]> Cypherpunks repositories - gostls13.git/commitdiff
misc/cgo/testshared: fix tests in module mode
authorBryan C. Mills <bcmills@google.com>
Thu, 21 Feb 2019 19:17:19 +0000 (14:17 -0500)
committerBryan C. Mills <bcmills@google.com>
Fri, 22 Feb 2019 21:57:16 +0000 (21:57 +0000)
Updates #30228

Change-Id: I5cc739eb9fdfb648ec45e350d43d4cb02e450553
Reviewed-on: https://go-review.googlesource.com/c/163211
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Jay Conrod <jayconrod@google.com>
24 files changed:
misc/cgo/testshared/overlaydir_test.go [new file with mode: 0644]
misc/cgo/testshared/shared_test.go
misc/cgo/testshared/testdata/dep2/dep2.go [moved from misc/cgo/testshared/src/dep2/dep2.go with 82% similarity]
misc/cgo/testshared/testdata/dep3/dep3.go [moved from misc/cgo/testshared/src/dep3/dep3.go with 91% similarity]
misc/cgo/testshared/testdata/depBase/asm.s [moved from misc/cgo/testshared/src/depBase/asm.s with 100% similarity]
misc/cgo/testshared/testdata/depBase/dep.go [moved from misc/cgo/testshared/src/depBase/dep.go with 100% similarity]
misc/cgo/testshared/testdata/depBase/gccgo.go [moved from misc/cgo/testshared/src/depBase/gccgo.go with 100% similarity]
misc/cgo/testshared/testdata/depBase/stubs.go [moved from misc/cgo/testshared/src/depBase/stubs.go with 100% similarity]
misc/cgo/testshared/testdata/division/division.go [moved from misc/cgo/testshared/src/division/division.go with 100% similarity]
misc/cgo/testshared/testdata/exe/exe.go [moved from misc/cgo/testshared/src/exe/exe.go with 97% similarity]
misc/cgo/testshared/testdata/exe2/exe2.go [moved from misc/cgo/testshared/src/exe2/exe2.go with 77% similarity]
misc/cgo/testshared/testdata/exe3/exe3.go [moved from misc/cgo/testshared/src/exe3/exe3.go with 62% similarity]
misc/cgo/testshared/testdata/execgo/exe.go [moved from misc/cgo/testshared/src/execgo/exe.go with 100% similarity]
misc/cgo/testshared/testdata/explicit/explicit.go [moved from misc/cgo/testshared/src/explicit/explicit.go with 74% similarity]
misc/cgo/testshared/testdata/global/main.go [moved from misc/cgo/testshared/src/global/main.go with 98% similarity]
misc/cgo/testshared/testdata/globallib/global.go [moved from misc/cgo/testshared/src/globallib/global.go with 100% similarity]
misc/cgo/testshared/testdata/iface/main.go [moved from misc/cgo/testshared/src/iface/main.go with 85% similarity]
misc/cgo/testshared/testdata/iface_a/a.go [moved from misc/cgo/testshared/src/iface_a/a.go with 91% similarity]
misc/cgo/testshared/testdata/iface_b/b.go [moved from misc/cgo/testshared/src/iface_b/b.go with 91% similarity]
misc/cgo/testshared/testdata/iface_i/i.go [moved from misc/cgo/testshared/src/iface_i/i.go with 100% similarity]
misc/cgo/testshared/testdata/implicit/implicit.go [moved from misc/cgo/testshared/src/implicit/implicit.go with 100% similarity]
misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go [moved from misc/cgo/testshared/src/implicitcmd/implicitcmd.go with 63% similarity]
misc/cgo/testshared/testdata/issue25065/a.go [moved from misc/cgo/testshared/src/issue25065/a.go with 100% similarity]
misc/cgo/testshared/testdata/trivial/trivial.go [moved from misc/cgo/testshared/src/trivial/trivial.go with 100% similarity]

