Skip to content

Commit bc280a5

Browse files
aledbfclaude
andcommitted
test(devtool): hold the coverage, parity and runner edits
go tool mutate left six edits no test refused. Pct of a package with no statements is now tested (0, not NaN), and so is a cli file that is not a test and a test outside internal/cli, which both run the full parity matrix. ParseFloat's bitSize of 64 is exempt: any value but 32 means 64. The exec helper process now gets a GOCOVERDIR, since a binary built with coverage, as mutate builds it, warned on the helper's stderr and failed TestOSRunnerProcessContract before any edit; that hid the nil-stream edit in OSRunner.Run. A test with a single Env entry holds the len > 0 guard that the extra entry would otherwise leave untested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent edef421 commit bc280a5

4 files changed

Lines changed: 39 additions & 8 deletions

File tree

‎internal/devtools/coverage.go‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ func (p PkgCov) Pct() float64 {
2929
}
3030
// Round to 1 decimal exactly as fmt "%.1f" would, so String() and numeric
3131
// comparisons never disagree at a boundary.
32-
v, _ := strconv.ParseFloat(fmt.Sprintf("%.1f", float64(p.Covered)*100/float64(p.Total)), 64)
32+
rounded := fmt.Sprintf("%.1f", float64(p.Covered)*100/float64(p.Total))
33+
v, _ := strconv.ParseFloat(rounded, 64) // mutate-exempt: ParseFloat reads any bitSize but 32 as 64
3334
return v
3435
}
3536

@@ -156,7 +157,7 @@ func ParseFloors(specs []string) ([]Floor, error) {
156157
if !found || k == "" {
157158
return nil, fmt.Errorf("invalid floor %q: want <key>=<min>", s)
158159
}
159-
min, err := strconv.ParseFloat(v, 64)
160+
min, err := strconv.ParseFloat(v, 64) // mutate-exempt: ParseFloat reads any bitSize but 32 as 64
160161
if err != nil {
161162
return nil, fmt.Errorf("invalid floor %q: %w", s, err)
162163
}

‎internal/devtools/coverage_test.go‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,14 @@ func TestParseFloorsInvalid(t *testing.T) {
117117
}
118118
}
119119
}
120+
121+
// TestPctOfAnEmptyPackage holds the guard a package without statements needs: its
122+
// coverage is 0, not the NaN of 0/0 that the report and the gate would print.
123+
func TestPctOfAnEmptyPackage(t *testing.T) {
124+
if got := (PkgCov{Pkg: "p"}).Pct(); got != 0 {
125+
t.Errorf("Pct of 0 statements = %v, want 0", got)
126+
}
127+
if got := (PkgCov{Pkg: "p", Covered: 1, Total: 1}).Pct(); got != 100 {
128+
t.Errorf("Pct of 1/1 statements = %v, want 100", got)
129+
}
130+
}

‎internal/devtools/parityaffected_test.go‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ func TestParityAffected(t *testing.T) {
3838
{"Taskfile → all", []string{"Taskfile.yml"}, "all"},
3939
{"go-cli workflow → all", []string{".github/workflows/go-cli.yml"}, "all"},
4040
{"shared internal → all", []string{"internal/foo.go"}, "all"},
41+
{"shared cli file → all", []string{"internal/cli/shared.go"}, "all"},
42+
{"test outside cli → all", []string{"internal/docker/client_test.go"}, "all"},
4143
{"cmd → all", []string{"cmd/devcontainer/main.go"}, "all"},
4244
{"unknown path → all", []string{"totally-unknown-file"}, "all"},
4345
{"full wins over leaf", []string{"internal/cli/exec.go", "docs/parity/parity-matrix.yaml"}, "all"},

‎internal/exec/exec_test.go‎

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,17 @@ func helperArgs(args []string) []string {
4444
return nil
4545
}
4646

47-
func helperRunner(env ...string) OSRunner {
47+
// helperRunner runs this test binary as the helper process. GOCOVERDIR keeps a
48+
// binary built with coverage (as go tool mutate builds it) from warning on the
49+
// helper's stderr that it has nowhere to write its counters.
50+
func helperRunner(t *testing.T, env ...string) OSRunner {
4851
return OSRunner{Env: append([]string{
49-
"GO_WANT_EXEC_HELPER=1",
52+
"GO_WANT_EXEC_HELPER=1", "GOCOVERDIR=" + t.TempDir(),
5053
}, env...)}
5154
}
5255

5356
func TestOSRunnerProcessContract(t *testing.T) {
54-
stdout, stderr, code, err := helperRunner("EXEC_HELPER_STDERR=warning").Run(
57+
stdout, stderr, code, err := helperRunner(t, "EXEC_HELPER_STDERR=warning").Run(
5558
t.Context(), nil, os.Args[0], "-test.run=^TestHelperProcess$", "--", "echo", "one", "two",
5659
)
5760
if err != nil {
@@ -69,7 +72,7 @@ func TestOSRunnerProcessContract(t *testing.T) {
6972
}
7073

7174
func TestOSRunnerNonZeroIsExitCodeNotTransportError(t *testing.T) {
72-
_, _, code, err := helperRunner().Run(
75+
_, _, code, err := helperRunner(t).Run(
7376
t.Context(), nil, os.Args[0], "-test.run=^TestHelperProcess$", "--", "exit",
7477
)
7578
if err != nil {
@@ -83,7 +86,7 @@ func TestOSRunnerNonZeroIsExitCodeNotTransportError(t *testing.T) {
8386
func TestOSRunnerHonorsCancellation(t *testing.T) {
8487
ctx, cancel := context.WithTimeout(t.Context(), 100*time.Millisecond)
8588
defer cancel()
86-
_, _, code, err := helperRunner().Run(
89+
_, _, code, err := helperRunner(t).Run(
8790
ctx, nil, os.Args[0], "-test.run=^TestHelperProcess$", "--", "wait",
8891
)
8992
if !errors.Is(err, context.DeadlineExceeded) {
@@ -108,7 +111,7 @@ func TestOSRunnerMissingBinaryIsTransportError(t *testing.T) {
108111
// output live while the return value still captures it.
109112
func TestOSRunnerStreamsToWriter(t *testing.T) {
110113
var live strings.Builder
111-
stdout, _, code, err := helperRunner("EXEC_HELPER_STDERR=warn").Run(
114+
stdout, _, code, err := helperRunner(t, "EXEC_HELPER_STDERR=warn").Run(
112115
t.Context(), &live, os.Args[0], "-test.run=^TestHelperProcess$", "--", "echo", "hi",
113116
)
114117
if err != nil || code != 0 {
@@ -123,3 +126,17 @@ func TestOSRunnerStreamsToWriter(t *testing.T) {
123126
t.Errorf("captured stdout = %q, want hi", got)
124127
}
125128
}
129+
130+
// TestOSRunnerAppliesASingleEnvEntry holds that one entry is enough for Env to
131+
// reach the child: without it the helper below would not act as the helper.
132+
func TestOSRunnerAppliesASingleEnvEntry(t *testing.T) {
133+
stdout, _, code, err := OSRunner{Env: []string{"GO_WANT_EXEC_HELPER=1"}}.Run(
134+
t.Context(), nil, os.Args[0], "-test.run=^TestHelperProcess$", "--", "echo", "alone",
135+
)
136+
if err != nil || code != 0 {
137+
t.Fatalf("Run: err=%v code=%d", err, code)
138+
}
139+
if got := string(stdout); got != "alone" {
140+
t.Errorf("stdout = %q, want alone", got)
141+
}
142+
}

0 commit comments

Comments
 (0)