1*8fb009dcSAndroid Build Coastguard Worker// Copyright (c) 2015, Google Inc. 2*8fb009dcSAndroid Build Coastguard Worker// 3*8fb009dcSAndroid Build Coastguard Worker// Permission to use, copy, modify, and/or distribute this software for any 4*8fb009dcSAndroid Build Coastguard Worker// purpose with or without fee is hereby granted, provided that the above 5*8fb009dcSAndroid Build Coastguard Worker// copyright notice and this permission notice appear in all copies. 6*8fb009dcSAndroid Build Coastguard Worker// 7*8fb009dcSAndroid Build Coastguard Worker// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8*8fb009dcSAndroid Build Coastguard Worker// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9*8fb009dcSAndroid Build Coastguard Worker// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10*8fb009dcSAndroid Build Coastguard Worker// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11*8fb009dcSAndroid Build Coastguard Worker// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12*8fb009dcSAndroid Build Coastguard Worker// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13*8fb009dcSAndroid Build Coastguard Worker// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14*8fb009dcSAndroid Build Coastguard Worker 15*8fb009dcSAndroid Build Coastguard Worker//go:build ignore 16*8fb009dcSAndroid Build Coastguard Worker 17*8fb009dcSAndroid Build Coastguard Workerpackage main 18*8fb009dcSAndroid Build Coastguard Worker 19*8fb009dcSAndroid Build Coastguard Workerimport ( 20*8fb009dcSAndroid Build Coastguard Worker "bytes" 21*8fb009dcSAndroid Build Coastguard Worker "errors" 22*8fb009dcSAndroid Build Coastguard Worker "flag" 23*8fb009dcSAndroid Build Coastguard Worker "fmt" 24*8fb009dcSAndroid Build Coastguard Worker "os" 25*8fb009dcSAndroid Build Coastguard Worker "os/exec" 26*8fb009dcSAndroid Build Coastguard Worker "path" 27*8fb009dcSAndroid Build Coastguard Worker "runtime" 28*8fb009dcSAndroid Build Coastguard Worker "strconv" 29*8fb009dcSAndroid Build Coastguard Worker "strings" 30*8fb009dcSAndroid Build Coastguard Worker "sync" 31*8fb009dcSAndroid Build Coastguard Worker "syscall" 32*8fb009dcSAndroid Build Coastguard Worker 33*8fb009dcSAndroid Build Coastguard Worker "boringssl.googlesource.com/boringssl/util/testconfig" 34*8fb009dcSAndroid Build Coastguard Worker "boringssl.googlesource.com/boringssl/util/testresult" 35*8fb009dcSAndroid Build Coastguard Worker) 36*8fb009dcSAndroid Build Coastguard Worker 37*8fb009dcSAndroid Build Coastguard Worker// TODO(davidben): Link tests with the malloc shim and port -malloc-test to this runner. 38*8fb009dcSAndroid Build Coastguard Worker 39*8fb009dcSAndroid Build Coastguard Workervar ( 40*8fb009dcSAndroid Build Coastguard Worker useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind") 41*8fb009dcSAndroid Build Coastguard Worker useCallgrind = flag.Bool("callgrind", false, "If true, run code under valgrind to generate callgrind traces.") 42*8fb009dcSAndroid Build Coastguard Worker useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb") 43*8fb009dcSAndroid Build Coastguard Worker useSDE = flag.Bool("sde", false, "If true, run BoringSSL code under Intel's SDE for each supported chip") 44*8fb009dcSAndroid Build Coastguard Worker sdePath = flag.String("sde-path", "sde", "The path to find the sde binary.") 45*8fb009dcSAndroid Build Coastguard Worker buildDir = flag.String("build-dir", "build", "The build directory to run the tests from.") 46*8fb009dcSAndroid Build Coastguard Worker numWorkers = flag.Int("num-workers", runtime.NumCPU(), "Runs the given number of workers when testing.") 47*8fb009dcSAndroid Build Coastguard Worker jsonOutput = flag.String("json-output", "", "The file to output JSON results to.") 48*8fb009dcSAndroid Build Coastguard Worker mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.") 49*8fb009dcSAndroid Build Coastguard Worker mallocTestDebug = flag.Bool("malloc-test-debug", false, "If true, ask each test to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.") 50*8fb009dcSAndroid Build Coastguard Worker simulateARMCPUs = flag.Bool("simulate-arm-cpus", simulateARMCPUsDefault(), "If true, runs tests simulating different ARM CPUs.") 51*8fb009dcSAndroid Build Coastguard Worker qemuBinary = flag.String("qemu", "", "Optional, absolute path to a binary location for QEMU runtime.") 52*8fb009dcSAndroid Build Coastguard Worker) 53*8fb009dcSAndroid Build Coastguard Worker 54*8fb009dcSAndroid Build Coastguard Workerfunc simulateARMCPUsDefault() bool { 55*8fb009dcSAndroid Build Coastguard Worker return (runtime.GOOS == "linux" || runtime.GOOS == "android") && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") 56*8fb009dcSAndroid Build Coastguard Worker} 57*8fb009dcSAndroid Build Coastguard Worker 58*8fb009dcSAndroid Build Coastguard Workertype test struct { 59*8fb009dcSAndroid Build Coastguard Worker testconfig.Test 60*8fb009dcSAndroid Build Coastguard Worker 61*8fb009dcSAndroid Build Coastguard Worker shard, numShards int 62*8fb009dcSAndroid Build Coastguard Worker // cpu, if not empty, contains a code to simulate. For SDE, run `sde64 63*8fb009dcSAndroid Build Coastguard Worker // -help` to get a list of these codes. For ARM, see gtest_main.cc for 64*8fb009dcSAndroid Build Coastguard Worker // the supported values. 65*8fb009dcSAndroid Build Coastguard Worker cpu string 66*8fb009dcSAndroid Build Coastguard Worker} 67*8fb009dcSAndroid Build Coastguard Worker 68*8fb009dcSAndroid Build Coastguard Workertype result struct { 69*8fb009dcSAndroid Build Coastguard Worker Test test 70*8fb009dcSAndroid Build Coastguard Worker Passed bool 71*8fb009dcSAndroid Build Coastguard Worker Error error 72*8fb009dcSAndroid Build Coastguard Worker} 73*8fb009dcSAndroid Build Coastguard Worker 74*8fb009dcSAndroid Build Coastguard Worker// sdeCPUs contains a list of CPU code that we run all tests under when *useSDE 75*8fb009dcSAndroid Build Coastguard Worker// is true. 76*8fb009dcSAndroid Build Coastguard Workervar sdeCPUs = []string{ 77*8fb009dcSAndroid Build Coastguard Worker "p4p", // Pentium4 Prescott 78*8fb009dcSAndroid Build Coastguard Worker "mrm", // Merom 79*8fb009dcSAndroid Build Coastguard Worker "pnr", // Penryn 80*8fb009dcSAndroid Build Coastguard Worker "nhm", // Nehalem 81*8fb009dcSAndroid Build Coastguard Worker "wsm", // Westmere 82*8fb009dcSAndroid Build Coastguard Worker "snb", // Sandy Bridge 83*8fb009dcSAndroid Build Coastguard Worker "ivb", // Ivy Bridge 84*8fb009dcSAndroid Build Coastguard Worker "hsw", // Haswell 85*8fb009dcSAndroid Build Coastguard Worker "bdw", // Broadwell 86*8fb009dcSAndroid Build Coastguard Worker "slt", // Saltwell 87*8fb009dcSAndroid Build Coastguard Worker "slm", // Silvermont 88*8fb009dcSAndroid Build Coastguard Worker "glm", // Goldmont 89*8fb009dcSAndroid Build Coastguard Worker "glp", // Goldmont Plus 90*8fb009dcSAndroid Build Coastguard Worker "tnt", // Tremont 91*8fb009dcSAndroid Build Coastguard Worker "skl", // Skylake 92*8fb009dcSAndroid Build Coastguard Worker "cnl", // Cannon Lake 93*8fb009dcSAndroid Build Coastguard Worker "icl", // Ice Lake 94*8fb009dcSAndroid Build Coastguard Worker "skx", // Skylake server 95*8fb009dcSAndroid Build Coastguard Worker "clx", // Cascade Lake 96*8fb009dcSAndroid Build Coastguard Worker "cpx", // Cooper Lake 97*8fb009dcSAndroid Build Coastguard Worker "icx", // Ice Lake server 98*8fb009dcSAndroid Build Coastguard Worker "tgl", // Tiger Lake 99*8fb009dcSAndroid Build Coastguard Worker} 100*8fb009dcSAndroid Build Coastguard Worker 101*8fb009dcSAndroid Build Coastguard Workervar armCPUs = []string{ 102*8fb009dcSAndroid Build Coastguard Worker "none", // No support for any ARM extensions. 103*8fb009dcSAndroid Build Coastguard Worker "neon", // Support for NEON. 104*8fb009dcSAndroid Build Coastguard Worker "crypto", // Support for NEON and crypto extensions. 105*8fb009dcSAndroid Build Coastguard Worker} 106*8fb009dcSAndroid Build Coastguard Worker 107*8fb009dcSAndroid Build Coastguard Workerfunc valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd { 108*8fb009dcSAndroid Build Coastguard Worker valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full", "--quiet"} 109*8fb009dcSAndroid Build Coastguard Worker if dbAttach { 110*8fb009dcSAndroid Build Coastguard Worker valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p") 111*8fb009dcSAndroid Build Coastguard Worker } 112*8fb009dcSAndroid Build Coastguard Worker valgrindArgs = append(valgrindArgs, path) 113*8fb009dcSAndroid Build Coastguard Worker valgrindArgs = append(valgrindArgs, args...) 114*8fb009dcSAndroid Build Coastguard Worker 115*8fb009dcSAndroid Build Coastguard Worker return exec.Command("valgrind", valgrindArgs...) 116*8fb009dcSAndroid Build Coastguard Worker} 117*8fb009dcSAndroid Build Coastguard Worker 118*8fb009dcSAndroid Build Coastguard Workerfunc callgrindOf(path string, args ...string) *exec.Cmd { 119*8fb009dcSAndroid Build Coastguard Worker valgrindArgs := []string{"-q", "--tool=callgrind", "--dump-instr=yes", "--collect-jumps=yes", "--callgrind-out-file=" + *buildDir + "/callgrind/callgrind.out.%p"} 120*8fb009dcSAndroid Build Coastguard Worker valgrindArgs = append(valgrindArgs, path) 121*8fb009dcSAndroid Build Coastguard Worker valgrindArgs = append(valgrindArgs, args...) 122*8fb009dcSAndroid Build Coastguard Worker 123*8fb009dcSAndroid Build Coastguard Worker return exec.Command("valgrind", valgrindArgs...) 124*8fb009dcSAndroid Build Coastguard Worker} 125*8fb009dcSAndroid Build Coastguard Worker 126*8fb009dcSAndroid Build Coastguard Workerfunc gdbOf(path string, args ...string) *exec.Cmd { 127*8fb009dcSAndroid Build Coastguard Worker xtermArgs := []string{"-e", "gdb", "--args"} 128*8fb009dcSAndroid Build Coastguard Worker xtermArgs = append(xtermArgs, path) 129*8fb009dcSAndroid Build Coastguard Worker xtermArgs = append(xtermArgs, args...) 130*8fb009dcSAndroid Build Coastguard Worker 131*8fb009dcSAndroid Build Coastguard Worker return exec.Command("xterm", xtermArgs...) 132*8fb009dcSAndroid Build Coastguard Worker} 133*8fb009dcSAndroid Build Coastguard Worker 134*8fb009dcSAndroid Build Coastguard Workerfunc sdeOf(cpu, path string, args ...string) *exec.Cmd { 135*8fb009dcSAndroid Build Coastguard Worker sdeArgs := []string{"-" + cpu} 136*8fb009dcSAndroid Build Coastguard Worker // The kernel's vdso code for gettimeofday sometimes uses the RDTSCP 137*8fb009dcSAndroid Build Coastguard Worker // instruction. Although SDE has a -chip_check_vsyscall flag that 138*8fb009dcSAndroid Build Coastguard Worker // excludes such code by default, it does not seem to work. Instead, 139*8fb009dcSAndroid Build Coastguard Worker // pass the -chip_check_exe_only flag which retains test coverage when 140*8fb009dcSAndroid Build Coastguard Worker // statically linked and excludes the vdso. 141*8fb009dcSAndroid Build Coastguard Worker if cpu == "p4p" || cpu == "pnr" || cpu == "mrm" || cpu == "slt" { 142*8fb009dcSAndroid Build Coastguard Worker sdeArgs = append(sdeArgs, "-chip_check_exe_only") 143*8fb009dcSAndroid Build Coastguard Worker } 144*8fb009dcSAndroid Build Coastguard Worker sdeArgs = append(sdeArgs, "--", path) 145*8fb009dcSAndroid Build Coastguard Worker sdeArgs = append(sdeArgs, args...) 146*8fb009dcSAndroid Build Coastguard Worker return exec.Command(*sdePath, sdeArgs...) 147*8fb009dcSAndroid Build Coastguard Worker} 148*8fb009dcSAndroid Build Coastguard Worker 149*8fb009dcSAndroid Build Coastguard Workerfunc qemuOf(path string, args ...string) *exec.Cmd { 150*8fb009dcSAndroid Build Coastguard Worker // The QEMU binary becomes the program to run, and the previous test program 151*8fb009dcSAndroid Build Coastguard Worker // to run instead becomes an additional argument to the QEMU binary. 152*8fb009dcSAndroid Build Coastguard Worker args = append([]string{path}, args...) 153*8fb009dcSAndroid Build Coastguard Worker return exec.Command(*qemuBinary, args...) 154*8fb009dcSAndroid Build Coastguard Worker} 155*8fb009dcSAndroid Build Coastguard Worker 156*8fb009dcSAndroid Build Coastguard Workervar ( 157*8fb009dcSAndroid Build Coastguard Worker errMoreMallocs = errors.New("child process did not exhaust all allocation calls") 158*8fb009dcSAndroid Build Coastguard Worker errTestSkipped = errors.New("test was skipped") 159*8fb009dcSAndroid Build Coastguard Worker) 160*8fb009dcSAndroid Build Coastguard Worker 161*8fb009dcSAndroid Build Coastguard Workerfunc runTestOnce(test test, mallocNumToFail int64) (passed bool, err error) { 162*8fb009dcSAndroid Build Coastguard Worker prog := path.Join(*buildDir, test.Cmd[0]) 163*8fb009dcSAndroid Build Coastguard Worker args := append([]string{}, test.Cmd[1:]...) 164*8fb009dcSAndroid Build Coastguard Worker if *simulateARMCPUs && test.cpu != "" { 165*8fb009dcSAndroid Build Coastguard Worker args = append(args, "--cpu="+test.cpu) 166*8fb009dcSAndroid Build Coastguard Worker } 167*8fb009dcSAndroid Build Coastguard Worker if *useSDE { 168*8fb009dcSAndroid Build Coastguard Worker // SDE is neither compatible with the unwind tester nor automatically 169*8fb009dcSAndroid Build Coastguard Worker // detected. 170*8fb009dcSAndroid Build Coastguard Worker args = append(args, "--no_unwind_tests") 171*8fb009dcSAndroid Build Coastguard Worker } 172*8fb009dcSAndroid Build Coastguard Worker 173*8fb009dcSAndroid Build Coastguard Worker var cmd *exec.Cmd 174*8fb009dcSAndroid Build Coastguard Worker if *useValgrind { 175*8fb009dcSAndroid Build Coastguard Worker cmd = valgrindOf(false, prog, args...) 176*8fb009dcSAndroid Build Coastguard Worker } else if *useCallgrind { 177*8fb009dcSAndroid Build Coastguard Worker cmd = callgrindOf(prog, args...) 178*8fb009dcSAndroid Build Coastguard Worker } else if *useGDB { 179*8fb009dcSAndroid Build Coastguard Worker cmd = gdbOf(prog, args...) 180*8fb009dcSAndroid Build Coastguard Worker } else if *useSDE { 181*8fb009dcSAndroid Build Coastguard Worker cmd = sdeOf(test.cpu, prog, args...) 182*8fb009dcSAndroid Build Coastguard Worker } else if *qemuBinary != "" { 183*8fb009dcSAndroid Build Coastguard Worker cmd = qemuOf(prog, args...) 184*8fb009dcSAndroid Build Coastguard Worker } else { 185*8fb009dcSAndroid Build Coastguard Worker cmd = exec.Command(prog, args...) 186*8fb009dcSAndroid Build Coastguard Worker } 187*8fb009dcSAndroid Build Coastguard Worker if test.Env != nil || test.numShards != 0 { 188*8fb009dcSAndroid Build Coastguard Worker cmd.Env = make([]string, len(os.Environ())) 189*8fb009dcSAndroid Build Coastguard Worker copy(cmd.Env, os.Environ()) 190*8fb009dcSAndroid Build Coastguard Worker } 191*8fb009dcSAndroid Build Coastguard Worker if test.Env != nil { 192*8fb009dcSAndroid Build Coastguard Worker cmd.Env = append(cmd.Env, test.Env...) 193*8fb009dcSAndroid Build Coastguard Worker } 194*8fb009dcSAndroid Build Coastguard Worker if test.numShards != 0 { 195*8fb009dcSAndroid Build Coastguard Worker cmd.Env = append(cmd.Env, fmt.Sprintf("GTEST_SHARD_INDEX=%d", test.shard)) 196*8fb009dcSAndroid Build Coastguard Worker cmd.Env = append(cmd.Env, fmt.Sprintf("GTEST_TOTAL_SHARDS=%d", test.numShards)) 197*8fb009dcSAndroid Build Coastguard Worker } 198*8fb009dcSAndroid Build Coastguard Worker var outBuf bytes.Buffer 199*8fb009dcSAndroid Build Coastguard Worker cmd.Stdout = &outBuf 200*8fb009dcSAndroid Build Coastguard Worker cmd.Stderr = &outBuf 201*8fb009dcSAndroid Build Coastguard Worker if mallocNumToFail >= 0 { 202*8fb009dcSAndroid Build Coastguard Worker cmd.Env = os.Environ() 203*8fb009dcSAndroid Build Coastguard Worker cmd.Env = append(cmd.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10)) 204*8fb009dcSAndroid Build Coastguard Worker if *mallocTestDebug { 205*8fb009dcSAndroid Build Coastguard Worker cmd.Env = append(cmd.Env, "MALLOC_ABORT_ON_FAIL=1") 206*8fb009dcSAndroid Build Coastguard Worker } 207*8fb009dcSAndroid Build Coastguard Worker cmd.Env = append(cmd.Env, "_MALLOC_CHECK=1") 208*8fb009dcSAndroid Build Coastguard Worker } 209*8fb009dcSAndroid Build Coastguard Worker 210*8fb009dcSAndroid Build Coastguard Worker if err := cmd.Start(); err != nil { 211*8fb009dcSAndroid Build Coastguard Worker return false, err 212*8fb009dcSAndroid Build Coastguard Worker } 213*8fb009dcSAndroid Build Coastguard Worker if err := cmd.Wait(); err != nil { 214*8fb009dcSAndroid Build Coastguard Worker if exitError, ok := err.(*exec.ExitError); ok { 215*8fb009dcSAndroid Build Coastguard Worker switch exitError.Sys().(syscall.WaitStatus).ExitStatus() { 216*8fb009dcSAndroid Build Coastguard Worker case 88: 217*8fb009dcSAndroid Build Coastguard Worker return false, errMoreMallocs 218*8fb009dcSAndroid Build Coastguard Worker case 89: 219*8fb009dcSAndroid Build Coastguard Worker fmt.Print(string(outBuf.Bytes())) 220*8fb009dcSAndroid Build Coastguard Worker return false, errTestSkipped 221*8fb009dcSAndroid Build Coastguard Worker } 222*8fb009dcSAndroid Build Coastguard Worker } 223*8fb009dcSAndroid Build Coastguard Worker fmt.Print(string(outBuf.Bytes())) 224*8fb009dcSAndroid Build Coastguard Worker return false, err 225*8fb009dcSAndroid Build Coastguard Worker } 226*8fb009dcSAndroid Build Coastguard Worker 227*8fb009dcSAndroid Build Coastguard Worker // Account for Windows line-endings. 228*8fb009dcSAndroid Build Coastguard Worker stdout := bytes.Replace(outBuf.Bytes(), []byte("\r\n"), []byte("\n"), -1) 229*8fb009dcSAndroid Build Coastguard Worker 230*8fb009dcSAndroid Build Coastguard Worker if bytes.HasSuffix(stdout, []byte("PASS\n")) && 231*8fb009dcSAndroid Build Coastguard Worker (len(stdout) == 5 || stdout[len(stdout)-6] == '\n') { 232*8fb009dcSAndroid Build Coastguard Worker return true, nil 233*8fb009dcSAndroid Build Coastguard Worker } 234*8fb009dcSAndroid Build Coastguard Worker 235*8fb009dcSAndroid Build Coastguard Worker // Also accept a googletest-style pass line. This is left here in 236*8fb009dcSAndroid Build Coastguard Worker // transition until the tests are all converted and this script made 237*8fb009dcSAndroid Build Coastguard Worker // unnecessary. 238*8fb009dcSAndroid Build Coastguard Worker if bytes.Contains(stdout, []byte("\n[ PASSED ]")) { 239*8fb009dcSAndroid Build Coastguard Worker return true, nil 240*8fb009dcSAndroid Build Coastguard Worker } 241*8fb009dcSAndroid Build Coastguard Worker 242*8fb009dcSAndroid Build Coastguard Worker fmt.Print(string(outBuf.Bytes())) 243*8fb009dcSAndroid Build Coastguard Worker return false, nil 244*8fb009dcSAndroid Build Coastguard Worker} 245*8fb009dcSAndroid Build Coastguard Worker 246*8fb009dcSAndroid Build Coastguard Workerfunc runTest(test test) (bool, error) { 247*8fb009dcSAndroid Build Coastguard Worker if *mallocTest < 0 { 248*8fb009dcSAndroid Build Coastguard Worker return runTestOnce(test, -1) 249*8fb009dcSAndroid Build Coastguard Worker } 250*8fb009dcSAndroid Build Coastguard Worker 251*8fb009dcSAndroid Build Coastguard Worker for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ { 252*8fb009dcSAndroid Build Coastguard Worker if passed, err := runTestOnce(test, mallocNumToFail); err != errMoreMallocs { 253*8fb009dcSAndroid Build Coastguard Worker if err != nil { 254*8fb009dcSAndroid Build Coastguard Worker err = fmt.Errorf("at malloc %d: %s", mallocNumToFail, err) 255*8fb009dcSAndroid Build Coastguard Worker } 256*8fb009dcSAndroid Build Coastguard Worker return passed, err 257*8fb009dcSAndroid Build Coastguard Worker } 258*8fb009dcSAndroid Build Coastguard Worker } 259*8fb009dcSAndroid Build Coastguard Worker} 260*8fb009dcSAndroid Build Coastguard Worker 261*8fb009dcSAndroid Build Coastguard Worker// setWorkingDirectory walks up directories as needed until the current working 262*8fb009dcSAndroid Build Coastguard Worker// directory is the top of a BoringSSL checkout. 263*8fb009dcSAndroid Build Coastguard Workerfunc setWorkingDirectory() { 264*8fb009dcSAndroid Build Coastguard Worker for i := 0; i < 64; i++ { 265*8fb009dcSAndroid Build Coastguard Worker if _, err := os.Stat("BUILDING.md"); err == nil { 266*8fb009dcSAndroid Build Coastguard Worker return 267*8fb009dcSAndroid Build Coastguard Worker } 268*8fb009dcSAndroid Build Coastguard Worker os.Chdir("..") 269*8fb009dcSAndroid Build Coastguard Worker } 270*8fb009dcSAndroid Build Coastguard Worker 271*8fb009dcSAndroid Build Coastguard Worker panic("Couldn't find BUILDING.md in a parent directory!") 272*8fb009dcSAndroid Build Coastguard Worker} 273*8fb009dcSAndroid Build Coastguard Worker 274*8fb009dcSAndroid Build Coastguard Workerfunc worker(tests <-chan test, results chan<- result, done *sync.WaitGroup) { 275*8fb009dcSAndroid Build Coastguard Worker defer done.Done() 276*8fb009dcSAndroid Build Coastguard Worker for test := range tests { 277*8fb009dcSAndroid Build Coastguard Worker passed, err := runTest(test) 278*8fb009dcSAndroid Build Coastguard Worker results <- result{test, passed, err} 279*8fb009dcSAndroid Build Coastguard Worker } 280*8fb009dcSAndroid Build Coastguard Worker} 281*8fb009dcSAndroid Build Coastguard Worker 282*8fb009dcSAndroid Build Coastguard Workerfunc (t test) shortName() string { 283*8fb009dcSAndroid Build Coastguard Worker return strings.Join(t.Cmd, " ") + t.shardMsg() + t.cpuMsg() + t.envMsg() 284*8fb009dcSAndroid Build Coastguard Worker} 285*8fb009dcSAndroid Build Coastguard Worker 286*8fb009dcSAndroid Build Coastguard Workerfunc SpaceIf(returnSpace bool) string { 287*8fb009dcSAndroid Build Coastguard Worker if !returnSpace { 288*8fb009dcSAndroid Build Coastguard Worker return "" 289*8fb009dcSAndroid Build Coastguard Worker } 290*8fb009dcSAndroid Build Coastguard Worker return " " 291*8fb009dcSAndroid Build Coastguard Worker} 292*8fb009dcSAndroid Build Coastguard Worker 293*8fb009dcSAndroid Build Coastguard Workerfunc (t test) longName() string { 294*8fb009dcSAndroid Build Coastguard Worker return strings.Join(t.Env, " ") + SpaceIf(len(t.Env) != 0) + strings.Join(t.Cmd, " ") + t.shardMsg() + t.cpuMsg() 295*8fb009dcSAndroid Build Coastguard Worker} 296*8fb009dcSAndroid Build Coastguard Worker 297*8fb009dcSAndroid Build Coastguard Workerfunc (t test) shardMsg() string { 298*8fb009dcSAndroid Build Coastguard Worker if t.numShards == 0 { 299*8fb009dcSAndroid Build Coastguard Worker return "" 300*8fb009dcSAndroid Build Coastguard Worker } 301*8fb009dcSAndroid Build Coastguard Worker 302*8fb009dcSAndroid Build Coastguard Worker return fmt.Sprintf(" [shard %d/%d]", t.shard+1, t.numShards) 303*8fb009dcSAndroid Build Coastguard Worker} 304*8fb009dcSAndroid Build Coastguard Worker 305*8fb009dcSAndroid Build Coastguard Workerfunc (t test) cpuMsg() string { 306*8fb009dcSAndroid Build Coastguard Worker if len(t.cpu) == 0 { 307*8fb009dcSAndroid Build Coastguard Worker return "" 308*8fb009dcSAndroid Build Coastguard Worker } 309*8fb009dcSAndroid Build Coastguard Worker 310*8fb009dcSAndroid Build Coastguard Worker return fmt.Sprintf(" (for CPU %q)", t.cpu) 311*8fb009dcSAndroid Build Coastguard Worker} 312*8fb009dcSAndroid Build Coastguard Worker 313*8fb009dcSAndroid Build Coastguard Workerfunc (t test) envMsg() string { 314*8fb009dcSAndroid Build Coastguard Worker if len(t.Env) == 0 { 315*8fb009dcSAndroid Build Coastguard Worker return "" 316*8fb009dcSAndroid Build Coastguard Worker } 317*8fb009dcSAndroid Build Coastguard Worker 318*8fb009dcSAndroid Build Coastguard Worker return " (custom environment)" 319*8fb009dcSAndroid Build Coastguard Worker} 320*8fb009dcSAndroid Build Coastguard Worker 321*8fb009dcSAndroid Build Coastguard Workerfunc (t test) getGTestShards() ([]test, error) { 322*8fb009dcSAndroid Build Coastguard Worker if *numWorkers == 1 || !t.Shard { 323*8fb009dcSAndroid Build Coastguard Worker return []test{t}, nil 324*8fb009dcSAndroid Build Coastguard Worker } 325*8fb009dcSAndroid Build Coastguard Worker 326*8fb009dcSAndroid Build Coastguard Worker shards := make([]test, *numWorkers) 327*8fb009dcSAndroid Build Coastguard Worker for i := range shards { 328*8fb009dcSAndroid Build Coastguard Worker shards[i] = t 329*8fb009dcSAndroid Build Coastguard Worker shards[i].shard = i 330*8fb009dcSAndroid Build Coastguard Worker shards[i].numShards = *numWorkers 331*8fb009dcSAndroid Build Coastguard Worker } 332*8fb009dcSAndroid Build Coastguard Worker 333*8fb009dcSAndroid Build Coastguard Worker return shards, nil 334*8fb009dcSAndroid Build Coastguard Worker} 335*8fb009dcSAndroid Build Coastguard Worker 336*8fb009dcSAndroid Build Coastguard Workerfunc main() { 337*8fb009dcSAndroid Build Coastguard Worker flag.Parse() 338*8fb009dcSAndroid Build Coastguard Worker setWorkingDirectory() 339*8fb009dcSAndroid Build Coastguard Worker 340*8fb009dcSAndroid Build Coastguard Worker testCases, err := testconfig.ParseTestConfig("util/all_tests.json") 341*8fb009dcSAndroid Build Coastguard Worker if err != nil { 342*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("Failed to parse input: %s\n", err) 343*8fb009dcSAndroid Build Coastguard Worker os.Exit(1) 344*8fb009dcSAndroid Build Coastguard Worker } 345*8fb009dcSAndroid Build Coastguard Worker 346*8fb009dcSAndroid Build Coastguard Worker var wg sync.WaitGroup 347*8fb009dcSAndroid Build Coastguard Worker tests := make(chan test, *numWorkers) 348*8fb009dcSAndroid Build Coastguard Worker results := make(chan result, *numWorkers) 349*8fb009dcSAndroid Build Coastguard Worker 350*8fb009dcSAndroid Build Coastguard Worker for i := 0; i < *numWorkers; i++ { 351*8fb009dcSAndroid Build Coastguard Worker wg.Add(1) 352*8fb009dcSAndroid Build Coastguard Worker go worker(tests, results, &wg) 353*8fb009dcSAndroid Build Coastguard Worker } 354*8fb009dcSAndroid Build Coastguard Worker 355*8fb009dcSAndroid Build Coastguard Worker go func() { 356*8fb009dcSAndroid Build Coastguard Worker for _, baseTest := range testCases { 357*8fb009dcSAndroid Build Coastguard Worker test := test{Test: baseTest} 358*8fb009dcSAndroid Build Coastguard Worker if *useSDE { 359*8fb009dcSAndroid Build Coastguard Worker if test.SkipSDE { 360*8fb009dcSAndroid Build Coastguard Worker continue 361*8fb009dcSAndroid Build Coastguard Worker } 362*8fb009dcSAndroid Build Coastguard Worker // SDE generates plenty of tasks and gets slower 363*8fb009dcSAndroid Build Coastguard Worker // with additional sharding. 364*8fb009dcSAndroid Build Coastguard Worker for _, cpu := range sdeCPUs { 365*8fb009dcSAndroid Build Coastguard Worker testForCPU := test 366*8fb009dcSAndroid Build Coastguard Worker testForCPU.cpu = cpu 367*8fb009dcSAndroid Build Coastguard Worker tests <- testForCPU 368*8fb009dcSAndroid Build Coastguard Worker } 369*8fb009dcSAndroid Build Coastguard Worker } else if *simulateARMCPUs { 370*8fb009dcSAndroid Build Coastguard Worker // This mode is run instead of the default path, 371*8fb009dcSAndroid Build Coastguard Worker // so also include the native flow. 372*8fb009dcSAndroid Build Coastguard Worker tests <- test 373*8fb009dcSAndroid Build Coastguard Worker for _, cpu := range armCPUs { 374*8fb009dcSAndroid Build Coastguard Worker testForCPU := test 375*8fb009dcSAndroid Build Coastguard Worker testForCPU.cpu = cpu 376*8fb009dcSAndroid Build Coastguard Worker tests <- testForCPU 377*8fb009dcSAndroid Build Coastguard Worker } 378*8fb009dcSAndroid Build Coastguard Worker } else { 379*8fb009dcSAndroid Build Coastguard Worker shards, err := test.getGTestShards() 380*8fb009dcSAndroid Build Coastguard Worker if err != nil { 381*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("Error listing tests: %s\n", err) 382*8fb009dcSAndroid Build Coastguard Worker os.Exit(1) 383*8fb009dcSAndroid Build Coastguard Worker } 384*8fb009dcSAndroid Build Coastguard Worker for _, shard := range shards { 385*8fb009dcSAndroid Build Coastguard Worker tests <- shard 386*8fb009dcSAndroid Build Coastguard Worker } 387*8fb009dcSAndroid Build Coastguard Worker } 388*8fb009dcSAndroid Build Coastguard Worker } 389*8fb009dcSAndroid Build Coastguard Worker close(tests) 390*8fb009dcSAndroid Build Coastguard Worker 391*8fb009dcSAndroid Build Coastguard Worker wg.Wait() 392*8fb009dcSAndroid Build Coastguard Worker close(results) 393*8fb009dcSAndroid Build Coastguard Worker }() 394*8fb009dcSAndroid Build Coastguard Worker 395*8fb009dcSAndroid Build Coastguard Worker testOutput := testresult.NewResults() 396*8fb009dcSAndroid Build Coastguard Worker var failed, skipped []test 397*8fb009dcSAndroid Build Coastguard Worker for testResult := range results { 398*8fb009dcSAndroid Build Coastguard Worker test := testResult.Test 399*8fb009dcSAndroid Build Coastguard Worker args := test.Cmd 400*8fb009dcSAndroid Build Coastguard Worker 401*8fb009dcSAndroid Build Coastguard Worker if testResult.Error == errTestSkipped { 402*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("%s\n", test.longName()) 403*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("%s was skipped\n", args[0]) 404*8fb009dcSAndroid Build Coastguard Worker skipped = append(skipped, test) 405*8fb009dcSAndroid Build Coastguard Worker testOutput.AddSkip(test.longName()) 406*8fb009dcSAndroid Build Coastguard Worker } else if testResult.Error != nil { 407*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("%s\n", test.longName()) 408*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("%s failed to complete: %s\n", args[0], testResult.Error) 409*8fb009dcSAndroid Build Coastguard Worker failed = append(failed, test) 410*8fb009dcSAndroid Build Coastguard Worker testOutput.AddResult(test.longName(), "CRASH", testResult.Error) 411*8fb009dcSAndroid Build Coastguard Worker } else if !testResult.Passed { 412*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("%s\n", test.longName()) 413*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("%s failed to print PASS on the last line.\n", args[0]) 414*8fb009dcSAndroid Build Coastguard Worker failed = append(failed, test) 415*8fb009dcSAndroid Build Coastguard Worker testOutput.AddResult(test.longName(), "FAIL", nil) 416*8fb009dcSAndroid Build Coastguard Worker } else { 417*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("%s\n", test.shortName()) 418*8fb009dcSAndroid Build Coastguard Worker testOutput.AddResult(test.longName(), "PASS", nil) 419*8fb009dcSAndroid Build Coastguard Worker } 420*8fb009dcSAndroid Build Coastguard Worker } 421*8fb009dcSAndroid Build Coastguard Worker 422*8fb009dcSAndroid Build Coastguard Worker if *jsonOutput != "" { 423*8fb009dcSAndroid Build Coastguard Worker if err := testOutput.WriteToFile(*jsonOutput); err != nil { 424*8fb009dcSAndroid Build Coastguard Worker fmt.Fprintf(os.Stderr, "Error: %s\n", err) 425*8fb009dcSAndroid Build Coastguard Worker } 426*8fb009dcSAndroid Build Coastguard Worker } 427*8fb009dcSAndroid Build Coastguard Worker 428*8fb009dcSAndroid Build Coastguard Worker if len(skipped) > 0 { 429*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("\n%d of %d tests were skipped:\n", len(skipped), len(testCases)) 430*8fb009dcSAndroid Build Coastguard Worker for _, test := range skipped { 431*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("\t%s\n", test.shortName()) 432*8fb009dcSAndroid Build Coastguard Worker } 433*8fb009dcSAndroid Build Coastguard Worker } 434*8fb009dcSAndroid Build Coastguard Worker 435*8fb009dcSAndroid Build Coastguard Worker if len(failed) > 0 { 436*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("\n%d of %d tests failed:\n", len(failed), len(testCases)) 437*8fb009dcSAndroid Build Coastguard Worker for _, test := range failed { 438*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("\t%s\n", test.shortName()) 439*8fb009dcSAndroid Build Coastguard Worker } 440*8fb009dcSAndroid Build Coastguard Worker os.Exit(1) 441*8fb009dcSAndroid Build Coastguard Worker } 442*8fb009dcSAndroid Build Coastguard Worker 443*8fb009dcSAndroid Build Coastguard Worker fmt.Printf("All unit tests passed!\n") 444*8fb009dcSAndroid Build Coastguard Worker} 445