From dbd30e986b8f92e34a409403a783d8d18d203906 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 15 Dec 2021 20:54:22 +0100 Subject: [PATCH 1/4] testscript: tidy up condition logic --- testscript/testscript.go | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/testscript/testscript.go b/testscript/testscript.go index ea5f51e2..cf9a6724 100644 --- a/testscript/testscript.go +++ b/testscript/testscript.go @@ -572,32 +572,29 @@ func (ts *TestScript) applyScriptUpdates() { // condition reports whether the given condition is satisfied. func (ts *TestScript) condition(cond string) (bool, error) { - switch cond { - case "short": + switch { + case cond == "short": return testing.Short(), nil - case "net": + case cond == "net": return testenv.HasExternalNetwork(), nil - case "link": + case cond == "link": return testenv.HasLink(), nil - case "symlink": + case cond == "symlink": return testenv.HasSymlink(), nil - case runtime.GOOS, runtime.GOARCH: - return true, nil + case imports.KnownOS[cond]: + return cond == runtime.GOOS, nil + case imports.KnownArch[cond]: + return cond == runtime.GOARCH, nil + case strings.HasPrefix(cond, "exec:"): + prog := cond[len("exec:"):] + ok := execCache.Do(prog, func() interface{} { + _, err := execpath.Look(prog, ts.Getenv) + return err == nil + }).(bool) + return ok, nil + case ts.params.Condition != nil: + return ts.params.Condition(cond) default: - if imports.KnownArch[cond] || imports.KnownOS[cond] { - return false, nil - } - if strings.HasPrefix(cond, "exec:") { - prog := cond[len("exec:"):] - ok := execCache.Do(prog, func() interface{} { - _, err := execpath.Look(prog, ts.Getenv) - return err == nil - }).(bool) - return ok, nil - } - if ts.params.Condition != nil { - return ts.params.Condition(cond) - } ts.Fatalf("unknown condition %q", cond) panic("unreachable") } From edd2efc2fd7a1feecab310609a5b7cb68e2cf178 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 2 Mar 2022 00:51:55 +0100 Subject: [PATCH 2/4] testscript: add gc and gccgo conditions --- gotooltest/setup.go | 6 ------ testscript/doc.go | 2 ++ testscript/testdata/cond.txt | 6 ++++++ testscript/testscript.go | 5 +++++ 4 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 testscript/testdata/cond.txt diff --git a/gotooltest/setup.go b/gotooltest/setup.go index 84705cfa..6673580f 100644 --- a/gotooltest/setup.go +++ b/gotooltest/setup.go @@ -106,12 +106,6 @@ func Setup(p *testscript.Params) error { p.Cmds["go"] = cmdGo origCondition := p.Condition p.Condition = func(cond string) (bool, error) { - if cond == "gc" || cond == "gccgo" { - // TODO this reflects the compiler that the current - // binary was built with but not necessarily the compiler - // that will be used. - return cond == runtime.Compiler, nil - } if goVersionRegex.MatchString(cond) { for _, v := range build.Default.ReleaseTags { if cond == v { diff --git a/testscript/doc.go b/testscript/doc.go index d4fe1869..24dc703a 100644 --- a/testscript/doc.go +++ b/testscript/doc.go @@ -105,6 +105,8 @@ should only run when the condition is satisfied. The predefined conditions are: - [link] for whether the OS has hard link support - [symlink] for whether the OS has symbolic link support - [exec:prog] for whether prog is available for execution (found by exec.LookPath) + - [gc] for whether Go was built with gc + - [gccgo] for whether Go was built with gccgo A condition can be negated: [!short] means to run the rest of the line when testing.Short() is false. diff --git a/testscript/testdata/cond.txt b/testscript/testdata/cond.txt new file mode 100644 index 00000000..4c2ca21c --- /dev/null +++ b/testscript/testdata/cond.txt @@ -0,0 +1,6 @@ +[!exec:sh] skip 'sh not found in $PATH' + +# test that exactly one of gc and gccgo is set +[gc] exec sh -c 'echo gc >> go-compiler' +[gccgo] exec sh -c 'echo gccgo >> go-compiler' +grep '\A(gc|gccgo)\n\z' go-compiler \ No newline at end of file diff --git a/testscript/testscript.go b/testscript/testscript.go index cf9a6724..586c5a60 100644 --- a/testscript/testscript.go +++ b/testscript/testscript.go @@ -592,6 +592,11 @@ func (ts *TestScript) condition(cond string) (bool, error) { return err == nil }).(bool) return ok, nil + case cond == "gc" || cond == "gccgo": + // TODO this reflects the compiler that the current + // binary was built with but not necessarily the compiler + // that will be used. + return cond == runtime.Compiler, nil case ts.params.Condition != nil: return ts.params.Condition(cond) default: From 30d3000978fa167c6c3f6aa8a96f6954167da0ed Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 2 Mar 2022 01:39:29 +0100 Subject: [PATCH 3/4] gotooltest: fix Go version regular expression Trivia: the first defined Go version build constraint is go1.1. --- gotooltest/setup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gotooltest/setup.go b/gotooltest/setup.go index 6673580f..122d2464 100644 --- a/gotooltest/setup.go +++ b/gotooltest/setup.go @@ -22,7 +22,7 @@ import ( ) var ( - goVersionRegex = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`) + goVersionRegex = regexp.MustCompile(`^go([1-9][0-9]*)\.([1-9][0-9]*)$`) goEnv struct { GOROOT string From 190efae99c32c4e1e6300c0a37e03ea1cef5f015 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 2 Mar 2022 01:44:12 +0100 Subject: [PATCH 4/4] testscript: add go version conditions --- gotooltest/setup.go | 16 ---------------- testscript/doc.go | 1 + testscript/testdata/cond.txt | 7 ++++++- testscript/testscript.go | 10 ++++++++++ 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/gotooltest/setup.go b/gotooltest/setup.go index 122d2464..b1092c92 100644 --- a/gotooltest/setup.go +++ b/gotooltest/setup.go @@ -10,7 +10,6 @@ import ( "bytes" "encoding/json" "fmt" - "go/build" "os/exec" "path/filepath" "regexp" @@ -104,21 +103,6 @@ func Setup(p *testscript.Params) error { p.Cmds = make(map[string]func(ts *testscript.TestScript, neg bool, args []string)) } p.Cmds["go"] = cmdGo - origCondition := p.Condition - p.Condition = func(cond string) (bool, error) { - if goVersionRegex.MatchString(cond) { - for _, v := range build.Default.ReleaseTags { - if cond == v { - return true, nil - } - } - return false, nil - } - if origCondition == nil { - return false, fmt.Errorf("unknown condition %q", cond) - } - return origCondition(cond) - } return nil } diff --git a/testscript/doc.go b/testscript/doc.go index 24dc703a..ba91db36 100644 --- a/testscript/doc.go +++ b/testscript/doc.go @@ -107,6 +107,7 @@ should only run when the condition is satisfied. The predefined conditions are: - [exec:prog] for whether prog is available for execution (found by exec.LookPath) - [gc] for whether Go was built with gc - [gccgo] for whether Go was built with gccgo + - [go1.x] for whether the Go version is 1.x or later A condition can be negated: [!short] means to run the rest of the line when testing.Short() is false. diff --git a/testscript/testdata/cond.txt b/testscript/testdata/cond.txt index 4c2ca21c..60b62c2a 100644 --- a/testscript/testdata/cond.txt +++ b/testscript/testdata/cond.txt @@ -3,4 +3,9 @@ # test that exactly one of gc and gccgo is set [gc] exec sh -c 'echo gc >> go-compiler' [gccgo] exec sh -c 'echo gccgo >> go-compiler' -grep '\A(gc|gccgo)\n\z' go-compiler \ No newline at end of file +grep '\A(gc|gccgo)\n\z' go-compiler + +# test that go version build tags are set +[go1.1] exec sh -c 'echo go1.1 >> go-version' +[go2.1] exec sh -c 'echo go2.1 >> go-version' +grep '\Ago1\.1\n\z' go-version \ No newline at end of file diff --git a/testscript/testscript.go b/testscript/testscript.go index 586c5a60..af752e3f 100644 --- a/testscript/testscript.go +++ b/testscript/testscript.go @@ -12,6 +12,7 @@ import ( "context" "flag" "fmt" + "go/build" "io/ioutil" "os" "os/exec" @@ -30,6 +31,8 @@ import ( "github.com/rogpeppe/go-internal/txtar" ) +var goVersionRegex = regexp.MustCompile(`^go([1-9][0-9]*)\.([1-9][0-9]*)$`) + var execCache par.Cache // If -testwork is specified, the test prints the name of the temp directory @@ -597,6 +600,13 @@ func (ts *TestScript) condition(cond string) (bool, error) { // binary was built with but not necessarily the compiler // that will be used. return cond == runtime.Compiler, nil + case goVersionRegex.MatchString(cond): + for _, v := range build.Default.ReleaseTags { + if cond == v { + return true, nil + } + } + return false, nil case ts.params.Condition != nil: return ts.params.Condition(cond) default: