1package main 2 3import ( 4 "flag" 5 "log" 6 "os" 7 "runtime" 8 "sync" 9 "sync/atomic" 10 "time" 11) 12 13func init() { 14 log.SetFlags(0) 15} 16 17func main() { 18 parallelism := flag.Int("parallelism", runtime.NumCPU(), "Number of test cases to run in parallel") 19 goFlag := flag.Bool("go", false, "Run go test harness") 20 gogoFlag := flag.Bool("gogo", false, "Run gogo test harness") 21 ccFlag := flag.Bool("cc", false, "Run c++ test harness") 22 javaFlag := flag.Bool("java", false, "Run java test harness") 23 flag.Parse() 24 25 start := time.Now() 26 successes, failures, skips := run(*parallelism, *goFlag, *gogoFlag, *ccFlag, *javaFlag) 27 28 log.Printf("Successes: %d | Failures: %d | Skips: %d (%v)", 29 successes, failures, skips, time.Since(start)) 30 31 if failures > 0 { 32 os.Exit(1) 33 } 34} 35 36func run(parallelism int, goFlag bool, gogoFlag bool, ccFlag bool, javaFlag bool) (successes, failures, skips uint64) { 37 wg := new(sync.WaitGroup) 38 if parallelism <= 0 { 39 panic("Parallelism must be > 0") 40 } 41 if !(goFlag || gogoFlag || ccFlag || javaFlag) { 42 panic("At least one harness must be selected with a flag") 43 } 44 wg.Add(parallelism) 45 46 in := make(chan TestCase) 47 out := make(chan TestResult) 48 done := make(chan struct{}) 49 50 for i := 0; i < parallelism; i++ { 51 go Work(wg, in, out, goFlag, gogoFlag, ccFlag, javaFlag) 52 } 53 54 go func() { 55 for res := range out { 56 if res.Skipped { 57 atomic.AddUint64(&skips, 1) 58 } else if res.OK { 59 atomic.AddUint64(&successes, 1) 60 } else { 61 atomic.AddUint64(&failures, 1) 62 } 63 } 64 close(done) 65 }() 66 67 for _, test := range TestCases { 68 in <- test 69 } 70 close(in) 71 72 wg.Wait() 73 close(out) 74 <-done 75 76 return 77} 78