diff options
| author | Than McIntosh <thanm@google.com> | 2024-07-29 17:40:10 +0000 |
|---|---|---|
| committer | Than McIntosh <thanm@google.com> | 2024-07-31 13:21:14 +0000 |
| commit | b60f88d81022e4172e44aef2f0bdade87ed6916d (patch) | |
| tree | a37a6115cb048aea979ad51eb12f03cf6d9116fb /src/cmd/internal/script/scripttest | |
| parent | 86bec1ec198f2720c83bd232a72b800b4ea5a9f6 (diff) | |
| download | go-b60f88d81022e4172e44aef2f0bdade87ed6916d.tar.xz | |
cmd/internal/script: new hook for adding in toolchain script conditions
Introduce a new function AddToolChainScriptConditions that augments a
default "script.Cond" set with a collection of useful conditions,
including godebug/goexperiment, cgo, race support, buildmode, asan,
msan, and so on. Having these conditions available makes it easier to
write script tests that deal with specific build-flavor corner cases.
The functions backing the new conditions are helper functions migrated
over from the Go command's script test setup.
Updates #68606.
Change-Id: I14def1115b54dc47529c983abcd2c5ea9326b9de
Reviewed-on: https://go-review.googlesource.com/c/go/+/601715
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/cmd/internal/script/scripttest')
| -rw-r--r-- | src/cmd/internal/script/scripttest/conditions.go | 116 | ||||
| -rw-r--r-- | src/cmd/internal/script/scripttest/run.go | 12 |
2 files changed, 120 insertions, 8 deletions
diff --git a/src/cmd/internal/script/scripttest/conditions.go b/src/cmd/internal/script/scripttest/conditions.go new file mode 100644 index 0000000000..66dbfc2ac6 --- /dev/null +++ b/src/cmd/internal/script/scripttest/conditions.go @@ -0,0 +1,116 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package scripttest + +import ( + "cmd/internal/script" + "fmt" + "internal/buildcfg" + "internal/platform" + "internal/testenv" + "runtime" + "strings" + "testing" +) + +// AddToolChainConditions accepts a script.Cond map and adds into it a +// set of commonly used conditions for doing toolchains testing, +// including whether the platform supports cgo, a buildmode condition, +// support for GOEXPERIMENT testing, etc. Callers must also pass in +// current GOHOSTOOS/GOHOSTARCH settings, since some of the conditions +// introduced can be influenced by them. +func AddToolChainScriptConditions(t *testing.T, conds map[string]script.Cond, goHostOS, goHostArch string) { + add := func(name string, cond script.Cond) { + if _, ok := conds[name]; ok { + t.Fatalf("condition %q is already registered", name) + } + conds[name] = cond + } + + lazyBool := func(summary string, f func() bool) script.Cond { + return script.OnceCondition(summary, func() (bool, error) { return f(), nil }) + } + + add("asan", sysCondition("-asan", platform.ASanSupported, true, goHostOS, goHostArch)) + add("buildmode", script.PrefixCondition("go supports -buildmode=<suffix>", hasBuildmode)) + add("cgo", script.BoolCondition("host CGO_ENABLED", testenv.HasCGO())) + add("cgolinkext", script.Condition("platform requires external linking for cgo", cgoLinkExt)) + add("cross", script.BoolCondition("cmd/go GOOS/GOARCH != GOHOSTOS/GOHOSTARCH", goHostOS != runtime.GOOS || goHostArch != runtime.GOARCH)) + add("fuzz", sysCondition("-fuzz", platform.FuzzSupported, false, goHostOS, goHostArch)) + add("fuzz-instrumented", sysCondition("-fuzz with instrumentation", platform.FuzzInstrumented, false, goHostOS, goHostArch)) + add("GODEBUG", script.PrefixCondition("GODEBUG contains <suffix>", hasGodebug)) + add("GOEXPERIMENT", script.PrefixCondition("GOEXPERIMENT <suffix> is enabled", hasGoexperiment)) + add("go-builder", script.BoolCondition("GO_BUILDER_NAME is non-empty", testenv.Builder() != "")) + add("link", lazyBool("testenv.HasLink()", testenv.HasLink)) + add("msan", sysCondition("-msan", platform.MSanSupported, true, goHostOS, goHostArch)) + add("mustlinkext", script.Condition("platform always requires external linking", mustLinkExt)) + add("pielinkext", script.Condition("platform requires external linking for PIE", pieLinkExt)) + add("race", sysCondition("-race", platform.RaceDetectorSupported, true, goHostOS, goHostArch)) + add("symlink", lazyBool("testenv.HasSymlink()", testenv.HasSymlink)) +} + +func sysCondition(flag string, f func(goos, goarch string) bool, needsCgo bool, goHostOS, goHostArch string) script.Cond { + return script.Condition( + "GOOS/GOARCH supports "+flag, + func(s *script.State) (bool, error) { + GOOS, _ := s.LookupEnv("GOOS") + GOARCH, _ := s.LookupEnv("GOARCH") + cross := goHostOS != GOOS || goHostArch != GOARCH + return (!needsCgo || (testenv.HasCGO() && !cross)) && f(GOOS, GOARCH), nil + }) +} + +func hasBuildmode(s *script.State, mode string) (bool, error) { + GOOS, _ := s.LookupEnv("GOOS") + GOARCH, _ := s.LookupEnv("GOARCH") + return platform.BuildModeSupported(runtime.Compiler, mode, GOOS, GOARCH), nil +} + +func cgoLinkExt(s *script.State) (bool, error) { + GOOS, _ := s.LookupEnv("GOOS") + GOARCH, _ := s.LookupEnv("GOARCH") + return platform.MustLinkExternal(GOOS, GOARCH, true), nil +} + +func mustLinkExt(s *script.State) (bool, error) { + GOOS, _ := s.LookupEnv("GOOS") + GOARCH, _ := s.LookupEnv("GOARCH") + return platform.MustLinkExternal(GOOS, GOARCH, false), nil +} + +func pieLinkExt(s *script.State) (bool, error) { + GOOS, _ := s.LookupEnv("GOOS") + GOARCH, _ := s.LookupEnv("GOARCH") + return !platform.InternalLinkPIESupported(GOOS, GOARCH), nil +} + +func hasGodebug(s *script.State, value string) (bool, error) { + godebug, _ := s.LookupEnv("GODEBUG") + for _, p := range strings.Split(godebug, ",") { + if strings.TrimSpace(p) == value { + return true, nil + } + } + return false, nil +} + +func hasGoexperiment(s *script.State, value string) (bool, error) { + GOOS, _ := s.LookupEnv("GOOS") + GOARCH, _ := s.LookupEnv("GOARCH") + goexp, _ := s.LookupEnv("GOEXPERIMENT") + flags, err := buildcfg.ParseGOEXPERIMENT(GOOS, GOARCH, goexp) + if err != nil { + return false, err + } + for _, exp := range flags.All() { + if value == exp { + return true, nil + } + if strings.TrimPrefix(value, "no") == strings.TrimPrefix(exp, "no") { + return false, nil + } + } + return false, fmt.Errorf("unrecognized GOEXPERIMENT %q", value) +} diff --git a/src/cmd/internal/script/scripttest/run.go b/src/cmd/internal/script/scripttest/run.go index d2f3ed8ca9..29eb6f88f2 100644 --- a/src/cmd/internal/script/scripttest/run.go +++ b/src/cmd/internal/script/scripttest/run.go @@ -71,13 +71,6 @@ func RunToolScriptTest(t *testing.T, repls []ToolReplacement, pattern string) { cmds[name] = cmd } - addcond := func(name string, cond script.Cond) { - if _, ok := conds[name]; ok { - panic(fmt.Sprintf("condition %q is already registered", name)) - } - conds[name] = cond - } - prependToPath := func(env []string, dir string) { found := false for k := range env { @@ -135,7 +128,10 @@ func RunToolScriptTest(t *testing.T, repls []ToolReplacement, pattern string) { cccmd := script.Program(goEnv("CC"), interrupt, gracePeriod) addcmd("go", gocmd) addcmd("cc", cccmd) - addcond("cgo", script.BoolCondition("host CGO_ENABLED", testenv.HasCGO())) + + // Add various helpful conditions related to builds and toolchain use. + goHostOS, goHostArch := goEnv("GOHOSTOS"), goEnv("GOHOSTARCH") + AddToolChainScriptConditions(t, conds, goHostOS, goHostArch) // Environment setup. env := os.Environ() |
