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