1package main
2
3import (
4 "errors"
5 "flag"
6 "fmt"
7 "os"
8 "path/filepath"
9 "runtime"
10)
11
12func main() {
13 reporoot, err := findreporoot()
14 if err != nil {
15 die(err)
16 }
17
18 testsroot := filepath.Join(reporoot, "tests")
19 defaultmake := filepath.Join(testsroot, "shin-make")
20 defaultcases := filepath.Join(testsroot, "mk")
21 defaultwork := filepath.Join(testsroot, "work")
22
23 var cfg suiteconfig
24 cfg.reporoot = reporoot
25 cfg.casesroot = defaultcases
26 cfg.makepath = defaultmake
27 cfg.workroot = defaultwork
28 cfg.jobs = runtime.GOMAXPROCS(0)
29
30 flag.StringVar(&cfg.makepath, "make", cfg.makepath, "path to make executable to test")
31 flag.StringVar(&cfg.workroot, "work", cfg.workroot, "directory to preserve test artifacts")
32 flag.IntVar(&cfg.jobs, "j", cfg.jobs, "number of workers")
33 flag.BoolVar(&cfg.keep, "keep", false, "preserve work directories for all cases including succeding ones")
34 flag.BoolVar(&cfg.verbose, "verbose", false, "print category descriptions")
35 flag.BoolVar(&cfg.detail, "detail", false, "print category details")
36 flag.BoolVar(&cfg.list, "list", false, "list matching cases and exit")
37 flag.Parse()
38
39 if cfg.jobs <= 0 {
40 cfg.jobs = runtime.GOMAXPROCS(0)
41 }
42
43 makepath, err := resolveexecutable(cfg.makepath)
44 if err != nil {
45 die(err)
46 }
47 cfg.makepath = makepath
48
49 selectors := flag.Args()
50 cases, err := discovercases(cfg.casesroot, selectors)
51 if err != nil {
52 die(err)
53 }
54 if len(cases) == 0 {
55 die(errors.New("no matching extracted test cases found"))
56 }
57
58 if cfg.list {
59 for _, tc := range cases {
60 fmt.Println(tc.RelPath)
61 }
62 return
63 }
64
65 categories := orderedcategories(cases)
66 suites := orderedsuites(cases)
67 fmt.Printf("testing %d test cases from %d categories from %d test suites on %s %s\n",
68 len(cases), len(categories), len(suites), runtime.GOOS, runtime.GOARCH)
69 if err := os.RemoveAll(cfg.workroot); err != nil {
70 die(err)
71 }
72 if err := os.MkdirAll(cfg.workroot, 0o755); err != nil {
73 die(err)
74 }
75
76 temproot := filepath.Join(testsroot, ".runner")
77 if err := os.RemoveAll(temproot); err != nil {
78 die(err)
79 }
80 if err := os.MkdirAll(temproot, 0o755); err != nil {
81 die(err)
82 }
83 cfg.temproot = temproot
84 defer func() {
85 if cfg.keep {
86 return
87 }
88 _ = os.RemoveAll(temproot)
89 }()
90
91 summaries := runsuite(cfg, cases, categories)
92 printsummary(summaries)
93 fmt.Printf("tested %d test cases from %d categories from %d test suites on %s %s\n",
94 len(cases), len(categories), len(suites), runtime.GOOS, runtime.GOARCH)
95 fmt.Printf("logs in tests/work \n")
96
97 failed := 0
98 for _, summary := range summaries {
99 failed += summary.FailedCases
100 }
101 if failed > 0 {
102 os.Exit(1)
103 }
104}
105
106func findreporoot() (string, error) {
107 wd, err := os.Getwd()
108 if err != nil {
109 return "", err
110 }
111
112 for dir := wd; ; dir = filepath.Dir(dir) {
113 if isdir(filepath.Join(dir, "tests", "mk")) && isdir(filepath.Join(dir, "tests", "runner")) {
114 return dir, nil
115 }
116 parent := filepath.Dir(dir)
117 if parent == dir {
118 return "", errors.New("could not locate repository root")
119 }
120 }
121}
122
123func isdir(path string) bool {
124 info, err := os.Stat(path)
125 return err == nil && info.IsDir()
126}
127
128func die(err error) {
129 fmt.Fprintln(os.Stderr, err)
130 os.Exit(1)
131}