summaryrefslogtreecommitdiff
path: root/test/run.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/run.go')
-rw-r--r--test/run.go89
1 files changed, 70 insertions, 19 deletions
diff --git a/test/run.go b/test/run.go
index 5e167d6b0..f1f1ec034 100644
--- a/test/run.go
+++ b/test/run.go
@@ -27,6 +27,7 @@ import (
"sort"
"strconv"
"strings"
+ "unicode"
)
var (
@@ -134,7 +135,7 @@ func main() {
if !*verbose && test.err == nil {
continue
}
- fmt.Printf("%-20s %-20s: %s\n", test.action, test.goFileName(), errStr)
+ fmt.Printf("# go run run.go -- %s\n%-20s %-20s: %s\n", path.Join(test.dir, test.gofile), test.action, test.goFileName(), errStr)
}
if *summary {
@@ -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