Skip to content

Commit 4a2d3d0

Browse files
author
Bryan C. Mills
committed
cmd/go: in module mode, populate PackagePublic.Root with the module root
'go test' uses the Root field to determine the set of files that invalidate test results, and there is no other sensible meaning of “root” for code within a module. Fixes #29111 Change-Id: Icf1be90a26d22665613e42cb968087b63c36e74c Reviewed-on: https://go-review.googlesource.com/c/go/+/154100 Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent 5ba15db commit 4a2d3d0

File tree

4 files changed

+100
-8
lines changed

4 files changed

+100
-8
lines changed

src/cmd/go/internal/load/pkg.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ type PackagePublic struct {
6464
Doc string `json:",omitempty"` // package documentation string
6565
Target string `json:",omitempty"` // installed target for this package (may be executable)
6666
Shlib string `json:",omitempty"` // the shared library that contains this package (only set when -linkshared)
67-
Root string `json:",omitempty"` // Go root or Go path dir containing this package
67+
Root string `json:",omitempty"` // Go root, Go path dir, or module root dir containing this package
6868
ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
6969
ForTest string `json:",omitempty"` // package is only for use in named test
7070
Export string `json:",omitempty"` // file containing export data (set by go list -export)
@@ -647,6 +647,11 @@ func loadPackageData(path, parentPath, parentDir, parentRoot string, parentIsStd
647647
buildMode = build.ImportComment
648648
}
649649
data.p, data.err = cfg.BuildContext.ImportDir(r.dir, buildMode)
650+
if data.p.Root == "" && cfg.ModulesEnabled {
651+
if info := ModPackageModuleInfo(path); info != nil {
652+
data.p.Root = info.Dir
653+
}
654+
}
650655
} else if r.err != nil {
651656
data.p = new(build.Package)
652657
data.err = fmt.Errorf("unknown import path %q: %v", r.path, r.err)

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,15 @@ func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bo
12501250
return false
12511251
}
12521252

1253+
if a.Package.Root == "" {
1254+
// Caching does not apply to tests outside of any module, GOPATH, or GOROOT.
1255+
if cache.DebugTest {
1256+
fmt.Fprintf(os.Stderr, "testcache: caching disabled for package outside of module root, GOPATH, or GOROOT: %s\n", a.Package.ImportPath)
1257+
}
1258+
c.disableCache = true
1259+
return false
1260+
}
1261+
12531262
var cacheArgs []string
12541263
for _, arg := range testArgs {
12551264
i := strings.Index(arg, "=")
@@ -1437,17 +1446,17 @@ func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error)
14371446
if !filepath.IsAbs(name) {
14381447
name = filepath.Join(pwd, name)
14391448
}
1440-
if !inDir(name, a.Package.Root) {
1441-
// Do not recheck files outside the GOPATH or GOROOT root.
1449+
if a.Package.Root == "" || !inDir(name, a.Package.Root) {
1450+
// Do not recheck files outside the module, GOPATH, or GOROOT root.
14421451
break
14431452
}
14441453
fmt.Fprintf(h, "stat %s %x\n", name, hashStat(name))
14451454
case "open":
14461455
if !filepath.IsAbs(name) {
14471456
name = filepath.Join(pwd, name)
14481457
}
1449-
if !inDir(name, a.Package.Root) {
1450-
// Do not recheck files outside the GOPATH or GOROOT root.
1458+
if a.Package.Root == "" || !inDir(name, a.Package.Root) {
1459+
// Do not recheck files outside the module, GOPATH, or GOROOT root.
14511460
break
14521461
}
14531462
fh, err := hashOpen(name)

src/cmd/go/testdata/script/build_cache_output.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
env GO111MODULE=off
2+
env GODEBUG=gocachetest=1
23

34
[!gc] skip
45
[short] skip # clears cache, rebuilds too much
@@ -32,7 +33,7 @@ stderr 'main.go:2.* can inline main' # from compiler
3233
stderr '\d+ symbols' # from linker
3334

3435
# Running a test should run the compiler, linker, and the test the first time.
35-
go test -v -x -gcflags=-m -ldflags=-v p_test.go
36+
go test -v -x -gcflags=-m -ldflags=-v p
3637
stderr 'compile( |\.exe"?)'
3738
stderr 'p_test.go:.*can inline Test' # from compile of p_test
3839
stderr 'testmain\.go:.*inlin' # from compile of testmain
@@ -42,7 +43,7 @@ stderr 'p\.test( |\.exe"?)'
4243
stdout 'TEST' # from test
4344

4445
# ... but not the second, even though it still prints the compiler, linker, and test output.
45-
go test -v -x -gcflags=-m -ldflags=-v p_test.go
46+
go test -v -x -gcflags=-m -ldflags=-v p
4647
! stderr 'compile( |\.exe"?)'
4748
stderr 'p_test.go:.*can inline Test' # from compile of p_test
4849
stderr 'testmain\.go:.*inlin' # from compile of testmain
@@ -60,7 +61,7 @@ func f(x *int) *int { return x }
6061
package main
6162
func main() {}
6263

63-
-- p_test.go --
64+
-- p/p_test.go --
6465
package p
6566
import "testing"
6667
func Test(t *testing.T) {println("TEST")}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
[short] skip
2+
3+
env GO111MODULE=on
4+
env GOCACHE=$WORK/gocache
5+
env GODEBUG=gocachetest=1
6+
7+
# The first run of a test should not be cached.
8+
# The second run should be.
9+
go test -run=WriteTmp .
10+
! stdout '(cached)'
11+
go test -run=WriteTmp .
12+
stdout '(cached)'
13+
14+
# 'go test' without arguments should never be cached.
15+
go test -run=WriteTmp
16+
! stdout '(cached)'
17+
go test -run=WriteTmp
18+
! stdout '(cached)'
19+
20+
# We should never cache a test run from command-line files.
21+
go test -run=WriteTmp ./foo_test.go
22+
! stdout '(cached)'
23+
go test -run=WriteTmp ./foo_test.go
24+
! stdout '(cached)'
25+
26+
[!exec:sleep] stop
27+
# The go command refuses to cache access to files younger than 2s, so sleep that long.
28+
exec sleep 2
29+
30+
# Touching a file that the test reads from within its testdata should invalidate the cache.
31+
go test -run=ReadTestdata .
32+
! stdout '(cached)'
33+
go test -run=ReadTestdata .
34+
stdout '(cached)'
35+
cp testdata/bar.txt testdata/foo.txt
36+
go test -run=ReadTestdata .
37+
! stdout '(cached)'
38+
39+
-- go.mod --
40+
module golang.org/issue/29111/foo
41+
42+
-- foo.go --
43+
package foo
44+
45+
-- testdata/foo.txt --
46+
foo
47+
-- testdata/bar.txt --
48+
bar
49+
50+
-- foo_test.go --
51+
package foo_test
52+
53+
import (
54+
"io/ioutil"
55+
"os"
56+
"path/filepath"
57+
"testing"
58+
)
59+
60+
func TestWriteTmp(t *testing.T) {
61+
dir, err := ioutil.TempDir("", "")
62+
if err != nil {
63+
t.Fatal(err)
64+
}
65+
defer os.RemoveAll(dir)
66+
err = ioutil.WriteFile(filepath.Join(dir, "x"), nil, 0666)
67+
if err != nil {
68+
t.Fatal(err)
69+
}
70+
}
71+
72+
func TestReadTestdata(t *testing.T) {
73+
_, err := ioutil.ReadFile("testdata/foo.txt")
74+
if err != nil {
75+
t.Fatal(err)
76+
}
77+
}

0 commit comments

Comments
 (0)