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