diff options
author | Russ Cox <rsc@golang.org> | 2017-06-22 20:08:00 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2017-06-23 15:35:55 +0000 |
commit | c23948a2b83bfbe21d2d721f38a7f18f737ba7bb (patch) | |
tree | ec2f7d54121a1ea0f6b8b9f569c493ecb76c98a4 | |
parent | 3445ece2128b0721cae4f6e84b159539acd314ef (diff) | |
download | go-c23948a2b83bfbe21d2d721f38a7f18f737ba7bb.tar.gz go-c23948a2b83bfbe21d2d721f38a7f18f737ba7bb.zip |
cmd/go: fix TestExecutableGOROOT when GOROOT_FINAL is set
If GOROOT_FINAL was set during the build, the default GOROOT
will not be testGOROOT. Determine the default GOROOT by reading
the right source file instead of guessing. (GOROOT_FINAL may no
longer be set when the test is actually run.)
Also refactor a bit.
Fixes #20284.
Change-Id: I2274595a235bee10c3f3a5ffecf4bb976f4d9982
Reviewed-on: https://go-review.googlesource.com/46428
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
-rw-r--r-- | src/cmd/go/go_test.go | 122 |
1 files changed, 62 insertions, 60 deletions
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 239b9c37a4..60c0c6f369 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -4031,76 +4031,78 @@ func TestExecutableGOROOT(t *testing.T) { t.Skipf("test case does not work on %s, missing os.Executable", runtime.GOOS) } - tg := testgo(t) - defer tg.cleanup() - - tg.makeTempdir() - tg.tempDir("newgoroot/bin") - newGoTool := tg.path("newgoroot/bin/go" + exeSuffix) - err := copyFile(tg.goTool(), newGoTool, 0775) - if err != nil { - t.Fatalf("error copying go tool %v", err) + // Env with no GOROOT. + var env []string + for _, e := range os.Environ() { + if !strings.HasPrefix(e, "GOROOT=") { + env = append(env, e) + } } - goroot := func(goTool string) string { - cmd := exec.Command(goTool, "env", "GOROOT") - cmd.Env = os.Environ() - for i, val := range cmd.Env { - if strings.HasPrefix(val, "GOROOT=") { - cmd.Env = append(cmd.Env[:i], cmd.Env[i+1:]...) - break - } - } + check := func(t *testing.T, exe, want string) { + cmd := exec.Command(exe, "env", "GOROOT") + cmd.Env = env out, err := cmd.CombinedOutput() if err != nil { - t.Fatalf("copied go tool failed %v: %s", err, out) + t.Fatal(err) } - root := strings.TrimSpace(string(out)) - resolved, err := filepath.EvalSymlinks(root) + goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out))) if err != nil { - t.Fatalf("EvalSymlinks(%q) failed: %v", root, err) + t.Fatal(err) + } + want, err = filepath.EvalSymlinks(want) + if err != nil { + t.Fatal(err) + } + if !strings.EqualFold(goroot, want) { + t.Errorf("go env GOROOT:\nhave %s\nwant %s", goroot, want) + } else { + t.Logf("go env GOROOT: %s", goroot) } - return resolved - } - - // Filenames are case insensitive on Windows. - // There should probably be a path/filepath function for this. - equal := func(a, b string) bool { return a == b } - if runtime.GOOS == "windows" { - equal = strings.EqualFold - } - - // macOS uses a symlink for /tmp. - resolvedTestGOROOT, err := filepath.EvalSymlinks(testGOROOT) - if err != nil { - t.Fatalf("could not eval testgoroot symlinks: %v", err) - } - - // Missing GOROOT/pkg/tool, the go tool should fall back to - // its default path. - if got, want := goroot(newGoTool), resolvedTestGOROOT; !equal(got, want) { - t.Fatalf("%s env GOROOT = %q, want %q", newGoTool, got, want) - } - - // Now the executable's path looks like a GOROOT. - tg.tempDir("newgoroot/pkg/tool") - resolvedNewGOROOT, err := filepath.EvalSymlinks(tg.path("newgoroot")) - if err != nil { - t.Fatalf("could not eval newgoroot symlinks: %v", err) - } - if got, want := goroot(newGoTool), resolvedNewGOROOT; !equal(got, want) { - t.Fatalf("%s env GOROOT = %q with pkg/tool, want %q", newGoTool, got, want) } - testenv.MustHaveSymlink(t) - - tg.tempDir("notgoroot/bin") - symGoTool := tg.path("notgoroot/bin/go" + exeSuffix) - tg.must(os.Symlink(newGoTool, symGoTool)) + // Note: Must not call tg methods inside subtests: tg is attached to outer t. + tg := testgo(t) + defer tg.cleanup() - if got, want := goroot(symGoTool), resolvedNewGOROOT; !equal(got, want) { - t.Fatalf("%s env GOROOT = %q, want %q", symGoTool, got, want) - } + tg.makeTempdir() + tg.tempDir("new/bin") + newGoTool := tg.path("new/bin/go" + exeSuffix) + tg.must(copyFile(tg.goTool(), newGoTool, 0775)) + newRoot := tg.path("new") + + t.Run("RelocatedExe", func(t *testing.T) { + // Should fall back to default location in binary. + // No way to dig out other than look at source code. + data, err := ioutil.ReadFile("../../runtime/internal/sys/zversion.go") + if err != nil { + t.Fatal(err) + } + m := regexp.MustCompile("const DefaultGoroot = `([^`]+)`").FindStringSubmatch(string(data)) + if m == nil { + t.Fatal("cannot find DefaultGoroot in ../../runtime/internal/sys/zversion.go") + } + check(t, newGoTool, m[1]) + }) + + // If the binary is sitting in a bin dir next to ../pkg/tool, that counts as a GOROOT, + // so it should find the new tree. + tg.tempDir("new/pkg/tool") + t.Run("RelocatedTree", func(t *testing.T) { + check(t, newGoTool, newRoot) + }) + + tg.tempDir("other/bin") + symGoTool := tg.path("other/bin/go" + exeSuffix) + + // Symlink into go tree should still find go tree. + t.Run("SymlinkedExe", func(t *testing.T) { + testenv.MustHaveSymlink(t) + if err := os.Symlink(newGoTool, symGoTool); err != nil { + t.Fatal(err) + } + check(t, symGoTool, newRoot) + }) } func TestNeedVersion(t *testing.T) { |