Commit d513ee77 authored by Russ Cox's avatar Russ Cox

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/18199Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent b6473ff1
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
) )
...@@ -195,6 +196,7 @@ func (t *tester) run() { ...@@ -195,6 +196,7 @@ func (t *tester) run() {
} }
dt := dt // dt used in background after this iteration dt := dt // dt used in background after this iteration
if err := dt.fn(&dt); err != nil { if err := dt.fn(&dt); err != nil {
t.runPending(dt) // in case that hasn't been done yet
t.failed = true t.failed = true
if t.keepGoing { if t.keepGoing {
log.Printf("Failed: %v", err) log.Printf("Failed: %v", err)
...@@ -788,8 +790,11 @@ func (t *tester) cgoTest(dt *distTest) error { ...@@ -788,8 +790,11 @@ func (t *tester) cgoTest(dt *distTest) error {
} }
// run pending test commands, in parallel, emitting headers as appropriate. // 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). // 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) { func (t *tester) runPending(nextTest *distTest) {
worklist := t.worklist worklist := t.worklist
t.worklist = nil t.worklist = nil
...@@ -961,20 +966,35 @@ func (t *tester) raceTest(dt *distTest) error { ...@@ -961,20 +966,35 @@ func (t *tester) raceTest(dt *distTest) error {
return nil return nil
} }
var runtest struct {
sync.Once
exe string
err error
}
func (t *tester) testDirTest(dt *distTest, shard, shards int) error { func (t *tester) testDirTest(dt *distTest, shard, shards int) error {
t.runPending(dt) runtest.Do(func() {
const runExe = "runtest.exe" // named exe for Windows, but harmless elsewhere const exe = "runtest.exe" // named exe for Windows, but harmless elsewhere
cmd := t.dirCmd("test", "go", "build", "-o", runExe, "run.go") cmd := t.dirCmd("test", "go", "build", "-o", exe, "run.go")
cmd.Env = mergeEnvLists([]string{"GOOS=" + t.gohostos, "GOARCH=" + t.gohostarch, "GOMAXPROCS="}, os.Environ()) 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 { if err := cmd.Run(); err != nil {
return err runtest.err = err
return
} }
absExe := filepath.Join(cmd.Dir, runExe) xatexit(func() {
defer os.Remove(absExe) os.Remove(runtest.exe)
return t.dirCmd("test", absExe, })
})
if runtest.err != nil {
return runtest.err
}
t.addCmd(dt, "test", runtest.exe,
fmt.Sprintf("--shard=%d", shard), fmt.Sprintf("--shard=%d", shard),
fmt.Sprintf("--shards=%d", shards), fmt.Sprintf("--shards=%d", shards),
).Run() )
return nil
} }
func (t *tester) shootoutTests() []string { func (t *tester) shootoutTests() []string {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment