From 72c0802a6f2274bd07cdf1c7a3cfb2e2ee44fe97 Mon Sep 17 00:00:00 2001 From: Samuel K Date: Mon, 21 Sep 2026 12:02:46 -0600 Subject: [PATCH] test(tunnel): wait for listener shutdown after context cancellation The test asserted an asynchronous effect with a fixed 100ms sleep: after cancel(), the listener is closed by a separate goroutine watching the context, so under -race on a loaded macOS runner the close can land after the dial and the connection succeeds. Poll until the port refuses connections (bounded at 2s) instead, matching the existing health-check shutdown test. Signed-off-by: Samuel K --- pkg/tunnel/local_listener_test.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/pkg/tunnel/local_listener_test.go b/pkg/tunnel/local_listener_test.go index 3b2c9fb6c..293fc0c7e 100644 --- a/pkg/tunnel/local_listener_test.go +++ b/pkg/tunnel/local_listener_test.go @@ -183,10 +183,22 @@ func TestLocalTunnel_ContextCancellation(t *testing.T) { addr := tun.Addr() cancel() - time.Sleep(100 * time.Millisecond) - _, err = net.DialTimeout("tcp", addr, 500*time.Millisecond) - if err == nil { - t.Error("expected connection to be refused after context cancellation") + // The listener is closed asynchronously after cancellation. + deadline := time.After(2 * time.Second) + ticker := time.NewTicker(10 * time.Millisecond) + defer ticker.Stop() + + for { + conn, err := net.DialTimeout("tcp", addr, 50*time.Millisecond) + if err != nil { + return + } + _ = conn.Close() + select { + case <-deadline: + t.Fatal("listener still accepting connections after context cancellation") + case <-ticker.C: + } } }