Skip to content

AMT coverage: g4-dotrainsourcev1-hash-fet - #183

Open
thedavidmeister wants to merge 6 commits into
mainfrom
2026-08-22-amt-g4-dotrainsourcev1-hash-fet
Open

AMT coverage: g4-dotrainsourcev1-hash-fet#183
thedavidmeister wants to merge 6 commits into
mainfrom
2026-08-22-amt-g4-dotrainsourcev1-hash-fet

Conversation

@thedavidmeister

Copy link
Copy Markdown
Contributor

Adversarial mutation-test coverage for group g4-dotrainsourcev1-hash-fet (30 behaviours across 6 units), at scanned commit bba50a7.

Method: every behaviour was first probed as one or more exact-string mutants against the PRE-EXISTING suite (attribution pass, no new tests present); survivors then got new tests, or existing tests strengthened in place; everything re-probed until killed — or, for three mutants, shown to be behaviourally equivalent consequences of a filed defect (#173). Adversarial findings were filed as issues labelled audit + adversarial and are linked below; tests pin only behaviour derived from the intent oracles, never buggy output.

Behaviour matrix

Verdict legend: PRE = killed by a pre-existing test (attribution pass), NEW = killed by a test added here, STR = killed by a pre-existing test strengthened in place here, SURVIVES = equivalent mutant, unkillable until the linked issue is resolved.

DotrainSourceV1 (crates/cli/src/meta/types/dotrain/source_v1.rs)

behaviour mutation verdict killing test
hash = keccak256(utf8 bytes) S01 keccak over uppercased bytes NEW test_hash_known_keccak256_vectors (independent Keccak-256 reference vectors)
fetch_by_subject: 0x-prefixed hex subject on the wire S02 drop 0x prefix PRE test_fetch_by_subject_sends_0x_prefixed_hex
empty metabytes -> Ok(None) guard S03 guard inverted PRE test_fetch_by_subject_found (+_invalid_cbor, _wrong_magic)
cbor decode of first meta; try_from first item S04 take last decoded item NEW test_fetch_by_subject_takes_first_decoded_item
ClientError::Empty -> Ok(None) S05 Empty arm errors PRE test_fetch_by_subject_not_found
other client errors -> Err wrap S06 swallow to Ok(None) NEW test_fetch_by_subject_propagates_non_empty_client_errors
From -> item: DotrainSourceV1 magic S07 wrong magic PRE test_into_document (+roundtrips)
From -> item: OctetStream + None fields S08 wrong content_type PRE test_into_document
TryFrom item: magic gate S09 gate inverted PRE test_try_from_document_invalid_magic (+_success, roundtrips)
TryFrom item: InvalidMetaMagic(expected, actual) order S10 args swapped PRE test_try_from_document_invalid_magic (+test_fetch_by_subject_wrong_magic)
TryFrom item: utf8 error S11 lossy conversion swallows PRE test_try_from_document_invalid_utf8

OrderBuilderStateV1 (crates/cli/src/meta/types/dotrain/order_builder_state_v1.rs)

behaviour mutation verdict killing test
get_token_addresses maps all tokens O01 skip first token PRE test_get_token_addresses
get_vault_ids keeps non-None only O02 return empty PRE test_get_vault_ids
extract_from_meta recurses into RainMetaDocumentV1-magic items O03 recursion arm deleted NEW test_extract_from_meta_nested_rain_document
OrderBuilderStateV1-magic item -> try_from and return O04 magic match inverted PRE test_extract_from_meta_found (+_not_found, _multiple_documents, _corrupted_instance_data)
found instance is returned O05 return Ok(None) instead PRE test_extract_from_meta_found (+_multiple_documents)
none found -> Ok(None) O06 error instead PRE test_extract_from_meta_not_found
TryFrom struct -> item: OrderBuilderStateV1 magic O07 wrong magic PRE test_into_document (+roundtrips)
TryFrom struct -> item: cbor of whole struct O08 cbor of one field PRE test_into_document (+roundtrips)
TryFrom item -> struct: magic gate O09 gate inverted PRE test_try_from_document_invalid_magic (+_success)
TryFrom item -> struct: InvalidMetaMagic arg order O10 args swapped PRE test_try_from_document_invalid_magic
TryFrom item -> struct: cbor payload parse O11 truncated parse PRE test_try_from_document_success (+roundtrips)

RaindexSignedContextOracleV1 (crates/cli/src/meta/types/raindex_signed_context_oracle/mod.rs)

behaviour mutation verdict killing test
parse validates URL R01 skip validation PRE test_parse_invalid_url (+test_parse_empty_url)
parse error variant InvalidUrl R02 UnsupportedMeta instead STR test_parse_invalid_url (variant now matched)
url() accessor R03 empty str PRE test_new_with_url (+test_parse_valid_url, roundtrip)
parsed_url() parses stored string R04 parse mangled string PRE test_parsed_url
to_meta_item: oracle magic R05 wrong magic PRE test_roundtrip (+test_find_in_items)
to_meta_item: raw utf8 payload R06 mangled payload PRE test_roundtrip (+test_find_in_items)
to_meta_item: content_type None R07 OctetStream instead NEW test_to_meta_item_fields
to_meta_item: content_encoding None R08 Deflate instead PRE test_roundtrip (+test_find_in_items)
cbor_encode: RainMetaDocumentV1 prefix R09 wrong prefix magic PRE test_roundtrip
cbor_encode: single-item seq R10 two items PRE test_roundtrip
find_in_items: find by magic R11 predicate negated PRE test_find_in_items (+_decode_error)
find_in_items: Some -> try_from, error propagates R12 error swallowed PRE test_find_in_items_decode_error
find_in_items: None -> Ok(None) R13 error instead PRE test_find_in_items_missing
TryFrom: magic gate R14 gate inverted PRE test_wrong_magic_fails (+roundtrip, test_find_in_items)
TryFrom: gate error UnsupportedMeta R15 CorruptMeta instead STR test_wrong_magic_fails (variant now matched)
TryFrom: utf8 step errors with FromUtf8Error R16 lossy swallows STR test_find_in_items_decode_error (variant now matched)
TryFrom: unpack (content_encoding honoured) R17 raw payload read NEW test_try_from_unpacks_content_encoding
TryFrom: url parse step R18 skip parse NEW test_try_from_rejects_non_url_payload

Common validation newtypes (crates/cli/src/meta/types/common/v1.rs)

behaviour mutation verdict killing test
REGEX_RAIN_SYMBOL ^[a-z][0-9a-z-]*$ C01 anchor dropped PRE test_rain_symbol_validate
REGEX_SOLIDITY_IDENTIFIER ^[a-zA-Z$_][a-zA-Z0-9$_]*$ C02 leading digit allowed PRE test_solidity_identifier_validate
REGEX_RAIN_STRING ^[\s!-~]*$ C03 whitespace dropped PRE test_rain_string_validate (+authoring roundtrips)
REGEX_RAIN_TITLE no leading space C04 leading space allowed PRE test_rain_title_validate
REGEX_RAIN_TITLE no trailing space C05 trailing space allowed PRE test_rain_title_validate
HASH_PATTERN ^0x[a-fA-F0-9]{64}$ C06 63 hex chars allowed PRE test_hash_pattern
RainSymbol validate() wired to its regex C07 wrong regex path PRE test_rain_symbol_validate
RainTitle validate() wired to its regex C08 wrong regex path PRE test_rain_title_validate
RainString validate() wired to its regex C09 wrong regex path PRE test_rain_string_validate
SolidityIdentifier validate() wired to its regex C10 wrong regex path PRE test_solidity_identifier_validate

OpMeta v1 (crates/cli/src/meta/types/op/v1.rs)

behaviour mutation verdict killing test
BitInteger range 0..=15 (MAX from size_of::()*8-1) P01 MAX off-by-one; P20 range attr loses max NEW test_bit_integer_bounds
BitIntegerRange min<=max order check P02 order inverted NEW test_bit_integer_range_order
BitIntegerRange per-end validation merged P03 per-end vec dropped SURVIVES (equivalent under confirmed bug) none possible today: merge_all drops the per-end results regardless — see the merge_all issue; NOTE comment left in tests
OperandArgRange: Exact ok P05 Exact arm rejects NEW test_operand_arg_range_exact_is_valid
OperandArgRange: Range min<=max P04 becomes strict < NEW test_operand_arg_range_min_max (equal bounds pinned valid)
OperandArgRange: per-operand validation merge P06 per-operand vec dropped SURVIVES (equivalent) Operand derives Validate with no constraints, and merge_all drops children anyway — doubly unobservable; see the merge_all issue
Output validate: Exact vs Computed sub-validations P07 Computed sub-validation dropped SURVIVES (equivalent under confirmed bug) Output::validate is unconditionally Ok today (merge_all misuse) — rejection cannot be pinned without encoding the bug; positive cases pinned by test_output_validation_accepts_well_formed
OpMeta serde defaults on desc/operand/inputs/outputs/aliases P09/P10/P11/P12/P13 drop each default NEW test_opmeta_minimal_json_defaults
OpMeta nested #[validate] (name, aliases) P08 name validate dropped; P14 aliases validate dropped NEW test_opmeta_try_from_validates; test_opmeta_aliases_validated
Input.bits optional validation P17 bits validate dropped NEW test_opmeta_input_bits_validated (order-violation arm; end-bounds arm blocked by the merge_all bug)
Input.computation optional validation P18 computation validate dropped NEW test_opmeta_input_computation_validated
InputParameter.spread default false P19 serde default dropped NEW test_input_parameter_spread_defaults_false
TryFrom Vec: json parse + validate P15 validate skipped NEW test_opmeta_try_from_validates
TryFrom meta item via unpack P16 raw payload read NEW test_opmeta_try_from_item_unpacks_content_encoding

InterpreterCallerMeta v1 (crates/cli/src/meta/types/interpreter_caller/v1.rs)

behaviour mutation verdict killing test
deny_unknown_fields on InterpreterCallerMeta I01 dropped NEW test_deny_unknown_fields_top_level
deny_unknown_fields on Method I02 dropped NEW test_deny_unknown_fields_method
deny_unknown_fields on MethodInput I03 dropped NEW test_deny_unknown_fields_method_input
deny_unknown_fields on Expression I04 dropped NEW test_deny_unknown_fields_expression
deny_unknown_fields on ContextColumn I05 dropped NEW test_deny_unknown_fields_context_column
deny_unknown_fields on ContextCell I06 dropped NEW test_deny_unknown_fields_context_cell
methods length(min=1) I07 relaxed to 0 NEW test_methods_min_length_one
Method.inputs length(min=1) I08 relaxed to 0 NEW test_method_inputs_min_length_one
Expression.context_columns length(max=255) I09 max dropped NEW test_context_columns_max_255 (255 ok / 256 rejected)

QA

  • Discriminating tests: 27 tests added/strengthened across the five touched files (named per row in the matrix above) - each fails on base, verified by mutation-probe pass 2: 36/39 base-equivalent mutants KILLED with these tests as the named killers (the probe demands red-under-mutation, green-on-baseline)
  • Mutations applied: 79 exact-string mutants over the six units; per-mutant line -> mutation -> killing test recorded in the behaviour matrix above (S/O/R/C/P/I ids)
  • Oracle: NatSpec/doc comments, the KnownMagic envelope contract, validator/serde attribute intent, and references independent of the implementation - Keccak-256 reference vectors cross-checked with cast keccak, regex semantics cross-checked against the regex crate directly; no expected value mirrors the code under test
  • Category check: group g4-dotrainsourcev1-hash-fet owns exactly the 30 listed behaviours across DotrainSourceV1, OrderBuilderStateV1, RaindexSignedContextOracleV1, common v1 newtypes, OpMeta v1, InterpreterCallerMeta v1; all 30 probed (three sub-behaviours unpinnable pending BitIntegerRange/OperandArgRange/Output validation drops all sub-validation errors (ValidationErrors::merge_all misuse) #173, recorded above); no behaviour outside the slice touched

Probe tool: nix run github:rainlanguage/adversarial-mutation-test#mutation-probe over a 79-mutant exact-string mutants file (kept outside the repo, never committed); suite command nix develop -c cargo test -p rain-metadata; pass/fail proof read from cargo's own tally; killers attributed from cargo's FAILED lines.

Issues filed from the adversarial pass (all carrying audit + adversarial): #155, #158, #159, #162, #165, #167, #171, #173.

Deliberately not pinned by tests:

🤖 Generated with Claude Code

baku-ccron and others added 6 commits August 22, 2026 18:22
… propagation

AMT survivors S01/S04/S06: hash() pinned to independent Keccak-256
reference vectors; fetch_by_subject pinned to take the first decoded
item of the first meta; non-Empty subgraph client errors pinned to
surface as Err(MetaboardSubgraphClientError), never Ok(None).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AMT survivor O03: extract_from_meta must recurse into a decoded item
whose magic is RainMetaDocumentV1 and whose payload is itself a
complete prefixed document.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AMT survivors R02/R07/R15/R16/R17/R18: to_meta_item envelope pinned
field by field; TryFrom pinned to unpack() (deflate honoured) and to
reject non-URL payloads with InvalidUrl; parse/gate/utf8 error
variants pinned in place in the existing tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AMT survivors P01-P20 (previously zero-covered unit): BitInteger
0..=15 bounds, BitIntegerRange order check, OperandArgRange
Exact/Range semantics, OpMeta serde defaults and nested validation,
Input bits/computation validation, InputParameter.spread default,
TryFrom validate gate and content-encoding unpack.

Deliberately NOT pinned: BitIntegerRange per-end bounds and
Output::Computed sub-validation rejections - both are currently
dropped by a merge_all misuse (child errors are not Struct-kind under
the merge field), so pinning either outcome would encode the bug; NOTE
comments in the tests point at the audit issue.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AMT survivors I01-I09 (previously zero-covered unit):
deny_unknown_fields pinned at all six struct levels; methods min 1,
Method.inputs min 1, Expression.context_columns max 255.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@thedavidmeister, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 33 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9e645378-7b24-4198-a7ef-d0232c36bd94

📥 Commits

Reviewing files that changed from the base of the PR and between bba50a7 and 8910e14.

📒 Files selected for processing (5)
  • crates/cli/src/meta/types/dotrain/order_builder_state_v1.rs
  • crates/cli/src/meta/types/dotrain/source_v1.rs
  • crates/cli/src/meta/types/interpreter_caller/v1.rs
  • crates/cli/src/meta/types/op/v1.rs
  • crates/cli/src/meta/types/raindex_signed_context_oracle/mod.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant