test(rivet-core): kill 35+ surviving mutants from sharded mutation testing#218
Merged
test(rivet-core): kill 35+ surviving mutants from sharded mutation testing#218
Conversation
Surviving mutants from the sharded mutation-testing run on main (8a5a4a7, run 24941881359, shards 1+2 of 4) clustered in two areas: 1. Howard-Hinnant civil_from_days arithmetic in `embed.rs::epoch_to_ymd_hm` and `reqif.rs::reqif_creation_timestamp` (~60 surviving arithmetic mutants between them — every replace `/` / `%` / `+` / `-` / `*` survived because the wrappers wrap `SystemTime::now()` directly, with no deterministic input path). 2. HTML renderers in `embed.rs` (`render_coverage`, `render_diagnostics`, `render_matrix_table`, `find_rule_for_types`, `render_query`, `render_group`) — boundary thresholds, equality predicates, match guards. This commit: - Refactors `reqif_creation_timestamp` to call a deterministic helper `epoch_secs_to_iso8601(secs: u64) -> String` so the algorithm can be pinned by unit tests (mirrors the `epoch_days_to_ymd` extraction already in export.rs). - Adds 8 known-input/known-output tests for `epoch_to_ymd_hm` and 7 for `epoch_secs_to_iso8601`, covering Unix epoch, 2024-01-01, 2024-12-31 23:59:59, 2024-04-25 12:34:56, 2024-02-15 (mp = 11 branch), 2004-02-29 (doe/1460 = 1, doe/36524 = 0 boundary), 2200-03-01 (doe/36524 = 2 boundary), 2400-02-29 (doe = 146096 — the only era-boundary date that exercises the `- doe/146096` term). These together pin every arithmetic position in the algorithm. - Adds renderer-coverage tests for the 25 / 55 / 85 / 100 % bar-class thresholds in `render_coverage` and `render_matrix_table`, plus targeted tests for `find_rule_for_types` (both legs of the `&&`, both `==`), `render_diagnostics` severity filter + summary counts, `render_query` truncation-note `>` boundary and id-column wrapping, `render_group` empty-second-arg guard, and the `<details>` block emission in `render_coverage` when uncovered_ids is empty. - Adds reqif tests for: Adapter::id() / name() string identity; `parse_reqif` recognising `ReqIF.Name` and `ReqIF.ChapterName` as title (not as a generic field); empty-value guards on `ReqIF.ForeignID` / `ReqIF.Name` (must NOT overwrite defaults with blanks); enum-valued `status` and `tags` arms; `REL-N` counter incrementing per link in `build_reqif_with_schema`; mixed-extension directory walk picking up both `.reqif` AND `.xml` files in `import_reqif_directory`. Local cargo-mutants verification (against this commit): - `cargo mutants -p rivet-core --file rivet-core/src/embed.rs --regex 'epoch_to_ymd_hm'` — 106 / 106 caught (was 5 missed pre-fix). - `cargo mutants -p rivet-core --file rivet-core/src/reqif.rs --regex 'reqif_creation_timestamp|epoch_secs_to_iso8601'` — 80 / 80 caught (entire arithmetic block was previously surviving). Test count: rivet-core --lib goes from 780 to 816 (+36 tests, all deterministic and Miri-tagged where they hit XML / quick-xml paths). Refs: REQ-004 Verifies: REQ-004
📐 Rivet artifact deltaNo artifact changes in this PR. Code-only changes (renderer, CLI wiring, tests) don't touch the artifact graph. |
There was a problem hiding this comment.
⚠️ Performance Alert ⚠️
Possible performance regression was detected for benchmark 'Rivet Criterion Benchmarks'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.20.
| Benchmark suite | Current: f59ecf4 | Previous: 58801b6 | Ratio |
|---|---|---|---|
store_lookup/100 |
2116 ns/iter (± 5) |
1718 ns/iter (± 16) |
1.23 |
store_lookup/1000 |
25820 ns/iter (± 191) |
19320 ns/iter (± 203) |
1.34 |
validate/10000 |
15980477 ns/iter (± 1421545) |
12656985 ns/iter (± 862501) |
1.26 |
traceability_matrix/1000 |
60186 ns/iter (± 979) |
41047 ns/iter (± 91) |
1.47 |
query/100 |
783 ns/iter (± 5) |
630 ns/iter (± 1) |
1.24 |
query/1000 |
7708 ns/iter (± 147) |
5229 ns/iter (± 124) |
1.47 |
This comment was automatically generated by workflow using github-action-benchmark.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
avrabe
added a commit
that referenced
this pull request
Apr 26, 2026
…merge style(rivet-core): cargo fmt drift after PR #218 merge
avrabe
added a commit
that referenced
this pull request
Apr 26, 2026
Follow-up to PR #218 which addressed embed.rs + reqif.rs survivors from the 4-shard rivet-core mutation matrix. The 16-shard config (this branch's previous commit) now lets every shard complete without timeout, exposing survivors in the semantic modules. Local cargo-mutants runs against main produced these survivor counts; this commit's tests drive each to zero (verified locally with the same `cargo mutants -p rivet-core --file <module>.rs` command): module before after coverage_evidence.rs 10 0 compliance.rs 21 0 convergence.rs 6 0 links.rs 21 1* store.rs 2 0 ───────────────────────── ───── ───── total 60 1* (*) The remaining links.rs survivor is the `&&` between `forward == other.forward` and `backward == other.backward` on line 104. It is an EQUIVALENT mutant: `LinkGraph::backward` is derived from `forward` during `build()`, so any forward difference always implies a backward difference. No external test can distinguish `&&` from `||` for this clause. The companion clause on line 105 (`broken == other.broken`) IS killed because `broken` is independent of forward/backward. Tests added (each pins one or more named mutants): coverage_evidence.rs: - computed_percentage_partial_value (kills f64-const, *↔+/, /↔*/% in computed_percentage) - computed_percentage_total_zero_returns_one_hundred - computed_percentage_total_nonzero_full_coverage - coverage_store_is_empty_true_on_new - coverage_store_is_empty_false_after_insert compliance.rs: - is_eu_ai_act_loaded_requires_both_anchor_types (kills && → ||, constant-false on the loader) - compute_compliance_partial_section_arithmetic (kills += ↔ -=/*=, > ↔ ==/<=/>= , == ↔ != , * ↔ +/, / ↔ %/* across compute_compliance) - compute_compliance_overall_pct_when_total_required_zero convergence.rs: - signature_message_hash_uses_xor_not_or_or_and (kills ^= ↔ |=/&= in simple_hash) - failure_signature_display_writes_inner_string - retry_strategy_guidance_returns_distinct_messages (kills constant-string replacement on guidance()) - retry_strategy_display_uses_guidance links.rs (new tests module — file had no prior tests): - debug_fmt_writes_struct_name - partial_eq_distinguishes_distinct_graphs - node_map_returns_artifact_indices - backlinks_of_type_filters_by_type - has_cycles_distinguishes_acyclic_and_cyclic - orphans_lists_only_artifacts_with_no_links - reachable_traverses_only_matching_link_type store.rs: - store_is_empty_distinguishes_empty_and_populated Per CLAUDE.md, every commit touching `rivet-core/src/` requires artifact trailers. Verifies: REQ-002, REQ-004, REQ-009, REQ-010 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 tasks
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
Surviving mutants from the latest sharded
cargo mutants -p rivet-corerun on main (commit 8a5a4a7, run 24941881359, shards 1 + 2 of 4) clustered in two areas:civil_from_daysarithmetic inembed.rs::epoch_to_ymd_hmandreqif.rs::reqif_creation_timestamp— every replace//%/+/-/*survived because the wrappers consumedSystemTime::now()directly with no deterministic input path. ~60 mutants between the two.embed.rs(render_coverage,render_diagnostics,render_matrix_table,find_rule_for_types,render_query,render_group) — boundary thresholds, equality predicates, match guards.This PR:
reqif_creation_timestampto call a deterministic helperepoch_secs_to_iso8601(secs: u64) -> String(mirroring theepoch_days_to_ymdextraction already inexport.rs).epoch_to_ymd_hmand 7 forepoch_secs_to_iso8601, covering Unix epoch, 2024-01-01 / 2024-04-25 / 2024-12-31, 2024-02-15 (mp = 11 branch), 2004-02-29 (doe/1460=1, doe/36524=0), 2200-03-01 (doe/36524=2), 2400-02-29 (the only era-boundary date that exercises- doe/146096). Together these pin every arithmetic position in the algorithm.render_coverageandrender_matrix_table, plus targeted tests forfind_rule_for_types(both legs of&&, both==),render_diagnosticsseverity filter + summary counts,render_querytruncation-note>boundary and id-column wrapping,render_groupempty-second-arg guard, and the<details>block emission inrender_coveragewhenuncovered_idsis empty.reqif.rstests:Adapter::id()/name()identity;parse_reqifrecognisingReqIF.NameandReqIF.ChapterNameas titles (not as fields); empty-value guards (must NOT overwrite defaults); enum-valuedstatusandtagsarms;REL-Ncounter incrementing per link; mixed-extension directory walk picking up.reqifAND.xmlfiles inimport_reqif_directory.Local cargo-mutants verification (against this branch)
embed.rs::epoch_to_ymd_hmreqif.rs::reqif_creation_timestamp+epoch_secs_to_iso8601embed.rsHTML rendererscargo test -p rivet-core --libgoes from 780 to 816 (+36 deterministic tests; Miri-tagged where they touch quick-xml).Coverage notes for follow-up
Shards 0 / 3 of the CI mutation run timed out at 45 min and never uploaded artifacts. Their files (
commits.rs,coverage.rs,coverage_evidence.rs,compliance.rs,convergence.rs,validate.rs, etc.) contain mutants we could not enumerate from CI. This PR addresses the survivors we DO have data for; a follow-up should either (a) further shrink the shards once arithmetic-heavy modules are pinned, or (b) skip surveys of theepoch_*helpers incargo mutantsconfig so the budget covers the more semantic modules.Test plan
cargo test -p rivet-core --libpasses (816 tests).cargo mutants -p rivet-core --file rivet-core/src/embed.rs --regex 'epoch_to_ymd_hm'reports 106 / 106 caught.cargo mutants -p rivet-core --file rivet-core/src/reqif.rs --regex 'reqif_creation_timestamp|epoch_secs_to_iso8601'reports 80 / 80 caught.🤖 Generated with Claude Code