Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/timeout_test.go

Documentation: net

     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  //go:build !js
     6  // +build !js
     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 // for deadline
    26  
    27  	guard time.Duration
    28  	max   time.Duration
    29  }{
    30  	// Tests that dial timeouts, deadlines in the past work.
    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}, // timeout over deadline
    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}, // timeout over deadline
    40  }
    41  
    42  func TestDialTimeout(t *testing.T) {
    43  	// Cannot use t.Parallel - modifies global hooks.
    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  			// This dial never starts to send any TCP SYN
    72  			// segment because of above socket filter and
    73  			// test hook.
    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 // for deadline
    99  }{
   100  	// Large timeouts that will overflow an int64 unix nanos.
   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 // expected errors in transition
   149  }{
   150  	// Tests that accept deadlines in the past work, even if
   151  	// there's incoming connections available.
   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 // wait for tester goroutine to stop
   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 // wait for tester goroutine to stop
   297  	}
   298  }
   299  
   300  var readTimeoutTests = []struct {
   301  	timeout time.Duration
   302  	xerrs   [2]error // expected errors in transition
   303  }{
   304  	// Tests that read deadlines work, even if there's data ready
   305  	// to be read.
   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 // wait for tester goroutine to stop
   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 // expected errors in transition
   424  }{
   425  	// Tests that read deadlines work, even if there's data ready
   426  	// to be read.
   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 // expected errors in transition
   492  }{
   493  	// Tests that write deadlines work, even if there's buffer
   494  	// space available to write.
   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 // wait for tester goroutine to stop
   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 // expected errors in transition
   606  }{
   607  	// Tests that write deadlines work, even if there's buffer
   608  	// space available to write.
   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 // see golang.org/issue/10775
   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  	// Cannot use t.Parallel - modifies global GOMAXPROCS.
   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  	// Cannot use t.Parallel - modifies global GOMAXPROCS.
   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)) // wait for client to close connection
   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  // TestReadWriteProlongedTimeout tests concurrent deadline
   898  // modification. Known to cause data races in the past.
   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[:]) // ignore possible timeout errors
  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[:]) // ignore possible timeout errors
  1033  		}
  1034  	}()
  1035  	wg.Wait() // wait for tester goroutine to stop
  1036  }
  1037  
  1038  // Issue 35367.
  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  			// Make the deadlines steadily earlier,
  1066  			// to trigger runtime adjusttimers calls.
  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  // isDeadlineExceeded reports whether err is or wraps os.ErrDeadlineExceeded.
  1079  // We also check that the error implements net.Error, and that the
  1080  // Timeout method returns true.
  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