1
2
3
4
5 package scripttest
6
7 import (
8 "cmd/internal/script"
9 "fmt"
10 "internal/buildcfg"
11 "internal/platform"
12 "internal/testenv"
13 "runtime"
14 "strings"
15 "testing"
16 )
17
18
19
20
21
22
23
24 func AddToolChainScriptConditions(t *testing.T, conds map[string]script.Cond, goHostOS, goHostArch string) {
25 add := func(name string, cond script.Cond) {
26 if _, ok := conds[name]; ok {
27 t.Fatalf("condition %q is already registered", name)
28 }
29 conds[name] = cond
30 }
31
32 lazyBool := func(summary string, f func() bool) script.Cond {
33 return script.OnceCondition(summary, func() (bool, error) { return f(), nil })
34 }
35
36 add("asan", sysCondition("-asan", platform.ASanSupported, true, goHostOS, goHostArch))
37 add("buildmode", script.PrefixCondition("go supports -buildmode=<suffix>", hasBuildmode))
38 add("cgo", script.BoolCondition("host CGO_ENABLED", testenv.HasCGO()))
39 add("cgolinkext", script.Condition("platform requires external linking for cgo", cgoLinkExt))
40 add("cross", script.BoolCondition("cmd/go GOOS/GOARCH != GOHOSTOS/GOHOSTARCH", goHostOS != runtime.GOOS || goHostArch != runtime.GOARCH))
41 add("fuzz", sysCondition("-fuzz", platform.FuzzSupported, false, goHostOS, goHostArch))
42 add("fuzz-instrumented", sysCondition("-fuzz with instrumentation", platform.FuzzInstrumented, false, goHostOS, goHostArch))
43 add("GODEBUG", script.PrefixCondition("GODEBUG contains <suffix>", hasGodebug))
44 add("GOEXPERIMENT", script.PrefixCondition("GOEXPERIMENT <suffix> is enabled", hasGoexperiment))
45 add("go-builder", script.BoolCondition("GO_BUILDER_NAME is non-empty", testenv.Builder() != ""))
46 add("link", lazyBool("testenv.HasLink()", testenv.HasLink))
47 add("msan", sysCondition("-msan", platform.MSanSupported, true, goHostOS, goHostArch))
48 add("mustlinkext", script.Condition("platform always requires external linking", mustLinkExt))
49 add("pielinkext", script.Condition("platform requires external linking for PIE", pieLinkExt))
50 add("race", sysCondition("-race", platform.RaceDetectorSupported, true, goHostOS, goHostArch))
51 add("symlink", lazyBool("testenv.HasSymlink()", testenv.HasSymlink))
52 }
53
54 func sysCondition(flag string, f func(goos, goarch string) bool, needsCgo bool, goHostOS, goHostArch string) script.Cond {
55 return script.Condition(
56 "GOOS/GOARCH supports "+flag,
57 func(s *script.State) (bool, error) {
58 GOOS, _ := s.LookupEnv("GOOS")
59 GOARCH, _ := s.LookupEnv("GOARCH")
60 cross := goHostOS != GOOS || goHostArch != GOARCH
61 return (!needsCgo || (testenv.HasCGO() && !cross)) && f(GOOS, GOARCH), nil
62 })
63 }
64
65 func hasBuildmode(s *script.State, mode string) (bool, error) {
66 GOOS, _ := s.LookupEnv("GOOS")
67 GOARCH, _ := s.LookupEnv("GOARCH")
68 return platform.BuildModeSupported(runtime.Compiler, mode, GOOS, GOARCH), nil
69 }
70
71 func cgoLinkExt(s *script.State) (bool, error) {
72 GOOS, _ := s.LookupEnv("GOOS")
73 GOARCH, _ := s.LookupEnv("GOARCH")
74 return platform.MustLinkExternal(GOOS, GOARCH, true), nil
75 }
76
77 func mustLinkExt(s *script.State) (bool, error) {
78 GOOS, _ := s.LookupEnv("GOOS")
79 GOARCH, _ := s.LookupEnv("GOARCH")
80 return platform.MustLinkExternal(GOOS, GOARCH, false), nil
81 }
82
83 func pieLinkExt(s *script.State) (bool, error) {
84 GOOS, _ := s.LookupEnv("GOOS")
85 GOARCH, _ := s.LookupEnv("GOARCH")
86 return !platform.InternalLinkPIESupported(GOOS, GOARCH), nil
87 }
88
89 func hasGodebug(s *script.State, value string) (bool, error) {
90 godebug, _ := s.LookupEnv("GODEBUG")
91 for _, p := range strings.Split(godebug, ",") {
92 if strings.TrimSpace(p) == value {
93 return true, nil
94 }
95 }
96 return false, nil
97 }
98
99 func hasGoexperiment(s *script.State, value string) (bool, error) {
100 GOOS, _ := s.LookupEnv("GOOS")
101 GOARCH, _ := s.LookupEnv("GOARCH")
102 goexp, _ := s.LookupEnv("GOEXPERIMENT")
103 flags, err := buildcfg.ParseGOEXPERIMENT(GOOS, GOARCH, goexp)
104 if err != nil {
105 return false, err
106 }
107 for _, exp := range flags.All() {
108 if value == exp {
109 return true, nil
110 }
111 if strings.TrimPrefix(value, "no") == strings.TrimPrefix(exp, "no") {
112 return false, nil
113 }
114 }
115 return false, fmt.Errorf("unrecognized GOEXPERIMENT %q", value)
116 }
117
View as plain text