Source file
src/cmd/dist/test.go
1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "flag"
10 "fmt"
11 "io/ioutil"
12 "log"
13 "os"
14 "os/exec"
15 "path"
16 "path/filepath"
17 "reflect"
18 "regexp"
19 "runtime"
20 "strconv"
21 "strings"
22 "sync"
23 "time"
24 )
25
26 func cmdtest() {
27 gogcflags = os.Getenv("GO_GCFLAGS")
28
29 var t tester
30 var noRebuild bool
31 flag.BoolVar(&t.listMode, "list", false, "list available tests")
32 flag.BoolVar(&t.rebuild, "rebuild", false, "rebuild everything first")
33 flag.BoolVar(&noRebuild, "no-rebuild", false, "overrides -rebuild (historical dreg)")
34 flag.BoolVar(&t.keepGoing, "k", false, "keep going even when error occurred")
35 flag.BoolVar(&t.race, "race", false, "run in race builder mode (different set of tests)")
36 flag.BoolVar(&t.compileOnly, "compile-only", false, "compile tests, but don't run them. This is for some builders. Not all dist tests respect this flag, but most do.")
37 flag.StringVar(&t.banner, "banner", "##### ", "banner prefix; blank means no section banners")
38 flag.StringVar(&t.runRxStr, "run", os.Getenv("GOTESTONLY"),
39 "run only those tests matching the regular expression; empty means to run all. "+
40 "Special exception: if the string begins with '!', the match is inverted.")
41 xflagparse(-1)
42 if noRebuild {
43 t.rebuild = false
44 }
45
46 t.run()
47 }
48
49
50 type tester struct {
51 race bool
52 listMode bool
53 rebuild bool
54 failed bool
55 keepGoing bool
56 compileOnly bool
57 runRxStr string
58 runRx *regexp.Regexp
59 runRxWant bool
60 runNames []string
61 banner string
62 lastHeading string
63
64 cgoEnabled bool
65 partial bool
66 haveTime bool
67
68 tests []distTest
69 timeoutScale int
70
71 worklist []*work
72 }
73
74 type work struct {
75 dt *distTest
76 cmd *exec.Cmd
77 start chan bool
78 out []byte
79 err error
80 end chan bool
81 }
82
83
84
85 type distTest struct {
86 name string
87 heading string
88 fn func(*distTest) error
89 }
90
91 func (t *tester) run() {
92 timelog("start", "dist test")
93
94 var exeSuffix string
95 if goos == "windows" {
96 exeSuffix = ".exe"
97 }
98 if _, err := os.Stat(filepath.Join(gobin, "go"+exeSuffix)); err == nil {
99 os.Setenv("PATH", fmt.Sprintf("%s%c%s", gobin, os.PathListSeparator, os.Getenv("PATH")))
100 }
101
102 cmd := exec.Command("go", "env", "CGO_ENABLED")
103 cmd.Stderr = new(bytes.Buffer)
104 slurp, err := cmd.Output()
105 if err != nil {
106 fatalf("Error running go env CGO_ENABLED: %v\n%s", err, cmd.Stderr)
107 }
108 t.cgoEnabled, _ = strconv.ParseBool(strings.TrimSpace(string(slurp)))
109 if flag.NArg() > 0 && t.runRxStr != "" {
110 fatalf("the -run regular expression flag is mutually exclusive with test name arguments")
111 }
112
113 t.runNames = flag.Args()
114
115 if t.hasBash() {
116 if _, err := exec.LookPath("time"); err == nil {
117 t.haveTime = true
118 }
119 }
120
121
122
123
124
125
126 if ok := isEnvSet("GOTRACEBACK"); !ok {
127 if err := os.Setenv("GOTRACEBACK", "system"); err != nil {
128 if t.keepGoing {
129 log.Printf("Failed to set GOTRACEBACK: %v", err)
130 } else {
131 fatalf("Failed to set GOTRACEBACK: %v", err)
132 }
133 }
134 }
135
136 if t.rebuild {
137 t.out("Building packages and commands.")
138
139 goInstall("go", append([]string{"-a", "-i"}, toolchain...)...)
140 }
141
142 if !t.listMode {
143 if os.Getenv("GO_BUILDER_NAME") == "" {
144
145
146
147
148
149
150
151
152
153
154
155
156 goInstall("go", append([]string{"-i"}, toolchain...)...)
157 goInstall("go", append([]string{"-i"}, toolchain...)...)
158 goInstall("go", "std", "cmd")
159 } else {
160
161
162
163
164
165 willTest := []string{"std"}
166 if t.shouldTestCmd() {
167 willTest = append(willTest, "cmd")
168 }
169 checkNotStale("go", willTest...)
170 }
171 }
172
173 t.timeoutScale = 1
174 switch goarch {
175 case "arm":
176 t.timeoutScale = 2
177 case "mips", "mipsle", "mips64", "mips64le":
178 t.timeoutScale = 4
179 }
180 if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" {
181 t.timeoutScale, err = strconv.Atoi(s)
182 if err != nil {
183 fatalf("failed to parse $GO_TEST_TIMEOUT_SCALE = %q as integer: %v", s, err)
184 }
185 }
186
187 if t.runRxStr != "" {
188 if t.runRxStr[0] == '!' {
189 t.runRxWant = false
190 t.runRxStr = t.runRxStr[1:]
191 } else {
192 t.runRxWant = true
193 }
194 t.runRx = regexp.MustCompile(t.runRxStr)
195 }
196
197 t.registerTests()
198 if t.listMode {
199 for _, tt := range t.tests {
200 fmt.Println(tt.name)
201 }
202 return
203 }
204
205 for _, name := range t.runNames {
206 if !t.isRegisteredTestName(name) {
207 fatalf("unknown test %q", name)
208 }
209 }
210
211
212 if strings.HasPrefix(os.Getenv("GO_BUILDER_NAME"), "linux-") {
213 if os.Getuid() == 0 {
214
215
216 } else {
217 xatexit(t.makeGOROOTUnwritable())
218 }
219 }
220
221 for _, dt := range t.tests {
222 if !t.shouldRunTest(dt.name) {
223 t.partial = true
224 continue
225 }
226 dt := dt
227 if err := dt.fn(&dt); err != nil {
228 t.runPending(&dt)
229 t.failed = true
230 if t.keepGoing {
231 log.Printf("Failed: %v", err)
232 } else {
233 fatalf("Failed: %v", err)
234 }
235 }
236 }
237 t.runPending(nil)
238 timelog("end", "dist test")
239
240 if t.failed {
241 fmt.Println("\nFAILED")
242 xexit(1)
243 } else if incomplete[goos+"/"+goarch] {
244
245
246
247 fmt.Println("\nFAILED (incomplete port)")
248 xexit(1)
249 } else if t.partial {
250 fmt.Println("\nALL TESTS PASSED (some were excluded)")
251 } else {
252 fmt.Println("\nALL TESTS PASSED")
253 }
254 }
255
256 func (t *tester) shouldRunTest(name string) bool {
257 if t.runRx != nil {
258 return t.runRx.MatchString(name) == t.runRxWant
259 }
260 if len(t.runNames) == 0 {
261 return true
262 }
263 for _, runName := range t.runNames {
264 if runName == name {
265 return true
266 }
267 }
268 return false
269 }
270
271
272
273
274
275
276
277
278
279
280 func short() string {
281 if v := os.Getenv("GO_TEST_SHORT"); v != "" {
282 short, err := strconv.ParseBool(v)
283 if err != nil {
284 fatalf("invalid GO_TEST_SHORT %q: %v", v, err)
285 }
286 if !short {
287 return "false"
288 }
289 }
290 return "true"
291 }
292
293
294
295
296 func (t *tester) goTest() []string {
297 return []string{
298 "go", "test", "-short=" + short(), "-count=1", t.tags(), t.runFlag(""),
299 }
300 }
301
302 func (t *tester) tags() string {
303 if t.iOS() {
304 return "-tags=lldb"
305 }
306 return "-tags="
307 }
308
309
310
311 func (t *tester) timeoutDuration(sec int) time.Duration {
312 return time.Duration(sec) * time.Second * time.Duration(t.timeoutScale)
313 }
314
315
316
317
318 func (t *tester) timeout(sec int) string {
319 return "-timeout=" + t.timeoutDuration(sec).String()
320 }
321
322
323
324
325
326
327
328 var (
329 ranGoTest bool
330 stdMatches []string
331
332 ranGoBench bool
333 benchMatches []string
334 )
335
336 func (t *tester) registerStdTest(pkg string, useG3 bool) {
337 heading := "Testing packages."
338 testPrefix := "go_test:"
339 gcflags := gogcflags
340 if useG3 {
341 heading = "Testing packages with -G=3."
342 testPrefix = "go_test_g3:"
343 gcflags += " -G=3"
344 }
345
346 testName := testPrefix + pkg
347 if t.runRx == nil || t.runRx.MatchString(testName) == t.runRxWant {
348 stdMatches = append(stdMatches, pkg)
349 }
350
351 t.tests = append(t.tests, distTest{
352 name: testName,
353 heading: heading,
354 fn: func(dt *distTest) error {
355 if ranGoTest {
356 return nil
357 }
358 t.runPending(dt)
359 timelog("start", dt.name)
360 defer timelog("end", dt.name)
361 ranGoTest = true
362
363 timeoutSec := 180
364 for _, pkg := range stdMatches {
365 if pkg == "cmd/go" {
366 timeoutSec *= 3
367 break
368 }
369 }
370
371
372 if t.shouldUsePrecompiledStdTest() {
373 return t.runPrecompiledStdTest(t.timeoutDuration(timeoutSec))
374 }
375 args := []string{
376 "test",
377 "-short=" + short(),
378 t.tags(),
379 t.timeout(timeoutSec),
380 "-gcflags=all=" + gcflags,
381 }
382 if t.race {
383 args = append(args, "-race")
384 }
385 if t.compileOnly {
386 args = append(args, "-run=^$")
387 }
388 args = append(args, stdMatches...)
389 cmd := exec.Command("go", args...)
390 cmd.Stdout = os.Stdout
391 cmd.Stderr = os.Stderr
392 return cmd.Run()
393 },
394 })
395 }
396
397 func (t *tester) registerRaceBenchTest(pkg string) {
398 testName := "go_test_bench:" + pkg
399 if t.runRx == nil || t.runRx.MatchString(testName) == t.runRxWant {
400 benchMatches = append(benchMatches, pkg)
401 }
402 t.tests = append(t.tests, distTest{
403 name: testName,
404 heading: "Running benchmarks briefly.",
405 fn: func(dt *distTest) error {
406 if ranGoBench {
407 return nil
408 }
409 t.runPending(dt)
410 timelog("start", dt.name)
411 defer timelog("end", dt.name)
412 ranGoBench = true
413 args := []string{
414 "test",
415 "-short=" + short(),
416 "-race",
417 t.timeout(1200),
418 "-run=^$",
419 "-benchtime=.1s",
420 "-cpu=4",
421 }
422 if !t.compileOnly {
423 args = append(args, "-bench=.*")
424 }
425 args = append(args, benchMatches...)
426 cmd := exec.Command("go", args...)
427 cmd.Stdout = os.Stdout
428 cmd.Stderr = os.Stderr
429 return cmd.Run()
430 },
431 })
432 }
433
434
435
436 var stdOutErrAreTerminals func() bool
437
438 func (t *tester) registerTests() {
439
440
441
442 if len(t.runNames) > 0 {
443 for _, name := range t.runNames {
444 if strings.HasPrefix(name, "go_test:") {
445 t.registerStdTest(strings.TrimPrefix(name, "go_test:"), false)
446 }
447 if strings.HasPrefix(name, "go_test_g3:") {
448 t.registerStdTest(strings.TrimPrefix(name, "go_test_g3:"), true)
449 }
450 if strings.HasPrefix(name, "go_test_bench:") {
451 t.registerRaceBenchTest(strings.TrimPrefix(name, "go_test_bench:"))
452 }
453 }
454 } else {
455
456 const format = "{{if (or .TestGoFiles .XTestGoFiles)}}{{.ImportPath}}{{end}}"
457 cmd := exec.Command("go", "list", "-f", format)
458 if t.race {
459 cmd.Args = append(cmd.Args, "-tags=race")
460 }
461 cmd.Args = append(cmd.Args, "std")
462 if t.shouldTestCmd() {
463 cmd.Args = append(cmd.Args, "cmd")
464 }
465 cmd.Stderr = new(bytes.Buffer)
466 all, err := cmd.Output()
467 if err != nil {
468 fatalf("Error running go list std cmd: %v:\n%s", err, cmd.Stderr)
469 }
470 pkgs := strings.Fields(string(all))
471 if false {
472
473
474 for _, pkg := range pkgs {
475 t.registerStdTest(pkg, true )
476 }
477 }
478 for _, pkg := range pkgs {
479 t.registerStdTest(pkg, false)
480 }
481 if t.race {
482 for _, pkg := range pkgs {
483 if t.packageHasBenchmarks(pkg) {
484 t.registerRaceBenchTest(pkg)
485 }
486 }
487 }
488 }
489
490
491 if !t.compileOnly {
492 t.tests = append(t.tests, distTest{
493 name: "osusergo",
494 heading: "os/user with tag osusergo",
495 fn: func(dt *distTest) error {
496 t.addCmd(dt, "src", t.goTest(), t.timeout(300), "-tags=osusergo", "os/user")
497 return nil
498 },
499 })
500 }
501
502
503 if goos == "darwin" && goarch == "amd64" && t.cgoEnabled {
504 t.tests = append(t.tests, distTest{
505 name: "amd64ios",
506 heading: "GOOS=ios on darwin/amd64",
507 fn: func(dt *distTest) error {
508 cmd := t.addCmd(dt, "src", t.goTest(), t.timeout(300), "-run=SystemRoots", "crypto/x509")
509 setEnv(cmd, "GOOS", "ios")
510 setEnv(cmd, "CGO_ENABLED", "1")
511 return nil
512 },
513 })
514 }
515
516 if t.race {
517 return
518 }
519
520
521 if !t.compileOnly && goos != "js" {
522 testName := "runtime:cpu124"
523 t.tests = append(t.tests, distTest{
524 name: testName,
525 heading: "GOMAXPROCS=2 runtime -cpu=1,2,4 -quick",
526 fn: func(dt *distTest) error {
527 cmd := t.addCmd(dt, "src", t.goTest(), t.timeout(300), "runtime", "-cpu=1,2,4", "-quick")
528
529
530 setEnv(cmd, "GOMAXPROCS", "2")
531 return nil
532 },
533 })
534 }
535
536
537
538 if goos == "linux" {
539 t.tests = append(t.tests, distTest{
540 name: "cmd_go_test_terminal",
541 heading: "cmd/go terminal test",
542 fn: func(dt *distTest) error {
543 t.runPending(dt)
544 timelog("start", dt.name)
545 defer timelog("end", dt.name)
546 if !stdOutErrAreTerminals() {
547 fmt.Println("skipping terminal test; stdout/stderr not terminals")
548 return nil
549 }
550 cmd := exec.Command("go", "test")
551 setDir(cmd, filepath.Join(os.Getenv("GOROOT"), "src/cmd/go/testdata/testterminal18153"))
552 cmd.Stdout = os.Stdout
553 cmd.Stderr = os.Stderr
554 return cmd.Run()
555 },
556 })
557 }
558
559
560
561
562
563
564 if os.Getenv("GO_BUILDER_NAME") != "" && goos != "android" && !t.iOS() && goos != "plan9" && goos != "js" {
565 t.tests = append(t.tests, distTest{
566 name: "moved_goroot",
567 heading: "moved GOROOT",
568 fn: func(dt *distTest) error {
569 t.runPending(dt)
570 timelog("start", dt.name)
571 defer timelog("end", dt.name)
572 moved := goroot + "-moved"
573 if err := os.Rename(goroot, moved); err != nil {
574 if goos == "windows" {
575
576
577
578
579
580
581
582 log.Printf("skipping test on Windows")
583 return nil
584 }
585 return err
586 }
587
588
589
590 cmd := exec.Command(filepath.Join(moved, "bin", "go"), "test", "fmt")
591 cmd.Stdout = os.Stdout
592 cmd.Stderr = os.Stderr
593 unsetEnv(cmd, "GOROOT")
594 unsetEnv(cmd, "GOCACHE")
595 err := cmd.Run()
596
597 if rerr := os.Rename(moved, goroot); rerr != nil {
598 fatalf("failed to restore GOROOT: %v", rerr)
599 }
600 return err
601 },
602 })
603 }
604
605
606
607
608
609 for _, pkg := range cgoPackages {
610 if !t.internalLink() {
611 break
612 }
613
614
615 if goarch == "arm" {
616 break
617 }
618
619 pkg := pkg
620 var run string
621 if pkg == "net" {
622 run = "TestTCPStress"
623 }
624 t.tests = append(t.tests, distTest{
625 name: "nolibgcc:" + pkg,
626 heading: "Testing without libgcc.",
627 fn: func(dt *distTest) error {
628
629
630 t.addCmd(dt, "src", t.goTest(), "-ldflags=-linkmode=internal -libgcc=none", "-run=^Test[^CS]", pkg, t.runFlag(run))
631 return nil
632 },
633 })
634 }
635
636
637 if t.internalLinkPIE() {
638 t.tests = append(t.tests, distTest{
639 name: "pie_internal",
640 heading: "internal linking of -buildmode=pie",
641 fn: func(dt *distTest) error {
642 t.addCmd(dt, "src", t.goTest(), "reflect", "-buildmode=pie", "-ldflags=-linkmode=internal", t.timeout(60))
643 return nil
644 },
645 })
646
647 if t.cgoEnabled && t.internalLink() {
648 t.tests = append(t.tests, distTest{
649 name: "pie_internal_cgo",
650 heading: "internal linking of -buildmode=pie",
651 fn: func(dt *distTest) error {
652 t.addCmd(dt, "src", t.goTest(), "os/user", "-buildmode=pie", "-ldflags=-linkmode=internal", t.timeout(60))
653 return nil
654 },
655 })
656 }
657 }
658
659
660 if goos != "js" {
661 t.tests = append(t.tests, distTest{
662 name: "sync_cpu",
663 heading: "sync -cpu=10",
664 fn: func(dt *distTest) error {
665 t.addCmd(dt, "src", t.goTest(), "sync", t.timeout(120), "-cpu=10", t.runFlag(""))
666 return nil
667 },
668 })
669 }
670
671 if t.raceDetectorSupported() {
672 t.tests = append(t.tests, distTest{
673 name: "race",
674 heading: "Testing race detector",
675 fn: t.raceTest,
676 })
677 }
678
679 if t.cgoEnabled && !t.iOS() {
680
681 t.registerHostTest("cgo_stdio", "../misc/cgo/stdio", "misc/cgo/stdio", ".")
682 t.registerHostTest("cgo_life", "../misc/cgo/life", "misc/cgo/life", ".")
683 fortran := os.Getenv("FC")
684 if fortran == "" {
685 fortran, _ = exec.LookPath("gfortran")
686 }
687 if t.hasBash() && goos != "android" && fortran != "" {
688 t.tests = append(t.tests, distTest{
689 name: "cgo_fortran",
690 heading: "../misc/cgo/fortran",
691 fn: func(dt *distTest) error {
692 t.addCmd(dt, "misc/cgo/fortran", "./test.bash", fortran)
693 return nil
694 },
695 })
696 }
697 if t.hasSwig() && goos != "android" {
698 t.tests = append(t.tests, distTest{
699 name: "swig_stdio",
700 heading: "../misc/swig/stdio",
701 fn: func(dt *distTest) error {
702 t.addCmd(dt, "misc/swig/stdio", t.goTest())
703 return nil
704 },
705 })
706 if t.hasCxx() {
707 t.tests = append(t.tests,
708 distTest{
709 name: "swig_callback",
710 heading: "../misc/swig/callback",
711 fn: func(dt *distTest) error {
712 t.addCmd(dt, "misc/swig/callback", t.goTest())
713 return nil
714 },
715 },
716 distTest{
717 name: "swig_callback_lto",
718 heading: "../misc/swig/callback",
719 fn: func(dt *distTest) error {
720 cmd := t.addCmd(dt, "misc/swig/callback", t.goTest())
721 setEnv(cmd, "CGO_CFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
722 setEnv(cmd, "CGO_CXXFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
723 setEnv(cmd, "CGO_LDFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
724 return nil
725 },
726 },
727 )
728 }
729 }
730 }
731 if t.cgoEnabled {
732 t.tests = append(t.tests, distTest{
733 name: "cgo_test",
734 heading: "../misc/cgo/test",
735 fn: t.cgoTest,
736 })
737 }
738
739
740
741
742
743 if t.cgoEnabled && gogcflags == "" {
744 t.registerHostTest("testgodefs", "../misc/cgo/testgodefs", "misc/cgo/testgodefs", ".")
745
746 t.registerTest("testso", "../misc/cgo/testso", t.goTest(), t.timeout(600), ".")
747 t.registerTest("testsovar", "../misc/cgo/testsovar", t.goTest(), t.timeout(600), ".")
748 if t.supportedBuildmode("c-archive") {
749 t.registerHostTest("testcarchive", "../misc/cgo/testcarchive", "misc/cgo/testcarchive", ".")
750 }
751 if t.supportedBuildmode("c-shared") {
752 t.registerHostTest("testcshared", "../misc/cgo/testcshared", "misc/cgo/testcshared", ".")
753 }
754 if t.supportedBuildmode("shared") {
755 t.registerTest("testshared", "../misc/cgo/testshared", t.goTest(), t.timeout(600), ".")
756 }
757 if t.supportedBuildmode("plugin") {
758 t.registerTest("testplugin", "../misc/cgo/testplugin", t.goTest(), t.timeout(600), ".")
759 }
760 if gohostos == "linux" && goarch == "amd64" {
761 t.registerTest("testasan", "../misc/cgo/testasan", "go", "run", ".")
762 }
763 if goos == "linux" && goarch != "ppc64le" {
764
765
766 t.registerHostTest("testsanitizers", "../misc/cgo/testsanitizers", "misc/cgo/testsanitizers", ".")
767 }
768 if t.hasBash() && goos != "android" && !t.iOS() && gohostos != "windows" {
769 t.registerHostTest("cgo_errors", "../misc/cgo/errors", "misc/cgo/errors", ".")
770 }
771 if gohostos == "linux" && t.extLink() {
772 t.registerTest("testsigfwd", "../misc/cgo/testsigfwd", "go", "run", ".")
773 }
774 }
775
776 if goos != "android" && !t.iOS() {
777
778
779
780 t.registerTest("bench_go1", "../test/bench/go1", t.goTest(), "-c", "-o="+os.DevNull)
781 }
782 if goos != "android" && !t.iOS() {
783
784
785
786 nShards := 1
787 if os.Getenv("GO_BUILDER_NAME") != "" {
788 nShards = 10
789 }
790 if n, err := strconv.Atoi(os.Getenv("GO_TEST_SHARDS")); err == nil {
791 nShards = n
792 }
793 for shard := 0; shard < nShards; shard++ {
794 shard := shard
795 t.tests = append(t.tests, distTest{
796 name: fmt.Sprintf("test:%d_%d", shard, nShards),
797 heading: "../test",
798 fn: func(dt *distTest) error { return t.testDirTest(dt, shard, nShards) },
799 })
800 }
801 }
802
803
804
805
806
807 if goos != "android" && !t.iOS() && goos != "js" && goos != "plan9" {
808 t.tests = append(t.tests, distTest{
809 name: "api",
810 heading: "API check",
811 fn: func(dt *distTest) error {
812 if t.compileOnly {
813 t.addCmd(dt, "src", "go", "build", "-o", os.DevNull, filepath.Join(goroot, "src/cmd/api/run.go"))
814 return nil
815 }
816 t.addCmd(dt, "src", "go", "run", filepath.Join(goroot, "src/cmd/api/run.go"))
817 return nil
818 },
819 })
820 }
821
822
823
824 if os.Getenv("GO_BUILDER_NAME") != "" && goos != "android" && !t.iOS() {
825 t.registerHostTest("reboot", "../misc/reboot", "misc/reboot", ".")
826 }
827 }
828
829
830
831 func (t *tester) isRegisteredTestName(testName string) bool {
832 for _, tt := range t.tests {
833 if tt.name == testName {
834 return true
835 }
836 }
837 return false
838 }
839
840 func (t *tester) registerTest1(seq bool, name, dirBanner string, cmdline ...interface{}) {
841 bin, args := flattenCmdline(cmdline)
842 if bin == "time" && !t.haveTime {
843 bin, args = args[0], args[1:]
844 }
845 if t.isRegisteredTestName(name) {
846 panic("duplicate registered test name " + name)
847 }
848 t.tests = append(t.tests, distTest{
849 name: name,
850 heading: dirBanner,
851 fn: func(dt *distTest) error {
852 if seq {
853 t.runPending(dt)
854 timelog("start", name)
855 defer timelog("end", name)
856 return t.dirCmd(filepath.Join(goroot, "src", dirBanner), bin, args).Run()
857 }
858 t.addCmd(dt, filepath.Join(goroot, "src", dirBanner), bin, args)
859 return nil
860 },
861 })
862 }
863
864 func (t *tester) registerTest(name, dirBanner string, cmdline ...interface{}) {
865 t.registerTest1(false, name, dirBanner, cmdline...)
866 }
867
868 func (t *tester) registerSeqTest(name, dirBanner string, cmdline ...interface{}) {
869 t.registerTest1(true, name, dirBanner, cmdline...)
870 }
871
872 func (t *tester) bgDirCmd(dir, bin string, args ...string) *exec.Cmd {
873 cmd := exec.Command(bin, args...)
874 if filepath.IsAbs(dir) {
875 setDir(cmd, dir)
876 } else {
877 setDir(cmd, filepath.Join(goroot, dir))
878 }
879 return cmd
880 }
881
882 func (t *tester) dirCmd(dir string, cmdline ...interface{}) *exec.Cmd {
883 bin, args := flattenCmdline(cmdline)
884 cmd := t.bgDirCmd(dir, bin, args...)
885 cmd.Stdout = os.Stdout
886 cmd.Stderr = os.Stderr
887 if vflag > 1 {
888 errprintf("%s\n", strings.Join(cmd.Args, " "))
889 }
890 return cmd
891 }
892
893
894
895 func flattenCmdline(cmdline []interface{}) (bin string, args []string) {
896 var list []string
897 for _, x := range cmdline {
898 switch x := x.(type) {
899 case string:
900 list = append(list, x)
901 case []string:
902 list = append(list, x...)
903 default:
904 panic("invalid addCmd argument type: " + reflect.TypeOf(x).String())
905 }
906 }
907
908
909
910 drop := make([]bool, len(list))
911 have := map[string]int{}
912 for i := 1; i < len(list); i++ {
913 j := strings.Index(list[i], "=")
914 if j < 0 {
915 continue
916 }
917 flag := list[i][:j]
918 switch flag {
919 case "-run", "-tags":
920 if have[flag] != 0 {
921 drop[have[flag]] = true
922 }
923 have[flag] = i
924 }
925 }
926 out := list[:0]
927 for i, x := range list {
928 if !drop[i] {
929 out = append(out, x)
930 }
931 }
932 list = out
933
934 return list[0], list[1:]
935 }
936
937 func (t *tester) addCmd(dt *distTest, dir string, cmdline ...interface{}) *exec.Cmd {
938 bin, args := flattenCmdline(cmdline)
939 w := &work{
940 dt: dt,
941 cmd: t.bgDirCmd(dir, bin, args...),
942 }
943 t.worklist = append(t.worklist, w)
944 return w.cmd
945 }
946
947 func (t *tester) iOS() bool {
948 return goos == "ios"
949 }
950
951 func (t *tester) out(v string) {
952 if t.banner == "" {
953 return
954 }
955 fmt.Println("\n" + t.banner + v)
956 }
957
958 func (t *tester) extLink() bool {
959 pair := gohostos + "-" + goarch
960 switch pair {
961 case "aix-ppc64",
962 "android-arm", "android-arm64",
963 "darwin-amd64", "darwin-arm64",
964 "dragonfly-amd64",
965 "freebsd-386", "freebsd-amd64", "freebsd-arm",
966 "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-mips64", "linux-mips64le", "linux-mips", "linux-mipsle", "linux-riscv64", "linux-s390x",
967 "netbsd-386", "netbsd-amd64",
968 "openbsd-386", "openbsd-amd64",
969 "windows-386", "windows-amd64":
970 return true
971 }
972 return false
973 }
974
975 func (t *tester) internalLink() bool {
976 if gohostos == "dragonfly" {
977
978 return false
979 }
980 if goos == "android" {
981 return false
982 }
983 if goos == "ios" {
984 return false
985 }
986 if goos == "windows" && goarch == "arm64" {
987 return false
988 }
989
990
991
992 if goarch == "mips64" || goarch == "mips64le" || goarch == "mips" || goarch == "mipsle" || goarch == "riscv64" {
993 return false
994 }
995 if goos == "aix" {
996
997 return false
998 }
999 return true
1000 }
1001
1002 func (t *tester) internalLinkPIE() bool {
1003 switch goos + "-" + goarch {
1004 case "darwin-amd64", "darwin-arm64",
1005 "linux-amd64", "linux-arm64", "linux-ppc64le",
1006 "android-arm64",
1007 "windows-amd64", "windows-386", "windows-arm":
1008 return true
1009 }
1010 return false
1011 }
1012
1013 func (t *tester) supportedBuildmode(mode string) bool {
1014 pair := goos + "-" + goarch
1015 switch mode {
1016 case "c-archive":
1017 if !t.extLink() {
1018 return false
1019 }
1020 switch pair {
1021 case "aix-ppc64",
1022 "darwin-amd64", "darwin-arm64", "ios-arm64",
1023 "linux-amd64", "linux-386", "linux-ppc64le", "linux-riscv64", "linux-s390x",
1024 "freebsd-amd64",
1025 "windows-amd64", "windows-386":
1026 return true
1027 }
1028 return false
1029 case "c-shared":
1030 switch pair {
1031 case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-riscv64", "linux-s390x",
1032 "darwin-amd64", "darwin-arm64",
1033 "freebsd-amd64",
1034 "android-arm", "android-arm64", "android-386",
1035 "windows-amd64", "windows-386", "windows-arm64":
1036 return true
1037 }
1038 return false
1039 case "shared":
1040 switch pair {
1041 case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-s390x":
1042 return true
1043 }
1044 return false
1045 case "plugin":
1046 switch pair {
1047 case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-s390x", "linux-ppc64le":
1048 return true
1049 case "darwin-amd64", "darwin-arm64":
1050 return true
1051 case "freebsd-amd64":
1052 return true
1053 }
1054 return false
1055 case "pie":
1056 switch pair {
1057 case "aix/ppc64",
1058 "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-riscv64", "linux-s390x",
1059 "android-amd64", "android-arm", "android-arm64", "android-386":
1060 return true
1061 case "darwin-amd64", "darwin-arm64":
1062 return true
1063 case "windows-amd64", "windows-386", "windows-arm":
1064 return true
1065 }
1066 return false
1067
1068 default:
1069 fatalf("internal error: unknown buildmode %s", mode)
1070 return false
1071 }
1072 }
1073
1074 func (t *tester) registerHostTest(name, heading, dir, pkg string) {
1075 t.tests = append(t.tests, distTest{
1076 name: name,
1077 heading: heading,
1078 fn: func(dt *distTest) error {
1079 t.runPending(dt)
1080 timelog("start", name)
1081 defer timelog("end", name)
1082 return t.runHostTest(dir, pkg)
1083 },
1084 })
1085 }
1086
1087 func (t *tester) runHostTest(dir, pkg string) error {
1088 out, err := exec.Command("go", "env", "GOEXE", "GOTMPDIR").Output()
1089 if err != nil {
1090 return err
1091 }
1092
1093 parts := strings.Split(string(out), "\n")
1094 if len(parts) < 2 {
1095 return fmt.Errorf("'go env GOEXE GOTMPDIR' output contains <2 lines")
1096 }
1097 GOEXE := strings.TrimSpace(parts[0])
1098 GOTMPDIR := strings.TrimSpace(parts[1])
1099
1100 f, err := ioutil.TempFile(GOTMPDIR, "test.test-*"+GOEXE)
1101 if err != nil {
1102 return err
1103 }
1104 f.Close()
1105 defer os.Remove(f.Name())
1106
1107 cmd := t.dirCmd(dir, t.goTest(), "-c", "-o", f.Name(), pkg)
1108 setEnv(cmd, "GOARCH", gohostarch)
1109 setEnv(cmd, "GOOS", gohostos)
1110 if err := cmd.Run(); err != nil {
1111 return err
1112 }
1113 return t.dirCmd(dir, f.Name(), "-test.short="+short()).Run()
1114 }
1115
1116 func (t *tester) cgoTest(dt *distTest) error {
1117 cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
1118 setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=auto")
1119
1120
1121
1122 skipInternalLink := goarch == "arm64" && goos != "darwin"
1123
1124 if t.internalLink() && !skipInternalLink {
1125 cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal")
1126 setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=internal")
1127 }
1128
1129 pair := gohostos + "-" + goarch
1130 switch pair {
1131 case "darwin-amd64", "darwin-arm64",
1132 "windows-386", "windows-amd64":
1133
1134 if !t.extLink() {
1135 break
1136 }
1137 cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
1138 setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external")
1139
1140 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s")
1141
1142 if t.supportedBuildmode("pie") {
1143 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie")
1144 if t.internalLink() && t.internalLinkPIE() {
1145 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie")
1146 }
1147 }
1148
1149 case "aix-ppc64",
1150 "android-arm", "android-arm64",
1151 "dragonfly-amd64",
1152 "freebsd-386", "freebsd-amd64", "freebsd-arm",
1153 "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-riscv64", "linux-s390x",
1154 "netbsd-386", "netbsd-amd64",
1155 "openbsd-386", "openbsd-amd64", "openbsd-arm", "openbsd-arm64", "openbsd-mips64":
1156
1157 cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
1158 setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external")
1159
1160
1161 setEnv(cmd, "CGO_CFLAGS", "-g0 -fdiagnostics-color")
1162
1163 t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=auto")
1164 t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=external")
1165
1166 switch pair {
1167 case "aix-ppc64", "netbsd-386", "netbsd-amd64":
1168
1169 case "freebsd-arm":
1170
1171
1172
1173
1174
1175 default:
1176 cmd := t.dirCmd("misc/cgo/test",
1177 compilerEnvLookup(defaultcc, goos, goarch), "-xc", "-o", "/dev/null", "-static", "-")
1178 cmd.Stdin = strings.NewReader("int main() {}")
1179 if err := cmd.Run(); err != nil {
1180 fmt.Println("No support for static linking found (lacks libc.a?), skip cgo static linking test.")
1181 } else {
1182 if goos != "android" {
1183 t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
1184 }
1185 t.addCmd(dt, "misc/cgo/nocgo", t.goTest())
1186 t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external`)
1187 if goos != "android" {
1188 t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
1189 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
1190
1191
1192
1193 cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static")
1194 setEnv(cmd, "CGO_LDFLAGS", "-static -pthread")
1195 }
1196 }
1197
1198 if t.supportedBuildmode("pie") {
1199 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie")
1200 if t.internalLink() && t.internalLinkPIE() && !skipInternalLink {
1201 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie")
1202 }
1203 t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie")
1204 t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie")
1205 }
1206 }
1207 }
1208
1209 return nil
1210 }
1211
1212
1213
1214
1215
1216
1217
1218 func (t *tester) runPending(nextTest *distTest) {
1219 checkNotStale("go", "std")
1220 worklist := t.worklist
1221 t.worklist = nil
1222 for _, w := range worklist {
1223 w.start = make(chan bool)
1224 w.end = make(chan bool)
1225 go func(w *work) {
1226 if !<-w.start {
1227 timelog("skip", w.dt.name)
1228 w.out = []byte(fmt.Sprintf("skipped due to earlier error\n"))
1229 } else {
1230 timelog("start", w.dt.name)
1231 w.out, w.err = w.cmd.CombinedOutput()
1232 if w.err != nil {
1233 if isUnsupportedVMASize(w) {
1234 timelog("skip", w.dt.name)
1235 w.out = []byte(fmt.Sprintf("skipped due to unsupported VMA\n"))
1236 w.err = nil
1237 }
1238 }
1239 }
1240 timelog("end", w.dt.name)
1241 w.end <- true
1242 }(w)
1243 }
1244
1245 started := 0
1246 ended := 0
1247 var last *distTest
1248 for ended < len(worklist) {
1249 for started < len(worklist) && started-ended < maxbg {
1250 w := worklist[started]
1251 started++
1252 w.start <- !t.failed || t.keepGoing
1253 }
1254 w := worklist[ended]
1255 dt := w.dt
1256 if dt.heading != "" && t.lastHeading != dt.heading {
1257 t.lastHeading = dt.heading
1258 t.out(dt.heading)
1259 }
1260 if dt != last {
1261
1262 last = w.dt
1263 if vflag > 0 {
1264 fmt.Printf("# go tool dist test -run=^%s$\n", dt.name)
1265 }
1266 }
1267 if vflag > 1 {
1268 errprintf("%s\n", strings.Join(w.cmd.Args, " "))
1269 }
1270 ended++
1271 <-w.end
1272 os.Stdout.Write(w.out)
1273 if w.err != nil {
1274 log.Printf("Failed: %v", w.err)
1275 t.failed = true
1276 }
1277 checkNotStale("go", "std")
1278 }
1279 if t.failed && !t.keepGoing {
1280 fatalf("FAILED")
1281 }
1282
1283 if dt := nextTest; dt != nil {
1284 if dt.heading != "" && t.lastHeading != dt.heading {
1285 t.lastHeading = dt.heading
1286 t.out(dt.heading)
1287 }
1288 if vflag > 0 {
1289 fmt.Printf("# go tool dist test -run=^%s$\n", dt.name)
1290 }
1291 }
1292 }
1293
1294 func (t *tester) hasBash() bool {
1295 switch gohostos {
1296 case "windows", "plan9":
1297 return false
1298 }
1299 return true
1300 }
1301
1302 func (t *tester) hasCxx() bool {
1303 cxx, _ := exec.LookPath(compilerEnvLookup(defaultcxx, goos, goarch))
1304 return cxx != ""
1305 }
1306
1307 func (t *tester) hasSwig() bool {
1308 swig, err := exec.LookPath("swig")
1309 if err != nil {
1310 return false
1311 }
1312
1313
1314
1315
1316 output, err := exec.Command(swig, "-go", "-swiglib").Output()
1317 if err != nil {
1318 return false
1319 }
1320 swigDir := strings.TrimSpace(string(output))
1321
1322 _, err = os.Stat(filepath.Join(swigDir, "go"))
1323 if err != nil {
1324 return false
1325 }
1326
1327
1328
1329 out, err := exec.Command(swig, "-version").CombinedOutput()
1330 if err != nil {
1331 return false
1332 }
1333
1334 re := regexp.MustCompile(`[vV]ersion +([\d]+)([.][\d]+)?([.][\d]+)?`)
1335 matches := re.FindSubmatch(out)
1336 if matches == nil {
1337
1338 return true
1339 }
1340
1341 major, err := strconv.Atoi(string(matches[1]))
1342 if err != nil {
1343
1344 return true
1345 }
1346 if major < 3 {
1347 return false
1348 }
1349 if major > 3 {
1350
1351 return true
1352 }
1353
1354
1355 if len(matches[2]) > 0 {
1356 minor, err := strconv.Atoi(string(matches[2][1:]))
1357 if err != nil {
1358 return true
1359 }
1360 if minor > 0 {
1361
1362 return true
1363 }
1364 }
1365
1366
1367 if len(matches[3]) > 0 {
1368 patch, err := strconv.Atoi(string(matches[3][1:]))
1369 if err != nil {
1370 return true
1371 }
1372 if patch < 6 {
1373
1374 return false
1375 }
1376 }
1377
1378 return true
1379 }
1380
1381 func (t *tester) raceDetectorSupported() bool {
1382 if gohostos != goos {
1383 return false
1384 }
1385 if !t.cgoEnabled {
1386 return false
1387 }
1388 if !raceDetectorSupported(goos, goarch) {
1389 return false
1390 }
1391
1392
1393 if isAlpineLinux() {
1394 return false
1395 }
1396
1397
1398 if goos == "netbsd" {
1399 return false
1400 }
1401 return true
1402 }
1403
1404 func isAlpineLinux() bool {
1405 if runtime.GOOS != "linux" {
1406 return false
1407 }
1408 fi, err := os.Lstat("/etc/alpine-release")
1409 return err == nil && fi.Mode().IsRegular()
1410 }
1411
1412 func (t *tester) runFlag(rx string) string {
1413 if t.compileOnly {
1414 return "-run=^$"
1415 }
1416 return "-run=" + rx
1417 }
1418
1419 func (t *tester) raceTest(dt *distTest) error {
1420 t.addCmd(dt, "src", t.goTest(), "-race", t.runFlag("Output"), "runtime/race")
1421 t.addCmd(dt, "src", t.goTest(), "-race", t.runFlag("TestParse|TestEcho|TestStdinCloseRace|TestClosedPipeRace|TestTypeRace|TestFdRace|TestFdReadRace|TestFileCloseRace"), "flag", "net", "os", "os/exec", "encoding/gob")
1422
1423
1424
1425
1426
1427 if t.cgoEnabled {
1428
1429
1430
1431
1432
1433
1434 }
1435 if t.extLink() {
1436
1437 t.addCmd(dt, "src", t.goTest(), "-race", "-ldflags=-linkmode=external", t.runFlag("TestParse|TestEcho|TestStdinCloseRace"), "flag", "os/exec")
1438 }
1439 return nil
1440 }
1441
1442 var runtest struct {
1443 sync.Once
1444 exe string
1445 err error
1446 }
1447
1448 func (t *tester) testDirTest(dt *distTest, shard, shards int) error {
1449 runtest.Do(func() {
1450 f, err := ioutil.TempFile("", "runtest-*.exe")
1451 if err != nil {
1452 runtest.err = err
1453 return
1454 }
1455 f.Close()
1456
1457 runtest.exe = f.Name()
1458 xatexit(func() {
1459 os.Remove(runtest.exe)
1460 })
1461
1462 cmd := t.dirCmd("test", "go", "build", "-o", runtest.exe, "run.go")
1463 setEnv(cmd, "GOOS", gohostos)
1464 setEnv(cmd, "GOARCH", gohostarch)
1465 runtest.err = cmd.Run()
1466 })
1467 if runtest.err != nil {
1468 return runtest.err
1469 }
1470 if t.compileOnly {
1471 return nil
1472 }
1473 t.addCmd(dt, "test", runtest.exe,
1474 fmt.Sprintf("--shard=%d", shard),
1475 fmt.Sprintf("--shards=%d", shards),
1476 )
1477 return nil
1478 }
1479
1480
1481 var cgoPackages = []string{
1482 "net",
1483 "os/user",
1484 }
1485
1486 var funcBenchmark = []byte("\nfunc Benchmark")
1487
1488
1489
1490
1491
1492
1493
1494
1495 func (t *tester) packageHasBenchmarks(pkg string) bool {
1496 pkgDir := filepath.Join(goroot, "src", pkg)
1497 d, err := os.Open(pkgDir)
1498 if err != nil {
1499 return true
1500 }
1501 defer d.Close()
1502 names, err := d.Readdirnames(-1)
1503 if err != nil {
1504 return true
1505 }
1506 for _, name := range names {
1507 if !strings.HasSuffix(name, "_test.go") {
1508 continue
1509 }
1510 slurp, err := ioutil.ReadFile(filepath.Join(pkgDir, name))
1511 if err != nil {
1512 return true
1513 }
1514 if bytes.Contains(slurp, funcBenchmark) {
1515 return true
1516 }
1517 }
1518 return false
1519 }
1520
1521
1522
1523 func (t *tester) makeGOROOTUnwritable() (undo func()) {
1524 dir := os.Getenv("GOROOT")
1525 if dir == "" {
1526 panic("GOROOT not set")
1527 }
1528
1529 type pathMode struct {
1530 path string
1531 mode os.FileMode
1532 }
1533 var dirs []pathMode
1534
1535 undo = func() {
1536 for i := range dirs {
1537 os.Chmod(dirs[i].path, dirs[i].mode)
1538 }
1539 }
1540
1541 gocache := os.Getenv("GOCACHE")
1542 if gocache == "" {
1543 panic("GOCACHE not set")
1544 }
1545 gocacheSubdir, _ := filepath.Rel(dir, gocache)
1546
1547
1548 filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
1549 if suffix := strings.TrimPrefix(path, dir+string(filepath.Separator)); suffix != "" {
1550 if suffix == gocacheSubdir {
1551
1552 return filepath.SkipDir
1553 }
1554 if suffix == ".git" {
1555
1556
1557
1558 return filepath.SkipDir
1559 }
1560 }
1561 if err == nil {
1562 mode := info.Mode()
1563 if mode&0222 != 0 && (mode.IsDir() || mode.IsRegular()) {
1564 dirs = append(dirs, pathMode{path, mode})
1565 }
1566 }
1567 return nil
1568 })
1569
1570
1571 for i := len(dirs) - 1; i >= 0; i-- {
1572 err := os.Chmod(dirs[i].path, dirs[i].mode&^0222)
1573 if err != nil {
1574 dirs = dirs[i:]
1575 undo()
1576 fatalf("failed to make GOROOT read-only: %v", err)
1577 }
1578 }
1579
1580 return undo
1581 }
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593 func (t *tester) shouldUsePrecompiledStdTest() bool {
1594 bin := t.prebuiltGoPackageTestBinary()
1595 if bin == "" {
1596 return false
1597 }
1598 _, err := os.Stat(bin)
1599 return err == nil
1600 }
1601
1602 func (t *tester) shouldTestCmd() bool {
1603 if goos == "js" && goarch == "wasm" {
1604
1605 return false
1606 }
1607 return true
1608 }
1609
1610
1611
1612
1613
1614 func (t *tester) prebuiltGoPackageTestBinary() string {
1615 if len(stdMatches) != 1 || t.race || t.compileOnly || os.Getenv("GO_BUILDER_NAME") == "" {
1616 return ""
1617 }
1618 pkg := stdMatches[0]
1619 return filepath.Join(os.Getenv("GOROOT"), "src", pkg, path.Base(pkg)+".test")
1620 }
1621
1622
1623
1624 func (t *tester) runPrecompiledStdTest(timeout time.Duration) error {
1625 bin := t.prebuiltGoPackageTestBinary()
1626 fmt.Fprintf(os.Stderr, "# %s: using pre-built %s...\n", stdMatches[0], bin)
1627 cmd := exec.Command(bin, "-test.short="+short(), "-test.timeout="+timeout.String())
1628 setDir(cmd, filepath.Dir(bin))
1629 cmd.Stdout = os.Stdout
1630 cmd.Stderr = os.Stderr
1631 if err := cmd.Start(); err != nil {
1632 return err
1633 }
1634
1635
1636 const backupKillFactor = 1.05
1637 timer := time.AfterFunc(time.Duration(float64(timeout)*backupKillFactor), func() {
1638 fmt.Fprintf(os.Stderr, "# %s: timeout running %s; killing...\n", stdMatches[0], bin)
1639 cmd.Process.Kill()
1640 })
1641 defer timer.Stop()
1642 return cmd.Wait()
1643 }
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653 func raceDetectorSupported(goos, goarch string) bool {
1654 switch goos {
1655 case "linux":
1656 return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64"
1657 case "darwin":
1658 return goarch == "amd64" || goarch == "arm64"
1659 case "freebsd", "netbsd", "openbsd", "windows":
1660 return goarch == "amd64"
1661 default:
1662 return false
1663 }
1664 }
1665
1666
1667
1668
1669 func isUnsupportedVMASize(w *work) bool {
1670 unsupportedVMA := []byte("unsupported VMA range")
1671 return w.dt.name == "race" && bytes.Contains(w.out, unsupportedVMA)
1672 }
1673
1674
1675
1676 func isEnvSet(evar string) bool {
1677 evarEq := evar + "="
1678 for _, e := range os.Environ() {
1679 if strings.HasPrefix(e, evarEq) {
1680 return true
1681 }
1682 }
1683 return false
1684 }
1685
View as plain text