From 269937ed90811287893b8d79b2a0dbea7598e836 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Tue, 16 Dec 2025 07:43:59 +0100 Subject: [PATCH] Test components in parallel --- playground/components_test.go | 19 ++++++++++++++++++- playground/local_runner.go | 30 +++++++++++++----------------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/playground/components_test.go b/playground/components_test.go index 8c114f6..c330ddb 100644 --- a/playground/components_test.go +++ b/playground/components_test.go @@ -9,6 +9,7 @@ import ( "path/filepath" "regexp" "strings" + "sync" "testing" "time" @@ -16,6 +17,8 @@ import ( ) func TestRecipeOpstackSimple(t *testing.T) { + t.Parallel() + tt := newTestFramework(t) defer tt.Close() @@ -23,6 +26,8 @@ func TestRecipeOpstackSimple(t *testing.T) { } func TestRecipeOpstackExternalBuilder(t *testing.T) { + t.Parallel() + tt := newTestFramework(t) defer tt.Close() @@ -32,6 +37,8 @@ func TestRecipeOpstackExternalBuilder(t *testing.T) { } func TestRecipeOpstackEnableForkAfter(t *testing.T) { + t.Parallel() + tt := newTestFramework(t) defer tt.Close() @@ -46,6 +53,8 @@ func TestRecipeOpstackEnableForkAfter(t *testing.T) { } func TestRecipeL1Simple(t *testing.T) { + t.Parallel() + tt := newTestFramework(t) defer tt.Close() @@ -53,6 +62,8 @@ func TestRecipeL1Simple(t *testing.T) { } func TestRecipeL1UseNativeReth(t *testing.T) { + t.Parallel() + tt := newTestFramework(t) defer tt.Close() @@ -62,6 +73,8 @@ func TestRecipeL1UseNativeReth(t *testing.T) { } func TestComponentBuilderHub(t *testing.T) { + t.Parallel() + tt := newTestFramework(t) defer tt.Close() @@ -83,6 +96,8 @@ func newTestFramework(t *testing.T) *testFramework { return &testFramework{t: t} } +var artifactsLock sync.Mutex + func (tt *testFramework) test(s ServiceGen, args []string) *Manifest { t := tt.t @@ -114,7 +129,10 @@ func (tt *testFramework) test(s ServiceGen, args []string) *Manifest { err := recipe.Flags().Parse(args) require.NoError(t, err) + artifactsLock.Lock() _, err = recipe.Artifacts().OutputDir(e2eTestDir).Build() + artifactsLock.Unlock() + require.NoError(t, err) } @@ -136,7 +154,6 @@ func (tt *testFramework) test(s ServiceGen, args []string) *Manifest { dockerRunner, err := NewLocalRunner(cfg) require.NoError(t, err) - dockerRunner.cleanupNetwork = true tt.runner = dockerRunner err = dockerRunner.Run(context.Background()) diff --git a/playground/local_runner.go b/playground/local_runner.go index 0a72c6f..34872cd 100644 --- a/playground/local_runner.go +++ b/playground/local_runner.go @@ -43,10 +43,6 @@ type LocalRunner struct { manifest *Manifest client *client.Client - // reservedPorts is a map of port numbers reserved for each service to avoid conflicts - // since we reserve ports for all the services before they are used - reservedPorts map[int]bool - // handles stores the references to the processes that are running on host machine // they are executed sequentially so we do not need to lock the handles handles []*exec.Cmd @@ -57,9 +53,6 @@ type LocalRunner struct { // tasks tracks the status of each service tasksMtx sync.Mutex tasks map[string]*task - - // whether to remove the network name after execution (used in testing) - cleanupNetwork bool } type task struct { @@ -147,14 +140,13 @@ func NewLocalRunner(cfg *RunnerConfig) (*LocalRunner, error) { } d := &LocalRunner{ - config: cfg, - out: cfg.Out, - manifest: cfg.Manifest, - client: client, - reservedPorts: map[int]bool{}, - handles: []*exec.Cmd{}, - tasks: tasks, - exitErr: make(chan error, 2), + config: cfg, + out: cfg.Out, + manifest: cfg.Manifest, + client: client, + handles: []*exec.Cmd{}, + tasks: tasks, + exitErr: make(chan error, 2), } return d, nil @@ -247,12 +239,16 @@ func (d *LocalRunner) Stop() error { return nil } +var ( + reservedPorts sync.Map +) + // reservePort finds the first available port from the startPort and reserves it // Note that we have to keep track of the port in 'reservedPorts' because // the port allocation happens before the services uses it and binds to it. func (d *LocalRunner) reservePort(startPort int, protocol string) int { for i := startPort; i < startPort+1000; i++ { - if _, ok := d.reservedPorts[i]; ok { + if _, ok := reservedPorts.Load(i); ok { continue } @@ -280,7 +276,7 @@ func (d *LocalRunner) reservePort(startPort int, protocol string) int { panic(fmt.Sprintf("invalid protocol: %s", protocol)) } - d.reservedPorts[i] = true + reservedPorts.Store(i, true) return i } panic("BUG: could not reserve a port")