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