]> Cypherpunks repositories - gostls13.git/commitdiff
misc/cgo/testso{,var}: fix tests in module mode
authorBryan C. Mills <bcmills@google.com>
Fri, 22 Feb 2019 15:50:47 +0000 (10:50 -0500)
committerBryan C. Mills <bcmills@google.com>
Tue, 26 Feb 2019 02:43:55 +0000 (02:43 +0000)
Add _test.go files in the individal directories to invoke 'go build'
with appropriate arguments.

Move the test driver out of cmd/dist so that it's easier to invoke the
test separately (using 'go test .').

Updates #30228
Updates #28387

Change-Id: Ibc4a024a52c12a274058298b41cc90709f7f56c8
Reviewed-on: https://go-review.googlesource.com/c/163420
Reviewed-by: Ian Lance Taylor <iant@golang.org>
16 files changed:
misc/cgo/testso/noso_test.go [new file with mode: 0644]
misc/cgo/testso/overlaydir_test.go [new file with mode: 0644]
misc/cgo/testso/so_test.go [new file with mode: 0644]
misc/cgo/testso/testdata/cgoso.c [moved from misc/cgo/testso/cgoso.c with 100% similarity]
misc/cgo/testso/testdata/cgoso.go [moved from misc/cgo/testso/cgoso.go with 100% similarity]
misc/cgo/testso/testdata/cgoso_c.c [moved from misc/cgo/testso/cgoso_c.c with 100% similarity]
misc/cgo/testso/testdata/cgoso_unix.go [moved from misc/cgo/testso/cgoso_unix.go with 100% similarity]
misc/cgo/testso/testdata/main.go [moved from misc/cgo/testso/main.go with 92% similarity]
misc/cgo/testsovar/noso_test.go [new file with mode: 0644]
misc/cgo/testsovar/overlaydir_test.go [new file with mode: 0644]
misc/cgo/testsovar/so_test.go [new file with mode: 0644]
misc/cgo/testsovar/testdata/cgoso.go [moved from misc/cgo/testsovar/cgoso.go with 100% similarity]
misc/cgo/testsovar/testdata/cgoso_c.c [moved from misc/cgo/testsovar/cgoso_c.c with 100% similarity]
misc/cgo/testsovar/testdata/cgoso_c.h [moved from misc/cgo/testsovar/cgoso_c.h with 100% similarity]
misc/cgo/testsovar/testdata/main.go [moved from misc/cgo/testsovar/main.go with 92% similarity]
src/cmd/dist/test.go

