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