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