Update prebuilts to go 1.5.1
Change-Id: Ic39c72590cb0561132faefbca121c3782372b9bf
diff --git a/test/run.go b/test/run.go
index e8ec2df..6e1cde9 100644
--- a/test/run.go
+++ b/test/run.go
@@ -15,7 +15,8 @@
"errors"
"flag"
"fmt"
- "go/build"
+ "hash/fnv"
+ "io"
"io/ioutil"
"log"
"os"
@@ -36,16 +37,14 @@
numParallel = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run")
summary = flag.Bool("summary", false, "show summary of results")
showSkips = flag.Bool("show_skips", false, "show skipped tests")
+ updateErrors = flag.Bool("update_errors", false, "update error messages in test file based on compiler output")
runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run")
+
+ shard = flag.Int("shard", 0, "shard index to run. Only applicable if -shards is non-zero.")
+ shards = flag.Int("shards", 0, "number of shards. If 0, all tests are run. This is used by the continuous build.")
)
var (
- // gc and ld are [568][gl].
- gc, ld string
-
- // letter is the build.ArchChar
- letter string
-
goos, goarch string
// dirs are the directories to look for *.go files in.
@@ -83,11 +82,6 @@
ratec = make(chan bool, *numParallel)
rungatec = make(chan bool, *runoutputLimit)
- var err error
- letter, err = build.ArchChar(build.Default.GOARCH)
- check(err)
- gc = letter + "g"
- ld = letter + "l"
var tests []*test
if flag.NArg() > 0 {
@@ -126,12 +120,9 @@
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"
- }
+ errStr = "unexpected skip for " + path.Join(test.dir, test.gofile) + ": " + errStr
+ status = "FAIL"
}
if test.err != nil {
status = "FAIL"
@@ -176,6 +167,15 @@
return p
}
+func shardMatch(name string) bool {
+ if *shards == 0 {
+ return true
+ }
+ h := fnv.New32()
+ io.WriteString(h, name)
+ return int(h.Sum32()%uint32(*shards)) == *shard
+}
+
func goFiles(dir string) []string {
f, err := os.Open(dir)
check(err)
@@ -183,7 +183,7 @@
check(err)
names := []string{}
for _, name := range dirnames {
- if !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") {
+ if !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") && shardMatch(name) {
names = append(names, name)
}
}
@@ -194,11 +194,11 @@
type runCmd func(...string) ([]byte, error)
func compileFile(runcmd runCmd, longname string) (out []byte, err error) {
- return runcmd("go", "tool", gc, "-e", longname)
+ return runcmd("go", "tool", "compile", "-e", longname)
}
func compileInDir(runcmd runCmd, dir string, names ...string) (out []byte, err error) {
- cmd := []string{"go", "tool", gc, "-e", "-D", ".", "-I", "."}
+ cmd := []string{"go", "tool", "compile", "-e", "-D", ".", "-I", "."}
for _, name := range names {
cmd = append(cmd, filepath.Join(dir, name))
}
@@ -206,8 +206,8 @@
}
func linkFile(runcmd runCmd, goname string) (err error) {
- pfile := strings.Replace(goname, ".go", "."+letter, -1)
- _, err = runcmd("go", "tool", ld, "-w", "-o", "a.exe", "-L", ".", pfile)
+ pfile := strings.Replace(goname, ".go", ".o", -1)
+ _, err = runcmd("go", "tool", "link", "-w", "-o", "a.exe", "-L", ".", pfile)
return
}
@@ -328,9 +328,6 @@
// 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]
- }
for _, line := range strings.Split(src, "\n") {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "//") {
@@ -415,18 +412,13 @@
t.err = skipError("starts with newline")
return
}
+
+ // Execution recipe stops at first blank line.
pos := strings.Index(t.src, "\n\n")
if pos == -1 {
t.err = errors.New("double newline not found")
return
}
- if ok, why := shouldTest(t.src, goos, goarch); !ok {
- t.action = "skip"
- if *showSkips {
- fmt.Printf("%-20s %-20s: %s\n", t.action, t.goFileName(), why)
- }
- return
- }
action := t.src[:pos]
if nl := strings.Index(action, "\n"); nl >= 0 && strings.Contains(action[:nl], "+build") {
// skip first line
@@ -436,6 +428,19 @@
action = action[2:]
}
+ // Check for build constraints only up to the actual code.
+ pkgPos := strings.Index(t.src, "\npackage")
+ if pkgPos == -1 {
+ pkgPos = pos // some files are intentionally malformed
+ }
+ if ok, why := shouldTest(t.src[:pkgPos], goos, goarch); !ok {
+ t.action = "skip"
+ if *showSkips {
+ fmt.Printf("%-20s %-20s: %s\n", t.action, t.goFileName(), why)
+ }
+ return
+ }
+
var args, flags []string
wantError := false
f := strings.Fields(action)
@@ -510,7 +515,7 @@
t.err = fmt.Errorf("unimplemented action %q", action)
case "errorcheck":
- cmdline := []string{"go", "tool", gc, "-e", "-o", "a." + letter}
+ cmdline := []string{"go", "tool", "compile", "-e", "-o", "a.o"}
cmdline = append(cmdline, flags...)
cmdline = append(cmdline, long)
out, err := runcmd(cmdline...)
@@ -525,6 +530,9 @@
return
}
}
+ if *updateErrors {
+ t.updateErrors(string(out), long)
+ }
t.err = t.errorCheck(string(out), long, t.gofile)
return
@@ -670,7 +678,7 @@
t.err = fmt.Errorf("write tempfile:%s", err)
return
}
- cmdline := []string{"go", "tool", gc, "-e", "-o", "a." + letter}
+ cmdline := []string{"go", "tool", "compile", "-e", "-o", "a.o"}
cmdline = append(cmdline, flags...)
cmdline = append(cmdline, tfile)
out, err = runcmd(cmdline...)
@@ -725,6 +733,26 @@
return string(b)
}
+func splitOutput(out string) []string {
+ // gc error messages continue onto additional lines with leading tabs.
+ // Split the output at the beginning of each line that doesn't begin with a tab.
+ // <autogenerated> lines are impossible to match so those are filtered out.
+ var res []string
+ for _, line := range strings.Split(out, "\n") {
+ if strings.HasSuffix(line, "\r") { // remove '\r', output by compiler on windows
+ line = line[:len(line)-1]
+ }
+ if strings.HasPrefix(line, "\t") {
+ res[len(res)-1] += "\n" + line
+ } else if strings.HasPrefix(line, "go tool") || strings.HasPrefix(line, "<autogenerated>") {
+ continue
+ } else if strings.TrimSpace(line) != "" {
+ res = append(res, line)
+ }
+ }
+ return res
+}
+
func (t *test) errorCheck(outStr string, fullshort ...string) (err error) {
defer func() {
if *verbose && err != nil {
@@ -732,22 +760,7 @@
}
}()
var errs []error
-
- var out []string
- // 6g error messages continue onto additional lines with leading tabs.
- // Split the output at the beginning of each line that doesn't begin with a tab.
- for _, line := range strings.Split(outStr, "\n") {
- if strings.HasSuffix(line, "\r") { // remove '\r', output by compiler on windows
- line = line[:len(line)-1]
- }
- if strings.HasPrefix(line, "\t") {
- out[len(out)-1] += "\n" + line
- } else if strings.HasPrefix(line, "go tool") {
- continue
- } else if strings.TrimSpace(line) != "" {
- out = append(out, line)
- }
- }
+ out := splitOutput(outStr)
// Cut directory name.
for i := range out {
@@ -804,7 +817,72 @@
fmt.Fprintf(&buf, "%s\n", err.Error())
}
return errors.New(buf.String())
+}
+func (t *test) updateErrors(out string, file string) {
+ // Read in source file.
+ src, err := ioutil.ReadFile(file)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return
+ }
+ lines := strings.Split(string(src), "\n")
+ // Remove old errors.
+ for i, ln := range lines {
+ pos := strings.Index(ln, " // ERROR ")
+ if pos >= 0 {
+ lines[i] = ln[:pos]
+ }
+ }
+ // Parse new errors.
+ errors := make(map[int]map[string]bool)
+ tmpRe := regexp.MustCompile(`autotmp_[0-9]+`)
+ for _, errStr := range splitOutput(out) {
+ colon1 := strings.Index(errStr, ":")
+ if colon1 < 0 || errStr[:colon1] != file {
+ continue
+ }
+ colon2 := strings.Index(errStr[colon1+1:], ":")
+ if colon2 < 0 {
+ continue
+ }
+ colon2 += colon1 + 1
+ line, err := strconv.Atoi(errStr[colon1+1 : colon2])
+ line--
+ if err != nil || line < 0 || line >= len(lines) {
+ continue
+ }
+ msg := errStr[colon2+2:]
+ for _, r := range []string{`\`, `*`, `+`, `[`, `]`, `(`, `)`} {
+ msg = strings.Replace(msg, r, `\`+r, -1)
+ }
+ msg = strings.Replace(msg, `"`, `.`, -1)
+ msg = tmpRe.ReplaceAllLiteralString(msg, `autotmp_[0-9]+`)
+ if errors[line] == nil {
+ errors[line] = make(map[string]bool)
+ }
+ errors[line][msg] = true
+ }
+ // Add new errors.
+ for line, errs := range errors {
+ var sorted []string
+ for e := range errs {
+ sorted = append(sorted, e)
+ }
+ sort.Strings(sorted)
+ lines[line] += " // ERROR"
+ for _, e := range sorted {
+ lines[line] += fmt.Sprintf(` "%s$"`, e)
+ }
+ }
+ // Write new file.
+ err = ioutil.WriteFile(file, []byte(strings.Join(lines, "\n")), 0640)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return
+ }
+ // Polish.
+ exec.Command("go", "fmt", file).CombinedOutput()
}
// matchPrefix reports whether s is of the form ^(.*/)?prefix(:|[),
@@ -888,7 +966,7 @@
var err error
re, err = regexp.Compile(rx)
if err != nil {
- log.Fatalf("%s:%d: invalid regexp in ERROR line: %v", t.goFileName(), lineNum, err)
+ log.Fatalf("%s:%d: invalid regexp \"%s\" in ERROR line: %v", t.goFileName(), lineNum, rx, err)
}
cache[rx] = re
}
@@ -906,15 +984,6 @@
return
}
-var skipOkay = map[string]bool{
- "fixedbugs/bug248.go": true, // combines errorcheckdir and rundir in the same dir.
- "fixedbugs/bug302.go": true, // tests both .$O and .a imports.
- "fixedbugs/bug345.go": true, // needs the appropriate flags in gc invocation.
- "fixedbugs/bug369.go": true, // needs compiler flags.
- "fixedbugs/bug429.go": true, // like "run" but program should fail
- "bugs/bug395.go": true,
-}
-
// defaultRunOutputLimit returns the number of runoutput tests that
// can be executed in parallel.
func defaultRunOutputLimit() int {