Skip to content

Commit 1b9f663

Browse files
rscbradfitz
authored andcommitted
cmd/go: disable tests when GOOS/GOARCH != GOHOSTARCH/GOHOSTARCH
The whole GOROOT/pkg tree is installed using the GOHOSTOS/GOHOSTARCH toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH). The testgo.exe we run during the cmd/go test will be built for GOOS/GOARCH, which means it will use the GOOS/GOARCH toolchain (installed in GOROOT/pkg/tool/GOOS_GOARCH). If these are not the same toolchain, then the entire standard library will look out of date to testgo.exe (the compilers in those two different tool directories are built for different architectures and have different buid IDs), which will cause many tests to do unnecessary rebuilds and some tests to attempt to overwrite the installed standard library, which will in turn make it look out of date to whatever runs after the cmd/go test exits. Bail out entirely in this case instead of destroying the world. The changes outside TestMain are checks that might have caught this a bit earlier and made it much less confusing to debug. Fixes #22709. Fixes #22965. Change-Id: Ibf28fa19e29a1f1b8f17875f446d3474dd04a924 Reviewed-on: https://go-review.googlesource.com/81516 Run-TryBot: Russ Cox <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent f047422 commit 1b9f663

File tree

1 file changed

+49
-15
lines changed

1 file changed

+49
-15
lines changed

