SetDERPMap spawns a goroutine that calls ReSTUN, which logs via the test logger. If the test returns before that goroutine logs, the goroutine races with testing cleanup. Use tstest.WhileTestRunningLogger so the goroutine's logf call becomes a no-op once the test finishes. Fixes #19829 Change-Id: I1097f98e40ffd1c5dd7fb7a715c918255853e3c6 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
133 lines
3.3 KiB
Go
133 lines
3.3 KiB
Go
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package magicsock
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"tailscale.com/health"
|
|
"tailscale.com/net/netcheck"
|
|
"tailscale.com/tailcfg"
|
|
"tailscale.com/tstest"
|
|
"tailscale.com/util/eventbus"
|
|
"tailscale.com/util/eventbus/eventbustest"
|
|
)
|
|
|
|
func CheckDERPHeuristicTimes(t *testing.T) {
|
|
if netcheck.PreferredDERPFrameTime <= frameReceiveRecordRate {
|
|
t.Errorf("PreferredDERPFrameTime too low; should be at least frameReceiveRecordRate")
|
|
}
|
|
}
|
|
|
|
func TestForceSetNearestDERP(t *testing.T) {
|
|
derpMap := &tailcfg.DERPMap{
|
|
Regions: map[int]*tailcfg.DERPRegion{
|
|
7: {
|
|
RegionID: 7,
|
|
RegionCode: "test",
|
|
Nodes: []*tailcfg.DERPNode{
|
|
{
|
|
Name: "7a",
|
|
RegionID: 7,
|
|
HostName: "derp7.test.unused",
|
|
IPv4: "127.0.0.1",
|
|
IPv6: "none",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
// Force the real control health check so we can verify force=true bypasses it.
|
|
tstest.Replace(t, &checkControlHealthDuringNearestDERPInTests, true)
|
|
|
|
bus := eventbustest.NewBus(t)
|
|
ht := health.NewTracker(bus)
|
|
c := newConn(t.Logf)
|
|
ec := bus.Client("magicsock.Conn.Test")
|
|
c.eventClient = ec
|
|
c.homeDERPChangedPub = eventbus.Publish[HomeDERPChanged](ec)
|
|
c.eventBus = bus
|
|
c.derpMap = derpMap
|
|
c.health = ht
|
|
|
|
ht.SetOutOfPollNetMap()
|
|
|
|
tw := eventbustest.NewWatcher(t, bus)
|
|
|
|
got := c.ForceSetNearestDERP(7)
|
|
if got != 7 {
|
|
t.Fatalf("ForceSetNearestDERP(7) = %d, want 7", got)
|
|
}
|
|
if c.myDerp != 7 {
|
|
t.Errorf("c.myDerp = %d after ForceSetNearestDERP, want 7", c.myDerp)
|
|
}
|
|
|
|
if err := eventbustest.Expect(tw, func(e HomeDERPChanged) error {
|
|
if e.Old != 0 || e.New != 7 {
|
|
return fmt.Errorf("got HomeDERPChanged{Old:%d, New:%d}, want {Old:0, New:7}", e.Old, e.New)
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
t.Errorf("expected HomeDERPChanged event: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSetDERPMapDoReStun(t *testing.T) {
|
|
derpMap1 := &tailcfg.DERPMap{
|
|
Regions: map[int]*tailcfg.DERPRegion{
|
|
1: {
|
|
RegionID: 1,
|
|
RegionCode: "cph",
|
|
Nodes: []*tailcfg.DERPNode{
|
|
{Name: "1a", RegionID: 1, HostName: "cph.test.unused", IPv4: "127.0.0.1", IPv6: "none"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
derpMap2 := &tailcfg.DERPMap{
|
|
Regions: map[int]*tailcfg.DERPRegion{
|
|
2: {
|
|
RegionID: 2,
|
|
RegionCode: "inc",
|
|
Nodes: []*tailcfg.DERPNode{
|
|
{Name: "2a", RegionID: 2, HostName: "inc.test.unused", IPv4: "127.0.0.1", IPv6: "none"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
var reSTUNCalls int
|
|
tstest.Replace(t, &reSTUNHookForTests, func(_ string) {
|
|
reSTUNCalls++
|
|
})
|
|
|
|
bus := eventbustest.NewBus(t)
|
|
ht := health.NewTracker(bus)
|
|
// Use WhileTestRunningLogger so the goroutine spawned by setDERPMap
|
|
// (which calls ReSTUN, which logs) doesn't race with test cleanup.
|
|
c := newConn(tstest.WhileTestRunningLogger(t))
|
|
ec := bus.Client("magicsock.Conn.Test")
|
|
c.eventClient = ec
|
|
c.homeDERPChangedPub = eventbus.Publish[HomeDERPChanged](ec)
|
|
c.eventBus = bus
|
|
c.health = ht
|
|
// With a zero private key and everHadKey=true, ReSTUN returns early without
|
|
// spawning updateEndpoints.
|
|
c.everHadKey = true
|
|
|
|
// SetDERPMapWithoutReSTUN should not trigger a ReSTUN.
|
|
c.SetDERPMapWithoutReSTUN(derpMap1)
|
|
if reSTUNCalls != 0 {
|
|
t.Errorf("SetDERPMapWithoutReSTUN: got %d ReSTUN calls, want 0", reSTUNCalls)
|
|
}
|
|
|
|
// SetDERPMap should trigger a ReSTUN.
|
|
c.SetDERPMap(derpMap2)
|
|
if reSTUNCalls != 1 {
|
|
t.Errorf("SetDERPMap: got %d ReSTUN calls, want 1", reSTUNCalls)
|
|
}
|
|
}
|