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