diff --git a/agent/agent_test.go b/agent/agent_test.go index 4b0712bcf93c6..4b1e36ea6d806 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -834,12 +834,12 @@ func TestAgent_TCPRemoteForwarding(t *testing.T) { sshClient := setupAgentSSHClient(ctx, t) localhost := netip.MustParseAddr("127.0.0.1") - var randomPort uint16 + var port uint16 var ll net.Listener var err error for { - randomPort = testutil.RandomPortNoListen(t) - addr := net.TCPAddrFromAddrPort(netip.AddrPortFrom(localhost, randomPort)) + port = testutil.EphemeralPortNoListen() + addr := net.TCPAddrFromAddrPort(netip.AddrPortFrom(localhost, port)) ll, err = sshClient.ListenTCP(addr) if err != nil { t.Logf("error remote forwarding: %s", err.Error()) @@ -855,7 +855,7 @@ func TestAgent_TCPRemoteForwarding(t *testing.T) { defer ll.Close() go echoOnce(t, ll) - conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", randomPort)) + conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port)) require.NoError(t, err) defer conn.Close() requireEcho(t, conn) diff --git a/enterprise/cli/provisionerdaemons_test.go b/enterprise/cli/provisionerdaemons_test.go index 299ddd1d4ff5a..f0e8625c1ad71 100644 --- a/enterprise/cli/provisionerdaemons_test.go +++ b/enterprise/cli/provisionerdaemons_test.go @@ -303,9 +303,7 @@ func TestProvisionerDaemon_SessionToken(t *testing.T) { //nolint:paralleltest,tparallel // Prometheus endpoint tends to fail with `bind: address already in use`. func TestProvisionerDaemon_PrometheusEnabled(t *testing.T) { - t.Skip("Flaky test - see https://github.com/coder/coder/issues/13931") - - prometheusPort := testutil.RandomPortNoListen(t) + prometheusPort := testutil.EphemeralPortNoListen() // Configure CLI client client, admin := coderdenttest.New(t, &coderdenttest.Options{ diff --git a/testutil/port.go b/testutil/port.go index b5720e44a0966..767ee07205e6e 100644 --- a/testutil/port.go +++ b/testutil/port.go @@ -1,19 +1,22 @@ package testutil import ( - "math/rand" "net" "sync" "testing" - "time" "github.com/stretchr/testify/require" ) +const ( + // Overlap of windows, linux in https://en.wikipedia.org/wiki/Ephemeral_port + minPort = 49152 + maxPort = 60999 +) + var ( - // nolint:gosec // not used for cryptography - rnd = rand.New(rand.NewSource(time.Now().Unix())) - rndMu sync.Mutex + rndMu sync.Mutex + rndPort = maxPort ) // RandomPort is a helper function to find a free random port. @@ -28,18 +31,17 @@ func RandomPort(t *testing.T) int { return tcpAddr.Port } -// RandomPortNoListen returns a random port in the ephemeral port range. +// EphemeralPortNoListen returns the next port in the ephemeral port range. // Does not attempt to listen and close to find a port as the OS may // reallocate the port very quickly. -func RandomPortNoListen(*testing.T) uint16 { - const ( - // Overlap of windows, linux in https://en.wikipedia.org/wiki/Ephemeral_port - min = 49152 - max = 60999 - ) - n := max - min +func EphemeralPortNoListen() uint16 { rndMu.Lock() - x := rnd.Intn(n) + p := rndPort + + rndPort-- + if rndPort < minPort { + rndPort = maxPort + } rndMu.Unlock() - return uint16(min + x) + return uint16(p) }