@ -4,13 +4,20 @@
package relayserver
import (
"errors"
"net/netip"
"reflect"
"testing"
"tailscale.com/ipn"
"tailscale.com/net/udprelay/endpoint"
"tailscale.com/net/udprelay/status"
"tailscale.com/tailcfg"
"tailscale.com/tsd"
"tailscale.com/tstime"
"tailscale.com/types/key"
"tailscale.com/types/logger"
"tailscale.com/types/ptr"
"tailscale.com/util/eventbus"
)
func Test_extension_profileStateChanged ( t * testing . T ) {
@ -19,29 +26,33 @@ func Test_extension_profileStateChanged(t *testing.T) {
type fields struct {
port * int
rs relayServer
}
type args struct {
prefs ipn . PrefsView
sameNode bool
}
tests := [ ] struct {
name string
fields fields
args args
wantPort * int
wantBusRunning bool
name string
fields fields
args args
wantPort * int
wantRelayServerFieldNonNil bool
wantRelayServerFieldMutated bool
} {
{
name : "no changes non-nil port ",
name : "no changes non-nil port previously running ",
fields : fields {
port : ptr . To ( 1 ) ,
rs : mockRelayServerNotZeroVal ( ) ,
} ,
args : args {
prefs : prefsWithPortOne . View ( ) ,
sameNode : true ,
} ,
wantPort : ptr . To ( 1 ) ,
wantBusRunning : true ,
wantPort : ptr . To ( 1 ) ,
wantRelayServerFieldNonNil : true ,
wantRelayServerFieldMutated : false ,
} ,
{
name : "prefs port nil" ,
@ -52,8 +63,23 @@ func Test_extension_profileStateChanged(t *testing.T) {
prefs : prefsWithNilPort . View ( ) ,
sameNode : true ,
} ,
wantPort : nil ,
wantBusRunning : false ,
wantPort : nil ,
wantRelayServerFieldNonNil : false ,
wantRelayServerFieldMutated : false ,
} ,
{
name : "prefs port nil previously running" ,
fields : fields {
port : ptr . To ( 1 ) ,
rs : mockRelayServerNotZeroVal ( ) ,
} ,
args : args {
prefs : prefsWithNilPort . View ( ) ,
sameNode : true ,
} ,
wantPort : nil ,
wantRelayServerFieldNonNil : false ,
wantRelayServerFieldMutated : true ,
} ,
{
name : "prefs port changed" ,
@ -64,8 +90,23 @@ func Test_extension_profileStateChanged(t *testing.T) {
prefs : prefsWithPortOne . View ( ) ,
sameNode : true ,
} ,
wantPort : ptr . To ( 1 ) ,
wantBusRunning : true ,
wantPort : ptr . To ( 1 ) ,
wantRelayServerFieldNonNil : true ,
wantRelayServerFieldMutated : true ,
} ,
{
name : "prefs port changed previously running" ,
fields : fields {
port : ptr . To ( 2 ) ,
rs : mockRelayServerNotZeroVal ( ) ,
} ,
args : args {
prefs : prefsWithPortOne . View ( ) ,
sameNode : true ,
} ,
wantPort : ptr . To ( 1 ) ,
wantRelayServerFieldNonNil : true ,
wantRelayServerFieldMutated : true ,
} ,
{
name : "sameNode false" ,
@ -76,8 +117,23 @@ func Test_extension_profileStateChanged(t *testing.T) {
prefs : prefsWithPortOne . View ( ) ,
sameNode : false ,
} ,
wantPort : ptr . To ( 1 ) ,
wantBusRunning : true ,
wantPort : ptr . To ( 1 ) ,
wantRelayServerFieldNonNil : true ,
wantRelayServerFieldMutated : true ,
} ,
{
name : "sameNode false previously running" ,
fields : fields {
port : ptr . To ( 1 ) ,
rs : mockRelayServerNotZeroVal ( ) ,
} ,
args : args {
prefs : prefsWithPortOne . View ( ) ,
sameNode : false ,
} ,
wantPort : ptr . To ( 1 ) ,
wantRelayServerFieldNonNil : true ,
wantRelayServerFieldMutated : true ,
} ,
{
name : "prefs port non-nil extension port nil" ,
@ -88,85 +144,165 @@ func Test_extension_profileStateChanged(t *testing.T) {
prefs : prefsWithPortOne . View ( ) ,
sameNode : false ,
} ,
wantPort : ptr . To ( 1 ) ,
wantBusRunning : true ,
wantPort : ptr . To ( 1 ) ,
wantRelayServerFieldNonNil : true ,
wantRelayServerFieldMutated : true ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
sys := tsd . NewSystem ( )
bus := sys . Bus . Get ( )
e := & extension {
logf : logger . Discard ,
port : tt . fields . port ,
bus : bus ,
ipne , err := newExtension ( logger . Discard , mockSafeBackend { sys } )
if err != nil {
t . Fatal ( err )
}
e := ipne . ( * extension )
e . newServerFn = func ( logf logger . Logf , port int , overrideAddrs [ ] netip . Addr ) ( relayServer , error ) {
return & mockRelayServer { } , nil
}
defer e . disconnectFromBusLocked ( )
e . port = tt . fields . port
e . rs = tt . fields . rs
defer e . Shutdown ( )
e . profileStateChanged ( ipn . LoginProfileView { } , tt . args . prefs , tt . args . sameNode )
if tt . wantBusRunning != ( e . eventSubs != nil ) {
t . Errorf ( "want BusRunning: %v != (e.eventSubs != nil): %v", tt . wantBusRunning , e . eventSub s != nil )
if tt . want RelayServerFieldNonNil != ( e . r s != nil ) {
t . Errorf ( "want RelayServerFieldNonNil: %v != (e.rs != nil): %v", tt . wantRelayServerFieldNonNil , e . r s != nil )
}
if ( tt . wantPort == nil ) != ( e . port == nil ) {
t . Errorf ( "(tt.wantPort == nil): %v != (e.port == nil): %v" , tt . wantPort == nil , e . port == nil )
} else if tt . wantPort != nil && * tt . wantPort != * e . port {
t . Errorf ( "wantPort: %d != *e.port: %d" , * tt . wantPort , * e . port )
}
if tt . wantRelayServerFieldMutated != ! reflect . DeepEqual ( tt . fields . rs , e . rs ) {
t . Errorf ( "wantRelayServerFieldMutated: %v != !reflect.DeepEqual(tt.fields.rs, e.rs): %v" , tt . wantRelayServerFieldMutated , ! reflect . DeepEqual ( tt . fields . rs , e . rs ) )
}
} )
}
}
func Test_extension_handleBusLifetimeLocked ( t * testing . T ) {
func mockRelayServerNotZeroVal ( ) * mockRelayServer {
return & mockRelayServer { true }
}
type mockRelayServer struct {
set bool
}
func ( mockRelayServer ) Close ( ) error { return nil }
func ( mockRelayServer ) AllocateEndpoint ( _ , _ key . DiscoPublic ) ( endpoint . ServerEndpoint , error ) {
return endpoint . ServerEndpoint { } , errors . New ( "not implemented" )
}
func ( mockRelayServer ) GetSessions ( ) [ ] status . ServerSession { return nil }
func ( mockRelayServer ) SetDERPMapView ( tailcfg . DERPMapView ) { return }
type mockSafeBackend struct {
sys * tsd . System
}
func ( m mockSafeBackend ) Sys ( ) * tsd . System { return m . sys }
func ( mockSafeBackend ) Clock ( ) tstime . Clock { return nil }
func ( mockSafeBackend ) TailscaleVarRoot ( ) string { return "" }
func Test_extension_handleRelayServerLifetimeLocked ( t * testing . T ) {
tests := [ ] struct {
name string
shutdown bool
port * int
eventSubs * eventbus . Monitor
rs relayServe r
hasNodeAttrDisableRelayServer bool
wantBusRunning bool
wantRelayServerFieldNonNil bool
wantRelayServerFieldMutated bool
} {
{
name : "want running" ,
shutdown : false ,
port : ptr . To ( 1 ) ,
hasNodeAttrDisableRelayServer : false ,
wantBusRunning : true ,
wantRelayServerFieldNonNil : true ,
wantRelayServerFieldMutated : true ,
} ,
{
name : "want running previously running" ,
shutdown : false ,
port : ptr . To ( 1 ) ,
rs : mockRelayServerNotZeroVal ( ) ,
hasNodeAttrDisableRelayServer : false ,
wantRelayServerFieldNonNil : true ,
wantRelayServerFieldMutated : false ,
} ,
{
name : "shutdown true" ,
shutdown : true ,
port : ptr . To ( 1 ) ,
hasNodeAttrDisableRelayServer : false ,
wantBusRunning : false ,
wantRelayServerFieldNonNil : false ,
wantRelayServerFieldMutated : false ,
} ,
{
name : "shutdown true previously running" ,
shutdown : true ,
port : ptr . To ( 1 ) ,
rs : mockRelayServerNotZeroVal ( ) ,
hasNodeAttrDisableRelayServer : false ,
wantRelayServerFieldNonNil : false ,
wantRelayServerFieldMutated : true ,
} ,
{
name : "port nil" ,
shutdown : false ,
port : nil ,
hasNodeAttrDisableRelayServer : false ,
wantBusRunning : false ,
wantRelayServerFieldNonNil : false ,
wantRelayServerFieldMutated : false ,
} ,
{
name : "port nil previously running" ,
shutdown : false ,
port : nil ,
rs : mockRelayServerNotZeroVal ( ) ,
hasNodeAttrDisableRelayServer : false ,
wantRelayServerFieldNonNil : false ,
wantRelayServerFieldMutated : true ,
} ,
{
name : "hasNodeAttrDisableRelayServer true" ,
shutdown : false ,
port : nil ,
hasNodeAttrDisableRelayServer : true ,
wantBusRunning : false ,
wantRelayServerFieldNonNil : false ,
wantRelayServerFieldMutated : false ,
} ,
{
name : "hasNodeAttrDisableRelayServer true previously running" ,
shutdown : false ,
port : nil ,
rs : mockRelayServerNotZeroVal ( ) ,
hasNodeAttrDisableRelayServer : true ,
wantRelayServerFieldNonNil : false ,
wantRelayServerFieldMutated : true ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
e := & extension {
logf : logger . Discard ,
bus : eventbus . New ( ) ,
shutdown : tt . shutdown ,
port : tt . port ,
eventSubs : tt . eventSubs ,
hasNodeAttrDisableRelayServer : tt . hasNodeAttrDisableRelayServer ,
sys := tsd . NewSystem ( )
ipne , err := newExtension ( logger . Discard , mockSafeBackend { sys } )
if err != nil {
t . Fatal ( err )
}
e := ipne . ( * extension )
e . newServerFn = func ( logf logger . Logf , port int , overrideAddrs [ ] netip . Addr ) ( relayServer , error ) {
return & mockRelayServer { } , nil
}
e . shutdown = tt . shutdown
e . port = tt . port
e . rs = tt . rs
e . hasNodeAttrDisableRelayServer = tt . hasNodeAttrDisableRelayServer
e . handleRelayServerLifetimeLocked ( )
defer e . Shutdown ( )
if tt . wantRelayServerFieldNonNil != ( e . rs != nil ) {
t . Errorf ( "wantRelayServerFieldNonNil: %v != (e.rs != nil): %v" , tt . wantRelayServerFieldNonNil , e . rs != nil )
}
e . handleBusLifetimeLocked ( )
defer e . disconnectFromBusLocked ( )
if tt . wantBusRunning != ( e . eventSubs != nil ) {
t . Errorf ( "wantBusRunning: %v != (e.eventSubs != nil): %v" , tt . wantBusRunning , e . eventSubs != nil )
if tt . wantRelayServerFieldMutated != ! reflect . DeepEqual ( tt . rs , e . rs ) {
t . Errorf ( "wantRelayServerFieldMutated: %v != !reflect.DeepEqual(tt.rs, e.rs): %v" , tt . wantRelayServerFieldMutated , ! reflect . DeepEqual ( tt . rs , e . rs ) )
}
} )
}