diff options
author | Anthony Martin <ality@pbrane.org> | 2013-08-13 12:25:41 -0400 |
---|---|---|
committer | Anthony Martin <ality@pbrane.org> | 2013-08-13 12:25:41 -0400 |
commit | 037bc7f20827578de55a209f28398e0d710315dc (patch) | |
tree | 3881430de896b2d886307813807e0c4f09d4fb26 /test/run.go | |
parent | efc4ea55773e70ec0d4a742500b302a17c282e7f (diff) | |
download | go-037bc7f20827578de55a209f28398e0d710315dc.tar.gz |
test/run: process build tags like go/build
R=bradfitz, dave, rsc, r
CC=golang-dev
https://codereview.appspot.com/10001045
Committer: Russ Cox <rsc@golang.org>
Diffstat (limited to 'test/run.go')
-rw-r--r-- | test/run.go | 87 |
1 files changed, 69 insertions, 18 deletions
diff --git a/test/run.go b/test/run.go index 5e167d6b0..353553240 100644 --- a/test/run.go +++ b/test/run.go @@ -27,6 +27,7 @@ import ( "sort" "strconv" "strings" + "unicode" ) var ( @@ -299,14 +300,17 @@ func goDirPackages(longdir string) ([][]string, error) { return pkgs, nil } +type context struct { + GOOS string + GOARCH string +} + // shouldTest looks for build tags in a source file and returns // whether the file should be used according to the tags. func shouldTest(src string, goos, goarch string) (ok bool, whyNot string) { if idx := strings.Index(src, "\npackage"); idx >= 0 { src = src[:idx] } - notgoos := "!" + goos - notgoarch := "!" + goarch for _, line := range strings.Split(src, "\n") { line = strings.TrimSpace(line) if strings.HasPrefix(line, "//") { @@ -318,29 +322,59 @@ func shouldTest(src string, goos, goarch string) (ok bool, whyNot string) { if len(line) == 0 || line[0] != '+' { continue } + ctxt := &context{ + GOOS: goos, + GOARCH: goarch, + } words := strings.Fields(line) if words[0] == "+build" { - for _, word := range words { - switch word { - case goos, goarch: - return true, "" - case notgoos, notgoarch: - continue - default: - if word[0] == '!' { - // NOT something-else - return true, "" - } + ok := false + for _, word := range words[1:] { + if ctxt.match(word) { + ok = true + break } } - // no matching tag found. - return false, line + if !ok { + // no matching tag found. + return false, line + } } } - // no build tags. + // no build tags return true, "" } +func (ctxt *context) match(name string) bool { + if name == "" { + return false + } + if i := strings.Index(name, ","); i >= 0 { + // comma-separated list + return ctxt.match(name[:i]) && ctxt.match(name[i+1:]) + } + if strings.HasPrefix(name, "!!") { // bad syntax, reject always + return false + } + if strings.HasPrefix(name, "!") { // negation + return len(name) > 1 && !ctxt.match(name[1:]) + } + + // Tags must be letters, digits, underscores or dots. + // Unlike in Go identifiers, all digits are fine (e.g., "386"). + for _, c := range name { + if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { + return false + } + } + + if name == ctxt.GOOS || name == ctxt.GOARCH { + return true + } + + return false +} + func init() { checkShouldTest() } // run runs a test. @@ -815,7 +849,7 @@ func defaultRunOutputLimit() int { return cpu } -// checkShouldTest runs canity checks on the shouldTest function. +// checkShouldTest runs sanity checks on the shouldTest function. func checkShouldTest() { assert := func(ok bool, _ string) { if !ok { @@ -823,11 +857,28 @@ func checkShouldTest() { } } assertNot := func(ok bool, _ string) { assert(!ok, "") } + + // Simple tests. assert(shouldTest("// +build linux", "linux", "arm")) assert(shouldTest("// +build !windows", "linux", "arm")) assertNot(shouldTest("// +build !windows", "windows", "amd64")) - assertNot(shouldTest("// +build arm 386", "linux", "amd64")) + + // A file with no build tags will always be tested. assert(shouldTest("// This is a test.", "os", "arch")) + + // Build tags separated by a space are OR-ed together. + assertNot(shouldTest("// +build arm 386", "linux", "amd64")) + + // Build tags seperated by a comma are AND-ed together. + assertNot(shouldTest("// +build !windows,!plan9", "windows", "amd64")) + assertNot(shouldTest("// +build !windows,!plan9", "plan9", "386")) + + // Build tags on multiple lines are AND-ed together. + assert(shouldTest("// +build !windows\n// +build amd64", "linux", "amd64")) + assertNot(shouldTest("// +build !windows\n// +build amd64", "windows", "amd64")) + + // Test that (!a OR !b) matches anything. + assert(shouldTest("// +build !windows !plan9", "windows", "amd64")) } // envForDir returns a copy of the environment |