@ -136,10 +136,12 @@ type mockControl struct {
calls [ ] string
authBlocked bool
shutdown chan struct { }
hi * tailcfg . Hostinfo
}
func newClient ( tb testing . TB , opts controlclient . Options ) * mockControl {
return & mockControl {
cc := mockControl {
tb : tb ,
authBlocked : true ,
logf : opts . Logf ,
@ -148,6 +150,10 @@ func newClient(tb testing.TB, opts controlclient.Options) *mockControl {
persist : opts . Persist . Clone ( ) ,
controlClientID : rand . Int64 ( ) ,
}
if opts . Hostinfo != nil {
cc . SetHostinfoDirect ( opts . Hostinfo )
}
return & cc
}
func ( cc * mockControl ) assertShutdown ( wasPaused bool ) {
@ -298,6 +304,11 @@ func (cc *mockControl) AuthCantContinue() bool {
func ( cc * mockControl ) SetHostinfo ( hi * tailcfg . Hostinfo ) {
cc . logf ( "SetHostinfo: %v" , * hi )
cc . called ( "SetHostinfo" )
cc . SetHostinfoDirect ( hi )
}
func ( cc * mockControl ) SetHostinfoDirect ( hi * tailcfg . Hostinfo ) {
cc . hi = hi
}
func ( cc * mockControl ) SetNetInfo ( ni * tailcfg . NetInfo ) {
@ -1621,7 +1632,7 @@ func runTestSendPreservesAuthURL(t *testing.T, seamless bool) {
return cc
} )
t . Log f ( "Start" )
t . Log ( "Start" )
b . Start ( ipn . Options {
UpdatePrefs : & ipn . Prefs {
WantRunning : true ,
@ -1629,7 +1640,7 @@ func runTestSendPreservesAuthURL(t *testing.T, seamless bool) {
} ,
} )
t . Log f ( "LoginFinished" )
t . Log ( "LoginFinished" )
cc . persist . UserProfile . LoginName = "user1"
cc . persist . NodeID = "node1"
@ -1641,13 +1652,13 @@ func runTestSendPreservesAuthURL(t *testing.T, seamless bool) {
SelfNode : ( & tailcfg . Node { MachineAuthorized : true } ) . View ( ) ,
} } )
t . Log f ( "Running" )
t . Log ( "Running" )
b . setWgengineStatus ( & wgengine . Status { AsOf : time . Now ( ) , DERPs : 1 } , nil )
t . Log f ( "Re-auth (StartLoginInteractive)" )
t . Log ( "Re-auth (StartLoginInteractive)" )
b . StartLoginInteractive ( t . Context ( ) )
t . Log f ( "Re-auth (receive URL)" )
t . Log ( "Re-auth (receive URL)" )
url1 := "https://localhost:1/1"
cc . send ( sendOpt { url : url1 } )
@ -1655,12 +1666,79 @@ func runTestSendPreservesAuthURL(t *testing.T, seamless bool) {
// be set, and once .send has completed, any opportunities for a WG engine
// status update to trample it have ended as well.
if b . authURL == "" {
t . Fatal f ( "expected authURL to be set" )
t . Fatal ( "expected authURL to be set" )
} else {
t . Log ( "authURL was set" )
}
}
func TestServicesNotClearedByStart ( t * testing . T ) {
connect := & ipn . MaskedPrefs { Prefs : ipn . Prefs { WantRunning : true } , WantRunningSet : true }
node1 := buildNetmapWithPeers (
makePeer ( 1 , withName ( "node-1" ) , withAddresses ( netip . MustParsePrefix ( "100.64.1.1/32" ) ) ) ,
)
var cc * mockControl
lb := newLocalBackendWithTestControl ( t , true , func ( tb testing . TB , opts controlclient . Options ) controlclient . Client {
cc = newClient ( t , opts )
return cc
} )
mustDo ( t ) ( lb . Start ( ipn . Options { } ) )
mustDo2 ( t ) ( lb . EditPrefs ( connect ) )
cc . assertCalls ( "Login" )
// Simulate authentication and wait for goroutines to finish (so peer
// listeners have been set up and hostinfo updated)
cc . authenticated ( node1 )
waitForGoroutinesToStop ( lb )
if cc . hi == nil || len ( cc . hi . Services ) == 0 {
t . Fatal ( "test setup bug: services should be present" )
}
mustDo ( t ) ( lb . Start ( ipn . Options { } ) )
if len ( cc . hi . Services ) == 0 {
t . Error ( "services should still be present in hostinfo after no-op Start" )
}
lb . initPeerAPIListenerLocked ( )
waitForGoroutinesToStop ( lb )
// Clearing out services on Start would be less of a problem if they would at
// least come back after authreconfig or any other change, but they don't if
// the addresses in the netmap haven't changed and still match the stored
// peerAPIListeners.
if len ( cc . hi . Services ) == 0 {
t . Error ( "services STILL not present after authreconfig" )
}
}
func waitForGoroutinesToStop ( lb * LocalBackend ) {
goroutineDone := make ( chan struct { } )
removeTrackerCallback := lb . goTracker . AddDoneCallback ( func ( ) {
select {
case goroutineDone <- struct { } { } :
default :
}
} )
defer removeTrackerCallback ( )
for {
if lb . goTracker . RunningGoroutines ( ) == 0 {
return
}
select {
case <- time . Tick ( 1 * time . Second ) :
continue
case <- goroutineDone :
continue
}
}
}
func buildNetmapWithPeers ( self tailcfg . NodeView , peers ... tailcfg . NodeView ) * netmap . NetworkMap {
const (
firstAutoUserID = tailcfg . UserID ( 10000 )