ed4d38fc

By: Tom Sydney Kerckhove <syd@cs-syd.eu>

Mutation: order covering tests cheapest-first in the mutation child

When a mutation child runs the tests that cover a mutation, it runs them
synchronously under fail-fast, so the first covering test that fails kills the
mutant.  Ordering the covering tests cheapest-first, using the per-test baseline
the coverage phase already measures (and previously discarded into a single
timeout), reaches a killing test sooner and cuts the mutation phase's wall-clock,
since killed mutants are the overwhelming majority of a run.  On two sample
projects the mutation phase ran ~6% and ~24% faster, with identical verdicts.

- reorderTestForestByTiming: a pure, tree-aware, stable reorder.  It sorts
  siblings by ascending baseline (missing = first) and orders each subtree by the
  minimum cost of any leaf it contains, so a shared-setup group reorders as a
  unit and setup is never split.  It mirrors randomiseTestForest: inside a
  DoNotRandomiseExecutionOrder scope it leaves the subtree untouched at every
  depth.  So it is a drop-in alternative to execution-order randomisation, legal
  under exactly the same conditions.  Only sibling order changes, so which tests
  run (and every verdict) is unaffected.
- reorderForMutationChild: the pure gate the child uses -- reorder only when the
  suite randomises execution order and a baseline is available.  Keeping it out
  of the child's IO makes the gate unit-testable.
- The coverage phase persists the merged per-test baselines as baseline.json next
  to the manifest; the run and diff paths union them into the augmented dir the
  children read.
- The child reads that baseline and reorders the filtered forest after filtering,
  so the coverage-order TestIds the filter needs are untouched.

Tests: ReorderSpec covers ascending order, stable ties + missing-as-first, that a
sequential (parallelism) subtree is reordered but a doNotRandomiseExecutionOrder
one is not (incl. no descent into a nested randomise block), that a beforeAll_
group reorders as a unit without splitting setup, that the test-id set is
unchanged, and the gate (on/off/no-baseline).

Suite timing

Time to Start Worker time Duration Time to finish Idle
Config 4s 1s 1s 6s 4s
Eval 6s 16s 16s 23s 0s
Build 48m18s 1m28s 1m34s 49m53s 48m01s
Suite 4s 1m47s 49m48s 49m53s 48m05s

Timeline

0s10s20s48m20s48m30s48m40s48m50s49m49m10s49m20s49m30s49m40s49m50s