diff options
Diffstat (limited to 'gcc/testsuite/go.test/test/run.go')
-rw-r--r-- | gcc/testsuite/go.test/test/run.go | 134 |
1 files changed, 101 insertions, 33 deletions
diff --git a/gcc/testsuite/go.test/test/run.go b/gcc/testsuite/go.test/test/run.go index 5e167d6b0cc..5c94de6400f 100644 --- a/gcc/testsuite/go.test/test/run.go +++ b/gcc/testsuite/go.test/test/run.go @@ -27,6 +27,8 @@ import ( "sort" "strconv" "strings" + "time" + "unicode" ) var ( @@ -113,28 +115,39 @@ func main() { failed := false resCount := map[string]int{} for _, test := range tests { - <-test.donec - _, isSkip := test.err.(skipError) - errStr := "pass" + <-test.donec + status := "ok " + errStr := "" + if _, isSkip := test.err.(skipError); isSkip { + status = "skip" + test.err = nil + if !skipOkay[path.Join(test.dir, test.gofile)] { + errStr = "unexpected skip for " + path.Join(test.dir, test.gofile) + ": " + errStr + status = "FAIL" + } + } if test.err != nil { + status = "FAIL" errStr = test.err.Error() - if !isSkip { - failed = true - } } - if isSkip && !skipOkay[path.Join(test.dir, test.gofile)] { - errStr = "unexpected skip for " + path.Join(test.dir, test.gofile) + ": " + errStr - isSkip = false + if status == "FAIL" { failed = true } - resCount[errStr]++ - if isSkip && !*verbose && !*showSkips { + resCount[status]++ + if status == "skip" && !*verbose && !*showSkips { + continue + } + dt := fmt.Sprintf("%.3fs", test.dt.Seconds()) + if status == "FAIL" { + fmt.Printf("# go run run.go -- %s\n%s\nFAIL\t%s\t%s\n", + path.Join(test.dir, test.gofile), + errStr, test.goFileName(), dt) continue } - if !*verbose && test.err == nil { + if !*verbose { continue } - fmt.Printf("%-20s %-20s: %s\n", test.action, test.goFileName(), errStr) + fmt.Printf("%s\t%s\t%s\n", status, test.goFileName(), dt) } if *summary { @@ -206,7 +219,8 @@ func check(err error) { type test struct { dir, gofile string donec chan bool // closed when done - + dt time.Duration + src string action string // "compile", "build", etc. @@ -299,14 +313,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,34 +335,68 @@ 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. func (t *test) run() { - defer close(t.donec) + start := time.Now() + defer func() { + t.dt = time.Since(start) + close(t.donec) + }() srcBytes, err := ioutil.ReadFile(t.goFileName()) if err != nil { @@ -815,7 +866,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 +874,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 |