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