aboutsummaryrefslogtreecommitdiff
path: root/test/run.go
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-06-11 09:54:40 -0700
committerMatthew Dempsky <mdempsky@google.com>2021-06-12 14:36:25 +0000
commitdb7c868307c87c5e9338e1cb0b5738eb96a929ad (patch)
tree81da1a9d7ecf69fa79c907d7c6c5db754e1f7a57 /test/run.go
parent0132b91127c3cf6e19e0e1db014a04219427171e (diff)
downloadgo-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.go68
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
+}