Source file src/net/tcpsock_test.go

     1  // Copyright 2012 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  
     7  package net
     8  
     9  import (
    10  	"fmt"
    11  	"internal/testenv"
    12  	"io"
    13  	"os"
    14  	"reflect"
    15  	"runtime"
    16  	"sync"
    17  	"testing"
    18  	"time"
    19  )
    20  
    21  func BenchmarkTCP4OneShot(b *testing.B) {
    22  	benchmarkTCP(b, false, false, "127.0.0.1:0")
    23  }
    24  
    25  func BenchmarkTCP4OneShotTimeout(b *testing.B) {
    26  	benchmarkTCP(b, false, true, "127.0.0.1:0")
    27  }
    28  
    29  func BenchmarkTCP4Persistent(b *testing.B) {
    30  	benchmarkTCP(b, true, false, "127.0.0.1:0")
    31  }
    32  
    33  func BenchmarkTCP4PersistentTimeout(b *testing.B) {
    34  	benchmarkTCP(b, true, true, "127.0.0.1:0")
    35  }
    36  
    37  func BenchmarkTCP6OneShot(b *testing.B) {
    38  	if !supportsIPv6() {
    39  		b.Skip("ipv6 is not supported")
    40  	}
    41  	benchmarkTCP(b, false, false, "[::1]:0")
    42  }
    43  
    44  func BenchmarkTCP6OneShotTimeout(b *testing.B) {
    45  	if !supportsIPv6() {
    46  		b.Skip("ipv6 is not supported")
    47  	}
    48  	benchmarkTCP(b, false, true, "[::1]:0")
    49  }
    50  
    51  func BenchmarkTCP6Persistent(b *testing.B) {
    52  	if !supportsIPv6() {
    53  		b.Skip("ipv6 is not supported")
    54  	}
    55  	benchmarkTCP(b, true, false, "[::1]:0")
    56  }
    57  
    58  func BenchmarkTCP6PersistentTimeout(b *testing.B) {
    59  	if !supportsIPv6() {
    60  		b.Skip("ipv6 is not supported")
    61  	}
    62  	benchmarkTCP(b, true, true, "[::1]:0")
    63  }
    64  
    65  func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
    66  	testHookUninstaller.Do(uninstallTestHooks)
    67  
    68  	const msgLen = 512
    69  	conns := b.N
    70  	numConcurrent := runtime.GOMAXPROCS(-1) * 2
    71  	msgs := 1
    72  	if persistent {
    73  		conns = numConcurrent
    74  		msgs = b.N / conns
    75  		if msgs == 0 {
    76  			msgs = 1
    77  		}
    78  		if conns > b.N {
    79  			conns = b.N
    80  		}
    81  	}
    82  	sendMsg := func(c Conn, buf []byte) bool {
    83  		n, err := c.Write(buf)
    84  		if n != len(buf) || err != nil {
    85  			b.Log(err)
    86  			return false
    87  		}
    88  		return true
    89  	}
    90  	recvMsg := func(c Conn, buf []byte) bool {
    91  		for read := 0; read != len(buf); {
    92  			n, err := c.Read(buf)
    93  			read += n
    94  			if err != nil {
    95  				b.Log(err)
    96  				return false
    97  			}
    98  		}
    99  		return true
   100  	}
   101  	ln, err := Listen("tcp", laddr)
   102  	if err != nil {
   103  		b.Fatal(err)
   104  	}
   105  	defer ln.Close()
   106  	serverSem := make(chan bool, numConcurrent)
   107  	// Acceptor.
   108  	go func() {
   109  		for {
   110  			c, err := ln.Accept()
   111  			if err != nil {
   112  				break
   113  			}
   114  			serverSem <- true
   115  			// Server connection.
   116  			go func(c Conn) {
   117  				defer func() {
   118  					c.Close()
   119  					<-serverSem
   120  				}()
   121  				if timeout {
   122  					c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
   123  				}
   124  				var buf [msgLen]byte
   125  				for m := 0; m < msgs; m++ {
   126  					if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
   127  						break
   128  					}
   129  				}
   130  			}(c)
   131  		}
   132  	}()
   133  	clientSem := make(chan bool, numConcurrent)
   134  	for i := 0; i < conns; i++ {
   135  		clientSem <- true
   136  		// Client connection.
   137  		go func() {
   138  			defer func() {
   139  				<-clientSem
   140  			}()
   141  			c, err := Dial("tcp", ln.Addr().String())
   142  			if err != nil {
   143  				b.Log(err)
   144  				return
   145  			}
   146  			defer c.Close()
   147  			if timeout {
   148  				c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
   149  			}
   150  			var buf [msgLen]byte
   151  			for m := 0; m < msgs; m++ {
   152  				if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
   153  					break
   154  				}
   155  			}
   156  		}()
   157  	}
   158  	for i := 0; i < numConcurrent; i++ {
   159  		clientSem <- true
   160  		serverSem <- true
   161  	}
   162  }
   163  
   164  func BenchmarkTCP4ConcurrentReadWrite(b *testing.B) {
   165  	benchmarkTCPConcurrentReadWrite(b, "127.0.0.1:0")
   166  }
   167  
   168  func BenchmarkTCP6ConcurrentReadWrite(b *testing.B) {
   169  	if !supportsIPv6() {
   170  		b.Skip("ipv6 is not supported")
   171  	}
   172  	benchmarkTCPConcurrentReadWrite(b, "[::1]:0")
   173  }
   174  
   175  func benchmarkTCPConcurrentReadWrite(b *testing.B, laddr string) {
   176  	testHookUninstaller.Do(uninstallTestHooks)
   177  
   178  	// The benchmark creates GOMAXPROCS client/server pairs.
   179  	// Each pair creates 4 goroutines: client reader/writer and server reader/writer.
   180  	// The benchmark stresses concurrent reading and writing to the same connection.
   181  	// Such pattern is used in net/http and net/rpc.
   182  
   183  	b.StopTimer()
   184  
   185  	P := runtime.GOMAXPROCS(0)
   186  	N := b.N / P
   187  	W := 1000
   188  
   189  	// Setup P client/server connections.
   190  	clients := make([]Conn, P)
   191  	servers := make([]Conn, P)
   192  	ln, err := Listen("tcp", laddr)
   193  	if err != nil {
   194  		b.Fatal(err)
   195  	}
   196  	defer ln.Close()
   197  	done := make(chan bool)
   198  	go func() {
   199  		for p := 0; p < P; p++ {
   200  			s, err := ln.Accept()
   201  			if err != nil {
   202  				b.Error(err)
   203  				return
   204  			}
   205  			servers[p] = s
   206  		}
   207  		done <- true
   208  	}()
   209  	for p := 0; p < P; p++ {
   210  		c, err := Dial("tcp", ln.Addr().String())
   211  		if err != nil {
   212  			b.Fatal(err)
   213  		}
   214  		clients[p] = c
   215  	}
   216  	<-done
   217  
   218  	b.StartTimer()
   219  
   220  	var wg sync.WaitGroup
   221  	wg.Add(4 * P)
   222  	for p := 0; p < P; p++ {
   223  		// Client writer.
   224  		go func(c Conn) {
   225  			defer wg.Done()
   226  			var buf [1]byte
   227  			for i := 0; i < N; i++ {
   228  				v := byte(i)
   229  				for w := 0; w < W; w++ {
   230  					v *= v
   231  				}
   232  				buf[0] = v
   233  				_, err := c.Write(buf[:])
   234  				if err != nil {
   235  					b.Error(err)
   236  					return
   237  				}
   238  			}
   239  		}(clients[p])
   240  
   241  		// Pipe between server reader and server writer.
   242  		pipe := make(chan byte, 128)
   243  
   244  		// Server reader.
   245  		go func(s Conn) {
   246  			defer wg.Done()
   247  			var buf [1]byte
   248  			for i := 0; i < N; i++ {
   249  				_, err := s.Read(buf[:])
   250  				if err != nil {
   251  					b.Error(err)
   252  					return
   253  				}
   254  				pipe <- buf[0]
   255  			}
   256  		}(servers[p])
   257  
   258  		// Server writer.
   259  		go func(s Conn) {
   260  			defer wg.Done()
   261  			var buf [1]byte
   262  			for i := 0; i < N; i++ {
   263  				v := <-pipe
   264  				for w := 0; w < W; w++ {
   265  					v *= v
   266  				}
   267  				buf[0] = v
   268  				_, err := s.Write(buf[:])
   269  				if err != nil {
   270  					b.Error(err)
   271  					return
   272  				}
   273  			}
   274  			s.Close()
   275  		}(servers[p])
   276  
   277  		// Client reader.
   278  		go func(c Conn) {
   279  			defer wg.Done()
   280  			var buf [1]byte
   281  			for i := 0; i < N; i++ {
   282  				_, err := c.Read(buf[:])
   283  				if err != nil {
   284  					b.Error(err)
   285  					return
   286  				}
   287  			}
   288  			c.Close()
   289  		}(clients[p])
   290  	}
   291  	wg.Wait()
   292  }
   293  
   294  type resolveTCPAddrTest struct {
   295  	network       string
   296  	litAddrOrName string
   297  	addr          *TCPAddr
   298  	err           error
   299  }
   300  
   301  var resolveTCPAddrTests = []resolveTCPAddrTest{
   302  	{"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
   303  	{"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
   304  
   305  	{"tcp", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},
   306  	{"tcp6", "[::1]:65535", &TCPAddr{IP: ParseIP("::1"), Port: 65535}, nil},
   307  
   308  	{"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
   309  	{"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
   310  
   311  	{"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
   312  	{"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior
   313  
   314  	{"tcp", ":12345", &TCPAddr{Port: 12345}, nil},
   315  
   316  	{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
   317  
   318  	{"tcp", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
   319  	{"tcp", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 80}, nil},
   320  	{"tcp", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil},
   321  	{"tcp4", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
   322  	{"tcp4", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
   323  	{"tcp6", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil},
   324  
   325  	{"tcp4", "[2001:db8::1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
   326  	{"tcp6", "127.0.0.1:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
   327  	{"tcp6", "[::ffff:127.0.0.1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
   328  }
   329  
   330  func TestResolveTCPAddr(t *testing.T) {
   331  	origTestHookLookupIP := testHookLookupIP
   332  	defer func() { testHookLookupIP = origTestHookLookupIP }()
   333  	testHookLookupIP = lookupLocalhost
   334  
   335  	for _, tt := range resolveTCPAddrTests {
   336  		addr, err := ResolveTCPAddr(tt.network, tt.litAddrOrName)
   337  		if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) {
   338  			t.Errorf("ResolveTCPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err)
   339  			continue
   340  		}
   341  		if err == nil {
   342  			addr2, err := ResolveTCPAddr(addr.Network(), addr.String())
   343  			if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err {
   344  				t.Errorf("(%q, %q): ResolveTCPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err)
   345  			}
   346  		}
   347  	}
   348  }
   349  
   350  var tcpListenerNameTests = []struct {
   351  	net   string
   352  	laddr *TCPAddr
   353  }{
   354  	{"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}},
   355  	{"tcp4", &TCPAddr{}},
   356  	{"tcp4", nil},
   357  }
   358  
   359  func TestTCPListenerName(t *testing.T) {
   360  	testenv.MustHaveExternalNetwork(t)
   361  
   362  	for _, tt := range tcpListenerNameTests {
   363  		ln, err := ListenTCP(tt.net, tt.laddr)
   364  		if err != nil {
   365  			t.Fatal(err)
   366  		}
   367  		defer ln.Close()
   368  		la := ln.Addr()
   369  		if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
   370  			t.Fatalf("got %v; expected a proper address with non-zero port number", la)
   371  		}
   372  	}
   373  }
   374  
   375  func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
   376  	testenv.MustHaveExternalNetwork(t)
   377  
   378  	if !supportsIPv6() {
   379  		t.Skip("IPv6 is not supported")
   380  	}
   381  
   382  	for i, tt := range ipv6LinkLocalUnicastTCPTests {
   383  		ln, err := Listen(tt.network, tt.address)
   384  		if err != nil {
   385  			// It might return "LookupHost returned no
   386  			// suitable address" error on some platforms.
   387  			t.Log(err)
   388  			continue
   389  		}
   390  		ls := (&streamListener{Listener: ln}).newLocalServer()
   391  		defer ls.teardown()
   392  		ch := make(chan error, 1)
   393  		handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
   394  		if err := ls.buildup(handler); err != nil {
   395  			t.Fatal(err)
   396  		}
   397  		if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
   398  			t.Fatalf("got %v; expected a proper address with zone identifier", la)
   399  		}
   400  
   401  		c, err := Dial(tt.network, ls.Listener.Addr().String())
   402  		if err != nil {
   403  			t.Fatal(err)
   404  		}
   405  		defer c.Close()
   406  		if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
   407  			t.Fatalf("got %v; expected a proper address with zone identifier", la)
   408  		}
   409  		if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
   410  			t.Fatalf("got %v; expected a proper address with zone identifier", ra)
   411  		}
   412  
   413  		if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err != nil {
   414  			t.Fatal(err)
   415  		}
   416  		b := make([]byte, 32)
   417  		if _, err := c.Read(b); err != nil {
   418  			t.Fatal(err)
   419  		}
   420  
   421  		for err := range ch {
   422  			t.Errorf("#%d: %v", i, err)
   423  		}
   424  	}
   425  }
   426  
   427  func TestTCPConcurrentAccept(t *testing.T) {
   428  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
   429  	ln, err := Listen("tcp", "127.0.0.1:0")
   430  	if err != nil {
   431  		t.Fatal(err)
   432  	}
   433  	const N = 10
   434  	var wg sync.WaitGroup
   435  	wg.Add(N)
   436  	for i := 0; i < N; i++ {
   437  		go func() {
   438  			for {
   439  				c, err := ln.Accept()
   440  				if err != nil {
   441  					break
   442  				}
   443  				c.Close()
   444  			}
   445  			wg.Done()
   446  		}()
   447  	}
   448  	attempts := 10 * N
   449  	fails := 0
   450  	d := &Dialer{Timeout: 200 * time.Millisecond}
   451  	for i := 0; i < attempts; i++ {
   452  		c, err := d.Dial("tcp", ln.Addr().String())
   453  		if err != nil {
   454  			fails++
   455  		} else {
   456  			c.Close()
   457  		}
   458  	}
   459  	ln.Close()
   460  	wg.Wait()
   461  	if fails > attempts/9 { // see issues 7400 and 7541
   462  		t.Fatalf("too many Dial failed: %v", fails)
   463  	}
   464  	if fails > 0 {
   465  		t.Logf("# of failed Dials: %v", fails)
   466  	}
   467  }
   468  
   469  func TestTCPReadWriteAllocs(t *testing.T) {
   470  	switch runtime.GOOS {
   471  	case "plan9":
   472  		// The implementation of asynchronous cancelable
   473  		// I/O on Plan 9 allocates memory.
   474  		// See net/fd_io_plan9.go.
   475  		t.Skipf("not supported on %s", runtime.GOOS)
   476  	}
   477  
   478  	ln, err := Listen("tcp", "127.0.0.1:0")
   479  	if err != nil {
   480  		t.Fatal(err)
   481  	}
   482  	defer ln.Close()
   483  	var server Conn
   484  	errc := make(chan error, 1)
   485  	go func() {
   486  		var err error
   487  		server, err = ln.Accept()
   488  		errc <- err
   489  	}()
   490  	client, err := Dial("tcp", ln.Addr().String())
   491  	if err != nil {
   492  		t.Fatal(err)
   493  	}
   494  	defer client.Close()
   495  	if err := <-errc; err != nil {
   496  		t.Fatal(err)
   497  	}
   498  	defer server.Close()
   499  
   500  	var buf [128]byte
   501  	allocs := testing.AllocsPerRun(1000, func() {
   502  		_, err := server.Write(buf[:])
   503  		if err != nil {
   504  			t.Fatal(err)
   505  		}
   506  		_, err = io.ReadFull(client, buf[:])
   507  		if err != nil {
   508  			t.Fatal(err)
   509  		}
   510  	})
   511  	if allocs > 0 {
   512  		t.Fatalf("got %v; want 0", allocs)
   513  	}
   514  
   515  	var bufwrt [128]byte
   516  	ch := make(chan bool)
   517  	defer close(ch)
   518  	go func() {
   519  		for <-ch {
   520  			_, err := server.Write(bufwrt[:])
   521  			errc <- err
   522  		}
   523  	}()
   524  	allocs = testing.AllocsPerRun(1000, func() {
   525  		ch <- true
   526  		if _, err = io.ReadFull(client, buf[:]); err != nil {
   527  			t.Fatal(err)
   528  		}
   529  		if err := <-errc; err != nil {
   530  			t.Fatal(err)
   531  		}
   532  	})
   533  	if allocs > 0 {
   534  		t.Fatalf("got %v; want 0", allocs)
   535  	}
   536  }
   537  
   538  func TestTCPStress(t *testing.T) {
   539  	const conns = 2
   540  	const msgLen = 512
   541  	msgs := int(1e4)
   542  	if testing.Short() {
   543  		msgs = 1e2
   544  	}
   545  
   546  	sendMsg := func(c Conn, buf []byte) bool {
   547  		n, err := c.Write(buf)
   548  		if n != len(buf) || err != nil {
   549  			t.Log(err)
   550  			return false
   551  		}
   552  		return true
   553  	}
   554  	recvMsg := func(c Conn, buf []byte) bool {
   555  		for read := 0; read != len(buf); {
   556  			n, err := c.Read(buf)
   557  			read += n
   558  			if err != nil {
   559  				t.Log(err)
   560  				return false
   561  			}
   562  		}
   563  		return true
   564  	}
   565  
   566  	ln, err := Listen("tcp", "127.0.0.1:0")
   567  	if err != nil {
   568  		t.Fatal(err)
   569  	}
   570  	done := make(chan bool)
   571  	// Acceptor.
   572  	go func() {
   573  		defer func() {
   574  			done <- true
   575  		}()
   576  		for {
   577  			c, err := ln.Accept()
   578  			if err != nil {
   579  				break
   580  			}
   581  			// Server connection.
   582  			go func(c Conn) {
   583  				defer c.Close()
   584  				var buf [msgLen]byte
   585  				for m := 0; m < msgs; m++ {
   586  					if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
   587  						break
   588  					}
   589  				}
   590  			}(c)
   591  		}
   592  	}()
   593  	for i := 0; i < conns; i++ {
   594  		// Client connection.
   595  		go func() {
   596  			defer func() {
   597  				done <- true
   598  			}()
   599  			c, err := Dial("tcp", ln.Addr().String())
   600  			if err != nil {
   601  				t.Log(err)
   602  				return
   603  			}
   604  			defer c.Close()
   605  			var buf [msgLen]byte
   606  			for m := 0; m < msgs; m++ {
   607  				if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
   608  					break
   609  				}
   610  			}
   611  		}()
   612  	}
   613  	for i := 0; i < conns; i++ {
   614  		<-done
   615  	}
   616  	ln.Close()
   617  	<-done
   618  }
   619  
   620  func TestTCPSelfConnect(t *testing.T) {
   621  	if runtime.GOOS == "windows" {
   622  		// TODO(brainman): do not know why it hangs.
   623  		t.Skip("known-broken test on windows")
   624  	}
   625  
   626  	ln := newLocalListener(t, "tcp")
   627  	var d Dialer
   628  	c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
   629  	if err != nil {
   630  		ln.Close()
   631  		t.Fatal(err)
   632  	}
   633  	network := c.LocalAddr().Network()
   634  	laddr := *c.LocalAddr().(*TCPAddr)
   635  	c.Close()
   636  	ln.Close()
   637  
   638  	// Try to connect to that address repeatedly.
   639  	n := 100000
   640  	if testing.Short() {
   641  		n = 1000
   642  	}
   643  	switch runtime.GOOS {
   644  	case "darwin", "ios", "dragonfly", "freebsd", "netbsd", "openbsd", "plan9", "illumos", "solaris", "windows":
   645  		// Non-Linux systems take a long time to figure
   646  		// out that there is nothing listening on localhost.
   647  		n = 100
   648  	}
   649  	for i := 0; i < n; i++ {
   650  		d.Timeout = time.Millisecond
   651  		c, err := d.Dial(network, laddr.String())
   652  		if err == nil {
   653  			addr := c.LocalAddr().(*TCPAddr)
   654  			if addr.Port == laddr.Port || addr.IP.Equal(laddr.IP) {
   655  				t.Errorf("Dial %v should fail", addr)
   656  			} else {
   657  				t.Logf("Dial %v succeeded - possibly racing with other listener", addr)
   658  			}
   659  			c.Close()
   660  		}
   661  	}
   662  }
   663  
   664  // Test that >32-bit reads work on 64-bit systems.
   665  // On 32-bit systems this tests that maxint reads work.
   666  func TestTCPBig(t *testing.T) {
   667  	if !*testTCPBig {
   668  		t.Skip("test disabled; use -tcpbig to enable")
   669  	}
   670  
   671  	for _, writev := range []bool{false, true} {
   672  		t.Run(fmt.Sprintf("writev=%v", writev), func(t *testing.T) {
   673  			ln := newLocalListener(t, "tcp")
   674  			defer ln.Close()
   675  
   676  			x := int(1 << 30)
   677  			x = x*5 + 1<<20 // just over 5 GB on 64-bit, just over 1GB on 32-bit
   678  			done := make(chan int)
   679  			go func() {
   680  				defer close(done)
   681  				c, err := ln.Accept()
   682  				if err != nil {
   683  					t.Error(err)
   684  					return
   685  				}
   686  				buf := make([]byte, x)
   687  				var n int
   688  				if writev {
   689  					var n64 int64
   690  					n64, err = (&Buffers{buf}).WriteTo(c)
   691  					n = int(n64)
   692  				} else {
   693  					n, err = c.Write(buf)
   694  				}
   695  				if n != len(buf) || err != nil {
   696  					t.Errorf("Write(buf) = %d, %v, want %d, nil", n, err, x)
   697  				}
   698  				c.Close()
   699  			}()
   700  
   701  			c, err := Dial("tcp", ln.Addr().String())
   702  			if err != nil {
   703  				t.Fatal(err)
   704  			}
   705  			buf := make([]byte, x)
   706  			n, err := io.ReadFull(c, buf)
   707  			if n != len(buf) || err != nil {
   708  				t.Errorf("Read(buf) = %d, %v, want %d, nil", n, err, x)
   709  			}
   710  			c.Close()
   711  			<-done
   712  		})
   713  	}
   714  }
   715  
   716  func TestCopyPipeIntoTCP(t *testing.T) {
   717  	ln := newLocalListener(t, "tcp")
   718  	defer ln.Close()
   719  
   720  	errc := make(chan error, 1)
   721  	defer func() {
   722  		if err := <-errc; err != nil {
   723  			t.Error(err)
   724  		}
   725  	}()
   726  	go func() {
   727  		c, err := ln.Accept()
   728  		if err != nil {
   729  			errc <- err
   730  			return
   731  		}
   732  		defer c.Close()
   733  
   734  		buf := make([]byte, 100)
   735  		n, err := io.ReadFull(c, buf)
   736  		if err != io.ErrUnexpectedEOF || n != 2 {
   737  			errc <- fmt.Errorf("got err=%q n=%v; want err=%q n=2", err, n, io.ErrUnexpectedEOF)
   738  			return
   739  		}
   740  
   741  		errc <- nil
   742  	}()
   743  
   744  	c, err := Dial("tcp", ln.Addr().String())
   745  	if err != nil {
   746  		t.Fatal(err)
   747  	}
   748  	defer c.Close()
   749  
   750  	r, w, err := os.Pipe()
   751  	if err != nil {
   752  		t.Fatal(err)
   753  	}
   754  	defer r.Close()
   755  
   756  	errc2 := make(chan error, 1)
   757  	defer func() {
   758  		if err := <-errc2; err != nil {
   759  			t.Error(err)
   760  		}
   761  	}()
   762  
   763  	defer w.Close()
   764  
   765  	go func() {
   766  		_, err := io.Copy(c, r)
   767  		errc2 <- err
   768  	}()
   769  
   770  	// Split write into 2 packets. That makes Windows TransmitFile
   771  	// drop second packet.
   772  	packet := make([]byte, 1)
   773  	_, err = w.Write(packet)
   774  	if err != nil {
   775  		t.Fatal(err)
   776  	}
   777  	time.Sleep(100 * time.Millisecond)
   778  	_, err = w.Write(packet)
   779  	if err != nil {
   780  		t.Fatal(err)
   781  	}
   782  }
   783  
   784  func BenchmarkSetReadDeadline(b *testing.B) {
   785  	ln := newLocalListener(b, "tcp")
   786  	defer ln.Close()
   787  	var serv Conn
   788  	done := make(chan error)
   789  	go func() {
   790  		var err error
   791  		serv, err = ln.Accept()
   792  		done <- err
   793  	}()
   794  	c, err := Dial("tcp", ln.Addr().String())
   795  	if err != nil {
   796  		b.Fatal(err)
   797  	}
   798  	defer c.Close()
   799  	if err := <-done; err != nil {
   800  		b.Fatal(err)
   801  	}
   802  	defer serv.Close()
   803  	c.SetWriteDeadline(time.Now().Add(2 * time.Hour))
   804  	deadline := time.Now().Add(time.Hour)
   805  	b.ResetTimer()
   806  	for i := 0; i < b.N; i++ {
   807  		c.SetReadDeadline(deadline)
   808  		deadline = deadline.Add(1)
   809  	}
   810  }
   811  

View as plain text