af4083ea

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).

Bump sydtest to 0.27.2.0 for the new functions exposed from
Test.Syd.Mutation.Forest, and release sydtest-mutation, sydtest-mutation-runtime,
and sydtest-mutation-driver as 0.1.0.0 (first released versions, with CHANGELOGs).

Suite timing

Time to Start Worker time Duration Time to finish Idle
Config 30s 2s 2s 32s 30s
Eval 34s 17s 17s 52s 2s
Build 41m45s 1m16s 56s 42m41s 40m53s
Suite 30s 1m36s 42m11s 42m41s 41m25s

Timeline

0s40s50s41m50s42m42m10s42m20s42m30s42m40s