testCacheExpire time.Time // ignore cached test results before this time
testBlockProfile, testCPUProfile, testMemProfile, testMutexProfile, testTrace string // profiling flag that limits test to one package
+
+ testODir = false
)
// testProfile returns the name of an arbitrary single-package profiling flag
base.Fatalf("no packages to test")
}
- if testC && len(pkgs) != 1 {
- base.Fatalf("cannot use -c flag with multiple packages")
- }
- if testO != "" && len(pkgs) != 1 {
- base.Fatalf("cannot use -o flag with multiple packages")
- }
if testFuzz != "" {
if !platform.FuzzSupported(cfg.Goos, cfg.Goarch) {
base.Fatalf("-fuzz flag is not supported on %s/%s", cfg.Goos, cfg.Goarch)
if testProfile() != "" && len(pkgs) != 1 {
base.Fatalf("cannot use %s flag with multiple packages", testProfile())
}
+
+ if testO != "" {
+ if strings.HasSuffix(testO, "/") || strings.HasSuffix(testO, string(os.PathSeparator)) {
+ testODir = true
+ } else if fi, err := os.Stat(testO); err == nil && fi.IsDir() {
+ testODir = true
+ }
+ }
+
+ if len(pkgs) > 1 && (testC || testO != "") && !base.IsNull(testO) {
+ if testO != "" && !testODir {
+ base.Fatalf("with multiple packages, -o must refer to a directory or %s", os.DevNull)
+ }
+
+ pkgsForBinary := map[string][]*load.Package{}
+
+ for _, p := range pkgs {
+ testBinary := testBinaryName(p)
+ pkgsForBinary[testBinary] = append(pkgsForBinary[testBinary], p)
+ }
+
+ for testBinary, pkgs := range pkgsForBinary {
+ if len(pkgs) > 1 {
+ var buf strings.Builder
+ for _, pkg := range pkgs {
+ buf.WriteString(pkg.ImportPath)
+ buf.WriteString("\n")
+ }
+
+ base.Errorf("cannot write test binary %s for multiple packages:\n%s", testBinary, buf.String())
+ }
+ }
+
+ base.ExitIfErrors()
+ }
+
initCoverProfile()
defer closeCoverProfile()
buildTest.Deps = append(buildTest.Deps, buildP)
}
- // Use last element of import path, not package name.
- // They differ when package name is "main".
- // But if the import path is "command-line-arguments",
- // like it is during 'go run', use the package name.
- var elem string
- if p.ImportPath == "command-line-arguments" {
- elem = p.Name
- } else {
- elem = p.DefaultExecName()
- }
- testBinary := elem + ".test"
+ testBinary := testBinaryName(p)
testDir := b.NewObjdir()
if err := b.Mkdir(testDir); err != nil {
// -c or profiling flag: create action to copy binary to ./test.out.
target := filepath.Join(base.Cwd(), testBinary+cfg.ExeSuffix)
isNull := false
+
if testO != "" {
target = testO
- if base.IsNull(target) {
- isNull = true
- } else if !filepath.IsAbs(target) {
- target = filepath.Join(base.Cwd(), target)
+
+ if testODir {
+ if filepath.IsAbs(target) {
+ target = filepath.Join(target, testBinary+cfg.ExeSuffix)
+ } else {
+ target = filepath.Join(base.Cwd(), target, testBinary+cfg.ExeSuffix)
+ }
+ } else {
+ if base.IsNull(target) {
+ isNull = true
+ } else if !filepath.IsAbs(target) {
+ target = filepath.Join(base.Cwd(), target)
+ }
}
}
+
if isNull {
runAction = buildAction
} else {
}
return nil
}
+
+// testBinaryName can be used to create name for test binary executable.
+// Use last element of import path, not package name.
+// They differ when package name is "main".
+// But if the import path is "command-line-arguments",
+// like it is during 'go run', use the package name.
+func testBinaryName(p *load.Package) string {
+ var elem string
+ if p.ImportPath == "command-line-arguments" {
+ elem = p.Name
+ } else {
+ elem = p.DefaultExecName()
+ }
+
+ return elem + ".test"
+}
--- /dev/null
+[short] skip 'links test binaries'
+
+# Verify test -c can output multiple executables to a directory.
+
+go test -c -o $WORK/some/nonexisting/directory/ ./pkg/...
+exists -exec $WORK/some/nonexisting/directory/pkg1.test$GOEXE
+exists -exec $WORK/some/nonexisting/directory/pkg2.test$GOEXE
+
+go test -c ./pkg/...
+exists -exec pkg1.test$GOEXE
+exists -exec pkg2.test$GOEXE
+
+! go test -c -o $WORK/bin/test/bin.test.exe ./pkg/...
+stderr '^with multiple packages, -o must refer to a directory or '$devnull
+
+! go test -c ./...
+stderr '^cannot write test binary pkg1.test for multiple packages:\nexample/anotherpkg/pkg1\nexample/pkg/pkg1'
+
+! go test -c -o $WORK/bin/test/ ./...
+stderr '^cannot write test binary pkg1.test for multiple packages:\nexample/anotherpkg/pkg1\nexample/pkg/pkg1'
+
+! go test -o $WORK/bin/filename.exe ./pkg/...
+stderr '^with multiple packages, -o must refer to a directory or '$devnull
+
+! go test -o $WORK/bin/ ./...
+stderr '^cannot write test binary pkg1.test for multiple packages:\nexample/anotherpkg/pkg1\nexample/pkg/pkg1'
+
+go test -c -o $devnull ./...
+
+rm pkg1.test$GOEXE
+rm pkg2.test$GOEXE
+go test -o . ./pkg/...
+exists -exec pkg1.test$GOEXE
+exists -exec pkg2.test$GOEXE
+
+-- go.mod --
+module example
+
+-- pkg/pkg1/pkg1_test.go --
+package pkg1
+
+-- pkg/pkg2/pkg2_test.go --
+package pkg2
+
+-- anotherpkg/pkg1/pkg1_test.go --
+package pkg1
\ No newline at end of file