39dc5032

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

Mutation: keep source text out of the MutationId so swap mutants activate

A MutationId renders and parses as '/'-separated parts (Test.Syd.Mutation.Runtime),
and its parts must contain no '/'. But recordMutationAt embedded the replacement
string (raw source text) as a part. A SwitchFunctionArguments swap of e.g.
'stripPrefix "/nix/store/" t' has replacement text 't "/nix/store/"', which
contains '/'. The compiled ifMutation carried that id intact, but the driver
renders the id into MUTATION_ACTIVE and the runtime parses it back by splitting
on '/': the '/' inside the replacement split into extra parts, so the parsed id
never equalled the compiled one and the mutation was never activated. The mutant
survived even though a test killed it, while same-site operators with a
'/'-free replacement (ConstNothing -> 'Nothing') were killed normally. The
coverage phase still recorded the (intact) id, so it showed up as 'survived',
not 'uncovered'.

Drop the replacement string from the id. The id is now the structural key
[module, operator, line, colStart, colEnd, altIndex]; none of those can contain
'/', and the index already disambiguates alternatives at one span (the
replacement text remains in the manifest's mutRecReplacement field for humans).
Update the two positional consumers of the id's arity (the instrumentation
debug line and Manifest.Render's '#n' variant suffix), regenerate the example
manifest goldens, and add Example.SwitchArgsLib.stripStorePrefix as a regression
test (a swap whose replacement contains '/').

Bump sydtest-mutation-plugin to 0.4.1.0 with a changelog entry.

Suite timing

Time to Start Worker time Duration Time to finish Idle
Config 0s 2s 2s 2s 0s
Eval 2s 45s 45s 47s 0s
Build 5s 21m53s 9m04s 9m10s 0s
Suite 0s 22m41s 9m10s 9m10s 0s

Timeline

0s1m2m3m4m5m6m7m8m9m