diff --git a/misc/cgo/testso/noso_test.go b/misc/cgo/testso/noso_test.go
new file mode 100644 (file)
index 0000000..c88aebf
--- /dev/null
@@ -0,0 +1,9 @@
+// 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.
+
+// +build !cgo
+
+package so_test
+
+// Nothing to test.
diff --git a/misc/cgo/testso/overlaydir_test.go b/misc/cgo/testso/overlaydir_test.go
new file mode 100644 (file)
index 0000000..10c874d
--- /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 so_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
+       })
+}
diff --git a/misc/cgo/testso/so_test.go b/misc/cgo/testso/so_test.go
new file mode 100644 (file)
index 0000000..500b08f
--- /dev/null
@@ -0,0 +1,126 @@
+// 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.
+
+// +build cgo
+
+package so_test
+
+import (
+       "io/ioutil"
+       "log"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime"
+       "strings"
+       "testing"
+)
+
+func requireTestSOSupported(t *testing.T) {
+       t.Helper()
+       switch runtime.GOARCH {
+       case "arm", "arm64":
+               if runtime.GOOS == "darwin" {
+                       t.Skip("No exec facility on iOS.")
+               }
+       case "ppc64":
+               t.Skip("External linking not implemented on ppc64 (issue #8912).")
+       case "mips64le", "mips64":
+               t.Skip("External linking not implemented on mips64.")
+       }
+       if runtime.GOOS == "android" {
+               t.Skip("No exec facility on Android.")
+       }
+}
+
+func TestSO(t *testing.T) {
+       requireTestSOSupported(t)
+
+       GOPATH, err := ioutil.TempDir("", "cgosotest")
+       if err != nil {
+               log.Fatal(err)
+       }
+       defer os.RemoveAll(GOPATH)
+
+       modRoot := filepath.Join(GOPATH, "src", "cgosotest")
+       if err := overlayDir(modRoot, "testdata"); err != nil {
+               log.Panic(err)
+       }
+       if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
+               log.Panic(err)
+       }
+
+       cmd := exec.Command("go", "env", "CC", "GOGCCFLAGS")
+       cmd.Dir = modRoot
+       cmd.Stderr = new(strings.Builder)
+       cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
+       out, err := cmd.Output()
+       if err != nil {
+               t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
+       }
+       lines := strings.Split(string(out), "\n")
+       if len(lines) != 3 || lines[2] != "" {
+               t.Fatalf("Unexpected output from %s:\n%s", strings.Join(cmd.Args, " "), lines)
+       }
+
+       cc := lines[0]
+       if cc == "" {
+               t.Fatal("CC environment variable (go env CC) cannot be empty")
+       }
+       gogccflags := strings.Split(lines[1], " ")
+
+       // build shared object
+       ext := "so"
+       args := append(gogccflags, "-shared")
+       switch runtime.GOOS {
+       case "darwin":
+               ext = "dylib"
+               args = append(args, "-undefined", "suppress", "-flat_namespace")
+       case "windows":
+               ext = "dll"
+               args = append(args, "-DEXPORT_DLL")
+       }
+       sofname := "libcgosotest." + ext
+       args = append(args, "-o", sofname, "cgoso_c.c")
+
+       cmd = exec.Command(cc, args...)
+       cmd.Dir = modRoot
+       cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
+       }
+       t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
+
+       cmd = exec.Command("go", "build", "-o", "main.exe", "main.go")
+       cmd.Dir = modRoot
+       cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
+       }
+       t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
+
+       cmd = exec.Command("./main.exe")
+       cmd.Dir = modRoot
+       cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
+       if runtime.GOOS != "windows" {
+               s := "LD_LIBRARY_PATH"
+               if runtime.GOOS == "darwin" {
+                       s = "DYLD_LIBRARY_PATH"
+               }
+               cmd.Env = append(os.Environ(), s+"=.")
+
+               // On FreeBSD 64-bit architectures, the 32-bit linker looks for
+               // different environment variables.
+               if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" {
+                       cmd.Env = append(cmd.Env, "LD_32_LIBRARY_PATH=.")
+               }
+       }
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
+       }
+       t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
+}
similarity index 92%
rename from misc/cgo/testso/main.go
rename to misc/cgo/testso/testdata/main.go
index 88aa4322d242cf7adc33c0d57b4aa727166f6640..963d45121e4409721a698d1024366e1b1f8063f4 100644 (file)
@@ -6,7 +6,7 @@
 
 package main
 
