2017-07-18 François Dumont <fdumont@gcc.gnu.org>
[official-gcc.git] / libgo / go / net / listen_test.go
blob6037f3600df7f8d5666cbe81439733fb152de817
1 // Copyright 2011 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 // +build !plan9
7 package net
9 import (
10 "fmt"
11 "internal/testenv"
12 "os"
13 "runtime"
14 "syscall"
15 "testing"
18 func (ln *TCPListener) port() string {
19 _, port, err := SplitHostPort(ln.Addr().String())
20 if err != nil {
21 return ""
23 return port
26 func (c *UDPConn) port() string {
27 _, port, err := SplitHostPort(c.LocalAddr().String())
28 if err != nil {
29 return ""
31 return port
34 var tcpListenerTests = []struct {
35 network string
36 address string
38 {"tcp", ""},
39 {"tcp", "0.0.0.0"},
40 {"tcp", "::ffff:0.0.0.0"},
41 {"tcp", "::"},
43 {"tcp", "127.0.0.1"},
44 {"tcp", "::ffff:127.0.0.1"},
45 {"tcp", "::1"},
47 {"tcp4", ""},
48 {"tcp4", "0.0.0.0"},
49 {"tcp4", "::ffff:0.0.0.0"},
51 {"tcp4", "127.0.0.1"},
52 {"tcp4", "::ffff:127.0.0.1"},
54 {"tcp6", ""},
55 {"tcp6", "::"},
57 {"tcp6", "::1"},
60 // TestTCPListener tests both single and double listen to a test
61 // listener with same address family, same listening address and
62 // same port.
63 func TestTCPListener(t *testing.T) {
64 switch runtime.GOOS {
65 case "plan9":
66 t.Skipf("not supported on %s", runtime.GOOS)
69 for _, tt := range tcpListenerTests {
70 if !testableListenArgs(tt.network, JoinHostPort(tt.address, "0"), "") {
71 t.Logf("skipping %s test", tt.network+" "+tt.address)
72 continue
75 ln1, err := Listen(tt.network, JoinHostPort(tt.address, "0"))
76 if err != nil {
77 t.Fatal(err)
79 if err := checkFirstListener(tt.network, ln1); err != nil {
80 ln1.Close()
81 t.Fatal(err)
83 ln2, err := Listen(tt.network, JoinHostPort(tt.address, ln1.(*TCPListener).port()))
84 if err == nil {
85 ln2.Close()
87 if err := checkSecondListener(tt.network, tt.address, err); err != nil {
88 ln1.Close()
89 t.Fatal(err)
91 ln1.Close()
95 var udpListenerTests = []struct {
96 network string
97 address string
99 {"udp", ""},
100 {"udp", "0.0.0.0"},
101 {"udp", "::ffff:0.0.0.0"},
102 {"udp", "::"},
104 {"udp", "127.0.0.1"},
105 {"udp", "::ffff:127.0.0.1"},
106 {"udp", "::1"},
108 {"udp4", ""},
109 {"udp4", "0.0.0.0"},
110 {"udp4", "::ffff:0.0.0.0"},
112 {"udp4", "127.0.0.1"},
113 {"udp4", "::ffff:127.0.0.1"},
115 {"udp6", ""},
116 {"udp6", "::"},
118 {"udp6", "::1"},
121 // TestUDPListener tests both single and double listen to a test
122 // listener with same address family, same listening address and
123 // same port.
124 func TestUDPListener(t *testing.T) {
125 switch runtime.GOOS {
126 case "plan9":
127 t.Skipf("not supported on %s", runtime.GOOS)
130 for _, tt := range udpListenerTests {
131 if !testableListenArgs(tt.network, JoinHostPort(tt.address, "0"), "") {
132 t.Logf("skipping %s test", tt.network+" "+tt.address)
133 continue
136 c1, err := ListenPacket(tt.network, JoinHostPort(tt.address, "0"))
137 if err != nil {
138 t.Fatal(err)
140 if err := checkFirstListener(tt.network, c1); err != nil {
141 c1.Close()
142 t.Fatal(err)
144 c2, err := ListenPacket(tt.network, JoinHostPort(tt.address, c1.(*UDPConn).port()))
145 if err == nil {
146 c2.Close()
148 if err := checkSecondListener(tt.network, tt.address, err); err != nil {
149 c1.Close()
150 t.Fatal(err)
152 c1.Close()
156 var dualStackTCPListenerTests = []struct {
157 network1, address1 string // first listener
158 network2, address2 string // second listener
159 xerr error // expected error value, nil or other
161 // Test cases and expected results for the attempting 2nd listen on the same port
162 // 1st listen 2nd listen darwin freebsd linux openbsd
163 // ------------------------------------------------------------------------------------
164 // "tcp" "" "tcp" "" - - - -
165 // "tcp" "" "tcp" "0.0.0.0" - - - -
166 // "tcp" "0.0.0.0" "tcp" "" - - - -
167 // ------------------------------------------------------------------------------------
168 // "tcp" "" "tcp" "[::]" - - - ok
169 // "tcp" "[::]" "tcp" "" - - - ok
170 // "tcp" "0.0.0.0" "tcp" "[::]" - - - ok
171 // "tcp" "[::]" "tcp" "0.0.0.0" - - - ok
172 // "tcp" "[::ffff:0.0.0.0]" "tcp" "[::]" - - - ok
173 // "tcp" "[::]" "tcp" "[::ffff:0.0.0.0]" - - - ok
174 // ------------------------------------------------------------------------------------
175 // "tcp4" "" "tcp6" "" ok ok ok ok
176 // "tcp6" "" "tcp4" "" ok ok ok ok
177 // "tcp4" "0.0.0.0" "tcp6" "[::]" ok ok ok ok
178 // "tcp6" "[::]" "tcp4" "0.0.0.0" ok ok ok ok
179 // ------------------------------------------------------------------------------------
180 // "tcp" "127.0.0.1" "tcp" "[::1]" ok ok ok ok
181 // "tcp" "[::1]" "tcp" "127.0.0.1" ok ok ok ok
182 // "tcp4" "127.0.0.1" "tcp6" "[::1]" ok ok ok ok
183 // "tcp6" "[::1]" "tcp4" "127.0.0.1" ok ok ok ok
185 // Platform default configurations:
186 // darwin, kernel version 11.3.0
187 // net.inet6.ip6.v6only=0 (overridable by sysctl or IPV6_V6ONLY option)
188 // freebsd, kernel version 8.2
189 // net.inet6.ip6.v6only=1 (overridable by sysctl or IPV6_V6ONLY option)
190 // linux, kernel version 3.0.0
191 // net.ipv6.bindv6only=0 (overridable by sysctl or IPV6_V6ONLY option)
192 // openbsd, kernel version 5.0
193 // net.inet6.ip6.v6only=1 (overriding is prohibited)
195 {"tcp", "", "tcp", "", syscall.EADDRINUSE},
196 {"tcp", "", "tcp", "0.0.0.0", syscall.EADDRINUSE},
197 {"tcp", "0.0.0.0", "tcp", "", syscall.EADDRINUSE},
199 {"tcp", "", "tcp", "::", syscall.EADDRINUSE},
200 {"tcp", "::", "tcp", "", syscall.EADDRINUSE},
201 {"tcp", "0.0.0.0", "tcp", "::", syscall.EADDRINUSE},
202 {"tcp", "::", "tcp", "0.0.0.0", syscall.EADDRINUSE},
203 {"tcp", "::ffff:0.0.0.0", "tcp", "::", syscall.EADDRINUSE},
204 {"tcp", "::", "tcp", "::ffff:0.0.0.0", syscall.EADDRINUSE},
206 {"tcp4", "", "tcp6", "", nil},
207 {"tcp6", "", "tcp4", "", nil},
208 {"tcp4", "0.0.0.0", "tcp6", "::", nil},
209 {"tcp6", "::", "tcp4", "0.0.0.0", nil},
211 {"tcp", "127.0.0.1", "tcp", "::1", nil},
212 {"tcp", "::1", "tcp", "127.0.0.1", nil},
213 {"tcp4", "127.0.0.1", "tcp6", "::1", nil},
214 {"tcp6", "::1", "tcp4", "127.0.0.1", nil},
217 // TestDualStackTCPListener tests both single and double listen
218 // to a test listener with various address families, different
219 // listening address and same port.
221 // On DragonFly BSD, we expect the kernel version of node under test
222 // to be greater than or equal to 4.4.
223 func TestDualStackTCPListener(t *testing.T) {
224 switch runtime.GOOS {
225 case "nacl", "plan9":
226 t.Skipf("not supported on %s", runtime.GOOS)
228 if !supportsIPv4 || !supportsIPv6 {
229 t.Skip("both IPv4 and IPv6 are required")
232 for _, tt := range dualStackTCPListenerTests {
233 if !testableListenArgs(tt.network1, JoinHostPort(tt.address1, "0"), "") {
234 t.Logf("skipping %s test", tt.network1+" "+tt.address1)
235 continue
238 if !supportsIPv4map && differentWildcardAddr(tt.address1, tt.address2) {
239 tt.xerr = nil
241 var firstErr, secondErr error
242 for i := 0; i < 5; i++ {
243 lns, err := newDualStackListener()
244 if err != nil {
245 t.Fatal(err)
247 port := lns[0].port()
248 for _, ln := range lns {
249 ln.Close()
251 var ln1 Listener
252 ln1, firstErr = Listen(tt.network1, JoinHostPort(tt.address1, port))
253 if firstErr != nil {
254 continue
256 if err := checkFirstListener(tt.network1, ln1); err != nil {
257 ln1.Close()
258 t.Fatal(err)
260 ln2, err := Listen(tt.network2, JoinHostPort(tt.address2, ln1.(*TCPListener).port()))
261 if err == nil {
262 ln2.Close()
264 if secondErr = checkDualStackSecondListener(tt.network2, tt.address2, err, tt.xerr); secondErr != nil {
265 ln1.Close()
266 continue
268 ln1.Close()
269 break
271 if firstErr != nil {
272 t.Error(firstErr)
274 if secondErr != nil {
275 t.Error(secondErr)
280 var dualStackUDPListenerTests = []struct {
281 network1, address1 string // first listener
282 network2, address2 string // second listener
283 xerr error // expected error value, nil or other
285 {"udp", "", "udp", "", syscall.EADDRINUSE},
286 {"udp", "", "udp", "0.0.0.0", syscall.EADDRINUSE},
287 {"udp", "0.0.0.0", "udp", "", syscall.EADDRINUSE},
289 {"udp", "", "udp", "::", syscall.EADDRINUSE},
290 {"udp", "::", "udp", "", syscall.EADDRINUSE},
291 {"udp", "0.0.0.0", "udp", "::", syscall.EADDRINUSE},
292 {"udp", "::", "udp", "0.0.0.0", syscall.EADDRINUSE},
293 {"udp", "::ffff:0.0.0.0", "udp", "::", syscall.EADDRINUSE},
294 {"udp", "::", "udp", "::ffff:0.0.0.0", syscall.EADDRINUSE},
296 {"udp4", "", "udp6", "", nil},
297 {"udp6", "", "udp4", "", nil},
298 {"udp4", "0.0.0.0", "udp6", "::", nil},
299 {"udp6", "::", "udp4", "0.0.0.0", nil},
301 {"udp", "127.0.0.1", "udp", "::1", nil},
302 {"udp", "::1", "udp", "127.0.0.1", nil},
303 {"udp4", "127.0.0.1", "udp6", "::1", nil},
304 {"udp6", "::1", "udp4", "127.0.0.1", nil},
307 // TestDualStackUDPListener tests both single and double listen
308 // to a test listener with various address families, different
309 // listening address and same port.
311 // On DragonFly BSD, we expect the kernel version of node under test
312 // to be greater than or equal to 4.4.
313 func TestDualStackUDPListener(t *testing.T) {
314 switch runtime.GOOS {
315 case "nacl", "plan9":
316 t.Skipf("not supported on %s", runtime.GOOS)
318 if !supportsIPv4 || !supportsIPv6 {
319 t.Skip("both IPv4 and IPv6 are required")
322 for _, tt := range dualStackUDPListenerTests {
323 if !testableListenArgs(tt.network1, JoinHostPort(tt.address1, "0"), "") {
324 t.Logf("skipping %s test", tt.network1+" "+tt.address1)
325 continue
328 if !supportsIPv4map && differentWildcardAddr(tt.address1, tt.address2) {
329 tt.xerr = nil
331 var firstErr, secondErr error
332 for i := 0; i < 5; i++ {
333 cs, err := newDualStackPacketListener()
334 if err != nil {
335 t.Fatal(err)
337 port := cs[0].port()
338 for _, c := range cs {
339 c.Close()
341 var c1 PacketConn
342 c1, firstErr = ListenPacket(tt.network1, JoinHostPort(tt.address1, port))
343 if firstErr != nil {
344 continue
346 if err := checkFirstListener(tt.network1, c1); err != nil {
347 c1.Close()
348 t.Fatal(err)
350 c2, err := ListenPacket(tt.network2, JoinHostPort(tt.address2, c1.(*UDPConn).port()))
351 if err == nil {
352 c2.Close()
354 if secondErr = checkDualStackSecondListener(tt.network2, tt.address2, err, tt.xerr); secondErr != nil {
355 c1.Close()
356 continue
358 c1.Close()
359 break
361 if firstErr != nil {
362 t.Error(firstErr)
364 if secondErr != nil {
365 t.Error(secondErr)
370 func differentWildcardAddr(i, j string) bool {
371 if (i == "" || i == "0.0.0.0" || i == "::ffff:0.0.0.0") && (j == "" || j == "0.0.0.0" || j == "::ffff:0.0.0.0") {
372 return false
374 if i == "[::]" && j == "[::]" {
375 return false
377 return true
380 func checkFirstListener(network string, ln interface{}) error {
381 switch network {
382 case "tcp":
383 fd := ln.(*TCPListener).fd
384 if err := checkDualStackAddrFamily(fd); err != nil {
385 return err
387 case "tcp4":
388 fd := ln.(*TCPListener).fd
389 if fd.family != syscall.AF_INET {
390 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET)
392 case "tcp6":
393 fd := ln.(*TCPListener).fd
394 if fd.family != syscall.AF_INET6 {
395 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET6)
397 case "udp":
398 fd := ln.(*UDPConn).fd
399 if err := checkDualStackAddrFamily(fd); err != nil {
400 return err
402 case "udp4":
403 fd := ln.(*UDPConn).fd
404 if fd.family != syscall.AF_INET {
405 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET)
407 case "udp6":
408 fd := ln.(*UDPConn).fd
409 if fd.family != syscall.AF_INET6 {
410 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET6)
412 default:
413 return UnknownNetworkError(network)
415 return nil
418 func checkSecondListener(network, address string, err error) error {
419 switch network {
420 case "tcp", "tcp4", "tcp6":
421 if err == nil {
422 return fmt.Errorf("%s should fail", network+" "+address)
424 case "udp", "udp4", "udp6":
425 if err == nil {
426 return fmt.Errorf("%s should fail", network+" "+address)
428 default:
429 return UnknownNetworkError(network)
431 return nil
434 func checkDualStackSecondListener(network, address string, err, xerr error) error {
435 switch network {
436 case "tcp", "tcp4", "tcp6":
437 if xerr == nil && err != nil || xerr != nil && err == nil {
438 return fmt.Errorf("%s got %v; want %v", network+" "+address, err, xerr)
440 case "udp", "udp4", "udp6":
441 if xerr == nil && err != nil || xerr != nil && err == nil {
442 return fmt.Errorf("%s got %v; want %v", network+" "+address, err, xerr)
444 default:
445 return UnknownNetworkError(network)
447 return nil
450 func checkDualStackAddrFamily(fd *netFD) error {
451 switch a := fd.laddr.(type) {
452 case *TCPAddr:
453 // If a node under test supports both IPv6 capability
454 // and IPv6 IPv4-mapping capability, we can assume
455 // that the node listens on a wildcard address with an
456 // AF_INET6 socket.
457 if supportsIPv4map && fd.laddr.(*TCPAddr).isWildcard() {
458 if fd.family != syscall.AF_INET6 {
459 return fmt.Errorf("Listen(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, syscall.AF_INET6)
461 } else {
462 if fd.family != a.family() {
463 return fmt.Errorf("Listen(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, a.family())
466 case *UDPAddr:
467 // If a node under test supports both IPv6 capability
468 // and IPv6 IPv4-mapping capability, we can assume
469 // that the node listens on a wildcard address with an
470 // AF_INET6 socket.
471 if supportsIPv4map && fd.laddr.(*UDPAddr).isWildcard() {
472 if fd.family != syscall.AF_INET6 {
473 return fmt.Errorf("ListenPacket(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, syscall.AF_INET6)
475 } else {
476 if fd.family != a.family() {
477 return fmt.Errorf("ListenPacket(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, a.family())
480 default:
481 return fmt.Errorf("unexpected protocol address type: %T", a)
483 return nil
486 func TestWildWildcardListener(t *testing.T) {
487 testenv.MustHaveExternalNetwork(t)
489 switch runtime.GOOS {
490 case "plan9":
491 t.Skipf("not supported on %s", runtime.GOOS)
494 defer func() {
495 if p := recover(); p != nil {
496 t.Fatalf("panicked: %v", p)
500 if ln, err := Listen("tcp", ""); err == nil {
501 ln.Close()
503 if ln, err := ListenPacket("udp", ""); err == nil {
504 ln.Close()
506 if ln, err := ListenTCP("tcp", nil); err == nil {
507 ln.Close()
509 if ln, err := ListenUDP("udp", nil); err == nil {
510 ln.Close()
512 if ln, err := ListenIP("ip:icmp", nil); err == nil {
513 ln.Close()
517 var ipv4MulticastListenerTests = []struct {
518 net string
519 gaddr *UDPAddr // see RFC 4727
521 {"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
523 {"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
526 // TestIPv4MulticastListener tests both single and double listen to a
527 // test listener with same address family, same group address and same
528 // port.
529 func TestIPv4MulticastListener(t *testing.T) {
530 testenv.MustHaveExternalNetwork(t)
532 switch runtime.GOOS {
533 case "android", "nacl", "plan9":
534 t.Skipf("not supported on %s", runtime.GOOS)
535 case "solaris":
536 t.Skipf("not supported on solaris, see golang.org/issue/7399")
538 if !supportsIPv4 {
539 t.Skip("IPv4 is not supported")
542 closer := func(cs []*UDPConn) {
543 for _, c := range cs {
544 if c != nil {
545 c.Close()
550 for _, ifi := range []*Interface{loopbackInterface(), nil} {
551 // Note that multicast interface assignment by system
552 // is not recommended because it usually relies on
553 // routing stuff for finding out an appropriate
554 // nexthop containing both network and link layer
555 // adjacencies.
556 if ifi == nil || !*testIPv4 {
557 continue
559 for _, tt := range ipv4MulticastListenerTests {
560 var err error
561 cs := make([]*UDPConn, 2)
562 if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
563 t.Fatal(err)
565 if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
566 closer(cs)
567 t.Fatal(err)
569 if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
570 closer(cs)
571 t.Fatal(err)
573 if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
574 closer(cs)
575 t.Fatal(err)
577 closer(cs)
582 var ipv6MulticastListenerTests = []struct {
583 net string
584 gaddr *UDPAddr // see RFC 4727
586 {"udp", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
587 {"udp", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
588 {"udp", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
589 {"udp", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
590 {"udp", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
591 {"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
593 {"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
594 {"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
595 {"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
596 {"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
597 {"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
598 {"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
601 // TestIPv6MulticastListener tests both single and double listen to a
602 // test listener with same address family, same group address and same
603 // port.
604 func TestIPv6MulticastListener(t *testing.T) {
605 testenv.MustHaveExternalNetwork(t)
607 switch runtime.GOOS {
608 case "plan9":
609 t.Skipf("not supported on %s", runtime.GOOS)
610 case "solaris":
611 t.Skipf("not supported on solaris, see issue 7399")
613 if !supportsIPv6 {
614 t.Skip("IPv6 is not supported")
616 if os.Getuid() != 0 {
617 t.Skip("must be root")
620 closer := func(cs []*UDPConn) {
621 for _, c := range cs {
622 if c != nil {
623 c.Close()
628 for _, ifi := range []*Interface{loopbackInterface(), nil} {
629 // Note that multicast interface assignment by system
630 // is not recommended because it usually relies on
631 // routing stuff for finding out an appropriate
632 // nexthop containing both network and link layer
633 // adjacencies.
634 if ifi == nil && !*testIPv6 {
635 continue
637 for _, tt := range ipv6MulticastListenerTests {
638 var err error
639 cs := make([]*UDPConn, 2)
640 if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
641 t.Fatal(err)
643 if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
644 closer(cs)
645 t.Fatal(err)
647 if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
648 closer(cs)
649 t.Fatal(err)
651 if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
652 closer(cs)
653 t.Fatal(err)
655 closer(cs)
660 func checkMulticastListener(c *UDPConn, ip IP) error {
661 if ok, err := multicastRIBContains(ip); err != nil {
662 return err
663 } else if !ok {
664 return fmt.Errorf("%s not found in multicast rib", ip.String())
666 la := c.LocalAddr()
667 if la, ok := la.(*UDPAddr); !ok || la.Port == 0 {
668 return fmt.Errorf("got %v; want a proper address with non-zero port number", la)
670 return nil
673 func multicastRIBContains(ip IP) (bool, error) {
674 switch runtime.GOOS {
675 case "dragonfly", "netbsd", "openbsd", "plan9", "solaris", "windows":
676 return true, nil // not implemented yet
677 case "linux":
678 if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
679 return true, nil // not implemented yet
682 ift, err := Interfaces()
683 if err != nil {
684 return false, err
686 for _, ifi := range ift {
687 ifmat, err := ifi.MulticastAddrs()
688 if err != nil {
689 return false, err
691 for _, ifma := range ifmat {
692 if ifma.(*IPAddr).IP.Equal(ip) {
693 return true, nil
697 return false, nil