@ -308,26 +308,141 @@ func TestUndeltaPeers(t *testing.T) {
}
}
func TestFlagExpiredPeers ( t * testing . T ) {
n := func ( id tailcfg . NodeID , name string , expiry time . Time , mod ... func ( * tailcfg . Node ) ) * tailcfg . Node {
n := & tailcfg . Node { ID : id , Name : name , KeyExpiry : expiry }
for _ , f := range mod {
f ( n )
}
return n
}
now := time . Unix ( 1673373129 , 0 )
oldClockNow := clockNow
clockNow = func ( ) time . Time { return now }
t . Cleanup ( func ( ) { clockNow = oldClockNow } )
timeInPast := now . Add ( - 1 * time . Hour )
timeInFuture := now . Add ( 1 * time . Hour )
timeBeforeEpoch := flagExpiredPeersEpoch . Add ( - 1 * time . Second )
if now . Before ( timeBeforeEpoch ) {
panic ( "current time in test cannot be before epoch" )
}
var expiredKey key . NodePublic
if err := expiredKey . UnmarshalText ( [ ] byte ( "nodekey:6da774d5d7740000000000000000000000000000000000000000000000000000" ) ) ; err != nil {
panic ( err )
}
tests := [ ] struct {
name string
mapRes * tailcfg . MapResponse
want [ ] * tailcfg . Node
} {
{
name : "no_expiry" ,
mapRes : & tailcfg . MapResponse {
ControlTime : & now ,
Peers : [ ] * tailcfg . Node {
n ( 1 , "foo" , timeInFuture ) ,
n ( 2 , "bar" , timeInFuture ) ,
} ,
} ,
want : [ ] * tailcfg . Node {
n ( 1 , "foo" , timeInFuture ) ,
n ( 2 , "bar" , timeInFuture ) ,
} ,
} ,
{
name : "expiry" ,
mapRes : & tailcfg . MapResponse {
ControlTime : & now ,
Peers : [ ] * tailcfg . Node {
n ( 1 , "foo" , timeInFuture ) ,
n ( 2 , "bar" , timeInPast ) ,
} ,
} ,
want : [ ] * tailcfg . Node {
n ( 1 , "foo" , timeInFuture ) ,
n ( 2 , "bar" , timeInPast , func ( n * tailcfg . Node ) {
n . Expired = true
n . Key = expiredKey
} ) ,
} ,
} ,
{
name : "bad_ControlTime" ,
mapRes : & tailcfg . MapResponse {
// ControlTime here is intentionally before our hardcoded epoch
ControlTime : & timeBeforeEpoch ,
Peers : [ ] * tailcfg . Node {
n ( 1 , "foo" , timeInFuture ) ,
n ( 2 , "bar" , timeBeforeEpoch . Add ( - 1 * time . Hour ) ) , // before ControlTime
} ,
} ,
want : [ ] * tailcfg . Node {
n ( 1 , "foo" , timeInFuture ) ,
n ( 2 , "bar" , timeBeforeEpoch . Add ( - 1 * time . Hour ) ) , // should have expired, but ControlTime is before epoch
} ,
} ,
{
name : "tagged_node" ,
mapRes : & tailcfg . MapResponse {
ControlTime : & now ,
Peers : [ ] * tailcfg . Node {
n ( 1 , "foo" , timeInFuture ) ,
n ( 2 , "bar" , time . Time { } ) , // tagged node; zero expiry
} ,
} ,
want : [ ] * tailcfg . Node {
n ( 1 , "foo" , timeInFuture ) ,
n ( 2 , "bar" , time . Time { } ) , // not expired
} ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
ms := newTestMapSession ( t )
ms . flagExpiredPeers ( tt . mapRes )
if ! reflect . DeepEqual ( tt . mapRes . Peers , tt . want ) {
t . Errorf ( "wrong results\n got: %s\nwant: %s" , formatNodes ( tt . mapRes . Peers ) , formatNodes ( tt . want ) )
}
} )
}
}
func formatNodes ( nodes [ ] * tailcfg . Node ) string {
var sb strings . Builder
for i , n := range nodes {
if i > 0 {
sb . WriteString ( ", " )
}
var extra string
fmt . Fprintf ( & sb , "(%d, %q" , n . ID , n . Name )
if n . Online != nil {
extra += fmt . Sprintf ( ", online=%v" , * n . Online )
fmt. Fprintf ( & sb , ", online=%v" , * n . Online )
}
if n . LastSeen != nil {
extra += fmt . Sprintf ( ", lastSeen=%v" , n . LastSeen . Unix ( ) )
fmt . Fprintf ( & sb , ", lastSeen=%v" , n . LastSeen . Unix ( ) )
}
if n . Key != ( key . NodePublic { } ) {
fmt . Fprintf ( & sb , ", key=%v" , n . Key . String ( ) )
}
if n . Expired {
fmt . Fprintf ( & sb , ", expired=true" )
}
fmt . Fprintf ( & sb , "(%d, %q%s)" , n . ID , n . Name , extra )
sb. WriteString ( ")" )
}
return sb . String ( )
}
func newTestMapSession ( t * testing . T ) * mapSession {
return newMapSession ( key . NewNode ( ) )
ms := newMapSession ( key . NewNode ( ) )
ms . logf = t . Logf
return ms
}
func TestNetmapForResponse ( t * testing . T ) {