-
Notifications
You must be signed in to change notification settings - Fork 182
feat: more wallet conformance tests #5959
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds ServerError::inner accessor. Introduces --allow-failure to GenerateTestSnapshot and threads it into run_test_with_dump to optionally tolerate RPC failures. Adds case-insensitive error policy and new wallet snapshot tests; removes several Wallet* entries from the ignore list. Uses inner() for snapshot error messages. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant CLI as Tool CLI
participant Gen as generate_test_snapshot::run_test_with_dump
participant RPC as RPC Executor
User->>CLI: run GenerateTestSnapshot --allow-failure
CLI->>Gen: run_test_with_dump(..., allow_failure)
loop For each RPC in dump
Gen->>RPC: execute RPC
alt RPC Ok
RPC-->>Gen: Ok(response)
Gen->>Gen: compare Forest vs Lotus (allow_response_mismatch honored)
else RPC Err and allow_failure = true
RPC-->>Gen: Err(e)
Gen->>Gen: skip failure for this RPC
else RPC Err and allow_failure = false
RPC-->>Gen: Err(e)
Gen-->>CLI: bail with error (includes RPC name)
end
end
Gen-->>CLI: success
sequenceDiagram
autonumber
participant Comp as API Compare Tests
participant Forest as Forest Node
participant Lotus as Lotus Node
Comp->>Forest: call method
Comp->>Lotus: call method
Forest-->>Comp: Rejected(error_reason)
Lotus-->>Comp: Rejected(error_reason)
alt Policy = PassWithIdenticalErrorCaseInsensitive
Comp->>Comp: lowercase(reason_forest) == lowercase(reason_lotus)?
alt equal
Comp-->>Comp: mark as pass
else not equal
Comp-->>Comp: mark as fail
end
else other policies
Comp-->>Comp: evaluate per existing rules
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Suggested labels
Suggested reviewers
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
60d7c7d to
36b4584
Compare
| .await | ||
| .map(|r| r.into_lotus_json()) | ||
| .map_err(|e| e.to_string()); | ||
| .map_err(|e| e.inner().to_string()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is needed, otherwise the error is wrapped and the comparison fails:
❯ forest-tool api test rpc-snaps/filecoin_walletvalidateaddress_1755692429792245.rpcsnap.json
2025-08-20T13:18:54.548741Z INFO forest::genesis: Initialized genesis: bafy2bzacecyaggy24wol5ruvs6qm73gjibs2l2iyhcqmvi7r7a4ph7zx3yqd4
thread 'main' panicked at /home/rumcajs/prj/forest3/src/tool/subcommands/api_cmd/test_snapshot.rs:120:5:
assertion `left == right` failed
left: Err("JSON-RPC error:\n\tcode: -32603\n\tmessage: Unknown address network\n")
right: Err("ErrorObject { code: InternalError, message: \"Unknown address network\", data: None }")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fish: Job 1, 'forest-tool api test rpc-snaps/…' terminated by signal SIGABRT (Abort)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (7)
src/tool/subcommands/api_cmd/api_compare_tests.rs (3)
1142-1161: Make comments future-proof; keep tests as identity checksThe test logic is solid. The comments asserting specific balances (e.g., “666 attoFIL each”) can go stale and aren’t enforced by the tests (which use identity Forest vs Lotus). Recommend softening them to avoid misleading future readers.
Apply this diff to update the comments:
- let prefunded_wallets = [ - // the following addresses should have 666 attoFIL each + let prefunded_wallets = [ + // Pre-funded addresses for conformance testing (expected to have non-zero balances) Address::from_str("t0168923").unwrap(), // this is the ID address of the `t1w2zb5a723izlm4q3khclsjcnapfzxcfhvqyfoly` address Address::from_str("t1w2zb5a723izlm4q3khclsjcnapfzxcfhvqyfoly").unwrap(), Address::from_str("t2nfplhzpyeck5dcc4fokj5ar6nbs3mhbdmq6xu3q").unwrap(), Address::from_str("t3wmbvnabsj6x2uki33phgtqqemmunnttowpx3chklrchy76pv52g5ajnaqdypxoomq5ubfk65twl5ofvkhshq").unwrap(), Address::from_str("t410fx2cumi6pgaz64varl77xbuub54bgs3k5xsvn3ki").unwrap(), - // This address should have 0 FIL + // Address expected to have zero balance Address::from_str("t1qb2x5qctp34rxd7ucl327h5ru6aazj2heno7x5y").unwrap(), ];
1174-1193: Fix typo in comment and keep error-policy usageThe negative validate-address case and the case-insensitive policy are spot on. Small typo nit in the comment.
- // Both Forest and Lotus should fail miserably at invocking Cthulhu's name + // Both Forest and Lotus should fail miserably at invoking Cthulhu's name
3086-3088: Prefer ASCII case-insensitive comparison without allocationsUse
eq_ignore_ascii_caseto avoid allocations fromto_lowercase()and match typical ASCII-only error messages.- reason_forest.to_lowercase() == reason_lotus.to_lowercase() + reason_forest.eq_ignore_ascii_case(reason_lotus)src/tool/subcommands/api_cmd/test_snapshot.rs (1)
109-109: Switching to inner error formatting aligns outputs across toolsUsing
e.inner().to_string()makes snapshot error strings originate from the JSON-RPC error object itself, reducing noise fromServerError’s Display. This is consistent with the new accessor and the intent in this PR.If you want even tighter alignment with API-compare behavior (which compares only the message), consider serializing
e.inner().message().to_string()instead. That would be a behavior change and require regenerating affected snapshots, so treat it as optional.src/tool/subcommands/api_cmd/generate_test_snapshot.rs (1)
49-63: Log skipped failures when allow_failure is setCurrently, failures are silently skipped when
allow_failureis true. A debug log will help diagnose why a snapshot was generated despite an RPC error.- match <$ty>::handle(ctx.clone(), params).await { + match <$ty>::handle(ctx.clone(), params).await { Ok(result) => { anyhow::ensure!( allow_response_mismatch || test_dump.forest_response == Ok(result.into_lotus_json_value()?), "Response mismatch between Forest and Lotus" ); } - Err(_) if allow_failure => { - // If we allow failure, we do not check the error - } + Err(e) if allow_failure => { + // If we allow failure, do not assert on the error, but record it for visibility. + tracing::debug!("Allowing failure for {}: {}", <$ty>::NAME, e); + } Err(e) => { bail!("Error running test {}: {}", <$ty>::NAME, e); } }src/tool/subcommands/api_cmd.rs (2)
175-177: Add --allow-failure flag: good addition; drop redundant default to simplifyClap treats boolean flags as false by default and sets them to true when present. The explicit
default_value_t = falseis unnecessary noise.Apply this minimal cleanup:
- /// Allow generating snapshot even if the test fails. - #[arg(long, default_value_t = false)] - allow_failure: bool, + /// Allow generating snapshot even if the test fails. + #[arg(long)] + allow_failure: bool,Optional: consider mentioning this new flag in the subcommand’s top-level doc block (above Line 156) so users see it in the long description alongside
--use-response-from.
278-279: Wiring and propagation of allow_failure look correct; consider avoiding positional boolsThe flag is correctly destructured and forwarded to
run_test_with_dump. However, two adjacent boolean parameters are easy to mix up when maintaining this code.Short-term readability nit (low-risk and local change): add inline parameter comments at the call site to disambiguate intent.
match generate_test_snapshot::run_test_with_dump( &test_dump, tracking_db.clone(), &chain, - allow_response_mismatch, - allow_failure, + /* allow_response_mismatch: */ allow_response_mismatch, + /* allow_failure: */ allow_failure, )Longer-term: replace the pair of bools with an options struct to make the API self-documenting and future-proof.
Example (outside this file):
// In generate_test_snapshot.rs pub struct RunTestOptions { pub allow_response_mismatch: bool, pub allow_failure: bool, } // Signature: pub async fn run_test_with_dump( dump: &TestDump, db: TrackingDb, chain: &NetworkChain, opts: RunTestOptions, ) -> anyhow::Result<()>;And here:
generate_test_snapshot::run_test_with_dump( &test_dump, tracking_db.clone(), &chain, RunTestOptions { allow_response_mismatch, allow_failure, }, ) .awaitAlso applies to: 299-304
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (7)
src/rpc/error.rs(1 hunks)src/tool/subcommands/api_cmd.rs(3 hunks)src/tool/subcommands/api_cmd/api_compare_tests.rs(4 hunks)src/tool/subcommands/api_cmd/generate_test_snapshot.rs(2 hunks)src/tool/subcommands/api_cmd/test_snapshot.rs(1 hunks)src/tool/subcommands/api_cmd/test_snapshots.txt(1 hunks)src/tool/subcommands/api_cmd/test_snapshots_ignored.txt(0 hunks)
💤 Files with no reviewable changes (1)
- src/tool/subcommands/api_cmd/test_snapshots_ignored.txt
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: LesnyRumcajs
PR: ChainSafe/forest#5907
File: src/rpc/methods/state.rs:523-570
Timestamp: 2025-08-06T15:44:33.467Z
Learning: LesnyRumcajs prefers to rely on BufWriter's Drop implementation for automatic flushing rather than explicit flush() calls in Forest codebase.
🧬 Code Graph Analysis (4)
src/rpc/error.rs (1)
src/rpc/methods/chain.rs (1)
ErrorObjectOwned(237-237)
src/tool/subcommands/api_cmd/api_compare_tests.rs (1)
src/shim/address.rs (2)
from_str(178-183)from_str(299-302)
src/tool/subcommands/api_cmd/test_snapshot.rs (1)
src/rpc/error.rs (1)
inner(84-86)
src/tool/subcommands/api_cmd/generate_test_snapshot.rs (2)
src/rpc/methods/eth.rs (12)
handle(719-727)handle(741-747)handle(761-782)handle(796-801)handle(816-830)handle(844-857)handle(1460-1471)handle(1485-1496)handle(1554-1561)handle(1574-1581)handle(1595-1607)e(1785-1785)src/lotus_json/mod.rs (1)
into_lotus_json_value(150-152)
🔇 Additional comments (4)
src/tool/subcommands/api_cmd/test_snapshots.txt (1)
209-223: Wallet snapshot entries added — looks goodThe newly added walletBalance, walletValidateAddress, and walletVerify snapshots integrate cleanly with the existing list. No concerns from me.
src/rpc/error.rs (1)
83-86: Public accessor to inner JSON-RPC error is appropriateExposing
ServerError::inner()as&ErrorObjectOwnedis a minimal, safe change that enables downstream consumers (tests/tools) to format error output more precisely. No behavioral regressions introduced.src/tool/subcommands/api_cmd/api_compare_tests.rs (1)
200-208: Case-insensitive policy variant is a sensible addition
PassWithIdenticalErrorCaseInsensitivefills a practical gap where only the casing differs between Lotus and Forest error messages. Enum usage is consistently handled inevaluate_test_success.src/tool/subcommands/api_cmd/generate_test_snapshot.rs (1)
31-37: New allow_failure flag is well-threadedIntroducing
allow_failurehere gives granular control during snapshot generation without impacting existing flows. Signature change and propagation look correct.
36b4584 to
5f6c98e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
src/tool/subcommands/api_cmd/api_compare_tests.rs (4)
3086-3088: Normalize error strings more robustly (ASCII + trim) before comparingUsing to_lowercase() can introduce Unicode case-mapping surprises and extra allocations. Given our error messages are ASCII, a cheaper and more predictable normalization is trim + to_ascii_lowercase.
Apply this diff:
- PolicyOnRejected::PassWithIdenticalErrorCaseInsensitive => { - reason_forest.to_lowercase() == reason_lotus.to_lowercase() - } + PolicyOnRejected::PassWithIdenticalErrorCaseInsensitive => { + reason_forest.trim().to_ascii_lowercase() + == reason_lotus.trim().to_ascii_lowercase() + }
1174-1193: Typo in comment (“invocking” → “invoking”) and good use of the new policyThe case-insensitive policy usage here is spot-on for the network-name message discrepancy. Minor nit: fix the comment spelling.
- // Both Forest and Lotus should fail miserably at invocking Cthulhu's name + // Both Forest and Lotus should fail miserably at invoking Cthulhu's name
2982-3001: Dedup key ignores policy_on_rejected; can drop distinct tests unintentionallyDedup uses (method_name, params, api_paths, ignore.is_some()). If we ever add two tests with the same request but different PolicyOnRejected, one will be discarded unintentionally. Including the enum discriminant in the key fixes this without exploding the key size.
Apply this diff:
- for test in tests.into_iter().unique_by( + for test in tests.into_iter().unique_by( |RpcTest { request: rpc::Request { method_name, params, api_paths, .. }, ignore, .. }| { - ( - method_name.clone(), - params.clone(), - *api_paths, - ignore.is_some(), - ) + ( + method_name.clone(), + params.clone(), + *api_paths, + ignore.is_some(), + std::mem::discriminant(&test.policy_on_rejected), + ) }, ) {
1142-1161: Wallet balance tests: tighten semantics to catch unintended state changesGreat coverage across address kinds (ID, robust t1, t2, t3/BLS, t4/delegated, and an expected-zero account). A quick grep confirms these six test addresses only appear here (no other tests mutate them), so risk of cross-test interference is low.
To further reduce flakiness and explicitly encode intent, switch from
RpcTest::identitytoRpcTest::validate, checking both cross-node equality and the expected sign:• src/tool/subcommands/api_cmd/api_compare_tests.rs: lines 1142–1148 (prefunded wallets)
• src/tool/subcommands/api_cmd/api_compare_tests.rs: line 1150 (expected-zero wallet)Example diff (assuming
TokenAmount::is_positiveandTokenAmount::is_zeroexist):- for wallet in prefunded_wallets { - tests.push(RpcTest::identity( - WalletBalance::request((wallet,)).unwrap(), - )); + for wallet in prefunded_wallets { + tests.push(RpcTest::validate( + WalletBalance::request((wallet,)).unwrap(), + |forest, lotus| forest == lotus && forest.is_positive(), // >0 for prefunded + )); } - // expected-zero - tests.push(RpcTest::identity( - WalletBalance::request((zero_wallet,)).unwrap(), - )); + // expected-zero + tests.push(RpcTest::validate( + WalletBalance::request((zero_wallet,)).unwrap(), + |forest, lotus| forest == lotus && forest.is_zero(), + ));If those helpers aren’t available, compare against
TokenAmount::zero()orBigInt::from(0)directly. Happy to help wire up a follow-up patch.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (7)
src/rpc/error.rs(1 hunks)src/tool/subcommands/api_cmd.rs(3 hunks)src/tool/subcommands/api_cmd/api_compare_tests.rs(4 hunks)src/tool/subcommands/api_cmd/generate_test_snapshot.rs(2 hunks)src/tool/subcommands/api_cmd/test_snapshot.rs(1 hunks)src/tool/subcommands/api_cmd/test_snapshots.txt(1 hunks)src/tool/subcommands/api_cmd/test_snapshots_ignored.txt(0 hunks)
💤 Files with no reviewable changes (1)
- src/tool/subcommands/api_cmd/test_snapshots_ignored.txt
🚧 Files skipped from review as they are similar to previous changes (5)
- src/tool/subcommands/api_cmd/test_snapshots.txt
- src/rpc/error.rs
- src/tool/subcommands/api_cmd/test_snapshot.rs
- src/tool/subcommands/api_cmd.rs
- src/tool/subcommands/api_cmd/generate_test_snapshot.rs
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: LesnyRumcajs
PR: ChainSafe/forest#5907
File: src/rpc/methods/state.rs:523-570
Timestamp: 2025-08-06T15:44:33.467Z
Learning: LesnyRumcajs prefers to rely on BufWriter's Drop implementation for automatic flushing rather than explicit flush() calls in Forest codebase.
🧬 Code graph analysis (1)
src/tool/subcommands/api_cmd/api_compare_tests.rs (1)
src/shim/address.rs (2)
from_str(178-183)from_str(299-302)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
- GitHub Check: All lint checks
- GitHub Check: Build forest binaries on Linux AMD64
- GitHub Check: Build Ubuntu
- GitHub Check: cargo-publish-dry-run
- GitHub Check: Build MacOS
- GitHub Check: tests
- GitHub Check: tests-release
- GitHub Check: Analyze (actions)
- GitHub Check: Analyze (python)
- GitHub Check: Analyze (rust)
- GitHub Check: Analyze (go)
- GitHub Check: Analyze (ruby)
🔇 Additional comments (1)
src/tool/subcommands/api_cmd/api_compare_tests.rs (1)
200-208: Nice addition: case-insensitive error policy variantThe new PolicyOnRejected::PassWithIdenticalErrorCaseInsensitive fills a real gap where only casing differs between Lotus and Forest error reasons. The wiring through evaluate_test_success looks correct.
Summary of changes
Changes introduced in this pull request:
Reference issue to close (if applicable)
Closes #5942
Other information and links
Change checklist
Summary by CodeRabbit