From c1fcb1d1eddeee3815b8db40f2a619badbb1d192 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Wed, 24 Jul 2024 13:12:09 +0200 Subject: [PATCH 1/4] fix: test: use monotonical port numbers --- agent/agent_test.go | 8 +++--- enterprise/cli/provisionerdaemons_test.go | 4 +-- testutil/port.go | 32 ++++++++++++----------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/agent/agent_test.go b/agent/agent_test.go index 4b0712bcf93c6..1d7ec8ca4b2d5 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(t) + 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..a02408dc70e44 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(t) // Configure CLI client client, admin := coderdenttest.New(t, &coderdenttest.Options{ diff --git a/testutil/port.go b/testutil/port.go index b5720e44a0966..bbdf5f915da3b 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 = minPort ) // 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(*testing.T) uint16 { rndMu.Lock() - x := rnd.Intn(n) + p := rndPort + + rndPort++ + if rndPort > maxPort { + rndPort = minPort + } rndMu.Unlock() - return uint16(min + x) + return uint16(p) } From 548f315c4f123ba1271656d25ec46260b662cbb9 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Wed, 24 Jul 2024 13:21:20 +0200 Subject: [PATCH 2/4] try: 50152 --- testutil/port.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testutil/port.go b/testutil/port.go index bbdf5f915da3b..bd23944ae9b32 100644 --- a/testutil/port.go +++ b/testutil/port.go @@ -10,7 +10,7 @@ import ( const ( // Overlap of windows, linux in https://en.wikipedia.org/wiki/Ephemeral_port - minPort = 49152 + minPort = 50152 maxPort = 60999 ) From f5b1bc1b0ea7eb58c24a2de85898d1b3f86eb9a5 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Wed, 24 Jul 2024 13:32:09 +0200 Subject: [PATCH 3/4] counting down --- testutil/port.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/testutil/port.go b/testutil/port.go index bd23944ae9b32..c0a30297e8a58 100644 --- a/testutil/port.go +++ b/testutil/port.go @@ -10,13 +10,13 @@ import ( const ( // Overlap of windows, linux in https://en.wikipedia.org/wiki/Ephemeral_port - minPort = 50152 + minPort = 49152 maxPort = 60999 ) var ( rndMu sync.Mutex - rndPort = minPort + rndPort = maxPort ) // RandomPort is a helper function to find a free random port. @@ -38,9 +38,9 @@ func EphemeralPortNoListen(*testing.T) uint16 { rndMu.Lock() p := rndPort - rndPort++ - if rndPort > maxPort { - rndPort = minPort + rndPort-- + if rndPort < minPort { + rndPort = maxPort } rndMu.Unlock() return uint16(p) From e6a3310d65a563e2dcecffd93b39083e8ec29210 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Wed, 24 Jul 2024 13:38:13 +0200 Subject: [PATCH 4/4] fix: def --- agent/agent_test.go | 2 +- enterprise/cli/provisionerdaemons_test.go | 2 +- testutil/port.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/agent/agent_test.go b/agent/agent_test.go index 1d7ec8ca4b2d5..4b1e36ea6d806 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -838,7 +838,7 @@ func TestAgent_TCPRemoteForwarding(t *testing.T) { var ll net.Listener var err error for { - port = testutil.EphemeralPortNoListen(t) + port = testutil.EphemeralPortNoListen() addr := net.TCPAddrFromAddrPort(netip.AddrPortFrom(localhost, port)) ll, err = sshClient.ListenTCP(addr) if err != nil { diff --git a/enterprise/cli/provisionerdaemons_test.go b/enterprise/cli/provisionerdaemons_test.go index a02408dc70e44..f0e8625c1ad71 100644 --- a/enterprise/cli/provisionerdaemons_test.go +++ b/enterprise/cli/provisionerdaemons_test.go @@ -303,7 +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) { - prometheusPort := testutil.EphemeralPortNoListen(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 c0a30297e8a58..767ee07205e6e 100644 --- a/testutil/port.go +++ b/testutil/port.go @@ -34,7 +34,7 @@ func RandomPort(t *testing.T) int { // 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 EphemeralPortNoListen(*testing.T) uint16 { +func EphemeralPortNoListen() uint16 { rndMu.Lock() p := rndPort