From 7dd52f09642e72aa8eda78359919c8129a51819b Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 11 Nov 2019 14:03:26 -0500 Subject: [PATCH] internal/testenv: reject the resolved 'go' command if it does not match runtime.GOROOT Many tests in x/tools invoke the 'go' command found from $PATH. If that command does not match the 'go' command used to invoke 'go test', the result will be misleading. Instead of silently accepting the mismatched result, check the 'go' tool's self-reported GOROOT and reject it if it doesn't match the 'go' tool used to invoke 'go test'. That rejection will cause the x/tools tests to fail if x/tools is the main module. Updates golang/go#35505 Change-Id: I581906468ef736fad42a0164376a07f876907621 Reviewed-on: https://go-review.googlesource.com/c/tools/+/206517 Run-TryBot: Bryan C. Mills Reviewed-by: Jay Conrod --- internal/testenv/testenv.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/internal/testenv/testenv.go b/internal/testenv/testenv.go index 295cc45d3f..0cc90d26a5 100644 --- a/internal/testenv/testenv.go +++ b/internal/testenv/testenv.go @@ -13,6 +13,7 @@ import ( "os/exec" "runtime" "strings" + "sync" ) // Testing is an abstraction of a *testing.T. @@ -32,11 +33,17 @@ type helperer interface { // be development versions. var packageMainIsDevel = func() bool { return true } +var checkGoGoroot struct { + once sync.Once + err error +} + func hasTool(tool string) error { _, err := exec.LookPath(tool) if err != nil { return err } + switch tool { case "patch": // check that the patch tools supports the -o argument @@ -50,7 +57,28 @@ func hasTool(tool string) error { if err := cmd.Run(); err != nil { return err } + + case "go": + checkGoGoroot.once.Do(func() { + // Ensure that the 'go' command found by exec.LookPath is from the correct + // GOROOT. Otherwise, 'some/path/go test ./...' will test against some + // version of the 'go' binary other than 'some/path/go', which is almost + // certainly not what the user intended. + out, err := exec.Command(tool, "env", "GOROOT").CombinedOutput() + if err != nil { + checkGoGoroot.err = err + return + } + GOROOT := strings.TrimSpace(string(out)) + if GOROOT != runtime.GOROOT() { + checkGoGoroot.err = fmt.Errorf("'go env GOROOT' does not match runtime.GOROOT:\n\tgo env: %s\n\tGOROOT: %s", GOROOT, runtime.GOROOT()) + } + }) + if checkGoGoroot.err != nil { + return checkGoGoroot.err + } } + return nil }