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) }