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.
18 func BenchmarkTCP4OneShot(b
*testing
.B
) {
19 benchmarkTCP(b
, false, false, "127.0.0.1:0")
22 func BenchmarkTCP4OneShotTimeout(b
*testing
.B
) {
23 benchmarkTCP(b
, false, true, "127.0.0.1:0")
26 func BenchmarkTCP4Persistent(b
*testing
.B
) {
27 benchmarkTCP(b
, true, false, "127.0.0.1:0")
30 func BenchmarkTCP4PersistentTimeout(b
*testing
.B
) {
31 benchmarkTCP(b
, true, true, "127.0.0.1:0")
34 func BenchmarkTCP6OneShot(b
*testing
.B
) {
36 b
.Skip("ipv6 is not supported")
38 benchmarkTCP(b
, false, false, "[::1]:0")
41 func BenchmarkTCP6OneShotTimeout(b
*testing
.B
) {
43 b
.Skip("ipv6 is not supported")
45 benchmarkTCP(b
, false, true, "[::1]:0")
48 func BenchmarkTCP6Persistent(b
*testing
.B
) {
50 b
.Skip("ipv6 is not supported")
52 benchmarkTCP(b
, true, false, "[::1]:0")
55 func BenchmarkTCP6PersistentTimeout(b
*testing
.B
) {
57 b
.Skip("ipv6 is not supported")
59 benchmarkTCP(b
, true, true, "[::1]:0")
62 func benchmarkTCP(b
*testing
.B
, persistent
, timeout
bool, laddr
string) {
63 testHookUninstaller
.Do(uninstallTestHooks
)
67 numConcurrent
:= runtime
.GOMAXPROCS(-1) * 2
79 sendMsg
:= func(c Conn
, buf
[]byte) bool {
80 n
, err
:= c
.Write(buf
)
81 if n
!= len(buf
) || err
!= nil {
87 recvMsg
:= func(c Conn
, buf
[]byte) bool {
88 for read
:= 0; read
!= len(buf
); {
98 ln
, err
:= Listen("tcp", laddr
)
103 serverSem
:= make(chan bool, numConcurrent
)
107 c
, err
:= ln
.Accept()
112 // Server connection.
119 c
.SetDeadline(time
.Now().Add(time
.Hour
)) // Not intended to fire.
122 for m
:= 0; m
< msgs
; m
++ {
123 if !recvMsg(c
, buf
[:]) ||
!sendMsg(c
, buf
[:]) {
130 clientSem
:= make(chan bool, numConcurrent
)
131 for i
:= 0; i
< conns
; i
++ {
133 // Client connection.
138 c
, err
:= Dial("tcp", ln
.Addr().String())
145 c
.SetDeadline(time
.Now().Add(time
.Hour
)) // Not intended to fire.
148 for m
:= 0; m
< msgs
; m
++ {
149 if !sendMsg(c
, buf
[:]) ||
!recvMsg(c
, buf
[:]) {
155 for i
:= 0; i
< numConcurrent
; i
++ {
161 func BenchmarkTCP4ConcurrentReadWrite(b
*testing
.B
) {
162 benchmarkTCPConcurrentReadWrite(b
, "127.0.0.1:0")
165 func BenchmarkTCP6ConcurrentReadWrite(b
*testing
.B
) {
167 b
.Skip("ipv6 is not supported")
169 benchmarkTCPConcurrentReadWrite(b
, "[::1]:0")
172 func benchmarkTCPConcurrentReadWrite(b
*testing
.B
, laddr
string) {
173 testHookUninstaller
.Do(uninstallTestHooks
)
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.
182 P
:= runtime
.GOMAXPROCS(0)
186 // Setup P client/server connections.
187 clients
:= make([]Conn
, P
)
188 servers
:= make([]Conn
, P
)
189 ln
, err
:= Listen("tcp", laddr
)
194 done
:= make(chan bool)
196 for p
:= 0; p
< P
; p
++ {
197 s
, err
:= ln
.Accept()
206 for p
:= 0; p
< P
; p
++ {
207 c
, err
:= Dial("tcp", ln
.Addr().String())
217 var wg sync
.WaitGroup
219 for p
:= 0; p
< P
; p
++ {
224 for i
:= 0; i
< N
; i
++ {
226 for w
:= 0; w
< W
; w
++ {
230 _
, err
:= c
.Write(buf
[:])
238 // Pipe between server reader and server writer.
239 pipe
:= make(chan byte, 128)
245 for i
:= 0; i
< N
; i
++ {
246 _
, err
:= s
.Read(buf
[:])
259 for i
:= 0; i
< N
; i
++ {
261 for w
:= 0; w
< W
; w
++ {
265 _
, err
:= s
.Write(buf
[:])
278 for i
:= 0; i
< N
; i
++ {
279 _
, err
:= c
.Read(buf
[:])
291 type resolveTCPAddrTest
struct {
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},
302 {"tcp", "[::1]:0", &TCPAddr
{IP
: ParseIP("::1"), Port
: 0}, nil},
303 {"tcp6", "[::1]:65535", &TCPAddr
{IP
: ParseIP("::1"), Port
: 65535}, nil},
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},
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
311 {"tcp", ":12345", &TCPAddr
{Port
: 12345}, nil},
313 {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
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},
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"}},
327 func TestResolveTCPAddr(t
*testing
.T
) {
328 origTestHookLookupIP
:= testHookLookupIP
329 defer func() { testHookLookupIP
= origTestHookLookupIP
}()
330 testHookLookupIP
= lookupLocalhost
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
)
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
)
347 var tcpListenerNameTests
= []struct {
351 {"tcp4", &TCPAddr
{IP
: IPv4(127, 0, 0, 1)}},
352 {"tcp4", &TCPAddr
{}},
356 func TestTCPListenerName(t
*testing
.T
) {
357 testenv
.MustHaveExternalNetwork(t
)
359 for _
, tt
:= range tcpListenerNameTests
{
360 ln
, err
:= ListenTCP(tt
.net
, tt
.laddr
)
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
)
372 func TestIPv6LinkLocalUnicastTCP(t
*testing
.T
) {
373 testenv
.MustHaveExternalNetwork(t
)
376 t
.Skip("IPv6 is not supported")
379 for i
, tt
:= range ipv6LinkLocalUnicastTCPTests
{
380 ln
, err
:= Listen(tt
.network
, tt
.address
)
382 // It might return "LookupHost returned no
383 // suitable address" error on some platforms.
387 ls
, err
:= (&streamListener
{Listener
: ln
}).newLocalServer()
392 ch
:= make(chan error
, 1)
393 handler
:= func(ls
*localServer
, ln Listener
) { transponder(ln
, ch
) }
394 if err
:= ls
.buildup(handler
); err
!= nil {
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
)
401 c
, err
:= Dial(tt
.network
, ls
.Listener
.Addr().String())
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
)
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
)
413 if _
, err
:= c
.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err
!= nil {
416 b
:= make([]byte, 32)
417 if _
, err
:= c
.Read(b
); err
!= nil {
421 for err
:= range ch
{
422 t
.Errorf("#%d: %v", i
, err
)
427 func TestTCPConcurrentAccept(t
*testing
.T
) {
428 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(4))
429 ln
, err
:= Listen("tcp", "127.0.0.1:0")
434 var wg sync
.WaitGroup
436 for i
:= 0; i
< N
; i
++ {
439 c
, err
:= ln
.Accept()
450 d
:= &Dialer
{Timeout
: 200 * time
.Millisecond
}
451 for i
:= 0; i
< attempts
; i
++ {
452 c
, err
:= d
.Dial("tcp", ln
.Addr().String())
461 if fails
> attempts
/9 { // see issues 7400 and 7541
462 t
.Fatalf("too many Dial failed: %v", fails
)
465 t
.Logf("# of failed Dials: %v", fails
)
469 func TestTCPReadWriteAllocs(t
*testing
.T
) {
470 if runtime
.Compiler
== "gccgo" {
471 t
.Skip("skipping for gccgo until escape analysis is enabled")
474 switch runtime
.GOOS
{
476 // The implementation of asynchronous cancelable
477 // I/O on Plan 9 allocates memory.
478 // See net/fd_io_plan9.go.
479 t
.Skipf("not supported on %s", runtime
.GOOS
)
481 // NaCl needs to allocate pseudo file descriptor
482 // stuff. See syscall/fd_nacl.go.
483 t
.Skipf("not supported on %s", runtime
.GOOS
)
486 ln
, err
:= Listen("tcp", "127.0.0.1:0")
492 errc
:= make(chan error
, 1)
495 server
, err
= ln
.Accept()
498 client
, err
:= Dial("tcp", ln
.Addr().String())
503 if err
:= <-errc
; err
!= nil {
509 allocs
:= testing
.AllocsPerRun(1000, func() {
510 _
, err
:= server
.Write(buf
[:])
514 _
, err
= io
.ReadFull(client
, buf
[:])
519 // For gccgo changed "> 0" to "> 7".
521 t
.Fatalf("got %v; want 0", allocs
)
525 ch
:= make(chan bool)
529 _
, err
:= server
.Write(bufwrt
[:])
533 allocs
= testing
.AllocsPerRun(1000, func() {
535 if _
, err
= io
.ReadFull(client
, buf
[:]); err
!= nil {
538 if err
:= <-errc
; err
!= nil {
543 t
.Fatalf("got %v; want 0", allocs
)
547 func TestTCPStress(t
*testing
.T
) {
555 sendMsg
:= func(c Conn
, buf
[]byte) bool {
556 n
, err
:= c
.Write(buf
)
557 if n
!= len(buf
) || err
!= nil {
563 recvMsg
:= func(c Conn
, buf
[]byte) bool {
564 for read
:= 0; read
!= len(buf
); {
565 n
, err
:= c
.Read(buf
)
575 ln
, err
:= Listen("tcp", "127.0.0.1:0")
579 done
:= make(chan bool)
586 c
, err
:= ln
.Accept()
590 // Server connection.
594 for m
:= 0; m
< msgs
; m
++ {
595 if !recvMsg(c
, buf
[:]) ||
!sendMsg(c
, buf
[:]) {
602 for i
:= 0; i
< conns
; i
++ {
603 // Client connection.
608 c
, err
:= Dial("tcp", ln
.Addr().String())
615 for m
:= 0; m
< msgs
; m
++ {
616 if !sendMsg(c
, buf
[:]) ||
!recvMsg(c
, buf
[:]) {
622 for i
:= 0; i
< conns
; i
++ {
629 func TestTCPSelfConnect(t
*testing
.T
) {
630 if runtime
.GOOS
== "windows" {
631 // TODO(brainman): do not know why it hangs.
632 t
.Skip("known-broken test on windows")
635 ln
, err
:= newLocalListener("tcp")
640 c
, err
:= d
.Dial(ln
.Addr().Network(), ln
.Addr().String())
645 network
:= c
.LocalAddr().Network()
646 laddr
:= *c
.LocalAddr().(*TCPAddr
)
650 // Try to connect to that address repeatedly.
655 switch runtime
.GOOS
{
656 case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd", "plan9", "solaris", "windows":
657 // Non-Linux systems take a long time to figure
658 // out that there is nothing listening on localhost.
661 for i
:= 0; i
< n
; i
++ {
662 d
.Timeout
= time
.Millisecond
663 c
, err
:= d
.Dial(network
, laddr
.String())
665 addr
:= c
.LocalAddr().(*TCPAddr
)
666 if addr
.Port
== laddr
.Port || addr
.IP
.Equal(laddr
.IP
) {
667 t
.Errorf("Dial %v should fail", addr
)
669 t
.Logf("Dial %v succeeded - possibly racing with other listener", addr
)
676 // Test that >32-bit reads work on 64-bit systems.
677 // On 32-bit systems this tests that maxint reads work.
678 func TestTCPBig(t
*testing
.T
) {
680 t
.Skip("test disabled; use -tcpbig to enable")
683 for _
, writev
:= range []bool{false, true} {
684 t
.Run(fmt
.Sprintf("writev=%v", writev
), func(t
*testing
.T
) {
685 ln
, err
:= newLocalListener("tcp")
692 x
= x
*5 + 1<<20 // just over 5 GB on 64-bit, just over 1GB on 32-bit
693 done
:= make(chan int)
696 c
, err
:= ln
.Accept()
701 buf
:= make([]byte, x
)
705 n64
, err
= (&Buffers
{buf
}).WriteTo(c
)
708 n
, err
= c
.Write(buf
)
710 if n
!= len(buf
) || err
!= nil {
711 t
.Errorf("Write(buf) = %d, %v, want %d, nil", n
, err
, x
)
716 c
, err
:= Dial("tcp", ln
.Addr().String())
720 buf
:= make([]byte, x
)
721 n
, err
:= io
.ReadFull(c
, buf
)
722 if n
!= len(buf
) || err
!= nil {
723 t
.Errorf("Read(buf) = %d, %v, want %d, nil", n
, err
, x
)