From a69ae2b0ea0ae96b3ddd0565d17cebb7b053126c Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 24 Oct 2026 07:20:16 +0200 Subject: [PATCH] test(tuic): retry until one port is free for both TCP and UDP The route marker took a free TCP port and bound UDP on the same number, which fails whenever that UDP port is in use or reserved (Windows excludes port ranges per protocol), so the TUIC routing tests failed at random on such hosts. --- .../web/service/tuic_user_routing_test.go | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/internal/web/service/tuic_user_routing_test.go b/internal/web/service/tuic_user_routing_test.go index f225c5a47..385e09af6 100644 --- a/internal/web/service/tuic_user_routing_test.go +++ b/internal/web/service/tuic_user_routing_test.go @@ -272,17 +272,28 @@ func TestTuicUserRoutingDoesNotDoubleCountTraffic(t *testing.T) { } } +// listenTCPAndUDPOnOnePort retries because a free TCP port may be taken or reserved for UDP +// (Windows excludes port ranges per protocol). +func listenTCPAndUDPOnOnePort(t *testing.T) (net.Listener, net.PacketConn) { + t.Helper() + for range 20 { + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatal(err) + } + if packet, err := net.ListenPacket("udp", listener.Addr().String()); err == nil { + return listener, packet + } + _ = listener.Close() + } + t.Fatal("no port free for both TCP and UDP") + return nil, nil +} + func startTuicRouteMarker(t *testing.T, marker string) string { t.Helper() - listener, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - t.Fatal(err) - } + listener, packet := listenTCPAndUDPOnOnePort(t) t.Cleanup(func() { _ = listener.Close() }) - packet, err := net.ListenPacket("udp", listener.Addr().String()) - if err != nil { - t.Fatal(err) - } t.Cleanup(func() { _ = packet.Close() }) go func() { for {