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