github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/net/tcpsock_test.go (about)

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