diff options
| author | Brad Fitzpatrick <bradfitz@golang.org> | 2011-06-01 15:26:53 -0700 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@golang.org> | 2011-06-01 15:26:53 -0700 |
| commit | f259f6ba0adfa0b98e74b27dbe6013d012a037eb (patch) | |
| tree | f180aad60f74af96b5437c798123c83fab63da8a /src/pkg/exec/exec_test.go | |
| parent | 2132a7f575cba670eeffde495c0bb2df120c2c5b (diff) | |
| download | go-f259f6ba0adfa0b98e74b27dbe6013d012a037eb.tar.xz | |
exec: new API, replace Run with Command
This removes exec.Run and replaces exec.Cmd with a
new implementation. The new exec.Cmd represents
both a currently-running command and also a command
being prepared. It has a good zero value.
You can Start + Wait on a Cmd, or simply Run it.
Start (and Run) deal with copying stdout, stdin,
and stderr between the Cmd's io.Readers and
io.Writers.
There are convenience methods to capture a command's
stdout and/or stderr.
R=r, n13m3y3r, rsc, gustavo, alex.brainman, dsymonds, r, adg, duzy.chan, mike.rosset, kevlar
CC=golang-dev
https://golang.org/cl/4552052
Diffstat (limited to 'src/pkg/exec/exec_test.go')
| -rw-r--r-- | src/pkg/exec/exec_test.go | 224 |
1 files changed, 100 insertions, 124 deletions
diff --git a/src/pkg/exec/exec_test.go b/src/pkg/exec/exec_test.go index 362b41c013..041d527e01 100644 --- a/src/pkg/exec/exec_test.go +++ b/src/pkg/exec/exec_test.go @@ -5,163 +5,139 @@ package exec import ( + "fmt" "io" - "io/ioutil" "testing" "os" + "strconv" + "strings" ) -func run(argv []string, stdin, stdout, stderr int) (p *Cmd, err os.Error) { - exe, err := LookPath(argv[0]) - if err != nil { - return nil, err - } - return Run(exe, argv, nil, "", stdin, stdout, stderr) +func helperCommand(s ...string) *Cmd { + cs := []string{"-test.run=exec.TestHelperProcess", "--"} + cs = append(cs, s...) + cmd := Command(os.Args[0], cs...) + cmd.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...) + return cmd } -func TestRunCat(t *testing.T) { - cmd, err := run([]string{"cat"}, Pipe, Pipe, DevNull) - if err != nil { - t.Fatal("run:", err) - } - io.WriteString(cmd.Stdin, "hello, world\n") - cmd.Stdin.Close() - buf, err := ioutil.ReadAll(cmd.Stdout) +func TestEcho(t *testing.T) { + bs, err := helperCommand("echo", "foo bar", "baz").Output() if err != nil { - t.Fatal("read:", err) + t.Errorf("echo: %v", err) } - if string(buf) != "hello, world\n" { - t.Fatalf("read: got %q", buf) - } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) + if g, e := string(bs), "foo bar baz\n"; g != e { + t.Errorf("echo: want %q, got %q", e, g) } } -func TestRunEcho(t *testing.T) { - cmd, err := run([]string{"bash", "-c", "echo hello world"}, - DevNull, Pipe, DevNull) - if err != nil { - t.Fatal("run:", err) - } - buf, err := ioutil.ReadAll(cmd.Stdout) +func TestCatStdin(t *testing.T) { + // Cat, testing stdin and stdout. + input := "Input string\nLine 2" + p := helperCommand("cat") + p.Stdin = strings.NewReader(input) + bs, err := p.Output() if err != nil { - t.Fatal("read:", err) - } - if string(buf) != "hello world\n" { - t.Fatalf("read: got %q", buf) + t.Errorf("cat: %v", err) } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) + s := string(bs) + if s != input { + t.Errorf("cat: want %q, got %q", input, s) } } -func TestStderr(t *testing.T) { - cmd, err := run([]string{"bash", "-c", "echo hello world 1>&2"}, - DevNull, DevNull, Pipe) - if err != nil { - t.Fatal("run:", err) +func TestCatGoodAndBadFile(t *testing.T) { + // Testing combined output and error values. + bs, err := helperCommand("cat", "/bogus/file.foo", "exec_test.go").CombinedOutput() + if _, ok := err.(*os.Waitmsg); !ok { + t.Errorf("expected Waitmsg from cat combined; got %T: %v", err, err) } - buf, err := ioutil.ReadAll(cmd.Stderr) - if err != nil { - t.Fatal("read:", err) + s := string(bs) + sp := strings.Split(s, "\n", 2) + if len(sp) != 2 { + t.Fatalf("expected two lines from cat; got %q", s) } - if string(buf) != "hello world\n" { - t.Fatalf("read: got %q", buf) + errLine, body := sp[0], sp[1] + if !strings.HasPrefix(errLine, "Error: open /bogus/file.foo") { + t.Errorf("expected stderr to complain about file; got %q", errLine) } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) + if !strings.Contains(body, "func TestHelperProcess(t *testing.T)") { + t.Errorf("expected test code; got %q (len %d)", body, len(body)) } } -func TestMergeWithStdout(t *testing.T) { - cmd, err := run([]string{"bash", "-c", "echo hello world 1>&2"}, - DevNull, Pipe, MergeWithStdout) - if err != nil { - t.Fatal("run:", err) - } - buf, err := ioutil.ReadAll(cmd.Stdout) - if err != nil { - t.Fatal("read:", err) - } - if string(buf) != "hello world\n" { - t.Fatalf("read: got %q", buf) - } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) + +func TestNoExistBinary(t *testing.T) { + // Can't run a non-existent binary + err := Command("/no-exist-binary").Run() + if err == nil { + t.Error("expected error from /no-exist-binary") } } -func TestAddEnvVar(t *testing.T) { - err := os.Setenv("NEWVAR", "hello world") - if err != nil { - t.Fatal("setenv:", err) - } - cmd, err := run([]string{"bash", "-c", "echo $NEWVAR"}, - DevNull, Pipe, DevNull) - if err != nil { - t.Fatal("run:", err) - } - buf, err := ioutil.ReadAll(cmd.Stdout) - if err != nil { - t.Fatal("read:", err) - } - if string(buf) != "hello world\n" { - t.Fatalf("read: got %q", buf) - } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) +func TestExitStatus(t *testing.T) { + // Test that exit values are returned correctly + err := helperCommand("exit", "42").Run() + if werr, ok := err.(*os.Waitmsg); ok { + if s, e := werr.String(), "exit status 42"; s != e { + t.Errorf("from exit 42 got exit %q, want %q", s, e) + } + } else { + t.Fatalf("expected Waitmsg from exit 42; got %T: %v", err, err) } } -var tryargs = []string{ - `2`, - `2 `, - "2 \t", - `2" "`, - `2 ab `, - `2 "ab" `, - `2 \ `, - `2 \\ `, - `2 \" `, - `2 \`, - `2\`, - `2"`, - `2\"`, - `2 "`, - `2 \"`, - ``, - `2 ^ `, - `2 \^`, -} +// TestHelperProcess isn't a real test. It's used as a helper process +// for TestParameterRun. +func TestHelperProcess(*testing.T) { + if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { + return + } + defer os.Exit(0) -func TestArgs(t *testing.T) { - for _, a := range tryargs { - argv := []string{ - "awk", - `BEGIN{printf("%s|%s|%s",ARGV[1],ARGV[2],ARGV[3])}`, - "/dev/null", - a, - "EOF", - } - exe, err := LookPath(argv[0]) - if err != nil { - t.Fatal("run:", err) - } - cmd, err := Run(exe, argv, nil, "", DevNull, Pipe, DevNull) - if err != nil { - t.Fatal("run:", err) + args := os.Args + for len(args) > 0 { + if args[0] == "--" { + args = args[1:] + break } - buf, err := ioutil.ReadAll(cmd.Stdout) - if err != nil { - t.Fatal("read:", err) + args = args[1:] + } + if len(args) == 0 { + fmt.Fprintf(os.Stderr, "No command\n") + os.Exit(2) + } + + cmd, args := args[0], args[1:] + switch cmd { + case "echo": + iargs := []interface{}{} + for _, s := range args { + iargs = append(iargs, s) } - expect := "/dev/null|" + a + "|EOF" - if string(buf) != expect { - t.Errorf("read: got %q expect %q", buf, expect) + fmt.Println(iargs...) + case "cat": + if len(args) == 0 { + io.Copy(os.Stdout, os.Stdin) + return } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) + exit := 0 + for _, fn := range args { + f, err := os.Open(fn) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + exit = 2 + } else { + defer f.Close() + io.Copy(os.Stdout, f) + } } + os.Exit(exit) + case "exit": + n, _ := strconv.Atoi(args[0]) + os.Exit(n) + default: + fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd) + os.Exit(2) } } |
