]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: fix TestExecutableGOROOT when GOROOT_FINAL is set
authorRuss Cox <rsc@golang.org>
Fri, 23 Jun 2017 00:08:00 +0000 (20:08 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 23 Jun 2017 15:35:55 +0000 (15:35 +0000)
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>
src/cmd/go/go_test.go

index 239b9c37a47f0d53aed5d9bc931193192ee65bee..60c0c6f36978cf05f7a4e032a915d8920b98f7ac 100644 (file)
@@ -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) {