src/cmd/go/go_test.go

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,42 @@ func TestMain(m *testing.M) {
103103
fmt.Fprintln(os.Stderr, err)
104104
os.Exit(2)
105105
}
106-
out, err := exec.Command(gotool, args...).CombinedOutput()
107-
if err != nil {
108-
fmt.Fprintf(os.Stderr, "building testgo failed: %v\n%s", err, out)
109-
os.Exit(2)
106+
107+
goEnv := func(name string) string {
108+
out, err := exec.Command(gotool, "env", name).CombinedOutput()
109+
if err != nil {
110+
fmt.Fprintf(os.Stderr, "go env %s: %v\n%s", name, err, out)
111+
os.Exit(2)
112+
}
113+
return strings.TrimSpace(string(out))
114+
}
115+
testGOROOT = goEnv("GOROOT")
116+
117+
// The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH
118+
// toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH).
119+
// The testgo.exe we are about to create will be built for GOOS/GOARCH,
120+
// which means it will use the GOOS/GOARCH toolchain
121+
// (installed in GOROOT/pkg/tool/GOOS_GOARCH).
122+
// If these are not the same toolchain, then the entire standard library
123+
// will look out of date (the compilers in those two different tool directories
124+
// are built for different architectures and have different buid IDs),
125+
// which will cause many tests to do unnecessary rebuilds and some
126+
// tests to attempt to overwrite the installed standard library.
127+
// Bail out entirely in this case.
128+
hostGOOS := goEnv("GOHOSTOS")
129+
hostGOARCH := goEnv("GOHOSTARCH")
130+
if hostGOOS != runtime.GOOS || hostGOARCH != runtime.GOARCH {
131+
fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go
132+
fmt.Printf("cmd/go test is not compatible with GOOS/GOARCH != GOHOSTOS/GOHOSTARCH (%s/%s != %s/%s)\n", runtime.GOOS, runtime.GOARCH, hostGOOS, hostGOARCH)
133+
fmt.Printf("SKIP\n")
134+
return
110135
}
111136

112-
out, err = exec.Command(gotool, "env", "GOROOT").CombinedOutput()
137+
out, err := exec.Command(gotool, args...).CombinedOutput()
113138
if err != nil {
114-
fmt.Fprintf(os.Stderr, "could not find testing GOROOT: %v\n%s", err, out)
139+
fmt.Fprintf(os.Stderr, "building testgo failed: %v\n%s", err, out)
115140
os.Exit(2)
116141
}
117-
testGOROOT = strings.TrimSpace(string(out))
118142

119143
out, err = exec.Command(gotool, "env", "CC").CombinedOutput()
120144
if err != nil {
@@ -1449,6 +1473,10 @@ func TestRelativeImportsGoTest(t *testing.T) {
14491473
func TestRelativeImportsGoTestDashI(t *testing.T) {
14501474
tg := testgo(t)
14511475
defer tg.cleanup()
1476+
1477+
// don't let test -i overwrite runtime
1478+
tg.wantNotStale("runtime", "", "must be non-stale before test -i")
1479+
14521480
tg.run("test", "-i", "./testdata/testimport")
14531481
}
14541482

@@ -1573,7 +1601,9 @@ func TestPackageNotStaleWithTrailingSlash(t *testing.T) {
15731601
defer tg.cleanup()
15741602

15751603
// Make sure the packages below are not stale.
1576-
tg.run("install", "runtime", "os", "io")
1604+
tg.wantNotStale("runtime", "", "must be non-stale before test runs")
1605+
tg.wantNotStale("os", "", "must be non-stale before test runs")
1606+
tg.wantNotStale("io", "", "must be non-stale before test runs")
15771607

15781608
goroot := runtime.GOROOT()
15791609
tg.setenv("GOROOT", goroot+"/")
@@ -2078,6 +2108,10 @@ func TestGoTestDashIDashOWritesBinary(t *testing.T) {
20782108
defer tg.cleanup()
20792109
tg.parallel()
20802110
tg.makeTempdir()
2111+
2112+
// don't let test -i overwrite runtime
2113+
tg.wantNotStale("runtime", "", "must be non-stale before test -i")
2114+
20812115
tg.run("test", "-v", "-i", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
20822116
tg.grepBothNot("PASS|FAIL", "test should not have run")
20832117
tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
@@ -2888,6 +2922,9 @@ func TestBuildDashIInstallsDependencies(t *testing.T) {
28882922
func F() { foo.F() }`)
28892923
tg.setenv("GOPATH", tg.path("."))
28902924

2925+
// don't let build -i overwrite runtime
2926+
tg.wantNotStale("runtime", "", "must be non-stale before build -i")
2927+
28912928
checkbar := func(desc string) {
28922929
tg.run("build", "-v", "-i", "x/y/bar")
28932930
tg.grepBoth("x/y/foo", "first build -i "+desc+" did not build x/y/foo")
@@ -3067,7 +3104,6 @@ func TestGoVetWithExternalTests(t *testing.T) {
30673104
tg := testgo(t)
30683105
defer tg.cleanup()
30693106
tg.makeTempdir()
3070-
tg.run("install", "cmd/vet")
30713107
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
30723108
tg.runFail("vet", "vetpkg")
30733109
tg.grepBoth("Printf", "go vet vetpkg did not find missing argument for Printf")
@@ -3077,7 +3113,6 @@ func TestGoVetWithTags(t *testing.T) {
30773113
tg := testgo(t)
30783114
defer tg.cleanup()
30793115
tg.makeTempdir()
3080-
tg.run("install", "cmd/vet")
30813116
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
30823117
tg.runFail("vet", "-tags", "tagtest", "vetpkg")
30833118
tg.grepBoth(`c\.go.*Printf`, "go vet vetpkg did not run scan tagged file")
@@ -3087,7 +3122,6 @@ func TestGoVetWithFlagsOn(t *testing.T) {
30873122
tg := testgo(t)
30883123
defer tg.cleanup()
30893124
tg.makeTempdir()
3090-
tg.run("install", "cmd/vet")
30913125
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
30923126
tg.runFail("vet", "-printf", "vetpkg")
30933127
tg.grepBoth("Printf", "go vet -printf vetpkg did not find missing argument for Printf")
@@ -3097,7 +3131,6 @@ func TestGoVetWithFlagsOff(t *testing.T) {
30973131
tg := testgo(t)
30983132
defer tg.cleanup()
30993133
tg.makeTempdir()
3100-
tg.run("install", "cmd/vet")
31013134
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
31023135
tg.run("vet", "-printf=false", "vetpkg")
31033136
}
@@ -4321,9 +4354,7 @@ func TestBuildTagsNoComma(t *testing.T) {
43214354
defer tg.cleanup()
43224355
tg.makeTempdir()
43234356
tg.setenv("GOPATH", tg.path("go"))
4324-
tg.run("install", "-tags", "tag1 tag2", "math")
4325-
tg.runFail("install", "-tags", "tag1,tag2", "math")
4326-
tg.grepBoth("space-separated list contains comma", "-tags with a comma-separated list didn't error")
4357+
tg.run("build", "-tags", "tag1 tag2", "math")
43274358
tg.runFail("build", "-tags", "tag1,tag2", "math")
43284359
tg.grepBoth("space-separated list contains comma", "-tags with a comma-separated list didn't error")
43294360
}
@@ -5172,6 +5203,9 @@ func TestInstallDeps(t *testing.T) {
51725203
tg.mustExist(p2)
51735204
tg.mustNotExist(p1)
51745205

5206+
// don't let install -i overwrite runtime
5207+
tg.wantNotStale("runtime", "", "must be non-stale before install -i")
5208+
51755209
tg.run("install", "-i", "main1")
51765210
tg.mustExist(p1)
51775211
tg.must(os.Remove(p1))

0 commit comments

Comments
 (0)