Use GTest's built-in sharding feature
https://github.com/google/googletest/blob/main/docs/advanced.md#distributing-test-functions-to-multiple-machines
Change-Id: I3998bb4735800a645286728852cb8494b28a6577
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/51225
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
diff --git a/util/all_tests.go b/util/all_tests.go
index 884da26..4f484f3 100644
--- a/util/all_tests.go
+++ b/util/all_tests.go
@@ -15,12 +15,10 @@
package main
import (
- "bufio"
"bytes"
"errors"
"flag"
"fmt"
- "math/rand"
"os"
"os/exec"
"path"
@@ -175,11 +173,17 @@
} else {
cmd = exec.Command(prog, args...)
}
- if test.Env != nil {
+ if test.Env != nil || test.numShards != 0 {
cmd.Env = make([]string, len(os.Environ()))
copy(cmd.Env, os.Environ())
+ }
+ if test.Env != nil {
cmd.Env = append(cmd.Env, test.Env...)
}
+ if test.numShards != 0 {
+ cmd.Env = append(cmd.Env, fmt.Sprintf("GTEST_SHARD_INDEX=%d", test.shard))
+ cmd.Env = append(cmd.Env, fmt.Sprintf("GTEST_TOTAL_SHARDS=%d", test.numShards))
+ }
var outBuf bytes.Buffer
cmd.Stdout = &outBuf
cmd.Stderr = &outBuf
@@ -265,7 +269,7 @@
}
func (t test) shortName() string {
- return t.Cmd[0] + t.shardMsg() + t.cpuMsg() + t.envMsg()
+ return strings.Join(t.Cmd, " ") + t.shardMsg() + t.cpuMsg() + t.envMsg()
}
func SpaceIf(returnSpace bool) string {
@@ -276,7 +280,7 @@
}
func (t test) longName() string {
- return strings.Join(t.Env, " ") + SpaceIf(len(t.Env) != 0) + strings.Join(t.Cmd, " ") + t.cpuMsg()
+ return strings.Join(t.Env, " ") + SpaceIf(len(t.Env) != 0) + strings.Join(t.Cmd, " ") + t.shardMsg() + t.cpuMsg()
}
func (t test) shardMsg() string {
@@ -313,70 +317,11 @@
return []test{t}, nil
}
- prog := path.Join(*buildDir, t.Cmd[0])
- cmd := exec.Command(prog, "--gtest_list_tests")
- var stdout bytes.Buffer
- cmd.Stdout = &stdout
- if err := cmd.Start(); err != nil {
- return nil, err
- }
- if err := cmd.Wait(); err != nil {
- return nil, err
- }
-
- var group string
- var tests []string
- scanner := bufio.NewScanner(&stdout)
- for scanner.Scan() {
- line := scanner.Text()
-
- // Remove the parameter comment and trailing space.
- if idx := strings.Index(line, "#"); idx >= 0 {
- line = line[:idx]
- }
- line = strings.TrimSpace(line)
- if len(line) == 0 {
- continue
- }
-
- if line[len(line)-1] == '.' {
- group = line
- continue
- }
-
- if len(group) == 0 {
- return nil, fmt.Errorf("found test case %q without group", line)
- }
- tests = append(tests, group+line)
- }
-
- const testsPerShard = 20
- if len(tests) <= testsPerShard {
- return []test{t}, nil
- }
-
- // Slow tests which process large test vector files tend to be grouped
- // together, so shuffle the order.
- shuffled := make([]string, len(tests))
- perm := rand.Perm(len(tests))
- for i, j := range perm {
- shuffled[i] = tests[j]
- }
-
- var shards []test
- for i := 0; i < len(shuffled); i += testsPerShard {
- n := len(shuffled) - i
- if n > testsPerShard {
- n = testsPerShard
- }
- shard := t
- shard.Cmd = []string{shard.Cmd[0], "--gtest_filter=" + strings.Join(shuffled[i:i+n], ":")}
- shard.shard = len(shards)
- shards = append(shards, shard)
- }
-
+ shards := make([]test, *numWorkers)
for i := range shards {
- shards[i].numShards = len(shards)
+ shards[i] = t
+ shards[i].shard = i
+ shards[i].numShards = *numWorkers
}
return shards, nil
@@ -477,14 +422,14 @@
if len(skipped) > 0 {
fmt.Printf("\n%d of %d tests were skipped:\n", len(skipped), len(testCases))
for _, test := range skipped {
- fmt.Printf("\t%s%s\n", strings.Join(test.Cmd, " "), test.cpuMsg())
+ fmt.Printf("\t%s\n", test.shortName())
}
}
if len(failed) > 0 {
fmt.Printf("\n%d of %d tests failed:\n", len(failed), len(testCases))
for _, test := range failed {
- fmt.Printf("\t%s%s\n", strings.Join(test.Cmd, " "), test.cpuMsg())
+ fmt.Printf("\t%s\n", test.shortName())
}
os.Exit(1)
}