]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: fix -coverpkg=all with dot imports
authorRuss Cox <rsc@golang.org>
Tue, 23 Jan 2018 01:07:58 +0000 (20:07 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 24 Jan 2018 16:33:06 +0000 (16:33 +0000)
If you use -coverpkg=all you get coverage for all packages in the build.
Go 1.9 used a global counter for all the GoCover variables, so that they
were distinct for the entire build. The global counter caused problems
with caching, so we switched to a per-package counter. But now the
GoCover_0 in one package may be dot-imported into another and
conflict with the GoCover_0 in that other package.

Reestablish (overwhelmingly likely) global uniqueness of GoCover
variables by appending an _xxxxxxxxxxxx suffix, where the x's are
the prefix of the SHA256 hash of the import path. The point is only
to avoid accidents, not to defeat people determined to break the tools.

Fixes #23432.

Change-Id: I3088eceebbe35174f2eefe8d558b7c8b59d3eeac
Reviewed-on: https://go-review.googlesource.com/89135
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/go/go_test.go
src/cmd/go/internal/test/test.go
src/cmd/go/testdata/src/coverdot1/p.go [new file with mode: 0644]
src/cmd/go/testdata/src/coverdot2/p.go [new file with mode: 0644]
src/cmd/go/testdata/src/coverdot2/p_test.go [new file with mode: 0644]

index 8662c81c93843f84e799aad70b4443d3e2e0b8be..7eaaf4875946967cecf64f01e8dea5b5d769e61a 100644 (file)
@@ -2437,6 +2437,16 @@ func TestCoverageRuns(t *testing.T) {
        checkCoverage(tg, data)
 }
 
+func TestCoverageDotImport(t *testing.T) {
+       tg := testgo(t)
+       defer tg.cleanup()
+       tg.parallel()
+       tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+       tg.run("test", "-coverpkg=coverdot1,coverdot2", "coverdot2")
+       data := tg.getStdout() + tg.getStderr()
+       checkCoverage(tg, data)
+}
+
 // Check that coverage analysis uses set mode.
 // Also check that coverage profiles merge correctly.
 func TestCoverageUsesSetMode(t *testing.T) {
index 5147c5b778e7ecc24be714b3d4089b94a03ba733..7f7ce63eda8cc4abf714015df1fe8e21431a280b 100644 (file)
@@ -6,6 +6,7 @@ package test
 
 import (
        "bytes"
+       "crypto/sha256"
        "errors"
        "fmt"
        "go/ast"
@@ -1091,13 +1092,21 @@ func isTestFile(file string) bool {
 func declareCoverVars(importPath string, files ...string) map[string]*load.CoverVar {
        coverVars := make(map[string]*load.CoverVar)
        coverIndex := 0
+       // We create the cover counters as new top-level variables in the package.
+       // We need to avoid collisions with user variables (GoCover_0 is unlikely but still)
+       // and more importantly with dot imports of other covered packages,
+       // so we append 12 hex digits from the SHA-256 of the import path.
+       // The point is only to avoid accidents, not to defeat users determined to
+       // break things.
+       sum := sha256.Sum256([]byte(importPath))
+       h := fmt.Sprintf("%x", sum[:6])
        for _, file := range files {
                if isTestFile(file) {
                        continue
                }
                coverVars[file] = &load.CoverVar{
                        File: filepath.Join(importPath, file),
-                       Var:  fmt.Sprintf("GoCover_%d", coverIndex),
+                       Var:  fmt.Sprintf("GoCover_%d_%x", coverIndex, h),
                }
                coverIndex++
        }
diff --git a/src/cmd/go/testdata/src/coverdot1/p.go b/src/cmd/go/testdata/src/coverdot1/p.go
new file mode 100644 (file)
index 0000000..cda364f
--- /dev/null
@@ -0,0 +1,3 @@
+package coverdot1
+
+func F() {}
diff --git a/src/cmd/go/testdata/src/coverdot2/p.go b/src/cmd/go/testdata/src/coverdot2/p.go
new file mode 100644 (file)
index 0000000..80f79ae
--- /dev/null
@@ -0,0 +1,5 @@
+package coverdot2
+
+import . "coverdot1"
+
+func G() { F() }
diff --git a/src/cmd/go/testdata/src/coverdot2/p_test.go b/src/cmd/go/testdata/src/coverdot2/p_test.go
new file mode 100644 (file)
index 0000000..da66e3e
--- /dev/null
@@ -0,0 +1,7 @@
+package coverdot2
+
+import "testing"
+
+func TestG(t *testing.T) {
+       G()
+}