-import "."
+import "cgosotest"
 
 func main() {
        cgosotest.Test()
diff --git a/misc/cgo/testsovar/noso_test.go b/misc/cgo/testsovar/noso_test.go
new file mode 100644 (file)
index 0000000..c88aebf
--- /dev/null
@@ -0,0 +1,9 @@
+// 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.
+
+// +build !cgo
+
+package so_test
+
+// Nothing to test.
diff --git a/misc/cgo/testsovar/overlaydir_test.go b/misc/cgo/testsovar/overlaydir_test.go
new file mode 100644 (file)
index 0000000..10c874d
--- /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 so_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
+       })
+}
diff --git a/misc/cgo/testsovar/so_test.go b/misc/cgo/testsovar/so_test.go
new file mode 100644 (file)
index 0000000..500b08f
--- /dev/null
@@ -0,0 +1,126 @@
+// 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.
+
+// +build cgo
+
+package so_test
+
+import (
+       "io/ioutil"
+       "log"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime"
+       "strings"
+       "testing"
+)
+
+func requireTestSOSupported(t *testing.T) {
+       t.Helper()
+       switch runtime.GOARCH {
+       case "arm", "arm64":
+               if runtime.GOOS == "darwin" {
+                       t.Skip("No exec facility on iOS.")
+               }
+       case "ppc64":
+               t.Skip("External linking not implemented on ppc64 (issue #8912).")
+       case "mips64le", "mips64":
+               t.Skip("External linking not implemented on mips64.")
+       }
+       if runtime.GOOS == "android" {
+               t.Skip("No exec facility on Android.")
+       }
+}
+
+func TestSO(t *testing.T) {
+       requireTestSOSupported(t)
+
+       GOPATH, err := ioutil.TempDir("", "cgosotest")
+       if err != nil {
+               log.Fatal(err)
+       }
+       defer os.RemoveAll(GOPATH)
+
+       modRoot := filepath.Join(GOPATH, "src", "cgosotest")
+       if err := overlayDir(modRoot, "testdata"); err != nil {
+               log.Panic(err)
+       }
+       if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
+               log.Panic(err)
+       }
+
+       cmd := exec.Command("go", "env", "CC", "GOGCCFLAGS")
+       cmd.Dir = modRoot
+       cmd.Stderr = new(strings.Builder)
+       cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
+       out, err := cmd.Output()
+       if err != nil {
+               t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
+       }
+       lines := strings.Split(string(out), "\n")
+       if len(lines) != 3 || lines[2] != "" {
+               t.Fatalf("Unexpected output from %s:\n%s", strings.Join(cmd.Args, " "), lines)
+       }
+
+       cc := lines[0]
+       if cc == "" {
+               t.Fatal("CC environment variable (go env CC) cannot be empty")
+       }
+       gogccflags := strings.Split(lines[1], " ")
+
+       // build shared object
+       ext := "so"
+       args := append(gogccflags, "-shared")
+       switch runtime.GOOS {
+       case "darwin":
+               ext = "dylib"
+               args = append(args, "-undefined", "suppress", "-flat_namespace")
+       case "windows":
+               ext = "dll"
+               args = append(args, "-DEXPORT_DLL")
+       }
+       sofname := "libcgosotest." + ext
+       args = append(args, "-o", sofname, "cgoso_c.c")
+
+       cmd = exec.Command(cc, args...)
+       cmd.Dir = modRoot
+       cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
+       }
+       t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
+
+       cmd = exec.Command("go", "build", "-o", "main.exe", "main.go")
+       cmd.Dir = modRoot
+       cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
+       }
+       t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
+
+       cmd = exec.Command("./main.exe")
+       cmd.Dir = modRoot
+       cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
+       if runtime.GOOS != "windows" {
+               s := "LD_LIBRARY_PATH"
+               if runtime.GOOS == "darwin" {
+                       s = "DYLD_LIBRARY_PATH"
+               }
+               cmd.Env = append(os.Environ(), s+"=.")
+
+               // On FreeBSD 64-bit architectures, the 32-bit linker looks for
+               // different environment variables.
+               if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" {
+                       cmd.Env = append(cmd.Env, "LD_32_LIBRARY_PATH=.")
+               }
+       }
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
+       }
+       t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
+}
similarity index 92%
rename from misc/cgo/testsovar/main.go
rename to misc/cgo/testsovar/testdata/main.go
index 9c8a1c4e66e630766b4dc4f2ed2d1f4c9f53ef0e..87b52cef6001947d0bd92a696a4646c5fee67ee4 100644 (file)
@@ -6,7 +6,7 @@
 
 package main
 
