Skip to content

Commit a5ef771

Browse files
authored
chore: refactor tests to allow dynamic injection of docker client (#3098)
* chore: refactor test setup to allow for injection of docker client * chore: fix test compilation errors, removed useless comments * chore: addresing PR feedback
1 parent 6d6cc17 commit a5ef771

10 files changed

+202
-165
lines changed

execution/evm/test/execution_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88
"time"
99

10+
tastoradocker "github.com/celestiaorg/tastora/framework/docker"
1011
"github.com/ethereum/go-ethereum/common"
1112
ethTypes "github.com/ethereum/go-ethereum/core/types"
1213
"github.com/ethereum/go-ethereum/ethclient"
@@ -59,8 +60,10 @@ func TestEngineExecution(t *testing.T) {
5960
genesisStateRoot := common.HexToHash(GENESIS_STATEROOT)
6061
GenesisStateRoot := genesisStateRoot[:]
6162

63+
dockerClient, dockerNetworkID := tastoradocker.Setup(t)
64+
6265
t.Run("Build chain", func(tt *testing.T) {
63-
rethNode := SetupTestRethNode(t)
66+
rethNode := SetupTestRethNode(t, dockerClient, dockerNetworkID)
6467

6568
ni, err := rethNode.GetNetworkInfo(context.TODO())
6669
require.NoError(tt, err)
@@ -158,7 +161,7 @@ func TestEngineExecution(t *testing.T) {
158161

159162
// start new container and try to sync
160163
t.Run("Sync chain", func(tt *testing.T) {
161-
rethNode := SetupTestRethNode(t)
164+
rethNode := SetupTestRethNode(t, dockerClient, dockerNetworkID)
162165

163166
ni, err := rethNode.GetNetworkInfo(context.TODO())
164167
require.NoError(tt, err)

execution/evm/test/test_helpers.go

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@ import (
99
mathrand "math/rand"
1010
"net/http"
1111
"strings"
12-
"sync"
1312
"testing"
1413
"time"
1514

16-
"github.com/celestiaorg/tastora/framework/docker"
1715
"github.com/celestiaorg/tastora/framework/docker/evstack/reth"
1816
"github.com/celestiaorg/tastora/framework/types"
1917
"github.com/golang-jwt/jwt/v5"
@@ -22,12 +20,8 @@ import (
2220
"go.uber.org/zap/zaptest"
2321
)
2422

25-
// Test-scoped Docker client/network mapping to avoid conflicts between tests
26-
var (
27-
dockerClients = make(map[string]types.TastoraDockerClient)
28-
dockerNetworks = make(map[string]string)
29-
dockerMutex sync.RWMutex
30-
)
23+
// RethNodeOpt allows tests to customize the reth node builder before building.
24+
type RethNodeOpt func(b *reth.NodeBuilder)
3125

3226
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
3327

@@ -40,52 +34,36 @@ func randomString(n int) string {
4034
return string(b)
4135
}
4236

43-
// getTestScopedDockerSetup returns a Docker client and network ID that are scoped to the specific test.
44-
func getTestScopedDockerSetup(t testing.TB) (types.TastoraDockerClient, string) {
45-
t.Helper()
46-
47-
testKey := t.Name()
48-
dockerMutex.Lock()
49-
defer dockerMutex.Unlock()
50-
51-
dockerCli, exists := dockerClients[testKey]
52-
if !exists {
53-
cli, netID := docker.Setup(t)
54-
dockerClients[testKey] = cli
55-
dockerNetworks[testKey] = netID
56-
dockerCli = cli
57-
}
58-
dockerNetID := dockerNetworks[testKey]
59-
60-
return dockerCli, dockerNetID
61-
}
62-
6337
// SetupTestRethNode creates a single Reth node for testing purposes.
64-
func SetupTestRethNode(t testing.TB) *reth.Node {
38+
func SetupTestRethNode(t testing.TB, client types.TastoraDockerClient, networkID string, opts ...RethNodeOpt) *reth.Node {
6539
t.Helper()
6640
ctx := context.Background()
6741

68-
dockerCli, dockerNetID := getTestScopedDockerSetup(t)
69-
7042
testName := fmt.Sprintf("%s-%s", t.Name(), randomString(6))
7143
logger := zap.NewNop()
7244
if testing.Verbose() {
7345
logger = zaptest.NewLogger(t)
7446
}
75-
n, err := new(reth.NodeBuilder).
47+
b := new(reth.NodeBuilder).
7648
WithTestName(testName).
7749
WithLogger(logger).
7850
WithImage(reth.DefaultImage()).
7951
WithBin("ev-reth").
80-
WithDockerClient(dockerCli).
81-
WithDockerNetworkID(dockerNetID).
82-
WithGenesis([]byte(reth.DefaultEvolveGenesisJSON())).
83-
Build(ctx)
52+
WithDockerClient(client).
53+
WithDockerNetworkID(networkID).
54+
WithGenesis([]byte(reth.DefaultEvolveGenesisJSON()))
55+
56+
for _, opt := range opts {
57+
if opt != nil {
58+
opt(b)
59+
}
60+
}
61+
62+
n, err := b.Build(ctx)
63+
require.NoError(t, err)
8464
t.Cleanup(func() {
8565
_ = n.Remove(context.Background())
8666
})
87-
88-
require.NoError(t, err)
8967
require.NoError(t, n.Start(ctx))
9068

9169
ni, err := n.GetNetworkInfo(ctx)

test/e2e/evm_contract_e2e_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"testing"
1111
"time"
1212

13+
tastoradocker "github.com/celestiaorg/tastora/framework/docker"
1314
"github.com/ethereum/go-ethereum"
1415
"github.com/ethereum/go-ethereum/common"
1516
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -243,7 +244,8 @@ func TestEvmContractEvents(t *testing.T) {
243244
func setupTestSequencer(t testing.TB, homeDir string, extraArgs ...string) (*ethclient.Client, string, func()) {
244245
sut := NewSystemUnderTest(t)
245246

246-
genesisHash, seqEthURL := setupSequencerOnlyTest(t, sut, homeDir, extraArgs...)
247+
dcli, netID := tastoradocker.Setup(t)
248+
genesisHash, seqEthURL := setupSequencerOnlyTest(t, sut, homeDir, dcli, netID, extraArgs...)
247249
t.Logf("Sequencer started at %s (Genesis: %s)", seqEthURL, genesisHash)
248250

249251
client, err := ethclient.Dial(seqEthURL)

test/e2e/evm_da_restart_e2e_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"testing"
2525
"time"
2626

27+
tastoradocker "github.com/celestiaorg/tastora/framework/docker"
2728
"github.com/ethereum/go-ethereum/common"
2829
"github.com/ethereum/go-ethereum/ethclient"
2930
"github.com/stretchr/testify/require"
@@ -56,7 +57,8 @@ func TestEvmDARestartWithPendingBlocksE2E(t *testing.T) {
5657
sut := NewSystemUnderTest(t)
5758

5859
// Setup sequencer and get genesis hash
59-
genesisHash, seqURL := setupSequencerOnlyTest(t, sut, nodeHome)
60+
dcli, netID := tastoradocker.Setup(t)
61+
genesisHash, seqURL := setupSequencerOnlyTest(t, sut, nodeHome, dcli, netID)
6062
t.Logf("Genesis hash: %s", genesisHash)
6163

6264
// Connect to EVM

test/e2e/evm_force_inclusion_e2e_test.go

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"testing"
1414
"time"
1515

16+
tastoradocker "github.com/celestiaorg/tastora/framework/docker"
1617
"github.com/ethereum/go-ethereum/common"
1718
"github.com/ethereum/go-ethereum/ethclient"
1819
"github.com/rs/zerolog"
@@ -77,13 +78,14 @@ func setupSequencerWithForceInclusion(t *testing.T, sut *SystemUnderTest, nodeHo
7778
t.Helper()
7879

7980
// Use common setup (no full node needed initially)
80-
jwtSecret, _, genesisHash, endpoints, _ := setupCommonEVMTest(t, sut, false)
81+
dcli, netID := tastoradocker.Setup(t)
82+
env := setupCommonEVMEnv(t, sut, dcli, netID)
8183

8284
// Create passphrase file
8385
passphraseFile := createPassphraseFile(t, nodeHome)
8486

8587
// Create JWT secret file
86-
jwtSecretFile := createJWTSecretFile(t, nodeHome, jwtSecret)
88+
jwtSecretFile := createJWTSecretFile(t, nodeHome, env.SequencerJWT)
8789

8890
// Initialize sequencer node
8991
output, err := sut.RunCmd(evmSingleBinaryPath,
@@ -102,25 +104,25 @@ func setupSequencerWithForceInclusion(t *testing.T, sut *SystemUnderTest, nodeHo
102104
args := []string{
103105
"start",
104106
"--evm.jwt-secret-file", jwtSecretFile,
105-
"--evm.genesis-hash", genesisHash,
107+
"--evm.genesis-hash", env.GenesisHash,
106108
"--evnode.node.block_time", DefaultBlockTime,
107109
"--evnode.node.aggregator=true",
108110
"--evnode.signer.passphrase_file", passphraseFile,
109111
"--home", nodeHome,
110112
"--evnode.da.block_time", DefaultDABlockTime,
111-
"--evnode.da.address", endpoints.GetDAAddress(),
113+
"--evnode.da.address", env.Endpoints.GetDAAddress(),
112114
"--evnode.da.namespace", DefaultDANamespace,
113115
"--evnode.da.forced_inclusion_namespace", "forced-inc",
114-
"--evnode.rpc.address", endpoints.GetRollkitRPCListen(),
115-
"--evnode.p2p.listen_address", endpoints.GetRollkitP2PAddress(),
116-
"--evm.engine-url", endpoints.GetSequencerEngineURL(),
117-
"--evm.eth-url", endpoints.GetSequencerEthURL(),
116+
"--evnode.rpc.address", env.Endpoints.GetRollkitRPCListen(),
117+
"--evnode.p2p.listen_address", env.Endpoints.GetRollkitP2PAddress(),
118+
"--evm.engine-url", env.Endpoints.GetSequencerEngineURL(),
119+
"--evm.eth-url", env.Endpoints.GetSequencerEthURL(),
118120
"--force-inclusion-server", fiAddr,
119121
}
120122
sut.ExecCmd(evmSingleBinaryPath, args...)
121-
sut.AwaitNodeUp(t, endpoints.GetRollkitRPCAddress(), NodeStartupTimeout)
123+
sut.AwaitNodeUp(t, env.Endpoints.GetRollkitRPCAddress(), NodeStartupTimeout)
122124

123-
return genesisHash, endpoints.GetSequencerEthURL()
125+
return env.GenesisHash, env.Endpoints.GetSequencerEthURL()
124126
}
125127

126128
func TestEvmSequencerForceInclusionE2E(t *testing.T) {
@@ -192,10 +194,11 @@ func TestEvmFullNodeForceInclusionE2E(t *testing.T) {
192194
// --- Start Sequencer Setup ---
193195
// We manually setup sequencer here because we need the force inclusion flag,
194196
// and we need to capture variables for full node setup.
195-
jwtSecret, fullNodeJwtSecret, genesisHash, endpoints, _ := setupCommonEVMTest(t, sut, true)
197+
dockerClient, networkID := tastoradocker.Setup(t)
198+
env := setupCommonEVMEnv(t, sut, dockerClient, networkID, WithFullNode())
196199

197200
passphraseFile := createPassphraseFile(t, sequencerHome)
198-
jwtSecretFile := createJWTSecretFile(t, sequencerHome, jwtSecret)
201+
jwtSecretFile := createJWTSecretFile(t, sequencerHome, env.SequencerJWT)
199202

200203
output, err := sut.RunCmd(evmSingleBinaryPath,
201204
"init",
@@ -212,38 +215,38 @@ func TestEvmFullNodeForceInclusionE2E(t *testing.T) {
212215
seqArgs := []string{
213216
"start",
214217
"--evm.jwt-secret-file", jwtSecretFile,
215-
"--evm.genesis-hash", genesisHash,
218+
"--evm.genesis-hash", env.GenesisHash,
216219
"--evnode.node.block_time", DefaultBlockTime,
217220
"--evnode.node.aggregator=true",
218221
"--evnode.signer.passphrase_file", passphraseFile,
219222
"--home", sequencerHome,
220223
"--evnode.da.block_time", DefaultDABlockTime,
221-
"--evnode.da.address", endpoints.GetDAAddress(),
224+
"--evnode.da.address", env.Endpoints.GetDAAddress(),
222225
"--evnode.da.namespace", DefaultDANamespace,
223226
"--evnode.da.forced_inclusion_namespace", "forced-inc",
224-
"--evnode.rpc.address", endpoints.GetRollkitRPCListen(),
225-
"--evnode.p2p.listen_address", endpoints.GetRollkitP2PAddress(),
226-
"--evm.engine-url", endpoints.GetSequencerEngineURL(),
227-
"--evm.eth-url", endpoints.GetSequencerEthURL(),
227+
"--evnode.rpc.address", env.Endpoints.GetRollkitRPCListen(),
228+
"--evnode.p2p.listen_address", env.Endpoints.GetRollkitP2PAddress(),
229+
"--evm.engine-url", env.Endpoints.GetSequencerEngineURL(),
230+
"--evm.eth-url", env.Endpoints.GetSequencerEthURL(),
228231
"--force-inclusion-server", fiAddr,
229232
}
230233
sut.ExecCmd(evmSingleBinaryPath, seqArgs...)
231-
sut.AwaitNodeUp(t, endpoints.GetRollkitRPCAddress(), NodeStartupTimeout)
234+
sut.AwaitNodeUp(t, env.Endpoints.GetRollkitRPCAddress(), NodeStartupTimeout)
232235
t.Log("Sequencer is up with force inclusion enabled")
233236
// --- End Sequencer Setup ---
234237

235238
// --- Start Full Node Setup ---
236239
// Reuse setupFullNode helper which handles genesis copying and node startup
237-
setupFullNode(t, sut, fullNodeHome, sequencerHome, fullNodeJwtSecret, genesisHash, endpoints.GetRollkitP2PAddress(), endpoints)
240+
setupFullNode(t, sut, fullNodeHome, sequencerHome, env.FullNodeJWT, env.GenesisHash, env.Endpoints.GetRollkitP2PAddress(), env.Endpoints)
238241
t.Log("Full node is up")
239242
// --- End Full Node Setup ---
240243

241244
// Connect to clients
242-
seqClient, err := ethclient.Dial(endpoints.GetSequencerEthURL())
245+
seqClient, err := ethclient.Dial(env.Endpoints.GetSequencerEthURL())
243246
require.NoError(t, err)
244247
defer seqClient.Close()
245248

246-
fnClient, err := ethclient.Dial(endpoints.GetFullNodeEthURL())
249+
fnClient, err := ethclient.Dial(env.Endpoints.GetFullNodeEthURL())
247250
require.NoError(t, err)
248251
defer fnClient.Close()
249252

@@ -284,10 +287,12 @@ func setupMaliciousSequencer(t *testing.T, sut *SystemUnderTest, nodeHome string
284287
t.Helper()
285288

286289
// Use common setup with full node support
287-
jwtSecret, fullNodeJwtSecret, genesisHash, endpoints, _ := setupCommonEVMTest(t, sut, true)
290+
dockerClient, networkID := tastoradocker.Setup(t)
291+
env := setupCommonEVMEnv(t, sut, dockerClient, networkID, WithFullNode())
292+
// Use env fields inline below to reduce local vars
288293

289294
passphraseFile := createPassphraseFile(t, nodeHome)
290-
jwtSecretFile := createJWTSecretFile(t, nodeHome, jwtSecret)
295+
jwtSecretFile := createJWTSecretFile(t, nodeHome, env.SequencerJWT)
291296

292297
output, err := sut.RunCmd(evmSingleBinaryPath,
293298
"init",
@@ -303,25 +308,25 @@ func setupMaliciousSequencer(t *testing.T, sut *SystemUnderTest, nodeHome string
303308
seqArgs := []string{
304309
"start",
305310
"--evm.jwt-secret-file", jwtSecretFile,
306-
"--evm.genesis-hash", genesisHash,
311+
"--evm.genesis-hash", env.GenesisHash,
307312
"--evnode.node.block_time", DefaultBlockTime,
308313
"--evnode.node.aggregator=true",
309314
"--evnode.signer.passphrase_file", passphraseFile,
310315
"--home", nodeHome,
311316
"--evnode.da.block_time", DefaultDABlockTime,
312-
"--evnode.da.address", endpoints.GetDAAddress(),
317+
"--evnode.da.address", env.Endpoints.GetDAAddress(),
313318
"--evnode.da.namespace", DefaultDANamespace,
314319
// CRITICAL: Set sequencer to listen to WRONG namespace - it won't see forced txs
315320
"--evnode.da.forced_inclusion_namespace", "wrong-namespace",
316-
"--evnode.rpc.address", endpoints.GetRollkitRPCListen(),
317-
"--evnode.p2p.listen_address", endpoints.GetRollkitP2PAddress(),
318-
"--evm.engine-url", endpoints.GetSequencerEngineURL(),
319-
"--evm.eth-url", endpoints.GetSequencerEthURL(),
321+
"--evnode.rpc.address", env.Endpoints.GetRollkitRPCListen(),
322+
"--evnode.p2p.listen_address", env.Endpoints.GetRollkitP2PAddress(),
323+
"--evm.engine-url", env.Endpoints.GetSequencerEngineURL(),
324+
"--evm.eth-url", env.Endpoints.GetSequencerEthURL(),
320325
}
321326
sut.ExecCmd(evmSingleBinaryPath, seqArgs...)
322-
sut.AwaitNodeUp(t, endpoints.GetRollkitRPCAddress(), NodeStartupTimeout)
327+
sut.AwaitNodeUp(t, env.Endpoints.GetRollkitRPCAddress(), NodeStartupTimeout)
323328

324-
return genesisHash, fullNodeJwtSecret, endpoints
329+
return env.GenesisHash, env.FullNodeJWT, env.Endpoints
325330
}
326331

327332
// setupFullNodeWithForceInclusionCheck sets up a full node that WILL verify forced inclusion txs

0 commit comments

Comments
 (0)