src/cmd/go/internal/load/test.go | 23 +++++++++++------------ src/cmd/go/internal/work/exec.go | 1 + src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt | 28 +++++++++++++++++----------- diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index 6293aea3c36dbe23393517581fa40f414727e145..48d03d8fce404bd37890c0d24a86199865d3fa2d 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -268,17 +268,8 @@ } pmain.Imports = pmain.Imports[:w] pmain.Internal.RawImports = str.StringList(pmain.Imports) - if ptest != p { - // We have made modifications to the package p being tested - // and are rebuilding p (as ptest). - // Arrange to rebuild all packages q such that - // the test depends on q and q depends on p. - // This makes sure that q sees the modifications to p. - // Strictly speaking, the rebuild is only necessary if the - // modifications to p change its export metadata, but - // determining that is a bit tricky, so we rebuild always. - recompileForTest(pmain, p, ptest, pxtest) - } + // Replace pmain's transitive dependencies with test copies, as necessary. + recompileForTest(pmain, p, ptest, pxtest) // Should we apply coverage analysis locally, // only for this package and only for this test? @@ -325,6 +316,14 @@ } return stk } +// recompileForTest copies and replaces certain packages in pmain's dependency +// graph. This is necessary for two reasons. First, if ptest is different than +// preal, packages that import the package under test should get ptest instead +// of preal. This is particularly important if pxtest depends on functionality +// exposed in test sources in ptest. Second, if there is a main package +// (other than pmain) anywhere, we need to clear p.Internal.BuildInfo in +// the test copy to prevent link conflicts. This may happen if both -coverpkg +// and the command line patterns include multiple main packages. func recompileForTest(pmain, preal, ptest, pxtest *Package) { // The "test copy" of preal is ptest. // For each package that depends on preal, make a "test copy" @@ -367,7 +366,7 @@ } // Don't compile build info from a main package. This can happen // if -coverpkg patterns include main packages, since those packages - // are imported by pmain. + // are imported by pmain. See golang.org/issue/30907. if p.Internal.BuildInfo != "" && p != pmain { split() } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index bbcbdd75686a300d7ecc15f358127a2493eda987..0ab7976c5638cee1ebfad1325cd08bee541e7ddd 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -214,6 +214,7 @@ } if p.Internal.CoverMode != "" { fmt.Fprintf(h, "cover %q %q\n", p.Internal.CoverMode, b.toolID("cover")) } + fmt.Fprintf(h, "modinfo %q\n", p.Internal.BuildInfo) // Configuration specific to compiler toolchain. switch cfg.BuildToolchainName { diff --git a/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt b/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt index 8ee4848d0a247040b4bd5b842ffcc42cbf50095e..ab7cd66949db0fbb60ddd3084c6d11e8082d2593 100644 --- a/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt +++ b/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt @@ -6,32 +6,38 @@ env GO111MODULE=on [short] skip -go test -coverpkg=all ./main1 ./main2 +go test -coverpkg=all ./... -- go.mod -- module example.com/cov --- main1/main1.go -- +-- mainonly/mainonly.go -- package main func main() {} --- main1/main1_test.go -- +-- mainwithtest/mainwithtest.go -- package main -import "testing" +func main() {} -func TestMain1(t *testing.T) {} +func Foo() {} --- main2/main2.go -- +-- mainwithtest/mainwithtest_test.go -- package main -func main() {} +import "testing" --- main2/main2_test.go -- -package main +func TestFoo(t *testing.T) { + Foo() +} -import "testing" +-- xtest/x.go -- +package x + +-- xtest/x_test.go -- +package x_test -func TestMain2(t *testing.T) {} +import "testing" +func TestX(t *testing.T) {}