summaryrefslogtreecommitdiff
path: root/libgo/go/os/exec/exec_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/os/exec/exec_test.go')
-rw-r--r--libgo/go/os/exec/exec_test.go123
1 files changed, 111 insertions, 12 deletions
diff --git a/libgo/go/os/exec/exec_test.go b/libgo/go/os/exec/exec_test.go
index f9ffde602ca..f4c025e839f 100644
--- a/libgo/go/os/exec/exec_test.go
+++ b/libgo/go/os/exec/exec_test.go
@@ -11,6 +11,7 @@ import (
"bufio"
"bytes"
"fmt"
+ "internal/testenv"
"io"
"io/ioutil"
"log"
@@ -28,9 +29,8 @@ import (
)
func helperCommand(t *testing.T, s ...string) *exec.Cmd {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
- }
+ testenv.MustHaveExec(t)
+
cs := []string{"-test.run=TestHelperProcess", "--"}
cs = append(cs, s...)
cmd := exec.Command(os.Args[0], cs...)
@@ -53,6 +53,8 @@ func TestEcho(t *testing.T) {
}
func TestCommandRelativeName(t *testing.T) {
+ testenv.MustHaveExec(t)
+
// Run our own binary as a relative path
// (e.g. "_test/exec.test") our parent directory.
base := filepath.Base(os.Args[0]) // "exec.test"
@@ -250,6 +252,12 @@ func TestPipeLookPathLeak(t *testing.T) {
}
func numOpenFDS(t *testing.T) (n int, lsof []byte) {
+ if runtime.GOOS == "android" {
+ // Android's stock lsof does not obey the -p option,
+ // so extra filtering is needed. (golang.org/issue/10206)
+ return numOpenFDsAndroid(t)
+ }
+
lsof, err := exec.Command("lsof", "-b", "-n", "-p", strconv.Itoa(os.Getpid())).Output()
if err != nil {
t.Skip("skipping test; error finding or running lsof")
@@ -257,6 +265,45 @@ func numOpenFDS(t *testing.T) (n int, lsof []byte) {
return bytes.Count(lsof, []byte("\n")), lsof
}
+func numOpenFDsAndroid(t *testing.T) (n int, lsof []byte) {
+ raw, err := exec.Command("lsof").Output()
+ if err != nil {
+ t.Skip("skipping test; error finding or running lsof")
+ }
+
+ // First find the PID column index by parsing the first line, and
+ // select lines containing pid in the column.
+ pid := []byte(strconv.Itoa(os.Getpid()))
+ pidCol := -1
+
+ s := bufio.NewScanner(bytes.NewReader(raw))
+ for s.Scan() {
+ line := s.Bytes()
+ fields := bytes.Fields(line)
+ if pidCol < 0 {
+ for i, v := range fields {
+ if bytes.Equal(v, []byte("PID")) {
+ pidCol = i
+ break
+ }
+ }
+ lsof = append(lsof, line...)
+ continue
+ }
+ if bytes.Equal(fields[pidCol], pid) {
+ lsof = append(lsof, '\n')
+ lsof = append(lsof, line...)
+ }
+ }
+ if pidCol < 0 {
+ t.Fatal("error processing lsof output: unexpected header format")
+ }
+ if err := s.Err(); err != nil {
+ t.Fatalf("error processing lsof output: %v", err)
+ }
+ return bytes.Count(lsof, []byte("\n")), lsof
+}
+
var testedAlreadyLeaked = false
// basefds returns the number of expected file descriptors
@@ -275,15 +322,15 @@ func closeUnexpectedFds(t *testing.T, m string) {
}
func TestExtraFilesFDShuffle(t *testing.T) {
- t.Skip("flaky test; see http://golang.org/issue/5780")
+ t.Skip("flaky test; see https://golang.org/issue/5780")
switch runtime.GOOS {
case "darwin":
- // TODO(cnicolaou): http://golang.org/issue/2603
+ // TODO(cnicolaou): https://golang.org/issue/2603
// leads to leaked file descriptors in this test when it's
// run from a builder.
closeUnexpectedFds(t, "TestExtraFilesFDShuffle")
case "netbsd":
- // http://golang.org/issue/3955
+ // https://golang.org/issue/3955
closeUnexpectedFds(t, "TestExtraFilesFDShuffle")
case "windows":
t.Skip("no operating system support; skipping")
@@ -379,8 +426,9 @@ func TestExtraFilesFDShuffle(t *testing.T) {
}
func TestExtraFiles(t *testing.T) {
- switch runtime.GOOS {
- case "nacl", "windows":
+ testenv.MustHaveExec(t)
+
+ if runtime.GOOS == "windows" {
t.Skipf("skipping test on %q", runtime.GOOS)
}
@@ -608,21 +656,21 @@ func TestHelperProcess(*testing.T) {
// file descriptors...
case "darwin":
// TODO(bradfitz): broken? Sometimes.
- // http://golang.org/issue/2603
+ // https://golang.org/issue/2603
// Skip this additional part of the test for now.
case "netbsd":
// TODO(jsing): This currently fails on NetBSD due to
// the cloned file descriptors that result from opening
// /dev/urandom.
- // http://golang.org/issue/3955
+ // https://golang.org/issue/3955
case "plan9":
// TODO(0intro): Determine why Plan 9 is leaking
// file descriptors.
- // http://golang.org/issue/7118
+ // https://golang.org/issue/7118
case "solaris":
// TODO(aram): This fails on Solaris because libc opens
// its own files, as it sees fit. Darwin does the same,
- // see: http://golang.org/issue/2603
+ // see: https://golang.org/issue/2603
default:
// Now verify that there are no other open fds.
var files []*os.File
@@ -721,3 +769,54 @@ func TestHelperProcess(*testing.T) {
os.Exit(2)
}
}
+
+// Issue 9173: ignore stdin pipe writes if the program completes successfully.
+func TestIgnorePipeErrorOnSuccess(t *testing.T) {
+ testenv.MustHaveExec(t)
+
+ // We really only care about testing this on Unixy things.
+ if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ }
+
+ cmd := helperCommand(t, "echo", "foo")
+ var out bytes.Buffer
+ cmd.Stdin = strings.NewReader(strings.Repeat("x", 10<<20))
+ cmd.Stdout = &out
+ if err := cmd.Run(); err != nil {
+ t.Fatal(err)
+ }
+ if got, want := out.String(), "foo\n"; got != want {
+ t.Errorf("output = %q; want %q", got, want)
+ }
+}
+
+type badWriter struct{}
+
+func (w *badWriter) Write(data []byte) (int, error) {
+ return 0, io.ErrUnexpectedEOF
+}
+
+func TestClosePipeOnCopyError(t *testing.T) {
+ testenv.MustHaveExec(t)
+
+ if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+ t.Skipf("skipping test on %s - no yes command", runtime.GOOS)
+ }
+ cmd := exec.Command("yes")
+ cmd.Stdout = new(badWriter)
+ c := make(chan int, 1)
+ go func() {
+ err := cmd.Run()
+ if err == nil {
+ t.Errorf("yes completed successfully")
+ }
+ c <- 1
+ }()
+ select {
+ case <-c:
+ // ok
+ case <-time.After(5 * time.Second):
+ t.Fatalf("yes got stuck writing to bad writer")
+ }
+}