Skip to content

Commit a85b881

Browse files
committed
cmd/go: fix problems with coverage percentage reporting w/ -coverpkg
This patch resolves a set of problems with "percent covered" metrics reported when the "-coverpkg" is in effect; these bugs were introduced in Go 1.22 with the rollout of CL 495452 and related changes. Specifically, for runs with multiple packages selected but without -coverpkg, "percent covered" metrics were generated for package P not based just on P's statements but on the entire corpus of statements. Fixes #65570. Change-Id: I38d61886cb46ebd38d8c4313c326d671197c3568 Reviewed-on: https://go-review.googlesource.com/c/go/+/592205 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Michael Matloob <[email protected]>
1 parent 7196db9 commit a85b881

File tree

5 files changed

+87
-6
lines changed

5 files changed

+87
-6
lines changed

src/cmd/go/internal/load/test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,22 @@ func (t *testFuncs) Covered() string {
683683
return " in " + strings.Join(t.Cover.Paths, ", ")
684684
}
685685

686+
func (t *testFuncs) CoverSelectedPackages() string {
687+
if t.Cover == nil || t.Cover.Paths == nil {
688+
return `[]string{"` + t.Package.ImportPath + `"}`
689+
}
690+
var sb strings.Builder
691+
fmt.Fprintf(&sb, "[]string{")
692+
for k, p := range t.Cover.Pkgs {
693+
if k != 0 {
694+
sb.WriteString(", ")
695+
}
696+
fmt.Fprintf(&sb, `"%s"`, p.ImportPath)
697+
}
698+
sb.WriteString("}")
699+
return sb.String()
700+
}
701+
686702
// Tested returns the name of the package being tested.
687703
func (t *testFuncs) Tested() string {
688704
return t.Package.Name
@@ -950,6 +966,7 @@ func init() {
950966
{{if .Cover}}
951967
testdeps.CoverMode = {{printf "%q" .Cover.Mode}}
952968
testdeps.Covered = {{printf "%q" .Covered}}
969+
testdeps.CoverSelectedPackages = {{printf "%s" .CoverSelectedPackages}}
953970
testdeps.CoverSnapshotFunc = cfile.Snapshot
954971
testdeps.CoverProcessTestDirFunc = cfile.ProcessCoverTestDir
955972
testdeps.CoverMarkProfileEmittedFunc = cfile.MarkProfileEmitted
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Without -coverpkg, we should get the same value for a given
2+
# package regardless of how many other packages are selected
3+
# (see issue 65570).
4+
5+
[short] skip
6+
7+
go test -count=1 -cover ./a ./b ./main
8+
stdout '^ok\s+M/main\s+\S+\s+coverage: 75.0% of statements'
9+
go test -count=1 -cover ./main
10+
stdout '^ok\s+M/main\s+\S+\s+coverage: 75.0% of statements'
11+
12+
-- go.mod --
13+
module M
14+
15+
go 1.21
16+
-- a/a.go --
17+
package a
18+
19+
func AFunc() int {
20+
return 42
21+
}
22+
-- b/b.go --
23+
package b
24+
25+
func BFunc() int {
26+
return -42
27+
}
28+
-- main/main.go --
29+
package main
30+
31+
import (
32+
"M/a"
33+
)
34+
35+
func MFunc() string {
36+
return "42"
37+
}
38+
39+
func M2Func() int {
40+
return a.AFunc()
41+
}
42+
43+
func init() {
44+
println("package 'main' init")
45+
}
46+
47+
func main() {
48+
println(a.AFunc())
49+
}
50+
-- main/main_test.go --
51+
package main
52+
53+
import "testing"
54+
55+
func TestMain(t *testing.T) {
56+
if MFunc() != "42" {
57+
t.Fatalf("bad!")
58+
}
59+
if M2Func() != 42 {
60+
t.Fatalf("also bad!")
61+
}
62+
}
63+

src/internal/coverage/cfile/testsupport.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import (
2727
// testmain code when "go test -cover" is in effect. It is not
2828
// intended to be used other than internally by the Go command's
2929
// generated code.
30-
func ProcessCoverTestDir(dir string, cfile string, cm string, cpkg string, w io.Writer) error {
30+
func ProcessCoverTestDir(dir string, cfile string, cm string, cpkg string, w io.Writer, selpkgs []string) error {
3131
cmode := coverage.ParseCounterMode(cm)
3232
if cmode == coverage.CtrModeInvalid {
3333
return fmt.Errorf("invalid counter mode %q", cm)
@@ -103,7 +103,7 @@ func ProcessCoverTestDir(dir string, cfile string, cm string, cpkg string, w io.
103103
}
104104

105105
// Emit percent.
106-
if err := ts.cf.EmitPercent(w, nil, cpkg, true, true); err != nil {
106+
if err := ts.cf.EmitPercent(w, selpkgs, cpkg, true, true); err != nil {
107107
return err
108108
}
109109

src/internal/coverage/cfile/ts_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func TestTestSupport(t *testing.T) {
4545
textfile := filepath.Join(t.TempDir(), "file.txt")
4646
var sb strings.Builder
4747
err := ProcessCoverTestDir(tgcd, textfile,
48-
testing.CoverMode(), "", &sb)
48+
testing.CoverMode(), "", &sb, nil)
4949
if err != nil {
5050
t.Fatalf("bad: %v", err)
5151
}
@@ -168,7 +168,7 @@ func TestAuxMetaDataFiles(t *testing.T) {
168168
var sb strings.Builder
169169
textfile := filepath.Join(td, "file2.txt")
170170
err = ProcessCoverTestDir(tgcd, textfile,
171-
testing.CoverMode(), "", &sb)
171+
testing.CoverMode(), "", &sb, nil)
172172
if err != nil {
173173
t.Fatalf("bad: %v", err)
174174
}

src/testing/internal/testdeps/deps.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,15 @@ func (TestDeps) SnapshotCoverage() {
203203

204204
var CoverMode string
205205
var Covered string
206+
var CoverSelectedPackages []string
206207

207208
// These variables below are set at runtime (via code in testmain) to point
208209
// to the equivalent functions in package internal/coverage/cfile; doing
209210
// things this way allows us to have tests import internal/coverage/cfile
210211
// only when -cover is in effect (as opposed to importing for all tests).
211212
var (
212213
CoverSnapshotFunc func() float64
213-
CoverProcessTestDirFunc func(dir string, cfile string, cm string, cpkg string, w io.Writer) error
214+
CoverProcessTestDirFunc func(dir string, cfile string, cm string, cpkg string, w io.Writer, selpkgs []string) error
214215
CoverMarkProfileEmittedFunc func(val bool)
215216
)
216217

@@ -232,7 +233,7 @@ func coverTearDown(coverprofile string, gocoverdir string) (string, error) {
232233
}
233234
CoverMarkProfileEmittedFunc(true)
234235
cmode := CoverMode
235-
if err := CoverProcessTestDirFunc(gocoverdir, coverprofile, cmode, Covered, os.Stdout); err != nil {
236+
if err := CoverProcessTestDirFunc(gocoverdir, coverprofile, cmode, Covered, os.Stdout, CoverSelectedPackages); err != nil {
236237
return "error generating coverage report", err
237238
}
238239
return "", nil

0 commit comments

Comments
 (0)