aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2015-12-21 20:42:40 -0500
committerRuss Cox <rsc@golang.org>2015-12-29 17:18:04 +0000
commitd513ee774cb3747eccc6b3483a67dbb9118dae8d (patch)
treef6e5aecc192c32cb6ee328bf014688f686530dc7
parentb6473ff132d580ca7ca1ff6d6523fa595016a8a6 (diff)
downloadgo-d513ee774cb3747eccc6b3483a67dbb9118dae8d.tar.xz
cmd/dist: run shards of test dir in parallel
Saves 15 seconds from all.bash on my laptop (3:20 -> 3:05). Change-Id: Ic5dc3c7804e78b584789dd856a3dada94000a8e2 Reviewed-on: https://go-review.googlesource.com/18199 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
-rw-r--r--src/cmd/dist/test.go42
1 files changed, 31 insertions, 11 deletions
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
index 77c736501a..cb99b0e358 100644
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -17,6 +17,7 @@ import (
"regexp"
"strconv"
"strings"
+ "sync"
"time"
)
@@ -195,6 +196,7 @@ func (t *tester) run() {
}
dt := dt // dt used in background after this iteration
if err := dt.fn(&dt); err != nil {
+ t.runPending(dt) // in case that hasn't been done yet
t.failed = true
if t.keepGoing {
log.Printf("Failed: %v", err)
@@ -788,8 +790,11 @@ func (t *tester) cgoTest(dt *distTest) error {
}
// run pending test commands, in parallel, emitting headers as appropriate.
-// When finished, emit header for dt, which is going to run after the
+// When finished, emit header for nextTest, which is going to run after the
// pending commands are done (and runPending returns).
+// A test should call runPending if it wants to make sure that it is not
+// running in parallel with earlier tests, or if it has some other reason
+// for needing the earlier tests to be done.
func (t *tester) runPending(nextTest *distTest) {
worklist := t.worklist
t.worklist = nil
@@ -961,20 +966,35 @@ func (t *tester) raceTest(dt *distTest) error {
return nil
}
+var runtest struct {
+ sync.Once
+ exe string
+ err error
+}
+
func (t *tester) testDirTest(dt *distTest, shard, shards int) error {
- t.runPending(dt)
- const runExe = "runtest.exe" // named exe for Windows, but harmless elsewhere
- cmd := t.dirCmd("test", "go", "build", "-o", runExe, "run.go")
- cmd.Env = mergeEnvLists([]string{"GOOS=" + t.gohostos, "GOARCH=" + t.gohostarch, "GOMAXPROCS="}, os.Environ())
- if err := cmd.Run(); err != nil {
- return err
+ runtest.Do(func() {
+ const exe = "runtest.exe" // named exe for Windows, but harmless elsewhere
+ cmd := t.dirCmd("test", "go", "build", "-o", exe, "run.go")
+ cmd.Env = mergeEnvLists([]string{"GOOS=" + t.gohostos, "GOARCH=" + t.gohostarch, "GOMAXPROCS="}, os.Environ())
+ runtest.exe = filepath.Join(cmd.Dir, exe)
+ if err := cmd.Run(); err != nil {
+ runtest.err = err
+ return
+ }
+ xatexit(func() {
+ os.Remove(runtest.exe)
+ })
+ })
+ if runtest.err != nil {
+ return runtest.err
}
- absExe := filepath.Join(cmd.Dir, runExe)
- defer os.Remove(absExe)
- return t.dirCmd("test", absExe,
+
+ t.addCmd(dt, "test", runtest.exe,
fmt.Sprintf("--shard=%d", shard),
fmt.Sprintf("--shards=%d", shards),
- ).Run()
+ )
+ return nil
}
func (t *tester) shootoutTests() []string {