From 13d9a29060f5fb28022003e006a92b22a75c650e Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 21 Feb 2019 12:34:27 -0500 Subject: [PATCH] misc/cgo/testcarchive: fix tests in module mode Updates #30228 Change-Id: I830e3c83416b2e5744f30d1a903a74c50462716b Reviewed-on: https://go-review.googlesource.com/c/163210 Run-TryBot: Bryan C. Mills Reviewed-by: Ian Lance Taylor Reviewed-by: Jay Conrod --- misc/cgo/testcarchive/carchive_test.go | 134 +++++++++--------- misc/cgo/testcarchive/overlaydir_test.go | 81 +++++++++++ .../{src => testdata}/libgo/libgo.go | 2 +- .../{src => testdata}/libgo2/libgo2.go | 0 .../{src => testdata}/libgo3/libgo3.go | 0 .../{src => testdata}/libgo4/libgo4.go | 0 .../{src => testdata}/libgo6/sigprof.go | 0 misc/cgo/testcarchive/{ => testdata}/main.c | 0 misc/cgo/testcarchive/{ => testdata}/main2.c | 0 misc/cgo/testcarchive/{ => testdata}/main3.c | 0 misc/cgo/testcarchive/{ => testdata}/main4.c | 0 misc/cgo/testcarchive/{ => testdata}/main5.c | 0 misc/cgo/testcarchive/{ => testdata}/main6.c | 0 .../testcarchive/{ => testdata}/main_unix.c | 0 .../{ => testdata}/main_windows.c | 0 .../cgo/testcarchive/{src => testdata}/p/p.go | 0 src/cmd/dist/test.go | 2 +- 17 files changed, 150 insertions(+), 69 deletions(-) create mode 100644 misc/cgo/testcarchive/overlaydir_test.go rename misc/cgo/testcarchive/{src => testdata}/libgo/libgo.go (97%) rename misc/cgo/testcarchive/{src => testdata}/libgo2/libgo2.go (100%) rename misc/cgo/testcarchive/{src => testdata}/libgo3/libgo3.go (100%) rename misc/cgo/testcarchive/{src => testdata}/libgo4/libgo4.go (100%) rename misc/cgo/testcarchive/{src => testdata}/libgo6/sigprof.go (100%) rename misc/cgo/testcarchive/{ => testdata}/main.c (100%) rename misc/cgo/testcarchive/{ => testdata}/main2.c (100%) rename misc/cgo/testcarchive/{ => testdata}/main3.c (100%) rename misc/cgo/testcarchive/{ => testdata}/main4.c (100%) rename misc/cgo/testcarchive/{ => testdata}/main5.c (100%) rename misc/cgo/testcarchive/{ => testdata}/main6.c (100%) rename misc/cgo/testcarchive/{ => testdata}/main_unix.c (100%) rename misc/cgo/testcarchive/{ => testdata}/main_windows.c (100%) rename misc/cgo/testcarchive/{src => testdata}/p/p.go (100%) diff --git a/misc/cgo/testcarchive/carchive_test.go b/misc/cgo/testcarchive/carchive_test.go index 457ac0db09..d6b35fb9ec 100644 --- a/misc/cgo/testcarchive/carchive_test.go +++ b/misc/cgo/testcarchive/carchive_test.go @@ -10,6 +10,7 @@ import ( "debug/elf" "fmt" "io/ioutil" + "log" "os" "os/exec" "path/filepath" @@ -28,16 +29,41 @@ var bin []string // C compiler with args (from $(go env CC) $(go env GOGCCFLAGS)). var cc []string -// An environment with GOPATH=$(pwd). -var gopathEnv []string - // ".exe" on Windows. var exeSuffix string -var GOOS, GOARCH string +var GOOS, GOARCH, GOPATH string var libgodir string -func init() { +func TestMain(m *testing.M) { + log.SetFlags(log.Lshortfile) + os.Exit(testMain(m)) +} + +func testMain(m *testing.M) int { + // We need a writable GOPATH in which to run the tests. + // Construct one in a temporary directory. + var err error + GOPATH, err = ioutil.TempDir("", "carchive_test") + if err != nil { + log.Panic(err) + } + defer os.RemoveAll(GOPATH) + os.Setenv("GOPATH", GOPATH) + + // Copy testdata into GOPATH/src/testarchive, along with a go.mod file + // declaring the same path. + modRoot := filepath.Join(GOPATH, "src", "testcarchive") + if err := overlayDir(modRoot, "testdata"); err != nil { + log.Panic(err) + } + if err := os.Chdir(modRoot); err != nil { + log.Panic(err) + } + if err := ioutil.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil { + log.Panic(err) + } + GOOS = goEnv("GOOS") GOARCH = goEnv("GOARCH") bin = cmdToRun("./testp") @@ -83,50 +109,36 @@ func init() { // TODO(crawshaw): can we do better? cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...) } - libgodir = GOOS + "_" + GOARCH + libbase := GOOS + "_" + GOARCH if runtime.Compiler == "gccgo" { - libgodir = "gccgo_" + libgodir + "_fPIC" + libbase = "gccgo_" + libgodir + "_fPIC" } else { switch GOOS { case "darwin": if GOARCH == "arm" || GOARCH == "arm64" { - libgodir += "_shared" + libbase += "_shared" } case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris": - libgodir += "_shared" - } - } - cc = append(cc, "-I", filepath.Join("pkg", libgodir)) - - // Build an environment with GOPATH=$(pwd) - env := os.Environ() - var n []string - for _, e := range env { - if !strings.HasPrefix(e, "GOPATH=") { - n = append(n, e) + libbase += "_shared" } } - dir, err := os.Getwd() - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(2) - } - n = append(n, "GOPATH="+dir) - gopathEnv = n + libgodir = filepath.Join(GOPATH, "pkg", libbase, "testcarchive") + cc = append(cc, "-I", libgodir) if GOOS == "windows" { exeSuffix = ".exe" } + + return m.Run() } func goEnv(key string) string { out, err := exec.Command("go", "env", key).Output() if err != nil { - fmt.Fprintf(os.Stderr, "go env %s failed:\n%s\n", key, err) if ee, ok := err.(*exec.ExitError); ok { fmt.Fprintf(os.Stderr, "%s", ee.Stderr) } - os.Exit(2) + log.Panicf("go env %s failed:\n%s\n", key, err) } return strings.TrimSpace(string(out)) } @@ -143,7 +155,6 @@ func cmdToRun(name string) []string { func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) { t.Helper() cmd := exec.Command(buildcmd[0], buildcmd[1:]...) - cmd.Env = gopathEnv t.Log(buildcmd) if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) @@ -204,7 +215,7 @@ func checkLineComments(t *testing.T, hdrname string) { } func TestInstall(t *testing.T) { - defer os.RemoveAll("pkg") + defer os.RemoveAll(filepath.Join(GOPATH, "pkg")) libgoa := "libgo.a" if runtime.Compiler == "gccgo" { @@ -212,17 +223,17 @@ func TestInstall(t *testing.T) { } testInstall(t, "./testp1"+exeSuffix, - filepath.Join("pkg", libgodir, libgoa), - filepath.Join("pkg", libgodir, "libgo.h"), - "go", "install", "-i", "-buildmode=c-archive", "libgo") + filepath.Join(libgodir, libgoa), + filepath.Join(libgodir, "libgo.h"), + "go", "install", "-i", "-buildmode=c-archive", "./libgo") // Test building libgo other than installing it. // Header files are now present. testInstall(t, "./testp2"+exeSuffix, "libgo.a", "libgo.h", - "go", "build", "-buildmode=c-archive", filepath.Join("src", "libgo", "libgo.go")) + "go", "build", "-buildmode=c-archive", filepath.Join(".", "libgo", "libgo.go")) testInstall(t, "./testp3"+exeSuffix, "libgo.a", "libgo.h", - "go", "build", "-buildmode=c-archive", "-o", "libgo.a", "libgo") + "go", "build", "-buildmode=c-archive", "-o", "libgo.a", "./libgo") } func TestEarlySignalHandler(t *testing.T) { @@ -240,11 +251,10 @@ func TestEarlySignalHandler(t *testing.T) { os.Remove("libgo2.a") os.Remove("libgo2.h") os.Remove("testp") - os.RemoveAll("pkg") + os.RemoveAll(filepath.Join(GOPATH, "pkg")) }() - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2") - cmd.Env = gopathEnv + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2") if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) t.Fatal(err) @@ -273,11 +283,10 @@ func TestSignalForwarding(t *testing.T) { os.Remove("libgo2.a") os.Remove("libgo2.h") os.Remove("testp") - os.RemoveAll("pkg") + os.RemoveAll(filepath.Join(GOPATH, "pkg")) }() - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2") - cmd.Env = gopathEnv + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2") if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) t.Fatal(err) @@ -317,11 +326,10 @@ func TestSignalForwardingExternal(t *testing.T) { os.Remove("libgo2.a") os.Remove("libgo2.h") os.Remove("testp") - os.RemoveAll("pkg") + os.RemoveAll(filepath.Join(GOPATH, "pkg")) }() - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2") - cmd.Env = gopathEnv + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2") if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) t.Fatal(err) @@ -433,11 +441,10 @@ func TestOsSignal(t *testing.T) { os.Remove("libgo3.a") os.Remove("libgo3.h") os.Remove("testp") - os.RemoveAll("pkg") + os.RemoveAll(filepath.Join(GOPATH, "pkg")) }() - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo3.a", "libgo3") - cmd.Env = gopathEnv + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo3.a", "./libgo3") if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) t.Fatal(err) @@ -469,11 +476,10 @@ func TestSigaltstack(t *testing.T) { os.Remove("libgo4.a") os.Remove("libgo4.h") os.Remove("testp") - os.RemoveAll("pkg") + os.RemoveAll(filepath.Join(GOPATH, "pkg")) }() - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo4.a", "libgo4") - cmd.Env = gopathEnv + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo4.a", "./libgo4") if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) t.Fatal(err) @@ -517,7 +523,7 @@ func TestExtar(t *testing.T) { os.Remove("libgo4.h") os.Remove("testar") os.Remove("testar.ran") - os.RemoveAll("pkg") + os.RemoveAll(filepath.Join(GOPATH, "pkg")) }() os.Remove("testar") @@ -530,8 +536,7 @@ func TestExtar(t *testing.T) { t.Fatal(err) } - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-ldflags=-extar="+filepath.Join(dir, "testar"), "-o", "libgo4.a", "libgo4") - cmd.Env = gopathEnv + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-ldflags=-extar="+filepath.Join(dir, "testar"), "-o", "libgo4.a", "./libgo4") if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) t.Fatal(err) @@ -555,11 +560,10 @@ func TestPIE(t *testing.T) { defer func() { os.Remove("testp" + exeSuffix) - os.RemoveAll("pkg") + os.RemoveAll(filepath.Join(GOPATH, "pkg")) }() - cmd := exec.Command("go", "install", "-i", "-buildmode=c-archive", "libgo") - cmd.Env = gopathEnv + cmd := exec.Command("go", "install", "-i", "-buildmode=c-archive", "./libgo") if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) t.Fatal(err) @@ -570,7 +574,7 @@ func TestPIE(t *testing.T) { libgoa = "liblibgo.a" } - ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", filepath.Join("pkg", libgodir, libgoa)) + ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", filepath.Join(libgodir, libgoa)) if runtime.Compiler == "gccgo" { ccArgs = append(ccArgs, "-lgo") } @@ -643,8 +647,7 @@ func TestSIGPROF(t *testing.T) { os.Remove("libgo6.h") }() - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo6.a", "libgo6") - cmd.Env = gopathEnv + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo6.a", "./libgo6") if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) t.Fatal(err) @@ -683,8 +686,7 @@ func TestCompileWithoutShared(t *testing.T) { os.Remove("libgo2.h") }() - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-gcflags=-shared=false", "-o", "libgo2.a", "libgo2") - cmd.Env = gopathEnv + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-gcflags=-shared=false", "-o", "libgo2.a", "./libgo2") t.Log(cmd.Args) out, err := cmd.CombinedOutput() t.Logf("%s", out) @@ -732,15 +734,14 @@ func TestCompileWithoutShared(t *testing.T) { // Test that installing a second time recreates the header files. func TestCachedInstall(t *testing.T) { - defer os.RemoveAll("pkg") + defer os.RemoveAll(filepath.Join(GOPATH, "pkg")) - h1 := filepath.Join("pkg", libgodir, "libgo.h") - h2 := filepath.Join("pkg", libgodir, "p.h") + h1 := filepath.Join(libgodir, "libgo.h") + h2 := filepath.Join(libgodir, "p.h") - buildcmd := []string{"go", "install", "-i", "-buildmode=c-archive", "libgo"} + buildcmd := []string{"go", "install", "-i", "-buildmode=c-archive", "./libgo"} cmd := exec.Command(buildcmd[0], buildcmd[1:]...) - cmd.Env = gopathEnv t.Log(buildcmd) if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) @@ -762,7 +763,6 @@ func TestCachedInstall(t *testing.T) { } cmd = exec.Command(buildcmd[0], buildcmd[1:]...) - cmd.Env = gopathEnv t.Log(buildcmd) if out, err := cmd.CombinedOutput(); err != nil { t.Logf("%s", out) diff --git a/misc/cgo/testcarchive/overlaydir_test.go b/misc/cgo/testcarchive/overlaydir_test.go new file mode 100644 index 0000000000..68878e4c66 --- /dev/null +++ b/misc/cgo/testcarchive/overlaydir_test.go @@ -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 carchive_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/testcarchive/src/libgo/libgo.go b/misc/cgo/testcarchive/testdata/libgo/libgo.go similarity index 97% rename from misc/cgo/testcarchive/src/libgo/libgo.go rename to misc/cgo/testcarchive/testdata/libgo/libgo.go index 45958a546c..37b30c1463 100644 --- a/misc/cgo/testcarchive/src/libgo/libgo.go +++ b/misc/cgo/testcarchive/testdata/libgo/libgo.go @@ -10,7 +10,7 @@ import ( "syscall" "time" - _ "p" + _ "testcarchive/p" ) import "C" diff --git a/misc/cgo/testcarchive/src/libgo2/libgo2.go b/misc/cgo/testcarchive/testdata/libgo2/libgo2.go similarity index 100% rename from misc/cgo/testcarchive/src/libgo2/libgo2.go rename to misc/cgo/testcarchive/testdata/libgo2/libgo2.go diff --git a/misc/cgo/testcarchive/src/libgo3/libgo3.go b/misc/cgo/testcarchive/testdata/libgo3/libgo3.go similarity index 100% rename from misc/cgo/testcarchive/src/libgo3/libgo3.go rename to misc/cgo/testcarchive/testdata/libgo3/libgo3.go diff --git a/misc/cgo/testcarchive/src/libgo4/libgo4.go b/misc/cgo/testcarchive/testdata/libgo4/libgo4.go similarity index 100% rename from misc/cgo/testcarchive/src/libgo4/libgo4.go rename to misc/cgo/testcarchive/testdata/libgo4/libgo4.go diff --git a/misc/cgo/testcarchive/src/libgo6/sigprof.go b/misc/cgo/testcarchive/testdata/libgo6/sigprof.go similarity index 100% rename from misc/cgo/testcarchive/src/libgo6/sigprof.go rename to misc/cgo/testcarchive/testdata/libgo6/sigprof.go diff --git a/misc/cgo/testcarchive/main.c b/misc/cgo/testcarchive/testdata/main.c similarity index 100% rename from misc/cgo/testcarchive/main.c rename to misc/cgo/testcarchive/testdata/main.c diff --git a/misc/cgo/testcarchive/main2.c b/misc/cgo/testcarchive/testdata/main2.c similarity index 100% rename from misc/cgo/testcarchive/main2.c rename to misc/cgo/testcarchive/testdata/main2.c diff --git a/misc/cgo/testcarchive/main3.c b/misc/cgo/testcarchive/testdata/main3.c similarity index 100% rename from misc/cgo/testcarchive/main3.c rename to misc/cgo/testcarchive/testdata/main3.c diff --git a/misc/cgo/testcarchive/main4.c b/misc/cgo/testcarchive/testdata/main4.c similarity index 100% rename from misc/cgo/testcarchive/main4.c rename to misc/cgo/testcarchive/testdata/main4.c diff --git a/misc/cgo/testcarchive/main5.c b/misc/cgo/testcarchive/testdata/main5.c similarity index 100% rename from misc/cgo/testcarchive/main5.c rename to misc/cgo/testcarchive/testdata/main5.c diff --git a/misc/cgo/testcarchive/main6.c b/misc/cgo/testcarchive/testdata/main6.c similarity index 100% rename from misc/cgo/testcarchive/main6.c rename to misc/cgo/testcarchive/testdata/main6.c diff --git a/misc/cgo/testcarchive/main_unix.c b/misc/cgo/testcarchive/testdata/main_unix.c similarity index 100% rename from misc/cgo/testcarchive/main_unix.c rename to misc/cgo/testcarchive/testdata/main_unix.c diff --git a/misc/cgo/testcarchive/main_windows.c b/misc/cgo/testcarchive/testdata/main_windows.c similarity index 100% rename from misc/cgo/testcarchive/main_windows.c rename to misc/cgo/testcarchive/testdata/main_windows.c diff --git a/misc/cgo/testcarchive/src/p/p.go b/misc/cgo/testcarchive/testdata/p/p.go similarity index 100% rename from misc/cgo/testcarchive/src/p/p.go rename to misc/cgo/testcarchive/testdata/p/p.go diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 74cee8f421..30b4468b08 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -692,7 +692,7 @@ func (t *tester) registerTests() { }) } if t.supportedBuildmode("c-archive") { - t.registerHostTest("testcarchive", "../misc/cgo/testcarchive", "misc/cgo/testcarchive", "carchive_test.go") + t.registerHostTest("testcarchive", "../misc/cgo/testcarchive", "misc/cgo/testcarchive", ".") } if t.supportedBuildmode("c-shared") { t.registerHostTest("testcshared", "../misc/cgo/testcshared", "misc/cgo/testcshared", "cshared_test.go") -- 2.48.1