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.
24 func TestNonpollableDeadline(t
*testing
.T
) {
25 // On BSD systems regular files seem to be pollable,
26 // so just run this test on Linux.
27 if runtime
.GOOS
!= "linux" {
28 t
.Skipf("skipping on %s", runtime
.GOOS
)
31 f
, err
:= ioutil
.TempFile("", "ostest")
35 defer os
.Remove(f
.Name())
37 deadline
:= time
.Now().Add(10 * time
.Second
)
38 if err
:= f
.SetDeadline(deadline
); err
!= os
.ErrNoDeadline
{
39 t
.Errorf("SetDeadline on file returned %v, wanted %v", err
, os
.ErrNoDeadline
)
41 if err
:= f
.SetReadDeadline(deadline
); err
!= os
.ErrNoDeadline
{
42 t
.Errorf("SetReadDeadline on file returned %v, wanted %v", err
, os
.ErrNoDeadline
)
44 if err
:= f
.SetWriteDeadline(deadline
); err
!= os
.ErrNoDeadline
{
45 t
.Errorf("SetWriteDeadline on file returned %v, wanted %v", err
, os
.ErrNoDeadline
)
49 // noDeadline is a zero time.Time value, which cancels a deadline.
50 var noDeadline time
.Time
52 var readTimeoutTests
= []struct {
54 xerrs
[2]error
// expected errors in transition
56 // Tests that read deadlines work, even if there's data ready
58 {-5 * time
.Second
, [2]error
{poll
.ErrTimeout
, poll
.ErrTimeout
}},
60 {50 * time
.Millisecond
, [2]error
{nil, poll
.ErrTimeout
}},
63 func TestReadTimeout(t
*testing
.T
) {
66 r
, w
, err
:= os
.Pipe()
73 if _
, err
:= w
.Write([]byte("READ TIMEOUT TEST")); err
!= nil {
77 for i
, tt
:= range readTimeoutTests
{
78 if err
:= r
.SetReadDeadline(time
.Now().Add(tt
.timeout
)); err
!= nil {
79 t
.Fatalf("#%d: %v", i
, err
)
82 for j
, xerr
:= range tt
.xerrs
{
84 n
, err
:= r
.Read(b
[:])
86 if !os
.IsTimeout(err
) {
87 t
.Fatalf("#%d/%d: %v", i
, j
, err
)
91 time
.Sleep(tt
.timeout
/ 3)
95 t
.Fatalf("#%d/%d: read %d; want 0", i
, j
, n
)
103 func TestReadTimeoutMustNotReturn(t
*testing
.T
) {
106 r
, w
, err
:= os
.Pipe()
113 max
:= time
.NewTimer(100 * time
.Millisecond
)
115 ch
:= make(chan error
)
117 if err
:= r
.SetDeadline(time
.Now().Add(-5 * time
.Second
)); err
!= nil {
120 if err
:= r
.SetWriteDeadline(time
.Now().Add(-5 * time
.Second
)); err
!= nil {
123 if err
:= r
.SetReadDeadline(noDeadline
); err
!= nil {
127 _
, err
:= r
.Read(b
[:])
133 t
.Fatalf("expected Read to not return, but it returned with %v", err
)
136 err
:= <-ch
// wait for tester goroutine to stop
137 if os
.IsTimeout(err
) {
143 var writeTimeoutTests
= []struct {
144 timeout time
.Duration
145 xerrs
[2]error
// expected errors in transition
147 // Tests that write deadlines work, even if there's buffer
148 // space available to write.
149 {-5 * time
.Second
, [2]error
{poll
.ErrTimeout
, poll
.ErrTimeout
}},
151 {10 * time
.Millisecond
, [2]error
{nil, poll
.ErrTimeout
}},
154 func TestWriteTimeout(t
*testing
.T
) {
157 for i
, tt
:= range writeTimeoutTests
{
158 t
.Run(fmt
.Sprintf("#%d", i
), func(t
*testing
.T
) {
159 r
, w
, err
:= os
.Pipe()
166 if err
:= w
.SetWriteDeadline(time
.Now().Add(tt
.timeout
)); err
!= nil {
169 for j
, xerr
:= range tt
.xerrs
{
171 n
, err
:= w
.Write([]byte("WRITE TIMEOUT TEST"))
173 if !os
.IsTimeout(err
) {
174 t
.Fatalf("%d: %v", j
, err
)
178 time
.Sleep(tt
.timeout
/ 3)
182 t
.Fatalf("%d: wrote %d; want 0", j
, n
)
191 func TestWriteTimeoutMustNotReturn(t
*testing
.T
) {
194 r
, w
, err
:= os
.Pipe()
201 max
:= time
.NewTimer(100 * time
.Millisecond
)
203 ch
:= make(chan error
)
205 if err
:= w
.SetDeadline(time
.Now().Add(-5 * time
.Second
)); err
!= nil {
208 if err
:= w
.SetReadDeadline(time
.Now().Add(-5 * time
.Second
)); err
!= nil {
211 if err
:= w
.SetWriteDeadline(noDeadline
); err
!= nil {
216 if _
, err
:= w
.Write(b
[:]); err
!= nil {
225 t
.Fatalf("expected Write to not return, but it returned with %v", err
)
228 err
:= <-ch
// wait for tester goroutine to stop
229 if os
.IsTimeout(err
) {
235 func timeoutReader(r
*os
.File
, d
, min
, max time
.Duration
, ch
chan<- error
) {
237 defer func() { ch
<- err
}()
240 if err
= r
.SetReadDeadline(time
.Now().Add(d
)); err
!= nil {
243 b
:= make([]byte, 256)
247 if n
!= 0 || err
== nil ||
!os
.IsTimeout(err
) {
248 err
= fmt
.Errorf("Read did not return (0, timeout): (%d, %v)", n
, err
)
251 if dt
:= t1
.Sub(t0
); min
> dt || dt
> max
&& !testing
.Short() {
252 err
= fmt
.Errorf("Read took %s; expected %s", dt
, d
)
257 func TestReadTimeoutFluctuation(t
*testing
.T
) {
260 r
, w
, err
:= os
.Pipe()
267 max
:= time
.NewTimer(time
.Second
)
269 ch
:= make(chan error
)
270 go timeoutReader(r
, 100*time
.Millisecond
, 50*time
.Millisecond
, 250*time
.Millisecond
, ch
)
274 t
.Fatal("Read took over 1s; expected 0.1s")
276 if !os
.IsTimeout(err
) {
282 func timeoutWriter(w
*os
.File
, d
, min
, max time
.Duration
, ch
chan<- error
) {
284 defer func() { ch
<- err
}()
287 if err
= w
.SetWriteDeadline(time
.Now().Add(d
)); err
!= nil {
292 n
, err
= w
.Write([]byte("TIMEOUT WRITER"))
298 if err
== nil ||
!os
.IsTimeout(err
) {
299 err
= fmt
.Errorf("Write did not return (any, timeout): (%d, %v)", n
, err
)
302 if dt
:= t1
.Sub(t0
); min
> dt || dt
> max
&& !testing
.Short() {
303 err
= fmt
.Errorf("Write took %s; expected %s", dt
, d
)
308 func TestWriteTimeoutFluctuation(t
*testing
.T
) {
311 r
, w
, err
:= os
.Pipe()
319 max
:= time
.NewTimer(d
)
321 ch
:= make(chan error
)
322 go timeoutWriter(w
, 100*time
.Millisecond
, 50*time
.Millisecond
, 250*time
.Millisecond
, ch
)
326 t
.Fatalf("Write took over %v; expected 0.1s", d
)
328 if !os
.IsTimeout(err
) {
334 func TestVariousDeadlines(t
*testing
.T
) {
336 testVariousDeadlines(t
)
339 func TestVariousDeadlines1Proc(t
*testing
.T
) {
340 // Cannot use t.Parallel - modifies global GOMAXPROCS.
342 t
.Skip("skipping in short mode")
344 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(1))
345 testVariousDeadlines(t
)
348 func TestVariousDeadlines4Proc(t
*testing
.T
) {
349 // Cannot use t.Parallel - modifies global GOMAXPROCS.
351 t
.Skip("skipping in short mode")
353 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(4))
354 testVariousDeadlines(t
)
357 type neverEnding
byte
359 func (b neverEnding
) Read(p
[]byte) (int, error
) {
366 func testVariousDeadlines(t
*testing
.T
) {
373 handler
:= func(w
*os
.File
, pasvch
chan result
) {
374 // The writer, with no timeouts of its own,
375 // sending bytes to clients as fast as it can.
377 n
, err
:= io
.Copy(w
, neverEnding('a'))
379 pasvch
<- result
{n
, err
, dt
}
382 for _
, timeout
:= range []time
.Duration
{
386 50 * time
.Nanosecond
,
387 100 * time
.Nanosecond
,
388 200 * time
.Nanosecond
,
389 500 * time
.Nanosecond
,
390 750 * time
.Nanosecond
,
391 1 * time
.Microsecond
,
392 5 * time
.Microsecond
,
393 25 * time
.Microsecond
,
394 250 * time
.Microsecond
,
395 500 * time
.Microsecond
,
396 1 * time
.Millisecond
,
397 5 * time
.Millisecond
,
398 100 * time
.Millisecond
,
399 250 * time
.Millisecond
,
400 500 * time
.Millisecond
,
406 if timeout
> 500*time
.Microsecond
{
410 for run
:= 0; run
< numRuns
; run
++ {
411 t
.Run(fmt
.Sprintf("%v-%d", timeout
, run
+1), func(t
*testing
.T
) {
412 r
, w
, err
:= os
.Pipe()
419 pasvch
:= make(chan result
)
420 go handler(w
, pasvch
)
422 tooLong
:= 5 * time
.Second
423 max
:= time
.NewTimer(tooLong
)
425 actvch
:= make(chan result
)
428 if err
:= r
.SetDeadline(t0
.Add(timeout
)); err
!= nil {
431 n
, err
:= io
.Copy(ioutil
.Discard
, r
)
434 actvch
<- result
{n
, err
, dt
}
438 case res
:= <-actvch
:
439 if os
.IsTimeout(res
.err
) {
440 t
.Logf("good client timeout after %v, reading %d bytes", res
.d
, res
.n
)
442 t
.Fatalf("client Copy = %d, %v; want timeout", res
.n
, res
.err
)
445 t
.Fatalf("timeout (%v) waiting for client to timeout (%v) reading", tooLong
, timeout
)
449 case res
:= <-pasvch
:
450 t
.Logf("writer in %v wrote %d: %v", res
.d
, res
.n
, res
.err
)
452 t
.Fatalf("timeout waiting for writer to finish writing")
459 func TestReadWriteDeadlineRace(t
*testing
.T
) {
467 r
, w
, err
:= os
.Pipe()
474 var wg sync
.WaitGroup
478 tic
:= time
.NewTicker(2 * time
.Microsecond
)
480 for i
:= 0; i
< N
; i
++ {
481 if err
:= r
.SetReadDeadline(time
.Now().Add(2 * time
.Microsecond
)); err
!= nil {
484 if err
:= w
.SetWriteDeadline(time
.Now().Add(2 * time
.Microsecond
)); err
!= nil {
493 for i
:= 0; i
< N
; i
++ {
494 _
, err
:= r
.Read(b
[:])
495 if err
!= nil && !os
.IsTimeout(err
) {
496 t
.Error("Read returned non-timeout error", err
)
503 for i
:= 0; i
< N
; i
++ {
504 _
, err
:= w
.Write(b
[:])
505 if err
!= nil && !os
.IsTimeout(err
) {
506 t
.Error("Write returned non-timeout error", err
)
510 wg
.Wait() // wait for tester goroutine to stop
513 // TestRacyRead tests that it is safe to mutate the input Read buffer
514 // immediately after cancelation has occurred.
515 func TestRacyRead(t
*testing
.T
) {
518 r
, w
, err
:= os
.Pipe()
525 var wg sync
.WaitGroup
528 go io
.Copy(w
, rand
.New(rand
.NewSource(0)))
530 r
.SetReadDeadline(time
.Now().Add(time
.Millisecond
))
531 for i
:= 0; i
< 10; i
++ {
536 b1
:= make([]byte, 1024)
537 b2
:= make([]byte, 1024)
538 for j
:= 0; j
< 100; j
++ {
540 copy(b1
, b2
) // Mutate b1 to trigger potential race
542 if !os
.IsTimeout(err
) {
545 r
.SetReadDeadline(time
.Now().Add(time
.Millisecond
))
552 // TestRacyWrite tests that it is safe to mutate the input Write buffer
553 // immediately after cancelation has occurred.
554 func TestRacyWrite(t
*testing
.T
) {
557 r
, w
, err
:= os
.Pipe()
564 var wg sync
.WaitGroup
567 go io
.Copy(ioutil
.Discard
, r
)
569 w
.SetWriteDeadline(time
.Now().Add(time
.Millisecond
))
570 for i
:= 0; i
< 10; i
++ {
575 b1
:= make([]byte, 1024)
576 b2
:= make([]byte, 1024)
577 for j
:= 0; j
< 100; j
++ {
578 _
, err
:= w
.Write(b1
)
579 copy(b1
, b2
) // Mutate b1 to trigger potential race
581 if !os
.IsTimeout(err
) {
584 w
.SetWriteDeadline(time
.Now().Add(time
.Millisecond
))