mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
test: make runindir tests pass regardless of whether module mode is in use
The "runindir" tests used "go run", but relied on relative imports (which are not supported by "go run" in module mode). Instead, such tests must use fully-qualified imports, which require either a go.mod file (in module mode) or that the package be in an appropriate subdirectory of GOPATH/src (in GOPATH mode). To set up such a directory, we use yet another copy of the same overlayDir function currently found in the misc subdirectory of this repository. Fixes #33912 Updates #30228 Change-Id: If3d7ea2f7942ba496d98aaaf24a90bcdcf4df9f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/225205 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
16cfab8d89
commit
91b8b130dd
@ -12,8 +12,8 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
ssa1 "./p1/ssa"
|
||||
ssa2 "./p2/ssa"
|
||||
ssa1 "issue29612.dir/p1/ssa"
|
||||
ssa2 "issue29612.dir/p2/ssa"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
137
test/run.go
137
test/run.go
@ -607,20 +607,23 @@ func (t *test) run() {
|
||||
os.Setenv("GOARCH", runtime.GOARCH)
|
||||
}
|
||||
|
||||
useTmp := true
|
||||
runInDir := false
|
||||
var (
|
||||
runInDir = t.tempDir
|
||||
tempDirIsGOPATH = false
|
||||
)
|
||||
runcmd := func(args ...string) ([]byte, error) {
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
var buf bytes.Buffer
|
||||
cmd.Stdout = &buf
|
||||
cmd.Stderr = &buf
|
||||
cmd.Env = os.Environ()
|
||||
if useTmp {
|
||||
cmd.Dir = t.tempDir
|
||||
cmd.Env = envForDir(cmd.Dir)
|
||||
cmd.Env = append(os.Environ(), "GOENV=off", "GOFLAGS=")
|
||||
if runInDir != "" {
|
||||
cmd.Dir = runInDir
|
||||
// Set PWD to match Dir to speed up os.Getwd in the child process.
|
||||
cmd.Env = append(cmd.Env, "PWD="+cmd.Dir)
|
||||
}
|
||||
if runInDir {
|
||||
cmd.Dir = t.goDirName()
|
||||
if tempDirIsGOPATH {
|
||||
cmd.Env = append(cmd.Env, "GOPATH="+t.tempDir)
|
||||
}
|
||||
|
||||
var err error
|
||||
@ -863,13 +866,31 @@ func (t *test) run() {
|
||||
}
|
||||
|
||||
case "runindir":
|
||||
// run "go run ." in t.goDirName()
|
||||
// It's used when test requires go build and run the binary success.
|
||||
// Example when long import path require (see issue29612.dir) or test
|
||||
// contains assembly file (see issue15609.dir).
|
||||
// Verify the expected output.
|
||||
useTmp = false
|
||||
runInDir = true
|
||||
// Make a shallow copy of t.goDirName() in its own module and GOPATH, and
|
||||
// run "go run ." in it. The module path (and hence import path prefix) of
|
||||
// the copy is equal to the basename of the source directory.
|
||||
//
|
||||
// It's used when test a requires a full 'go build' in order to compile
|
||||
// the sources, such as when importing multiple packages (issue29612.dir)
|
||||
// or compiling a package containing assembly files (see issue15609.dir),
|
||||
// but still needs to be run to verify the expected output.
|
||||
tempDirIsGOPATH = true
|
||||
srcDir := t.goDirName()
|
||||
modName := filepath.Base(srcDir)
|
||||
gopathSrcDir := filepath.Join(t.tempDir, "src", modName)
|
||||
runInDir = gopathSrcDir
|
||||
|
||||
if err := overlayDir(gopathSrcDir, srcDir); err != nil {
|
||||
t.err = err
|
||||
return
|
||||
}
|
||||
|
||||
modFile := fmt.Sprintf("module %s\ngo 1.14\n", modName)
|
||||
if err := ioutil.WriteFile(filepath.Join(gopathSrcDir, "go.mod"), []byte(modFile), 0666); err != nil {
|
||||
t.err = err
|
||||
return
|
||||
}
|
||||
|
||||
cmd := []string{goTool(), "run", goGcflags()}
|
||||
if *linkshared {
|
||||
cmd = append(cmd, "-linkshared")
|
||||
@ -1003,7 +1024,7 @@ func (t *test) run() {
|
||||
// Run Go file if no special go command flags are provided;
|
||||
// otherwise build an executable and run it.
|
||||
// Verify the output.
|
||||
useTmp = false
|
||||
runInDir = ""
|
||||
var out []byte
|
||||
var err error
|
||||
if len(flags)+len(args) == 0 && goGcflagsIsEmpty() && !*linkshared && goarch == runtime.GOARCH && goos == runtime.GOOS {
|
||||
@ -1051,7 +1072,7 @@ func (t *test) run() {
|
||||
defer func() {
|
||||
<-rungatec
|
||||
}()
|
||||
useTmp = false
|
||||
runInDir = ""
|
||||
cmd := []string{goTool(), "run", goGcflags()}
|
||||
if *linkshared {
|
||||
cmd = append(cmd, "-linkshared")
|
||||
@ -1084,7 +1105,7 @@ func (t *test) run() {
|
||||
case "errorcheckoutput":
|
||||
// Run Go file and write its output into temporary Go file.
|
||||
// Compile and errorCheck generated Go file.
|
||||
useTmp = false
|
||||
runInDir = ""
|
||||
cmd := []string{goTool(), "run", goGcflags()}
|
||||
if *linkshared {
|
||||
cmd = append(cmd, "-linkshared")
|
||||
@ -1752,23 +1773,6 @@ func checkShouldTest() {
|
||||
assert(shouldTest("// +build !windows !plan9", "windows", "amd64"))
|
||||
}
|
||||
|
||||
// envForDir returns a copy of the environment
|
||||
// suitable for running in the given directory.
|
||||
// The environment is the current process's environment
|
||||
// but with an updated $PWD, so that an os.Getwd in the
|
||||
// child will be faster.
|
||||
func envForDir(dir string) []string {
|
||||
env := os.Environ()
|
||||
for i, kv := range env {
|
||||
if strings.HasPrefix(kv, "PWD=") {
|
||||
env[i] = "PWD=" + dir
|
||||
return env
|
||||
}
|
||||
}
|
||||
env = append(env, "PWD="+dir)
|
||||
return env
|
||||
}
|
||||
|
||||
func getenv(key, def string) string {
|
||||
value := os.Getenv(key)
|
||||
if value != "" {
|
||||
@ -1776,3 +1780,66 @@ func getenv(key, def string) string {
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added.
|
||||
func overlayDir(dstRoot, srcRoot string) error {
|
||||
dstRoot = filepath.Clean(dstRoot)
|
||||
if err := os.MkdirAll(dstRoot, 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srcRoot, 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.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(srcPath, 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
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user