diff options
author | Bryan C. Mills <bcmills@google.com> | 2021-10-15 11:35:25 -0400 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2022-08-18 14:52:30 +0000 |
commit | e64c87157d1e8fbc512a670b8c0af8abc3afa7c1 (patch) | |
tree | 7db458aa825bad56d005d1ca5c69b8509b19af98 /src/cmd/go/script_test.go | |
parent | d8f90ce0f8119bf593efb6fb91825de5b61fcda7 (diff) | |
download | go-e64c87157d1e8fbc512a670b8c0af8abc3afa7c1.tar.gz go-e64c87157d1e8fbc512a670b8c0af8abc3afa7c1.zip |
cmd/go: run tests when cmd/go is cross-compiled
When the GOOS or GOARCH of the cmd/go test binary does not match the
GOOS or GOARCH of the installed 'go' binary itself, the test currently
attempts to trick 'go test' into thinking that there were no test
functions to run.
That makes it very difficult to discover how to actually run the
tests, which in turn makes it difficult to diagnose and fix
regressions in, say, the linux-386-longtest builders. (We have had a
few of those lately, and they shouldn't be as much of an ordeal to fix
as they currently are.)
There are three underlying problems:
1. cmd/go uses its own GOOS and GOARCH to figure out which variant of
other tools to use, and the cache keys for all installed tools and
libraries include the IDs of the tools used to build them. So when
cmd/go's GOARCH changes, all installed tools and binaries appear
stale *even if* they were just installed by invoking the native
cmd/go with the appropriate GOARCH value set.
2. The "go/build" library used by cmd/go toggles its default
CGO_ENABLED behavior depending on whether the GOOS and GOARCH being
imported match runtime.GOOS and runtime.GOARCH.
3. A handful of cmd/go tests explicitly use gccgo, but the user's
installed gccgo binary cannot necessarily cross-compile to the same
platforms as cmd/go.
To address the cache-invalidation problem, we modify the test variant
of cmd/go to use the host's native toolchain (as indicated by the new
TESTGO_GOHOSTOS and TESTGO_GOHOSTARCH environment variables) instead
of the toolchain matching the test binary itself. That allows a test
cmd/go binary compiled with GOARCH=386 to use libraries and tools
cross-compiled by the native toolchain, so that
$ GOARCH=386 go install std cmd
suffices to make the packages in std and cmd non-stale in the
tests.
To address the CGO_ENABLED mismatch, we set CGO_ENABLED explicitly in
the test's environment whenever it may differ from the default. Since
script tests that use cgo are already expected to use a [cgo]
condition, setting the environment to match that condition fixes the
cgo-specific tests.
To address the gccgo-specific cross-compilation failures, we add a new
script condition, [cross], which evaluates to true whenever the
platform of the test binary differs from that of the native toolchain.
We can then use that condition to explicitly skip the handful of gccgo
tests that fail under cross-compilation.
Fixes #53936.
Change-Id: I8633944f674eb5941ccc95df928991660e7e8137
Reviewed-on: https://go-review.googlesource.com/c/go/+/356611
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/cmd/go/script_test.go')
-rw-r--r-- | src/cmd/go/script_test.go | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 809dfb452f..e37a7b192b 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -167,11 +167,13 @@ func (ts *testScript) setup() { homeEnvName() + "=/no-home", "CCACHE_DISABLE=1", // ccache breaks with non-existent HOME "GOARCH=" + runtime.GOARCH, + "TESTGO_GOHOSTARCH=" + goHostArch, "GOCACHE=" + testGOCACHE, "GODEBUG=" + os.Getenv("GODEBUG"), "GOEXE=" + cfg.ExeSuffix, "GOEXPERIMENT=" + os.Getenv("GOEXPERIMENT"), "GOOS=" + runtime.GOOS, + "TESTGO_GOHOSTOS=" + goHostOS, "GOPATH=" + filepath.Join(ts.workdir, "gopath"), "GOPROXY=" + proxyURL, "GOPRIVATE=", @@ -200,6 +202,12 @@ func (ts *testScript) setup() { if !testenv.HasExternalNetwork() { ts.env = append(ts.env, "TESTGONETWORK=panic", "TESTGOVCS=panic") } + if os.Getenv("CGO_ENABLED") != "" || runtime.GOOS != goHostOS || runtime.GOARCH != goHostArch { + // If the actual CGO_ENABLED might not match the cmd/go default, set it + // explicitly in the environment. Otherwise, leave it unset so that we also + // cover the default behaviors. + ts.env = append(ts.env, "CGO_ENABLED="+cgoEnabled) + } for _, key := range extraEnvKeys { if val := os.Getenv(key); val != "" { @@ -360,6 +368,8 @@ Script: switch cond.tag { case runtime.GOOS, runtime.GOARCH, runtime.Compiler: ok = true + case "cross": + ok = goHostOS != runtime.GOOS || goHostArch != runtime.GOARCH case "short": ok = testing.Short() case "cgo": @@ -943,9 +953,9 @@ func (ts *testScript) cmdStale(want simpleStatus, args []string) { tmpl := "{{if .Error}}{{.ImportPath}}: {{.Error.Err}}{{else}}" switch want { case failure: - tmpl += "{{if .Stale}}{{.ImportPath}} is unexpectedly stale: {{.StaleReason}}{{end}}" + tmpl += `{{if .Stale}}{{.ImportPath}} ({{.Target}}) is unexpectedly stale:{{"\n\t"}}{{.StaleReason}}{{end}}` case success: - tmpl += "{{if not .Stale}}{{.ImportPath}} is unexpectedly NOT stale{{end}}" + tmpl += "{{if not .Stale}}{{.ImportPath}} ({{.Target}}) is unexpectedly NOT stale{{end}}" default: ts.fatalf("unsupported: %v stale", want) } @@ -953,10 +963,15 @@ func (ts *testScript) cmdStale(want simpleStatus, args []string) { goArgs := append([]string{"list", "-e", "-f=" + tmpl}, args...) stdout, stderr, err := ts.exec(testGo, goArgs...) if err != nil { + // Print stdout before stderr, because stderr may explain the error + // independent of whatever we may have printed to stdout. ts.fatalf("go list: %v\n%s%s", err, stdout, stderr) } if stdout != "" { - ts.fatalf("%s", stdout) + // Print stderr before stdout, because stderr may contain verbose + // debugging info (for example, if GODEBUG=gocachehash=1 is set) + // and we know that stdout contains a useful summary. + ts.fatalf("%s%s", stderr, stdout) } } |