Skip to content

Migrate seismic e2e tests from subprocess to in-process node harness #338

@ameya-deshmukh

Description

@ameya-deshmukh

Context

PR #336 fixed immediate lifecycle issues (orphaned processes, port conflicts, retry storms) in the seismic integration test. However, the underlying test architecture still shells out to cargo run --bin seismic-reth, which is fundamentally brittle and slow.

Current problems

  1. Recompilation at test timecargo run --bin seismic-reth reinvokes the compiler inside the test (utils.rs:47). Even though the test binary itself was just compiled, the cargo run triggers a separate compilation of the seismic-reth binary, adding significant time especially in CI.
  2. Hardcoded HTTP RPC porturl() returns 127.0.0.1:8545 (utils.rs:132), a latent source of conflicts if anything else binds that port.
  3. Stdout parsing for readiness — the test waits for "Starting consensus engine" in stdout to know the node is up; any log format change silently breaks this.
  4. Silent hangs on read errorsread_line errors in the spawned stdout/stderr tasks panic silently (the JoinHandle is never awaited), causing the test to hang until the nextest timeout.
  5. No isolation — all tests share the same filesystem paths and ports; parallel execution is impossible.

Proposed improvement

Upstream reth provides reth_e2e_test_utils which starts a full node in-process via NodeBuilder::new(config).testing_node(executor). Migrating to this pattern would:

  • Eliminate recompilation — the node is compiled once as part of the test binary, not again at runtime via cargo run.
  • Remove port conflicts — RPC is in-process, no TCP ports needed.
  • Improve isolation — each test gets its own TempDatabase.
  • Give direct access — call into node internals (pool, provider, payload builder) instead of going through HTTP RPC.
  • Simplify lifecycle — no process management, stdout parsing, or kill_on_drop.

The target API would look like:

let (mut nodes, _tasks, wallet) = setup::<SeismicNode>(
    1, Arc::new(chain_spec), false, eth_payload_attributes,
).await?;
let mut node = nodes.pop().unwrap();
let raw_tx = TransactionTestContext::transfer_tx_bytes(1, wallet.inner).await;
let tx_hash = node.rpc.inject_tx(raw_tx).await?;
let payload = node.advance_block().await?;

This may require implementing additional traits on SeismicNode to satisfy the NodeBuilder test infrastructure.

Intermediate step

Before the full migration, the hardcoded port 8545 can be addressed by parsing the bound port from reth's startup logs and passing it to url() dynamically.

References

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions