Source file
doc/progs/run.go
1
2
3
4
5
6 package main
7
8 import (
9 "bytes"
10 "flag"
11 "fmt"
12 "io/ioutil"
13 "os"
14 "os/exec"
15 "path/filepath"
16 "regexp"
17 "runtime"
18 "strings"
19 "time"
20 )
21
22 const usage = `go run run.go [tests]
23
24 run.go runs the docs tests in this directory.
25 If no tests are provided, it runs all tests.
26 Tests may be specified without their .go suffix.
27 `
28
29 func main() {
30 start := time.Now()
31
32 flag.Usage = func() {
33 fmt.Fprintf(os.Stderr, usage)
34 flag.PrintDefaults()
35 os.Exit(2)
36 }
37
38 flag.Parse()
39 if flag.NArg() == 0 {
40
41 fixcgo()
42 } else {
43
44 onlyTest(flag.Args()...)
45 }
46
47 tmpdir, err := ioutil.TempDir("", "go-progs")
48 if err != nil {
49 fmt.Fprintln(os.Stderr, err)
50 os.Exit(1)
51 }
52
53
54
55
56 ratec := make(chan bool, runtime.NumCPU())
57 errc := make(chan error, len(tests))
58
59 for _, tt := range tests {
60 tt := tt
61 ratec <- true
62 go func() {
63 errc <- test(tmpdir, tt.file, tt.want)
64 <-ratec
65 }()
66 }
67
68 var rc int
69 for range tests {
70 if err := <-errc; err != nil {
71 fmt.Fprintln(os.Stderr, err)
72 rc = 1
73 }
74 }
75 os.Remove(tmpdir)
76 if rc == 0 {
77 fmt.Printf("ok\t%s\t%s\n", filepath.Base(os.Args[0]), time.Since(start).Round(time.Millisecond))
78 }
79 os.Exit(rc)
80 }
81
82
83
84
85 func test(tmpdir, file, want string) error {
86
87 prog := filepath.Join(tmpdir, file+".exe")
88 cmd := exec.Command("go", "build", "-o", prog, file+".go")
89 out, err := cmd.CombinedOutput()
90 if err != nil {
91 return fmt.Errorf("go build %s.go failed: %v\nOutput:\n%s", file, err, out)
92 }
93 defer os.Remove(prog)
94
95
96 if want == "" {
97 return nil
98 }
99
100 cmd = exec.Command(prog)
101 out, err = cmd.CombinedOutput()
102 if err != nil {
103 return fmt.Errorf("%s failed: %v\nOutput:\n%s", file, err, out)
104 }
105
106
107 out = bytes.TrimRight(out, "\n")
108 out = bytes.ReplaceAll(out, []byte{'\n'}, []byte{' '})
109
110
111 match, err := regexp.Match(want, out)
112 if err != nil {
113 return fmt.Errorf("failed to parse regexp %q: %v", want, err)
114 }
115 if !match {
116 return fmt.Errorf("%s.go:\n%q\ndoes not match %s", file, out, want)
117 }
118
119 return nil
120 }
121
122 type testcase struct {
123 file string
124 want string
125 }
126
127 var tests = []testcase{
128
129 {"defer", `^0 3210 2$`},
130 {"defer2", `^Calling g. Printing in g 0 Printing in g 1 Printing in g 2 Printing in g 3 Panicking! Defer in g 3 Defer in g 2 Defer in g 1 Defer in g 0 Recovered in f 4 Returned normally from f.$`},
131
132
133 {"eff_bytesize", `^1.00YB 9.09TB$`},
134 {"eff_qr", ""},
135 {"eff_sequence", `^\[-1 2 6 16 44\]$`},
136 {"eff_unused2", ""},
137
138
139 {"error", ""},
140 {"error2", ""},
141 {"error3", ""},
142 {"error4", ""},
143
144
145 {"interface", ""},
146 {"interface2", `^type: float64$`},
147
148
149 {"cgo1", ""},
150 {"cgo2", ""},
151 {"cgo3", ""},
152 {"cgo4", ""},
153
154
155 {"timeout1", ""},
156 {"timeout2", ""},
157
158
159 {"gobs1", ""},
160 {"gobs2", ""},
161
162
163 {"json1", `^$`},
164 {"json2", `the reciprocal of i is`},
165 {"json3", `Age is int 6`},
166 {"json4", `^$`},
167 {"json5", ""},
168
169
170 {"image_package1", `^X is 2 Y is 1$`},
171 {"image_package2", `^3 4 false$`},
172 {"image_package3", `^3 4 true$`},
173 {"image_package4", `^image.Point{X:2, Y:1}$`},
174 {"image_package5", `^{255 0 0 255}$`},
175 {"image_package6", `^8 4 true$`},
176
177
178 {"go1", `^Christmas is a holiday: true .*go1.go already exists$`},
179 {"slices", ""},
180 }
181
182 func onlyTest(files ...string) {
183 var new []testcase
184 NextFile:
185 for _, file := range files {
186 file = strings.TrimSuffix(file, ".go")
187 for _, tt := range tests {
188 if tt.file == file {
189 new = append(new, tt)
190 continue NextFile
191 }
192 }
193 fmt.Fprintf(os.Stderr, "test %s.go not found\n", file)
194 os.Exit(1)
195 }
196 tests = new
197 }
198
199 func skipTest(file string) {
200 for i, tt := range tests {
201 if tt.file == file {
202 copy(tests[i:], tests[i+1:])
203 tests = tests[:len(tests)-1]
204 return
205 }
206 }
207 panic("delete(" + file + "): not found")
208 }
209
210 func fixcgo() {
211 if os.Getenv("CGO_ENABLED") != "1" {
212 skipTest("cgo1")
213 skipTest("cgo2")
214 skipTest("cgo3")
215 skipTest("cgo4")
216 return
217 }
218
219 switch runtime.GOOS {
220 case "freebsd":
221
222 skipTest("cgo1")
223 skipTest("cgo2")
224 case "netbsd":
225
226 skipTest("cgo1")
227 skipTest("cgo2")
228 }
229 }
230
View as plain text