Assert the door the refresh reads the roster through - #208
Merged
Conversation
roster.Named carried no test. It is the second door on the roster file, the one the refresh reads through before anything can be asked about the repositories a row names, and all three of its refusals were reached by nothing: a file that is not the array of rows, a row naming no repository, and a file holding no row at all. Every one of them could have stopped refusing with the suite green, and what the door hands back goes into the refresh that produces the record the build later reads as answered. Found by reading the survivor and uncovered lists of the mutation run this issue records rather than its score. Of the eight mutants the tool reports as NOT COVERED in this package, four sit in Named. Applied by hand at 3db5bc8, in a clone outside the working tree, each one leaves the suite green: internal/roster/roster.go:217 err != nil -> err == nil internal/roster/roster.go:224 == "" -> != "" internal/roster/roster.go:226 i+1 -> i-1 internal/roster/roster.go:231 len(names) == 0 -> len(names) != 0 The four cases here are one per refusal plus two neighbours: a file breaking nothing reads into the three repositories it declares in order, and a file the parser refuses three times over still comes back out of this door, which is the property that makes it a separate door rather than a flag on the first one. Each of the four mutations above was then applied again with these cases in and produced a red run naming the refusal it removed. The row number is compared against the whole opening of the reason rather than a fragment of it, which is the rule the table beside this one already follows: a reason saying row 1 where the fixture broke the third row still reads as a refusal about a row and sends somebody to the wrong line. The fixture breaks the third row, so counting from zero and counting the wrong row are both separated from the right answer. Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
roster.Namedcarried no test. It is the second door on the roster file, the onethe refresh reads through before anything can be asked about the repositories a
row names, and its own comment says why it exists as a separate door: it applies
no rule and judges nothing, so a caller that used it to render a page would be
rendering a file nobody checked.
It does refuse three things, and all three were reached by nothing:
Run 2026-08-27 against
3db5bc8. One caller, no case.I found it by reading the uncovered list of the mutation run #44 records rather
than its score. Eight mutants in this package are reported
NOT COVERED, and Iapplied every one of them by hand at
3db5bc8in a clone outside the workingtree, because a tool that cannot see a site is not the same statement as a suite
that does not assert it. The eight split cleanly in two:
Run 2026-08-27, each mutation applied alone with the tree restored between.
The four that survive are all of
Named, and they are this change. The four thatdie are all
caseexpressions of an expression switch insideParse, which thesuite does assert; Go's coverage counter sits on the case body rather than on the
case expression, so the tool reads the position as uncovered and never mutates
it. That half is a bound on the figure rather than a gap in the suite, and it is
written into #44 rather than repaired here.
What this does
Four cases over
Named, in the shape the table beside them already uses.One per refusal, each tripping exactly it: a file that is not the array of rows,
a row naming no repository, a row whose repository is only spaces, and a file
holding no row. The reason is compared against its whole opening rather than a
fragment, so the row number is part of what is asserted.
Two neighbours. A file breaking nothing reads into the three repositories it
declares, in order. And a file the parser refuses three times over still comes
back out of this door, with the parser refusing the same bytes asserted in the
same case, which is the property that makes it a separate door rather than a flag
on the first one.
What it prevents is
Namedlosing a refusal in silence. The list it hands backgoes into the refresh that writes the release record, and the build then reads
that record as an answered question.
Closes
Nothing. It belongs to #44 and does not close it: what that issue waits on is
where a mutation run lives, which is a call rather than a measurement and is not
touched here.
What was run
The gate, at the commit being pushed:
needs-networkwas not asked for and nothing here needs it: every case in thischange reads bytes in the test file.
Each of the four mutations these cases exist for, applied again by hand with the
cases in, one at a time with the tree restored between:
All run 2026-08-27. Each is red for the refusal it removed rather than for
something downstream.
The tool agrees, in a clone outside the working tree at the two commits:
Both run 2026-08-27, at the coefficient #44 argues belongs beside any score. The
four still reported uncovered are the four case expressions above, which are the
ones the reading at the top shows the suite already asserts.
No test was skipped. Nothing here needs a display, elevation, a socket or a
network.
The means
Go test cases in the package they judge, which is what every other suite in this
tree is made of. It adds no language, no runtime and no dependency:
go testalready runs it as the third leg of the gate, and the mutation figures above come
from a tool that is run by hand outside the gate and is not made a dependency of
it by this change.
It carries a rule a machine refuses, in the only form this repository has for a
rule about a suite: each case is shown to bite by removing the thing it exists
for and watching the run go red naming that thing, which is the four readings
above. Every claim in this body carries the command that produced it.
Who read it
Nobody else. This change carries no second reader, and the evidence above stands
in place of one: the eight-way hand reading that found the gap, the four
mutations replayed against the cases, and the two tool runs at the two commits.
The ruleset on this branch requires no approving review, so the merge is not
evidence of one either.