diff --git a/cmd/cli/network_shutdown_test.go b/cmd/cli/network_shutdown_test.go index 80b2aa6..2e2296a 100644 --- a/cmd/cli/network_shutdown_test.go +++ b/cmd/cli/network_shutdown_test.go @@ -176,13 +176,23 @@ func TestNetworkShutdownCancelsIndefiniteRecoveryWait(t *testing.T) { oldReset, oldIntercept := recoveryResetDNSFn, dnsIntercept dnsIntercept = false defer func() { recoveryResetDNSFn, dnsIntercept = oldReset, oldIntercept }() - p := &prog{cfg: &ctrld.Config{}} + // The only upstream is a loopback port nothing listens on, so recovery + // can never succeed. An empty upstream map no longer does that: recovery + // then checks upstream.os, and on a host with working DNS that answers, + // completes the recovery and turns the test into a probe of the host. + dead := &ctrld.UpstreamConfig{Type: ctrld.ResolverTypeLegacy, Endpoint: deadUDPAddr(t), Timeout: 300} + dead.Init(context.Background()) + cfg := &ctrld.Config{Upstream: map[string]*ctrld.UpstreamConfig{"0": dead}} + p := &prog{cfg: cfg} p.logger.Store(mainLog.Load()) + // Recovery reads the upstream monitor, which run creates before network + // monitoring can start any recovery. + p.um = newUpstreamMonitor(cfg, p.logger.Load()) entered := make(chan struct{}) recoveryResetDNSFn = func(*prog, bool, bool) { close(entered) } recovered := make(chan struct{}) - // An empty upstream map can never recover. Shutdown must cancel that wait - // without waiting on a mutex held for the recovery's entire lifetime. + // Shutdown must cancel that wait without waiting on a mutex held for the + // recovery's entire lifetime. go func() { p.handleRecovery(RecoveryReasonRegularFailure); close(recovered) }() waitNetworkShutdownSignal(t, entered, "recovery reset seam") closed := make(chan struct{})