Skip RSATest.DISABLED_BlindingCacheConcurrency in SDE.

The SDE bot has started developing flakes with that many threads.
(Unclear if it is due to SDE or running too many copies of the test
in parallel.)

Change-Id: I0081b6d75882b946bdccee5405dc688d0035d565
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40066
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/util/all_tests.go b/util/all_tests.go
index aba4447..8188675 100644
--- a/util/all_tests.go
+++ b/util/all_tests.go
@@ -17,7 +17,6 @@
 import (
 	"bufio"
 	"bytes"
-	"encoding/json"
 	"errors"
 	"flag"
 	"fmt"
@@ -31,6 +30,7 @@
 	"sync"
 	"syscall"
 
+	"boringssl.googlesource.com/boringssl/util/testconfig"
 	"boringssl.googlesource.com/boringssl/util/testresult"
 )
 
@@ -55,8 +55,8 @@
 }
 
 type test struct {
-	env              []string
-	args             []string
+	testconfig.Test
+
 	shard, numShards int
 	// cpu, if not empty, contains a code to simulate. For SDE, run `sde64
 	// -help` to get a list of these codes. For ARM, see gtest_main.cc for
@@ -146,8 +146,8 @@
 )
 
 func runTestOnce(test test, mallocNumToFail int64) (passed bool, err error) {
-	prog := path.Join(*buildDir, test.args[0])
-	args := append([]string{}, test.args[1:]...)
+	prog := path.Join(*buildDir, test.Cmd[0])
+	args := append([]string{}, test.Cmd[1:]...)
 	if *simulateARMCPUs && test.cpu != "" {
 		args = append(args, "--cpu="+test.cpu)
 	}
@@ -168,10 +168,10 @@
 	} else {
 		cmd = exec.Command(prog, args...)
 	}
-	if test.env != nil {
+	if test.Env != nil {
 		cmd.Env = make([]string, len(os.Environ()))
 		copy(cmd.Env, os.Environ())
-		cmd.Env = append(cmd.Env, test.env...)
+		cmd.Env = append(cmd.Env, test.Env...)
 	}
 	var outBuf bytes.Buffer
 	cmd.Stdout = &outBuf
@@ -249,31 +249,6 @@
 	panic("Couldn't find BUILDING.md in a parent directory!")
 }
 
