]> Cypherpunks.ru repositories - gostls13.git/blob - src/net/timeout_test.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / net / timeout_test.go
1 // Copyright 2009 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.
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         // Install a hook to ensure that a 1ns timeout will always
21         // be exceeded by the time Dial gets to the relevant system call.
22         //
23         // Without this, systems with a very large timer granularity — such as
24         // Windows — may be able to accept connections without measurably exceeding
25         // even an implausibly short deadline.
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 // for deadline
37 }{
38         // Tests that dial timeouts, deadlines in the past work.
39         {-5 * time.Second, 0},
40         {0, -5 * time.Second},
41         {-5 * time.Second, 5 * time.Second}, // timeout over deadline
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}, // timeout over deadline
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                         // We don't run these subtests in parallel because we don't know how big
68                         // the kernel's accept queue is, and we don't want to accidentally saturate
69                         // it with concurrent calls. (That could cause the Dial to fail with
70                         // ECONNREFUSED or ECONNRESET instead of a timeout error.)
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                                 // Even though we're not calling Accept on the Listener, the kernel may
95                                 // spuriously accept connections on its behalf. If that happens, we will
96                                 // close the connection (to try to get it out of the kernel's accept
97                                 // queue) and try a shorter timeout.
98                                 //
99                                 // We assume that we will reach a point where the call actually does
100                                 // time out, although in theory (since this socket is on a loopback
101                                 // address) a sufficiently clever kernel could notice that no Accept
102                                 // call is pending and bypass both the queue and the timeout to return
103                                 // another error immediately.
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 // for deadline
148         }{
149                 // Large timeouts that will overflow an int64 unix nanos.
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 // expected errors in transition
172 }{
173         // Tests that accept deadlines in the past work, even if
174         // there's incoming connections available.
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         max := time.NewTimer(time.Second)
246         defer max.Stop()
247         ch := make(chan error)
248         go func() {
249                 if err := ln.(*TCPListener).SetDeadline(noDeadline); err != nil {
250                         t.Error(err)
251                 }
252                 if err := ln.(*TCPListener).SetDeadline(time.Now().Add(10 * time.Millisecond)); err != nil {
253                         t.Error(err)
254                 }
255                 c, err := ln.Accept()
256                 if err == nil {
257                         c.Close()
258                 }
259                 ch <- err
260         }()
261
262         select {
263         case <-max.C:
264                 ln.Close()
265                 <-ch // wait for tester goroutine to stop
266                 t.Fatal("Accept didn't return in an expected time")
267         case err := <-ch:
268                 if perr := parseAcceptError(err); perr != nil {
269                         t.Error(perr)
270                 }
271                 if !isDeadlineExceeded(err) {
272                         t.Fatal(err)
273                 }
274         }
275 }
276
277 func TestAcceptTimeoutMustNotReturn(t *testing.T) {
278         t.Parallel()
279
280         switch runtime.GOOS {
281         case "plan9":
282                 t.Skipf("not supported on %s", runtime.GOOS)
283         }
284
285         ln := newLocalListener(t, "tcp")
286         defer ln.Close()
287
288         maxch := make(chan *time.Timer)
289         ch := make(chan error)
290         go func() {
291                 if err := ln.(*TCPListener).SetDeadline(time.Now().Add(-5 * time.Second)); err != nil {
292                         t.Error(err)
293                 }
294                 if err := ln.(*TCPListener).SetDeadline(noDeadline); err != nil {
295                         t.Error(err)
296                 }
297                 maxch <- time.NewTimer(100 * time.Millisecond)
298                 _, err := ln.Accept()
299                 ch <- err
300         }()
301
302         max := <-maxch
303         defer max.Stop()
304
305         select {
306         case err := <-ch:
307                 if perr := parseAcceptError(err); perr != nil {
308                         t.Error(perr)
309                 }
310                 t.Fatalf("expected Accept to not return, but it returned with %v", err)
311         case <-max.C:
312                 ln.Close()
313                 <-ch // wait for tester goroutine to stop
314         }
315 }
316
317 var readTimeoutTests = []struct {
318         timeout time.Duration
319         xerrs   [2]error // expected errors in transition
320 }{
321         // Tests that read deadlines work, even if there's data ready
322         // to be read.
323         {-5 * time.Second, [2]error{os.ErrDeadlineExceeded, os.ErrDeadlineExceeded}},
324
325         {50 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
326 }
327
328 // There is a very similar copy of this in os/timeout_test.go.
329 func TestReadTimeout(t *testing.T) {
330         handler := func(ls *localServer, ln Listener) {
331                 c, err := ln.Accept()
332                 if err != nil {
333                         t.Error(err)
334                         return
335                 }
336                 c.Write([]byte("READ TIMEOUT TEST"))
337                 defer c.Close()
338         }
339         ls := newLocalServer(t, "tcp")
340         defer ls.teardown()
341         if err := ls.buildup(handler); err != nil {
342                 t.Fatal(err)
343         }
344
345         c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
346         if err != nil {
347                 t.Fatal(err)
348         }
349         defer c.Close()
350
351         for i, tt := range readTimeoutTests {
352                 if err := c.SetReadDeadline(time.Now().Add(tt.timeout)); err != nil {
353                         t.Fatalf("#%d: %v", i, err)
354                 }
355                 var b [1]byte
356                 for j, xerr := range tt.xerrs {
357                         for {
358                                 n, err := c.Read(b[:])
359                                 if xerr != nil {
360                                         if perr := parseReadError(err); perr != nil {
361                                                 t.Errorf("#%d/%d: %v", i, j, perr)
362                                         }
363                                         if !isDeadlineExceeded(err) {
364                                                 t.Fatalf("#%d/%d: %v", i, j, err)
365                                         }
366                                 }
367                                 if err == nil {
368                                         time.Sleep(tt.timeout / 3)
369                                         continue
370                                 }
371                                 if n != 0 {
372                                         t.Fatalf("#%d/%d: read %d; want 0", i, j, n)
373                                 }
374                                 break
375                         }
376                 }
377         }
378 }
379
380 // There is a very similar copy of this in os/timeout_test.go.
381 func TestReadTimeoutMustNotReturn(t *testing.T) {
382         t.Parallel()
383
384         switch runtime.GOOS {
385         case "plan9":
386                 t.Skipf("not supported on %s", runtime.GOOS)
387         }
388
389         ln := newLocalListener(t, "tcp")
390         defer ln.Close()
391
392         c, err := Dial(ln.Addr().Network(), ln.Addr().String())
393         if err != nil {
394                 t.Fatal(err)
395         }
396         defer c.Close()
397
398         maxch := make(chan *time.Timer)
399         ch := make(chan error)
400         go func() {
401                 if err := c.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil {
402                         t.Error(err)
403                 }
404                 if err := c.SetWriteDeadline(time.Now().Add(-5 * time.Second)); err != nil {
405                         t.Error(err)
406                 }
407                 if err := c.SetReadDeadline(noDeadline); err != nil {
408                         t.Error(err)
409                 }
410                 maxch <- time.NewTimer(100 * time.Millisecond)
411                 var b [1]byte
412                 _, err := c.Read(b[:])
413                 ch <- err
414         }()
415
416         max := <-maxch
417         defer max.Stop()
418
419         select {
420         case err := <-ch:
421                 if perr := parseReadError(err); perr != nil {
422                         t.Error(perr)
423                 }
424                 t.Fatalf("expected Read to not return, but it returned with %v", err)
425         case <-max.C:
426                 c.Close()
427                 err := <-ch // wait for tester goroutine to stop
428                 if perr := parseReadError(err); perr != nil {
429                         t.Error(perr)
430                 }
431                 if nerr, ok := err.(Error); !ok || nerr.Timeout() || nerr.Temporary() {
432                         t.Fatal(err)
433                 }
434         }
435 }
436
437 var readFromTimeoutTests = []struct {
438         timeout time.Duration
439         xerrs   [2]error // expected errors in transition
440 }{
441         // Tests that read deadlines work, even if there's data ready
442         // to be read.
443         {-5 * time.Second, [2]error{os.ErrDeadlineExceeded, os.ErrDeadlineExceeded}},
444
445         {50 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
446 }
447
448 func TestReadFromTimeout(t *testing.T) {
449         ch := make(chan Addr)
450         defer close(ch)
451         handler := func(ls *localPacketServer, c PacketConn) {
452                 if dst, ok := <-ch; ok {
453                         c.WriteTo([]byte("READFROM TIMEOUT TEST"), dst)
454                 }
455         }
456         ls := newLocalPacketServer(t, "udp")
457         defer ls.teardown()
458         if err := ls.buildup(handler); err != nil {
459                 t.Fatal(err)
460         }
461
462         host, _, err := SplitHostPort(ls.PacketConn.LocalAddr().String())
463         if err != nil {
464                 t.Fatal(err)
465         }
466         c, err := ListenPacket(ls.PacketConn.LocalAddr().Network(), JoinHostPort(host, "0"))
467         if err != nil {
468                 t.Fatal(err)
469         }
470         defer c.Close()
471         ch <- c.LocalAddr()
472
473         for i, tt := range readFromTimeoutTests {
474                 if err := c.SetReadDeadline(time.Now().Add(tt.timeout)); err != nil {
475                         t.Fatalf("#%d: %v", i, err)
476                 }
477                 var b [1]byte
478                 for j, xerr := range tt.xerrs {
479                         for {
480                                 n, _, err := c.ReadFrom(b[:])
481                                 if xerr != nil {
482                                         if perr := parseReadError(err); perr != nil {
483                                                 t.Errorf("#%d/%d: %v", i, j, perr)
484                                         }
485                                         if !isDeadlineExceeded(err) {
486                                                 t.Fatalf("#%d/%d: %v", i, j, err)
487                                         }
488                                 }
489                                 if err == nil {
490                                         time.Sleep(tt.timeout / 3)
491                                         continue
492                                 }
493                                 if nerr, ok := err.(Error); ok && nerr.Timeout() && n != 0 {
494                                         t.Fatalf("#%d/%d: read %d; want 0", i, j, n)
495                                 }
496                                 break
497                         }
498                 }
499         }
500 }
501
502 var writeTimeoutTests = []struct {
503         timeout time.Duration
504         xerrs   [2]error // expected errors in transition
505 }{
506         // Tests that write deadlines work, even if there's buffer
507         // space available to write.
508         {-5 * time.Second, [2]error{os.ErrDeadlineExceeded, os.ErrDeadlineExceeded}},
509
510         {10 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
511 }
512
513 // There is a very similar copy of this in os/timeout_test.go.
514 func TestWriteTimeout(t *testing.T) {
515         t.Parallel()
516
517         ln := newLocalListener(t, "tcp")
518         defer ln.Close()
519
520         for i, tt := range writeTimeoutTests {
521                 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
522                 if err != nil {
523                         t.Fatal(err)
524                 }
525                 defer c.Close()
526
527                 if err := c.SetWriteDeadline(time.Now().Add(tt.timeout)); err != nil {
528                         t.Fatalf("#%d: %v", i, err)
529                 }
530                 for j, xerr := range tt.xerrs {
531                         for {
532                                 n, err := c.Write([]byte("WRITE TIMEOUT TEST"))
533                                 if xerr != nil {
534                                         if perr := parseWriteError(err); perr != nil {
535                                                 t.Errorf("#%d/%d: %v", i, j, perr)
536                                         }
537                                         if !isDeadlineExceeded(err) {
538                                                 t.Fatalf("#%d/%d: %v", i, j, err)
539                                         }
540                                 }
541                                 if err == nil {
542                                         time.Sleep(tt.timeout / 3)
543                                         continue
544                                 }
545                                 if n != 0 {
546                                         t.Fatalf("#%d/%d: wrote %d; want 0", i, j, n)
547                                 }
548                                 break
549                         }
550                 }
551         }
552 }
553
554 // There is a very similar copy of this in os/timeout_test.go.
555 func TestWriteTimeoutMustNotReturn(t *testing.T) {
556         t.Parallel()
557
558         switch runtime.GOOS {
559         case "plan9":
560                 t.Skipf("not supported on %s", runtime.GOOS)
561         }
562
563         ln := newLocalListener(t, "tcp")
564         defer ln.Close()
565
566         c, err := Dial(ln.Addr().Network(), ln.Addr().String())
567         if err != nil {
568                 t.Fatal(err)
569         }
570         defer c.Close()
571
572         maxch := make(chan *time.Timer)
573         ch := make(chan error)
574         go func() {
575                 if err := c.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil {
576                         t.Error(err)
577                 }
578                 if err := c.SetReadDeadline(time.Now().Add(-5 * time.Second)); err != nil {
579                         t.Error(err)
580                 }
581                 if err := c.SetWriteDeadline(noDeadline); err != nil {
582                         t.Error(err)
583                 }
584                 maxch <- time.NewTimer(100 * time.Millisecond)
585                 var b [1024]byte
586                 for {
587                         if _, err := c.Write(b[:]); err != nil {
588                                 ch <- err
589                                 break
590                         }
591                 }
592         }()
593
594         max := <-maxch
595         defer max.Stop()
596
597         select {
598         case err := <-ch:
599                 if perr := parseWriteError(err); perr != nil {
600                         t.Error(perr)
601                 }
602                 t.Fatalf("expected Write to not return, but it returned with %v", err)
603         case <-max.C:
604                 c.Close()
605                 err := <-ch // wait for tester goroutine to stop
606                 if perr := parseWriteError(err); perr != nil {
607                         t.Error(perr)
608                 }
609                 if nerr, ok := err.(Error); !ok || nerr.Timeout() || nerr.Temporary() {
610                         t.Fatal(err)
611                 }
612         }
613 }
614
615 func TestWriteToTimeout(t *testing.T) {
616         t.Parallel()
617
618         c1 := newLocalPacketListener(t, "udp")
619         defer c1.Close()
620
621         host, _, err := SplitHostPort(c1.LocalAddr().String())
622         if err != nil {
623                 t.Fatal(err)
624         }
625
626         timeouts := []time.Duration{
627                 -5 * time.Second,
628                 10 * time.Millisecond,
629         }
630
631         for _, timeout := range timeouts {
632                 t.Run(fmt.Sprint(timeout), func(t *testing.T) {
633                         c2, err := ListenPacket(c1.LocalAddr().Network(), JoinHostPort(host, "0"))
634                         if err != nil {
635                                 t.Fatal(err)
636                         }
637                         defer c2.Close()
638
639                         if err := c2.SetWriteDeadline(time.Now().Add(timeout)); err != nil {
640                                 t.Fatalf("SetWriteDeadline: %v", err)
641                         }
642                         backoff := 1 * time.Millisecond
643                         nDeadlineExceeded := 0
644                         for j := 0; nDeadlineExceeded < 2; j++ {
645                                 n, err := c2.WriteTo([]byte("WRITETO TIMEOUT TEST"), c1.LocalAddr())
646                                 t.Logf("#%d: WriteTo: %d, %v", j, n, err)
647                                 if err == nil && timeout >= 0 && nDeadlineExceeded == 0 {
648                                         // If the timeout is nonnegative, some number of WriteTo calls may
649                                         // succeed before the timeout takes effect.
650                                         t.Logf("WriteTo succeeded; sleeping %v", timeout/3)
651                                         time.Sleep(timeout / 3)
652                                         continue
653                                 }
654                                 if isENOBUFS(err) {
655                                         t.Logf("WriteTo: %v", err)
656                                         // We're looking for a deadline exceeded error, but if the kernel's
657                                         // network buffers are saturated we may see ENOBUFS instead (see
658                                         // https://go.dev/issue/49930). Give it some time to unsaturate.
659                                         time.Sleep(backoff)
660                                         backoff *= 2
661                                         continue
662                                 }
663                                 if perr := parseWriteError(err); perr != nil {
664                                         t.Errorf("failed to parse error: %v", perr)
665                                 }
666                                 if !isDeadlineExceeded(err) {
667                                         t.Errorf("error is not 'deadline exceeded'")
668                                 }
669                                 if n != 0 {
670                                         t.Errorf("unexpectedly wrote %d bytes", n)
671                                 }
672                                 if !t.Failed() {
673                                         t.Logf("WriteTo timed out as expected")
674                                 }
675                                 nDeadlineExceeded++
676                         }
677                 })
678         }
679 }
680
681 const (
682         // minDynamicTimeout is the minimum timeout to attempt for
683         // tests that automatically increase timeouts until success.
684         //
685         // Lower values may allow tests to succeed more quickly if the value is close
686         // to the true minimum, but may require more iterations (and waste more time
687         // and CPU power on failed attempts) if the timeout is too low.
688         minDynamicTimeout = 1 * time.Millisecond
689
690         // maxDynamicTimeout is the maximum timeout to attempt for
691         // tests that automatically increase timeouts until success.
692         //
693         // This should be a strict upper bound on the latency required to hit a
694         // timeout accurately, even on a slow or heavily-loaded machine. If a test
695         // would increase the timeout beyond this value, the test fails.
696         maxDynamicTimeout = 4 * time.Second
697 )
698
699 // timeoutUpperBound returns the maximum time that we expect a timeout of
700 // duration d to take to return the caller.
701 func timeoutUpperBound(d time.Duration) time.Duration {
702         switch runtime.GOOS {
703         case "openbsd", "netbsd":
704                 // NetBSD and OpenBSD seem to be unable to reliably hit deadlines even when
705                 // the absolute durations are long.
706                 // In https://build.golang.org/log/c34f8685d020b98377dd4988cd38f0c5bd72267e,
707                 // we observed that an openbsd-amd64-68 builder took 4.090948779s for a
708                 // 2.983020682s timeout (37.1% overhead).
709                 // (See https://go.dev/issue/50189 for further detail.)
710                 // Give them lots of slop to compensate.
711                 return d * 3 / 2
712         }
713         // Other platforms seem to hit their deadlines more reliably,
714         // at least when they are long enough to cover scheduling jitter.
715         return d * 11 / 10
716 }
717
718 // nextTimeout returns the next timeout to try after an operation took the given
719 // actual duration with a timeout shorter than that duration.
720 func nextTimeout(actual time.Duration) (next time.Duration, ok bool) {
721         if actual >= maxDynamicTimeout {
722                 return maxDynamicTimeout, false
723         }
724         // Since the previous attempt took actual, we can't expect to beat that
725         // duration by any significant margin. Try the next attempt with an arbitrary
726         // factor above that, so that our growth curve is at least exponential.
727         next = actual * 5 / 4
728         if next > maxDynamicTimeout {
729                 return maxDynamicTimeout, true
730         }
731         return next, true
732 }
733
734 // There is a very similar copy of this in os/timeout_test.go.
735 func TestReadTimeoutFluctuation(t *testing.T) {
736         ln := newLocalListener(t, "tcp")
737         defer ln.Close()
738
739         c, err := Dial(ln.Addr().Network(), ln.Addr().String())
740         if err != nil {
741                 t.Fatal(err)
742         }
743         defer c.Close()
744
745         d := minDynamicTimeout
746         b := make([]byte, 256)
747         for {
748                 t.Logf("SetReadDeadline(+%v)", d)
749                 t0 := time.Now()
750                 deadline := t0.Add(d)
751                 if err = c.SetReadDeadline(deadline); err != nil {
752                         t.Fatalf("SetReadDeadline(%v): %v", deadline, err)
753                 }
754                 var n int
755                 n, err = c.Read(b)
756                 t1 := time.Now()
757
758                 if n != 0 || err == nil || !err.(Error).Timeout() {
759                         t.Errorf("Read did not return (0, timeout): (%d, %v)", n, err)
760                 }
761                 if perr := parseReadError(err); perr != nil {
762                         t.Error(perr)
763                 }
764                 if !isDeadlineExceeded(err) {
765                         t.Errorf("Read error is not DeadlineExceeded: %v", err)
766                 }
767
768                 actual := t1.Sub(t0)
769                 if t1.Before(deadline) {
770                         t.Errorf("Read took %s; expected at least %s", actual, d)
771                 }
772                 if t.Failed() {
773                         return
774                 }
775                 if want := timeoutUpperBound(d); actual > want {
776                         next, ok := nextTimeout(actual)
777                         if !ok {
778                                 t.Fatalf("Read took %s; expected at most %v", actual, want)
779                         }
780                         // Maybe this machine is too slow to reliably schedule goroutines within
781                         // the requested duration. Increase the timeout and try again.
782                         t.Logf("Read took %s (expected %s); trying with longer timeout", actual, d)
783                         d = next
784                         continue
785                 }
786
787                 break
788         }
789 }
790
791 // There is a very similar copy of this in os/timeout_test.go.
792 func TestReadFromTimeoutFluctuation(t *testing.T) {
793         c1 := newLocalPacketListener(t, "udp")
794         defer c1.Close()
795
796         c2, err := Dial(c1.LocalAddr().Network(), c1.LocalAddr().String())
797         if err != nil {
798                 t.Fatal(err)
799         }
800         defer c2.Close()
801
802         d := minDynamicTimeout
803         b := make([]byte, 256)
804         for {
805                 t.Logf("SetReadDeadline(+%v)", d)
806                 t0 := time.Now()
807                 deadline := t0.Add(d)
808                 if err = c2.SetReadDeadline(deadline); err != nil {
809                         t.Fatalf("SetReadDeadline(%v): %v", deadline, err)
810                 }
811                 var n int
812                 n, _, err = c2.(PacketConn).ReadFrom(b)
813                 t1 := time.Now()
814
815                 if n != 0 || err == nil || !err.(Error).Timeout() {
816                         t.Errorf("ReadFrom did not return (0, timeout): (%d, %v)", n, err)
817                 }
818                 if perr := parseReadError(err); perr != nil {
819                         t.Error(perr)
820                 }
821                 if !isDeadlineExceeded(err) {
822                         t.Errorf("ReadFrom error is not DeadlineExceeded: %v", err)
823                 }
824
825                 actual := t1.Sub(t0)
826                 if t1.Before(deadline) {
827                         t.Errorf("ReadFrom took %s; expected at least %s", actual, d)
828                 }
829                 if t.Failed() {
830                         return
831                 }
832                 if want := timeoutUpperBound(d); actual > want {
833                         next, ok := nextTimeout(actual)
834                         if !ok {
835                                 t.Fatalf("ReadFrom took %s; expected at most %s", actual, want)
836                         }
837                         // Maybe this machine is too slow to reliably schedule goroutines within
838                         // the requested duration. Increase the timeout and try again.
839                         t.Logf("ReadFrom took %s (expected %s); trying with longer timeout", actual, d)
840                         d = next
841                         continue
842                 }
843
844                 break
845         }
846 }
847
848 func TestWriteTimeoutFluctuation(t *testing.T) {
849         switch runtime.GOOS {
850         case "plan9":
851                 t.Skipf("not supported on %s", runtime.GOOS)
852         }
853
854         ln := newLocalListener(t, "tcp")
855         defer ln.Close()
856
857         c, err := Dial(ln.Addr().Network(), ln.Addr().String())
858         if err != nil {
859                 t.Fatal(err)
860         }
861         defer c.Close()
862
863         d := minDynamicTimeout
864         for {
865                 t.Logf("SetWriteDeadline(+%v)", d)
866                 t0 := time.Now()
867                 deadline := t0.Add(d)
868                 if err := c.SetWriteDeadline(deadline); err != nil {
869                         t.Fatalf("SetWriteDeadline(%v): %v", deadline, err)
870                 }
871                 var n int64
872                 var err error
873                 for {
874                         var dn int
875                         dn, err = c.Write([]byte("TIMEOUT TRANSMITTER"))
876                         n += int64(dn)
877                         if err != nil {
878                                 break
879                         }
880                 }
881                 t1 := time.Now()
882                 // Inv: err != nil
883                 if !err.(Error).Timeout() {
884                         t.Fatalf("Write did not return (any, timeout): (%d, %v)", n, err)
885                 }
886                 if perr := parseWriteError(err); perr != nil {
887                         t.Error(perr)
888                 }
889                 if !isDeadlineExceeded(err) {
890                         t.Errorf("Write error is not DeadlineExceeded: %v", err)
891                 }
892
893                 actual := t1.Sub(t0)
894                 if t1.Before(deadline) {
895                         t.Errorf("Write took %s; expected at least %s", actual, d)
896                 }
897                 if t.Failed() {
898                         return
899                 }
900                 if want := timeoutUpperBound(d); actual > want {
901                         if n > 0 {
902                                 // SetWriteDeadline specifies a time “after which I/O operations fail
903                                 // instead of blocking”. However, the kernel's send buffer is not yet
904                                 // full, we may be able to write some arbitrary (but finite) number of
905                                 // bytes to it without blocking.
906                                 t.Logf("Wrote %d bytes into send buffer; retrying until buffer is full", n)
907                                 if d <= maxDynamicTimeout/2 {
908                                         // We don't know how long the actual write loop would have taken if
909                                         // the buffer were full, so just guess and double the duration so that
910                                         // the next attempt can make twice as much progress toward filling it.
911                                         d *= 2
912                                 }
913                         } else if next, ok := nextTimeout(actual); !ok {
914                                 t.Fatalf("Write took %s; expected at most %s", actual, want)
915                         } else {
916                                 // Maybe this machine is too slow to reliably schedule goroutines within
917                                 // the requested duration. Increase the timeout and try again.
918                                 t.Logf("Write took %s (expected %s); trying with longer timeout", actual, d)
919                                 d = next
920                         }
921                         continue
922                 }
923
924                 break
925         }
926 }
927
928 // There is a very similar copy of this in os/timeout_test.go.
929 func TestVariousDeadlines(t *testing.T) {
930         t.Parallel()
931         testVariousDeadlines(t)
932 }
933
934 // There is a very similar copy of this in os/timeout_test.go.
935 func TestVariousDeadlines1Proc(t *testing.T) {
936         // Cannot use t.Parallel - modifies global GOMAXPROCS.
937         if testing.Short() {
938                 t.Skip("skipping in short mode")
939         }
940         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
941         testVariousDeadlines(t)
942 }
943
944 // There is a very similar copy of this in os/timeout_test.go.
945 func TestVariousDeadlines4Proc(t *testing.T) {
946         // Cannot use t.Parallel - modifies global GOMAXPROCS.
947         if testing.Short() {
948                 t.Skip("skipping in short mode")
949         }
950         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
951         testVariousDeadlines(t)
952 }
953
954 func testVariousDeadlines(t *testing.T) {
955         handler := func(ls *localServer, ln Listener) {
956                 for {
957                         c, err := ln.Accept()
958                         if err != nil {
959                                 break
960                         }
961                         c.Read(make([]byte, 1)) // wait for client to close connection
962                         c.Close()
963                 }
964         }
965         ls := newLocalServer(t, "tcp")
966         defer ls.teardown()
967         if err := ls.buildup(handler); err != nil {
968                 t.Fatal(err)
969         }
970
971         for _, timeout := range []time.Duration{
972                 1 * time.Nanosecond,
973                 2 * time.Nanosecond,
974                 5 * time.Nanosecond,
975                 50 * time.Nanosecond,
976                 100 * time.Nanosecond,
977                 200 * time.Nanosecond,
978                 500 * time.Nanosecond,
979                 750 * time.Nanosecond,
980                 1 * time.Microsecond,
981                 5 * time.Microsecond,
982                 25 * time.Microsecond,
983                 250 * time.Microsecond,
984                 500 * time.Microsecond,
985                 1 * time.Millisecond,
986                 5 * time.Millisecond,
987                 100 * time.Millisecond,
988                 250 * time.Millisecond,
989                 500 * time.Millisecond,
990                 1 * time.Second,
991         } {
992                 numRuns := 3
993                 if testing.Short() {
994                         numRuns = 1
995                         if timeout > 500*time.Microsecond {
996                                 continue
997                         }
998                 }
999                 for run := 0; run < numRuns; run++ {
1000                         name := fmt.Sprintf("%v %d/%d", timeout, run, numRuns)
1001                         t.Log(name)
1002
1003                         c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
1004                         if err != nil {
1005                                 t.Fatal(err)
1006                         }
1007
1008                         t0 := time.Now()
1009                         if err := c.SetDeadline(t0.Add(timeout)); err != nil {
1010                                 t.Error(err)
1011                         }
1012                         n, err := io.Copy(io.Discard, c)
1013                         dt := time.Since(t0)
1014                         c.Close()
1015
1016                         if nerr, ok := err.(Error); ok && nerr.Timeout() {
1017                                 t.Logf("%v: good timeout after %v; %d bytes", name, dt, n)
1018                         } else {
1019                                 t.Fatalf("%v: Copy = %d, %v; want timeout", name, n, err)
1020                         }
1021                 }
1022         }
1023 }
1024
1025 // TestReadWriteProlongedTimeout tests concurrent deadline
1026 // modification. Known to cause data races in the past.
1027 func TestReadWriteProlongedTimeout(t *testing.T) {
1028         t.Parallel()
1029
1030         switch runtime.GOOS {
1031         case "plan9":
1032                 t.Skipf("not supported on %s", runtime.GOOS)
1033         }
1034
1035         handler := func(ls *localServer, ln Listener) {
1036                 c, err := ln.Accept()
1037                 if err != nil {
1038                         t.Error(err)
1039                         return
1040                 }
1041                 defer c.Close()
1042
1043                 var wg sync.WaitGroup
1044                 wg.Add(2)
1045                 go func() {
1046                         defer wg.Done()
1047                         var b [1]byte
1048                         for {
1049                                 if err := c.SetReadDeadline(time.Now().Add(time.Hour)); err != nil {
1050                                         if perr := parseCommonError(err); perr != nil {
1051                                                 t.Error(perr)
1052                                         }
1053                                         t.Error(err)
1054                                         return
1055                                 }
1056                                 if _, err := c.Read(b[:]); err != nil {
1057                                         if perr := parseReadError(err); perr != nil {
1058                                                 t.Error(perr)
1059                                         }
1060                                         return
1061                                 }
1062                         }
1063                 }()
1064                 go func() {
1065                         defer wg.Done()
1066                         var b [1]byte
1067                         for {
1068                                 if err := c.SetWriteDeadline(time.Now().Add(time.Hour)); err != nil {
1069                                         if perr := parseCommonError(err); perr != nil {
1070                                                 t.Error(perr)
1071                                         }
1072                                         t.Error(err)
1073                                         return
1074                                 }
1075                                 if _, err := c.Write(b[:]); err != nil {
1076                                         if perr := parseWriteError(err); perr != nil {
1077                                                 t.Error(perr)
1078                                         }
1079                                         return
1080                                 }
1081                         }
1082                 }()
1083                 wg.Wait()
1084         }
1085         ls := newLocalServer(t, "tcp")
1086         defer ls.teardown()
1087         if err := ls.buildup(handler); err != nil {
1088                 t.Fatal(err)
1089         }
1090
1091         c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
1092         if err != nil {
1093                 t.Fatal(err)
1094         }
1095         defer c.Close()
1096
1097         var b [1]byte
1098         for i := 0; i < 1000; i++ {
1099                 c.Write(b[:])
1100                 c.Read(b[:])
1101         }
1102 }
1103
1104 // There is a very similar copy of this in os/timeout_test.go.
1105 func TestReadWriteDeadlineRace(t *testing.T) {
1106         t.Parallel()
1107
1108         N := 1000
1109         if testing.Short() {
1110                 N = 50
1111         }
1112
1113         ln := newLocalListener(t, "tcp")
1114         defer ln.Close()
1115
1116         c, err := Dial(ln.Addr().Network(), ln.Addr().String())
1117         if err != nil {
1118                 t.Fatal(err)
1119         }
1120         defer c.Close()
1121
1122         var wg sync.WaitGroup
1123         wg.Add(3)
1124         go func() {
1125                 defer wg.Done()
1126                 tic := time.NewTicker(2 * time.Microsecond)
1127                 defer tic.Stop()
1128                 for i := 0; i < N; i++ {
1129                         if err := c.SetReadDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
1130                                 if perr := parseCommonError(err); perr != nil {
1131                                         t.Error(perr)
1132                                 }
1133                                 break
1134                         }
1135                         if err := c.SetWriteDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
1136                                 if perr := parseCommonError(err); perr != nil {
1137                                         t.Error(perr)
1138                                 }
1139                                 break
1140                         }
1141                         <-tic.C
1142                 }
1143         }()
1144         go func() {
1145                 defer wg.Done()
1146                 var b [1]byte
1147                 for i := 0; i < N; i++ {
1148                         c.Read(b[:]) // ignore possible timeout errors
1149                 }
1150         }()
1151         go func() {
1152                 defer wg.Done()
1153                 var b [1]byte
1154                 for i := 0; i < N; i++ {
1155                         c.Write(b[:]) // ignore possible timeout errors
1156                 }
1157         }()
1158         wg.Wait() // wait for tester goroutine to stop
1159 }
1160
1161 // Issue 35367.
1162 func TestConcurrentSetDeadline(t *testing.T) {
1163         ln := newLocalListener(t, "tcp")
1164         defer ln.Close()
1165
1166         const goroutines = 8
1167         const conns = 10
1168         const tries = 100
1169
1170         var c [conns]Conn
1171         for i := 0; i < conns; i++ {
1172                 var err error
1173                 c[i], err = Dial(ln.Addr().Network(), ln.Addr().String())
1174                 if err != nil {
1175                         t.Fatal(err)
1176                 }
1177                 defer c[i].Close()
1178         }
1179
1180         var wg sync.WaitGroup
1181         wg.Add(goroutines)
1182         now := time.Now()
1183         for i := 0; i < goroutines; i++ {
1184                 go func(i int) {
1185                         defer wg.Done()
1186                         // Make the deadlines steadily earlier,
1187                         // to trigger runtime adjusttimers calls.
1188                         for j := tries; j > 0; j-- {
1189                                 for k := 0; k < conns; k++ {
1190                                         c[k].SetReadDeadline(now.Add(2*time.Hour + time.Duration(i*j*k)*time.Second))
1191                                         c[k].SetWriteDeadline(now.Add(1*time.Hour + time.Duration(i*j*k)*time.Second))
1192                                 }
1193                         }
1194                 }(i)
1195         }
1196         wg.Wait()
1197 }
1198
1199 // isDeadlineExceeded reports whether err is or wraps os.ErrDeadlineExceeded.
1200 // We also check that the error implements net.Error, and that the
1201 // Timeout method returns true.
1202 func isDeadlineExceeded(err error) bool {
1203         nerr, ok := err.(Error)
1204         if !ok {
1205                 return false
1206         }
1207         if !nerr.Timeout() {
1208                 return false
1209         }
1210         if !errors.Is(err, os.ErrDeadlineExceeded) {
1211                 return false
1212         }
1213         return true
1214 }