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