From 659e3dd516040880cd0249fdfecbbfe777963bb6 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 25 Sep 2026 18:44:36 +0200 Subject: [PATCH] Record two Stryker findings from the surface nets mutation pass Three TryGetOtherEndpoint boundary-guard mutants (per-axis "if (x + 1 >= sizeX) return false;" forced to "if (true) return false;") were reported Survived despite being exercised by the X/Y/Z open-boundary tests. Hand- mutating all three and running dotnet test directly failed 11 of 24 SurfaceNetsTests, confirming a vstest-runner coverage-attribution false survivor (same class of caveat already recorded for CultMath's mtp runner, here under the default runner). Recorded under Known tool caveat. Separately, adding stryker-config.json in the same cut that first uses it defeats --since line scoping: Stryker fell back to mutating the whole GameCult.Geometry.csproj glob ("Non-CSharp files in test project were changed"), not just the new files, which is why the run's survivor list includes CultGeometryIsoSurface.cs, CultGeometryDocuments.cs, and CultGeometryPrimitives.cs. Recorded under Follow-ups so a later diff-only cut isn't surprised by the difference. Co-Authored-By: Claude Sonnet 5 --- docs/mutation-testing.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/mutation-testing.md b/docs/mutation-testing.md index 82e05fb9..189173a8 100644 --- a/docs/mutation-testing.md +++ b/docs/mutation-testing.md @@ -75,6 +75,18 @@ inside a `static readonly` field initializer as unproven until confirmed with a direct `dotnet test` run against the same mutation; do not triage it as a missing test without that check. +The default `vstest` runner has its own analog. GameCult.Geometry.Tests's +first `--since` pass reported three `Boolean mutation -> true` survivors in +`CultGeometrySurfaceNets.TryGetOtherEndpoint` (the per-axis `if (x + 1 >= +sizeX) return false;` guards, mutated to `if (true) return false;`), despite +X/Y/Z-axis open-boundary tests that exercise exactly those guards. Hand- +mutating all three and running `dotnet test tests/GameCult.Geometry.Tests +--filter FullyQualifiedName~SurfaceNetsTests` directly failed 11 of 24 tests, +confirming the mutants are well-covered and Stryker's coverage-based test +selection mis-attributed (or dropped) their covering tests. Treat a survivor +that looks like it must be covered as unproven until confirmed the same way, +regardless of which runner is in play. + ## Follow-ups CultMath.Tests and GameCult.Geometry.Tests are the only projects currently @@ -90,6 +102,16 @@ added surface nets; a full-project baseline (running mutation against all of `CultGeometryPrimitives`, not just the diff) is a recorded follow-up, not something either cut did. +That first `--since` pass did not actually stay diff-scoped: adding +`stryker-config.json` itself in the same cut that first used it made Stryker +log "391 mutants will be tested because: Non-CSharp files in test project +were changed" and mutate the whole `mutate` glob (all four existing +GameCult.Geometry source files), not just the new surface-nets files. A cut +that changes a non-C# file inside the test project (a fixture, this config +file, anything under `Fixtures/`) loses `--since` line-level scoping for that +run; a future cut whose diff is C#-only, against a base commit that already +has `stryker-config.json`, should scope correctly. + `GameCult.Caching`, `GameCult.Mesh` (+ `.Quic`, `.Quic.Native`), `GameCult.Networking` (+ `.WebSockets`), and the non-.NET runtimes (`cultcache-rs/py/ts`, `cultmesh-*`, `cultnet-*`) each still need their own