]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/script: new hook for adding in toolchain script conditions
authorThan McIntosh <thanm@google.com>
Mon, 29 Jul 2024 17:40:10 +0000 (17:40 +0000)
committerThan McIntosh <thanm@google.com>
Wed, 31 Jul 2024 13:21:14 +0000 (13:21 +0000)
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>
src/cmd/compile/testdata/script/script_test_basics.txt
src/cmd/go/script_test.go
src/cmd/go/scriptconds_test.go
src/cmd/internal/script/scripttest/conditions.go [new file with mode: 0644]
src/cmd/internal/script/scripttest/run.go

index ecc28951a1e58dde629dfda46a2efa47b4dd3036..7fe99dbbc2f042aa514fdecb9443114fbc307c13 100644 (file)
@@ -4,6 +4,7 @@
 go build
 [!cgo] skip
 cc -c testdata/mumble.c
+[GOEXPERIMENT:fieldtrack] help exec
 
 -- go.mod --
 module main
index 36605bb66c91fc7403cfeabc6bd28a5daf81c05d..09232100f53b74e54c84ac7c4e0d00423e912acc 100644 (file)
@@ -89,7 +89,7 @@ func TestScript(t *testing.T) {
                t.Fatal(err)
        }
        engine := &script.Engine{
-               Conds: scriptConditions(),
+               Conds: scriptConditions(t),
                Cmds:  scriptCommands(quitSignal(), gracePeriod),
                Quiet: !testing.Verbose(),
        }
index b4f139a983c1ae0107dd8c42283f3b37afc6b653..262214f6a96c76e7bfd174656bf35e4d74f3efca 100644 (file)
@@ -10,21 +10,21 @@ import (
        "cmd/internal/script/scripttest"
        "errors"
        "fmt"
-       "internal/buildcfg"
-       "internal/platform"
        "internal/testenv"
        "os"
        "os/exec"
        "path/filepath"
        "runtime"
        "runtime/debug"
-       "strings"
        "sync"
+       "testing"
 )
 
-func scriptConditions() map[string]script.Cond {
+func scriptConditions(t *testing.T) map[string]script.Cond {
        conds := scripttest.DefaultConds()
 
+       scripttest.AddToolChainScriptConditions(t, conds, goHostOS, goHostArch)
+
        add := func(name string, cond script.Cond) {
                if _, ok := conds[name]; ok {
                        panic(fmt.Sprintf("condition %q is already registered", name))
@@ -37,26 +37,10 @@ func scriptConditions() map[string]script.Cond {
        }
 
        add("abscc", script.Condition("default $CC path is absolute and exists", defaultCCIsAbsolute))
-       add("asan", sysCondition("-asan", platform.ASanSupported, true))
-       add("buildmode", script.PrefixCondition("go supports -buildmode=<suffix>", hasBuildmode))
        add("case-sensitive", script.OnceCondition("$WORK filesystem is case-sensitive", isCaseSensitive))
        add("cc", script.PrefixCondition("go env CC = <suffix> (ignoring the go/env file)", ccIs))
-       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))
-       add("fuzz-instrumented", sysCondition("-fuzz with instrumentation", platform.FuzzInstrumented, false))
        add("git", lazyBool("the 'git' executable exists and provides the standard CLI", hasWorkingGit))
-       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))
-       add("mustlinkext", script.Condition("platform always requires external linking", mustLinkExt))
        add("net", script.PrefixCondition("can connect to external network host <suffix>", hasNet))
-       add("pielinkext", script.Condition("platform requires external linking for PIE", pieLinkExt))
-       add("race", sysCondition("-race", platform.RaceDetectorSupported, true))
-       add("symlink", lazyBool("testenv.HasSymlink()", testenv.HasSymlink))
        add("trimpath", script.OnceCondition("test binary was built with -trimpath", isTrimpath))
 
        return conds
@@ -84,23 +68,6 @@ func ccIs(s *script.State, want string) (bool, error) {
        return cfg.DefaultCC(GOOS, GOARCH) == want, nil
 }
 
-func sysCondition(flag string, f func(goos, goarch string) bool, needsCgo bool) 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
-}
-
 var scriptNetEnabled sync.Map // testing.TB → already enabled
 
 func hasNet(s *script.State, host string) (bool, error) {
@@ -137,35 +104,6 @@ func hasNet(s *script.State, host string) (bool, error) {
        return true, 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)
-}
-
 func isCaseSensitive() (bool, error) {
        tmpdir, err := os.MkdirTemp(testTmpDir, "case-sensitive")
        if err != nil {
@@ -213,21 +151,3 @@ func hasWorkingGit() bool {
        _, err := exec.LookPath("git")
        return err == 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
-}
diff --git a/src/cmd/internal/script/scripttest/conditions.go b/src/cmd/internal/script/scripttest/conditions.go
new file mode 100644 (file)
index 0000000..66dbfc2
--- /dev/null
@@ -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)
+}
index d2f3ed8ca9f3f6913b48a8e34294d1048570e889..29eb6f88f243a043366ee7dc9083417b2f71a078 100644 (file)
@@ -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()