diff options
author | Matthew Dempsky <mdempsky@google.com> | 2021-06-11 09:54:40 -0700 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2021-06-12 14:36:25 +0000 |
commit | db7c868307c87c5e9338e1cb0b5738eb96a929ad (patch) | |
tree | 81da1a9d7ecf69fa79c907d7c6c5db754e1f7a57 /test/run.go | |
parent | 0132b91127c3cf6e19e0e1db014a04219427171e (diff) | |
download | go-db7c868307c87c5e9338e1cb0b5738eb96a929ad.tar.gz go-db7c868307c87c5e9338e1cb0b5738eb96a929ad.zip |
[dev.typeparams] test: add string quoting support to test/run.go
This CL copies go/build's splitQuoted function (used for parsing #cgo
directives within `import "C"` preambles) to parse test recipe
commands. In particular, this now allows writing "build" and "run"
tests that use -gcflags to pass multiple compiler flags.
Change-Id: I0d18a9c13a4ce24bbdfa1da8662c0498c93a6762
Reviewed-on: https://go-review.googlesource.com/c/go/+/327275
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Diffstat (limited to 'test/run.go')
-rw-r--r-- | test/run.go | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/test/run.go b/test/run.go index ef1e9de150..ca6a0f5c29 100644 --- a/test/run.go +++ b/test/run.go @@ -573,7 +573,11 @@ func (t *test) run() { singlefilepkgs := false setpkgpaths := false localImports := true - f := strings.Fields(action) + f, err := splitQuoted(action) + if err != nil { + t.err = fmt.Errorf("invalid test recipe: %v", err) + return + } if len(f) > 0 { action = f[0] args = f[1:] @@ -2116,3 +2120,65 @@ var excludedFiles = map[string]bool{ "fixedbugs/issue7921.go": true, "inline.go": true, } + +// splitQuoted splits the string s around each instance of one or more consecutive +// white space characters while taking into account quotes and escaping, and +// returns an array of substrings of s or an empty list if s contains only white space. +// Single quotes and double quotes are recognized to prevent splitting within the +// quoted region, and are removed from the resulting substrings. If a quote in s +// isn't closed err will be set and r will have the unclosed argument as the +// last element. The backslash is used for escaping. +// +// For example, the following string: +// +// a b:"c d" 'e''f' "g\"" +// +// Would be parsed as: +// +// []string{"a", "b:c d", "ef", `g"`} +// +// [copied from src/go/build/build.go] +func splitQuoted(s string) (r []string, err error) { + var args []string + arg := make([]rune, len(s)) + escaped := false + quoted := false + quote := '\x00' + i := 0 + for _, rune := range s { + switch { + case escaped: + escaped = false + case rune == '\\': + escaped = true + continue + case quote != '\x00': + if rune == quote { + quote = '\x00' + continue + } + case rune == '"' || rune == '\'': + quoted = true + quote = rune + continue + case unicode.IsSpace(rune): + if quoted || i > 0 { + quoted = false + args = append(args, string(arg[:i])) + i = 0 + } + continue + } + arg[i] = rune + i++ + } + if quoted || i > 0 { + args = append(args, string(arg[:i])) + } + if quote != 0 { + err = errors.New("unclosed quote") + } else if escaped { + err = errors.New("unfinished escaping") + } + return args, err +} |