all: make more tests pass/skip in airplane mode

Updates tailscale/corp#19786

Change-Id: Iedc6730fe91c627b556bff5325bdbaf7bf79d8e6
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-05-05 11:57:47 -07:00 committed by Brad Fitzpatrick
parent 41f2195899
commit c3c18027c6
7 changed files with 28 additions and 15 deletions

View File

@ -24,6 +24,7 @@
"tailscale.com/tsnet" "tailscale.com/tsnet"
"tailscale.com/tstest/integration" "tailscale.com/tstest/integration"
"tailscale.com/tstest/integration/testcontrol" "tailscale.com/tstest/integration/testcontrol"
"tailscale.com/tstest/nettest"
"tailscale.com/types/appctype" "tailscale.com/types/appctype"
"tailscale.com/types/ipproto" "tailscale.com/types/ipproto"
"tailscale.com/types/key" "tailscale.com/types/key"
@ -111,6 +112,7 @@ func startNode(t *testing.T, ctx context.Context, controlURL, hostname string) (
} }
func TestSNIProxyWithNetmapConfig(t *testing.T) { func TestSNIProxyWithNetmapConfig(t *testing.T) {
nettest.SkipIfNoNetwork(t)
c, controlURL := startControl(t) c, controlURL := startControl(t)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel() defer cancel()
@ -189,6 +191,7 @@ func TestSNIProxyWithNetmapConfig(t *testing.T) {
} }
func TestSNIProxyWithFlagConfig(t *testing.T) { func TestSNIProxyWithFlagConfig(t *testing.T) {
nettest.SkipIfNoNetwork(t)
_, controlURL := startControl(t) _, controlURL := startControl(t)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel() defer cancel()

View File

@ -614,6 +614,8 @@ func (b *LocalBackend) ReloadConfig() (ok bool, err error) {
return true, nil return true, nil
} }
var assumeNetworkUpdateForTest = envknob.RegisterBool("TS_ASSUME_NETWORK_UP_FOR_TEST")
// pauseOrResumeControlClientLocked pauses b.cc if there is no network available // pauseOrResumeControlClientLocked pauses b.cc if there is no network available
// or if the LocalBackend is in Stopped state with a valid NetMap. In all other // or if the LocalBackend is in Stopped state with a valid NetMap. In all other
// cases, it unpauses it. It is a no-op if b.cc is nil. // cases, it unpauses it. It is a no-op if b.cc is nil.
@ -624,7 +626,7 @@ func (b *LocalBackend) pauseOrResumeControlClientLocked() {
return return
} }
networkUp := b.prevIfState.AnyInterfaceUp() networkUp := b.prevIfState.AnyInterfaceUp()
b.cc.SetPaused((b.state == ipn.Stopped && b.netMap != nil) || (!networkUp && !testenv.InTest())) b.cc.SetPaused((b.state == ipn.Stopped && b.netMap != nil) || (!networkUp && !testenv.InTest() && !assumeNetworkUpdateForTest()))
} }
// linkChange is our network monitor callback, called whenever the network changes. // linkChange is our network monitor callback, called whenever the network changes.

View File

