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