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