...
Run Format

Source file src/net/tcpsock_test.go

Documentation: net

     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  // +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, err := (&streamListener{Listener: ln}).newLocalServer()
   391  		if err != nil {
   392  			t.Fatal(err)
   393  		}
   394  		defer ls.teardown()
   395  		ch := make(chan error, 1)
   396  		handler := func(ls *localServer, ln Listener) { transponder(ln, ch) }
   397  		if err := ls.buildup(handler); err != nil {
   398  			t.Fatal(err)
   399  		}
   400  		if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
   401  			t.Fatalf("got %v; expected a proper address with zone identifier", la)
   402  		}
   403  
   404  		c, err := Dial(tt.network, ls.Listener.Addr().String())
   405  		if err != nil {
   406  			t.Fatal(err)
   407  		}
   408  		defer c.Close()
   409  		if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
   410  			t.Fatalf("got %v; expected a proper address with zone identifier", la)
   411  		}
   412  		if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
   413  			t.Fatalf("got %v; expected a proper address with zone identifier", ra)
   414  		}
   415  
   416  		if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err != nil {
   417  			t.Fatal(err)
   418  		}
   419  		b := make([]byte, 32)
   420  		if _, err := c.Read(b); err != nil {
   421  			t.Fatal(err)
   422  		}
   423  
   424  		for err := range ch {
   425  			t.Errorf("#%d: %v", i, err)
   426  		}
   427  	}
   428  }
   429  
   430  func TestTCPConcurrentAccept(t *testing.T) {
   431  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
   432  	ln, err := Listen("tcp", "127.0.0.1:0")
   433  	if err != nil {
   434  		t.Fatal(err)
   435  	}
   436  	const N = 10
   437  	var wg sync.WaitGroup
   438  	wg.Add(N)
   439  	for i := 0; i < N; i++ {
   440  		go func() {
   441  			for {
   442  				c, err := ln.Accept()
   443  				if err != nil {
   444  					break
   445  				}
   446  				c.Close()
   447  			}
   448  			wg.Done()
   449  		}()
   450  	}
   451  	attempts := 10 * N
   452  	fails := 0
   453  	d := &Dialer{Timeout: 200 * time.Millisecond}
   454  	for i := 0; i < attempts; i++ {
   455  		c, err := d.Dial("tcp", ln.Addr().String())
   456  		if err != nil {
   457  			fails++
   458  		} else {
   459  			c.Close()
   460  		}
   461  	}
   462  	ln.Close()
   463  	wg.Wait()
   464  	if fails > attempts/9 { // see issues 7400 and 7541
   465  		t.Fatalf("too many Dial failed: %v", fails)
   466  	}
   467  	if fails > 0 {
   468  		t.Logf("# of failed Dials: %v", fails)
   469  	}
   470  }
   471  
   472  func TestTCPReadWriteAllocs(t *testing.T) {
   473  	switch runtime.GOOS {
   474  	case "plan9":
   475  		// The implementation of asynchronous cancelable
   476  		// I/O on Plan 9 allocates memory.
   477  		// See net/fd_io_plan9.go.
   478  		t.Skipf("not supported on %s", runtime.GOOS)
   479  	case "nacl":
   480  		// NaCl needs to allocate pseudo file descriptor
   481  		// stuff. See syscall/fd_nacl.go.
   482  		t.Skipf("not supported on %s", runtime.GOOS)
   483  	}
   484  
   485  	ln, err := Listen("tcp", "127.0.0.1:0")
   486  	if err != nil {
   487  		t.Fatal(err)
   488  	}
   489  	defer ln.Close()
   490  	var server Conn
   491  	errc := make(chan error, 1)
   492  	go func() {
   493  		var err error
   494  		server, err = ln.Accept()
   495  		errc <- err
   496  	}()
   497  	client, err := Dial("tcp", ln.Addr().String())
   498  	if err != nil {
   499  		t.Fatal(err)
   500  	}
   501  	defer client.Close()
   502  	if err := <-errc; err != nil {
   503  		t.Fatal(err)
   504  	}
   505  	defer server.Close()
   506  
   507  	var buf [128]byte
   508  	allocs := testing.AllocsPerRun(1000, func() {
   509  		_, err := server.Write(buf[:])
   510  		if err != nil {
   511  			t.Fatal(err)
   512  		}
   513  		_, err = io.ReadFull(client, buf[:])
   514  		if err != nil {
   515  			t.Fatal(err)
   516  		}
   517  	})
   518  	if allocs > 0 {
   519  		t.Fatalf("got %v; want 0", allocs)
   520  	}
   521  
   522  	var bufwrt [128]byte
   523  	ch := make(chan bool)
   524  	defer close(ch)
   525  	go func() {
   526  		for <-ch {
   527  			_, err := server.Write(bufwrt[:])
   528  			errc <- err
   529  		}
   530  	}()
   531  	allocs = testing.AllocsPerRun(1000, func() {
   532  		ch <- true
   533  		if _, err = io.ReadFull(client, buf[:]); err != nil {
   534  			t.Fatal(err)
   535  		}
   536  		if err := <-errc; err != nil {
   537  			t.Fatal(err)
   538  		}
   539  	})
   540  	if allocs > 0 {
   541  		t.Fatalf("got %v; want 0", allocs)
   542  	}
   543  }
   544  
   545  func TestTCPStress(t *testing.T) {
   546  	const conns = 2
   547  	const msgLen = 512
   548  	msgs := int(1e4)
   549  	if testing.Short() {
   550  		msgs = 1e2
   551  	}
   552  
   553  	sendMsg := func(c Conn, buf []byte) bool {
   554  		n, err := c.Write(buf)
   555  		if n != len(buf) || err != nil {
   556  			t.Log(err)
   557  			return false
   558  		}
   559  		return true
   560  	}
   561  	recvMsg := func(c Conn, buf []byte) bool {
   562  		for read := 0; read != len(buf); {
   563  			n, err := c.Read(buf)
   564  			read += n
   565  			if err != nil {
   566  				t.Log(err)
   567  				return false
   568  			}
   569  		}
   570  		return true
   571  	}
   572  
   573  	ln, err := Listen("tcp", "127.0.0.1:0")
   574  	if err != nil {
   575  		t.Fatal(err)
   576  	}
   577  	done := make(chan bool)
   578  	// Acceptor.
   579  	go func() {
   580  		defer func() {
   581  			done <- true
   582  		}()
   583  		for {
   584  			c, err := ln.Accept()
   585  			if err != nil {
   586  				break
   587  			}
   588  			// Server connection.
   589  			go func(c Conn) {
   590  				defer c.Close()
   591  				var buf [msgLen]byte
   592  				for m := 0; m < msgs; m++ {
   593  					if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
   594  						break
   595  					}
   596  				}
   597  			}(c)
   598  		}
   599  	}()
   600  	for i := 0; i < conns; i++ {
   601  		// Client connection.
   602  		go func() {
   603  			defer func() {
   604  				done <- true
   605  			}()
   606  			c, err := Dial("tcp", ln.Addr().String())
   607  			if err != nil {
   608  				t.Log(err)
   609  				return
   610  			}
   611  			defer c.Close()
   612  			var buf [msgLen]byte
   613  			for m := 0; m < msgs; m++ {
   614  				if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
   615  					break
   616  				}
   617  			}
   618  		}()
   619  	}
   620  	for i := 0; i < conns; i++ {
   621  		<-done
   622  	}
   623  	ln.Close()
   624  	<-done
   625  }
   626  
   627  func TestTCPSelfConnect(t *testing.T) {
   628  	if runtime.GOOS == "windows" {
   629  		// TODO(brainman): do not know why it hangs.
   630  		t.Skip("known-broken test on windows")
   631  	}
   632  
   633  	ln, err := newLocalListener("tcp")
   634  	if err != nil {
   635  		t.Fatal(err)
   636  	}
   637  	var d Dialer
   638  	c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
   639  	if err != nil {
   640  		ln.Close()
   641  		t.Fatal(err)
   642  	}
   643  	network := c.LocalAddr().Network()
   644  	laddr := *c.LocalAddr().(*TCPAddr)
   645  	c.Close()
   646  	ln.Close()
   647  
   648  	// Try to connect to that address repeatedly.
   649  	n := 100000
   650  	if testing.Short() {
   651  		n = 1000
   652  	}
   653  	switch runtime.GOOS {
   654  	case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd", "plan9", "solaris", "windows":
   655  		// Non-Linux systems take a long time to figure
   656  		// out that there is nothing listening on localhost.
   657  		n = 100
   658  	}
   659  	for i := 0; i < n; i++ {
   660  		d.Timeout = time.Millisecond
   661  		c, err := d.Dial(network, laddr.String())
   662  		if err == nil {
   663  			addr := c.LocalAddr().(*TCPAddr)
   664  			if addr.Port == laddr.Port || addr.IP.Equal(laddr.IP) {
   665  				t.Errorf("Dial %v should fail", addr)
   666  			} else {
   667  				t.Logf("Dial %v succeeded - possibly racing with other listener", addr)
   668  			}
   669  			c.Close()
   670  		}
   671  	}
   672  }
   673  
   674  // Test that >32-bit reads work on 64-bit systems.
   675  // On 32-bit systems this tests that maxint reads work.
   676  func TestTCPBig(t *testing.T) {
   677  	if !*testTCPBig {
   678  		t.Skip("test disabled; use -tcpbig to enable")
   679  	}
   680  
   681  	for _, writev := range []bool{false, true} {
   682  		t.Run(fmt.Sprintf("writev=%v", writev), func(t *testing.T) {
   683  			ln, err := newLocalListener("tcp")
   684  			if err != nil {
   685  				t.Fatal(err)
   686  			}
   687  			defer ln.Close()
   688  
   689  			x := int(1 << 30)
   690  			x = x*5 + 1<<20 // just over 5 GB on 64-bit, just over 1GB on 32-bit
   691  			done := make(chan int)
   692  			go func() {
   693  				defer close(done)
   694  				c, err := ln.Accept()
   695  				if err != nil {
   696  					t.Error(err)
   697  					return
   698  				}
   699  				buf := make([]byte, x)
   700  				var n int
   701  				if writev {
   702  					var n64 int64
   703  					n64, err = (&Buffers{buf}).WriteTo(c)
   704  					n = int(n64)
   705  				} else {
   706  					n, err = c.Write(buf)
   707  				}
   708  				if n != len(buf) || err != nil {
   709  					t.Errorf("Write(buf) = %d, %v, want %d, nil", n, err, x)
   710  				}
   711  				c.Close()
   712  			}()
   713  
   714  			c, err := Dial("tcp", ln.Addr().String())
   715  			if err != nil {
   716  				t.Fatal(err)
   717  			}
   718  			buf := make([]byte, x)
   719  			n, err := io.ReadFull(c, buf)
   720  			if n != len(buf) || err != nil {
   721  				t.Errorf("Read(buf) = %d, %v, want %d, nil", n, err, x)
   722  			}
   723  			c.Close()
   724  			<-done
   725  		})
   726  	}
   727  }
   728  
   729  func TestCopyPipeIntoTCP(t *testing.T) {
   730  	ln, err := newLocalListener("tcp")
   731  	if err != nil {
   732  		t.Fatal(err)
   733  	}
   734  	defer ln.Close()
   735  
   736  	errc := make(chan error, 1)
   737  	defer func() {
   738  		if err := <-errc; err != nil {
   739  			t.Error(err)
   740  		}
   741  	}()
   742  	go func() {
   743  		c, err := ln.Accept()
   744  		if err != nil {
   745  			errc <- err
   746  			return
   747  		}
   748  		defer c.Close()
   749  
   750  		buf := make([]byte, 100)
   751  		n, err := io.ReadFull(c, buf)
   752  		if err != io.ErrUnexpectedEOF || n != 2 {
   753  			errc <- fmt.Errorf("got err=%q n=%v; want err=%q n=2", err, n, io.ErrUnexpectedEOF)
   754  			return
   755  		}
   756  
   757  		errc <- nil
   758  	}()
   759  
   760  	c, err := Dial("tcp", ln.Addr().String())
   761  	if err != nil {
   762  		t.Fatal(err)
   763  	}
   764  	defer c.Close()
   765  
   766  	r, w, err := os.Pipe()
   767  	if err != nil {
   768  		t.Fatal(err)
   769  	}
   770  	defer r.Close()
   771  
   772  	errc2 := make(chan error, 1)
   773  	defer func() {
   774  		if err := <-errc2; err != nil {
   775  			t.Error(err)
   776  		}
   777  	}()
   778  
   779  	defer w.Close()
   780  
   781  	go func() {
   782  		_, err := io.Copy(c, r)
   783  		errc2 <- err
   784  	}()
   785  
   786  	// Split write into 2 packets. That makes Windows TransmitFile
   787  	// drop second packet.
   788  	packet := make([]byte, 1)
   789  	_, err = w.Write(packet)
   790  	if err != nil {
   791  		t.Fatal(err)
   792  	}
   793  	time.Sleep(100 * time.Millisecond)
   794  	_, err = w.Write(packet)
   795  	if err != nil {
   796  		t.Fatal(err)
   797  	}
   798  }
   799  

View as plain text