2018-23-01 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / go / os / timeout_test.go
blob6f47ed04a9748d892977050575794a5d3f9529a2
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.
5 // +build !nacl
6 // +build !plan9
7 // +build !windows
9 package os_test
11 import (
12 "fmt"
13 "internal/poll"
14 "io"
15 "io/ioutil"
16 "math/rand"
17 "os"
18 "runtime"
19 "sync"
20 "testing"
21 "time"
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")
32 if err != nil {
33 t.Fatal(err)
35 defer os.Remove(f.Name())
36 defer f.Close()
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 {
53 timeout time.Duration
54 xerrs [2]error // expected errors in transition
56 // Tests that read deadlines work, even if there's data ready
57 // to be read.
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) {
64 t.Parallel()
66 r, w, err := os.Pipe()
67 if err != nil {
68 t.Fatal(err)
70 defer r.Close()
71 defer w.Close()
73 if _, err := w.Write([]byte("READ TIMEOUT TEST")); err != nil {
74 t.Fatal(err)
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)
81 var b [1]byte
82 for j, xerr := range tt.xerrs {
83 for {
84 n, err := r.Read(b[:])
85 if xerr != nil {
86 if !os.IsTimeout(err) {
87 t.Fatalf("#%d/%d: %v", i, j, err)
90 if err == nil {
91 time.Sleep(tt.timeout / 3)
92 continue
94 if n != 0 {
95 t.Fatalf("#%d/%d: read %d; want 0", i, j, n)
97 break
103 func TestReadTimeoutMustNotReturn(t *testing.T) {
104 t.Parallel()
106 r, w, err := os.Pipe()
107 if err != nil {
108 t.Fatal(err)
110 defer r.Close()
111 defer w.Close()
113 max := time.NewTimer(100 * time.Millisecond)
114 defer max.Stop()
115 ch := make(chan error)
116 go func() {
117 if err := r.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil {
118 t.Error(err)
120 if err := r.SetWriteDeadline(time.Now().Add(-5 * time.Second)); err != nil {
121 t.Error(err)
123 if err := r.SetReadDeadline(noDeadline); err != nil {
124 t.Error(err)
126 var b [1]byte
127 _, err := r.Read(b[:])
128 ch <- err
131 select {
132 case err := <-ch:
133 t.Fatalf("expected Read to not return, but it returned with %v", err)
134 case <-max.C:
135 w.Close()
136 err := <-ch // wait for tester goroutine to stop
137 if os.IsTimeout(err) {
138 t.Fatal(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) {
155 t.Parallel()
157 for i, tt := range writeTimeoutTests {
158 t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
159 r, w, err := os.Pipe()
160 if err != nil {
161 t.Fatal(err)
163 defer r.Close()
164 defer w.Close()
166 if err := w.SetWriteDeadline(time.Now().Add(tt.timeout)); err != nil {
167 t.Fatalf("%v", err)
169 for j, xerr := range tt.xerrs {
170 for {
171 n, err := w.Write([]byte("WRITE TIMEOUT TEST"))
172 if xerr != nil {
173 if !os.IsTimeout(err) {
174 t.Fatalf("%d: %v", j, err)
177 if err == nil {
178 time.Sleep(tt.timeout / 3)
179 continue
181 if n != 0 {
182 t.Fatalf("%d: wrote %d; want 0", j, n)
184 break
191 func TestWriteTimeoutMustNotReturn(t *testing.T) {
192 t.Parallel()
194 r, w, err := os.Pipe()
195 if err != nil {
196 t.Fatal(err)
198 defer r.Close()
199 defer w.Close()
201 max := time.NewTimer(100 * time.Millisecond)
202 defer max.Stop()
203 ch := make(chan error)
204 go func() {
205 if err := w.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil {
206 t.Error(err)
208 if err := w.SetReadDeadline(time.Now().Add(-5 * time.Second)); err != nil {
209 t.Error(err)
211 if err := w.SetWriteDeadline(noDeadline); err != nil {
212 t.Error(err)
214 var b [1]byte
215 for {
216 if _, err := w.Write(b[:]); err != nil {
217 ch <- err
218 break
223 select {
224 case err := <-ch:
225 t.Fatalf("expected Write to not return, but it returned with %v", err)
226 case <-max.C:
227 r.Close()
228 err := <-ch // wait for tester goroutine to stop
229 if os.IsTimeout(err) {
230 t.Fatal(err)
235 func timeoutReader(r *os.File, d, min, max time.Duration, ch chan<- error) {
236 var err error
237 defer func() { ch <- err }()
239 t0 := time.Now()
240 if err = r.SetReadDeadline(time.Now().Add(d)); err != nil {
241 return
243 b := make([]byte, 256)
244 var n int
245 n, err = r.Read(b)
246 t1 := time.Now()
247 if n != 0 || err == nil || !os.IsTimeout(err) {
248 err = fmt.Errorf("Read did not return (0, timeout): (%d, %v)", n, err)
249 return
251 if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() {
252 err = fmt.Errorf("Read took %s; expected %s", dt, d)
253 return
257 func TestReadTimeoutFluctuation(t *testing.T) {
258 t.Parallel()
260 r, w, err := os.Pipe()
261 if err != nil {
262 t.Fatal(err)
264 defer r.Close()
265 defer w.Close()
267 max := time.NewTimer(time.Second)
268 defer max.Stop()
269 ch := make(chan error)
270 go timeoutReader(r, 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch)
272 select {
273 case <-max.C:
274 t.Fatal("Read took over 1s; expected 0.1s")
275 case err := <-ch:
276 if !os.IsTimeout(err) {
277 t.Fatal(err)
282 func timeoutWriter(w *os.File, d, min, max time.Duration, ch chan<- error) {
283 var err error
284 defer func() { ch <- err }()
286 t0 := time.Now()
287 if err = w.SetWriteDeadline(time.Now().Add(d)); err != nil {
288 return
290 var n int
291 for {
292 n, err = w.Write([]byte("TIMEOUT WRITER"))
293 if err != nil {
294 break
297 t1 := time.Now()
298 if err == nil || !os.IsTimeout(err) {
299 err = fmt.Errorf("Write did not return (any, timeout): (%d, %v)", n, err)
300 return
302 if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() {
303 err = fmt.Errorf("Write took %s; expected %s", dt, d)
304 return
308 func TestWriteTimeoutFluctuation(t *testing.T) {
309 t.Parallel()
311 r, w, err := os.Pipe()
312 if err != nil {
313 t.Fatal(err)
315 defer r.Close()
316 defer w.Close()
318 d := time.Second
319 max := time.NewTimer(d)
320 defer max.Stop()
321 ch := make(chan error)
322 go timeoutWriter(w, 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch)
324 select {
325 case <-max.C:
326 t.Fatalf("Write took over %v; expected 0.1s", d)
327 case err := <-ch:
328 if !os.IsTimeout(err) {
329 t.Fatal(err)
334 func TestVariousDeadlines(t *testing.T) {
335 t.Parallel()
336 testVariousDeadlines(t)
339 func TestVariousDeadlines1Proc(t *testing.T) {
340 // Cannot use t.Parallel - modifies global GOMAXPROCS.
341 if testing.Short() {
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.
350 if testing.Short() {
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) {
360 for i := range p {
361 p[i] = byte(b)
363 return len(p), nil
366 func testVariousDeadlines(t *testing.T) {
367 type result struct {
368 n int64
369 err error
370 d time.Duration
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.
376 t0 := time.Now()
377 n, err := io.Copy(w, neverEnding('a'))
378 dt := time.Since(t0)
379 pasvch <- result{n, err, dt}
382 for _, timeout := range []time.Duration{
383 1 * time.Nanosecond,
384 2 * time.Nanosecond,
385 5 * time.Nanosecond,
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,
401 1 * time.Second,
403 numRuns := 3
404 if testing.Short() {
405 numRuns = 1
406 if timeout > 500*time.Microsecond {
407 continue
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()
413 if err != nil {
414 t.Fatal(err)
416 defer r.Close()
417 defer w.Close()
419 pasvch := make(chan result)
420 go handler(w, pasvch)
422 tooLong := 5 * time.Second
423 max := time.NewTimer(tooLong)
424 defer max.Stop()
425 actvch := make(chan result)
426 go func() {
427 t0 := time.Now()
428 if err := r.SetDeadline(t0.Add(timeout)); err != nil {
429 t.Error(err)
431 n, err := io.Copy(ioutil.Discard, r)
432 dt := time.Since(t0)
433 r.Close()
434 actvch <- result{n, err, dt}
437 select {
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)
441 } else {
442 t.Fatalf("client Copy = %d, %v; want timeout", res.n, res.err)
444 case <-max.C:
445 t.Fatalf("timeout (%v) waiting for client to timeout (%v) reading", tooLong, timeout)
448 select {
449 case res := <-pasvch:
450 t.Logf("writer in %v wrote %d: %v", res.d, res.n, res.err)
451 case <-max.C:
452 t.Fatalf("timeout waiting for writer to finish writing")
459 func TestReadWriteDeadlineRace(t *testing.T) {
460 t.Parallel()
462 N := 1000
463 if testing.Short() {
464 N = 50
467 r, w, err := os.Pipe()
468 if err != nil {
469 t.Fatal(err)
471 defer r.Close()
472 defer w.Close()
474 var wg sync.WaitGroup
475 wg.Add(3)
476 go func() {
477 defer wg.Done()
478 tic := time.NewTicker(2 * time.Microsecond)
479 defer tic.Stop()
480 for i := 0; i < N; i++ {
481 if err := r.SetReadDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
482 break
484 if err := w.SetWriteDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
485 break
487 <-tic.C
490 go func() {
491 defer wg.Done()
492 var b [1]byte
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)
500 go func() {
501 defer wg.Done()
502 var b [1]byte
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) {
516 t.Parallel()
518 r, w, err := os.Pipe()
519 if err != nil {
520 t.Fatal(err)
522 defer r.Close()
523 defer w.Close()
525 var wg sync.WaitGroup
526 defer wg.Wait()
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++ {
532 wg.Add(1)
533 go func() {
534 defer wg.Done()
536 b1 := make([]byte, 1024)
537 b2 := make([]byte, 1024)
538 for j := 0; j < 100; j++ {
539 _, err := r.Read(b1)
540 copy(b1, b2) // Mutate b1 to trigger potential race
541 if err != nil {
542 if !os.IsTimeout(err) {
543 t.Error(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) {
555 t.Parallel()
557 r, w, err := os.Pipe()
558 if err != nil {
559 t.Fatal(err)
561 defer r.Close()
562 defer w.Close()
564 var wg sync.WaitGroup
565 defer wg.Wait()
567 go io.Copy(ioutil.Discard, r)
569 w.SetWriteDeadline(time.Now().Add(time.Millisecond))
570 for i := 0; i < 10; i++ {
571 wg.Add(1)
572 go func() {
573 defer wg.Done()
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
580 if err != nil {
581 if !os.IsTimeout(err) {
582 t.Error(err)
584 w.SetWriteDeadline(time.Now().Add(time.Millisecond))