Skip to content

Make the nightly mutation gates pass again - #31

Merged
zonuexe merged 4 commits into
masterfrom
fix/mutation-gates
Nov 3, 2026
Merged

zonuexe merged 4 commits into
masterfrom
fix/mutation-gates

Conversation

@zonuexe

@zonuexe zonuexe commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

The nightly rust-mutation and frontend-mutation jobs have been red on master for weeks. With this PR, both pass locally.

Rust (npm run mutants:rust)

The run at the last nightly (41334596805) had 64 MISSED mutants plus 11 timeouts and exited 3. cargo-mutants gives any timeout its own non-zero exit code, so timeouts were failing the gate as well, which contradicts the note in AGENTS.md. After the riida-core split, 3 more misses appeared in config::collapse_home_path: its callers stayed in the app crate, and cargo-mutants runs only the mutated package's tests.

  • Killing tests for every pure helper that had misses: epub_image (OPF layout parsing, viewBox/viewport sizes, single_image_href, jpeg_dimensions, percent_decode, content_type_for, spread_side_str), fulltext_extract::html_to_text, BookIndexInput::is_pdf/is_epub, config::collapse_home_path, and the tantivy tokenizer's token_mut.
  • Index write path: finish_write's merge wait and consolidate are now tested deterministically. The tests seed segments with NoMergePolicy, then check that the code under test merges them.
  • docstore_compression: cargo-mutants 27 does not apply exclude_re to struct-field deletion mutants at all. Even --exclude-re docstore_compression leaves it in --list. A tempdir test now asserts the zstd doc store. Because it is tested, the old open_or_create exclusion is dropped. The quirk is documented in mutants.toml.
  • jpeg_dimensions had equivalent mutants: | vs ^ on disjoint bits, and a redundant len < 4 guard. They are rewritten with starts_with and u16::from_be_bytes, so those mutants are no longer generated.
  • Exclusions: pdfium_dir is excluded because it reads a global OnceLock. Three name-specific patterns exclude mutants that can only hang: deleting an XML read loop's Eof arm, a byte cursor that stops advancing, and TokenStream::advance -> true. The patterns name the mutation, not the function, so every other mutant in those functions stays in scope. AGENTS.md is corrected to match.

Local result, with the Nix dev shell on top of 97958eb:
npm run mutants:rust -- -j 4 → 624 mutants tested in 21m: 550 caught, 74 unviable, exit 0.

Frontend (npm run mutants:frontend)

  1. Crash (fixed). The job died with ts.parseConfigFileTextToJson is not a function. Stryker 10.1.1 (the latest) uses the TypeScript JS API in its tsconfig preprocessor, and TypeScript 7 (126a9c9) no longer ships that API. That preprocessor only rewrites extends/references paths that point outside the sandbox. Our tsconfig has neither, so tsconfigFile now points at a file that does not exist, which skips the preprocessor.
  2. Fixture mutated (fixed). src/pdf-page-fixtures.ts holds test-only helpers but was being mutated. It is now excluded from mutate.
  3. mutants:frontend:list (fixed). It used --dryRun, which Stryker 10 renamed to --dryRunOnly.
  4. Pixel-analysis modules excluded. Stryker's instrumentation of the per-pixel loops in pdf-deskew.ts, pdf-trim.ts, pdf-gray-image.ts and pdf-page-sample.ts made their tests about 300× slower.
    • Dry run without them: 534 tests in 3 s.
    • Dry run with them: 596 tests in 2 min 26 s. That only completed with a raised testTimeout; otherwise resolvePdfTrimBoxes timed out even at 60 s.
    • Those modules held 758 of the 6,362 mutants, enough to push a full run past the job's 60-minute limit.
    • The job was green until 2026-09-03 and first failed on 09-09, the day both TS 7 and these modules landed. The TS 7 crash was hiding this second problem.
    • They are now excluded from mutate, as documented in AGENTS.md. They stay covered by unit tests and the v8 coverage thresholds.

Verification

  • cargo nextest run --workspace (all pass), rust:fmt:check, rust:lint, fmt:check
  • npm run mutants:rust exits 0 (above)
  • npm run mutants:frontend → final mutation score 53.70 (threshold break: 50), done in 1 min 52 s

@zonuexe
zonuexe merged commit eff5b88 into master Nov 3, 2026
6 checks passed
@zonuexe
zonuexe deleted the fix/mutation-gates branch November 3, 2026 03:41
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