Skip to content

Commit b611b3a

Browse files
maksadbekgopherbot
authored andcommitted
cmd/go: make go test build multiple executables
If -c is set while testing multiple packages, then allow to build testing binary executables to the current directory or to the directory that -o refers to. $ go test -c -o /tmp ./pkg1 ./pkg2 ./pkg2 $ ls /tmp pkg1.test pkg2.test pkg3.test Fixes #15513. Change-Id: I3aba01bebfa90e61e59276f2832d99c0d323b82e Reviewed-on: https://go-review.googlesource.com/c/go/+/466397 Run-TryBot: Bryan Mills <[email protected]> Auto-Submit: Bryan Mills <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Bryan Mills <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
1 parent 1a5cf03 commit b611b3a

File tree

2 files changed

+116
-21
lines changed

2 files changed

+116
-21
lines changed

src/cmd/go/internal/test/test.go

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,8 @@ var (
587587
testCacheExpire time.Time // ignore cached test results before this time
588588

589589
testBlockProfile, testCPUProfile, testMemProfile, testMutexProfile, testTrace string // profiling flag that limits test to one package
590+
591+
testODir = false
590592
)
591593

592594
// testProfile returns the name of an arbitrary single-package profiling flag
@@ -694,12 +696,6 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
694696
base.Fatalf("no packages to test")
695697
}
696698

