summaryrefslogtreecommitdiff
path: root/test/run.go
diff options
context:
space:
mode:
authorAnthony Martin <ality@pbrane.org>2013-08-13 12:25:41 -0400
committerAnthony Martin <ality@pbrane.org>2013-08-13 12:25:41 -0400
commit037bc7f20827578de55a209f28398e0d710315dc (patch)
tree3881430de896b2d886307813807e0c4f09d4fb26 /test/run.go
parentefc4ea55773e70ec0d4a742500b302a17c282e7f (diff)
downloadgo-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.go87
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