Add tests to kill cargo-mutants survivors (72% → 100%)#35
Merged
Conversation
Implements the recommendations from notes/cargo-mutants-analysis.md: Dead code: - Removed Algorithm::signature_len() — never called anywhere New tests in keys.rs (12): - validate_public_key_size: wrong-length Ed25519 and ML-DSA-44 public keys - extract_verifying_key: Groth16 algorithms rejected (|| branches) - deserialize_verifying_key: Groth16 algorithms rejected as symmetric - Oversized secret_key (> MAX_SECRET_KEY_BYTES) and public_key (> MAX_PUBLIC_KEY_BYTES) - Exact-boundary acceptance tests (at MAX_SECRET_KEY_BYTES / MAX_PUBLIC_KEY_BYTES) - Groth16 signing key serialization roundtrip + short-key rejection New tests in poseidon.rs (2): - bytes_to_fr known-value test (little-endian 1 == Fr(1)) - poseidon_config parameter pinning (8/57/5/2/1) New tests in proto3.rs (5): - 10-byte varint overflow (final byte > 1 must reject) - Valid zero varint at nonzero offset (pos - start correctness) - Non-minimal varint at nonzero offset - to_u8 / read_u32 boundary rejection New tests in serialize.rs (16): - Oversized payload / signed token / signature / proof rejection - Exact-boundary acceptance (MAX_SIGNATURE_BYTES, MAX_PROOF_BYTES, 255-byte subject/audience/scope) - MAX_SIGNED_TOKEN_BYTES arithmetic pinned to 6944 - Proof field roundtrip (serialize.rs:324-334 match arm) - FullKeyHash payload roundtrip + wrong-length rejection - Duplicate non-scope field rejection (canonical-order check) New tests in sign.rs (13): - generate_hmac_key length (32 bytes) + entropy (two keys differ) - compute_full_key_hash / compute_sha256_full_key_hash deterministic + diff-inputs - compute_sha256_full_key_hash known value (SHA-256 of zero bytes) - Claims::validate boundary via sign_hmac: overlong subject/audience/scope, too many scopes, exact-255-byte acceptance, not_before == expires_at - mldsa44_key_hash wrong-length rejection New tests in types.rs (10): - Algorithm / KeyIdType from_byte exhaustive (all arms incl. Groth16) - Algorithm / KeyIdType to_byte roundtrip - KeyIdentifier::key_id_type all variants - is_zero: JSON serialization skips zero not_before/issued_at; includes nonzero - Claims::validate duplicate-scope rejection New tests in verify.rs (3): - verify_key_match: specifically asserts KeyHashMismatch (not shadowed by sig check) - Ed25519 key hash mismatch returns KeyHashMismatch specifically Test names avoid 'snark'/'groth16' so they run under --skip filters. Fast test suite: 95 → 156 unit tests (+64% increase).
Tightens 3 tests whose assertions were too loose to catch subtle mutants:
1. keys.rs:203/204 (|| → &&):
test_rejects_zk_symmetric_verifying_key was asserting m.contains("symmetric"),
but the fallback validate_public_key_size path ALSO returns a "symmetric"
error. Now asserts the specific "cannot be a verifying key" message.
2. serialize.rs:70, serialize.rs:276 (> → == / >=):
Oversized-input tests were only checking is_err(), but a zero-filled buffer
that slips past a mutated size check still fails at parse time. Now asserts
the specific "too large" error AND adds boundary tests proving exactly-MAX
inputs pass the size check.
Config:
- .cargo/mutants.toml: exclude sign_groth16/verify_groth16 function body
replacements (12 mutants). These need ~2min SNARK trusted setup per test,
covered only by `make test-snark`. All their internal helpers are
fast-tested individually.
Docs:
- notes/cargo-mutants-analysis.md: add post-fix summary (72.2% → 100%)
- CLAUDE.md: update test count (142 → 205)
Final mutation score: 100% of fast-testable mutants (264 caught / 264 viable).
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 all recommendations from
notes/cargo-mutants-analysis.md(PR #34). Adds 63 new unit tests and removes one dead function, raising the mutation score from 72.2% to 100% of fast-testable mutants.Results
Verified with
cargo mutants -j 2in 8 minutes.Changes by file
Deleted
Algorithm::signature_len()— dead code, never called anywheretypes.rs (+10 tests)
Algorithm::from_byte/to_byteexhaustive roundtrip (all 5 variants incl. Groth16)KeyIdType::from_byte/to_byteexhaustive roundtripKeyIdentifier::key_id_type()all variantsis_zero(): JSON serialization omits zeronot_before/issued_at; includes nonzeroClaims::validateduplicate-scope rejectionproto3.rs (+5 tests)
pos - startarithmetic)to_u8/read_u32boundary rejectionserialize.rs (+18 tests)
>→==mutants don't slip through to downstream parse errors)MAX_PAYLOAD_BYTES,MAX_SIGNATURE_BYTES,MAX_PROOF_BYTES, 255-byte subject/audience/scopeMAX_SIGNED_TOKEN_BYTESpinned to 6944 (catches arithmetic mutations)keys.rs (+12 tests)
validate_public_key_size: wrong-length Ed25519 (31 B) and ML-DSA-44 (1000 B) keysVerifyingKeyandextract_verifying_keywith specific message pinningsecret_key/public_keyDoS limits + boundary acceptancesign.rs (+13 tests)
generate_hmac_key(): length is 32, two keys differ, not all-zeroscompute_full_key_hash/compute_sha256_full_key_hash: deterministic, different inputs → different outputs, known SHA-256 value for zero bytesClaims::validateboundary viasign_hmac: overlong subject/audience/scope, too many scopes, exact-limit acceptance,not_before == expires_atmldsa44_key_hashwrong-length rejectionverify.rs (+3 tests)
verify_key_matchspecifically returnsKeyHashMismatch(was shadowed by signature check in all existing tests)KeyHashMismatchposeidon.rs (+2 tests)
bytes_to_frknown values (little-endian 1 ==Fr(1), zero ==Fr(0))poseidon_configparameters pinned (8/57/5/2/1).cargo/mutants.toml
sign_groth16/verify_groth16function body replacements (12 mutants). These need ~2min SNARK trusted setup per test, covered bymake test-snark. All their constituent helpers have fast unit tests.Key test patterns
matches!(err, MalformedEncoding(m) if m.contains("specific message"))— ensures error-shadowing mutants (which reach a different error path) are caught.>→>=→==mutation cycles.zk_symmetricinstead ofsnark/groth16so they run under the--skip snark --skip groth16filters used during mutation testing.