Source file
src/net/timeout_test.go
Documentation: net
1
2
3
4
5 package net
6
7 import (
8 "errors"
9 "fmt"
10 "internal/testenv"
11 "io"
12 "os"
13 "runtime"
14 "sync"
15 "testing"
16 "time"
17 )
18
19 func init() {
20
21
22
23
24
25
26 testHookStepTime = func() {
27 now := time.Now()
28 for time.Since(now) == 0 {
29 time.Sleep(1 * time.Nanosecond)
30 }
31 }
32 }
33
34 var dialTimeoutTests = []struct {
35 initialTimeout time.Duration
36 initialDelta time.Duration
37 }{
38
39 {-5 * time.Second, 0},
40 {0, -5 * time.Second},
41 {-5 * time.Second, 5 * time.Second},
42 {-1 << 63, 0},
43 {0, -1 << 63},
44
45 {1 * time.Millisecond, 0},
46 {0, 1 * time.Millisecond},
47 {1 * time.Millisecond, 5 * time.Second},
48 }
49
50 func TestDialTimeout(t *testing.T) {
51 switch runtime.GOOS {
52 case "plan9":
53 t.Skipf("not supported on %s", runtime.GOOS)
54 }
55
56 t.Parallel()
57
58 ln := newLocalListener(t, "tcp")
59 defer func() {
60 if err := ln.Close(); err != nil {
61 t.Error(err)
62 }
63 }()
64
65 for _, tt := range dialTimeoutTests {
66 t.Run(fmt.Sprintf("%v/%v", tt.initialTimeout, tt.initialDelta), func(t *testing.T) {
67
68
69
70
71 d := Dialer{Timeout: tt.initialTimeout}
72 delta := tt.initialDelta
73
74 var (
75 beforeDial time.Time
76 afterDial time.Time
77 err error
78 )
79 for {
80 if delta != 0 {
81 d.Deadline = time.Now().Add(delta)
82 }
83
84 beforeDial = time.Now()
85
86 var c Conn
87 c, err = d.Dial(ln.Addr().Network(), ln.Addr().String())
88 afterDial = time.Now()
89
90 if err != nil {
91 break
92 }
93
94
95
96
97
98
99
100
101
102
103
104 t.Logf("closing spurious connection from Dial")
105 c.Close()
106
107 if delta <= 1 && d.Timeout <= 1 {
108 t.Fatalf("can't reduce Timeout or Deadline")
109 }
110 if delta > 1 {
111 delta /= 2
112 t.Logf("reducing Deadline delta to %v", delta)
113 }
114 if d.Timeout > 1 {
115 d.Timeout /= 2
116 t.Logf("reducing Timeout to %v", d.Timeout)
117 }
118 }
119
120 if d.Deadline.IsZero() || afterDial.Before(d.Deadline) {
121 delay := afterDial.Sub(beforeDial)
122 if delay < d.Timeout {
123 t.Errorf("Dial returned after %v; want ≥%v", delay, d.Timeout)
124 }
125 }
126
127 if perr := parseDialError(err); perr != nil {
128 t.Errorf("unexpected error from Dial: %v", perr)
129 }
130 if nerr, ok := err.(Error); !ok || !nerr.Timeout() {
131 t.Errorf("Dial: %v, want timeout", err)
132 }
133 })
134 }
135 }
136
137 func TestDialTimeoutMaxDuration(t *testing.T) {
138 ln := newLocalListener(t, "tcp")
139 defer func() {
140 if err := ln.Close(); err != nil {
141 t.Error(err)
142 }
143 }()
144
145 for _, tt := range []struct {
146 timeout time.Duration
147 delta time.Duration
148 }{
149
150 {1<<63 - 1, 0},
151 {0, 1<<63 - 1},
152 } {
153 t.Run(fmt.Sprintf("timeout=%s/delta=%s", tt.timeout, tt.delta), func(t *testing.T) {
154 d := Dialer{Timeout: tt.timeout}
155 if tt.delta != 0 {
156 d.Deadline = time.Now().Add(tt.delta)
157 }
158 c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
159 if err != nil {
160 t.Fatal(err)
161 }
162 if err := c.Close(); err != nil {
163 t.Error(err)
164 }
165 })
166 }
167 }
168
169 var acceptTimeoutTests = []struct {
170 timeout time.Duration
171 xerrs [2]error
172 }{
173
174
175 {-5 * time.Second, [2]error{os.ErrDeadlineExceeded, os.ErrDeadlineExceeded}},
176
177 {50 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
178 }
179
180 func TestAcceptTimeout(t *testing.T) {
181 testenv.SkipFlaky(t, 17948)
182 t.Parallel()
183
184 switch runtime.GOOS {
185 case "plan9":
186 t.Skipf("not supported on %s", runtime.GOOS)
187 }
188
189 ln := newLocalListener(t, "tcp")
190 defer ln.Close()
191
192 var wg sync.WaitGroup
193 for i, tt := range acceptTimeoutTests {
194 if tt.timeout < 0 {
195 wg.Add(1)
196 go func() {
197 defer wg.Done()
198 d := Dialer{Timeout: 100 * time.Millisecond}
199 c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
200 if err != nil {
201 t.Error(err)
202 return
203 }
204 c.Close()
205 }()
206 }
207
208 if err := ln.(*TCPListener).SetDeadline(time.Now().Add(tt.timeout)); err != nil {
209 t.Fatalf("$%d: %v", i, err)
210 }
211 for j, xerr := range tt.xerrs {
212 for {
213 c, err := ln.Accept()
214 if xerr != nil {
215 if perr := parseAcceptError(err); perr != nil {
216 t.Errorf("#%d/%d: %v", i, j, perr)
217 }
218 if !isDeadlineExceeded(err) {
219 t.Fatalf("#%d/%d: %v", i, j, err)
220 }
221 }
222 if err == nil {
223 c.Close()
224 time.Sleep(10 * time.Millisecond)
225 continue
226 }
227 break
228 }
229 }
230 }
231 wg.Wait()
232 }
233
234 func TestAcceptTimeoutMustReturn(t *testing.T) {
235 t.Parallel()
236
237 switch runtime.GOOS {
238 case "plan9":
239 t.Skipf("not supported on %s", runtime.GOOS)
240 }
241
242 ln := newLocalListener(t, "tcp")
243 defer ln.Close()
244
245 if err := ln.(*TCPListener).SetDeadline(noDeadline); err != nil {
246 t.Error(err)
247 }
248 if err := ln.(*TCPListener).SetDeadline(time.Now().Add(10 * time.Millisecond)); err != nil {
249 t.Error(err)
250 }
251 c, err := ln.Accept()
252 if err == nil {
253 c.Close()
254 }
255
256 if perr := parseAcceptError(err); perr != nil {
257 t.Error(perr)
258 }
259 if !isDeadlineExceeded(err) {
260 t.Fatal(err)
261 }
262 }
263
264 func TestAcceptTimeoutMustNotReturn(t *testing.T) {
265 t.Parallel()
266
267 switch runtime.GOOS {
268 case "plan9":
269 t.Skipf("not supported on %s", runtime.GOOS)
270 }
271
272 ln := newLocalListener(t, "tcp")
273 defer ln.Close()
274
275 maxch := make(chan *time.Timer)
276 ch := make(chan error)
277 go func() {
278 if err := ln.(*TCPListener).SetDeadline(time.Now().Add(-5 * time.Second)); err != nil {
279 t.Error(err)
280 }
281 if err := ln.(*TCPListener).SetDeadline(noDeadline); err != nil {
282 t.Error(err)
283 }
284 maxch <- time.NewTimer(100 * time.Millisecond)
285 _, err := ln.Accept()
286 ch <- err
287 }()
288
289 max := <-maxch
290 defer max.Stop()
291
292 select {
293 case err := <-ch:
294 if perr := parseAcceptError(err); perr != nil {
295 t.Error(perr)
296 }
297 t.Fatalf("expected Accept to not return, but it returned with %v", err)
298 case <-max.C:
299 ln.Close()
300 <-ch
301 }
302 }
303
304 var readTimeoutTests = []struct {
305 timeout time.Duration
306 xerrs [2]error
307 }{
308
309
310 {-5 * time.Second, [2]error{os.ErrDeadlineExceeded, os.ErrDeadlineExceeded}},
311
312 {50 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
313 }
314
315
316 func TestReadTimeout(t *testing.T) {
317 handler := func(ls *localServer, ln Listener) {
318 c, err := ln.Accept()
319 if err != nil {
320 t.Error(err)
321 return
322 }
323 c.Write([]byte("READ TIMEOUT TEST"))
324 defer c.Close()
325 }
326 ls := newLocalServer(t, "tcp")
327 defer ls.teardown()
328 if err := ls.buildup(handler); err != nil {
329 t.Fatal(err)
330 }
331
332 c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
333 if err != nil {
334 t.Fatal(err)
335 }
336 defer c.Close()
337
338 for i, tt := range readTimeoutTests {
339 if err := c.SetReadDeadline(time.Now().Add(tt.timeout)); err != nil {
340 t.Fatalf("#%d: %v", i, err)
341 }
342 var b [1]byte
343 for j, xerr := range tt.xerrs {
344 for {
345 n, err := c.Read(b[:])
346 if xerr != nil {
347 if perr := parseReadError(err); perr != nil {
348 t.Errorf("#%d/%d: %v", i, j, perr)
349 }
350 if !isDeadlineExceeded(err) {
351 t.Fatalf("#%d/%d: %v", i, j, err)
352 }
353 }
354 if err == nil {
355 time.Sleep(tt.timeout / 3)
356 continue
357 }
358 if n != 0 {
359 t.Fatalf("#%d/%d: read %d; want 0", i, j, n)
360 }
361 break
362 }
363 }
364 }
365 }
366
367
368 func TestReadTimeoutMustNotReturn(t *testing.T) {
369 t.Parallel()
370
371 switch runtime.GOOS {
372 case "plan9":
373 t.Skipf("not supported on %s", runtime.GOOS)
374 }
375
376 ln := newLocalListener(t, "tcp")
377 defer ln.Close()
378
379 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
380 if err != nil {
381 t.Fatal(err)
382 }
383 defer c.Close()
384
385 maxch := make(chan *time.Timer)
386 ch := make(chan error)
387 go func() {
388 if err := c.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil {
389 t.Error(err)
390 }
391 if err := c.SetWriteDeadline(time.Now().Add(-5 * time.Second)); err != nil {
392 t.Error(err)
393 }
394 if err := c.SetReadDeadline(noDeadline); err != nil {
395 t.Error(err)
396 }
397 maxch <- time.NewTimer(100 * time.Millisecond)
398 var b [1]byte
399 _, err := c.Read(b[:])
400 ch <- err
401 }()
402
403 max := <-maxch
404 defer max.Stop()
405
406 select {
407 case err := <-ch:
408 if perr := parseReadError(err); perr != nil {
409 t.Error(perr)
410 }
411 t.Fatalf("expected Read to not return, but it returned with %v", err)
412 case <-max.C:
413 c.Close()
414 err := <-ch
415 if perr := parseReadError(err); perr != nil {
416 t.Error(perr)
417 }
418 if nerr, ok := err.(Error); !ok || nerr.Timeout() || nerr.Temporary() {
419 t.Fatal(err)
420 }
421 }
422 }
423
424 var readFromTimeoutTests = []struct {
425 timeout time.Duration
426 xerrs [2]error
427 }{
428
429
430 {-5 * time.Second, [2]error{os.ErrDeadlineExceeded, os.ErrDeadlineExceeded}},
431
432 {50 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
433 }
434
435 func TestReadFromTimeout(t *testing.T) {
436 ch := make(chan Addr)
437 defer close(ch)
438 handler := func(ls *localPacketServer, c PacketConn) {
439 if dst, ok := <-ch; ok {
440 c.WriteTo([]byte("READFROM TIMEOUT TEST"), dst)
441 }
442 }
443 ls := newLocalPacketServer(t, "udp")
444 defer ls.teardown()
445 if err := ls.buildup(handler); err != nil {
446 t.Fatal(err)
447 }
448
449 host, _, err := SplitHostPort(ls.PacketConn.LocalAddr().String())
450 if err != nil {
451 t.Fatal(err)
452 }
453 c, err := ListenPacket(ls.PacketConn.LocalAddr().Network(), JoinHostPort(host, "0"))
454 if err != nil {
455 t.Fatal(err)
456 }
457 defer c.Close()
458 ch <- c.LocalAddr()
459
460 for i, tt := range readFromTimeoutTests {
461 if err := c.SetReadDeadline(time.Now().Add(tt.timeout)); err != nil {
462 t.Fatalf("#%d: %v", i, err)
463 }
464 var b [1]byte
465 for j, xerr := range tt.xerrs {
466 for {
467 n, _, err := c.ReadFrom(b[:])
468 if xerr != nil {
469 if perr := parseReadError(err); perr != nil {
470 t.Errorf("#%d/%d: %v", i, j, perr)
471 }
472 if !isDeadlineExceeded(err) {
473 t.Fatalf("#%d/%d: %v", i, j, err)
474 }
475 }
476 if err == nil {
477 time.Sleep(tt.timeout / 3)
478 continue
479 }
480 if nerr, ok := err.(Error); ok && nerr.Timeout() && n != 0 {
481 t.Fatalf("#%d/%d: read %d; want 0", i, j, n)
482 }
483 break
484 }
485 }
486 }
487 }
488
489 var writeTimeoutTests = []struct {
490 timeout time.Duration
491 xerrs [2]error
492 }{
493
494
495 {-5 * time.Second, [2]error{os.ErrDeadlineExceeded, os.ErrDeadlineExceeded}},
496
497 {10 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
498 }
499
500
501 func TestWriteTimeout(t *testing.T) {
502 t.Parallel()
503
504 ln := newLocalListener(t, "tcp")
505 defer ln.Close()
506
507 for i, tt := range writeTimeoutTests {
508 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
509 if err != nil {
510 t.Fatal(err)
511 }
512 defer c.Close()
513
514 if err := c.SetWriteDeadline(time.Now().Add(tt.timeout)); err != nil {
515 t.Fatalf("#%d: %v", i, err)
516 }
517 for j, xerr := range tt.xerrs {
518 for {
519 n, err := c.Write([]byte("WRITE TIMEOUT TEST"))
520 if xerr != nil {
521 if perr := parseWriteError(err); perr != nil {
522 t.Errorf("#%d/%d: %v", i, j, perr)
523 }
524 if !isDeadlineExceeded(err) {
525 t.Fatalf("#%d/%d: %v", i, j, err)
526 }
527 }
528 if err == nil {
529 time.Sleep(tt.timeout / 3)
530 continue
531 }
532 if n != 0 {
533 t.Fatalf("#%d/%d: wrote %d; want 0", i, j, n)
534 }
535 break
536 }
537 }
538 }
539 }
540
541
542 func TestWriteTimeoutMustNotReturn(t *testing.T) {
543 t.Parallel()
544
545 switch runtime.GOOS {
546 case "plan9":
547 t.Skipf("not supported on %s", runtime.GOOS)
548 }
549
550 ln := newLocalListener(t, "tcp")
551 defer ln.Close()
552
553 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
554 if err != nil {
555 t.Fatal(err)
556 }
557 defer c.Close()
558
559 maxch := make(chan *time.Timer)
560 ch := make(chan error)
561 go func() {
562 if err := c.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil {
563 t.Error(err)
564 }
565 if err := c.SetReadDeadline(time.Now().Add(-5 * time.Second)); err != nil {
566 t.Error(err)
567 }
568 if err := c.SetWriteDeadline(noDeadline); err != nil {
569 t.Error(err)
570 }
571 maxch <- time.NewTimer(100 * time.Millisecond)
572 var b [1024]byte
573 for {
574 if _, err := c.Write(b[:]); err != nil {
575 ch <- err
576 break
577 }
578 }
579 }()
580
581 max := <-maxch
582 defer max.Stop()
583
584 select {
585 case err := <-ch:
586 if perr := parseWriteError(err); perr != nil {
587 t.Error(perr)
588 }
589 t.Fatalf("expected Write to not return, but it returned with %v", err)
590 case <-max.C:
591 c.Close()
592 err := <-ch
593 if perr := parseWriteError(err); perr != nil {
594 t.Error(perr)
595 }
596 if nerr, ok := err.(Error); !ok || nerr.Timeout() || nerr.Temporary() {
597 t.Fatal(err)
598 }
599 }
600 }
601
602 func TestWriteToTimeout(t *testing.T) {
603 t.Parallel()
604
605 c1 := newLocalPacketListener(t, "udp")
606 defer c1.Close()
607
608 host, _, err := SplitHostPort(c1.LocalAddr().String())
609 if err != nil {
610 t.Fatal(err)
611 }
612
613 timeouts := []time.Duration{
614 -5 * time.Second,
615 10 * time.Millisecond,
616 }
617
618 for _, timeout := range timeouts {
619 t.Run(fmt.Sprint(timeout), func(t *testing.T) {
620 c2, err := ListenPacket(c1.LocalAddr().Network(), JoinHostPort(host, "0"))
621 if err != nil {
622 t.Fatal(err)
623 }
624 defer c2.Close()
625
626 if err := c2.SetWriteDeadline(time.Now().Add(timeout)); err != nil {
627 t.Fatalf("SetWriteDeadline: %v", err)
628 }
629 backoff := 1 * time.Millisecond
630 nDeadlineExceeded := 0
631 for j := 0; nDeadlineExceeded < 2; j++ {
632 n, err := c2.WriteTo([]byte("WRITETO TIMEOUT TEST"), c1.LocalAddr())
633 t.Logf("#%d: WriteTo: %d, %v", j, n, err)
634 if err == nil && timeout >= 0 && nDeadlineExceeded == 0 {
635
636
637 t.Logf("WriteTo succeeded; sleeping %v", timeout/3)
638 time.Sleep(timeout / 3)
639 continue
640 }
641 if isENOBUFS(err) {
642 t.Logf("WriteTo: %v", err)
643
644
645
646 time.Sleep(backoff)
647 backoff *= 2
648 continue
649 }
650 if perr := parseWriteError(err); perr != nil {
651 t.Errorf("failed to parse error: %v", perr)
652 }
653 if !isDeadlineExceeded(err) {
654 t.Errorf("error is not 'deadline exceeded'")
655 }
656 if n != 0 {
657 t.Errorf("unexpectedly wrote %d bytes", n)
658 }
659 if !t.Failed() {
660 t.Logf("WriteTo timed out as expected")
661 }
662 nDeadlineExceeded++
663 }
664 })
665 }
666 }
667
668 const (
669
670
671
672
673
674
675 minDynamicTimeout = 1 * time.Millisecond
676
677
678
679
680
681
682
683 maxDynamicTimeout = 4 * time.Second
684 )
685
686
687
688 func timeoutUpperBound(d time.Duration) time.Duration {
689 switch runtime.GOOS {
690 case "openbsd", "netbsd":
691
692
693
694
695
696
697
698 return d * 3 / 2
699 }
700
701
702 return d * 11 / 10
703 }
704
705
706
707 func nextTimeout(actual time.Duration) (next time.Duration, ok bool) {
708 if actual >= maxDynamicTimeout {
709 return maxDynamicTimeout, false
710 }
711
712
713
714 next = actual * 5 / 4
715 if next > maxDynamicTimeout {
716 return maxDynamicTimeout, true
717 }
718 return next, true
719 }
720
721
722 func TestReadTimeoutFluctuation(t *testing.T) {
723 ln := newLocalListener(t, "tcp")
724 defer ln.Close()
725
726 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
727 if err != nil {
728 t.Fatal(err)
729 }
730 defer c.Close()
731
732 d := minDynamicTimeout
733 b := make([]byte, 256)
734 for {
735 t.Logf("SetReadDeadline(+%v)", d)
736 t0 := time.Now()
737 deadline := t0.Add(d)
738 if err = c.SetReadDeadline(deadline); err != nil {
739 t.Fatalf("SetReadDeadline(%v): %v", deadline, err)
740 }
741 var n int
742 n, err = c.Read(b)
743 t1 := time.Now()
744
745 if n != 0 || err == nil || !err.(Error).Timeout() {
746 t.Errorf("Read did not return (0, timeout): (%d, %v)", n, err)
747 }
748 if perr := parseReadError(err); perr != nil {
749 t.Error(perr)
750 }
751 if !isDeadlineExceeded(err) {
752 t.Errorf("Read error is not DeadlineExceeded: %v", err)
753 }
754
755 actual := t1.Sub(t0)
756 if t1.Before(deadline) {
757 t.Errorf("Read took %s; expected at least %s", actual, d)
758 }
759 if t.Failed() {
760 return
761 }
762 if want := timeoutUpperBound(d); actual > want {
763 next, ok := nextTimeout(actual)
764 if !ok {
765 t.Fatalf("Read took %s; expected at most %v", actual, want)
766 }
767
768
769 t.Logf("Read took %s (expected %s); trying with longer timeout", actual, d)
770 d = next
771 continue
772 }
773
774 break
775 }
776 }
777
778
779 func TestReadFromTimeoutFluctuation(t *testing.T) {
780 c1 := newLocalPacketListener(t, "udp")
781 defer c1.Close()
782
783 c2, err := Dial(c1.LocalAddr().Network(), c1.LocalAddr().String())
784 if err != nil {
785 t.Fatal(err)
786 }
787 defer c2.Close()
788
789 d := minDynamicTimeout
790 b := make([]byte, 256)
791 for {
792 t.Logf("SetReadDeadline(+%v)", d)
793 t0 := time.Now()
794 deadline := t0.Add(d)
795 if err = c2.SetReadDeadline(deadline); err != nil {
796 t.Fatalf("SetReadDeadline(%v): %v", deadline, err)
797 }
798 var n int
799 n, _, err = c2.(PacketConn).ReadFrom(b)
800 t1 := time.Now()
801
802 if n != 0 || err == nil || !err.(Error).Timeout() {
803 t.Errorf("ReadFrom did not return (0, timeout): (%d, %v)", n, err)
804 }
805 if perr := parseReadError(err); perr != nil {
806 t.Error(perr)
807 }
808 if !isDeadlineExceeded(err) {
809 t.Errorf("ReadFrom error is not DeadlineExceeded: %v", err)
810 }
811
812 actual := t1.Sub(t0)
813 if t1.Before(deadline) {
814 t.Errorf("ReadFrom took %s; expected at least %s", actual, d)
815 }
816 if t.Failed() {
817 return
818 }
819 if want := timeoutUpperBound(d); actual > want {
820 next, ok := nextTimeout(actual)
821 if !ok {
822 t.Fatalf("ReadFrom took %s; expected at most %s", actual, want)
823 }
824
825
826 t.Logf("ReadFrom took %s (expected %s); trying with longer timeout", actual, d)
827 d = next
828 continue
829 }
830
831 break
832 }
833 }
834
835 func TestWriteTimeoutFluctuation(t *testing.T) {
836 switch runtime.GOOS {
837 case "plan9":
838 t.Skipf("not supported on %s", runtime.GOOS)
839 }
840
841 ln := newLocalListener(t, "tcp")
842 defer ln.Close()
843
844 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
845 if err != nil {
846 t.Fatal(err)
847 }
848 defer c.Close()
849
850 d := minDynamicTimeout
851 for {
852 t.Logf("SetWriteDeadline(+%v)", d)
853 t0 := time.Now()
854 deadline := t0.Add(d)
855 if err := c.SetWriteDeadline(deadline); err != nil {
856 t.Fatalf("SetWriteDeadline(%v): %v", deadline, err)
857 }
858 var n int64
859 var err error
860 for {
861 var dn int
862 dn, err = c.Write([]byte("TIMEOUT TRANSMITTER"))
863 n += int64(dn)
864 if err != nil {
865 break
866 }
867 }
868 t1 := time.Now()
869
870 if !err.(Error).Timeout() {
871 t.Fatalf("Write did not return (any, timeout): (%d, %v)", n, err)
872 }
873 if perr := parseWriteError(err); perr != nil {
874 t.Error(perr)
875 }
876 if !isDeadlineExceeded(err) {
877 t.Errorf("Write error is not DeadlineExceeded: %v", err)
878 }
879
880 actual := t1.Sub(t0)
881 if t1.Before(deadline) {
882 t.Errorf("Write took %s; expected at least %s", actual, d)
883 }
884 if t.Failed() {
885 return
886 }
887 if want := timeoutUpperBound(d); actual > want {
888 if n > 0 {
889
890
891
892
893 t.Logf("Wrote %d bytes into send buffer; retrying until buffer is full", n)
894 if d <= maxDynamicTimeout/2 {
895
896
897
898 d *= 2
899 }
900 } else if next, ok := nextTimeout(actual); !ok {
901 t.Fatalf("Write took %s; expected at most %s", actual, want)
902 } else {
903
904
905 t.Logf("Write took %s (expected %s); trying with longer timeout", actual, d)
906 d = next
907 }
908 continue
909 }
910
911 break
912 }
913 }
914
915
916 func TestVariousDeadlines(t *testing.T) {
917 t.Parallel()
918 testVariousDeadlines(t)
919 }
920
921
922 func TestVariousDeadlines1Proc(t *testing.T) {
923
924 if testing.Short() {
925 t.Skip("skipping in short mode")
926 }
927 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
928 testVariousDeadlines(t)
929 }
930
931
932 func TestVariousDeadlines4Proc(t *testing.T) {
933
934 if testing.Short() {
935 t.Skip("skipping in short mode")
936 }
937 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
938 testVariousDeadlines(t)
939 }
940
941 func testVariousDeadlines(t *testing.T) {
942 handler := func(ls *localServer, ln Listener) {
943 for {
944 c, err := ln.Accept()
945 if err != nil {
946 break
947 }
948 c.Read(make([]byte, 1))
949 c.Close()
950 }
951 }
952 ls := newLocalServer(t, "tcp")
953 defer ls.teardown()
954 if err := ls.buildup(handler); err != nil {
955 t.Fatal(err)
956 }
957
958 for _, timeout := range []time.Duration{
959 1 * time.Nanosecond,
960 2 * time.Nanosecond,
961 5 * time.Nanosecond,
962 50 * time.Nanosecond,
963 100 * time.Nanosecond,
964 200 * time.Nanosecond,
965 500 * time.Nanosecond,
966 750 * time.Nanosecond,
967 1 * time.Microsecond,
968 5 * time.Microsecond,
969 25 * time.Microsecond,
970 250 * time.Microsecond,
971 500 * time.Microsecond,
972 1 * time.Millisecond,
973 5 * time.Millisecond,
974 100 * time.Millisecond,
975 250 * time.Millisecond,
976 500 * time.Millisecond,
977 1 * time.Second,
978 } {
979 numRuns := 3
980 if testing.Short() {
981 numRuns = 1
982 if timeout > 500*time.Microsecond {
983 continue
984 }
985 }
986 for run := 0; run < numRuns; run++ {
987 name := fmt.Sprintf("%v %d/%d", timeout, run, numRuns)
988 t.Log(name)
989
990 c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
991 if err != nil {
992 t.Fatal(err)
993 }
994
995 t0 := time.Now()
996 if err := c.SetDeadline(t0.Add(timeout)); err != nil {
997 t.Error(err)
998 }
999 n, err := io.Copy(io.Discard, c)
1000 dt := time.Since(t0)
1001 c.Close()
1002
1003 if nerr, ok := err.(Error); ok && nerr.Timeout() {
1004 t.Logf("%v: good timeout after %v; %d bytes", name, dt, n)
1005 } else {
1006 t.Fatalf("%v: Copy = %d, %v; want timeout", name, n, err)
1007 }
1008 }
1009 }
1010 }
1011
1012
1013
1014 func TestReadWriteProlongedTimeout(t *testing.T) {
1015 t.Parallel()
1016
1017 switch runtime.GOOS {
1018 case "plan9":
1019 t.Skipf("not supported on %s", runtime.GOOS)
1020 }
1021
1022 handler := func(ls *localServer, ln Listener) {
1023 c, err := ln.Accept()
1024 if err != nil {
1025 t.Error(err)
1026 return
1027 }
1028 defer c.Close()
1029
1030 var wg sync.WaitGroup
1031 wg.Add(2)
1032 go func() {
1033 defer wg.Done()
1034 var b [1]byte
1035 for {
1036 if err := c.SetReadDeadline(time.Now().Add(time.Hour)); err != nil {
1037 if perr := parseCommonError(err); perr != nil {
1038 t.Error(perr)
1039 }
1040 t.Error(err)
1041 return
1042 }
1043 if _, err := c.Read(b[:]); err != nil {
1044 if perr := parseReadError(err); perr != nil {
1045 t.Error(perr)
1046 }
1047 return
1048 }
1049 }
1050 }()
1051 go func() {
1052 defer wg.Done()
1053 var b [1]byte
1054 for {
1055 if err := c.SetWriteDeadline(time.Now().Add(time.Hour)); err != nil {
1056 if perr := parseCommonError(err); perr != nil {
1057 t.Error(perr)
1058 }
1059 t.Error(err)
1060 return
1061 }
1062 if _, err := c.Write(b[:]); err != nil {
1063 if perr := parseWriteError(err); perr != nil {
1064 t.Error(perr)
1065 }
1066 return
1067 }
1068 }
1069 }()
1070 wg.Wait()
1071 }
1072 ls := newLocalServer(t, "tcp")
1073 defer ls.teardown()
1074 if err := ls.buildup(handler); err != nil {
1075 t.Fatal(err)
1076 }
1077
1078 c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
1079 if err != nil {
1080 t.Fatal(err)
1081 }
1082 defer c.Close()
1083
1084 var b [1]byte
1085 for i := 0; i < 1000; i++ {
1086 c.Write(b[:])
1087 c.Read(b[:])
1088 }
1089 }
1090
1091
1092 func TestReadWriteDeadlineRace(t *testing.T) {
1093 t.Parallel()
1094
1095 N := 1000
1096 if testing.Short() {
1097 N = 50
1098 }
1099
1100 ln := newLocalListener(t, "tcp")
1101 defer ln.Close()
1102
1103 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
1104 if err != nil {
1105 t.Fatal(err)
1106 }
1107 defer c.Close()
1108
1109 var wg sync.WaitGroup
1110 wg.Add(3)
1111 go func() {
1112 defer wg.Done()
1113 tic := time.NewTicker(2 * time.Microsecond)
1114 defer tic.Stop()
1115 for i := 0; i < N; i++ {
1116 if err := c.SetReadDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
1117 if perr := parseCommonError(err); perr != nil {
1118 t.Error(perr)
1119 }
1120 break
1121 }
1122 if err := c.SetWriteDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
1123 if perr := parseCommonError(err); perr != nil {
1124 t.Error(perr)
1125 }
1126 break
1127 }
1128 <-tic.C
1129 }
1130 }()
1131 go func() {
1132 defer wg.Done()
1133 var b [1]byte
1134 for i := 0; i < N; i++ {
1135 c.Read(b[:])
1136 }
1137 }()
1138 go func() {
1139 defer wg.Done()
1140 var b [1]byte
1141 for i := 0; i < N; i++ {
1142 c.Write(b[:])
1143 }
1144 }()
1145 wg.Wait()
1146 }
1147
1148
1149 func TestConcurrentSetDeadline(t *testing.T) {
1150 ln := newLocalListener(t, "tcp")
1151 defer ln.Close()
1152
1153 const goroutines = 8
1154 const conns = 10
1155 const tries = 100
1156
1157 var c [conns]Conn
1158 for i := 0; i < conns; i++ {
1159 var err error
1160 c[i], err = Dial(ln.Addr().Network(), ln.Addr().String())
1161 if err != nil {
1162 t.Fatal(err)
1163 }
1164 defer c[i].Close()
1165 }
1166
1167 var wg sync.WaitGroup
1168 wg.Add(goroutines)
1169 now := time.Now()
1170 for i := 0; i < goroutines; i++ {
1171 go func(i int) {
1172 defer wg.Done()
1173
1174
1175 for j := tries; j > 0; j-- {
1176 for k := 0; k < conns; k++ {
1177 c[k].SetReadDeadline(now.Add(2*time.Hour + time.Duration(i*j*k)*time.Second))
1178 c[k].SetWriteDeadline(now.Add(1*time.Hour + time.Duration(i*j*k)*time.Second))
1179 }
1180 }
1181 }(i)
1182 }
1183 wg.Wait()
1184 }
1185
1186
1187
1188
1189 func isDeadlineExceeded(err error) bool {
1190 nerr, ok := err.(Error)
1191 if !ok {
1192 return false
1193 }
1194 if !nerr.Timeout() {
1195 return false
1196 }
1197 if !errors.Is(err, os.ErrDeadlineExceeded) {
1198 return false
1199 }
1200 return true
1201 }
1202
View as plain text