-func parseTestConfig(filename string) ([]test, error) {
-	in, err := os.Open(filename)
-	if err != nil {
-		return nil, err
-	}
-	defer in.Close()
-
-	decoder := json.NewDecoder(in)
-	var testArgs [][]string
-	if err := decoder.Decode(&testArgs); err != nil {
-		return nil, err
-	}
-
-	var result []test
-	for _, args := range testArgs {
-		var env []string
-		for len(args) > 0 && strings.HasPrefix(args[0], "$") {
-			env = append(env, args[0][1:])
-			args = args[1:]
-		}
-		result = append(result, test{args: args, env: env})
-	}
-	return result, nil
-}
-
 func worker(tests <-chan test, results chan<- result, done *sync.WaitGroup) {
 	defer done.Done()
 	for test := range tests {
@@ -283,7 +258,7 @@
 }
 
 func (t test) shortName() string {
-	return t.args[0] + t.shardMsg() + t.cpuMsg() + t.envMsg()
+	return t.Cmd[0] + t.shardMsg() + t.cpuMsg() + t.envMsg()
 }
 
 func SpaceIf(returnSpace bool) string {
@@ -294,7 +269,7 @@
 }
 
 func (t test) longName() string {
-	return strings.Join(t.env, " ") + SpaceIf(len(t.env) != 0) + strings.Join(t.args, " ") + t.cpuMsg()
+	return strings.Join(t.Env, " ") + SpaceIf(len(t.Env) != 0) + strings.Join(t.Cmd, " ") + t.cpuMsg()
 }
 
 func (t test) shardMsg() string {
@@ -314,7 +289,7 @@
 }
 
 func (t test) envMsg() string {
-	if len(t.env) == 0 {
+	if len(t.Env) == 0 {
 		return ""
 	}
 
@@ -322,16 +297,16 @@
 }
 
 func (t test) getGTestShards() ([]test, error) {
-	if *numWorkers == 1 || len(t.args) != 1 {
+	if *numWorkers == 1 || len(t.Cmd) != 1 {
 		return []test{t}, nil
 	}
 
 	// Only shard the three GTest-based tests.
-	if t.args[0] != "crypto/crypto_test" && t.args[0] != "ssl/ssl_test" && t.args[0] != "decrepit/decrepit_test" {
+	if t.Cmd[0] != "crypto/crypto_test" && t.Cmd[0] != "ssl/ssl_test" && t.Cmd[0] != "decrepit/decrepit_test" {
 		return []test{t}, nil
 	}
 
-	prog := path.Join(*buildDir, t.args[0])
+	prog := path.Join(*buildDir, t.Cmd[0])
 	cmd := exec.Command(prog, "--gtest_list_tests")
 	var stdout bytes.Buffer
 	cmd.Stdout = &stdout
@@ -388,7 +363,7 @@
 			n = testsPerShard
 		}
 		shard := t
-		shard.args = []string{shard.args[0], "--gtest_filter=" + strings.Join(shuffled[i:i+n], ":")}
+		shard.Cmd = []string{shard.Cmd[0], "--gtest_filter=" + strings.Join(shuffled[i:i+n], ":")}
 		shard.shard = len(shards)
 		shards = append(shards, shard)
 	}
@@ -404,7 +379,7 @@
 	flag.Parse()
 	setWorkingDirectory()
 
-	testCases, err := parseTestConfig("util/all_tests.json")
+	testCases, err := testconfig.ParseTestConfig("util/all_tests.json")
 	if err != nil {
 		fmt.Printf("Failed to parse input: %s\n", err)
 		os.Exit(1)
@@ -420,8 +395,12 @@
 	}
 
 	go func() {
-		for _, test := range testCases {
+		for _, baseTest := range testCases {
+			test := test{Test: baseTest}
 			if *useSDE {
+				if test.SkipSDE {
+					continue
+				}
 				// SDE generates plenty of tasks and gets slower
 				// with additional sharding.
 				for _, cpu := range sdeCPUs {
@@ -459,7 +438,7 @@
 	var failed, skipped []test
 	for testResult := range results {
 		test := testResult.Test
-		args := test.args
+		args := test.Cmd
 
 		if testResult.Error == errTestSkipped {
 			fmt.Printf("%s\n", test.longName())
@@ -491,14 +470,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.args, " "), test.cpuMsg())
+			fmt.Printf("\t%s%s\n", strings.Join(test.Cmd, " "), test.cpuMsg())
 		}
 	}
 
 	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.args, " "), test.cpuMsg())
+			fmt.Printf("\t%s%s\n", strings.Join(test.Cmd, " "), test.cpuMsg())
 		}
 		os.Exit(1)
 	}
diff --git a/util/all_tests.json b/util/all_tests.json
index ca2db25..c4c2787 100644
--- a/util/all_tests.json
+++ b/util/all_tests.json
@@ -1,9 +1,28 @@
 [
-	["crypto/crypto_test"],
-	["crypto/crypto_test", "--gtest_also_run_disabled_tests", "--gtest_filter=RSATest.DISABLED_BlindingCacheConcurrency:BNTest.DISABLED_WycheproofPrimality"],
-	["crypto/urandom_test"],
-	["$OPENSSL_ia32cap=~0x4000000000000000", "crypto/urandom_test"],
-	["crypto/crypto_test", "--fork_unsafe_buffering", "--gtest_filter=RandTest.*:-RandTest.Fork"],
-	["decrepit/decrepit_test"],
-	["ssl/ssl_test"]
+  {
+    "cmd": ["crypto/crypto_test"]
+  },
+  {
+    "cmd": ["crypto/crypto_test", "--gtest_also_run_disabled_tests", "--gtest_filter=BNTest.DISABLED_WycheproofPrimality"]
+  },
+  {
+    "cmd": ["crypto/crypto_test", "--gtest_also_run_disabled_tests", "--gtest_filter=RSATest.DISABLED_BlindingCacheConcurrency"],
+    "skip_sde": true
+  },
+  {
+    "cmd": ["crypto/urandom_test"]
+  },
+  {
+    "cmd": ["crypto/urandom_test"],
+    "env": ["OPENSSL_ia32cap=~0x4000000000000000"]
+  },
+  {
+    "cmd": ["crypto/crypto_test", "--fork_unsafe_buffering", "--gtest_filter=RandTest.*:-RandTest.Fork"]
+  },
+  {
+    "cmd": ["decrepit/decrepit_test"]
+  },
+  {
+    "cmd": ["ssl/ssl_test"]
+  }
 ]
diff --git a/util/run_android_tests.go b/util/run_android_tests.go
index b2ad913..5eae742 100644
--- a/util/run_android_tests.go
+++ b/util/run_android_tests.go
@@ -17,7 +17,6 @@
 import (
 	"bufio"
 	"bytes"
-	"encoding/json"
 	"errors"
 	"flag"
 	"fmt"
@@ -29,6 +28,8 @@
 	"runtime"
 	"strconv"
 	"strings"
+
+	"boringssl.googlesource.com/boringssl/util/testconfig"
 )
 
 var (
@@ -244,37 +245,6 @@
 	return nil
 }
 
-type test struct {
-	args []string
-	env  []string
-}
-
-func parseTestConfig(filename string) ([]test, error) {
-	in, err := os.Open(filename)
-	if err != nil {
-		return nil, err
-	}
-	defer in.Close()
-
-	decoder := json.NewDecoder(in)
-	var result [][]string
-	if err := decoder.Decode(&result); err != nil {
-		return nil, err
-	}
-
-	tests := make([]test, 0, len(result))
-	for _, args := range result {
-		var env []string
-		for len(args) > 0 && strings.HasPrefix(args[0], "$") {
-			env = append(env, args[0][1:])
-			args = args[1:]
-		}
-		tests = append(tests, test{args: args, env: env})
-	}
-
-	return tests, nil
-}
-
 func copyFile(dst, src string) error {
 	srcFile, err := os.Open(src)
 	if err != nil {
@@ -338,7 +308,7 @@
 			"BUILDING.md",
 		)
 
-		tests, err := parseTestConfig("util/all_tests.json")
+		tests, err := testconfig.ParseTestConfig("util/all_tests.json")
 		if err != nil {
 			fmt.Printf("Failed to parse input: %s\n", err)
 			os.Exit(1)
@@ -346,11 +316,11 @@
 
 		seenBinary := make(map[string]struct{})
 		for _, test := range tests {
-			if _, ok := seenBinary[test.args[0]]; !ok {
-				binaries = append(binaries, test.args[0])
-				seenBinary[test.args[0]] = struct{}{}
+			if _, ok := seenBinary[test.Cmd[0]]; !ok {
+				binaries = append(binaries, test.Cmd[0])
+				seenBinary[test.Cmd[0]] = struct{}{}
 			}
-			for _, arg := range test.args[1:] {
+			for _, arg := range test.Cmd[1:] {
 				if strings.Contains(arg, "/") {
 					files = append(files, arg)
 				}
diff --git a/util/testconfig/testconfig.go b/util/testconfig/testconfig.go
new file mode 100644
index 0000000..1efcab1
--- /dev/null
+++ b/util/testconfig/testconfig.go
@@ -0,0 +1,41 @@
+/* Copyright (c) 2020, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+package testconfig
+
+import (
+	"encoding/json"
+	"os"
+)
+
+type Test struct {
+	Cmd     []string `json:"cmd"`
+	Env     []string `json:"env"`
+	SkipSDE bool     `json:"skip_sde"`
+}
+
+func ParseTestConfig(filename string) ([]Test, error) {
+	in, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer in.Close()
+
+	decoder := json.NewDecoder(in)
+	var result []Test
+	if err := decoder.Decode(&result); err != nil {
+		return nil, err
+	}
+	return result, nil
+}