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