Revert r215321.
[official-gcc.git] / libgo / go / net / tcp_test.go
blobc04198ea000b6f0b81196071f3f225b1d4dddb7c
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.
5 package net
7 import (
8 "fmt"
9 "io"
10 "reflect"
11 "runtime"
12 "sync"
13 "testing"
14 "time"
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) {
34 if !supportsIPv6 {
35 b.Skip("ipv6 is not supported")
37 benchmarkTCP(b, false, false, "[::1]:0")
40 func BenchmarkTCP6OneShotTimeout(b *testing.B) {
41 if !supportsIPv6 {
42 b.Skip("ipv6 is not supported")
44 benchmarkTCP(b, false, true, "[::1]:0")
47 func BenchmarkTCP6Persistent(b *testing.B) {
48 if !supportsIPv6 {
49 b.Skip("ipv6 is not supported")
51 benchmarkTCP(b, true, false, "[::1]:0")
54 func BenchmarkTCP6PersistentTimeout(b *testing.B) {
55 if !supportsIPv6 {
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) {
62 const msgLen = 512
63 conns := b.N
64 numConcurrent := runtime.GOMAXPROCS(-1) * 2
65 msgs := 1
66 if persistent {
67 conns = numConcurrent
68 msgs = b.N / conns
69 if msgs == 0 {
70 msgs = 1
72 if conns > b.N {
73 conns = b.N
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)
80 return false
82 return true
84 recvMsg := func(c Conn, buf []byte) bool {
85 for read := 0; read != len(buf); {
86 n, err := c.Read(buf)
87 read += n
88 if err != nil {
89 b.Logf("Read failed: %v", err)
90 return false
93 return true
95 ln, err := Listen("tcp", laddr)
96 if err != nil {
97 b.Fatalf("Listen failed: %v", err)
99 defer ln.Close()
100 serverSem := make(chan bool, numConcurrent)
101 // Acceptor.
102 go func() {
103 for {
104 c, err := ln.Accept()
105 if err != nil {
106 break
108 serverSem <- true
109 // Server connection.
110 go func(c Conn) {
111 defer func() {
112 c.Close()
113 <-serverSem
115 if timeout {
116 c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
118 var buf [msgLen]byte
119 for m := 0; m < msgs; m++ {
120 if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
121 break
124 }(c)
127 clientSem := make(chan bool, numConcurrent)
128 for i := 0; i < conns; i++ {
129 clientSem <- true
130 // Client connection.
131 go func() {
132 defer func() {
133 <-clientSem
135 c, err := Dial("tcp", ln.Addr().String())
136 if err != nil {
137 b.Logf("Dial failed: %v", err)
138 return
140 defer c.Close()
141 if timeout {
142 c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
144 var buf [msgLen]byte
145 for m := 0; m < msgs; m++ {
146 if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
147 break
152 for i := 0; i < numConcurrent; i++ {
153 clientSem <- true
154 serverSem <- true
158 func BenchmarkTCP4ConcurrentReadWrite(b *testing.B) {
159 benchmarkTCPConcurrentReadWrite(b, "127.0.0.1:0")
162 func BenchmarkTCP6ConcurrentReadWrite(b *testing.B) {
163 if !supportsIPv6 {
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.
175 b.StopTimer()
177 P := runtime.GOMAXPROCS(0)
178 N := b.N / P
179 W := 1000
181 // Setup P client/server connections.
182 clients := make([]Conn, P)
183 servers := make([]Conn, P)
184 ln, err := Listen("tcp", laddr)
185 if err != nil {
186 b.Fatalf("Listen failed: %v", err)
188 defer ln.Close()
189 done := make(chan bool)
190 go func() {
191 for p := 0; p < P; p++ {
192 s, err := ln.Accept()
193 if err != nil {
194 b.Errorf("Accept failed: %v", err)
195 return
197 servers[p] = s
199 done <- true
201 for p := 0; p < P; p++ {
202 c, err := Dial("tcp", ln.Addr().String())
203 if err != nil {
204 b.Fatalf("Dial failed: %v", err)
206 clients[p] = c
208 <-done
210 b.StartTimer()
212 var wg sync.WaitGroup
213 wg.Add(4 * P)
214 for p := 0; p < P; p++ {
215 // Client writer.
216 go func(c Conn) {
217 defer wg.Done()
218 var buf [1]byte
219 for i := 0; i < N; i++ {
220 v := byte(i)
221 for w := 0; w < W; w++ {
222 v *= v
224 buf[0] = v
225 _, err := c.Write(buf[:])
226 if err != nil {
227 b.Errorf("Write failed: %v", err)
228 return
231 }(clients[p])
233 // Pipe between server reader and server writer.
234 pipe := make(chan byte, 128)
236 // Server reader.
237 go func(s Conn) {
238 defer wg.Done()
239 var buf [1]byte
240 for i := 0; i < N; i++ {
241 _, err := s.Read(buf[:])
242 if err != nil {
243 b.Errorf("Read failed: %v", err)
244 return
246 pipe <- buf[0]
248 }(servers[p])
250 // Server writer.
251 go func(s Conn) {
252 defer wg.Done()
253 var buf [1]byte
254 for i := 0; i < N; i++ {
255 v := <-pipe
256 for w := 0; w < W; w++ {
257 v *= v
259 buf[0] = v
260 _, err := s.Write(buf[:])
261 if err != nil {
262 b.Errorf("Write failed: %v", err)
263 return
266 s.Close()
267 }(servers[p])
269 // Client reader.
270 go func(c Conn) {
271 defer wg.Done()
272 var buf [1]byte
273 for i := 0; i < N; i++ {
274 _, err := c.Read(buf[:])
275 if err != nil {
276 b.Errorf("Read failed: %v", err)
277 return
280 c.Close()
281 }(clients[p])
283 wg.Wait()
286 type resolveTCPAddrTest struct {
287 net string
288 litAddrOrName string
289 addr *TCPAddr
290 err error
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")},
311 func init() {
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},
317 }...)
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},
324 }...)
328 func TestResolveTCPAddr(t *testing.T) {
329 for _, tt := range resolveTCPAddrTests {
330 addr, err := ResolveTCPAddr(tt.net, tt.litAddrOrName)
331 if err != tt.err {
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)
337 if err == nil {
338 str := addr.String()
339 addr1, err := ResolveTCPAddr(tt.net, str)
340 if err != nil {
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 {
351 net string
352 laddr *TCPAddr
354 {"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}},
355 {"tcp4", &TCPAddr{}},
356 {"tcp4", nil},
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)
366 if err != nil {
367 t.Fatalf("ListenTCP failed: %v", err)
369 defer ln.Close()
370 la := ln.Addr()
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")
381 if !supportsIPv6 {
382 t.Skip("ipv6 is not supported")
384 ifi := loopbackInterface()
385 if ifi == nil {
386 t.Skip("loopback interface not found")
388 laddr := ipv6LinkLocalUnicastAddr(ifi)
389 if laddr == "" {
390 t.Skip("ipv6 unicast address on loopback not found")
393 type test struct {
394 net, addr string
395 nameLookup bool
397 var tests = []test{
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},
406 }...)
407 case "linux":
408 tests = append(tests, []test{
409 {"tcp", "[ip6-localhost%" + ifi.Name + "]:0", true},
410 {"tcp6", "[ip6-localhost%" + ifi.Name + "]:0", true},
411 }...)
413 for _, tt := range tests {
414 ln, err := Listen(tt.net, tt.addr)
415 if err != nil {
416 // It might return "LookupHost returned no
417 // suitable address" error on some platforms.
418 t.Logf("Listen failed: %v", err)
419 continue
421 defer ln.Close()
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())
430 if err != nil {
431 t.Fatalf("Dial failed: %v", err)
433 defer c.Close()
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)
449 <-done
453 func TestTCPConcurrentAccept(t *testing.T) {
454 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
455 ln, err := Listen("tcp", "127.0.0.1:0")
456 if err != nil {
457 t.Fatalf("Listen failed: %v", err)
459 const N = 10
460 var wg sync.WaitGroup
461 wg.Add(N)
462 for i := 0; i < N; i++ {
463 go func() {
464 for {
465 c, err := ln.Accept()
466 if err != nil {
467 break
469 c.Close()
471 wg.Done()
474 attempts := 10 * N
475 fails := 0
476 d := &Dialer{Timeout: 200 * time.Millisecond}
477 for i := 0; i < attempts; i++ {
478 c, err := d.Dial("tcp", ln.Addr().String())
479 if err != nil {
480 fails++
481 } else {
482 c.Close()
485 ln.Close()
486 wg.Wait()
487 if fails > attempts/9 { // see issues 7400 and 7541
488 t.Fatalf("too many Dial failed: %v", fails)
490 if fails > 0 {
491 t.Logf("# of failed Dials: %v", fails)
495 func TestTCPReadWriteMallocs(t *testing.T) {
496 if testing.Short() {
497 t.Skip("skipping malloc count in short mode")
499 ln, err := Listen("tcp", "127.0.0.1:0")
500 if err != nil {
501 t.Fatalf("Listen failed: %v", err)
503 defer ln.Close()
504 var server Conn
505 errc := make(chan error)
506 go func() {
507 var err error
508 server, err = ln.Accept()
509 errc <- err
511 client, err := Dial("tcp", ln.Addr().String())
512 if err != nil {
513 t.Fatalf("Dial failed: %v", err)
515 if err := <-errc; err != nil {
516 t.Fatalf("Accept failed: %v", err)
518 defer server.Close()
519 var buf [128]byte
520 mallocs := testing.AllocsPerRun(1000, func() {
521 _, err := server.Write(buf[:])
522 if err != nil {
523 t.Fatalf("Write failed: %v", err)
525 _, err = io.ReadFull(client, buf[:])
526 if err != nil {
527 t.Fatalf("Read failed: %v", err)
530 if mallocs > 0 {
531 t.Fatalf("Got %v allocs, want 0", mallocs)
535 func TestTCPStress(t *testing.T) {
536 const conns = 2
537 const msgLen = 512
538 msgs := int(1e4)
539 if testing.Short() {
540 msgs = 1e2
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)
547 return false
549 return true
551 recvMsg := func(c Conn, buf []byte) bool {
552 for read := 0; read != len(buf); {
553 n, err := c.Read(buf)
554 read += n
555 if err != nil {
556 t.Logf("Read failed: %v", err)
557 return false
560 return true
563 ln, err := Listen("tcp", "127.0.0.1:0")
564 if err != nil {
565 t.Fatalf("Listen failed: %v", err)
567 defer ln.Close()
568 // Acceptor.
569 go func() {
570 for {
571 c, err := ln.Accept()
572 if err != nil {
573 break
575 // Server connection.
576 go func(c Conn) {
577 defer c.Close()
578 var buf [msgLen]byte
579 for m := 0; m < msgs; m++ {
580 if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
581 break
584 }(c)
587 done := make(chan bool)
588 for i := 0; i < conns; i++ {
589 // Client connection.
590 go func() {
591 defer func() {
592 done <- true
594 c, err := Dial("tcp", ln.Addr().String())
595 if err != nil {
596 t.Logf("Dial failed: %v", err)
597 return
599 defer c.Close()
600 var buf [msgLen]byte
601 for m := 0; m < msgs; m++ {
602 if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
603 break
608 for i := 0; i < conns; i++ {
609 <-done