From 2491fec091c6bb3651e49289b6253cc2161df753 Mon Sep 17 00:00:00 2001 From: lazar Date: Thu, 19 Sep 2024 20:23:43 +0200 Subject: [PATCH 1/5] better port selection --- Makefile | 2 +- e2etest/container/container.go | 10 +++++----- e2etest/reporter_e2e_test.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index f2387d1..f93c41d 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ test: go test -race ./... test-e2e: - go test -mod=readonly --failfast -timeout=25m -v $(PACKAGES_E2E) -count=1 --parallel 12 --tags=e2e + go test -mod=readonly -failfast -timeout=15m -v $(PACKAGES_E2E) -count=1 --parallel 12 --tags=e2e build-docker: $(DOCKER) build --tag babylonlabs-io/vigilante -f Dockerfile \ diff --git a/e2etest/container/container.go b/e2etest/container/container.go index 0fd5106..1db3a15 100644 --- a/e2etest/container/container.go +++ b/e2etest/container/container.go @@ -6,7 +6,6 @@ import ( "fmt" bbn "github.com/babylonlabs-io/babylon/types" "github.com/btcsuite/btcd/btcec/v2" - "github.com/cometbft/cometbft/libs/rand" "net" "regexp" "strconv" @@ -263,12 +262,9 @@ func randomAvailablePort(t *testing.T) int { // Base port and spread range for port selection const ( basePort = 20000 - portRange = 20000 + portRange = 30000 ) - // Seed the random number generator to ensure randomness - rand.Seed(time.Now().UnixNano()) - // Try up to 10 times to find an available port for i := 0; i < 10; i++ { port := randPort(basePort, portRange) @@ -276,6 +272,10 @@ func randomAvailablePort(t *testing.T) int { if err != nil { continue } + + // listen on a port for a bit before closing, this should be just enough time for when other tests start + // when they try to net.Listen they should get an err and try a different port + time.Sleep(200 * time.Millisecond) if err := listener.Close(); err != nil { continue } diff --git a/e2etest/reporter_e2e_test.go b/e2etest/reporter_e2e_test.go index 8c74cf8..37b87bd 100644 --- a/e2etest/reporter_e2e_test.go +++ b/e2etest/reporter_e2e_test.go @@ -54,7 +54,7 @@ func (tm *TestManager) GenerateAndSubmitBlockNBlockStartingFromDepth(t *testing. } func TestReporter_BoostrapUnderFrequentBTCHeaders(t *testing.T) { - t.Parallel() + //t.Parallel() // todo(lazar): this test when run in parallel is very flaky, investigate why // no need to much mature outputs, we are not going to submit transactions in this test numMatureOutputs := uint32(150) From 87b3ea5c4de81cdd8b6760442a3f28fa75200817 Mon Sep 17 00:00:00 2001 From: lazar Date: Fri, 20 Sep 2024 10:30:39 +0200 Subject: [PATCH 2/5] shared port selection --- Makefile | 2 +- e2etest/container/container.go | 45 +++---------------------- e2etest/reporter_e2e_test.go | 1 + testutil/port.go | 61 ++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 42 deletions(-) create mode 100644 testutil/port.go diff --git a/Makefile b/Makefile index f93c41d..1ea66f1 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ test: go test -race ./... test-e2e: - go test -mod=readonly -failfast -timeout=15m -v $(PACKAGES_E2E) -count=1 --parallel 12 --tags=e2e + go test -mod=readonly -failfast -timeout=15m -v $(PACKAGES_E2E) -count=15 --parallel 12 --tags=e2e build-docker: $(DOCKER) build --tag babylonlabs-io/vigilante -f Dockerfile \ diff --git a/e2etest/container/container.go b/e2etest/container/container.go index 1db3a15..0b37dbf 100644 --- a/e2etest/container/container.go +++ b/e2etest/container/container.go @@ -5,8 +5,8 @@ import ( "context" "fmt" bbn "github.com/babylonlabs-io/babylon/types" + "github.com/babylonlabs-io/vigilante/testutil" "github.com/btcsuite/btcd/btcec/v2" - "net" "regexp" "strconv" "testing" @@ -15,7 +15,6 @@ import ( "github.com/ory/dockertest/v3" "github.com/ory/dockertest/v3/docker" "github.com/stretchr/testify/require" - mrand "math/rand/v2" ) const ( @@ -167,7 +166,7 @@ func (m *Manager) RunBitcoindResource( }, func(config *docker.HostConfig) { config.PortBindings = map[docker.Port][]docker.PortBinding{ - "18443/tcp": {{HostIP: "", HostPort: strconv.Itoa(randomAvailablePort(t))}}, // only expose what we need + "18443/tcp": {{HostIP: "", HostPort: strconv.Itoa(testutil.AllocateUniquePort(t))}}, // only expose what we need } config.PublishAllPorts = false // because in dockerfile they already expose them }, @@ -219,8 +218,8 @@ func (m *Manager) RunBabylondResource( }, func(config *docker.HostConfig) { config.PortBindings = map[docker.Port][]docker.PortBinding{ - "9090/tcp": {{HostIP: "", HostPort: strconv.Itoa(randomAvailablePort(t))}}, - "26657/tcp": {{HostIP: "", HostPort: strconv.Itoa(randomAvailablePort(t))}}, + "9090/tcp": {{HostIP: "", HostPort: strconv.Itoa(testutil.AllocateUniquePort(t))}}, + "26657/tcp": {{HostIP: "", HostPort: strconv.Itoa(testutil.AllocateUniquePort(t))}}, } }, noRestart, @@ -251,39 +250,3 @@ func noRestart(config *docker.HostConfig) { Name: "no", } } - -// randomAvailablePort tries to find an available TCP port on the localhost -// by testing multiple random ports within a specified range. -func randomAvailablePort(t *testing.T) int { - randPort := func(base, spread int) int { - return base + mrand.IntN(spread) - } - - // Base port and spread range for port selection - const ( - basePort = 20000 - portRange = 30000 - ) - - // Try up to 10 times to find an available port - for i := 0; i < 10; i++ { - port := randPort(basePort, portRange) - listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port)) - if err != nil { - continue - } - - // listen on a port for a bit before closing, this should be just enough time for when other tests start - // when they try to net.Listen they should get an err and try a different port - time.Sleep(200 * time.Millisecond) - if err := listener.Close(); err != nil { - continue - } - - return port - } - - // If no available port was found, fail the test - t.Fatalf("failed to find an available port in range %d-%d", basePort, basePort+portRange) - return 0 -} diff --git a/e2etest/reporter_e2e_test.go b/e2etest/reporter_e2e_test.go index 37b87bd..44a1c0f 100644 --- a/e2etest/reporter_e2e_test.go +++ b/e2etest/reporter_e2e_test.go @@ -54,6 +54,7 @@ func (tm *TestManager) GenerateAndSubmitBlockNBlockStartingFromDepth(t *testing. } func TestReporter_BoostrapUnderFrequentBTCHeaders(t *testing.T) { + t.Skip() //t.Parallel() // todo(lazar): this test when run in parallel is very flaky, investigate why // no need to much mature outputs, we are not going to submit transactions in this test numMatureOutputs := uint32(150) diff --git a/testutil/port.go b/testutil/port.go new file mode 100644 index 0000000..b914e26 --- /dev/null +++ b/testutil/port.go @@ -0,0 +1,61 @@ +package testutil + +import ( + "fmt" + "math/rand" + "net" + "sync" + "testing" +) + +// Track allocated ports, protected by a mutex +var ( + allocatedPorts = make(map[int]struct{}) + portMutex sync.Mutex +) + +// AllocateUniquePort tries to find an available TCP port on the localhost +// by testing multiple random ports within a specified range. +func AllocateUniquePort(t *testing.T) int { + randPort := func(base, spread int) int { + return base + rand.Intn(spread) + } + + // Base port and spread range for port selection + const ( + basePort = 20000 + portRange = 30000 + ) + + // Try up to 10 times to find an available port + for i := 0; i < 10; i++ { + port := randPort(basePort, portRange) + + // Lock the mutex to check and modify the shared map + portMutex.Lock() + if _, exists := allocatedPorts[port]; exists { + // Port already allocated, try another one + portMutex.Unlock() + continue + } + + listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port)) + if err != nil { + portMutex.Unlock() + continue + } + + allocatedPorts[port] = struct{}{} + portMutex.Unlock() + + if err := listener.Close(); err != nil { + continue + } + + return port + } + + // If no available port was found, fail the test + t.Fatalf("failed to find an available port in range %d-%d", basePort, basePort+portRange) + return 0 +} From 90238d1713810d0f9d2b1c19429395c0c28c79e0 Mon Sep 17 00:00:00 2001 From: lazar Date: Fri, 20 Sep 2024 10:31:34 +0200 Subject: [PATCH 3/5] count 1 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1ea66f1..f93c41d 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ test: go test -race ./... test-e2e: - go test -mod=readonly -failfast -timeout=15m -v $(PACKAGES_E2E) -count=15 --parallel 12 --tags=e2e + go test -mod=readonly -failfast -timeout=15m -v $(PACKAGES_E2E) -count=1 --parallel 12 --tags=e2e build-docker: $(DOCKER) build --tag babylonlabs-io/vigilante -f Dockerfile \ From cc3acd84acf6034125e80babe846325d60c3e462 Mon Sep 17 00:00:00 2001 From: lazar Date: Fri, 20 Sep 2024 10:31:49 +0200 Subject: [PATCH 4/5] cleanup --- e2etest/reporter_e2e_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/e2etest/reporter_e2e_test.go b/e2etest/reporter_e2e_test.go index 44a1c0f..37b87bd 100644 --- a/e2etest/reporter_e2e_test.go +++ b/e2etest/reporter_e2e_test.go @@ -54,7 +54,6 @@ func (tm *TestManager) GenerateAndSubmitBlockNBlockStartingFromDepth(t *testing. } func TestReporter_BoostrapUnderFrequentBTCHeaders(t *testing.T) { - t.Skip() //t.Parallel() // todo(lazar): this test when run in parallel is very flaky, investigate why // no need to much mature outputs, we are not going to submit transactions in this test numMatureOutputs := uint32(150) From 42214b90fad5b9304feb973d1ff2b34ccce86825 Mon Sep 17 00:00:00 2001 From: lazar Date: Fri, 20 Sep 2024 10:32:30 +0200 Subject: [PATCH 5/5] mrand2 --- testutil/port.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testutil/port.go b/testutil/port.go index b914e26..19ad7f7 100644 --- a/testutil/port.go +++ b/testutil/port.go @@ -2,7 +2,7 @@ package testutil import ( "fmt" - "math/rand" + mrand "math/rand/v2" "net" "sync" "testing" @@ -18,7 +18,7 @@ var ( // by testing multiple random ports within a specified range. func AllocateUniquePort(t *testing.T) int { randPort := func(base, spread int) int { - return base + rand.Intn(spread) + return base + mrand.IntN(spread) } // Base port and spread range for port selection