mirror of
https://github.com/golang/go
synced 2024-11-26 03:47:57 -07:00
test/run: process build tags like go/build
R=bradfitz, dave, rsc, r CC=golang-dev https://golang.org/cl/10001045
This commit is contained in:
parent
71c6da39ce
commit
a538558003
87
test/run.go
87
test/run.go
@ -27,6 +27,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -299,14 +300,17 @@ func goDirPackages(longdir string) ([][]string, error) {
|
|||||||
return pkgs, nil
|
return pkgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type context struct {
|
||||||
|
GOOS string
|
||||||
|
GOARCH string
|
||||||
|
}
|
||||||
|
|
||||||
// shouldTest looks for build tags in a source file and returns
|
// shouldTest looks for build tags in a source file and returns
|
||||||
// whether the file should be used according to the tags.
|
// whether the file should be used according to the tags.
|
||||||
func shouldTest(src string, goos, goarch string) (ok bool, whyNot string) {
|
func shouldTest(src string, goos, goarch string) (ok bool, whyNot string) {
|
||||||
if idx := strings.Index(src, "\npackage"); idx >= 0 {
|
if idx := strings.Index(src, "\npackage"); idx >= 0 {
|
||||||
src = src[:idx]
|
src = src[:idx]
|
||||||
}
|
}
|
||||||
notgoos := "!" + goos
|
|
||||||
notgoarch := "!" + goarch
|
|
||||||
for _, line := range strings.Split(src, "\n") {
|
for _, line := range strings.Split(src, "\n") {
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
if strings.HasPrefix(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] != '+' {
|
if len(line) == 0 || line[0] != '+' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
ctxt := &context{
|
||||||
|
GOOS: goos,
|
||||||
|
GOARCH: goarch,
|
||||||
|
}
|
||||||
words := strings.Fields(line)
|
words := strings.Fields(line)
|
||||||
if words[0] == "+build" {
|
if words[0] == "+build" {
|
||||||
for _, word := range words {
|
ok := false
|
||||||
switch word {
|
for _, word := range words[1:] {
|
||||||
case goos, goarch:
|
if ctxt.match(word) {
|
||||||
return true, ""
|
ok = true
|
||||||
case notgoos, notgoarch:
|
break
|
||||||
continue
|
|
||||||
default:
|
|
||||||
if word[0] == '!' {
|
|
||||||
// NOT something-else
|
|
||||||
return true, ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// no matching tag found.
|
if !ok {
|
||||||
return false, line
|
// no matching tag found.
|
||||||
|
return false, line
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// no build tags.
|
// no build tags
|
||||||
return true, ""
|
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() }
|
func init() { checkShouldTest() }
|
||||||
|
|
||||||
// run runs a test.
|
// run runs a test.
|
||||||
@ -815,7 +849,7 @@ func defaultRunOutputLimit() int {
|
|||||||
return cpu
|
return cpu
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkShouldTest runs canity checks on the shouldTest function.
|
// checkShouldTest runs sanity checks on the shouldTest function.
|
||||||
func checkShouldTest() {
|
func checkShouldTest() {
|
||||||
assert := func(ok bool, _ string) {
|
assert := func(ok bool, _ string) {
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -823,11 +857,28 @@ func checkShouldTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertNot := func(ok bool, _ string) { assert(!ok, "") }
|
assertNot := func(ok bool, _ string) { assert(!ok, "") }
|
||||||
|
|
||||||
|
// Simple tests.
|
||||||
assert(shouldTest("// +build linux", "linux", "arm"))
|
assert(shouldTest("// +build linux", "linux", "arm"))
|
||||||
assert(shouldTest("// +build !windows", "linux", "arm"))
|
assert(shouldTest("// +build !windows", "linux", "arm"))
|
||||||
assertNot(shouldTest("// +build !windows", "windows", "amd64"))
|
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"))
|
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
|
// envForDir returns a copy of the environment
|
||||||
|
51
test/testlib
51
test/testlib
@ -16,29 +16,50 @@ pkgs() {
|
|||||||
done | sort
|
done | sort
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_match() {
|
||||||
|
case $1 in
|
||||||
|
*,*)
|
||||||
|
#echo >&2 "match comma separated $1"
|
||||||
|
first=$(echo $1 | sed 's/,.*//')
|
||||||
|
rest=$(echo $1 | sed 's/[^,]*,//')
|
||||||
|
if _match $first && _match $rest; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
'!'*)
|
||||||
|
#echo >&2 "match negation $1"
|
||||||
|
neg=$(echo $1 | sed 's/^!//')
|
||||||
|
if _match $neg; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
$GOARCH|$GOOS)
|
||||||
|
#echo >&2 "match GOARCH or GOOS $1"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
# +build aborts execution if the supplied tags don't match,
|
# +build aborts execution if the supplied tags don't match,
|
||||||
# i.e. none of the tags (x or !x) matches GOARCH or GOOS.
|
# i.e. none of the tags (x or !x) matches GOARCH or GOOS.
|
||||||
+build() {
|
+build() {
|
||||||
if (( $# == 0 )); then
|
if (( $# == 0 )); then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
m=0
|
||||||
for tag; do
|
for tag; do
|
||||||
case $tag in
|
if _match $tag; then
|
||||||
$GOARCH|$GOOS)
|
m=1
|
||||||
#echo >&2 "match $tag in $1"
|
fi
|
||||||
return # don't exclude.
|
|
||||||
;;
|
|
||||||
'!'$GOARCH|'!'$GOOS)
|
|
||||||
;;
|
|
||||||
'!'*)
|
|
||||||
# not x where x is neither GOOS nor GOARCH.
|
|
||||||
#echo >&2 "match $tag in $1"
|
|
||||||
return # don't exclude
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
done
|
||||||
# no match.
|
if [ $m = 0 ]; then
|
||||||
exit 0
|
#echo >&2 no match
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
unset m
|
||||||
}
|
}
|
||||||
|
|
||||||
compile() {
|
compile() {
|
||||||
|
Loading…
Reference in New Issue
Block a user