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.
17 func BenchmarkTCP4OneShot(b
*testing
.B
) {
18 benchmarkTCP(b
, false, false, "127.0.0.1:0")
21 func BenchmarkTCP4OneShotTimeout(b
*testing
.B
) {
22 benchmarkTCP(b
, false, true, "127.0.0.1:0")
25 func BenchmarkTCP4Persistent(b
*testing
.B
) {
26 benchmarkTCP(b
, true, false, "127.0.0.1:0")
29 func BenchmarkTCP4PersistentTimeout(b
*testing
.B
) {
30 benchmarkTCP(b
, true, true, "127.0.0.1:0")
33 func BenchmarkTCP6OneShot(b
*testing
.B
) {
35 b
.Skip("ipv6 is not supported")
37 benchmarkTCP(b
, false, false, "[::1]:0")
40 func BenchmarkTCP6OneShotTimeout(b
*testing
.B
) {
42 b
.Skip("ipv6 is not supported")
44 benchmarkTCP(b
, false, true, "[::1]:0")
47 func BenchmarkTCP6Persistent(b
*testing
.B
) {
49 b
.Skip("ipv6 is not supported")
51 benchmarkTCP(b
, true, false, "[::1]:0")
54 func BenchmarkTCP6PersistentTimeout(b
*testing
.B
) {
56 b
.Skip("ipv6 is not supported")
58 benchmarkTCP(b
, true, true, "[::1]:0")
61 func benchmarkTCP(b
*testing
.B
, persistent
, timeout
bool, laddr
string) {
64 numConcurrent
:= runtime
.GOMAXPROCS(-1) * 2
76 sendMsg
:= func(c Conn
, buf
[]byte) bool {
77 n
, err
:= c
.Write(buf
)
78 if n
!= len(buf
) || err
!= nil {
79 b
.Logf("Write failed: %v", err
)
84 recvMsg
:= func(c Conn
, buf
[]byte) bool {
85 for read
:= 0; read
!= len(buf
); {
89 b
.Logf("Read failed: %v", err
)
95 ln
, err
:= Listen("tcp", laddr
)
97 b
.Fatalf("Listen failed: %v", err
)
100 serverSem
:= make(chan bool, numConcurrent
)
104 c
, err
:= ln
.Accept()
109 // Server connection.
116 c
.SetDeadline(time
.Now().Add(time
.Hour
)) // Not intended to fire.
119 for m
:= 0; m
< msgs
; m
++ {
120 if !recvMsg(c
, buf
[:]) ||
!sendMsg(c
, buf
[:]) {
127 clientSem
:= make(chan bool, numConcurrent
)
128 for i
:= 0; i
< conns
; i
++ {
130 // Client connection.
135 c
, err
:= Dial("tcp", ln
.Addr().String())
137 b
.Logf("Dial failed: %v", err
)
142 c
.SetDeadline(time
.Now().Add(time
.Hour
)) // Not intended to fire.
145 for m
:= 0; m
< msgs
; m
++ {
146 if !sendMsg(c
, buf
[:]) ||
!recvMsg(c
, buf
[:]) {
152 for i
:= 0; i
< numConcurrent
; i
++ {
158 func BenchmarkTCP4ConcurrentReadWrite(b
*testing
.B
) {
159 benchmarkTCPConcurrentReadWrite(b
, "127.0.0.1:0")
162 func BenchmarkTCP6ConcurrentReadWrite(b
*testing
.B
) {
164 b
.Skip("ipv6 is not supported")
166 benchmarkTCPConcurrentReadWrite(b
, "[::1]:0")
169 func benchmarkTCPConcurrentReadWrite(b
*testing
.B
, laddr
string) {
170 // The benchmark creates GOMAXPROCS client/server pairs.
171 // Each pair creates 4 goroutines: client reader/writer and server reader/writer.
172 // The benchmark stresses concurrent reading and writing to the same connection.
173 // Such pattern is used in net/http and net/rpc.
177 P
:= runtime
.GOMAXPROCS(0)
181 // Setup P client/server connections.
182 clients
:= make([]Conn
, P
)
183 servers
:= make([]Conn
, P
)
184 ln
, err
:= Listen("tcp", laddr
)
186 b
.Fatalf("Listen failed: %v", err
)
189 done
:= make(chan bool)
191 for p
:= 0; p
< P
; p
++ {
192 s
, err
:= ln
.Accept()
194 b
.Errorf("Accept failed: %v", err
)
201 for p
:= 0; p
< P
; p
++ {
202 c
, err
:= Dial("tcp", ln
.Addr().String())
204 b
.Fatalf("Dial failed: %v", err
)
212 var wg sync
.WaitGroup
214 for p
:= 0; p
< P
; p
++ {
219 for i
:= 0; i
< N
; i
++ {
221 for w
:= 0; w
< W
; w
++ {
225 _
, err
:= c
.Write(buf
[:])
227 b
.Errorf("Write failed: %v", err
)
233 // Pipe between server reader and server writer.
234 pipe
:= make(chan byte, 128)
240 for i
:= 0; i
< N
; i
++ {
241 _
, err
:= s
.Read(buf
[:])
243 b
.Errorf("Read failed: %v", err
)
254 for i
:= 0; i
< N
; i
++ {
256 for w
:= 0; w
< W
; w
++ {
260 _
, err
:= s
.Write(buf
[:])
262 b
.Errorf("Write failed: %v", err
)
273 for i
:= 0; i
< N
; i
++ {
274 _
, err
:= c
.Read(buf
[:])
276 b
.Errorf("Read failed: %v", err
)
286 type resolveTCPAddrTest
struct {
293 var resolveTCPAddrTests
= []resolveTCPAddrTest
{
294 {"tcp", "127.0.0.1:0", &TCPAddr
{IP
: IPv4(127, 0, 0, 1), Port
: 0}, nil},
295 {"tcp4", "127.0.0.1:65535", &TCPAddr
{IP
: IPv4(127, 0, 0, 1), Port
: 65535}, nil},
297 {"tcp", "[::1]:1", &TCPAddr
{IP
: ParseIP("::1"), Port
: 1}, nil},
298 {"tcp6", "[::1]:65534", &TCPAddr
{IP
: ParseIP("::1"), Port
: 65534}, nil},
300 {"tcp", "[::1%en0]:1", &TCPAddr
{IP
: ParseIP("::1"), Port
: 1, Zone
: "en0"}, nil},
301 {"tcp6", "[::1%911]:2", &TCPAddr
{IP
: ParseIP("::1"), Port
: 2, Zone
: "911"}, nil},
303 {"", "127.0.0.1:0", &TCPAddr
{IP
: IPv4(127, 0, 0, 1), Port
: 0}, nil}, // Go 1.0 behavior
304 {"", "[::1]:0", &TCPAddr
{IP
: ParseIP("::1"), Port
: 0}, nil}, // Go 1.0 behavior
306 {"tcp", ":12345", &TCPAddr
{Port
: 12345}, nil},
308 {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
312 if ifi
:= loopbackInterface(); ifi
!= nil {
313 index
:= fmt
.Sprintf("%v", ifi
.Index
)
314 resolveTCPAddrTests
= append(resolveTCPAddrTests
, []resolveTCPAddrTest
{
315 {"tcp6", "[fe80::1%" + ifi
.Name
+ "]:3", &TCPAddr
{IP
: ParseIP("fe80::1"), Port
: 3, Zone
: zoneToString(ifi
.Index
)}, nil},
316 {"tcp6", "[fe80::1%" + index
+ "]:4", &TCPAddr
{IP
: ParseIP("fe80::1"), Port
: 4, Zone
: index
}, nil},
319 if ips
, err
:= LookupIP("localhost"); err
== nil && len(ips
) > 1 && supportsIPv4
&& supportsIPv6
{
320 resolveTCPAddrTests
= append(resolveTCPAddrTests
, []resolveTCPAddrTest
{
321 {"tcp", "localhost:5", &TCPAddr
{IP
: IPv4(127, 0, 0, 1), Port
: 5}, nil},
322 {"tcp4", "localhost:6", &TCPAddr
{IP
: IPv4(127, 0, 0, 1), Port
: 6}, nil},
323 {"tcp6", "localhost:7", &TCPAddr
{IP
: IPv6loopback
, Port
: 7}, nil},
328 func TestResolveTCPAddr(t
*testing
.T
) {
329 for _
, tt
:= range resolveTCPAddrTests
{
330 addr
, err
:= ResolveTCPAddr(tt
.net
, tt
.litAddrOrName
)
332 t
.Fatalf("ResolveTCPAddr(%q, %q) failed: %v", tt
.net
, tt
.litAddrOrName
, err
)
334 if !reflect
.DeepEqual(addr
, tt
.addr
) {
335 t
.Fatalf("ResolveTCPAddr(%q, %q) = %#v, want %#v", tt
.net
, tt
.litAddrOrName
, addr
, tt
.addr
)
339 addr1
, err
:= ResolveTCPAddr(tt
.net
, str
)
341 t
.Fatalf("ResolveTCPAddr(%q, %q) [from %q]: %v", tt
.net
, str
, tt
.litAddrOrName
, err
)
343 if !reflect
.DeepEqual(addr1
, addr
) {
344 t
.Fatalf("ResolveTCPAddr(%q, %q) [from %q] = %#v, want %#v", tt
.net
, str
, tt
.litAddrOrName
, addr1
, addr
)
350 var tcpListenerNameTests
= []struct {
354 {"tcp4", &TCPAddr
{IP
: IPv4(127, 0, 0, 1)}},
355 {"tcp4", &TCPAddr
{}},
359 func TestTCPListenerName(t
*testing
.T
) {
360 if testing
.Short() ||
!*testExternal
{
361 t
.Skip("skipping test to avoid external network")
364 for _
, tt
:= range tcpListenerNameTests
{
365 ln
, err
:= ListenTCP(tt
.net
, tt
.laddr
)
367 t
.Fatalf("ListenTCP failed: %v", err
)
371 if a
, ok
:= la
.(*TCPAddr
); !ok || a
.Port
== 0 {
372 t
.Fatalf("got %v; expected a proper address with non-zero port number", la
)
377 func TestIPv6LinkLocalUnicastTCP(t
*testing
.T
) {
378 if testing
.Short() ||
!*testExternal
{
379 t
.Skip("skipping test to avoid external network")
382 t
.Skip("ipv6 is not supported")
384 ifi
:= loopbackInterface()
386 t
.Skip("loopback interface not found")
388 laddr
:= ipv6LinkLocalUnicastAddr(ifi
)
390 t
.Skip("ipv6 unicast address on loopback not found")
398 {"tcp", "[" + laddr
+ "%" + ifi
.Name
+ "]:0", false},
399 {"tcp6", "[" + laddr
+ "%" + ifi
.Name
+ "]:0", false},
401 switch runtime
.GOOS
{
402 case "darwin", "freebsd", "openbsd", "netbsd":
403 tests
= append(tests
, []test
{
404 {"tcp", "[localhost%" + ifi
.Name
+ "]:0", true},
405 {"tcp6", "[localhost%" + ifi
.Name
+ "]:0", true},
408 tests
= append(tests
, []test
{
409 {"tcp", "[ip6-localhost%" + ifi
.Name
+ "]:0", true},
410 {"tcp6", "[ip6-localhost%" + ifi
.Name
+ "]:0", true},
413 for _
, tt
:= range tests
{
414 ln
, err
:= Listen(tt
.net
, tt
.addr
)
416 // It might return "LookupHost returned no
417 // suitable address" error on some platforms.
418 t
.Logf("Listen failed: %v", err
)
422 if la
, ok
:= ln
.Addr().(*TCPAddr
); !ok ||
!tt
.nameLookup
&& la
.Zone
== "" {
423 t
.Fatalf("got %v; expected a proper address with zone identifier", la
)
426 done
:= make(chan int)
427 go transponder(t
, ln
, done
)
429 c
, err
:= Dial(tt
.net
, ln
.Addr().String())
431 t
.Fatalf("Dial failed: %v", err
)
434 if la
, ok
:= c
.LocalAddr().(*TCPAddr
); !ok ||
!tt
.nameLookup
&& la
.Zone
== "" {
435 t
.Fatalf("got %v; expected a proper address with zone identifier", la
)
437 if ra
, ok
:= c
.RemoteAddr().(*TCPAddr
); !ok ||
!tt
.nameLookup
&& ra
.Zone
== "" {
438 t
.Fatalf("got %v; expected a proper address with zone identifier", ra
)
441 if _
, err
:= c
.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err
!= nil {
442 t
.Fatalf("Conn.Write failed: %v", err
)
444 b
:= make([]byte, 32)
445 if _
, err
:= c
.Read(b
); err
!= nil {
446 t
.Fatalf("Conn.Read failed: %v", err
)
453 func TestTCPConcurrentAccept(t
*testing
.T
) {
454 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(4))
455 ln
, err
:= Listen("tcp", "127.0.0.1:0")
457 t
.Fatalf("Listen failed: %v", err
)
460 var wg sync
.WaitGroup
462 for i
:= 0; i
< N
; i
++ {
465 c
, err
:= ln
.Accept()
476 d
:= &Dialer
{Timeout
: 200 * time
.Millisecond
}
477 for i
:= 0; i
< attempts
; i
++ {
478 c
, err
:= d
.Dial("tcp", ln
.Addr().String())
487 if fails
> attempts
/9 { // see issues 7400 and 7541
488 t
.Fatalf("too many Dial failed: %v", fails
)
491 t
.Logf("# of failed Dials: %v", fails
)
495 func TestTCPReadWriteMallocs(t
*testing
.T
) {
497 t
.Skip("skipping malloc count in short mode")
499 ln
, err
:= Listen("tcp", "127.0.0.1:0")
501 t
.Fatalf("Listen failed: %v", err
)
505 errc
:= make(chan error
)
508 server
, err
= ln
.Accept()
511 client
, err
:= Dial("tcp", ln
.Addr().String())
513 t
.Fatalf("Dial failed: %v", err
)
515 if err
:= <-errc
; err
!= nil {
516 t
.Fatalf("Accept failed: %v", err
)
520 mallocs
:= testing
.AllocsPerRun(1000, func() {
521 _
, err
:= server
.Write(buf
[:])
523 t
.Fatalf("Write failed: %v", err
)
525 _
, err
= io
.ReadFull(client
, buf
[:])
527 t
.Fatalf("Read failed: %v", err
)
531 t
.Fatalf("Got %v allocs, want 0", mallocs
)
535 func TestTCPStress(t
*testing
.T
) {
543 sendMsg
:= func(c Conn
, buf
[]byte) bool {
544 n
, err
:= c
.Write(buf
)
545 if n
!= len(buf
) || err
!= nil {
546 t
.Logf("Write failed: %v", err
)
551 recvMsg
:= func(c Conn
, buf
[]byte) bool {
552 for read
:= 0; read
!= len(buf
); {
553 n
, err
:= c
.Read(buf
)
556 t
.Logf("Read failed: %v", err
)
563 ln
, err
:= Listen("tcp", "127.0.0.1:0")
565 t
.Fatalf("Listen failed: %v", err
)
571 c
, err
:= ln
.Accept()
575 // Server connection.
579 for m
:= 0; m
< msgs
; m
++ {
580 if !recvMsg(c
, buf
[:]) ||
!sendMsg(c
, buf
[:]) {
587 done
:= make(chan bool)
588 for i
:= 0; i
< conns
; i
++ {
589 // Client connection.
594 c
, err
:= Dial("tcp", ln
.Addr().String())
596 t
.Logf("Dial failed: %v", err
)
601 for m
:= 0; m
< msgs
; m
++ {
602 if !sendMsg(c
, buf
[:]) ||
!recvMsg(c
, buf
[:]) {
608 for i
:= 0; i
< conns
; i
++ {