-import "."
+import "cgosotest"
 
 func main() {
        cgosotest.Test()
index c5cc6dcb3c88e3687d685e191f038a305a6a3bf5..31b44e8ef43a1851ce332dd1e2ab5fe417766fc5 100644 (file)
@@ -6,7 +6,6 @@ package main
 
 import (
        "bytes"
-       "errors"
        "flag"
        "fmt"
        "io/ioutil"
@@ -675,22 +674,8 @@ func (t *tester) registerTests() {
        // recompile the entire standard library. If make.bash ran with
        // special -gcflags, that's not true.
        if t.cgoEnabled && gogcflags == "" {
-               if t.cgoTestSOSupported() {
-                       t.tests = append(t.tests, distTest{
-                               name:    "testso",
-                               heading: "../misc/cgo/testso",
-                               fn: func(dt *distTest) error {
-                                       return t.cgoTestSO(dt, "misc/cgo/testso")
-                               },
-                       })
-                       t.tests = append(t.tests, distTest{
-                               name:    "testsovar",
-                               heading: "../misc/cgo/testsovar",
-                               fn: func(dt *distTest) error {
-                                       return t.cgoTestSO(dt, "misc/cgo/testsovar")
-                               },
-                       })
-               }
+               t.registerHostTest("testso", "../misc/cgo/testso", "misc/cgo/testso", ".")
+               t.registerHostTest("testsovar", "../misc/cgo/testsovar", "misc/cgo/testsovar", ".")
                if t.supportedBuildmode("c-archive") {
                        t.registerHostTest("testcarchive", "../misc/cgo/testcarchive", "misc/cgo/testcarchive", ".")
                }
@@ -1166,85 +1151,6 @@ func (t *tester) runPending(nextTest *distTest) {
        }
 }
 
-func (t *tester) cgoTestSOSupported() bool {
-       if goos == "android" || t.iOS() {
-               // No exec facility on Android or iOS.
-               return false
-       }
-       if goarch == "ppc64" {
-               // External linking not implemented on ppc64 (issue #8912).
-               return false
-       }
-       if goarch == "mips64le" || goarch == "mips64" {
-               // External linking not implemented on mips64.
-               return false
-       }
-       return true
-}
-
-func (t *tester) cgoTestSO(dt *distTest, testpath string) error {
-       t.runPending(dt)
-
-       timelog("start", dt.name)
-       defer timelog("end", dt.name)
-
-       dir := filepath.Join(goroot, testpath)
-
-       // build shared object
-       output, err := exec.Command("go", "env", "CC").Output()
-       if err != nil {
-               return fmt.Errorf("Error running go env CC: %v", err)
-       }
-       cc := strings.TrimSuffix(string(output), "\n")
-       if cc == "" {
-               return errors.New("CC environment variable (go env CC) cannot be empty")
-       }
-       output, err = exec.Command("go", "env", "GOGCCFLAGS").Output()
-       if err != nil {
-               return fmt.Errorf("Error running go env GOGCCFLAGS: %v", err)
-       }
-       gogccflags := strings.Split(strings.TrimSuffix(string(output), "\n"), " ")
-
-       ext := "so"
-       args := append(gogccflags, "-shared")
-       switch goos {
-       case "darwin":
-               ext = "dylib"
-               args = append(args, "-undefined", "suppress", "-flat_namespace")
-       case "windows":
-               ext = "dll"
-               args = append(args, "-DEXPORT_DLL")
-       }
-       sofname := "libcgosotest." + ext
-       args = append(args, "-o", sofname, "cgoso_c.c")
-
-       if err := t.dirCmd(dir, cc, args).Run(); err != nil {
-               return err
-       }
-       defer os.Remove(filepath.Join(dir, sofname))
-
-       if err := t.dirCmd(dir, "go", "build", "-o", "main.exe", "main.go").Run(); err != nil {
-               return err
-       }
-       defer os.Remove(filepath.Join(dir, "main.exe"))
-
-       cmd := t.dirCmd(dir, "./main.exe")
-       if goos != "windows" {
-               s := "LD_LIBRARY_PATH"
-               if goos == "darwin" {
-                       s = "DYLD_LIBRARY_PATH"
-               }
-               cmd.Env = append(os.Environ(), s+"=.")
-
-               // On FreeBSD 64-bit architectures, the 32-bit linker looks for
-               // different environment variables.
-               if goos == "freebsd" && gohostarch == "386" {
-                       cmd.Env = append(cmd.Env, "LD_32_LIBRARY_PATH=.")
-               }
-       }
-       return cmd.Run()
-}
-
 func (t *tester) hasBash() bool {
        switch gohostos {
        case "windows", "plan9":