From b5bcb472fdb984c9e261180836af99b85dc112df Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Sat, 20 Jul 2024 11:10:53 +0100 Subject: [PATCH 1/2] test: racy port creation in port forwarding tests Fix racy creation of free ports in port forwarding tests which were causing random failures. --- port_forwarding_test.go | 68 +++++++++-------------------------------- 1 file changed, 14 insertions(+), 54 deletions(-) diff --git a/port_forwarding_test.go b/port_forwarding_test.go index 46a1917a52..cfc030043e 100644 --- a/port_forwarding_test.go +++ b/port_forwarding_test.go @@ -6,9 +6,12 @@ import ( "io" "net" "net/http" + "net/http/httptest" "testing" "time" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" tcexec "github.com/testcontainers/testcontainers-go/exec" "github.com/testcontainers/testcontainers-go/network" @@ -52,21 +55,10 @@ func TestExposeHostPorts(t *testing.T) { t.Run(tc.name, func(tt *testing.T) { freePorts := make([]int, tc.numberOfPorts) for i := range freePorts { - freePort, err := getFreePort() - if err != nil { - tt.Fatal(err) - } - - freePorts[i] = freePort - - // create an http server for each port - server, err := createHttpServer(freePort) - if err != nil { - tt.Fatal(err) - } - go func() { - _ = server.ListenAndServe() - }() + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, expectedResponse) + })) + freePorts[i] = server.Listener.Addr().(*net.TCPAddr).Port tt.Cleanup(func() { server.Close() }) @@ -87,13 +79,11 @@ func TestExposeHostPorts(t *testing.T) { if tc.hasNetwork { var err error nw, err = network.New(context.Background()) - if err != nil { - tt.Fatal(err) - } + require.NoError(tt, err) + tt.Cleanup(func() { - if err := nw.Remove(context.Background()); err != nil { - tt.Fatal(err) - } + err := nw.Remove(context.Background()) + require.NoError(tt, err) }) req.Networks = []string{nw.Name} @@ -108,13 +98,10 @@ func TestExposeHostPorts(t *testing.T) { } c, err := testcontainers.GenericContainer(ctx, req) - if err != nil { - tt.Fatal(err) - } + require.NoError(tt, err) tt.Cleanup(func() { - if err := c.Terminate(context.Background()); err != nil { - tt.Fatal(err) - } + err := c.Terminate(context.Background()) + require.NoError(tt, err) }) if tc.hasHostAccess { @@ -174,30 +161,3 @@ func assertContainerHasNoHostAccess(t *testing.T, c testcontainers.Container, po } } } - -func createHttpServer(port int) (*http.Server, error) { - server := &http.Server{ - Addr: fmt.Sprintf(":%d", port), - } - - server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, expectedResponse) - }) - - return server, nil -} - -// getFreePort asks the kernel for a free open port that is ready to use. -func getFreePort() (int, error) { - addr, err := net.ResolveTCPAddr("tcp", "localhost:0") - if err != nil { - return 0, err - } - - l, err := net.ListenTCP("tcp", addr) - if err != nil { - return 0, err - } - defer l.Close() - return l.Addr().(*net.TCPAddr).Port, nil -} From bb2101f9e5a6cc8e7970a46a01c777914bf32e1b Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 7 Aug 2024 12:31:41 +0100 Subject: [PATCH 2/2] chore: apply feedback suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply PR feedback suggestions to use a single line error check. Co-authored-by: Manuel de la Peña --- port_forwarding_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/port_forwarding_test.go b/port_forwarding_test.go index cfc030043e..471736150b 100644 --- a/port_forwarding_test.go +++ b/port_forwarding_test.go @@ -82,8 +82,7 @@ func TestExposeHostPorts(t *testing.T) { require.NoError(tt, err) tt.Cleanup(func() { - err := nw.Remove(context.Background()) - require.NoError(tt, err) + require.NoError(tt, nw.Remove(context.Background())) }) req.Networks = []string{nw.Name} @@ -100,8 +99,7 @@ func TestExposeHostPorts(t *testing.T) { c, err := testcontainers.GenericContainer(ctx, req) require.NoError(tt, err) tt.Cleanup(func() { - err := c.Terminate(context.Background()) - require.NoError(tt, err) + require.NoError(tt, c.Terminate(context.Background())) }) if tc.hasHostAccess {