diff --git a/misc/cgo/testshared/overlaydir_test.go b/misc/cgo/testshared/overlaydir_test.go
new file mode 100644 (file)
index 0000000..68be056
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package shared_test
+
+import (
+       "io"
+       "os"
+       "path/filepath"
+       "strings"
+)
+
+// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added.
+//
+// TODO: Once we no longer need to support the misc module in GOPATH mode,
+// factor this function out into a package to reduce duplication.
+func overlayDir(dstRoot, srcRoot string) error {
+       dstRoot = filepath.Clean(dstRoot)
+       if err := os.MkdirAll(dstRoot, 0777); err != nil {
+               return err
+       }
+
+       symBase, err := filepath.Rel(srcRoot, dstRoot)
+       if err != nil {
+               symBase, err = filepath.Abs(srcRoot)
+               if err != nil {
+                       return err
+               }
+       }
+
+       return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
+               if err != nil || srcPath == srcRoot {
+                       return err
+               }
+
+               suffix := strings.TrimPrefix(srcPath, srcRoot)
+               for len(suffix) > 0 && suffix[0] == filepath.Separator {
+                       suffix = suffix[1:]
+               }
+               dstPath := filepath.Join(dstRoot, suffix)
+
+               perm := info.Mode() & os.ModePerm
+               if info.Mode()&os.ModeSymlink != 0 {
+                       info, err = os.Stat(srcPath)
+                       if err != nil {
+                               return err
+                       }
+                       perm = info.Mode() & os.ModePerm
+               }
+
+               // Always copy directories (don't symlink them).
+               // If we add a file in the overlay, we don't want to add it in the original.
+               if info.IsDir() {
+                       return os.Mkdir(dstPath, perm)
+               }
+
+               // If the OS supports symlinks, use them instead of copying bytes.
+               if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
+                       return nil
+               }
+
+               // Otherwise, copy the bytes.
+               src, err := os.Open(srcPath)
+               if err != nil {
+                       return err
+               }
+               defer src.Close()
+
+               dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
+               if err != nil {
+                       return err
+               }
+
+               _, err = io.Copy(dst, src)
+               if closeErr := dst.Close(); err == nil {
+                       err = closeErr
+               }
+               return err
+       })
+}
index 41a24efe22c0ed97cdb9f13cb99ad79dce9dc9a2..9a8c3989762d19a3ff4e79affdcbe8d0cd88eecf 100644 (file)
@@ -44,31 +44,35 @@ func run(t *testing.T, msg string, args ...string) {
 
 // goCmd invokes the go tool with the installsuffix set up by TestMain. It calls
 // t.Fatalf if the command fails.
-func goCmd(t *testing.T, args ...string) {
+func goCmd(t *testing.T, args ...string) string {
        newargs := []string{args[0], "-installsuffix=" + suffix}
        if testing.Verbose() {
                newargs = append(newargs, "-x")
        }
        newargs = append(newargs, args[1:]...)
        c := exec.Command("go", newargs...)
+
+       stderr := new(strings.Builder)
        var output []byte
        var err error
        if testing.Verbose() {
-               fmt.Printf("+ go %s\n", strings.Join(newargs, " "))
-               c.Stdout = os.Stdout
+               fmt.Printf("+ go %s\n", strings.Join(args, " "))
                c.Stderr = os.Stderr
-               err = c.Run()
-               output = []byte("(output above)")
+               stderr.WriteString("(output above)")
        } else {
-               output, err = c.CombinedOutput()
+               c.Stderr = stderr
        }
+       output, err = c.Output()
+
        if err != nil {
                if t != nil {
-                       t.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, output)
+                       t.Helper()
+                       t.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr)
                } else {
-                       log.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, output)
+                       log.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr)
                }
        }
+       return string(bytes.TrimSpace(output))
 }
 
 // TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit).
@@ -105,47 +109,32 @@ func testMain(m *testing.M) (int, error) {
 
        // Some tests need to edit the source in GOPATH, so copy this directory to a
        // temporary directory and chdir to that.
-       scratchDir, err := ioutil.TempDir("", "testshared")
+       gopath, err := ioutil.TempDir("", "testshared")
        if err != nil {
                return 0, fmt.Errorf("TempDir failed: %v", err)
        }
        if testing.Verbose() {
-               fmt.Printf("+ mkdir -p %s\n", scratchDir)
-       }
-       defer os.RemoveAll(scratchDir)
-       err = filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
-               scratchPath := filepath.Join(scratchDir, path)
-               if info.IsDir() {
-                       if path == "." {
-                               return nil
-                       }
-                       if testing.Verbose() {
-                               fmt.Printf("+ mkdir -p %s\n", scratchPath)
-                       }
-                       return os.Mkdir(scratchPath, info.Mode())
-               } else {
-                       fromBytes, err := ioutil.ReadFile(path)
-                       if err != nil {
-                               return err
-                       }
-                       if testing.Verbose() {
-                               fmt.Printf("+ cp %s %s\n", path, scratchPath)
-                       }
-                       return ioutil.WriteFile(scratchPath, fromBytes, info.Mode())
-               }
-       })
-       if err != nil {
-               return 0, fmt.Errorf("walk failed: %v", err)
+               fmt.Printf("+ mkdir -p %s\n", gopath)
+       }
+       defer os.RemoveAll(gopath)
+
+       modRoot := filepath.Join(gopath, "src", "testshared")
+       if err := overlayDir(modRoot, "testdata"); err != nil {
+               return 0, err
        }
-       os.Setenv("GOPATH", scratchDir)
        if testing.Verbose() {
-               fmt.Printf("+ export GOPATH=%s\n", scratchDir)
+               fmt.Printf("+ cd %s\n", modRoot)
+       }
+       os.Chdir(modRoot)
+       if err := ioutil.WriteFile("go.mod", []byte("module testshared\n"), 0666); err != nil {
+               return 0, err
        }
-       myContext.GOPATH = scratchDir
+
+       os.Setenv("GOPATH", gopath)
        if testing.Verbose() {
-               fmt.Printf("+ cd %s\n", scratchDir)
+               fmt.Printf("+ export GOPATH=%s\n", gopath)
        }
