test: ethflow error-path coverage + manifest topic-0 assertions#164
test: ethflow error-path coverage + manifest topic-0 assertions#164jean-neiverth wants to merge 1 commit into
Conversation
Add 429 rate-limiting and malformed-JSON-body test cases to ethflow-watcher's observe path. Both verify the strategy handles degraded orderbook responses without writing false markers. Add a compile-time assertion per module that the hardcoded event_signature in module.toml matches the keccak256 SIGNATURE_HASH from the cowprotocol crate, so an ABI change or typo breaks the build instead of silently missing on-chain events. Closes #60 Closes #61
lgahdl
left a comment
There was a problem hiding this comment.
Solid additions — the topic-0 pin tests are especially valuable (a silently mismatched event_signature would drop all on-chain events). Two small comments and one doc nit.
| fn manifest_topic0_matches_order_placement_signature_hash() { | ||
| let manifest = include_str!("../module.toml"); | ||
| let expected = format!("0x{:x}", OrderPlacement::SIGNATURE_HASH); | ||
| assert!( |
There was a problem hiding this comment.
manifest.contains(&expected) searches the whole file as a raw string — today it only matches because the hash appears once, but a future TOML addition (comment, second subscription, etc.) could produce a false positive. Anchoring to the field name makes the intent explicit:
| assert!( | |
| assert!( | |
| manifest.contains(&format!("event_signature = \"{expected}\"")), |
|
|
||
| /// 200 with a malformed (non-JSON) body → the observe path still | ||
| /// marks the order as observed, because the strategy only checks | ||
| /// the HTTP status, not the body structure. |
There was a problem hiding this comment.
The comment describes what the strategy does, not why. The reason the body is irrelevant is that HTTP 200 is the orderbook's contract guarantee that the order is indexed — the response body is an implementation detail, not part of that contract.
| /// the HTTP status, not the body structure. | |
| /// marks the order as observed. HTTP 200 is the orderbook's contract | |
| /// guarantee that the order is indexed; the response body is not | |
| /// part of that contract. |
| let expected = format!("0x{:x}", ConditionalOrderCreated::SIGNATURE_HASH); | ||
| assert!( | ||
| manifest.contains(&expected), | ||
| "module.toml event_signature must equal ConditionalOrderCreated::SIGNATURE_HASH\n\ |
There was a problem hiding this comment.
Same manifest.contains raw-string concern as in ethflow-watcher — anchor to the TOML field to make the assertion precise:
| "module.toml event_signature must equal ConditionalOrderCreated::SIGNATURE_HASH\n\ | |
| assert!( | |
| manifest.contains(&format!("event_signature = \"{expected}\"")), |
lgahdl
left a comment
There was a problem hiding this comment.
Good coverage additions. One assertion is fragile; one minor note on the topic-0 guard.
| .filter(|l| l.message.contains("indexer check failed")) | ||
| .collect(); | ||
| assert_eq!(warn_lines.len(), 1); | ||
| assert_eq!(warn_lines[0].level, LogLevel::Warn); |
There was a problem hiding this comment.
SdkHostError's Display may render the message field ("Too Many Requests") without the numeric code, in which case this assertion fails even when the behaviour is correct. Use "Too Many Requests" instead, or drop the string check and rely on the level + empty-store assertions which already capture the important invariant.
| assert_eq!(warn_lines[0].level, LogLevel::Warn); | |
| assert!(warn_lines[0].message.contains("Too Many Requests")); |
| fn manifest_topic0_matches_order_placement_signature_hash() { | ||
| let manifest = include_str!("../module.toml"); | ||
| let expected = format!("0x{:x}", OrderPlacement::SIGNATURE_HASH); | ||
| assert!( |
There was a problem hiding this comment.
Minor: manifest.contains(&expected) passes if the hash string appears anywhere in the manifest (comment, another field). In practice a 32-byte hex won't show up elsewhere, but parsing the TOML and comparing event_signature directly would make the test self-documenting and immune to that edge case.
Reads the shipped module.toml via include_str! and asserts its pinned event_signature equals the OrderPlacement / ConditionalOrderCreated SIGNATURE_HASH constant - a manifest/code drift the existing ABI-hash guard cannot catch. Ported from #164 before closing it as superseded.
|
Superseded by #343. Both add the same #60/#61 coverage (topic-0 guards + EthFlow 429 / malformed-body tests), but this PR is pinned to the pre-refactor |
Reads the shipped module.toml via include_str! and asserts its pinned event_signature equals the OrderPlacement / ConditionalOrderCreated SIGNATURE_HASH constant - a manifest/code drift the existing ABI-hash guard cannot catch. Ported from #164 before closing it as superseded.
…ts (#343) * test(#60,#61): assert topic-0 values and add EthFlow error-path tests Fixes #60: both twap-monitor and ethflow-watcher now assert at test time that the hardcoded topic-0 in module.toml equals keccak256 of the canonical event ABI string via alloy_sol_types::SolEvent::SIGNATURE_HASH. Fixes #61: adds two missing coverage paths in ethflow-watcher — - 429 rate-limit: verify Warn is emitted and no observed: marker is written (distinguishes from the 404 indexer-lag path) - malformed JSON body with HTTP 200: verify the strategy writes the observed: marker because it treats Ok(_) as confirmation without parsing the response body * test: assert module.toml event_signature matches the code SIGNATURE_HASH Reads the shipped module.toml via include_str! and asserts its pinned event_signature equals the OrderPlacement / ConditionalOrderCreated SIGNATURE_HASH constant - a manifest/code drift the existing ABI-hash guard cannot catch. Ported from #164 before closing it as superseded. --------- Co-authored-by: Luiz Gustavo Abou Hatem de Liz <luizgustavoahsc@gmail.com>
Summary
manifest_topic0_matches_*test to bothethflow-watcherandtwap-monitorthat asserts the hardcodedevent_signatureinmodule.tomlequals theSIGNATURE_HASHconstant from the cowprotocol crateTest plan
cargo fmtandcargo clippycleanCloses #60
Closes #61