1 // Copyright 2017 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.
27 func TestNonpollableDeadline(t *testing.T) {
28 // On BSD systems regular files seem to be pollable,
29 // so just run this test on Linux.
30 if runtime.GOOS != "linux" {
31 t.Skipf("skipping on %s", runtime.GOOS)
34 f, err := ioutil.TempFile("", "ostest")
38 defer os.Remove(f.Name())
40 deadline := time.Now().Add(10 * time.Second)
41 if err := f.SetDeadline(deadline); err != os.ErrNoDeadline {
42 t.Errorf("SetDeadline on file returned %v, wanted %v", err, os.ErrNoDeadline)
44 if err := f.SetReadDeadline(deadline); err != os.ErrNoDeadline {
45 t.Errorf("SetReadDeadline on file returned %v, wanted %v", err, os.ErrNoDeadline)
47 if err := f.SetWriteDeadline(deadline); err != os.ErrNoDeadline {
48 t.Errorf("SetWriteDeadline on file returned %v, wanted %v", err, os.ErrNoDeadline)
52 // noDeadline is a zero time.Time value, which cancels a deadline.
53 var noDeadline time.Time
55 var readTimeoutTests = []struct {
57 xerrs [2]error // expected errors in transition
59 // Tests that read deadlines work, even if there's data ready
61 {-5 * time.Second, [2]error{poll.ErrTimeout, poll.ErrTimeout}},
63 {50 * time.Millisecond, [2]error{nil, poll.ErrTimeout}},
66 func TestReadTimeout(t *testing.T) {
69 r, w, err := os.Pipe()
76 if _, err := w.Write([]byte("READ TIMEOUT TEST")); err != nil {
80 for i, tt := range readTimeoutTests {
81 if err := r.SetReadDeadline(time.Now().Add(tt.timeout)); err != nil {
82 t.Fatalf("#%d: %v", i, err)
85 for j, xerr := range tt.xerrs {
87 n, err := r.Read(b[:])
89 if !os.IsTimeout(err) {
90 t.Fatalf("#%d/%d: %v", i, j, err)
94 time.Sleep(tt.timeout / 3)
98 t.Fatalf("#%d/%d: read %d; want 0", i, j, n)
106 func TestReadTimeoutMustNotReturn(t *testing.T) {
109 r, w, err := os.Pipe()
116 max := time.NewTimer(100 * time.Millisecond)
118 ch := make(chan error)
120 if err := r.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil {
123 if err := r.SetWriteDeadline(time.Now().Add(-5 * time.Second)); err != nil {
126 if err := r.SetReadDeadline(noDeadline); err != nil {
130 _, err := r.Read(b[:])
136 t.Fatalf("expected Read to not return, but it returned with %v", err)
139 err := <-ch // wait for tester goroutine to stop
140 if os.IsTimeout(err) {
146 var writeTimeoutTests = []struct {
147 timeout time.Duration
148 xerrs [2]error // expected errors in transition
150 // Tests that write deadlines work, even if there's buffer
151 // space available to write.
152 {-5 * time.Second, [2]error{poll.ErrTimeout, poll.ErrTimeout}},
154 {10 * time.Millisecond, [2]error{nil, poll.ErrTimeout}},
157 func TestWriteTimeout(t *testing.T) {
160 for i, tt := range writeTimeoutTests {
161 t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
162 r, w, err := os.Pipe()
169 if err := w.SetWriteDeadline(time.Now().Add(tt.timeout)); err != nil {
172 for j, xerr := range tt.xerrs {
174 n, err := w.Write([]byte("WRITE TIMEOUT TEST"))
176 if !os.IsTimeout(err) {
177 t.Fatalf("%d: %v", j, err)
181 time.Sleep(tt.timeout / 3)
185 t.Fatalf("%d: wrote %d; want 0", j, n)
194 func TestWriteTimeoutMustNotReturn(t *testing.T) {
197 r, w, err := os.Pipe()
204 max := time.NewTimer(100 * time.Millisecond)
206 ch := make(chan error)
208 if err := w.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil {
211 if err := w.SetReadDeadline(time.Now().Add(-5 * time.Second)); err != nil {
214 if err := w.SetWriteDeadline(noDeadline); err != nil {
219 if _, err := w.Write(b[:]); err != nil {
228 t.Fatalf("expected Write to not return, but it returned with %v", err)
231 err := <-ch // wait for tester goroutine to stop
232 if os.IsTimeout(err) {
238 func timeoutReader(r *os.File, d, min, max time.Duration, ch chan<- error) {
240 defer func() { ch <- err }()
243 if err = r.SetReadDeadline(time.Now().Add(d)); err != nil {
246 b := make([]byte, 256)
250 if n != 0 || err == nil || !os.IsTimeout(err) {
251 err = fmt.Errorf("Read did not return (0, timeout): (%d, %v)", n, err)
254 if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() {
255 err = fmt.Errorf("Read took %s; expected %s", dt, d)
260 func TestReadTimeoutFluctuation(t *testing.T) {
263 r, w, err := os.Pipe()
270 max := time.NewTimer(time.Second)
272 ch := make(chan error)
273 go timeoutReader(r, 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch)
277 t.Fatal("Read took over 1s; expected 0.1s")
279 if !os.IsTimeout(err) {
285 func timeoutWriter(w *os.File, d, min, max time.Duration, ch chan<- error) {
287 defer func() { ch <- err }()
290 if err = w.SetWriteDeadline(time.Now().Add(d)); err != nil {
295 n, err = w.Write([]byte("TIMEOUT WRITER"))
301 if err == nil || !os.IsTimeout(err) {
302 err = fmt.Errorf("Write did not return (any, timeout): (%d, %v)", n, err)
305 if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() {
306 err = fmt.Errorf("Write took %s; expected %s", dt, d)
311 func TestWriteTimeoutFluctuation(t *testing.T) {
314 r, w, err := os.Pipe()
322 max := time.NewTimer(d)
324 ch := make(chan error)
325 go timeoutWriter(w, 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch)
329 t.Fatalf("Write took over %v; expected 0.1s", d)
331 if !os.IsTimeout(err) {
337 func TestVariousDeadlines(t *testing.T) {
339 testVariousDeadlines(t)
342 func TestVariousDeadlines1Proc(t *testing.T) {
343 // Cannot use t.Parallel - modifies global GOMAXPROCS.
345 t.Skip("skipping in short mode")
347 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
348 testVariousDeadlines(t)
351 func TestVariousDeadlines4Proc(t *testing.T) {
352 // Cannot use t.Parallel - modifies global GOMAXPROCS.
354 t.Skip("skipping in short mode")
356 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
357 testVariousDeadlines(t)
360 type neverEnding byte
362 func (b neverEnding) Read(p []byte) (int, error) {
369 func testVariousDeadlines(t *testing.T) {
376 handler := func(w *os.File, pasvch chan result) {
377 // The writer, with no timeouts of its own,
378 // sending bytes to clients as fast as it can.
380 n, err := io.Copy(w, neverEnding('a'))
382 pasvch <- result{n, err, dt}
385 for _, timeout := range []time.Duration{
389 50 * time.Nanosecond,
390 100 * time.Nanosecond,
391 200 * time.Nanosecond,
392 500 * time.Nanosecond,
393 750 * time.Nanosecond,
394 1 * time.Microsecond,
395 5 * time.Microsecond,
396 25 * time.Microsecond,
397 250 * time.Microsecond,
398 500 * time.Microsecond,
399 1 * time.Millisecond,
400 5 * time.Millisecond,
401 100 * time.Millisecond,
402 250 * time.Millisecond,
403 500 * time.Millisecond,
409 if timeout > 500*time.Microsecond {
413 for run := 0; run < numRuns; run++ {
414 t.Run(fmt.Sprintf("%v-%d", timeout, run+1), func(t *testing.T) {
415 r, w, err := os.Pipe()
422 pasvch := make(chan result)
423 go handler(w, pasvch)
425 tooLong := 5 * time.Second
426 max := time.NewTimer(tooLong)
428 actvch := make(chan result)
431 if err := r.SetDeadline(t0.Add(timeout)); err != nil {
434 n, err := io.Copy(ioutil.Discard, r)
437 actvch <- result{n, err, dt}
441 case res := <-actvch:
442 if os.IsTimeout(res.err) {
443 t.Logf("good client timeout after %v, reading %d bytes", res.d, res.n)
445 t.Fatalf("client Copy = %d, %v; want timeout", res.n, res.err)
448 t.Fatalf("timeout (%v) waiting for client to timeout (%v) reading", tooLong, timeout)
452 case res := <-pasvch:
453 t.Logf("writer in %v wrote %d: %v", res.d, res.n, res.err)
455 t.Fatalf("timeout waiting for writer to finish writing")
462 func TestReadWriteDeadlineRace(t *testing.T) {
470 r, w, err := os.Pipe()
477 var wg sync.WaitGroup
481 tic := time.NewTicker(2 * time.Microsecond)
483 for i := 0; i < N; i++ {
484 if err := r.SetReadDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
487 if err := w.SetWriteDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
496 for i := 0; i < N; i++ {
497 _, err := r.Read(b[:])
498 if err != nil && !os.IsTimeout(err) {
499 t.Error("Read returned non-timeout error", err)
506 for i := 0; i < N; i++ {
507 _, err := w.Write(b[:])
508 if err != nil && !os.IsTimeout(err) {
509 t.Error("Write returned non-timeout error", err)
513 wg.Wait() // wait for tester goroutine to stop
516 // TestRacyRead tests that it is safe to mutate the input Read buffer
517 // immediately after cancelation has occurred.
518 func TestRacyRead(t *testing.T) {
521 r, w, err := os.Pipe()
528 var wg sync.WaitGroup
531 go io.Copy(w, rand.New(rand.NewSource(0)))
533 r.SetReadDeadline(time.Now().Add(time.Millisecond))
534 for i := 0; i < 10; i++ {
539 b1 := make([]byte, 1024)
540 b2 := make([]byte, 1024)
541 for j := 0; j < 100; j++ {
543 copy(b1, b2) // Mutate b1 to trigger potential race
545 if !os.IsTimeout(err) {
548 r.SetReadDeadline(time.Now().Add(time.Millisecond))
555 // TestRacyWrite tests that it is safe to mutate the input Write buffer
556 // immediately after cancelation has occurred.
557 func TestRacyWrite(t *testing.T) {
560 r, w, err := os.Pipe()
567 var wg sync.WaitGroup
570 go io.Copy(ioutil.Discard, r)
572 w.SetWriteDeadline(time.Now().Add(time.Millisecond))
573 for i := 0; i < 10; i++ {
578 b1 := make([]byte, 1024)
579 b2 := make([]byte, 1024)
580 for j := 0; j < 100; j++ {
581 _, err := w.Write(b1)
582 copy(b1, b2) // Mutate b1 to trigger potential race
584 if !os.IsTimeout(err) {
587 w.SetWriteDeadline(time.Now().Add(time.Millisecond))
594 // Closing a TTY while reading from it should not hang. Issue 23943.
595 func TestTTYClose(t *testing.T) {
596 // Ignore SIGTTIN in case we are running in the background.
597 signal.Ignore(syscall.SIGTTIN)
598 defer signal.Reset(syscall.SIGTTIN)
600 f, err := os.Open("/dev/tty")
602 t.Skipf("skipping because opening /dev/tty failed: %v", err)
610 // Give the goroutine a chance to enter the read.
611 // It doesn't matter much if it occasionally fails to do so,
612 // we won't be testing what we want to test but the test will pass.
613 time.Sleep(time.Millisecond)
623 case <-time.After(time.Second):
624 t.Error("timed out waiting for close")
627 // On some systems the goroutines may now be hanging.
628 // There's not much we can do about that.