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 if pkg == "cmd/go" {
577 timeoutSec *= 3
578 break
579 }
580 }
581 return (&goTest{
582 timeout: timeoutSec,
583 gcflags: gcflags,
584 pkgs: stdMatches,
585 }).run(t)
586 })
587 }
588
589 func (t *tester) registerRaceBenchTest(pkg string) {
590 const raceBenchHeading = "Running benchmarks briefly."
591 name := testName(pkg, "racebench")
592 if t.runRx == nil || t.runRx.MatchString(name) == t.runRxWant {
593 benchMatches = append(benchMatches, pkg)
594 }
595 t.addTest(name, raceBenchHeading, func(dt *distTest) error {
596 if ranGoBench {
597 return nil
598 }
599 t.runPending(dt)
600 timelog("start", dt.name)
601 defer timelog("end", dt.name)
602 ranGoBench = true
603 return (&goTest{
604 variant: "racebench",
605
606
607
608 omitVariant: false,
609 timeout: 1200 * time.Second,
610 race: true,
611 bench: true,
612 cpu: "4",
613 pkgs: benchMatches,
614 }).run(t)
615 })
616 }
617
618 func (t *tester) registerTests() {
619
620
621
622
623
624
625
626 registerStdTestSpecially := map[string]bool{
627
628
629
630
631 "cmd/internal/testdir": true,
632 }
633
634
635
636
637 if len(t.runNames) > 0 {
638 for _, name := range t.runNames {
639 if !strings.Contains(name, ":") {
640 t.registerStdTest(name)
641 } else if strings.HasSuffix(name, ":racebench") {
642 t.registerRaceBenchTest(strings.TrimSuffix(name, ":racebench"))
643 }
644 }
645 } else {
646
647
648
649
650
651
652
653
654
655
656
657
658
659 cmd := exec.Command(gorootBinGo, "list")
660 if t.race {
661 cmd.Args = append(cmd.Args, "-tags=race")
662 }
663 cmd.Args = append(cmd.Args, "std", "cmd")
664 cmd.Stderr = new(bytes.Buffer)
665 all, err := cmd.Output()
666 if err != nil {
667 fatalf("Error running go list std cmd: %v:\n%s", err, cmd.Stderr)
668 }
669 pkgs := strings.Fields(string(all))
670 for _, pkg := range pkgs {
671 if registerStdTestSpecially[pkg] {
672 continue
673 }
674 if t.short && (strings.HasPrefix(pkg, "vendor/") || strings.HasPrefix(pkg, "cmd/vendor/")) {
675
676
677
678 continue
679 }
680 t.registerStdTest(pkg)
681 }
682 if t.race && !t.short {
683 for _, pkg := range pkgs {
684 if t.packageHasBenchmarks(pkg) {
685 t.registerRaceBenchTest(pkg)
686 }
687 }
688 }
689 }
690
691 if t.race {
692 return
693 }
694
695
696 if !t.compileOnly {
697 t.registerTest("os/user with tag osusergo",
698 &goTest{
699 variant: "osusergo",
700 timeout: 300 * time.Second,
701 tags: []string{"osusergo"},
702 pkg: "os/user",
703 })
704 }
705
706
707 t.registerTest("crypto with tag purego (build and vet only)", &goTest{
708 variant: "purego",
709 tags: []string{"purego"},
710 pkg: "crypto/...",
711 runTests: "^$",
712 })
713
714
715 if t.fipsSupported() {
716
717 t.registerTest("GOFIPS140=latest go test crypto/...", &goTest{
718 variant: "gofips140",
719 env: []string{"GOFIPS140=latest"},
720 pkg: "crypto/...",
721 })
722
723
724
725 for _, version := range fipsVersions() {
726 suffix := " # (build and vet only)"
727 run := "^$"
728 if !t.short {
729 suffix = ""
730 run = ""
731 }
732 t.registerTest("GOFIPS140="+version+" go test crypto/..."+suffix, &goTest{
733 variant: "gofips140-" + version,
734 pkg: "crypto/...",
735 runTests: run,
736 env: []string{"GOFIPS140=" + version, "GOMODCACHE=" + filepath.Join(workdir, "fips-"+version)},
737 })
738 }
739 }
740
741
742 if !strings.Contains(goexperiment, "jsonv2") {
743 t.registerTest("GOEXPERIMENT=jsonv2 go test encoding/json/...", &goTest{
744 variant: "jsonv2",
745 env: []string{"GOEXPERIMENT=" + goexperiments("jsonv2")},
746 pkg: "encoding/json/...",
747 })
748 }
749
750
751 if !strings.Contains(goexperiment, "runtimesecret") {
752 t.registerTest("GOEXPERIMENT=runtimesecret go test runtime/secret/...", &goTest{
753 variant: "runtimesecret",
754 env: []string{"GOEXPERIMENT=" + goexperiments("runtimesecret")},
755 pkg: "runtime/secret/...",
756 })
757 }
758
759
760 if goarch == "amd64" && !strings.Contains(goexperiment, "simd") {
761 t.registerTest("GOEXPERIMENT=simd go test simd/archsimd/...", &goTest{
762 variant: "simd",
763 env: []string{"GOEXPERIMENT=" + goexperiments("simd")},
764 pkg: "simd/archsimd/...",
765 })
766 }
767
768
769 if goos == "darwin" && goarch == "amd64" && t.cgoEnabled {
770 t.registerTest("GOOS=ios on darwin/amd64",
771 &goTest{
772 variant: "amd64ios",
773 timeout: 300 * time.Second,
774 runTests: "SystemRoots",
775 env: []string{"GOOS=ios", "CGO_ENABLED=1"},
776 pkg: "crypto/x509",
777 })
778 }
779
780
781
782
783 if !t.compileOnly && !t.short {
784 t.registerTest("GODEBUG=gcstoptheworld=2 archive/zip",
785 &goTest{
786 variant: "gcstoptheworld2",
787 timeout: 300 * time.Second,
788 short: true,
789 env: []string{"GODEBUG=gcstoptheworld=2"},
790 pkg: "archive/zip",
791 })
792 t.registerTest("GODEBUG=gccheckmark=1 runtime",
793 &goTest{
794 variant: "gccheckmark",
795 timeout: 300 * time.Second,
796 short: true,
797 env: []string{"GODEBUG=gccheckmark=1"},
798 pkg: "runtime",
799 })
800 }
801
802
803 if goos == "linux" && goarch == "amd64" && !(gogcflags == "-spectre=all" && t.asmflags == "all=-spectre=all") {
804
805 pkgs := []string{"internal/runtime/...", "reflect", "crypto/..."}
806 if !t.short {
807 pkgs = append(pkgs, "runtime")
808 }
809 t.registerTest("spectre",
810 &goTest{
811 variant: "spectre",
812 short: true,
813 env: []string{"GOFLAGS=-gcflags=all=-spectre=all -asmflags=all=-spectre=all"},
814 pkgs: pkgs,
815 })
816 }
817
818
819
820
821
822 if !t.compileOnly && !t.short {
823
824 hooks := []string{"mayMoreStackPreempt", "mayMoreStackMove"}
825
826
827 hookPkgs := []string{"runtime/...", "reflect", "sync"}
828
829
830 unhookPkgs := []string{"runtime/testdata/..."}
831 for _, hook := range hooks {
832
833
834
835
836
837
838 goFlagsList := []string{}
839 for _, flag := range []string{"-gcflags", "-asmflags"} {
840 for _, hookPkg := range hookPkgs {
841 goFlagsList = append(goFlagsList, flag+"="+hookPkg+"=-d=maymorestack=runtime."+hook)
842 }
843 for _, unhookPkg := range unhookPkgs {
844 goFlagsList = append(goFlagsList, flag+"="+unhookPkg+"=")
845 }
846 }
847 goFlags := strings.Join(goFlagsList, " ")
848
849 t.registerTest("maymorestack="+hook,
850 &goTest{
851 variant: hook,
852 timeout: 600 * time.Second,
853 short: true,
854 env: []string{"GOFLAGS=" + goFlags},
855 pkgs: []string{"runtime", "reflect", "sync"},
856 })
857 }
858 }
859
860
861
862
863
864 for _, pkg := range cgoPackages {
865 if !t.internalLink() {
866 break
867 }
868
869
870 if goarch == "arm" {
871 break
872 }
873
874
875
876 run := "^Test[^CS]"
877 if pkg == "net" {
878 run = "TestTCPStress"
879 }
880 t.registerTest("Testing without libgcc.",
881 &goTest{
882 variant: "nolibgcc",
883 ldflags: "-linkmode=internal -libgcc=none",
884 runTests: run,
885 pkg: pkg,
886 })
887 }
888
889
890 builderName := os.Getenv("GO_BUILDER_NAME")
891 disablePIE := strings.HasSuffix(builderName, "-alpine")
892
893
894 if t.internalLinkPIE() && !disablePIE {
895 t.registerTest("internal linking, -buildmode=pie",
896 &goTest{
897 variant: "pie_internal",
898 timeout: 60 * time.Second,
899 buildmode: "pie",
900 ldflags: "-linkmode=internal",
901 env: []string{"CGO_ENABLED=0"},
902 pkg: "reflect",
903 })
904 t.registerTest("internal linking, -buildmode=pie",
905 &goTest{
906 variant: "pie_internal",
907 timeout: 60 * time.Second,
908 buildmode: "pie",
909 ldflags: "-linkmode=internal",
910 env: []string{"CGO_ENABLED=0"},
911 pkg: "crypto/internal/fips140test",
912 runTests: "TestFIPSCheck",
913 })
914
915 if t.cgoEnabled && t.internalLink() && !disablePIE {
916 t.registerTest("internal linking, -buildmode=pie",
917 &goTest{
918 variant: "pie_internal",
919 timeout: 60 * time.Second,
920 buildmode: "pie",
921 ldflags: "-linkmode=internal",
922 pkg: "os/user",
923 })
924 }
925 }
926
927 if t.extLink() && !t.compileOnly {
928 if goos != "android" {
929 t.registerTest("external linking, -buildmode=exe",
930 &goTest{
931 variant: "exe_external",
932 timeout: 60 * time.Second,
933 buildmode: "exe",
934 ldflags: "-linkmode=external",
935 env: []string{"CGO_ENABLED=1"},
936 pkg: "crypto/internal/fips140test",
937 runTests: "TestFIPSCheck",
938 })
939 }
940 if t.externalLinkPIE() && !disablePIE {
941 t.registerTest("external linking, -buildmode=pie",
942 &goTest{
943 variant: "pie_external",
944 timeout: 60 * time.Second,
945 buildmode: "pie",
946 ldflags: "-linkmode=external",
947 env: []string{"CGO_ENABLED=1"},
948 pkg: "crypto/internal/fips140test",
949 runTests: "TestFIPSCheck",
950 })
951 }
952 }
953
954
955 if t.hasParallelism() {
956 t.registerTest("sync -cpu=10",
957 &goTest{
958 variant: "cpu10",
959 timeout: 120 * time.Second,
960 cpu: "10",
961 pkg: "sync",
962 })
963 }
964
965 const cgoHeading = "Testing cgo"
966 if t.cgoEnabled {
967 t.registerCgoTests(cgoHeading)
968 }
969
970 if goos == "wasip1" {
971 t.registerTest("wasip1 host tests",
972 &goTest{
973 variant: "host",
974 pkg: "internal/runtime/wasitest",
975 timeout: 1 * time.Minute,
976 runOnHost: true,
977 })
978 }
979
980
981
982
983
984
985
986
987
988
989 if goos == "darwin" || ((goos == "linux" || goos == "windows") && (goarch == "amd64" && !strings.Contains(goexperiment, "simd"))) {
990 t.registerTest("API release note check", &goTest{variant: "check", pkg: "cmd/relnote", testFlags: []string{"-check"}})
991 t.registerTest("API check", &goTest{variant: "check", pkg: "cmd/api", timeout: 5 * time.Minute, testFlags: []string{"-check"}})
992 }
993
994
995 if !t.compileOnly && t.hasParallelism() {
996 for i := 1; i <= 4; i *= 2 {
997 t.registerTest(fmt.Sprintf("GOMAXPROCS=2 runtime -cpu=%d -quick", i),
998 &goTest{
999 variant: "cpu" + strconv.Itoa(i),
1000 timeout: 300 * time.Second,
1001 cpu: strconv.Itoa(i),
1002 gcflags: gogcflags,
1003 short: true,
1004 testFlags: []string{"-quick"},
1005
1006
1007 env: []string{"GOMAXPROCS=2"},
1008 pkg: "runtime",
1009 })
1010 }
1011 }
1012
1013 if t.raceDetectorSupported() && !t.msan && !t.asan {
1014
1015 t.registerRaceTests()
1016 }
1017
1018 if goos != "android" && !t.iOS() {
1019
1020
1021
1022 nShards := 1
1023 if os.Getenv("GO_BUILDER_NAME") != "" {
1024 nShards = 10
1025 }
1026 if n, err := strconv.Atoi(os.Getenv("GO_TEST_SHARDS")); err == nil {
1027 nShards = n
1028 }
1029 for shard := 0; shard < nShards; shard++ {
1030 id := fmt.Sprintf("%d_%d", shard, nShards)
1031 t.registerTest("../test",
1032 &goTest{
1033 variant: id,
1034
1035
1036
1037 omitVariant: false,
1038 pkg: "cmd/internal/testdir",
1039 testFlags: []string{fmt.Sprintf("-shard=%d", shard), fmt.Sprintf("-shards=%d", nShards)},
1040 runOnHost: true,
1041 },
1042 )
1043 }
1044 }
1045 }
1046
1047
1048
1049
1050 func (t *tester) addTest(name, heading string, fn func(*distTest) error) {
1051 if t.testNames[name] {
1052 panic("duplicate registered test name " + name)
1053 }
1054 if heading == "" {
1055 panic("empty heading")
1056 }
1057
1058 if !strings.Contains(name, ":") && heading != "Testing packages." {
1059 panic("empty variant is reserved exclusively for registerStdTest")
1060 } else if strings.HasSuffix(name, ":racebench") && heading != "Running benchmarks briefly." {
1061 panic("racebench variant is reserved exclusively for registerRaceBenchTest")
1062 }
1063 if t.testNames == nil {
1064 t.testNames = make(map[string]bool)
1065 }
1066 t.testNames[name] = true
1067 t.tests = append(t.tests, distTest{
1068 name: name,
1069 heading: heading,
1070 fn: fn,
1071 })
1072 }
1073
1074 type registerTestOpt interface {
1075 isRegisterTestOpt()
1076 }
1077
1078
1079
1080 type rtSkipFunc struct {
1081 skip func(*distTest) (string, bool)
1082 }
1083
1084 func (rtSkipFunc) isRegisterTestOpt() {}
1085
1086
1087
1088
1089
1090
1091
1092 func (t *tester) registerTest(heading string, test *goTest, opts ...registerTestOpt) {
1093 var skipFunc func(*distTest) (string, bool)
1094 for _, opt := range opts {
1095 switch opt := opt.(type) {
1096 case rtSkipFunc:
1097 skipFunc = opt.skip
1098 }
1099 }
1100
1101 register1 := func(test *goTest) {
1102 if test.variant == "" {
1103 panic("empty variant")
1104 }
1105 name := testName(test.pkg, test.variant)
1106 t.addTest(name, heading, func(dt *distTest) error {
1107 if skipFunc != nil {
1108 msg, skip := skipFunc(dt)
1109 if skip {
1110 test.printSkip(t, msg)
1111 return nil
1112 }
1113 }
1114 w := &work{dt: dt}
1115 w.cmd, w.flush = test.bgCommand(t, &w.out, &w.out)
1116 t.worklist = append(t.worklist, w)
1117 return nil
1118 })
1119 }
1120 if test.pkg != "" && len(test.pkgs) == 0 {
1121
1122 register1(test)
1123 return
1124 }
1125
1126
1127
1128
1129
1130
1131 for _, pkg := range test.packages() {
1132 test1 := *test
1133 test1.pkg, test1.pkgs = pkg, nil
1134 register1(&test1)
1135 }
1136 }
1137
1138
1139
1140
1141 func (t *tester) dirCmd(dir string, cmdline ...any) *exec.Cmd {
1142 bin, args := flattenCmdline(cmdline)
1143 cmd := exec.Command(bin, args...)
1144 if filepath.IsAbs(dir) {
1145 setDir(cmd, dir)
1146 } else {
1147 setDir(cmd, filepath.Join(goroot, dir))
1148 }
1149 cmd.Stdout = os.Stdout
1150 cmd.Stderr = os.Stderr
1151 if vflag > 1 {
1152 errprintf("%#q\n", cmd)
1153 }
1154 return cmd
1155 }
1156
1157
1158
1159 func flattenCmdline(cmdline []any) (bin string, args []string) {
1160 var list []string
1161 for _, x := range cmdline {
1162 switch x := x.(type) {
1163 case string:
1164 list = append(list, x)
1165 case []string:
1166 list = append(list, x...)
1167 default:
1168 panic("invalid dirCmd argument type: " + reflect.TypeOf(x).String())
1169 }
1170 }
1171
1172 bin = list[0]
1173 if !filepath.IsAbs(bin) {
1174 panic("command is not absolute: " + bin)
1175 }
1176 return bin, list[1:]
1177 }
1178
1179 func (t *tester) iOS() bool {
1180 return goos == "ios"
1181 }
1182
1183 func (t *tester) out(v string) {
1184 if t.json {
1185 return
1186 }
1187 if t.banner == "" {
1188 return
1189 }
1190 fmt.Println("\n" + t.banner + v)
1191 }
1192
1193
1194
1195 func (t *tester) extLink() bool {
1196 if !cgoEnabled[goos+"/"+goarch] {
1197 return false
1198 }
1199 if goarch == "ppc64" && goos != "aix" {
1200 return false
1201 }
1202 return true
1203 }
1204
1205 func (t *tester) internalLink() bool {
1206 if gohostos == "dragonfly" {
1207
1208 return false
1209 }
1210 if goos == "android" {
1211 return false
1212 }
1213 if goos == "ios" {
1214 return false
1215 }
1216
1217
1218
1219 if goarch == "mips64" || goarch == "mips64le" || goarch == "mips" || goarch == "mipsle" || goarch == "riscv64" {
1220 return false
1221 }
1222 if goos == "aix" {
1223
1224 return false
1225 }
1226 if t.msan || t.asan {
1227
1228 return false
1229 }
1230 return true
1231 }
1232
1233 func (t *tester) internalLinkPIE() bool {
1234 if t.msan || t.asan {
1235
1236 return false
1237 }
1238 switch goos + "-" + goarch {
1239 case "darwin-amd64", "darwin-arm64",
1240 "linux-amd64", "linux-arm64", "linux-loong64", "linux-ppc64le", "linux-s390x",
1241 "android-arm64",
1242 "windows-amd64", "windows-386", "windows-arm64":
1243 return true
1244 }
1245 return false
1246 }
1247
1248 func (t *tester) externalLinkPIE() bool {
1249
1250 return t.internalLinkPIE() && t.extLink()
1251 }
1252
1253
1254 func (t *tester) supportedBuildmode(mode string) bool {
1255 switch mode {
1256 case "c-archive", "c-shared", "shared", "plugin", "pie":
1257 default:
1258 fatalf("internal error: unknown buildmode %s", mode)
1259 return false
1260 }
1261
1262 return buildModeSupported("gc", mode, goos, goarch)
1263 }
1264
1265 func (t *tester) registerCgoTests(heading string) {
1266 cgoTest := func(variant string, subdir, linkmode, buildmode string, opts ...registerTestOpt) *goTest {
1267 gt := &goTest{
1268 variant: variant,
1269 pkg: "cmd/cgo/internal/" + subdir,
1270 buildmode: buildmode,
1271 }
1272 var ldflags []string
1273 if linkmode != "auto" {
1274
1275 ldflags = append(ldflags, "-linkmode="+linkmode)
1276 }
1277
1278 if linkmode == "internal" {
1279 gt.tags = append(gt.tags, "internal")
1280 if buildmode == "pie" {
1281 gt.tags = append(gt.tags, "internal_pie")
1282 }
1283 }
1284 if buildmode == "static" {
1285
1286
1287 gt.buildmode = ""
1288 switch linkmode {
1289 case "external":
1290 ldflags = append(ldflags, `-extldflags "-static -pthread"`)
1291 case "auto":
1292 gt.env = append(gt.env, "CGO_LDFLAGS=-static -pthread")
1293 default:
1294 panic("unknown linkmode with static build: " + linkmode)
1295 }
1296 gt.tags = append(gt.tags, "static")
1297 }
1298 gt.ldflags = strings.Join(ldflags, " ")
1299
1300 t.registerTest(heading, gt, opts...)
1301 return gt
1302 }
1303
1304
1305
1306
1307
1308
1309 builderName := os.Getenv("GO_BUILDER_NAME")
1310 disablePIE := strings.HasSuffix(builderName, "-alpine")
1311
1312 if t.internalLink() {
1313 cgoTest("internal", "test", "internal", "")
1314 }
1315
1316 os := gohostos
1317 p := gohostos + "/" + goarch
1318 switch os {
1319 case "darwin", "windows":
1320 if !t.extLink() {
1321 break
1322 }
1323
1324 cgoTest("external", "test", "external", "")
1325
1326 gt := cgoTest("external-s", "test", "external", "")
1327 gt.ldflags += " -s"
1328
1329 if t.supportedBuildmode("pie") && !disablePIE {
1330 cgoTest("auto-pie", "test", "auto", "pie")
1331 if t.internalLink() && t.internalLinkPIE() {
1332 cgoTest("internal-pie", "test", "internal", "pie")
1333 }
1334 }
1335
1336 case "aix", "android", "dragonfly", "freebsd", "linux", "netbsd", "openbsd":
1337 gt := cgoTest("external-g0", "test", "external", "")
1338 gt.env = append(gt.env, "CGO_CFLAGS=-g0 -fdiagnostics-color")
1339
1340 cgoTest("external", "testtls", "external", "")
1341 switch {
1342 case os == "aix":
1343
1344 case p == "freebsd/arm":
1345
1346
1347
1348
1349
1350 default:
1351
1352 var staticCheck rtSkipFunc
1353 ccName := compilerEnvLookup("CC", defaultcc, goos, goarch)
1354 cc, err := exec.LookPath(ccName)
1355 if err != nil {
1356 staticCheck.skip = func(*distTest) (string, bool) {
1357 return fmt.Sprintf("$CC (%q) not found, skip cgo static linking test.", ccName), true
1358 }
1359 } else {
1360 cmd := t.dirCmd("src/cmd/cgo/internal/test", cc, "-xc", "-o", "/dev/null", "-static", "-")
1361 cmd.Stdin = strings.NewReader("int main() {}")
1362 cmd.Stdout, cmd.Stderr = nil, nil
1363 if err := cmd.Run(); err != nil {
1364
1365 staticCheck.skip = func(*distTest) (string, bool) {
1366 return "No support for static linking found (lacks libc.a?), skip cgo static linking test.", true
1367 }
1368 }
1369 }
1370
1371
1372
1373
1374
1375 if staticCheck.skip == nil && goos == "linux" && strings.Contains(goexperiment, "boringcrypto") {
1376 staticCheck.skip = func(*distTest) (string, bool) {
1377 return "skipping static linking check on Linux when using boringcrypto to avoid C linker warning about getaddrinfo", true
1378 }
1379 }
1380
1381
1382 if goos != "android" && p != "netbsd/arm" && !t.msan && !t.asan {
1383
1384
1385
1386 cgoTest("static", "testtls", "external", "static", staticCheck)
1387 }
1388 cgoTest("external", "testnocgo", "external", "", staticCheck)
1389 if goos != "android" && !t.msan && !t.asan {
1390
1391
1392 cgoTest("static", "testnocgo", "external", "static", staticCheck)
1393 cgoTest("static", "test", "external", "static", staticCheck)
1394
1395
1396
1397 if goarch != "loong64" && !t.msan && !t.asan {
1398
1399 cgoTest("auto-static", "test", "auto", "static", staticCheck)
1400 }
1401 }
1402
1403
1404 if t.supportedBuildmode("pie") && !disablePIE {
1405 cgoTest("auto-pie", "test", "auto", "pie")
1406 if t.internalLink() && t.internalLinkPIE() {
1407 cgoTest("internal-pie", "test", "internal", "pie")
1408 }
1409 cgoTest("auto-pie", "testtls", "auto", "pie")
1410 cgoTest("auto-pie", "testnocgo", "auto", "pie")
1411 }
1412 }
1413 }
1414 }
1415
1416
1417
1418
1419
1420
1421
1422 func (t *tester) runPending(nextTest *distTest) {
1423 worklist := t.worklist
1424 t.worklist = nil
1425 for _, w := range worklist {
1426 w.start = make(chan bool)
1427 w.end = make(chan struct{})
1428
1429
1430 if w.cmd.Stdout == nil || w.cmd.Stdout == os.Stdout || w.cmd.Stderr == nil || w.cmd.Stderr == os.Stderr {
1431 panic("work.cmd.Stdout/Stderr must be redirected")
1432 }
1433 go func(w *work) {
1434 if !<-w.start {
1435 timelog("skip", w.dt.name)
1436 w.printSkip(t, "skipped due to earlier error")
1437 } else {
1438 timelog("start", w.dt.name)
1439 w.err = w.cmd.Run()
1440 if w.flush != nil {
1441 w.flush()
1442 }
1443 if w.err != nil {
1444 if isUnsupportedVMASize(w) {
1445 timelog("skip", w.dt.name)
1446 w.out.Reset()
1447 w.printSkip(t, "skipped due to unsupported VMA")
1448 w.err = nil
1449 }
1450 }
1451 }
1452 timelog("end", w.dt.name)
1453 w.end <- struct{}{}
1454 }(w)
1455 }
1456
1457 maxbg := maxbg
1458
1459
1460 if runtime.NumCPU() > 4 && runtime.GOMAXPROCS(0) != 1 {
1461 for _, w := range worklist {
1462
1463
1464
1465
1466
1467 if strings.Contains(w.dt.heading, "GOMAXPROCS=2 runtime") {
1468 maxbg = runtime.NumCPU()
1469 break
1470 }
1471 }
1472 }
1473
1474 started := 0
1475 ended := 0
1476 var last *distTest
1477 for ended < len(worklist) {
1478 for started < len(worklist) && started-ended < maxbg {
1479 w := worklist[started]
1480 started++
1481 w.start <- !t.failed || t.keepGoing
1482 }
1483 w := worklist[ended]
1484 dt := w.dt
1485 if t.lastHeading != dt.heading {
1486 t.lastHeading = dt.heading
1487 t.out(dt.heading)
1488 }
1489 if dt != last {
1490
1491 last = w.dt
1492 if vflag > 0 {
1493 fmt.Printf("# go tool dist test -run=^%s$\n", dt.name)
1494 }
1495 }
1496 if vflag > 1 {
1497 errprintf("%#q\n", w.cmd)
1498 }
1499 ended++
1500 <-w.end
1501 os.Stdout.Write(w.out.Bytes())
1502
1503 w.out = bytes.Buffer{}
1504 if w.err != nil {
1505 log.Printf("Failed: %v", w.err)
1506 t.failed = true
1507 }
1508 }
1509 if t.failed && !t.keepGoing {
1510 fatalf("FAILED")
1511 }
1512
1513 if dt := nextTest; dt != nil {
1514 if t.lastHeading != dt.heading {
1515 t.lastHeading = dt.heading
1516 t.out(dt.heading)
1517 }
1518 if vflag > 0 {
1519 fmt.Printf("# go tool dist test -run=^%s$\n", dt.name)
1520 }
1521 }
1522 }
1523
1524
1525
1526
1527 func (t *tester) hasParallelism() bool {
1528 switch goos {
1529 case "js", "wasip1":
1530 return false
1531 }
1532 return true
1533 }
1534
1535 func (t *tester) raceDetectorSupported() bool {
1536 if gohostos != goos {
1537 return false
1538 }
1539 if !t.cgoEnabled {
1540 return false
1541 }
1542 if !raceDetectorSupported(goos, goarch) {
1543 return false
1544 }
1545
1546
1547 if isAlpineLinux() {
1548 return false
1549 }
1550
1551
1552 if goos == "netbsd" {
1553 return false
1554 }
1555 return true
1556 }
1557
1558 func isAlpineLinux() bool {
1559 if runtime.GOOS != "linux" {
1560 return false
1561 }
1562 fi, err := os.Lstat("/etc/alpine-release")
1563 return err == nil && fi.Mode().IsRegular()
1564 }
1565
1566 func (t *tester) registerRaceTests() {
1567 hdr := "Testing race detector"
1568 t.registerTest(hdr,
1569 &goTest{
1570 variant: "race",
1571 race: true,
1572 runTests: "Output",
1573 pkg: "runtime/race",
1574 })
1575 t.registerTest(hdr,
1576 &goTest{
1577 variant: "race",
1578 race: true,
1579 runTests: "TestParse|TestEcho|TestStdinCloseRace|TestClosedPipeRace|TestTypeRace|TestFdRace|TestFdReadRace|TestFileCloseRace",
1580 pkgs: []string{"flag", "net", "os", "os/exec", "encoding/gob"},
1581 })
1582
1583
1584
1585
1586
1587 if t.cgoEnabled {
1588
1589
1590
1591
1592
1593 }
1594 if t.extLink() {
1595
1596 t.registerTest(hdr,
1597 &goTest{
1598 variant: "race-external",
1599 race: true,
1600 ldflags: "-linkmode=external",
1601 runTests: "TestParse|TestEcho|TestStdinCloseRace",
1602 pkgs: []string{"flag", "os/exec"},
1603 })
1604 }
1605 }
1606
1607
1608 var cgoPackages = []string{
1609 "net",
1610 "os/user",
1611 }
1612
1613 var funcBenchmark = []byte("\nfunc Benchmark")
1614
1615
1616
1617
1618
1619
1620
1621
1622 func (t *tester) packageHasBenchmarks(pkg string) bool {
1623 pkgDir := filepath.Join(goroot, "src", pkg)
1624 d, err := os.Open(pkgDir)
1625 if err != nil {
1626 return true
1627 }
1628 defer d.Close()
1629 names, err := d.Readdirnames(-1)
1630 if err != nil {
1631 return true
1632 }
1633 for _, name := range names {
1634 if !strings.HasSuffix(name, "_test.go") {
1635 continue
1636 }
1637 slurp, err := os.ReadFile(filepath.Join(pkgDir, name))
1638 if err != nil {
1639 return true
1640 }
1641 if bytes.Contains(slurp, funcBenchmark) {
1642 return true
1643 }
1644 }
1645 return false
1646 }
1647
1648
1649
1650 func (t *tester) makeGOROOTUnwritable() (undo func()) {
1651 dir := os.Getenv("GOROOT")
1652 if dir == "" {
1653 panic("GOROOT not set")
1654 }
1655
1656 type pathMode struct {
1657 path string
1658 mode os.FileMode
1659 }
1660 var dirs []pathMode
1661
1662 undo = func() {
1663 for i := range dirs {
1664 os.Chmod(dirs[i].path, dirs[i].mode)
1665 }
1666 }
1667
1668 filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
1669 if suffix := strings.TrimPrefix(path, dir+string(filepath.Separator)); suffix != "" {
1670 if suffix == ".git" {
1671
1672
1673
1674 return filepath.SkipDir
1675 }
1676 }
1677 if err != nil {
1678 return nil
1679 }
1680
1681 info, err := d.Info()
1682 if err != nil {
1683 return nil
1684 }
1685
1686 mode := info.Mode()
1687 if mode&0222 != 0 && (mode.IsDir() || mode.IsRegular()) {
1688 dirs = append(dirs, pathMode{path, mode})
1689 }
1690 return nil
1691 })
1692
1693
1694 for i := len(dirs) - 1; i >= 0; i-- {
1695 err := os.Chmod(dirs[i].path, dirs[i].mode&^0222)
1696 if err != nil {
1697 dirs = dirs[i:]
1698 undo()
1699 fatalf("failed to make GOROOT read-only: %v", err)
1700 }
1701 }
1702
1703 return undo
1704 }
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714 func raceDetectorSupported(goos, goarch string) bool {
1715 switch goos {
1716 case "linux":
1717 return goarch == "amd64" || goarch == "arm64" || goarch == "loong64" || goarch == "ppc64le" || goarch == "riscv64" || goarch == "s390x"
1718 case "darwin":
1719 return goarch == "amd64" || goarch == "arm64"
1720 case "freebsd", "netbsd", "windows":
1721 return goarch == "amd64"
1722 default:
1723 return false
1724 }
1725 }
1726
1727
1728
1729
1730 func buildModeSupported(compiler, buildmode, goos, goarch string) bool {
1731 if compiler == "gccgo" {
1732 return true
1733 }
1734
1735 platform := goos + "/" + goarch
1736
1737 switch buildmode {
1738 case "archive":
1739 return true
1740
1741 case "c-archive":
1742 switch goos {
1743 case "aix", "darwin", "ios", "windows":
1744 return true
1745 case "linux":
1746 switch goarch {
1747 case "386", "amd64", "arm", "armbe", "arm64", "arm64be", "loong64", "ppc64le", "riscv64", "s390x":
1748
1749
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/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/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/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/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