return " in " + strings.Join(t.Cover.Paths, ", ")
}
+func (t *testFuncs) CoverSelectedPackages() string {
+ if t.Cover == nil || t.Cover.Paths == nil {
+ return `[]string{"` + t.Package.ImportPath + `"}`
+ }
+ var sb strings.Builder
+ fmt.Fprintf(&sb, "[]string{")
+ for k, p := range t.Cover.Pkgs {
+ if k != 0 {
+ sb.WriteString(", ")
+ }
+ fmt.Fprintf(&sb, `"%s"`, p.ImportPath)
+ }
+ sb.WriteString("}")
+ return sb.String()
+}
+
// Tested returns the name of the package being tested.
func (t *testFuncs) Tested() string {
return t.Package.Name
{{if .Cover}}
testdeps.CoverMode = {{printf "%q" .Cover.Mode}}
testdeps.Covered = {{printf "%q" .Covered}}
+ testdeps.CoverSelectedPackages = {{printf "%s" .CoverSelectedPackages}}
testdeps.CoverSnapshotFunc = cfile.Snapshot
testdeps.CoverProcessTestDirFunc = cfile.ProcessCoverTestDir
testdeps.CoverMarkProfileEmittedFunc = cfile.MarkProfileEmitted
--- /dev/null
+# Without -coverpkg, we should get the same value for a given
+# package regardless of how many other packages are selected
+# (see issue 65570).
+
+[short] skip
+
+go test -count=1 -cover ./a ./b ./main
+stdout '^ok\s+M/main\s+\S+\s+coverage: 75.0% of statements'
+go test -count=1 -cover ./main
+stdout '^ok\s+M/main\s+\S+\s+coverage: 75.0% of statements'
+
+-- go.mod --
+module M
+
+go 1.21
+-- a/a.go --
+package a
+
+func AFunc() int {
+ return 42
+}
+-- b/b.go --
+package b
+
+func BFunc() int {
+ return -42
+}
+-- main/main.go --
+package main
+
+import (
+ "M/a"
+)
+
+func MFunc() string {
+ return "42"
+}
+
+func M2Func() int {
+ return a.AFunc()
+}
+
+func init() {
+ println("package 'main' init")
+}
+
+func main() {
+ println(a.AFunc())
+}
+-- main/main_test.go --
+package main
+
+import "testing"
+
+func TestMain(t *testing.T) {
+ if MFunc() != "42" {
+ t.Fatalf("bad!")
+ }
+ if M2Func() != 42 {
+ t.Fatalf("also bad!")
+ }
+}
+
// testmain code when "go test -cover" is in effect. It is not
// intended to be used other than internally by the Go command's
// generated code.
-func ProcessCoverTestDir(dir string, cfile string, cm string, cpkg string, w io.Writer) error {
+func ProcessCoverTestDir(dir string, cfile string, cm string, cpkg string, w io.Writer, selpkgs []string) error {
cmode := coverage.ParseCounterMode(cm)
if cmode == coverage.CtrModeInvalid {
return fmt.Errorf("invalid counter mode %q", cm)
}
// Emit percent.
- if err := ts.cf.EmitPercent(w, nil, cpkg, true, true); err != nil {
+ if err := ts.cf.EmitPercent(w, selpkgs, cpkg, true, true); err != nil {
return err
}
textfile := filepath.Join(t.TempDir(), "file.txt")
var sb strings.Builder
err := ProcessCoverTestDir(tgcd, textfile,
- testing.CoverMode(), "", &sb)
+ testing.CoverMode(), "", &sb, nil)
if err != nil {
t.Fatalf("bad: %v", err)
}
var sb strings.Builder
textfile := filepath.Join(td, "file2.txt")
err = ProcessCoverTestDir(tgcd, textfile,
- testing.CoverMode(), "", &sb)
+ testing.CoverMode(), "", &sb, nil)
if err != nil {
t.Fatalf("bad: %v", err)
}
var CoverMode string
var Covered string
+var CoverSelectedPackages []string
// These variables below are set at runtime (via code in testmain) to point
// to the equivalent functions in package internal/coverage/cfile; doing
// only when -cover is in effect (as opposed to importing for all tests).
var (
CoverSnapshotFunc func() float64
- CoverProcessTestDirFunc func(dir string, cfile string, cm string, cpkg string, w io.Writer) error
+ CoverProcessTestDirFunc func(dir string, cfile string, cm string, cpkg string, w io.Writer, selpkgs []string) error
CoverMarkProfileEmittedFunc func(val bool)
)
}
CoverMarkProfileEmittedFunc(true)
cmode := CoverMode
- if err := CoverProcessTestDirFunc(gocoverdir, coverprofile, cmode, Covered, os.Stdout); err != nil {
+ if err := CoverProcessTestDirFunc(gocoverdir, coverprofile, cmode, Covered, os.Stdout, CoverSelectedPackages); err != nil {
return "error generating coverage report", err
}
return "", nil