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