| test: add -target flag. |
| |
| --- test/run.go |
| +++ test/run.go |
| @@ -34,19 +34,19 @@ import ( |
| |
| var ( |
| verbose = flag.Bool("v", false, "verbose. if set, parallelism is set to 1.") |
| keep = flag.Bool("k", false, "keep. keep temporary directory.") |
| 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") |
| runSkips = flag.Bool("run_skips", false, "run skipped tests (ignore skip and build tags)") |
| - linkshared = flag.Bool("linkshared", false, "") |
| 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") |
| + target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries") |
| |
| 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 ( |
| goos, goarch string |
| |
| @@ -189,48 +189,49 @@ func goFiles(dir string) []string { |
| } |
| sort.Strings(names) |
| return names |
| } |
| |
| type runCmd func(...string) ([]byte, error) |
| |
| func compileFile(runcmd runCmd, longname string, flags []string) (out []byte, err error) { |
| - cmd := []string{"go", "tool", "compile", "-e"} |
| + cmd := []string{findGoCmd(), "tool", "compile", "-e"} |
| cmd = append(cmd, flags...) |
| - if *linkshared { |
| - cmd = append(cmd, "-dynlink", "-installsuffix=dynlink") |
| - } |
| cmd = append(cmd, longname) |
| return runcmd(cmd...) |
| } |
| |
| func compileInDir(runcmd runCmd, dir string, flags []string, names ...string) (out []byte, err error) { |
| - cmd := []string{"go", "tool", "compile", "-e", "-D", ".", "-I", "."} |
| + cmd := []string{findGoCmd(), "tool", "compile", "-e", "-D", ".", "-I", "."} |
| cmd = append(cmd, flags...) |
| - if *linkshared { |
| - cmd = append(cmd, "-dynlink", "-installsuffix=dynlink") |
| - } |
| for _, name := range names { |
| cmd = append(cmd, filepath.Join(dir, name)) |
| } |
| return runcmd(cmd...) |
| } |
| |
| func linkFile(runcmd runCmd, goname string) (err error) { |
| pfile := strings.Replace(goname, ".go", ".o", -1) |
| - cmd := []string{"go", "tool", "link", "-w", "-o", "a.exe", "-L", "."} |
| - if *linkshared { |
| - cmd = append(cmd, "-linkshared", "-installsuffix=dynlink") |
| - } |
| - cmd = append(cmd, pfile) |
| - _, err = runcmd(cmd...) |
| + _, err = runcmd(findGoCmd(), "tool", "link", "-w", "-o", "a.exe", "-L", ".", pfile) |
| return |
| } |
| |
| +func goRun(runcmd runCmd, flags []string, goname string, args ...string) (out []byte, err error) { |
| + cmd := []string{findGoCmd(), "run", goGcflags()} |
| + if len(findExecCmd()) > 0 { |
| + cmd = append(cmd, "-exec") |
| + cmd = append(cmd, findExecCmd()...) |
| + } |
| + cmd = append(cmd, flags...) |
| + cmd = append(cmd, goname) |
| + cmd = append(cmd, args...) |
| + return runcmd(cmd...) |
| +} |
| + |
| // skipError describes why a test was skipped. |
| type skipError string |
| |
| func (s skipError) Error() string { return string(s) } |
| |
| func check(err error) { |
| if err != nil { |
| log.Fatal(err) |
| @@ -590,18 +591,17 @@ func (t *test) run() { |
| |
| long := filepath.Join(cwd, t.goFileName()) |
| switch action { |
| default: |
| t.err = fmt.Errorf("unimplemented action %q", action) |
| |
| case "errorcheck": |
| // TODO(gri) remove need for -C (disable printing of columns in error messages) |
| - cmdline := []string{"go", "tool", "compile", "-C", "-e", "-o", "a.o"} |
| - // No need to add -dynlink even if linkshared if we're just checking for errors... |
| + cmdline := []string{findGoCmd(), "tool", "compile", "-C", "-e", "-o", "a.o"} |
| cmdline = append(cmdline, flags...) |
| cmdline = append(cmdline, long) |
| out, err := runcmd(cmdline...) |
| if wantError { |
| if err == nil { |
| t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out) |
| return |
| } |
| @@ -704,17 +704,17 @@ func (t *test) run() { |
| } |
| if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() { |
| t.err = fmt.Errorf("incorrect output\n%s", out) |
| } |
| } |
| } |
| |
| case "build": |
| - _, err := runcmd("go", "build", goGcflags(), "-o", "a.exe", long) |
| + _, err := runcmd(findGoCmd(), "build", goGcflags(), "-o", "a.exe", long) |
| if err != nil { |
| t.err = err |
| } |
| |
| case "builddir": |
| // Build an executable from all the .go and .s files in a subdirectory. |
| useTmp = true |
| longdir := filepath.Join(cwd, t.goDirName()) |
| @@ -730,177 +730,132 @@ func (t *test) run() { |
| case ".go": |
| gos = append(gos, file) |
| case ".s": |
| asms = append(asms, file) |
| } |
| |
| } |
| var objs []string |
| - cmd := []string{"go", "tool", "compile", "-e", "-D", ".", "-I", ".", "-o", "go.o"} |
| + cmd := []string{findGoCmd(), "tool", "compile", "-e", "-D", ".", "-I", ".", "-o", "go.o"} |
| if len(asms) > 0 { |
| cmd = append(cmd, "-asmhdr", "go_asm.h") |
| } |
| for _, file := range gos { |
| cmd = append(cmd, filepath.Join(longdir, file.Name())) |
| } |
| _, err := runcmd(cmd...) |
| if err != nil { |
| t.err = err |
| break |
| } |
| objs = append(objs, "go.o") |
| if len(asms) > 0 { |
| - cmd = []string{"go", "tool", "asm", "-e", "-I", ".", "-o", "asm.o"} |
| + cmd = []string{findGoCmd(), "tool", "asm", "-e", "-I", ".", "-o", "asm.o"} |
| for _, file := range asms { |
| cmd = append(cmd, filepath.Join(longdir, file.Name())) |
| } |
| _, err = runcmd(cmd...) |
| if err != nil { |
| t.err = err |
| break |
| } |
| objs = append(objs, "asm.o") |
| } |
| - cmd = []string{"go", "tool", "pack", "c", "all.a"} |
| + cmd = []string{findGoCmd(), "tool", "pack", "c", "all.a"} |
| cmd = append(cmd, objs...) |
| _, err = runcmd(cmd...) |
| if err != nil { |
| t.err = err |
| break |
| } |
| - cmd = []string{"go", "tool", "link", "all.a"} |
| + cmd = []string{findGoCmd(), "tool", "link", "all.a"} |
| _, err = runcmd(cmd...) |
| if err != nil { |
| t.err = err |
| break |
| } |
| |
| case "buildrun": // build binary, then run binary, instead of go run. Useful for timeout tests where failure mode is infinite loop. |
| // TODO: not supported on NaCl |
| useTmp = true |
| - cmd := []string{"go", "build", goGcflags(), "-o", "a.exe"} |
| - if *linkshared { |
| - cmd = append(cmd, "-linkshared") |
| - } |
| + cmd := []string{findGoCmd(), "build", goGcflags(), "-o", "a.exe"} |
| longdirgofile := filepath.Join(filepath.Join(cwd, t.dir), t.gofile) |
| cmd = append(cmd, flags...) |
| cmd = append(cmd, longdirgofile) |
| out, err := runcmd(cmd...) |
| if err != nil { |
| t.err = err |
| return |
| } |
| - cmd = []string{"./a.exe"} |
| + cmd = []string{} |
| + if len(findExecCmd()) > 0 { |
| + cmd = append(cmd, findExecCmd()...) |
| + } |
| + cmd = append(cmd, "./a.exe") |
| out, err = runcmd(append(cmd, args...)...) |
| if err != nil { |
| t.err = err |
| return |
| } |
| |
| if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() { |
| t.err = fmt.Errorf("incorrect output\n%s", out) |
| } |
| |
| case "run": |
| useTmp = false |
| - var out []byte |
| - var err error |
| - if len(flags)+len(args) == 0 && goGcflags() == "" && !*linkshared { |
| - // If we're not using special go command flags, |
| - // skip all the go command machinery. |
| - // This avoids any time the go command would |
| - // spend checking whether, for example, the installed |
| - // package runtime is up to date. |
| - // Because we run lots of trivial test programs, |
| - // the time adds up. |
| - pkg := filepath.Join(t.tempDir, "pkg.a") |
| - if _, err := runcmd("go", "tool", "compile", "-o", pkg, t.goFileName()); err != nil { |
| - t.err = err |
| - return |
| - } |
| - exe := filepath.Join(t.tempDir, "test.exe") |
| - cmd := []string{"go", "tool", "link", "-s", "-w"} |
| - cmd = append(cmd, "-o", exe, pkg) |
| - if _, err := runcmd(cmd...); err != nil { |
| - t.err = err |
| - return |
| - } |
| - out, err = runcmd(append([]string{exe}, args...)...) |
| - } else { |
| - cmd := []string{"go", "run", goGcflags()} |
| - if *linkshared { |
| - cmd = append(cmd, "-linkshared") |
| - } |
| - cmd = append(cmd, flags...) |
| - cmd = append(cmd, t.goFileName()) |
| - out, err = runcmd(append(cmd, args...)...) |
| - } |
| + out, err := goRun(runcmd, flags, t.goFileName(), args...) |
| if err != nil { |
| t.err = err |
| return |
| } |
| if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() { |
| t.err = fmt.Errorf("incorrect output\n%s", out) |
| } |
| |
| case "runoutput": |
| rungatec <- true |
| defer func() { |
| <-rungatec |
| }() |
| useTmp = false |
| - cmd := []string{"go", "run", goGcflags()} |
| - if *linkshared { |
| - cmd = append(cmd, "-linkshared") |
| - } |
| - cmd = append(cmd, t.goFileName()) |
| - out, err := runcmd(append(cmd, args...)...) |
| + out, err := goRun(runcmd, nil, t.goFileName(), args...) |
| if err != nil { |
| t.err = err |
| return |
| } |
| tfile := filepath.Join(t.tempDir, "tmp__.go") |
| if err := ioutil.WriteFile(tfile, out, 0666); err != nil { |
| t.err = fmt.Errorf("write tempfile:%s", err) |
| return |
| } |
| - cmd = []string{"go", "run", goGcflags()} |
| - if *linkshared { |
| - cmd = append(cmd, "-linkshared") |
| - } |
| - cmd = append(cmd, tfile) |
| - out, err = runcmd(cmd...) |
| + out, err = goRun(runcmd, nil, tfile) |
| if err != nil { |
| t.err = err |
| return |
| } |
| if string(out) != t.expectedOutput() { |
| t.err = fmt.Errorf("incorrect output\n%s", out) |
| } |
| |
| case "errorcheckoutput": |
| useTmp = false |
| - cmd := []string{"go", "run", goGcflags()} |
| - if *linkshared { |
| - cmd = append(cmd, "-linkshared") |
| - } |
| - cmd = append(cmd, t.goFileName()) |
| - out, err := runcmd(append(cmd, args...)...) |
| + out, err := goRun(runcmd, nil, t.goFileName(), args...) |
| if err != nil { |
| t.err = err |
| return |
| } |
| tfile := filepath.Join(t.tempDir, "tmp__.go") |
| err = ioutil.WriteFile(tfile, out, 0666) |
| if err != nil { |
| t.err = fmt.Errorf("write tempfile:%s", err) |
| return |
| } |
| - cmdline := []string{"go", "tool", "compile", "-e", "-o", "a.o"} |
| + cmdline := []string{findGoCmd(), "tool", "compile", "-e", "-o", "a.o"} |
| cmdline = append(cmdline, flags...) |
| cmdline = append(cmdline, tfile) |
| out, err = runcmd(cmdline...) |
| if wantError { |
| if err == nil { |
| t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out) |
| return |
| } |
| @@ -917,26 +872,37 @@ func (t *test) run() { |
| |
| var execCmd []string |
| |
| func findExecCmd() []string { |
| if execCmd != nil { |
| return execCmd |
| } |
| execCmd = []string{} // avoid work the second time |
| + if *target != "" { |
| + execCmd = []string{"go_" + *target + "_exec"} |
| + return execCmd |
| + } |
| if goos == runtime.GOOS && goarch == runtime.GOARCH { |
| return execCmd |
| } |
| path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", goos, goarch)) |
| if err == nil { |
| execCmd = []string{path} |
| } |
| return execCmd |
| } |
| |
| +func findGoCmd() string { |
| + if *target != "" { |
| + return "go_" + *target |
| + } |
| + return "go" |
| +} |
| + |
| func (t *test) String() string { |
| return filepath.Join(t.dir, t.gofile) |
| } |
| |
| func (t *test) makeTempDir() { |
| var err error |
| t.tempDir, err = ioutil.TempDir("", "") |
| check(err) |