Source file
src/cmd/dist/test.go
1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "encoding/json"
10 "flag"
11 "fmt"
12 "io"
13 "io/fs"
14 "log"
15 "os"
16 "os/exec"
17 "path/filepath"
18 "reflect"
19 "regexp"
20 "runtime"
21 "slices"
22 "strconv"
23 "strings"
24 "time"
25 )
26
27 func cmdtest() {
28 gogcflags = os.Getenv("GO_GCFLAGS")
29 setNoOpt()
30
31 var t tester
32
33 t.asmflags = os.Getenv("GO_TEST_ASMFLAGS")
34
35 var noRebuild bool
36 flag.BoolVar(&t.listMode, "list", false, "list available tests")
37 flag.BoolVar(&t.rebuild, "rebuild", false, "rebuild everything first")
38 flag.BoolVar(&noRebuild, "no-rebuild", false, "overrides -rebuild (historical dreg)")
39 flag.BoolVar(&t.keepGoing, "k", false, "keep going even when error occurred")
40 flag.BoolVar(&t.race, "race", false, "run in race builder mode (different set of tests)")
41 flag.BoolVar(&t.compileOnly, "compile-only", false, "compile tests, but don't run them")
42 flag.StringVar(&t.banner, "banner", "##### ", "banner prefix; blank means no section banners")
43 flag.StringVar(&t.runRxStr, "run", "",
44 "run only those tests matching the regular expression; empty means to run all. "+
45 "Special exception: if the string begins with '!', the match is inverted.")
46 flag.BoolVar(&t.msan, "msan", false, "run in memory sanitizer builder mode")
47 flag.BoolVar(&t.asan, "asan", false, "run in address sanitizer builder mode")
48 flag.BoolVar(&t.json, "json", false, "report test results in JSON")
49 flag.StringVar(&t.artifactsDir, "artifacts-dir", "", "save test artifacts in the specified directory")
50 flag.StringVar(&debugTrace, "debug-trace", debugTrace, "write a merged trace of the test run to `file`")
51
52 xflagparse(-1)
53 if noRebuild {
54 debugTraceAppend = true
55 t.rebuild = false
56 }
57
58 t.run()
59 }
60
61
62 type tester struct {
63 race bool
64 msan bool
65 asan bool
66 listMode bool
67 rebuild bool
68 failed bool
69 keepGoing bool
70 compileOnly bool
71 short bool
72 cgoEnabled bool
73 asmflags string
74 json bool
75 artifactsDir string
76 runRxStr string
77 runRx *regexp.Regexp
78 runRxWant bool
79 runNames []string
80 banner string
81 lastHeading string
82
83 tests []distTest
84 testNames map[string]bool
85 timeoutScale int
86
87 worklist []*work
88 }
89
90
91 type work struct {
92 dt *distTest
93 cmd *exec.Cmd
94 flush func()
95 start chan bool
96 out bytes.Buffer
97 err error
98 end chan struct{}
99 }
100
101
102 func (w *work) printSkip(t *tester, msg string) {
103 if t.json {
104 synthesizeSkipEvent(json.NewEncoder(&w.out), w.dt.name, msg)
105 return
106 }
107 fmt.Fprintln(&w.out, msg)
108 }
109
110
111
112 type distTest struct {
113 name string
114 heading string
115 fn func(*distTest) error
116 }
117
118 func (t *tester) run() {
119 timelog("start", "dist test")
120 distSpan := startSpan("dist test")
121
122 os.Setenv("PATH", fmt.Sprintf("%s%c%s", gorootBin, os.PathListSeparator, os.Getenv("PATH")))
123
124 t.short = true
125 if v := os.Getenv("GO_TEST_SHORT"); v != "" {
126 short, err := strconv.ParseBool(v)
127 if err != nil {
128 fatalf("invalid GO_TEST_SHORT %q: %v", v, err)
129 }
130 t.short = short
131 }
132
133 cmd := exec.Command(gorootBinGo, "env", "CGO_ENABLED")
134 cmd.Stderr = new(bytes.Buffer)
135 slurp, err := cmd.Output()
136 if err != nil {
137 fatalf("Error running %s: %v\n%s", cmd, err, cmd.Stderr)
138 }
139 parts := strings.Split(string(slurp), "\n")
140 if nlines := len(parts) - 1; nlines < 1 {
141 fatalf("Error running %s: output contains <1 lines\n%s", cmd, cmd.Stderr)
142 }
143 t.cgoEnabled, _ = strconv.ParseBool(parts[0])
144
145 if flag.NArg() > 0 && t.runRxStr != "" {
146 fatalf("the -run regular expression flag is mutually exclusive with test name arguments")
147 }
148
149 t.runNames = flag.Args()
150
151
152
153
154
155
156 if ok := isEnvSet("GOTRACEBACK"); !ok {
157 if err := os.Setenv("GOTRACEBACK", "system"); err != nil {
158 if t.keepGoing {
159 log.Printf("Failed to set GOTRACEBACK: %v", err)
160 } else {
161 fatalf("Failed to set GOTRACEBACK: %v", err)
162 }
163 }
164 }
165
166 if t.rebuild {
167 t.out("Building packages and commands.")
168
169 rebuildSpan := startSpan("rebuild toolchain")
170 goInstall(toolenv(), gorootBinGo, append(append(maybeTraceFlag("rebuildToolchain"), "-a"), toolchain...)...)
171 rebuildSpan.done()
172 }
173
174 if !t.listMode {
175 if builder := os.Getenv("GO_BUILDER_NAME"); builder == "" {
176
177
178
179
180
181
182
183
184
185
186
187
188 toolchain1Span := startSpan("toolchain1")
189 goInstall(toolenv(), gorootBinGo, append(maybeTraceFlag("toolchain1"), toolchain...)...)
190 toolchain1Span.done()
191 toolchain2Span := startSpan("toolchain2")
192 goInstall(toolenv(), gorootBinGo, append(maybeTraceFlag("toolchain2"), toolchain...)...)
193 toolchain2Span.done()
194 toolsSpan := startSpan("tools")
195 goInstall(toolenv(), gorootBinGo, append(maybeTraceFlag("tools"), toolsToInstall...)...)
196 toolsSpan.done()
197 }
198 }
199
200 t.timeoutScale = 1
201 if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" {
202 t.timeoutScale, err = strconv.Atoi(s)
203 if err != nil {
204 fatalf("failed to parse $GO_TEST_TIMEOUT_SCALE = %q as integer: %v", s, err)
205 }
206 }
207
208 if t.runRxStr != "" {
209 if t.runRxStr[0] == '!' {
210 t.runRxWant = false
211 t.runRxStr = t.runRxStr[1:]
212 } else {
213 t.runRxWant = true
214 }
215 t.runRx = regexp.MustCompile(t.runRxStr)
216 }
217
218 t.registerTests()
219 if t.listMode {
220 for _, tt := range t.tests {
221 fmt.Println(tt.name)
222 }
223 return
224 }
225
226 for _, name := range t.runNames {
227 if !t.testNames[name] {
228 fatalf("unknown test %q", name)
229 }
230 }
231
232
233 if strings.HasPrefix(os.Getenv("GO_BUILDER_NAME"), "linux-") {
234 if os.Getuid() == 0 {
235
236
237 } else {
238 xatexit(t.makeGOROOTUnwritable())
239 }
240 }
241
242 if !t.json {
243 if err := t.maybeLogMetadata(); err != nil {
244 t.failed = true
245 if t.keepGoing {
246 log.Printf("Failed logging metadata: %v", err)
247 } else {
248 fatalf("Failed logging metadata: %v", err)
249 }
250 }
251 }
252
253 var anyIncluded, someExcluded bool
254 for _, dt := range t.tests {
255 if !t.shouldRunTest(dt.name) {
256 someExcluded = true
257 continue
258 }
259 anyIncluded = true
260 dt := dt
261 if err := dt.fn(&dt); err != nil {
262 t.runPending(&dt)
263 t.failed = true
264 if t.keepGoing {
265 log.Printf("Failed: %v", err)
266 } else {
267 fatalf("Failed: %v", err)
268 }
269 }
270 }
271 t.runPending(nil)
272 timelog("end", "dist test")
273 distSpan.done()
274 if debugTrace != "" {
275 writeTrace()
276 }
277
278 if !t.json {
279 if t.failed {
280 fmt.Println("\nFAILED")
281 } else if !anyIncluded {
282 fmt.Println()
283 errprintf("go tool dist: warning: %q matched no tests; use the -list flag to list available tests\n", t.runRxStr)
284 fmt.Println("NO TESTS TO RUN")
285 } else if someExcluded {
286 fmt.Println("\nALL TESTS PASSED (some were excluded)")
287 } else {
288 fmt.Println("\nALL TESTS PASSED")
289 }
290 }
291 if t.failed {
292 xexit(1)
293 }
294 }
295
296 func (t *tester) shouldRunTest(name string) bool {
297 if t.runRx != nil {
298 return t.runRx.MatchString(name) == t.runRxWant
299 }
300 if len(t.runNames) == 0 {
301 return true
302 }
303 return slices.Contains(t.runNames, name)
304 }
305
306 func (t *tester) maybeLogMetadata() error {
307 if t.compileOnly {
308
309
310 return nil
311 }
312 t.out("Test execution environment.")
313
314
315
316
317
318
319 return t.dirCmd(filepath.Join(goroot, "src/cmd/internal/metadata"), gorootBinGo, []string{"run", "main.go"}).Run()
320 }
321
322
323 func testName(pkg, variant string) string {
324 name := pkg
325 if variant != "" {
326 name += ":" + variant
327 }
328 return name
329 }
330
331
332
333 type goTest struct {
334 short bool
335 tags []string
336 race bool
337 bench bool
338 runTests string
339 cpu string
340 skip string
341
342 gcflags string
343 ldflags string
344 buildmode string
345
346 env []string
347
348
349
350
351
352
353
354
355
356 timeout time.Duration
357
358 runOnHost bool
359
360
361
362
363 variant string
364
365
366
367 pkgs []string
368 pkg string
369
370 testFlags []string
371 trace string
372 }
373
374
375
376 func (opts *goTest) compileOnly() bool {
377 return opts.runTests == "^$" && !opts.bench
378 }
379
380
381 func (opts *goTest) scaledTimeout(t *tester) time.Duration {
382 d := goTestDefaultTimeout
383 if opts.timeout != 0 {
384 d = opts.timeout
385 }
386 d *= time.Duration(t.timeoutScale)
387 return d
388 }
389
390 const goTestDefaultTimeout = 10 * time.Minute
391
392
393
394
395 func (opts *goTest) bgCommand(t *tester, stdout, stderr io.Writer) (cmd *exec.Cmd, flush func()) {
396 build, run, pkgs, testFlags, setupCmd := opts.buildArgs(t)
397
398
399 args := append([]string{"test"}, build...)
400 if t.compileOnly || opts.compileOnly() {
401 args = append(args, "-c", "-o", os.DevNull)
402 } else {
403 args = append(args, run...)
404 }
405 args = append(args, pkgs...)
406 if !t.compileOnly && !opts.compileOnly() {
407 args = append(args, testFlags...)
408 }
409
410 cmd = exec.Command(gorootBinGo, args...)
411 setupCmd(cmd)
412 if t.json && opts.variant != "" {
413
414
415
416
417
418
419
420
421
422
423
424
425 if stdout == stderr {
426 stdout = &lockedWriter{w: stdout}
427 stderr = stdout
428 }
429 f := &testJSONFilter{w: stdout, variant: opts.variant}
430 cmd.Stdout = f
431 flush = f.Flush
432 } else {
433 cmd.Stdout = stdout
434 flush = func() {}
435 }
436 cmd.Stderr = stderr
437
438 return cmd, flush
439 }
440
441
442 func (opts *goTest) run(t *tester) error {
443 cmd, flush := opts.bgCommand(t, os.Stdout, os.Stderr)
444 err := cmd.Run()
445 flush()
446 return err
447 }
448
449
450
451
452
453
454
455
456 func (opts *goTest) buildArgs(t *tester) (build, run, pkgs, testFlags []string, setupCmd func(*exec.Cmd)) {
457 run = append(run, "-count=1")
458 if d := opts.scaledTimeout(t); d > goTestDefaultTimeout {
459 run = append(run, "-timeout="+d.String())
460 }
461 if opts.short || t.short {
462 run = append(run, "-short")
463 }
464 var tags []string
465 if noOpt {
466 tags = append(tags, "noopt")
467 }
468 tags = append(tags, opts.tags...)
469 if len(tags) > 0 {
470 build = append(build, "-tags="+strings.Join(tags, ","))
471 }
472 if t.race || opts.race {
473 build = append(build, "-race")
474 }
475 if t.msan {
476 build = append(build, "-msan")
477 }
478 if t.asan {
479 build = append(build, "-asan")
480 }
481 if opts.bench {
482
483 run = append(run, "-run=^$")
484
485 run = append(run, "-bench=.*", "-benchtime=.1s")
486 } else if opts.runTests != "" {
487 run = append(run, "-run="+opts.runTests)
488 }
489 if opts.cpu != "" {
490 run = append(run, "-cpu="+opts.cpu)
491 }
492 if opts.skip != "" {
493 run = append(run, "-skip="+opts.skip)
494 }
495 if t.json {
496 build = append(build, "-json")
497 }
498 if t.artifactsDir != "" {
499 run = append(run, "-artifacts", "-outputdir="+t.artifactsDir)
500 }
501
502 if opts.gcflags != "" {
503 build = append(build, "-gcflags=all="+opts.gcflags)
504 }
505 if opts.ldflags != "" {
506 build = append(build, "-ldflags="+opts.ldflags)
507 }
508 if t.asmflags != "" {
509 build = append(build, "-asmflags="+t.asmflags)
510 }
511 if opts.buildmode != "" {
512 build = append(build, "-buildmode="+opts.buildmode)
513 }
514 if opts.trace != "" {
515 build = append(build, maybeTraceFlag(opts.trace)...)
516 }
517
518 pkgs = opts.packages()
519
520 runOnHost := opts.runOnHost && (goarch != gohostarch || goos != gohostos)
521 needTestFlags := len(opts.testFlags) > 0 || runOnHost
522 if needTestFlags {
523 testFlags = append([]string{"-args"}, opts.testFlags...)
524 }
525 if runOnHost {
526
527 testFlags = append(testFlags, "-target="+goos+"/"+goarch)
528 }
529
530 setupCmd = func(cmd *exec.Cmd) {
531 setDir(cmd, filepath.Join(goroot, "src"))
532 if len(opts.env) != 0 {
533 for _, kv := range opts.env {
534 if i := strings.Index(kv, "="); i < 0 {
535 unsetEnv(cmd, kv[:len(kv)-1])
536 } else {
537 setEnv(cmd, kv[:i], kv[i+1:])
538 }
539 }
540 }
541 if runOnHost {
542 setEnv(cmd, "GOARCH", gohostarch)
543 setEnv(cmd, "GOOS", gohostos)
544 }
545 }
546
547 return
548 }
549
550
551
552 func (opts *goTest) packages() []string {
553 pkgs := opts.pkgs
554 if opts.pkg != "" {
555 pkgs = append(pkgs[:len(pkgs):len(pkgs)], opts.pkg)
556 }
557 if len(pkgs) == 0 {
558 panic("no packages")
559 }
560 return pkgs
561 }
562
563
564 func (opts *goTest) printSkip(t *tester, msg string) {
565 if t.json {
566 enc := json.NewEncoder(os.Stdout)
567 for _, pkg := range opts.packages() {
568 synthesizeSkipEvent(enc, pkg, msg)
569 }
570 return
571 }
572 fmt.Println(msg)
573 }
574
575
576
577
578
579
580
581 var (
582 ranGoTest bool
583 stdMatches []string
584
585 ranGoBench bool
586 benchMatches []string
587 )
588
589 func (t *tester) registerStdTest(pkg string) {
590 const stdTestHeading = "Testing packages."
591 gcflags := gogcflags
592 name := testName(pkg, "")
593 if t.runRx == nil || t.runRx.MatchString(name) == t.runRxWant {
594 stdMatches = append(stdMatches, pkg)
595 }
596 t.addTest(name, stdTestHeading, func(dt *distTest) error {
597 if ranGoTest {
598 return nil
599 }
600 t.runPending(dt)
601 timelog("start", dt.name)
602 defer timelog("end", dt.name)
603 ranGoTest = true
604
605 stdSpan := startSpan("go test std cmd")
606 defer stdSpan.done()
607
608 return (&goTest{
609 gcflags: gcflags,
610 pkgs: stdMatches,
611 trace: "std",
612 }).run(t)
613 })
614 }
615
616 func (t *tester) registerRaceBenchTest(pkg string) {
617 const raceBenchHeading = "Running benchmarks briefly."
618 name := testName(pkg, "racebench")
619 if t.runRx == nil || t.runRx.MatchString(name) == t.runRxWant {
620 benchMatches = append(benchMatches, pkg)
621 }
622 t.addTest(name, raceBenchHeading, func(dt *distTest) error {
623 if ranGoBench {
624 return nil
625 }
626 t.runPending(dt)
627 timelog("start", dt.name)
628 defer timelog("end", dt.name)
629 ranGoBench = true
630 return (&goTest{
631
632
633
634 variant: "racebench",
635 timeout: 20 * time.Minute,
636 race: true,
637 bench: true,
638 cpu: "4",
639 pkgs: benchMatches,
640 }).run(t)
641 })
642 }
643
644 func (t *tester) registerTests() {
645
646
647
648 if len(t.runNames) > 0 {
649 for _, name := range t.runNames {
650 if !strings.Contains(name, ":") {
651 t.registerStdTest(name)
652 } else if strings.HasSuffix(name, ":racebench") {
653 t.registerRaceBenchTest(strings.TrimSuffix(name, ":racebench"))
654 }
655 }
656 } else {
657
658
659
660
661
662
663
664
665
666
667
668
669
670 cmd := exec.Command(gorootBinGo, "list")
671 if t.race {
672 cmd.Args = append(cmd.Args, "-tags=race")
673 }
674 cmd.Args = append(cmd.Args, "std", "cmd")
675 cmd.Stderr = new(bytes.Buffer)
676 all, err := cmd.Output()
677 if err != nil {
678 fatalf("Error running go list std cmd: %v:\n%s", err, cmd.Stderr)
679 }
680 pkgs := strings.Fields(string(all))
681 for _, pkg := range pkgs {
682 if t.short && (strings.HasPrefix(pkg, "vendor/") || strings.HasPrefix(pkg, "cmd/vendor/")) {
683
684
685
686 continue
687 }
688 t.registerStdTest(pkg)
689 }
690 if t.race && !t.short {
691 for _, pkg := range pkgs {
692 if t.packageHasBenchmarks(pkg) {
693 t.registerRaceBenchTest(pkg)
694 }
695 }
696 }
697 }
698
699 if t.race {
700 return
701 }
702
703
704 if !t.compileOnly {
705 t.registerTest("os/user with tag osusergo",
706 &goTest{
707 variant: "osusergo",
708 tags: []string{"osusergo"},
709 pkg: "os/user",
710 })
711 }
712
713
714
715 for _, tag := range []string{"nethttpomithttp2", "nethttpomithttp2server", "nethttpomithttp2client"} {
716 t.registerTest("net/http with tag "+tag, &goTest{
717 variant: tag,
718 tags: []string{tag},
719 pkg: "net/http",
720 })
721 }
722
723
724 t.registerTest("crypto with tag purego (build and vet only)", &goTest{
725 variant: "purego",
726 tags: []string{"purego"},
727 pkg: "crypto/...",
728 runTests: "^$",
729 })
730
731
732 if t.fips140Supported() {
733
734 t.registerTest("GOFIPS140=latest go test crypto/...", &goTest{
735 variant: "gofips140",
736 env: []string{"GOFIPS140=latest"},
737 pkg: "crypto/...",
738 })
739
740
741
742 for _, version := range fips140Versions() {
743 suffix := " # (build and vet only)"
744 run := "^$"
745 if !t.short {
746 suffix = ""
747 run = ""
748 }
749 t.registerTest("GOFIPS140="+version+" go test crypto/..."+suffix, &goTest{
750 variant: "gofips140-" + version,
751 pkg: "crypto/...",
752 runTests: run,
753 env: []string{"GOFIPS140=" + version, "GOMODCACHE=" + filepath.Join(workdir, "fips-"+version)},
754 })
755 }
756 }
757
758
759 if !strings.Contains(goexperiment, "nojsonv2") {
760 t.registerTest("GOEXPERIMENT=nojsonv2 go test encoding/json/...", &goTest{
761 variant: "nojsonv2",
762 env: []string{"GOEXPERIMENT=" + goexperiments("nojsonv2")},
763 pkg: "encoding/json/...",
764 })
765 }
766
767
768 if !strings.Contains(goexperiment, "runtimesecret") {
769 t.registerTest("GOEXPERIMENT=runtimesecret go test runtime/secret/...", &goTest{
770 variant: "runtimesecret",
771 env: []string{"GOEXPERIMENT=" + goexperiments("runtimesecret")},
772 pkg: "runtime/secret/...",
773 })
774 }
775
776
777 if !strings.Contains(goexperiment, "simd") {
778
779 t.registerTest("GOEXPERIMENT=simd go test simd", &goTest{
780 variant: "simd",
781 env: []string{"GOEXPERIMENT=" + goexperiments("simd")},
782 pkg: "simd",
783 })
784
785 archsimdSupported := goarch == "amd64" || goarch == "arm64" || goarch == "wasm"
786 if archsimdSupported {
787 t.registerTest("GOEXPERIMENT=simd go test simd/archsimd/...", &goTest{
788 variant: "simd",
789 env: []string{"GOEXPERIMENT=" + goexperiments("simd")},
790 pkg: "simd/archsimd/...",
791 })
792 }
793 }
794
795
796 if goos == "darwin" && goarch == "amd64" && t.cgoEnabled {
797 t.registerTest("GOOS=ios on darwin/amd64",
798 &goTest{
799 variant: "amd64ios",
800 runTests: "SystemRoots",
801 env: []string{"GOOS=ios", "CGO_ENABLED=1"},
802 pkg: "crypto/x509",
803 })
804 }
805
806
807
808
809 if !t.compileOnly && !t.short {
810 t.registerTest("GODEBUG=gcstoptheworld=2 archive/zip",
811 &goTest{
812 variant: "gcstoptheworld2",
813 short: true,
814 env: []string{"GODEBUG=gcstoptheworld=2"},
815 pkg: "archive/zip",
816 })
817 t.registerTest("GODEBUG=gccheckmark=1 runtime",
818 &goTest{
819 variant: "gccheckmark",
820 short: true,
821 env: []string{"GODEBUG=gccheckmark=1"},
822 pkg: "runtime",
823 })
824 }
825
826
827 if goos == "linux" && goarch == "amd64" && !(gogcflags == "-spectre=all" && t.asmflags == "all=-spectre=all") {
828
829 pkgs := []string{"internal/runtime/...", "reflect", "crypto/..."}
830 if !t.short {
831 pkgs = append(pkgs, "runtime")
832 }
833 t.registerTest("spectre",
834 &goTest{
835 variant: "spectre",
836 short: true,
837 env: []string{"GOFLAGS=-gcflags=all=-spectre=all -asmflags=all=-spectre=all"},
838 pkgs: pkgs,
839 })
840 }
841
842
843
844
845
846 if !t.compileOnly && !t.short {
847
848 hooks := []string{"mayMoreStackPreempt", "mayMoreStackMove"}
849
850
851 hookPkgs := []string{"runtime/...", "reflect", "sync"}
852
853
854 unhookPkgs := []string{"runtime/testdata/..."}
855 for _, hook := range hooks {
856
857
858
859
860
861
862 goFlagsList := []string{}
863 for _, flag := range []string{"-gcflags", "-asmflags"} {
864 for _, hookPkg := range hookPkgs {
865 goFlagsList = append(goFlagsList, flag+"="+hookPkg+"=-d=maymorestack=runtime."+hook)
866 }
867 for _, unhookPkg := range unhookPkgs {
868 goFlagsList = append(goFlagsList, flag+"="+unhookPkg+"=")
869 }
870 }
871 goFlags := strings.Join(goFlagsList, " ")
872
873 t.registerTest("maymorestack="+hook,
874 &goTest{
875 variant: hook,
876 short: true,
877 env: []string{"GOFLAGS=" + goFlags},
878 pkgs: []string{"runtime", "reflect", "sync"},
879 })
880 }
881 }
882
883
884
885
886
887 for _, pkg := range cgoPackages {
888 if !t.internalLink() {
889 break
890 }
891
892
893 if goarch == "arm" {
894 break
895 }
896
897
898
899 run := "^Test[^CS]"
900 if pkg == "net" {
901 run = "TestTCPStress"
902 }
903 t.registerTest("Testing without libgcc.",
904 &goTest{
905 variant: "nolibgcc",
906 ldflags: "-linkmode=internal -libgcc=none",
907 runTests: run,
908 pkg: pkg,
909 })
910 }
911
912
913 builderName := os.Getenv("GO_BUILDER_NAME")
914 disablePIE := strings.HasSuffix(builderName, "-alpine")
915
916
917 if t.internalLinkPIE() && !disablePIE {
918 t.registerTest("internal linking, -buildmode=pie",
919 &goTest{
920 variant: "pie_internal",
921 buildmode: "pie",
922 ldflags: "-linkmode=internal",
923 env: []string{"CGO_ENABLED=0"},
924 pkg: "reflect",
925 })
926 t.registerTest("internal linking, -buildmode=pie",
927 &goTest{
928 variant: "pie_internal",
929 buildmode: "pie",
930 ldflags: "-linkmode=internal",
931 env: []string{"CGO_ENABLED=0"},
932 pkg: "crypto/internal/fips140test",
933 runTests: "TestFIPSCheck",
934 })
935
936 if t.cgoEnabled && t.internalLink() && !disablePIE {
937 t.registerTest("internal linking, -buildmode=pie",
938 &goTest{
939 variant: "pie_internal",
940 buildmode: "pie",
941 ldflags: "-linkmode=internal",
942 pkg: "os/user",
943 })
944 }
945 }
946
947 if t.extLink() && !t.compileOnly {
948 if goos != "android" {
949 t.registerTest("external linking, -buildmode=exe",
950 &goTest{
951 variant: "exe_external",
952 buildmode: "exe",
953 ldflags: "-linkmode=external",
954 env: []string{"CGO_ENABLED=1"},
955 pkg: "crypto/internal/fips140test",
956 runTests: "TestFIPSCheck",
957 })
958 }
959 if t.externalLinkPIE() && !disablePIE {
960 t.registerTest("external linking, -buildmode=pie",
961 &goTest{
962 variant: "pie_external",
963 buildmode: "pie",
964 ldflags: "-linkmode=external",
965 env: []string{"CGO_ENABLED=1"},
966 pkg: "crypto/internal/fips140test",
967 runTests: "TestFIPSCheck",
968 })
969 }
970 }
971
972
973 if !t.compileOnly && t.hasParallelism() {
974 t.registerTest("sync -cpu=10",
975 &goTest{
976 variant: "cpu10",
977 cpu: "10",
978 pkg: "sync",
979 })
980 }
981
982 const cgoHeading = "Testing cgo"
983 if t.cgoEnabled {
984 t.registerCgoTests(cgoHeading)
985 }
986
987 if goos == "wasip1" {
988 t.registerTest("wasip1 host tests",
989 &goTest{
990 variant: "host",
991 pkg: "internal/runtime/wasitest",
992 runOnHost: true,
993 })
994 }
995
996
997 if !t.compileOnly && t.hasParallelism() {
998 for i := 1; i <= 4; i *= 2 {
999 t.registerTest(fmt.Sprintf("GOMAXPROCS=2 runtime -cpu=%d -quick", i),
1000 &goTest{
1001 variant: "cpu" + strconv.Itoa(i),
1002 cpu: strconv.Itoa(i),
1003 gcflags: gogcflags,
1004 short: true,
1005 testFlags: []string{"-quick"},
1006
1007
1008 env: []string{"GOMAXPROCS=2"},
1009 pkg: "runtime",
1010 })
1011 }
1012 }
1013
1014 if t.raceDetectorSupported() && !t.msan && !t.asan {
1015
1016 t.registerRaceTests()
1017 }
1018
1019
1020
1021 if goos == "js" || goos == "wasip1" {
1022 t.registerTest("../test",
1023 &goTest{
1024 variant: "host",
1025 pkg: "cmd/internal/testdir",
1026 runOnHost: true,
1027 },
1028 )
1029 }
1030 }
1031
1032
1033
1034
1035 func (t *tester) addTest(name, heading string, fn func(*distTest) error) {
1036 if t.testNames[name] {
1037 panic("duplicate registered test name " + name)
1038 }
1039 if heading == "" {
1040 panic("empty heading")
1041 }
1042
1043 if !strings.Contains(name, ":") && heading != "Testing packages." {
1044 panic("empty variant is reserved exclusively for registerStdTest")
1045 } else if strings.HasSuffix(name, ":racebench") && heading != "Running benchmarks briefly." {
1046 panic("racebench variant is reserved exclusively for registerRaceBenchTest")
1047 }
1048 if t.testNames == nil {
1049 t.testNames = make(map[string]bool)
1050 }
1051 t.testNames[name] = true
1052 t.tests = append(t.tests, distTest{
1053 name: name,
1054 heading: heading,
1055 fn: fn,
1056 })
1057 }
1058
1059 type registerTestOpt interface {
1060 isRegisterTestOpt()
1061 }
1062
1063
1064
1065 type rtSkipFunc struct {
1066 skip func(*distTest) (string, bool)
1067 }
1068
1069 func (rtSkipFunc) isRegisterTestOpt() {}
1070
1071
1072
1073
1074
1075
1076
1077 func (t *tester) registerTest(heading string, test *goTest, opts ...registerTestOpt) {
1078 var skipFunc func(*distTest) (string, bool)
1079 for _, opt := range opts {
1080 switch opt := opt.(type) {
1081 case rtSkipFunc:
1082 skipFunc = opt.skip
1083 }
1084 }
1085
1086 register1 := func(test *goTest) {
1087 if test.variant == "" {
1088 panic("empty variant")
1089 }
1090 name := testName(test.pkg, test.variant)
1091 t.addTest(name, heading, func(dt *distTest) error {
1092 if skipFunc != nil {
1093 msg, skip := skipFunc(dt)
1094 if skip {
1095 test.printSkip(t, msg)
1096 return nil
1097 }
1098 }
1099 w := &work{dt: dt}
1100 w.cmd, w.flush = test.bgCommand(t, &w.out, &w.out)
1101 t.worklist = append(t.worklist, w)
1102 return nil
1103 })
1104 }
1105 if test.pkg != "" && len(test.pkgs) == 0 {
1106
1107 register1(test)
1108 return
1109 }
1110
1111
1112
1113
1114
1115
1116 for _, pkg := range test.packages() {
1117 test1 := *test
1118 test1.pkg, test1.pkgs = pkg, nil
1119 register1(&test1)
1120 }
1121 }
1122
1123
1124
1125
1126 func (t *tester) dirCmd(dir string, cmdline ...any) *exec.Cmd {
1127 bin, args := flattenCmdline(cmdline)
1128 cmd := exec.Command(bin, args...)
1129 if filepath.IsAbs(dir) {
1130 setDir(cmd, dir)
1131 } else {
1132 setDir(cmd, filepath.Join(goroot, dir))
1133 }
1134 cmd.Stdout = os.Stdout
1135 cmd.Stderr = os.Stderr
1136 if vflag > 1 {
1137 errprintf("%#q\n", cmd)
1138 }
1139 return cmd
1140 }
1141
1142
1143
1144 func flattenCmdline(cmdline []any) (bin string, args []string) {
1145 var list []string
1146 for _, x := range cmdline {
1147 switch x := x.(type) {
1148 case string:
1149 list = append(list, x)
1150 case []string:
1151 list = append(list, x...)
1152 default:
1153 panic("invalid dirCmd argument type: " + reflect.TypeOf(x).String())
1154 }
1155 }
1156
1157 bin = list[0]
1158 if !filepath.IsAbs(bin) {
1159 panic("command is not absolute: " + bin)
1160 }
1161 return bin, list[1:]
1162 }
1163
1164 func (t *tester) iOS() bool {
1165 return goos == "ios"
1166 }
1167
1168 func (t *tester) out(v string) {
1169 if t.json {
1170 return
1171 }
1172 if t.banner == "" {
1173 return
1174 }
1175 fmt.Println("\n" + t.banner + v)
1176 }
1177
1178
1179
1180 func (t *tester) extLink() bool {
1181 if !cgoEnabled[goos+"/"+goarch] {
1182 return false
1183 }
1184 if goarch == "ppc64" && goos != "aix" && goos != "linux" {
1185 return false
1186 }
1187 return true
1188 }
1189
1190 func (t *tester) internalLink() bool {
1191 if gohostos == "dragonfly" {
1192
1193 return false
1194 }
1195 if goos == "android" {
1196 return false
1197 }
1198 if goos == "ios" {
1199 return false
1200 }
1201
1202
1203
1204 if goarch == "mips64" || goarch == "mips64le" || goarch == "mips" || goarch == "mipsle" || goarch == "riscv64" {
1205 return false
1206 }
1207 if goos == "aix" {
1208
1209 return false
1210 }
1211 if t.msan || t.asan {
1212
1213 return false
1214 }
1215 return true
1216 }
1217
1218 func (t *tester) internalLinkPIE() bool {
1219 if t.msan || t.asan {
1220
1221 return false
1222 }
1223 switch goos + "-" + goarch {
1224 case "darwin-amd64", "darwin-arm64",
1225 "linux-amd64", "linux-arm64", "linux-loong64", "linux-ppc64", "linux-ppc64le", "linux-s390x",
1226 "android-arm64",
1227 "windows-amd64", "windows-386", "windows-arm64":
1228 return true
1229 }
1230 return false
1231 }
1232
1233 func (t *tester) externalLinkPIE() bool {
1234
1235 return t.internalLinkPIE() && t.extLink()
1236 }
1237
1238
1239 func (t *tester) supportedBuildmode(mode string) bool {
1240 switch mode {
1241 case "c-archive", "c-shared", "shared", "plugin", "pie":
1242 default:
1243 fatalf("internal error: unknown buildmode %s", mode)
1244 return false
1245 }
1246
1247 return buildModeSupported("gc", mode, goos, goarch)
1248 }
1249
1250 func (t *tester) registerCgoTests(heading string) {
1251 cgoTest := func(variant string, subdir, linkmode, buildmode string, opts ...registerTestOpt) *goTest {
1252 gt := &goTest{
1253 variant: variant,
1254 pkg: "cmd/cgo/internal/" + subdir,
1255 buildmode: buildmode,
1256 }
1257 var ldflags []string
1258 if linkmode != "auto" {
1259
1260 ldflags = append(ldflags, "-linkmode="+linkmode)
1261 }
1262
1263 if linkmode == "internal" {
1264 gt.tags = append(gt.tags, "internal")
1265 if buildmode == "pie" {
1266 gt.tags = append(gt.tags, "internal_pie")
1267 }
1268 }
1269 if buildmode == "static" {
1270
1271
1272 gt.buildmode = ""
1273 switch linkmode {
1274 case "external":
1275 ldflags = append(ldflags, `-extldflags "-static -pthread"`)
1276 case "auto":
1277 gt.env = append(gt.env, "CGO_LDFLAGS=-static -pthread")
1278 default:
1279 panic("unknown linkmode with static build: " + linkmode)
1280 }
1281 gt.tags = append(gt.tags, "static")
1282 }
1283 gt.ldflags = strings.Join(ldflags, " ")
1284
1285 t.registerTest(heading, gt, opts...)
1286 return gt
1287 }
1288
1289
1290
1291
1292
1293
1294 builderName := os.Getenv("GO_BUILDER_NAME")
1295 disablePIE := strings.HasSuffix(builderName, "-alpine")
1296
1297 if t.internalLink() {
1298 cgoTest("internal", "test", "internal", "")
1299 }
1300
1301 os := gohostos
1302 p := gohostos + "/" + goarch
1303 switch os {
1304 case "darwin", "windows":
1305 if !t.extLink() {
1306 break
1307 }
1308
1309 cgoTest("external", "test", "external", "")
1310
1311 gt := cgoTest("external-s", "test", "external", "")
1312 gt.ldflags += " -s"
1313
1314 if t.supportedBuildmode("pie") && !disablePIE {
1315 cgoTest("auto-pie", "test", "auto", "pie")
1316 if t.internalLink() && t.internalLinkPIE() {
1317 cgoTest("internal-pie", "test", "internal", "pie")
1318 }
1319 }
1320
1321 case "aix", "android", "dragonfly", "freebsd", "linux", "netbsd", "openbsd":
1322 gt := cgoTest("external-g0", "test", "external", "")
1323 gt.env = append(gt.env, "CGO_CFLAGS=-g0 -fdiagnostics-color")
1324
1325 cgoTest("external", "testtls", "external", "")
1326 switch {
1327 case os == "aix":
1328
1329 case p == "freebsd/arm":
1330
1331
1332
1333
1334
1335 default:
1336
1337 var staticCheck rtSkipFunc
1338 ccName := compilerEnvLookup("CC", defaultcc, goos, goarch)
1339 cc, err := exec.LookPath(ccName)
1340 if err != nil {
1341 staticCheck.skip = func(*distTest) (string, bool) {
1342 return fmt.Sprintf("$CC (%q) not found, skip cgo static linking test.", ccName), true
1343 }
1344 } else {
1345 cmd := t.dirCmd("src/cmd/cgo/internal/test", cc, "-xc", "-o", "/dev/null", "-static", "-")
1346 cmd.Stdin = strings.NewReader("int main() {}")
1347 cmd.Stdout, cmd.Stderr = nil, nil
1348 if err := cmd.Run(); err != nil {
1349
1350 staticCheck.skip = func(*distTest) (string, bool) {
1351 return "No support for static linking found (lacks libc.a?), skip cgo static linking test.", true
1352 }
1353 }
1354 }
1355
1356
1357
1358
1359
1360 if staticCheck.skip == nil && goos == "linux" && strings.Contains(goexperiment, "boringcrypto") {
1361 staticCheck.skip = func(*distTest) (string, bool) {
1362 return "skipping static linking check on Linux when using boringcrypto to avoid C linker warning about getaddrinfo", true
1363 }
1364 }
1365
1366
1367 if goos != "android" && p != "netbsd/arm" && !t.msan && !t.asan {
1368
1369
1370
1371 cgoTest("static", "testtls", "external", "static", staticCheck)
1372 }
1373 cgoTest("external", "testnocgo", "external", "", staticCheck)
1374 if goos != "android" && !t.msan && !t.asan {
1375
1376
1377 cgoTest("static", "testnocgo", "external", "static", staticCheck)
1378 cgoTest("static", "test", "external", "static", staticCheck)
1379
1380
1381
1382 if goarch != "loong64" && !t.msan && !t.asan {
1383
1384 cgoTest("auto-static", "test", "auto", "static", staticCheck)
1385 }
1386 }
1387
1388
1389 if t.supportedBuildmode("pie") && !disablePIE {
1390 cgoTest("auto-pie", "test", "auto", "pie")
1391 if t.internalLink() && t.internalLinkPIE() {
1392 cgoTest("internal-pie", "test", "internal", "pie")
1393 }
1394 cgoTest("auto-pie", "testtls", "auto", "pie")
1395 cgoTest("auto-pie", "testnocgo", "auto", "pie")
1396 }
1397 }
1398 }
1399 }
1400
1401
1402
1403
1404
1405
1406
1407 func (t *tester) runPending(nextTest *distTest) {
1408 worklist := t.worklist
1409 t.worklist = nil
1410 var pendingSpan span
1411 if len(worklist) > 0 {
1412 pendingSpan = startSpan("runPending")
1413 }
1414 maxbg := runtime.GOMAXPROCS(0)
1415 for i, w := range worklist {
1416 w.start = make(chan bool)
1417 w.end = make(chan struct{})
1418
1419
1420 if w.cmd.Stdout == nil || w.cmd.Stdout == os.Stdout || w.cmd.Stderr == nil || w.cmd.Stderr == os.Stderr {
1421 panic("work.cmd.Stdout/Stderr must be redirected")
1422 }
1423 go func(w *work) {
1424 if !<-w.start {
1425 timelog("skip", w.dt.name)
1426 w.printSkip(t, "skipped due to earlier error")
1427 } else {
1428 timelog("start", w.dt.name)
1429 s := startSpanTID(w.dt.name, uint64(i%maxbg+1))
1430 w.err = w.cmd.Run()
1431 if w.flush != nil {
1432 w.flush()
1433 }
1434 s.done()
1435 if w.err != nil {
1436 if isUnsupportedVMASize(w) {
1437 timelog("skip", w.dt.name)
1438 w.out.Reset()
1439 w.printSkip(t, "skipped due to unsupported VMA")
1440 w.err = nil
1441 }
1442 }
1443 }
1444 timelog("end", w.dt.name)
1445 w.end <- struct{}{}
1446 }(w)
1447 }
1448
1449 started := 0
1450 ended := 0
1451 var last *distTest
1452 for ended < len(worklist) {
1453 for started < len(worklist) && started-ended < maxbg {
1454 w := worklist[started]
1455 started++
1456 w.start <- !t.failed || t.keepGoing
1457 }
1458 w := worklist[ended]
1459 dt := w.dt
1460 if t.lastHeading != dt.heading {
1461 t.lastHeading = dt.heading
1462 t.out(dt.heading)
1463 }
1464 if dt != last {
1465
1466 last = w.dt
1467 if vflag > 0 {
1468 fmt.Printf("# go tool dist test -run=^%s$\n", dt.name)
1469 }
1470 }
1471 if vflag > 1 {
1472 errprintf("%#q\n", w.cmd)
1473 }
1474 ended++
1475 <-w.end
1476 os.Stdout.Write(w.out.Bytes())
1477
1478 w.out = bytes.Buffer{}
1479 if w.err != nil {
1480 log.Printf("Failed: %v", w.err)
1481 t.failed = true
1482 }
1483 }
1484 pendingSpan.done()
1485 if t.failed && !t.keepGoing {
1486 fatalf("FAILED")
1487 }
1488
1489 if dt := nextTest; dt != nil {
1490 if t.lastHeading != dt.heading {
1491 t.lastHeading = dt.heading
1492 t.out(dt.heading)
1493 }
1494 if vflag > 0 {
1495 fmt.Printf("# go tool dist test -run=^%s$\n", dt.name)
1496 }
1497 }
1498 }
1499
1500
1501
1502
1503 func (t *tester) hasParallelism() bool {
1504 switch goos {
1505 case "js", "wasip1":
1506 return false
1507 }
1508 return true
1509 }
1510
1511 func (t *tester) raceDetectorSupported() bool {
1512 if gohostos != goos {
1513 return false
1514 }
1515 if !t.cgoEnabled {
1516 return false
1517 }
1518 if !raceDetectorSupported(goos, goarch) {
1519 return false
1520 }
1521
1522
1523 if isAlpineLinux() {
1524 return false
1525 }
1526
1527
1528 if goos == "netbsd" {
1529 return false
1530 }
1531 return true
1532 }
1533
1534 func isAlpineLinux() bool {
1535 if runtime.GOOS != "linux" {
1536 return false
1537 }
1538 fi, err := os.Lstat("/etc/alpine-release")
1539 return err == nil && fi.Mode().IsRegular()
1540 }
1541
1542 func (t *tester) registerRaceTests() {
1543 hdr := "Testing race detector"
1544 t.registerTest(hdr,
1545 &goTest{
1546 variant: "race",
1547 race: true,
1548 runTests: "Output",
1549 pkg: "runtime/race",
1550 })
1551 t.registerTest(hdr,
1552 &goTest{
1553 variant: "race",
1554 race: true,
1555 runTests: "TestParse|TestEcho|TestStdinCloseRace|TestClosedPipeRace|TestTypeRace|TestFdRace|TestFdReadRace|TestFileCloseRace",
1556 pkgs: []string{"flag", "net", "os", "os/exec", "encoding/gob"},
1557 })
1558
1559
1560
1561
1562
1563 if t.cgoEnabled {
1564
1565
1566
1567
1568
1569 }
1570 if t.extLink() {
1571
1572 t.registerTest(hdr,
1573 &goTest{
1574 variant: "race-external",
1575 race: true,
1576 ldflags: "-linkmode=external",
1577 runTests: "TestParse|TestEcho|TestStdinCloseRace",
1578 pkgs: []string{"flag", "os/exec"},
1579 })
1580 }
1581 }
1582
1583
1584 var cgoPackages = []string{
1585 "net",
1586 "os/user",
1587 }
1588
1589 var funcBenchmark = []byte("\nfunc Benchmark")
1590
1591
1592
1593
1594
1595
1596
1597
1598 func (t *tester) packageHasBenchmarks(pkg string) bool {
1599 pkgDir := filepath.Join(goroot, "src", pkg)
1600 d, err := os.Open(pkgDir)
1601 if err != nil {
1602 return true
1603 }
1604 defer d.Close()
1605 names, err := d.Readdirnames(-1)
1606 if err != nil {
1607 return true
1608 }
1609 for _, name := range names {
1610 if !strings.HasSuffix(name, "_test.go") {
1611 continue
1612 }
1613 slurp, err := os.ReadFile(filepath.Join(pkgDir, name))
1614 if err != nil {
1615 return true
1616 }
1617 if bytes.Contains(slurp, funcBenchmark) {
1618 return true
1619 }
1620 }
1621 return false
1622 }
1623
1624
1625
1626 func (t *tester) makeGOROOTUnwritable() (undo func()) {
1627 dir := os.Getenv("GOROOT")
1628 if dir == "" {
1629 panic("GOROOT not set")
1630 }
1631
1632 type pathMode struct {
1633 path string
1634 mode os.FileMode
1635 }
1636 var dirs []pathMode
1637
1638 undo = func() {
1639 for i := range dirs {
1640 os.Chmod(dirs[i].path, dirs[i].mode)
1641 }
1642 }
1643
1644 filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
1645 if suffix := strings.TrimPrefix(path, dir+string(filepath.Separator)); suffix != "" {
1646 if suffix == ".git" {
1647
1648
1649
1650 return filepath.SkipDir
1651 }
1652 }
1653 if err != nil {
1654 return nil
1655 }
1656
1657 info, err := d.Info()
1658 if err != nil {
1659 return nil
1660 }
1661
1662 mode := info.Mode()
1663 if mode&0222 != 0 && (mode.IsDir() || mode.IsRegular()) {
1664 dirs = append(dirs, pathMode{path, mode})
1665 }
1666 return nil
1667 })
1668
1669
1670 for i := len(dirs) - 1; i >= 0; i-- {
1671 err := os.Chmod(dirs[i].path, dirs[i].mode&^0222)
1672 if err != nil {
1673 dirs = dirs[i:]
1674 undo()
1675 fatalf("failed to make GOROOT read-only: %v", err)
1676 }
1677 }
1678
1679 return undo
1680 }
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690 func raceDetectorSupported(goos, goarch string) bool {
1691 switch goos {
1692 case "linux":
1693 return goarch == "amd64" || goarch == "arm64" || goarch == "loong64" || goarch == "ppc64le" || goarch == "riscv64" || goarch == "s390x"
1694 case "darwin":
1695 return goarch == "amd64" || goarch == "arm64"
1696 case "freebsd", "netbsd", "windows":
1697 return goarch == "amd64"
1698 default:
1699 return false
1700 }
1701 }
1702
1703
1704
1705
1706 func fips140Supported(goos, goarch string) bool {
1707 switch {
1708 case goarch == "wasm",
1709 goos == "windows" && goarch == "386",
1710 goos == "openbsd",
1711 goos == "aix":
1712 return false
1713 }
1714 return true
1715 }
1716
1717
1718
1719
1720 func buildModeSupported(compiler, buildmode, goos, goarch string) bool {
1721 if compiler == "gccgo" {
1722 return true
1723 }
1724
1725 platform := goos + "/" + goarch
1726
1727 switch buildmode {
1728 case "archive":
1729 return true
1730
1731 case "c-archive":
1732 switch goos {
1733 case "aix", "darwin", "ios", "windows":
1734 return true
1735 case "linux":
1736 switch goarch {
1737 case "386", "amd64", "arm", "armbe", "arm64", "arm64be", "loong64", "ppc64", "ppc64le", "riscv64", "s390x":
1738 return true
1739 default:
1740
1741
1742
1743
1744
1745
1746 return false
1747 }
1748 case "freebsd":
1749 return goarch == "amd64"
1750 }
1751 return false
1752
1753 case "c-shared":
1754 switch platform {
1755 case "linux/amd64", "linux/arm", "linux/arm64", "linux/loong64", "linux/386", "linux/ppc64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
1756 "android/amd64", "android/arm", "android/arm64", "android/386",
1757 "freebsd/amd64",
1758 "darwin/amd64", "darwin/arm64",
1759 "windows/amd64", "windows/386", "windows/arm64",
1760 "wasip1/wasm":
1761 return true
1762 }
1763 return false
1764
1765 case "default":
1766 return true
1767
1768 case "exe":
1769 return true
1770
1771 case "pie":
1772 switch platform {
1773 case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/loong64", "linux/ppc64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
1774 "android/amd64", "android/arm", "android/arm64", "android/386",
1775 "freebsd/amd64",
1776 "darwin/amd64", "darwin/arm64",
1777 "ios/amd64", "ios/arm64",
1778 "aix/ppc64",
1779 "openbsd/amd64", "openbsd/arm64",
1780 "windows/386", "windows/amd64", "windows/arm64":
1781 return true
1782 }
1783 return false
1784
1785 case "shared":
1786 switch platform {
1787 case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64", "linux/ppc64le", "linux/s390x":
1788 return true
1789 }
1790 return false
1791
1792 case "plugin":
1793 switch platform {
1794 case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/loong64", "linux/riscv64", "linux/s390x", "linux/ppc64", "linux/ppc64le",
1795 "android/amd64", "android/386",
1796 "darwin/amd64", "darwin/arm64",
1797 "freebsd/amd64":
1798 return true
1799 }
1800 return false
1801
1802 default:
1803 return false
1804 }
1805 }
1806
1807
1808
1809
1810 func isUnsupportedVMASize(w *work) bool {
1811 unsupportedVMA := []byte("unsupported VMA range")
1812 return strings.Contains(w.dt.name, ":race") && bytes.Contains(w.out.Bytes(), unsupportedVMA)
1813 }
1814
1815
1816
1817 func isEnvSet(evar string) bool {
1818 evarEq := evar + "="
1819 for _, e := range os.Environ() {
1820 if strings.HasPrefix(e, evarEq) {
1821 return true
1822 }
1823 }
1824 return false
1825 }
1826
1827 func (t *tester) fips140Supported() bool {
1828 if !fips140Supported(goos, goarch) {
1829 return false
1830 }
1831
1832
1833
1834
1835
1836 if strings.Contains(goexperiment, "boringcrypto") {
1837 return false
1838 }
1839
1840
1841
1842 if t.asan {
1843 return false
1844 }
1845
1846 return true
1847 }
1848
1849
1850 func fips140Versions() []string {
1851 var versions []string
1852 zips, err := filepath.Glob(filepath.Join(goroot, "lib/fips140/*.zip"))
1853 if err != nil {
1854 fatalf("%v", err)
1855 }
1856 for _, zip := range zips {
1857 versions = append(versions, strings.TrimSuffix(filepath.Base(zip), ".zip"))
1858 }
1859 return versions
1860 }
1861
1862
1863
1864
1865
1866 func goexperiments(exps ...string) string {
1867 if len(exps) == 0 {
1868 return goexperiment
1869 }
1870 existing := goexperiment
1871 if existing != "" {
1872 existing += ","
1873 }
1874 return existing + strings.Join(exps, ",")
1875
1876 }
1877
View as plain text