697-
if testC && len(pkgs) != 1 {
698-
base.Fatalf("cannot use -c flag with multiple packages")
699-
}
700-
if testO != "" && len(pkgs) != 1 {
701-
base.Fatalf("cannot use -o flag with multiple packages")
702-
}
703699
if testFuzz != "" {
704700
if !platform.FuzzSupported(cfg.Goos, cfg.Goarch) {
705701
base.Fatalf("-fuzz flag is not supported on %s/%s", cfg.Goos, cfg.Goarch)
@@ -749,6 +745,42 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
749745
if testProfile() != "" && len(pkgs) != 1 {
750746
base.Fatalf("cannot use %s flag with multiple packages", testProfile())
751747
}
748+
749+
if testO != "" {
750+
if strings.HasSuffix(testO, "/") || strings.HasSuffix(testO, string(os.PathSeparator)) {
751+
testODir = true
752+
} else if fi, err := os.Stat(testO); err == nil && fi.IsDir() {
753+
testODir = true
754+
}
755+
}
756+
757+
if len(pkgs) > 1 && (testC || testO != "") && !base.IsNull(testO) {
758+
if testO != "" && !testODir {
759+
base.Fatalf("with multiple packages, -o must refer to a directory or %s", os.DevNull)
760+
}
761+
762+
pkgsForBinary := map[string][]*load.Package{}
763+
764+
for _, p := range pkgs {
765+
testBinary := testBinaryName(p)
766+
pkgsForBinary[testBinary] = append(pkgsForBinary[testBinary], p)
767+
}
768+
769+
for testBinary, pkgs := range pkgsForBinary {
770+
if len(pkgs) > 1 {
771+
var buf strings.Builder
772+
for _, pkg := range pkgs {
773+
buf.WriteString(pkg.ImportPath)
774+
buf.WriteString("\n")
775+
}
776+
777+
base.Errorf("cannot write test binary %s for multiple packages:\n%s", testBinary, buf.String())
778+
}
779+
}
780+
781+
base.ExitIfErrors()
782+
}
783+
752784
initCoverProfile()
753785
defer closeCoverProfile()
754786

@@ -978,17 +1010,7 @@ func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts,
9781010
buildTest.Deps = append(buildTest.Deps, buildP)
9791011
}
9801012

981-
// Use last element of import path, not package name.
982-
// They differ when package name is "main".
983-
// But if the import path is "command-line-arguments",
984-
// like it is during 'go run', use the package name.
985-
var elem string
986-
if p.ImportPath == "command-line-arguments" {
987-
elem = p.Name
988-
} else {
989-
elem = p.DefaultExecName()
990-
}
991-
testBinary := elem + ".test"
1013+
testBinary := testBinaryName(p)
9921014

9931015
testDir := b.NewObjdir()
9941016
if err := b.Mkdir(testDir); err != nil {
@@ -1048,14 +1070,25 @@ func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts,
10481070
// -c or profiling flag: create action to copy binary to ./test.out.
10491071
target := filepath.Join(base.Cwd(), testBinary+cfg.ExeSuffix)
10501072
isNull := false
1073+
10511074
if testO != "" {
10521075
target = testO
1053-
if base.IsNull(target) {
1054-
isNull = true
1055-
} else if !filepath.IsAbs(target) {
1056-
target = filepath.Join(base.Cwd(), target)
1076+
1077+
if testODir {
1078+
if filepath.IsAbs(target) {
1079+
target = filepath.Join(target, testBinary+cfg.ExeSuffix)
1080+
} else {
1081+
target = filepath.Join(base.Cwd(), target, testBinary+cfg.ExeSuffix)
1082+
}
1083+
} else {
1084+
if base.IsNull(target) {
1085+
isNull = true
1086+
} else if !filepath.IsAbs(target) {
1087+
target = filepath.Join(base.Cwd(), target)
1088+
}
10571089
}
10581090
}
1091+
10591092
if isNull {
10601093
runAction = buildAction
10611094
} else {
@@ -1862,3 +1895,19 @@ func printExitStatus(b *work.Builder, ctx context.Context, a *work.Action) error
18621895
}
18631896
return nil
18641897
}
1898+
1899+
// testBinaryName can be used to create name for test binary executable.
1900+
// Use last element of import path, not package name.
1901+
// They differ when package name is "main".
1902+
// But if the import path is "command-line-arguments",
1903+
// like it is during 'go run', use the package name.
1904+
func testBinaryName(p *load.Package) string {
1905+
var elem string
1906+
if p.ImportPath == "command-line-arguments" {
1907+
elem = p.Name
1908+
} else {
1909+
elem = p.DefaultExecName()
1910+
}
1911+
1912+
return elem + ".test"
1913+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
[short] skip 'links test binaries'
2+
3+
# Verify test -c can output multiple executables to a directory.
4+
5+
go test -c -o $WORK/some/nonexisting/directory/ ./pkg/...
6+
exists -exec $WORK/some/nonexisting/directory/pkg1.test$GOEXE
7+
exists -exec $WORK/some/nonexisting/directory/pkg2.test$GOEXE
8+
9+
go test -c ./pkg/...
10+
exists -exec pkg1.test$GOEXE
11+
exists -exec pkg2.test$GOEXE
12+
13+
! go test -c -o $WORK/bin/test/bin.test.exe ./pkg/...
14+
stderr '^with multiple packages, -o must refer to a directory or '$devnull
15+
16+
! go test -c ./...
17+
stderr '^cannot write test binary pkg1.test for multiple packages:\nexample/anotherpkg/pkg1\nexample/pkg/pkg1'
18+
19+
! go test -c -o $WORK/bin/test/ ./...
20+
stderr '^cannot write test binary pkg1.test for multiple packages:\nexample/anotherpkg/pkg1\nexample/pkg/pkg1'
21+
22+
! go test -o $WORK/bin/filename.exe ./pkg/...
23+
stderr '^with multiple packages, -o must refer to a directory or '$devnull
24+
25+
! go test -o $WORK/bin/ ./...
26+
stderr '^cannot write test binary pkg1.test for multiple packages:\nexample/anotherpkg/pkg1\nexample/pkg/pkg1'
27+
28+
go test -c -o $devnull ./...
29+
30+
rm pkg1.test$GOEXE
31+
rm pkg2.test$GOEXE
32+
go test -o . ./pkg/...
33+
exists -exec pkg1.test$GOEXE
34+
exists -exec pkg2.test$GOEXE
35+
36+
-- go.mod --
37+
module example
38+
39+
-- pkg/pkg1/pkg1_test.go --
40+
package pkg1
41+
42+
-- pkg/pkg2/pkg2_test.go --
43+
package pkg2
44+
45+
-- anotherpkg/pkg1/pkg1_test.go --
46+
package pkg1

0 commit comments

Comments
 (0)