-       os.Chdir(scratchDir)
+       myContext.GOPATH = gopath
 
        // All tests depend on runtime being built into a shared library. Because
        // that takes a few seconds, do it here and have all tests use the version
@@ -154,15 +143,20 @@ func testMain(m *testing.M) (int, error) {
        goCmd(nil, append([]string{"install", "-buildmode=shared"}, minpkgs...)...)
 
        myContext.InstallSuffix = suffix + "_dynlink"
-       depP, err := myContext.Import("depBase", ".", build.ImportComment)
+       depP, err := myContext.Import("./depBase", ".", build.ImportComment)
        if err != nil {
                return 0, fmt.Errorf("import failed: %v", err)
        }
-       gopathInstallDir = depP.PkgTargetRoot
+       if depP.PkgTargetRoot == "" {
+               gopathInstallDir = filepath.Dir(goCmd(nil, "list", "-buildmode=shared", "-f", "{{.Target}}", "./depBase"))
+       } else {
+               gopathInstallDir = filepath.Join(depP.PkgTargetRoot, "testshared")
+       }
        return m.Run(), nil
 }
 
 func TestMain(m *testing.M) {
+       log.SetFlags(log.Lshortfile)
        flag.Parse()
 
        // Some of the tests install binaries into a custom GOPATH.
@@ -350,6 +344,7 @@ func readNotes(f *elf.File) ([]*note, error) {
 }
 
 func dynStrings(t *testing.T, path string, flag elf.DynTag) []string {
+       t.Helper()
        f, err := elf.Open(path)
        if err != nil {
                t.Fatalf("elf.Open(%q) failed: %v", path, err)
@@ -363,6 +358,7 @@ func dynStrings(t *testing.T, path string, flag elf.DynTag) []string {
 }
 
 func AssertIsLinkedToRegexp(t *testing.T, path string, re *regexp.Regexp) {
+       t.Helper()
        for _, dynstring := range dynStrings(t, path, elf.DT_NEEDED) {
                if re.MatchString(dynstring) {
                        return
@@ -372,10 +368,12 @@ func AssertIsLinkedToRegexp(t *testing.T, path string, re *regexp.Regexp) {
 }
 
 func AssertIsLinkedTo(t *testing.T, path, lib string) {
+       t.Helper()
        AssertIsLinkedToRegexp(t, path, regexp.MustCompile(regexp.QuoteMeta(lib)))
 }
 
 func AssertHasRPath(t *testing.T, path, dir string) {
+       t.Helper()
        for _, tag := range []elf.DynTag{elf.DT_RPATH, elf.DT_RUNPATH} {
                for _, dynstring := range dynStrings(t, path, tag) {
                        for _, rpath := range strings.Split(dynstring, ":") {
@@ -390,15 +388,15 @@ func AssertHasRPath(t *testing.T, path, dir string) {
 
 // Build a trivial program that links against the shared runtime and check it runs.
 func TestTrivialExecutable(t *testing.T) {
-       goCmd(t, "install", "-linkshared", "trivial")
-       run(t, "trivial executable", "./bin/trivial")
-       AssertIsLinkedTo(t, "./bin/trivial", soname)
-       AssertHasRPath(t, "./bin/trivial", gorootInstallDir)
+       goCmd(t, "install", "-linkshared", "./trivial")
+       run(t, "trivial executable", "../../bin/trivial")
+       AssertIsLinkedTo(t, "../../bin/trivial", soname)
+       AssertHasRPath(t, "../../bin/trivial", gorootInstallDir)
 }
 
 // Build a trivial program in PIE mode that links against the shared runtime and check it runs.
 func TestTrivialExecutablePIE(t *testing.T) {
-       goCmd(t, "build", "-buildmode=pie", "-o", "trivial.pie", "-linkshared", "trivial")
+       goCmd(t, "build", "-buildmode=pie", "-o", "trivial.pie", "-linkshared", "./trivial")
        run(t, "trivial executable", "./trivial.pie")
        AssertIsLinkedTo(t, "./trivial.pie", soname)
        AssertHasRPath(t, "./trivial.pie", gorootInstallDir)
@@ -406,15 +404,15 @@ func TestTrivialExecutablePIE(t *testing.T) {
 
 // Build a division test program and check it runs.
 func TestDivisionExecutable(t *testing.T) {
-       goCmd(t, "install", "-linkshared", "division")
-       run(t, "division executable", "./bin/division")
+       goCmd(t, "install", "-linkshared", "./division")
+       run(t, "division executable", "../../bin/division")
 }
 
 // Build an executable that uses cgo linked against the shared runtime and check it
 // runs.
 func TestCgoExecutable(t *testing.T) {
-       goCmd(t, "install", "-linkshared", "execgo")
-       run(t, "cgo executable", "./bin/execgo")
+       goCmd(t, "install", "-linkshared", "./execgo")
+       run(t, "cgo executable", "../../bin/execgo")
 }
 
 func checkPIE(t *testing.T, name string) {
@@ -433,7 +431,7 @@ func checkPIE(t *testing.T, name string) {
 
 func TestTrivialPIE(t *testing.T) {
        name := "trivial_pie"
-       goCmd(t, "build", "-buildmode=pie", "-o="+name, "trivial")
+       goCmd(t, "build", "-buildmode=pie", "-o="+name, "./trivial")
        defer os.Remove(name)
        run(t, name, "./"+name)
        checkPIE(t, name)
@@ -441,7 +439,7 @@ func TestTrivialPIE(t *testing.T) {
 
 func TestCgoPIE(t *testing.T) {
        name := "cgo_pie"
-       goCmd(t, "build", "-buildmode=pie", "-o="+name, "execgo")
+       goCmd(t, "build", "-buildmode=pie", "-o="+name, "./execgo")
        defer os.Remove(name)
        run(t, name, "./"+name)
        checkPIE(t, name)
@@ -450,15 +448,16 @@ func TestCgoPIE(t *testing.T) {
 // Build a GOPATH package into a shared library that links against the goroot runtime
 // and an executable that links against both.
 func TestGopathShlib(t *testing.T) {
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
-       AssertIsLinkedTo(t, filepath.Join(gopathInstallDir, "libdepBase.so"), soname)
-       goCmd(t, "install", "-linkshared", "exe")
-       AssertIsLinkedTo(t, "./bin/exe", soname)
-       AssertIsLinkedTo(t, "./bin/exe", "libdepBase.so")
-       AssertHasRPath(t, "./bin/exe", gorootInstallDir)
-       AssertHasRPath(t, "./bin/exe", gopathInstallDir)
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase")
+       shlib := goCmd(t, "list", "-f", "{{.Shlib}}", "-buildmode=shared", "-linkshared", "./depBase")
+       AssertIsLinkedTo(t, shlib, soname)
+       goCmd(t, "install", "-linkshared", "./exe")
+       AssertIsLinkedTo(t, "../../bin/exe", soname)
+       AssertIsLinkedTo(t, "../../bin/exe", filepath.Base(shlib))
+       AssertHasRPath(t, "../../bin/exe", gorootInstallDir)
+       AssertHasRPath(t, "../../bin/exe", filepath.Dir(gopathInstallDir))
        // And check it runs.
-       run(t, "executable linked to GOPATH library", "./bin/exe")
+       run(t, "executable linked to GOPATH library", "../../bin/exe")
 }
 
 // The shared library contains a note listing the packages it contains in a section
@@ -470,8 +469,8 @@ func testPkgListNote(t *testing.T, f *elf.File, note *note) {
        if isOffsetLoaded(f, note.section.Offset) {
                t.Errorf("package list section contained in PT_LOAD segment")
        }
-       if note.desc != "depBase\n" {
-               t.Errorf("incorrect package list %q, want %q", note.desc, "depBase\n")
+       if note.desc != "testshared/depBase\n" {
+               t.Errorf("incorrect package list %q, want %q", note.desc, "testshared/depBase\n")
        }
 }
 
@@ -528,8 +527,9 @@ func testDepsNote(t *testing.T, f *elf.File, note *note) {
 
 // The shared library contains notes with defined contents; see above.
 func TestNotes(t *testing.T) {
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
-       f, err := elf.Open(filepath.Join(gopathInstallDir, "libdepBase.so"))
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase")
+       shlib := goCmd(t, "list", "-f", "{{.Shlib}}", "-buildmode=shared", "-linkshared", "./depBase")
+       f, err := elf.Open(shlib)
        if err != nil {
                t.Fatal(err)
        }
@@ -581,23 +581,24 @@ func TestNotes(t *testing.T) {
 // runtime, another package (dep2) that links against the first, and an
 // executable that links against dep2.
 func TestTwoGopathShlibs(t *testing.T) {
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "dep2")
-       goCmd(t, "install", "-linkshared", "exe2")
-       run(t, "executable linked to GOPATH library", "./bin/exe2")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep2")
+       goCmd(t, "install", "-linkshared", "./exe2")
+       run(t, "executable linked to GOPATH library", "../../bin/exe2")
 }
 
 func TestThreeGopathShlibs(t *testing.T) {
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "dep2")
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "dep3")
-       goCmd(t, "install", "-linkshared", "exe3")
-       run(t, "executable linked to GOPATH library", "./bin/exe3")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep2")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep3")
+       goCmd(t, "install", "-linkshared", "./exe3")
+       run(t, "executable linked to GOPATH library", "../../bin/exe3")
 }
 
-// If gccgo is not available or not new enough call t.Skip. Otherwise,
-// return a build.Context that is set up for gccgo.
-func prepGccgo(t *testing.T) build.Context {
+// If gccgo is not available or not new enough, call t.Skip.
+func requireGccgo(t *testing.T) {
+       t.Helper()
+
        gccgoName := os.Getenv("GCCGO")
        if gccgoName == "" {
                gccgoName = "gccgo"
@@ -614,61 +615,64 @@ func prepGccgo(t *testing.T) build.Context {
        if string(output) < "5" {
                t.Skipf("gccgo too old (%s)", strings.TrimSpace(string(output)))
        }
-       gccgoContext := build.Default
-       gccgoContext.InstallSuffix = suffix + "_fPIC"
-       gccgoContext.Compiler = "gccgo"
-       gccgoContext.GOPATH = os.Getenv("GOPATH")
-       return gccgoContext
+
+       gomod, err := exec.Command("go", "env", "GOMOD").Output()
+       if err != nil {
+               t.Fatalf("go env GOMOD: %v", err)
+       }
+       if len(bytes.TrimSpace(gomod)) > 0 {
+               t.Skipf("gccgo not supported in module mode; see golang.org/issue/30344")
+       }
 }
 
 // Build a GOPATH package into a shared library with gccgo and an executable that
 // links against it.
 func TestGoPathShlibGccgo(t *testing.T) {
-       gccgoContext := prepGccgo(t)
+       requireGccgo(t)
 
        libgoRE := regexp.MustCompile("libgo.so.[0-9]+")
 
-       depP, err := gccgoContext.Import("depBase", ".", build.ImportComment)
-       if err != nil {
-               t.Fatalf("import failed: %v", err)
-       }
-       gccgoInstallDir := filepath.Join(depP.PkgTargetRoot, "shlibs")
-       goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "depBase")
-       AssertIsLinkedToRegexp(t, filepath.Join(gccgoInstallDir, "libdepBase.so"), libgoRE)
-       goCmd(t, "install", "-compiler=gccgo", "-linkshared", "exe")
-       AssertIsLinkedToRegexp(t, "./bin/exe", libgoRE)
-       AssertIsLinkedTo(t, "./bin/exe", "libdepBase.so")
-       AssertHasRPath(t, "./bin/exe", gccgoInstallDir)
+       goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./depBase")
+
+       // Run 'go list' after 'go install': with gccgo, we apparently don't know the
+       // shlib location until after we've installed it.
+       shlib := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./depBase")
+
+       AssertIsLinkedToRegexp(t, shlib, libgoRE)
+       goCmd(t, "install", "-compiler=gccgo", "-linkshared", "./exe")
+       AssertIsLinkedToRegexp(t, "../../bin/exe", libgoRE)
+       AssertIsLinkedTo(t, "../../bin/exe", filepath.Base(shlib))
+       AssertHasRPath(t, "../../bin/exe", filepath.Dir(shlib))
        // And check it runs.
-       run(t, "gccgo-built", "./bin/exe")
+       run(t, "gccgo-built", "../../bin/exe")
 }
 
 // The gccgo version of TestTwoGopathShlibs: build a GOPATH package into a shared
 // library with gccgo, another GOPATH package that depends on the first and an
 // executable that links the second library.
 func TestTwoGopathShlibsGccgo(t *testing.T) {
-       gccgoContext := prepGccgo(t)
+       requireGccgo(t)
 
        libgoRE := regexp.MustCompile("libgo.so.[0-9]+")
 
-       depP, err := gccgoContext.Import("depBase", ".", build.ImportComment)
-       if err != nil {
-               t.Fatalf("import failed: %v", err)
-       }
-       gccgoInstallDir := filepath.Join(depP.PkgTargetRoot, "shlibs")
-       goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "depBase")
-       goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "dep2")
-       goCmd(t, "install", "-compiler=gccgo", "-linkshared", "exe2")
+       goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./depBase")
+       goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./dep2")
+       goCmd(t, "install", "-compiler=gccgo", "-linkshared", "./exe2")
+
+       // Run 'go list' after 'go install': with gccgo, we apparently don't know the
+       // shlib location until after we've installed it.
+       dep2 := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./dep2")
+       depBase := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./depBase")
 
-       AssertIsLinkedToRegexp(t, filepath.Join(gccgoInstallDir, "libdepBase.so"), libgoRE)
-       AssertIsLinkedToRegexp(t, filepath.Join(gccgoInstallDir, "libdep2.so"), libgoRE)
-       AssertIsLinkedTo(t, filepath.Join(gccgoInstallDir, "libdep2.so"), "libdepBase.so")
-       AssertIsLinkedToRegexp(t, "./bin/exe2", libgoRE)
-       AssertIsLinkedTo(t, "./bin/exe2", "libdep2")
-       AssertIsLinkedTo(t, "./bin/exe2", "libdepBase.so")
+       AssertIsLinkedToRegexp(t, depBase, libgoRE)
+       AssertIsLinkedToRegexp(t, dep2, libgoRE)
+       AssertIsLinkedTo(t, dep2, filepath.Base(depBase))
+       AssertIsLinkedToRegexp(t, "../../bin/exe2", libgoRE)
+       AssertIsLinkedTo(t, "../../bin/exe2", filepath.Base(dep2))
+       AssertIsLinkedTo(t, "../../bin/exe2", filepath.Base(depBase))
 
        // And check it runs.
-       run(t, "gccgo-built", "./bin/exe2")
+       run(t, "gccgo-built", "../../bin/exe2")
 }
 
 // Testing rebuilding of shared libraries when they are stale is a bit more
@@ -694,9 +698,9 @@ func resetFileStamps() {
                }
 
        }
-       reset("bin")
-       reset("pkg")
-       reset("src")
+       reset("../../bin")
+       reset("../../pkg")
+       reset("../../src")
        reset(gorootInstallDir)
 }
 
@@ -746,6 +750,7 @@ func touch(t *testing.T, path string) (cleanup func()) {
 
 // isNew returns if the path is newer than the time stamp used by touch.
 func isNew(t *testing.T, path string) bool {
+       t.Helper()
        fi, err := os.Stat(path)
        if err != nil {
                t.Fatal(err)
@@ -771,40 +776,47 @@ func AssertNotRebuilt(t *testing.T, msg, path string) {
 }
 
 func TestRebuilding(t *testing.T) {
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
-       goCmd(t, "install", "-linkshared", "exe")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase")
+       goCmd(t, "install", "-linkshared", "./exe")
+       info := strings.Fields(goCmd(t, "list", "-buildmode=shared", "-linkshared", "-f", "{{.Target}} {{.Shlib}}", "./depBase"))
+       if len(info) != 2 {
+               t.Fatalf("go list failed to report Target and/or Shlib")
+       }
+       target := info[0]
+       shlib := info[1]
 
        // If the source is newer than both the .a file and the .so, both are rebuilt.
        t.Run("newsource", func(t *testing.T) {
                resetFileStamps()
-               cleanup := touch(t, "src/depBase/dep.go")
+               cleanup := touch(t, "./depBase/dep.go")
                defer func() {
                        cleanup()
-                       goCmd(t, "install", "-linkshared", "exe")
+                       goCmd(t, "install", "-linkshared", "./exe")
                }()
-               goCmd(t, "install", "-linkshared", "exe")
-               AssertRebuilt(t, "new source", filepath.Join(gopathInstallDir, "depBase.a"))
-               AssertRebuilt(t, "new source", filepath.Join(gopathInstallDir, "libdepBase.so"))
+               goCmd(t, "install", "-linkshared", "./exe")
+               AssertRebuilt(t, "new source", target)
+               AssertRebuilt(t, "new source", shlib)
        })
 
        // If the .a file is newer than the .so, the .so is rebuilt (but not the .a)
        t.Run("newarchive", func(t *testing.T) {
                resetFileStamps()
-               AssertNotRebuilt(t, "new .a file before build", filepath.Join(gopathInstallDir, "depBase.a"))
-               goCmd(t, "list", "-linkshared", "-f={{.ImportPath}} {{.Stale}} {{.StaleReason}} {{.Target}}", "depBase")
-               AssertNotRebuilt(t, "new .a file before build", filepath.Join(gopathInstallDir, "depBase.a"))
-               cleanup := touch(t, filepath.Join(gopathInstallDir, "depBase.a"))
+               AssertNotRebuilt(t, "new .a file before build", target)
+               goCmd(t, "list", "-linkshared", "-f={{.ImportPath}} {{.Stale}} {{.StaleReason}} {{.Target}}", "./depBase")
+               AssertNotRebuilt(t, "new .a file before build", target)
+               cleanup := touch(t, target)
                defer func() {
                        cleanup()
-                       goCmd(t, "install", "-v", "-linkshared", "exe")
+                       goCmd(t, "install", "-v", "-linkshared", "./exe")
                }()
-               goCmd(t, "install", "-v", "-linkshared", "exe")
-               AssertNotRebuilt(t, "new .a file", filepath.Join(gopathInstallDir, "depBase.a"))
-               AssertRebuilt(t, "new .a file", filepath.Join(gopathInstallDir, "libdepBase.so"))
+               goCmd(t, "install", "-v", "-linkshared", "./exe")
+               AssertNotRebuilt(t, "new .a file", target)
+               AssertRebuilt(t, "new .a file", shlib)
        })
 }
 
 func appendFile(t *testing.T, path, content string) {
+       t.Helper()
        f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0660)
        if err != nil {
                t.Fatalf("os.OpenFile failed: %v", err)
@@ -821,16 +833,24 @@ func appendFile(t *testing.T, path, content string) {
        }
 }
 
-func writeFile(t *testing.T, path, content string) {
-       err := ioutil.WriteFile(path, []byte(content), 0644)
+func createFile(t *testing.T, path, content string) {
+       t.Helper()
+       f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
        if err != nil {
-               t.Fatalf("ioutil.WriteFile failed: %v", err)
+               t.Fatalf("os.OpenFile failed: %v", err)
+       }
+       _, err = f.WriteString(content)
+       if closeErr := f.Close(); err == nil {
+               err = closeErr
+       }
+       if err != nil {
+               t.Fatalf("WriteString failed: %v", err)
        }
 }
 
 func TestABIChecking(t *testing.T) {
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
-       goCmd(t, "install", "-linkshared", "exe")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase")
+       goCmd(t, "install", "-linkshared", "./exe")
 
        // If we make an ABI-breaking change to depBase and rebuild libp.so but not exe,
        // exe will abort with a complaint on startup.
@@ -838,18 +858,21 @@ func TestABIChecking(t *testing.T) {
        // some senses but suffices for the narrow definition of ABI compatibility the
        // toolchain uses today.
        resetFileStamps()
-       appendFile(t, "src/depBase/dep.go", "func ABIBreak() {}\n")
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
-       c := exec.Command("./bin/exe")
+
+       createFile(t, "./depBase/break.go", "package depBase\nfunc ABIBreak() {}\n")
+       defer os.Remove("./depBase/break.go")
+
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase")
+       c := exec.Command("../../bin/exe")
        output, err := c.CombinedOutput()
        if err == nil {
                t.Fatal("executing exe did not fail after ABI break")
        }
        scanner := bufio.NewScanner(bytes.NewReader(output))
        foundMsg := false
-       const wantLine = "abi mismatch detected between the executable and libdepBase.so"
+       const wantPrefix = "abi mismatch detected between the executable and lib"
        for scanner.Scan() {
-               if scanner.Text() == wantLine {
+               if strings.HasPrefix(scanner.Text(), wantPrefix) {
                        foundMsg = true
                        break
                }
@@ -858,20 +881,20 @@ func TestABIChecking(t *testing.T) {
                t.Errorf("scanner encountered error: %v", err)
        }
        if !foundMsg {
-               t.Fatalf("exe failed, but without line %q; got output:\n%s", wantLine, output)
+               t.Fatalf("exe failed, but without line %q; got output:\n%s", wantPrefix, output)
        }
 
        // Rebuilding exe makes it work again.
-       goCmd(t, "install", "-linkshared", "exe")
-       run(t, "rebuilt exe", "./bin/exe")
+       goCmd(t, "install", "-linkshared", "./exe")
+       run(t, "rebuilt exe", "../../bin/exe")
 
        // If we make a change which does not break ABI (such as adding an unexported
        // function) and rebuild libdepBase.so, exe still works, even if new function
        // is in a file by itself.
        resetFileStamps()
-       writeFile(t, "src/depBase/dep2.go", "package depBase\nfunc noABIBreak() {}\n")
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
-       run(t, "after non-ABI breaking change", "./bin/exe")
+       createFile(t, "./depBase/dep2.go", "package depBase\nfunc noABIBreak() {}\n")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase")
+       run(t, "after non-ABI breaking change", "../../bin/exe")
 }
 
 // If a package 'explicit' imports a package 'implicit', building
@@ -881,29 +904,29 @@ func TestABIChecking(t *testing.T) {
 // executable rather than fetching it from the shared library. The
 // link still succeeds and the executable still runs though.
 func TestImplicitInclusion(t *testing.T) {
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "explicit")
-       goCmd(t, "install", "-linkshared", "implicitcmd")
-       run(t, "running executable linked against library that contains same package as it", "./bin/implicitcmd")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./explicit")
+       goCmd(t, "install", "-linkshared", "./implicitcmd")
+       run(t, "running executable linked against library that contains same package as it", "../../bin/implicitcmd")
 }
 
 // Tests to make sure that the type fields of empty interfaces and itab
 // fields of nonempty interfaces are unique even across modules,
 // so that interface equality works correctly.
 func TestInterface(t *testing.T) {
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "iface_a")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./iface_a")
        // Note: iface_i gets installed implicitly as a dependency of iface_a.
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "iface_b")
-       goCmd(t, "install", "-linkshared", "iface")
-       run(t, "running type/itab uniqueness tester", "./bin/iface")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./iface_b")
+       goCmd(t, "install", "-linkshared", "./iface")
+       run(t, "running type/itab uniqueness tester", "../../bin/iface")
 }
 
 // Access a global variable from a library.
 func TestGlobal(t *testing.T) {
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "globallib")
-       goCmd(t, "install", "-linkshared", "global")
-       run(t, "global executable", "./bin/global")
-       AssertIsLinkedTo(t, "./bin/global", soname)
-       AssertHasRPath(t, "./bin/global", gorootInstallDir)
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./globallib")
+       goCmd(t, "install", "-linkshared", "./global")
+       run(t, "global executable", "../../bin/global")
+       AssertIsLinkedTo(t, "../../bin/global", soname)
+       AssertHasRPath(t, "../../bin/global", gorootInstallDir)
 }
 
 // Run a test using -linkshared of an installed shared package.
@@ -915,5 +938,5 @@ func TestTestInstalledShared(t *testing.T) {
 // Test generated pointer method with -linkshared.
 // Issue 25065.
 func TestGeneratedMethod(t *testing.T) {
-       goCmd(t, "install", "-buildmode=shared", "-linkshared", "issue25065")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue25065")
 }
similarity index 82%
rename from misc/cgo/testshared/src/dep2/dep2.go
rename to misc/cgo/testshared/testdata/dep2/dep2.go
index c2c812adb9b4311cfba33f87de876d3d738de7ef..94f38cf507f3fa1047b75eecfe90ff95638fe5f3 100644 (file)
@@ -1,6 +1,6 @@
 package dep2
 
-import "depBase"
+import "testshared/depBase"
 
 var W int = 1
 
similarity index 91%
rename from misc/cgo/testshared/src/dep3/dep3.go
rename to misc/cgo/testshared/testdata/dep3/dep3.go
index 7b7c9dac1f9c1f035f7ddb7a08e574d308cf5795..6b02ad2ee5b97dae33373421c6bd8c3b8f616623 100644 (file)
@@ -7,8 +7,8 @@ package dep3
 // the type data in this case and later crash.
 
 import (
-       "dep2"
-       "depBase"
+       "testshared/dep2"
+       "testshared/depBase"
 )
 
 type Dep3 struct {
similarity index 97%
rename from misc/cgo/testshared/src/exe/exe.go
rename to misc/cgo/testshared/testdata/exe/exe.go
index bd864d88ad8435f15769e759375759e99daf20ea..86582581a6b1e082ed18c43a1e71d25f68f24646 100644 (file)
@@ -1,7 +1,7 @@
 package main
 
 import (
-       "depBase"
+       "testshared/depBase"
        "os"
        "reflect"
        "runtime"
similarity index 77%
rename from misc/cgo/testshared/src/exe2/exe2.go
rename to misc/cgo/testshared/testdata/exe2/exe2.go
index 675fd1f365cc665b8db52c80db0eed6ab3dd2890..433f331e369de6e4cf09b7fec1685d09c054cc99 100644 (file)
@@ -1,6 +1,6 @@
 package main
 
-import "dep2"
+import "testshared/dep2"
 
 func main() {
        d := &dep2.Dep2{}
similarity index 62%
rename from misc/cgo/testshared/src/exe3/exe3.go
rename to misc/cgo/testshared/testdata/exe3/exe3.go
index 643f2605f6600cbd0ba6bbf18d1b6017d7051164..533e3a9e3dd1c051659e681f8233b0885effce0d 100644 (file)
@@ -1,6 +1,6 @@
 package main
 
-import "dep3"
+import "testshared/dep3"
 
 func main() {
        dep3.D3()
similarity index 74%
rename from misc/cgo/testshared/src/explicit/explicit.go
rename to misc/cgo/testshared/testdata/explicit/explicit.go
index 6a4453f775861743074e2185f64ca6093f6c74cf..af969fcb23a8febb5827916cc2967add8ede7187 100644 (file)
@@ -1,7 +1,7 @@
 package explicit
 
 import (
-       "implicit"
+       "testshared/implicit"
 )
 
 func E() int {
similarity index 98%
rename from misc/cgo/testshared/src/global/main.go
rename to misc/cgo/testshared/testdata/global/main.go
index 94e7f247dee02d3bd925cb02ff1005906909b721..f43e7c3fb3559f59854ad02f75b33c1c2e1bb56d 100644 (file)
@@ -5,7 +5,7 @@
 package main
 
 import (
-       "globallib"
+       "testshared/globallib"
 )
 
 //go:noinline
similarity index 85%
rename from misc/cgo/testshared/src/iface/main.go
rename to misc/cgo/testshared/testdata/iface/main.go
index 3d5b54e73b9e8b0ad35a925ee845ee0e4698d808..d26ebbcc9cc1c466f1b4fb5918a4707480e25969 100644 (file)
@@ -4,8 +4,8 @@
 
 package main
 
-import "iface_a"
-import "iface_b"
+import "testshared/iface_a"
+import "testshared/iface_b"
 
 func main() {
        if iface_a.F() != iface_b.F() {
similarity index 91%
rename from misc/cgo/testshared/src/iface_a/a.go
rename to misc/cgo/testshared/testdata/iface_a/a.go
index e11047c166c66523e5a7960d150465c18eb922ac..e2cef1ecda6313a827b0708f9be672d1f3db2347 100644 (file)
@@ -4,7 +4,7 @@
 
 package iface_a
 
-import "iface_i"
+import "testshared/iface_i"
 
 //go:noinline
 func F() interface{} {
similarity index 91%
rename from misc/cgo/testshared/src/iface_b/b.go
rename to misc/cgo/testshared/testdata/iface_b/b.go
index 47aee2e77ee9d71e00947099b040ac0de252f52b..dd3e027b37a3bd2037ade0c18bf5de9bfe04e0d0 100644 (file)
@@ -4,7 +4,7 @@
 
 package iface_b
 
-import "iface_i"
+import "testshared/iface_i"
 
 //go:noinline
 func F() interface{} {
similarity index 63%
rename from misc/cgo/testshared/src/implicitcmd/implicitcmd.go
rename to misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go
index f6112933e56d6c9189259905388651331ee21517..4d4296738e3c018713d16c1bb570187e42d3e3fb 100644 (file)
@@ -1,8 +1,8 @@
 package main
 
 import (
-       "explicit"
-       "implicit"
+       "testshared/explicit"
+       "testshared/implicit"
 )
 
 func main() {