Commit 2d7323a
authored
gnd(test): Add mock-based subgraph test runner (#6361)
* gnd(test): Migrate from monolithic test.rs to modular test/ structure
Replaces monolithic gnd/src/commands/test.rs with organized test/
directory containing:
- mod.rs: Main entry point and test orchestration
- runner.rs: Test execution and infrastructure setup
- assertion.rs: GraphQL assertion logic
- block_stream.rs: Mock block stream implementation
- noop.rs: Stub trait implementations
- schema.rs: JSON schema and test types
- trigger.rs: ABI encoding for test triggers
- output.rs: Test result formatting
- mock_chain.rs: Block pointer helpers
Updates main.rs to make Test command async (.await).
Adds dependencies for test runner (graph-chain-ethereum,
graph-graphql, graph-store-postgres).
* gnd(test): Add remaining test module files
Adds supporting modules for test infrastructure:
- mock_chain: Helpers for block pointer construction
- schema: JSON schema types and parsing
- output: Console output formatting
- trigger: ABI encoding of test triggers
* gnd(test): Update module structure with new submodules
Adds module declarations for refactored components:
- mod assertion
- mod block_stream
- mod noop
Updates module documentation to reflect the new structure and improved
separation of concerns.
* gnd(test): Refactor runner.rs for readability - remove extracted code
Removes ~500 lines from runner.rs by delegating to new focused modules:
- block_stream: Mock block delivery infrastructure
- noop: Stub trait implementations
- assertion: GraphQL assertion logic
runner.rs now focuses exclusively on test orchestration:
- setup_stores: Initialize PostgreSQL and chain store
- setup_chain: Construct mock Ethereum chain
- setup_context: Wire up graph-node components
- wait_for_sync: Poll store until indexing completes
Reduced from 1198 to 729 lines (39% reduction).
Improves readability by separating concerns.
* gnd(test): Extract GraphQL assertion logic to dedicated module
Moves assertion execution to gnd/src/commands/test/assertion.rs:
- run_assertions: Execute all test assertions
- run_single_assertion: Execute and compare a single query
- r_value_to_json: Convert graph-node's r::Value to serde_json
- json_equal: Compare JSON with string-vs-number coercion
Makes TestContext fields pub(super) to allow assertion module access.
* gnd(test): Extract noop/stub trait implementations to dedicated module
Moves unused adapter stubs to gnd/src/commands/test/noop.rs:
- StaticBlockRefetcher
- NoopRuntimeAdapter / NoopRuntimeAdapterBuilder
- NoopAdapterSelector
- NoopTriggersAdapter
These satisfy Chain constructor trait bounds but are never called during
normal test execution since triggers are pre-built and host functions
are not available in mocks.
* gnd(test): Add eth_call mocking and refactor test output
* gnd(test): Add EIP-1559 base fee support and refactor block creation
- Add baseFeePerGas field to TestBlock schema
- Parse and apply base fee when creating test blocks
- Replace graph-node helper functions with direct alloy types
- Extract dummy_transaction creation into dedicated function
- Use alloy Block::empty() constructor for cleaner block creation
* gnd(test): Simplify test schema by auto-injecting block triggers
- Rename 'triggers' field to 'events' in TestBlock
- Remove TestTrigger enum and BlockTrigger type
- Keep LogEvent as the only event type users specify
- Auto-inject Start and End block triggers for every block
- This ensures block handlers fire correctly without explicit config
- Update docs to reflect that block triggers are automatic
* gnd(test): Add support for manifests with startBlock > 0
- Extract min startBlock from manifest in extract_start_block_from_manifest()
- Use startBlock as default test block numbering base
- Create start_block_override to bypass on-chain validation
- Pass override through setup_context() to SubgraphRegistrar
- This allows testing subgraphs that specify startBlock without needing a real chain
* gnd(test): Fix issues after rebase
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
* gnd(test): Fix matchstick path
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
* gnd(test): Reuse load_manifest()
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
* gnd(test): Add README, add important inline notes
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
* gnd: Fix missing fields, update readme
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
* gnd(test): Refactor CLI to accept test files/dirs as positional args
- Replace positional `manifest` arg with `--manifest` / `-m` flag (default: subgraph.yaml)
- Add positional `tests` args accepting file or directory
- When no args given, default to scanning `tests/`
- Bare filenames resolve to `tests/<filename>` for convenience (e.g., `gnd test foo.json` → `tests/foo.json`)
- Remove `--test-dir` flag (replaced by positional args)
- Update README with new usage examples
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
* gnd(test): Fix diff colors — red for expected, green for actual
* gnd(test): Support Array, FixedArray, and Tuple in Solidity type conversion
- Add Array, FixedArray, Tuple branches to json_to_sol_value
- Fix strip_prefix("0x") usage (trim_start_matches incorrectly strips repeated 0s)
- Fix i64::MIN two's complement handling via I256::into_raw()
- Add block number overflow check against i32::MAX
* gnd(test): Recurse into subdirectories when discovering test files
- discover_test_files now walks subdirectories recursively
- Skip entries starting with non-alphanumeric chars (.hidden, _fixture)
* gnd(test): Validate eth_call parameter and return value counts
Add upfront arity checks in encode_function_call and encode_return_value
so mismatches produce clear errors instead of silently truncating.
Also simplify redundant .with_context() wrappers in populate_single_call.
* gnd(test): Ensure subgraph cleanup and remove FilterStoreEventEndedDrain
- Remove FilterStoreEventEndedDrain log filter and unused logger field
- Always call stop_subgraph after test, even on error
- Warn when a test has blocks but no assertions
- Add block number overflow check against i32::MAX
* gnd(test): Validate datasource name to prevent shell injection in Docker mode
Add alphanumeric/hyphen/underscore validation before interpolating the
datasource name into Docker's sh -c command. Also simplify redundant
.with_context() wrappers.
* gnd(test): Replace unwrap/unimplemented with proper error handling
- block_stream: .unwrap() -> .expect() on mutex lock
- noop: unimplemented!() -> Err(anyhow!(...))
- mod: Fail early with bail! on missing test file
* gnd(test): Fix ServerAddress initialization
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
* gnd(test): Add verbose logging flag and extract manifest loading
Add `-v` / `--verbose` flag with count semantics for controlling
graph-node log verbosity during tests (-v=info, -vv=debug, -vvv=trace).
GRAPH_LOG env var always takes precedence when set.
Extract manifest loading into `ManifestInfo` struct loaded once per run,
avoiding redundant parsing across tests. Thread a single logger through
setup_stores/setup_chain instead of creating ad-hoc loggers.
* gnd(test): Add integration test harness with pgtemp fixes
Add gnd_test integration test suite with fixture subgraph and test
cases for blocks, transfers, templates, and expected failures. Fix
pgtemp Unix socket path overflow on macOS by overriding
unix_socket_directories to /tmp. Reduce default pool_size to 2.
* gnd(compiler): Look for asc binary in local if global does not exist.
* gnd(test): Use --postgres-url for tests
* gnd(test): Fix test cleanup for --postgres-url
* gnd(test): Replace TempPgHandle with TestDatabase enum
Makes the two database lifecycle paths explicit and self-documenting.
`TestDatabase::Temporary` vs `TestDatabase::Persistent`
(--postgres-url, needs cleanup) replaces the opaque `Option<TempPgHandle>`.
Cleanup in `setup_stores` is now gated on `db.needs_cleanup()` instead
of running unconditionally.
* gnd(test): Clean up persistent DB state after each test
When using --postgres-url, cleanup only ran at the start of each test
(to remove stale state from a previous run). The last test's deployment
was left in the DB, which broke unrelated unit test suites calling
remove_all_subgraphs_for_test_use_only() — they don't set
GRAPH_NODE_DISABLE_DEPLOYMENT_HASH_VALIDATION, so parsing the file-path
deployment hash fails.
Add post-test cleanup for persistent databases, mirroring the pre-test
cleanup. Pre-test handles interrupted runs; post-test handles the normal
case. Together they keep the DB clean regardless of how the run ends.
* gnd(test): Use Qm-prefixed SHA-1 hash as deployment hash
Each test run now computes a fake-but-valid DeploymentHash as
"Qm" + hex(sha1(manifest_path + seed)) where seed is the Unix
epoch in milliseconds. This:
- Passes DeploymentHash validation without bypassing it
- Produces a unique hash and subgraph name per run, so sequential
runs never conflict in the store
- Removes the pre-test cleanup (it would never match a fresh hash)
- Registers the hash as a FileLinkResolver alias so clone_for_manifest
can resolve it to the real manifest path
- Reuses the existing sha1 dep — no new dependencies
* gnd(test): Fix stale docs after pre-test cleanup removal
* gnd(test): Rename and move README into docs/
* gnd(test): Simplify TestResult, remove baseFeePerGas, fix timestamp default
- Flatten TestResult from enum to struct (handler_error + assertions fields)
- Remove AssertionOutcome/TestResult accessor methods; use public fields directly
- Remove baseFeePerGas from test block format (YAGNI)
- Change default block timestamp from number * 12 to number (chain-agnostic,
avoids future timestamps on high-block-number chains like Arbitrum)
* gnd(test): Move docs to correct location under gnd/docs/
* gnd(test): Fix fixture contract address
Update the contract address in the fixture subgraph manifest and
transfer.json test from the old placeholder address to the correct
one used by the test assertions.
* gnd(test): Fix AnyTxEnvelope and AnyHeader types in trigger.rs
dummy_transaction was returning Transaction<TxEnvelope> instead of the
required AnyTransaction (Transaction<AnyTxEnvelope>). Wrap the envelope
in AnyTxEnvelope::Ethereum(...) to match the expected type.
Also wrap ConsensusHeader in AnyHeader::from(...) when constructing the
block Header, producing Header<AnyHeader> as required by LightEthereumBlock::new.
* gnd(test): Address PR review comments
- Add -s short flag for --skip-build
- Print deprecation warning when --matchstick is used; update README
- Replace npm with pnpm in integration test setup
- Replace hand-rolled r_value_to_json with serde_json::to_value via
r::Value's built-in Serialize impl (also fixes Timestamp serialization)
- Make find_asc_binary pub and re-export from compiler module; reuse it
in gnd_test.rs instead of duplicating the lookup logic
- Skip DB cleanup on test failure for persistent databases and print the
connection URL so the data can be inspected
* gnd(test): Document lowercase hex requirement for assertions
graph-node returns all hex-encoded values (addresses, tx hashes, bytes)
in lowercase. Add a note in the Assertions section's comparison behavior
table and in Tips & Best Practices.
Event inputs are normalised automatically and can be mixed case.
Also fix the transfer.json fixture assertion to use lowercase token ID.
---------
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>1 parent db95c7d commit 2d7323a
File tree
36 files changed
+4708
-291
lines changed- gnd
- docs
- src
- commands
- test
- compiler
- validation
- tests
- fixtures/gnd_test/subgraph
- abis
- src
- tests
- graph/src/data_source
36 files changed
+4708
-291
lines changedSome generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
18 | 22 | | |
19 | 23 | | |
20 | 24 | | |
21 | 25 | | |
22 | 26 | | |
23 | 27 | | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
24 | 34 | | |
25 | 35 | | |
26 | 36 | | |
| |||
49 | 59 | | |
50 | 60 | | |
51 | 61 | | |
| 62 | + | |
52 | 63 | | |
53 | 64 | | |
54 | 65 | | |
| |||
78 | 89 | | |
79 | 90 | | |
80 | 91 | | |
81 | | - | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
301 | 301 | | |
302 | 302 | | |
303 | 303 | | |
304 | | - | |
| 304 | + | |
305 | 305 | | |
306 | 306 | | |
307 | | - | |
| 307 | + | |
308 | 308 | | |
309 | 309 | | |
310 | 310 | | |
311 | | - | |
| 311 | + | |
312 | 312 | | |
313 | 313 | | |
314 | 314 | | |
315 | 315 | | |
316 | 316 | | |
317 | | - | |
318 | | - | |
319 | | - | |
320 | | - | |
321 | | - | |
322 | | - | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
323 | 345 | | |
324 | 346 | | |
325 | 347 | | |
| |||
0 commit comments