gnd(test): Add mock-based subgraph test runner#6361
Draft
dimitrovmaksim wants to merge 16 commits intographprotocol:masterfrom
Draft
gnd(test): Add mock-based subgraph test runner#6361dimitrovmaksim wants to merge 16 commits intographprotocol:masterfrom
dimitrovmaksim wants to merge 16 commits intographprotocol:masterfrom
Conversation
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).
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
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.
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.
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.
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.
- 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
- 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
- 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
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
Signed-off-by: Maksim Dimitrov <dimitrov.maksim@gmail.com>
- 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements a native test runner for
gnd testthat executes JSON-defined tests through real graph-node infrastructure (store, WASM runtime, trigger processing) with only the blockchain layer mocked. Provides a faster, integrated alternative to Matchstick while maintaining backward compatibility.Key Features
once,polling, no filter)--matchstickflag preserves legacy behaviorArchitecture
Design decisions:
StaticStreamBuilder)Usage
Test Format Example
{ "name": "Transfer creates entity", "blocks": [ { "number": 1, "events": [ { "address": "0x1234...", "event": "Transfer(address indexed from, address indexed to, uint256 value)", "params": {"from": "0xaaaa...", "to": "0xbbbb...", "value": "1000"} } ], "ethCalls": [ { "address": "0x1234...", "function": "balanceOf(address)(uint256)", "params": ["0xaaaa..."], "returns": ["1000000000000000000"] } ] } ], "assertions": [ { "query": "{ transfer(id: \"1\") { from to value } }", "expected": {"transfer": {"from": "0xaaaa...", "to": "0xbbbb...", "value": "1000"}} } ] }Implementation
Modified Graph-Node Files
graph/src/data_source/subgraph.rs- Minor exports for startBlock supportSupported Features
once,polling, no filter)Breaking Changes
None. Adds native testing while preserving
--matchstickfor backward compatibility.Code Attribution
Human contributions: Initial requirements, code review, validation, and bug fixes.
Future Work
--jsonCI output format--filter)Checklist
--matchstick