@ -396,9 +396,7 @@ func makeProbePlan(dm *tailcfg.DERPMap, ifState *netmon.State, last *Report) (pl
have6if := ifState.HaveV6 have6if := ifState.HaveV6
have4if := ifState.HaveV4 have4if := ifState.HaveV4
plan = make(probePlan) plan = make(probePlan)
if !have4if && !have6if {
return plan
}
had4 := len(last.RegionV4Latency) > 0 had4 := len(last.RegionV4Latency) > 0
had6 := len(last.RegionV6Latency) > 0 had6 := len(last.RegionV6Latency) > 0
hadBoth := have6if && had4 && had6 hadBoth := have6if && had4 && had6
@ -452,10 +450,10 @@ func makeProbePlan(dm *tailcfg.DERPMap, ifState *netmon.State, last *Report) (pl
if try > 1 { if try > 1 {
delay += time.Duration(try) * 50 * time.Millisecond delay += time.Duration(try) * 50 * time.Millisecond
} }
if do4 { if do4 || n.IsTestNode() {
p4 = append(p4, probe{delay: delay, node: n.Name, proto: probeIPv4}) p4 = append(p4, probe{delay: delay, node: n.Name, proto: probeIPv4})
} }
if do6 { if do6 || n.IsTestNode() {
p6 = append(p6, probe{delay: delay, node: n.Name, proto: probeIPv6}) p6 = append(p6, probe{delay: delay, node: n.Name, proto: probeIPv6})
} }
} }
@ -478,10 +476,10 @@ func makeProbePlanInitial(dm *tailcfg.DERPMap, ifState *netmon.State) (plan prob
for try := 0; try < 3; try++ { for try := 0; try < 3; try++ {
n := reg.Nodes[try%len(reg.Nodes)] n := reg.Nodes[try%len(reg.Nodes)]
delay := time.Duration(try) * defaultInitialRetransmitTime delay := time.Duration(try) * defaultInitialRetransmitTime
if ifState.HaveV4 && nodeMight4(n) { if ifState.HaveV4 && nodeMight4(n) || n.IsTestNode() {
p4 = append(p4, probe{delay: delay, node: n.Name, proto: probeIPv4}) p4 = append(p4, probe{delay: delay, node: n.Name, proto: probeIPv4})
} }
if ifState.HaveV6 && nodeMight6(n) { if ifState.HaveV6 && nodeMight6(n) || n.IsTestNode() {
p6 = append(p6, probe{delay: delay, node: n.Name, proto: probeIPv6}) p6 = append(p6, probe{delay: delay, node: n.Name, proto: probeIPv6})
} }
} }

View File

@ -23,6 +23,7 @@
"tailscale.com/net/stun/stuntest" "tailscale.com/net/stun/stuntest"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/tstest/nettest"
) )
func TestHairpinSTUN(t *testing.T) { func TestHairpinSTUN(t *testing.T) {
@ -882,6 +883,8 @@ func TestSortRegions(t *testing.T) {
} }
func TestNoCaptivePortalWhenUDP(t *testing.T) { func TestNoCaptivePortalWhenUDP(t *testing.T) {
nettest.SkipIfNoNetwork(t) // empirically. not sure why.
// Override noRedirectClient to handle the /generate_204 endpoint // Override noRedirectClient to handle the /generate_204 endpoint
var generate204Called atomic.Bool var generate204Called atomic.Bool
tr := RoundTripFunc(func(req *http.Request) *http.Response { tr := RoundTripFunc(func(req *http.Request) *http.Response {
@ -934,6 +937,7 @@ func (f RoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
} }
func TestNodeAddrResolve(t *testing.T) { func TestNodeAddrResolve(t *testing.T) {
nettest.SkipIfNoNetwork(t)
c := &Client{ c := &Client{
Logf: t.Logf, Logf: t.Logf,
UseDNSCache: true, UseDNSCache: true,

View File

@ -125,6 +125,7 @@ func DERPMapOf(stun ...string) *tailcfg.DERPMap {
IPv6: ipv6, IPv6: ipv6,
STUNPort: port, STUNPort: port,
STUNOnly: true, STUNOnly: true,
STUNTestIP: host,
} }
m.Regions[regionID] = &tailcfg.DERPRegion{ m.Regions[regionID] = &tailcfg.DERPRegion{
RegionID: regionID, RegionID: regionID,

View File

@ -183,6 +183,10 @@ type DERPNode struct {
CanPort80 bool `json:",omitempty"` CanPort80 bool `json:",omitempty"`
} }
func (n *DERPNode) IsTestNode() bool {
return n.STUNTestIP != "" || n.IPv4 == "127.0.0.1"
}
// DotInvalid is a fake DNS TLD used in tests for an invalid hostname. // DotInvalid is a fake DNS TLD used in tests for an invalid hostname.
const DotInvalid = ".invalid" const DotInvalid = ".invalid"

View File

@ -1249,6 +1249,7 @@ func (n *testNode) StartDaemonAsIPNGOOS(ipnGOOS string) *Daemon {
"TS_DEBUG_FAKE_GOOS="+ipnGOOS, "TS_DEBUG_FAKE_GOOS="+ipnGOOS,
"TS_LOGS_DIR="+t.TempDir(), "TS_LOGS_DIR="+t.TempDir(),
"TS_NETCHECK_GENERATE_204_URL="+n.env.ControlServer.URL+"/generate_204", "TS_NETCHECK_GENERATE_204_URL="+n.env.ControlServer.URL+"/generate_204",
"TS_ASSUME_NETWORK_UP_FOR_TEST=1", // don't pause control client in airplane mode (no wifi, etc)
) )
if version.IsRace() { if version.IsRace() {
cmd.Env = append(cmd.Env, "GORACE=halt_on_error=1") cmd.Env = append(cmd.Env, "GORACE=halt_on_error=1")