issue #1535: make error discriminants append-only and fixture-checked - #1674
Merged
Jagadeeshftw merged 1 commit intoAug 31, 2026
Merged
Conversation
…h tests
Error discriminants are part of the public ABI — a client decodes an
on-chain Error(Contract, #N) against this table, and renumbering a variant
silently breaks every integration that relied on that number.
Before:
- error.rs had explicit = N values for all 31 variants, but there was no
test enforcing those values. A developer could renumber a variant and the
test suite would not notice.
After:
- contracts/stream/src/test/error_discriminants.rs adds:
1. DISCRIMINANT_FIXTURE — a const table mapping every variant name to its
frozen u32 value. Adding a new variant requires appending a row here;
changing an existing number causes discriminant_fixture_matches_source
to fail, which is the intended CI gate.
2. discriminant_fixture_is_complete_and_contiguous — asserts the table
covers discriminants 1..=LAST_DISCRIMINANT with no gaps, catching
authoring errors in the fixture itself.
3. discriminant_fixture_matches_source — casts every Error variant to u32
at runtime and compares against the fixture. Any renumbering in error.rs
fails this test immediately.
4. Public error-path tests — every error variant reachable through a try_*
client call is driven to that error at least once. Variants that cannot
be produced via a public try_* path in the test host (TokenMissing,
MalformedStreamId, StreamIdExhausted, TokenTransferFailed, InvalidTopUp)
are confirmed by discriminant-cast assertions with explanatory comments.
Verification:
cargo test -p fluxora-stream error -- --nocapture
(prints the full 31-variant fixture table; 80/80 tests pass)
Full suite: 503 tests, 0 failed.
Closes Fluxora-Org#1535
|
@ValJnr-dev1 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
1 task
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
Closes #1535
Error discriminants are part of the public ABI: a client decodes an on-chain
Error(Contract, #N)against a fixed table, and silently renumbering a variant breaks every integration that relied on that number without any compile-time warning.Before
error.rshad explicit= Nvalues for all 31 variants, but nothing in the test suite checked those values. A developer could renumber a variant and the CI suite would pass while every downstream client broke.After
Two files changed:
contracts/stream/src/test/error_discriminants.rs(new)DISCRIMINANT_FIXTURE-- aconsttable mapping every variant name to its frozenu32value (all 31 variants, 1-31). This is the canonical append registry.LAST_DISCRIMINANT = 31-- marks the append boundary. New variants must useLAST_DISCRIMINANT + 1and add a row to the fixture.discriminant_fixture_is_complete_and_contiguous-- asserts the fixture covers1..=LAST_DISCRIMINANTwith no gaps or misordering, catching authoring errors in the fixture itself.discriminant_fixture_matches_source-- casts everyError::Variant as u32at runtime and compares against the fixture. Any= Nchange inerror.rsfails this test immediately with a clear message: RENUMBERING DETECTED -- revert the change in error.rs. Only append new variants; never renumber existing ones. Prints the full discriminant table with--nocaptureas required by the issue.try_*client call is driven to that exact error at least once (covers Implement contract storage (Config, stream map, next_stream_id) #1-feat: set stream status to Completed when fully withdrawn #23, Feat/get stream state and tests #27-feat: emit StreamCreated event on create_stream #28, feat: Stream Event Definitions #30). Variants not reachable via publictry_*paths in the test host (TokenMissingImplemented recipient-only authorization for the withdraw function #26,MalformedStreamIdfeat: Defined a Withdrawal event (stream_id, recipient, amount) and emit it on each successful withdraw. #29,StreamIdExhaustedfeat: implement resume_stream with auth and Active status transition closes #10 #24,TokenTransferFailedfeat: implemented withdraw #25,InvalidTopUpfix: add overflow and safety checks to calculate_accrued #31) are confirmed by discriminant-cast assertions with inline explanations.contracts/stream/src/test/mod.rsRegistered
mod error_discriminantsunder the ABI inventory block.Verification
Issue verification command:
Output (abridged):
Full suite:
Acceptance criteria
discriminant_fixture_matches_sourcefails on any= Nchangetry_*path testScope
No behaviour changes, no refactors, no dependency upgrades. Purely additive test infrastructure as required by the issue.