libgo: update to Go 1.11
[official-gcc.git] / libgo / go / os / pipe_test.go
blob59d31e5837c9d107566c085893db2442513f6694
1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Test broken pipes on Unix systems.
6 // +build !windows,!plan9,!nacl,!js
8 package os_test
10 import (
11 "bufio"
12 "bytes"
13 "fmt"
14 "internal/testenv"
15 "io"
16 "io/ioutil"
17 "os"
18 osexec "os/exec"
19 "os/signal"
20 "runtime"
21 "strconv"
22 "strings"
23 "sync"
24 "syscall"
25 "testing"
26 "time"
29 func TestEPIPE(t *testing.T) {
30 r, w, err := os.Pipe()
31 if err != nil {
32 t.Fatal(err)
34 if err := r.Close(); err != nil {
35 t.Fatal(err)
38 // Every time we write to the pipe we should get an EPIPE.
39 for i := 0; i < 20; i++ {
40 _, err = w.Write([]byte("hi"))
41 if err == nil {
42 t.Fatal("unexpected success of Write to broken pipe")
44 if pe, ok := err.(*os.PathError); ok {
45 err = pe.Err
47 if se, ok := err.(*os.SyscallError); ok {
48 err = se.Err
50 if err != syscall.EPIPE {
51 t.Errorf("iteration %d: got %v, expected EPIPE", i, err)
56 func TestStdPipe(t *testing.T) {
57 testenv.MustHaveExec(t)
58 r, w, err := os.Pipe()
59 if err != nil {
60 t.Fatal(err)
62 if err := r.Close(); err != nil {
63 t.Fatal(err)
65 // Invoke the test program to run the test and write to a closed pipe.
66 // If sig is false:
67 // writing to stdout or stderr should cause an immediate SIGPIPE;
68 // writing to descriptor 3 should fail with EPIPE and then exit 0.
69 // If sig is true:
70 // all writes should fail with EPIPE and then exit 0.
71 for _, sig := range []bool{false, true} {
72 for dest := 1; dest < 4; dest++ {
73 cmd := osexec.Command(os.Args[0], "-test.run", "TestStdPipeHelper")
74 cmd.Stdout = w
75 cmd.Stderr = w
76 cmd.ExtraFiles = []*os.File{w}
77 cmd.Env = append(os.Environ(), fmt.Sprintf("GO_TEST_STD_PIPE_HELPER=%d", dest))
78 if sig {
79 cmd.Env = append(cmd.Env, "GO_TEST_STD_PIPE_HELPER_SIGNAL=1")
81 if err := cmd.Run(); err == nil {
82 if !sig && dest < 3 {
83 t.Errorf("unexpected success of write to closed pipe %d sig %t in child", dest, sig)
85 } else if ee, ok := err.(*osexec.ExitError); !ok {
86 t.Errorf("unexpected exec error type %T: %v", err, err)
87 } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
88 t.Errorf("unexpected wait status type %T: %v", ee.Sys(), ee.Sys())
89 } else if ws.Signaled() && ws.Signal() == syscall.SIGPIPE {
90 if sig || dest > 2 {
91 t.Errorf("unexpected SIGPIPE signal for descriptor %d sig %t", dest, sig)
93 } else {
94 t.Errorf("unexpected exit status %v for descriptor %d sig %t", err, dest, sig)
100 // This is a helper for TestStdPipe. It's not a test in itself.
101 func TestStdPipeHelper(t *testing.T) {
102 if os.Getenv("GO_TEST_STD_PIPE_HELPER_SIGNAL") != "" {
103 signal.Notify(make(chan os.Signal, 1), syscall.SIGPIPE)
105 switch os.Getenv("GO_TEST_STD_PIPE_HELPER") {
106 case "1":
107 os.Stdout.Write([]byte("stdout"))
108 case "2":
109 os.Stderr.Write([]byte("stderr"))
110 case "3":
111 if _, err := os.NewFile(3, "3").Write([]byte("3")); err == nil {
112 os.Exit(3)
114 default:
115 t.Skip("skipping test helper")
117 // For stdout/stderr, we should have crashed with a broken pipe error.
118 // The caller will be looking for that exit status,
119 // so just exit normally here to cause a failure in the caller.
120 // For descriptor 3, a normal exit is expected.
121 os.Exit(0)
124 func testClosedPipeRace(t *testing.T, read bool) {
125 switch runtime.GOOS {
126 case "freebsd":
127 t.Skip("FreeBSD does not use the poller; issue 19093")
130 limit := 1
131 if !read {
132 // Get the amount we have to write to overload a pipe
133 // with no reader.
134 limit = 65537
135 if b, err := ioutil.ReadFile("/proc/sys/fs/pipe-max-size"); err == nil {
136 if i, err := strconv.Atoi(strings.TrimSpace(string(b))); err == nil {
137 limit = i + 1
140 t.Logf("using pipe write limit of %d", limit)
143 r, w, err := os.Pipe()
144 if err != nil {
145 t.Fatal(err)
147 defer r.Close()
148 defer w.Close()
150 // Close the read end of the pipe in a goroutine while we are
151 // writing to the write end, or vice-versa.
152 go func() {
153 // Give the main goroutine a chance to enter the Read or
154 // Write call. This is sloppy but the test will pass even
155 // if we close before the read/write.
156 time.Sleep(20 * time.Millisecond)
158 var err error
159 if read {
160 err = r.Close()
161 } else {
162 err = w.Close()
164 if err != nil {
165 t.Error(err)
169 b := make([]byte, limit)
170 if read {
171 _, err = r.Read(b[:])
172 } else {
173 _, err = w.Write(b[:])
175 if err == nil {
176 t.Error("I/O on closed pipe unexpectedly succeeded")
177 } else if pe, ok := err.(*os.PathError); !ok {
178 t.Errorf("I/O on closed pipe returned unexpected error type %T; expected os.PathError", pe)
179 } else if pe.Err != os.ErrClosed {
180 t.Errorf("got error %q but expected %q", pe.Err, os.ErrClosed)
181 } else {
182 t.Logf("I/O returned expected error %q", err)
186 func TestClosedPipeRaceRead(t *testing.T) {
187 testClosedPipeRace(t, true)
190 func TestClosedPipeRaceWrite(t *testing.T) {
191 testClosedPipeRace(t, false)
194 // Issue 20915: Reading on nonblocking fd should not return "waiting
195 // for unsupported file type." Currently it returns EAGAIN; it is
196 // possible that in the future it will simply wait for data.
197 func TestReadNonblockingFd(t *testing.T) {
198 if os.Getenv("GO_WANT_READ_NONBLOCKING_FD") == "1" {
199 fd := int(os.Stdin.Fd())
200 syscall.SetNonblock(fd, true)
201 defer syscall.SetNonblock(fd, false)
202 _, err := os.Stdin.Read(make([]byte, 1))
203 if err != nil {
204 if perr, ok := err.(*os.PathError); !ok || perr.Err != syscall.EAGAIN {
205 t.Fatalf("read on nonblocking stdin got %q, should have gotten EAGAIN", err)
208 os.Exit(0)
211 testenv.MustHaveExec(t)
212 r, w, err := os.Pipe()
213 if err != nil {
214 t.Fatal(err)
216 defer r.Close()
217 defer w.Close()
218 cmd := osexec.Command(os.Args[0], "-test.run="+t.Name())
219 cmd.Env = append(os.Environ(), "GO_WANT_READ_NONBLOCKING_FD=1")
220 cmd.Stdin = r
221 output, err := cmd.CombinedOutput()
222 t.Logf("%s", output)
223 if err != nil {
224 t.Errorf("child process failed: %v", err)
228 func TestCloseWithBlockingReadByNewFile(t *testing.T) {
229 var p [2]int
230 err := syscall.Pipe(p[:])
231 if err != nil {
232 t.Fatal(err)
234 // os.NewFile returns a blocking mode file.
235 testCloseWithBlockingRead(t, os.NewFile(uintptr(p[0]), "reader"), os.NewFile(uintptr(p[1]), "writer"))
238 func TestCloseWithBlockingReadByFd(t *testing.T) {
239 r, w, err := os.Pipe()
240 if err != nil {
241 t.Fatal(err)
243 // Calling Fd will put the file into blocking mode.
244 _ = r.Fd()
245 testCloseWithBlockingRead(t, r, w)
248 // Test that we don't let a blocking read prevent a close.
249 func testCloseWithBlockingRead(t *testing.T, r, w *os.File) {
250 defer r.Close()
251 defer w.Close()
253 c1, c2 := make(chan bool), make(chan bool)
254 var wg sync.WaitGroup
256 wg.Add(1)
257 go func(c chan bool) {
258 defer wg.Done()
259 // Give the other goroutine a chance to enter the Read
260 // or Write call. This is sloppy but the test will
261 // pass even if we close before the read/write.
262 time.Sleep(20 * time.Millisecond)
264 if err := r.Close(); err != nil {
265 t.Error(err)
267 close(c)
268 }(c1)
270 wg.Add(1)
271 go func(c chan bool) {
272 defer wg.Done()
273 var b [1]byte
274 _, err := r.Read(b[:])
275 close(c)
276 if err == nil {
277 t.Error("I/O on closed pipe unexpectedly succeeded")
279 if err != io.EOF {
280 t.Errorf("got %v, expected io.EOF", err)
282 }(c2)
284 for c1 != nil || c2 != nil {
285 select {
286 case <-c1:
287 c1 = nil
288 // r.Close has completed, but the blocking Read
289 // is hanging. Close the writer to unblock it.
290 w.Close()
291 case <-c2:
292 c2 = nil
293 case <-time.After(1 * time.Second):
294 switch {
295 case c1 != nil && c2 != nil:
296 t.Error("timed out waiting for Read and Close")
297 w.Close()
298 case c1 != nil:
299 t.Error("timed out waiting for Close")
300 case c2 != nil:
301 t.Error("timed out waiting for Read")
302 default:
303 t.Error("impossible case")
308 wg.Wait()
311 // Issue 24164, for pipes.
312 func TestPipeEOF(t *testing.T) {
313 r, w, err := os.Pipe()
314 if err != nil {
315 t.Fatal(err)
318 var wg sync.WaitGroup
319 wg.Add(1)
320 go func() {
321 defer wg.Done()
323 defer func() {
324 if err := w.Close(); err != nil {
325 t.Errorf("error closing writer: %v", err)
329 for i := 0; i < 3; i++ {
330 time.Sleep(10 * time.Millisecond)
331 _, err := fmt.Fprintf(w, "line %d\n", i)
332 if err != nil {
333 t.Errorf("error writing to fifo: %v", err)
334 return
337 time.Sleep(10 * time.Millisecond)
340 defer wg.Wait()
342 done := make(chan bool)
343 go func() {
344 defer close(done)
346 defer func() {
347 if err := r.Close(); err != nil {
348 t.Errorf("error closing reader: %v", err)
352 rbuf := bufio.NewReader(r)
353 for {
354 b, err := rbuf.ReadBytes('\n')
355 if err == io.EOF {
356 break
358 if err != nil {
359 t.Error(err)
360 return
362 t.Logf("%s\n", bytes.TrimSpace(b))
366 select {
367 case <-done:
368 // Test succeeded.
369 case <-time.After(time.Second):
370 t.Error("timed out waiting for read")
371 // Close the reader to force the read to complete.
372 r.Close()
376 // Issue 24481.
377 func TestFdRace(t *testing.T) {
378 r, w, err := os.Pipe()
379 if err != nil {
380 t.Fatal(err)
382 defer r.Close()
383 defer w.Close()
385 var wg sync.WaitGroup
386 call := func() {
387 defer wg.Done()
388 w.Fd()
391 const tries = 100
392 for i := 0; i < tries; i++ {
393 wg.Add(1)
394 go call()
396 wg.Wait()
399 func TestFdReadRace(t *testing.T) {
400 t.Parallel()
402 r, w, err := os.Pipe()
403 if err != nil {
404 t.Fatal(err)
406 defer r.Close()
407 defer w.Close()
409 c := make(chan bool)
410 var wg sync.WaitGroup
411 wg.Add(1)
412 go func() {
413 defer wg.Done()
414 var buf [10]byte
415 r.SetReadDeadline(time.Now().Add(time.Second))
416 c <- true
417 if _, err := r.Read(buf[:]); os.IsTimeout(err) {
418 t.Error("read timed out")
422 wg.Add(1)
423 go func() {
424 defer wg.Done()
426 // Give the other goroutine a chance to enter the Read.
427 // It doesn't matter if this occasionally fails, the test
428 // will still pass, it just won't test anything.
429 time.Sleep(10 * time.Millisecond)
430 r.Fd()
432 // The bug was that Fd would hang until Read timed out.
433 // If the bug is fixed, then closing r here will cause
434 // the Read to exit before the timeout expires.
435 r.Close()
438 wg.Wait()