github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/net/unicast_posix_test.go (about)

     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.
     4  
     5  // +build !plan9
     6  
     7  package net
     8  
     9  import (
    10  	"runtime"
    11  	"syscall"
    12  	"testing"
    13  )
    14  
    15  var listenerTests = []struct {
    16  	net      string
    17  	laddr    string
    18  	ipv6     bool // test with underlying AF_INET6 socket
    19  	wildcard bool // test with wildcard address
    20  }{
    21  	{net: "tcp", laddr: "", wildcard: true},
    22  	{net: "tcp", laddr: "0.0.0.0", wildcard: true},
    23  	{net: "tcp", laddr: "[::ffff:0.0.0.0]", wildcard: true},
    24  	{net: "tcp", laddr: "[::]", ipv6: true, wildcard: true},
    25  
    26  	{net: "tcp", laddr: "127.0.0.1"},
    27  	{net: "tcp", laddr: "[::ffff:127.0.0.1]"},
    28  	{net: "tcp", laddr: "[::1]", ipv6: true},
    29  
    30  	{net: "tcp4", laddr: "", wildcard: true},
    31  	{net: "tcp4", laddr: "0.0.0.0", wildcard: true},
    32  	{net: "tcp4", laddr: "[::ffff:0.0.0.0]", wildcard: true},
    33  
    34  	{net: "tcp4", laddr: "127.0.0.1"},
    35  	{net: "tcp4", laddr: "[::ffff:127.0.0.1]"},
    36  
    37  	{net: "tcp6", laddr: "", ipv6: true, wildcard: true},
    38  	{net: "tcp6", laddr: "[::]", ipv6: true, wildcard: true},
    39  
    40  	{net: "tcp6", laddr: "[::1]", ipv6: true},
    41  }
    42  
    43  // TestTCPListener tests both single and double listen to a test
    44  // listener with same address family, same listening address and
    45  // same port.
    46  func TestTCPListener(t *testing.T) {
    47  	switch runtime.GOOS {
    48  	case "plan9":
    49  		t.Skipf("skipping test on %q", runtime.GOOS)
    50  	}
    51  
    52  	for _, tt := range listenerTests {
    53  		if tt.wildcard && (testing.Short() || !*testExternal) {
    54  			continue
    55  		}
    56  		if tt.ipv6 && !supportsIPv6 {
    57  			continue
    58  		}
    59  		l1, port := usableListenPort(t, tt.net, tt.laddr)
    60  		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
    61  		l2, err := Listen(tt.net, tt.laddr+":"+port)
    62  		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
    63  		l1.Close()
    64  	}
    65  }
    66  
    67  // TestUDPListener tests both single and double listen to a test
    68  // listener with same address family, same listening address and
    69  // same port.
    70  func TestUDPListener(t *testing.T) {
    71  	switch runtime.GOOS {
    72  	case "plan9":
    73  		t.Skipf("skipping test on %q", runtime.GOOS)
    74  	}
    75  
    76  	toudpnet := func(net string) string {
    77  		switch net {
    78  		case "tcp":
    79  			return "udp"
    80  		case "tcp4":
    81  			return "udp4"
    82  		case "tcp6":
    83  			return "udp6"
    84  		}
    85  		return "<nil>"
    86  	}
    87  
    88  	for _, tt := range listenerTests {
    89  		if tt.wildcard && (testing.Short() || !*testExternal) {
    90  			continue
    91  		}
    92  		if tt.ipv6 && !supportsIPv6 {
    93  			continue
    94  		}
    95  		tt.net = toudpnet(tt.net)
    96  		l1, port := usableListenPacketPort(t, tt.net, tt.laddr)
    97  		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
    98  		l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
    99  		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
   100  		l1.Close()
   101  	}
   102  }
   103  
   104  var dualStackListenerTests = []struct {
   105  	net1     string // first listener
   106  	laddr1   string
   107  	net2     string // second listener
   108  	laddr2   string
   109  	wildcard bool  // test with wildcard address
   110  	xerr     error // expected error value, nil or other
   111  }{
   112  	// Test cases and expected results for the attemping 2nd listen on the same port
   113  	// 1st listen                2nd listen                 darwin  freebsd  linux  openbsd
   114  	// ------------------------------------------------------------------------------------
   115  	// "tcp"  ""                 "tcp"  ""                    -        -       -       -
   116  	// "tcp"  ""                 "tcp"  "0.0.0.0"             -        -       -       -
   117  	// "tcp"  "0.0.0.0"          "tcp"  ""                    -        -       -       -
   118  	// ------------------------------------------------------------------------------------
   119  	// "tcp"  ""                 "tcp"  "[::]"                -        -       -       ok
   120  	// "tcp"  "[::]"             "tcp"  ""                    -        -       -       ok
   121  	// "tcp"  "0.0.0.0"          "tcp"  "[::]"                -        -       -       ok
   122  	// "tcp"  "[::]"             "tcp"  "0.0.0.0"             -        -       -       ok
   123  	// "tcp"  "[::ffff:0.0.0.0]" "tcp"  "[::]"                -        -       -       ok
   124  	// "tcp"  "[::]"             "tcp"  "[::ffff:0.0.0.0]"    -        -       -       ok
   125  	// ------------------------------------------------------------------------------------
   126  	// "tcp4" ""                 "tcp6" ""                    ok       ok      ok      ok
   127  	// "tcp6" ""                 "tcp4" ""                    ok       ok      ok      ok
   128  	// "tcp4" "0.0.0.0"          "tcp6" "[::]"                ok       ok      ok      ok
   129  	// "tcp6" "[::]"             "tcp4" "0.0.0.0"             ok       ok      ok      ok
   130  	// ------------------------------------------------------------------------------------
   131  	// "tcp"  "127.0.0.1"        "tcp"  "[::1]"               ok       ok      ok      ok
   132  	// "tcp"  "[::1]"            "tcp"  "127.0.0.1"           ok       ok      ok      ok
   133  	// "tcp4" "127.0.0.1"        "tcp6" "[::1]"               ok       ok      ok      ok
   134  	// "tcp6" "[::1]"            "tcp4" "127.0.0.1"           ok       ok      ok      ok
   135  	//
   136  	// Platform default configurations:
   137  	// darwin, kernel version 11.3.0
   138  	//	net.inet6.ip6.v6only=0 (overridable by sysctl or IPV6_V6ONLY option)
   139  	// freebsd, kernel version 8.2
   140  	//	net.inet6.ip6.v6only=1 (overridable by sysctl or IPV6_V6ONLY option)
   141  	// linux, kernel version 3.0.0
   142  	//	net.ipv6.bindv6only=0 (overridable by sysctl or IPV6_V6ONLY option)
   143  	// openbsd, kernel version 5.0
   144  	//	net.inet6.ip6.v6only=1 (overriding is prohibited)
   145  
   146  	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
   147  	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "0.0.0.0", wildcard: true, xerr: syscall.EADDRINUSE},
   148  	{net1: "tcp", laddr1: "0.0.0.0", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
   149  
   150  	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
   151  	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
   152  	{net1: "tcp", laddr1: "0.0.0.0", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
   153  	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "0.0.0.0", wildcard: true, xerr: syscall.EADDRINUSE},
   154  	{net1: "tcp", laddr1: "[::ffff:0.0.0.0]", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
   155  	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "[::ffff:0.0.0.0]", wildcard: true, xerr: syscall.EADDRINUSE},
   156  
   157  	{net1: "tcp4", laddr1: "", net2: "tcp6", laddr2: "", wildcard: true},
   158  	{net1: "tcp6", laddr1: "", net2: "tcp4", laddr2: "", wildcard: true},
   159  	{net1: "tcp4", laddr1: "0.0.0.0", net2: "tcp6", laddr2: "[::]", wildcard: true},
   160  	{net1: "tcp6", laddr1: "[::]", net2: "tcp4", laddr2: "0.0.0.0", wildcard: true},
   161  
   162  	{net1: "tcp", laddr1: "127.0.0.1", net2: "tcp", laddr2: "[::1]"},
   163  	{net1: "tcp", laddr1: "[::1]", net2: "tcp", laddr2: "127.0.0.1"},
   164  	{net1: "tcp4", laddr1: "127.0.0.1", net2: "tcp6", laddr2: "[::1]"},
   165  	{net1: "tcp6", laddr1: "[::1]", net2: "tcp4", laddr2: "127.0.0.1"},
   166  }
   167  
   168  // TestDualStackTCPListener tests both single and double listen
   169  // to a test listener with various address families, different
   170  // listening address and same port.
   171  func TestDualStackTCPListener(t *testing.T) {
   172  	if testing.Short() {
   173  		t.Skip("skipping in -short mode, see issue 5001")
   174  	}
   175  	switch runtime.GOOS {
   176  	case "plan9":
   177  		t.Skipf("skipping test on %q", runtime.GOOS)
   178  	}
   179  	if !supportsIPv6 {
   180  		t.Skip("ipv6 is not supported")
   181  	}
   182  
   183  	for _, tt := range dualStackListenerTests {
   184  		if tt.wildcard && !*testExternal {
   185  			continue
   186  		}
   187  		switch runtime.GOOS {
   188  		case "openbsd":
   189  			if tt.wildcard && differentWildcardAddr(tt.laddr1, tt.laddr2) {
   190  				tt.xerr = nil
   191  			}
   192  		}
   193  		l1, port := usableListenPort(t, tt.net1, tt.laddr1)
   194  		laddr := tt.laddr1 + ":" + port
   195  		checkFirstListener(t, tt.net1, laddr, l1)
   196  		laddr = tt.laddr2 + ":" + port
   197  		l2, err := Listen(tt.net2, laddr)
   198  		checkDualStackSecondListener(t, tt.net2, laddr, tt.xerr, err, l2)
   199  		l1.Close()
   200  	}
   201  }
   202  
   203  // TestDualStackUDPListener tests both single and double listen
   204  // to a test listener with various address families, differnet
   205  // listening address and same port.
   206  func TestDualStackUDPListener(t *testing.T) {
   207  	if testing.Short() {
   208  		t.Skip("skipping in -short mode, see issue 5001")
   209  	}
   210  	switch runtime.GOOS {
   211  	case "plan9":
   212  		t.Skipf("skipping test on %q", runtime.GOOS)
   213  	}
   214  	if !supportsIPv6 {
   215  		t.Skip("ipv6 is not supported")
   216  	}
   217  
   218  	toudpnet := func(net string) string {
   219  		switch net {
   220  		case "tcp":
   221  			return "udp"
   222  		case "tcp4":
   223  			return "udp4"
   224  		case "tcp6":
   225  			return "udp6"
   226  		}
   227  		return "<nil>"
   228  	}
   229  
   230  	for _, tt := range dualStackListenerTests {
   231  		if tt.wildcard && (testing.Short() || !*testExternal) {
   232  			continue
   233  		}
   234  		tt.net1 = toudpnet(tt.net1)
   235  		tt.net2 = toudpnet(tt.net2)
   236  		switch runtime.GOOS {
   237  		case "openbsd":
   238  			if tt.wildcard && differentWildcardAddr(tt.laddr1, tt.laddr2) {
   239  				tt.xerr = nil
   240  			}
   241  		}
   242  		l1, port := usableListenPacketPort(t, tt.net1, tt.laddr1)
   243  		laddr := tt.laddr1 + ":" + port
   244  		checkFirstListener(t, tt.net1, laddr, l1)
   245  		laddr = tt.laddr2 + ":" + port
   246  		l2, err := ListenPacket(tt.net2, laddr)
   247  		checkDualStackSecondListener(t, tt.net2, laddr, tt.xerr, err, l2)
   248  		l1.Close()
   249  	}
   250  }
   251  
   252  func usableListenPort(t *testing.T, net, laddr string) (l Listener, port string) {
   253  	var nladdr string
   254  	var err error
   255  	switch net {
   256  	default:
   257  		panic("usableListenPort net=" + net)
   258  	case "tcp", "tcp4", "tcp6":
   259  		l, err = Listen(net, laddr+":0")
   260  		if err != nil {
   261  			t.Fatalf("Probe Listen(%q, %q) failed: %v", net, laddr, err)
   262  		}
   263  		nladdr = l.(*TCPListener).Addr().String()
   264  	}
   265  	_, port, err = SplitHostPort(nladdr)
   266  	if err != nil {
   267  		t.Fatalf("SplitHostPort failed: %v", err)
   268  	}
   269  	return l, port
   270  }
   271  
   272  func usableListenPacketPort(t *testing.T, net, laddr string) (l PacketConn, port string) {
   273  	var nladdr string
   274  	var err error
   275  	switch net {
   276  	default:
   277  		panic("usableListenPacketPort net=" + net)
   278  	case "udp", "udp4", "udp6":
   279  		l, err = ListenPacket(net, laddr+":0")
   280  		if err != nil {
   281  			t.Fatalf("Probe ListenPacket(%q, %q) failed: %v", net, laddr, err)
   282  		}
   283  		nladdr = l.(*UDPConn).LocalAddr().String()
   284  	}
   285  	_, port, err = SplitHostPort(nladdr)
   286  	if err != nil {
   287  		t.Fatalf("SplitHostPort failed: %v", err)
   288  	}
   289  	return l, port
   290  }
   291  
   292  func differentWildcardAddr(i, j string) bool {
   293  	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") {
   294  		return false
   295  	}
   296  	if i == "[::]" && j == "[::]" {
   297  		return false
   298  	}
   299  	return true
   300  }
   301  
   302  func checkFirstListener(t *testing.T, net, laddr string, l interface{}) {
   303  	switch net {
   304  	case "tcp":
   305  		fd := l.(*TCPListener).fd
   306  		checkDualStackAddrFamily(t, net, laddr, fd)
   307  	case "tcp4":
   308  		fd := l.(*TCPListener).fd
   309  		if fd.family != syscall.AF_INET {
   310  			t.Fatalf("First Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET)
   311  		}
   312  	case "tcp6":
   313  		fd := l.(*TCPListener).fd
   314  		if fd.family != syscall.AF_INET6 {
   315  			t.Fatalf("First Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
   316  		}
   317  	case "udp":
   318  		fd := l.(*UDPConn).fd
   319  		checkDualStackAddrFamily(t, net, laddr, fd)
   320  	case "udp4":
   321  		fd := l.(*UDPConn).fd
   322  		if fd.family != syscall.AF_INET {
   323  			t.Fatalf("First ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET)
   324  		}
   325  	case "udp6":
   326  		fd := l.(*UDPConn).fd
   327  		if fd.family != syscall.AF_INET6 {
   328  			t.Fatalf("First ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
   329  		}
   330  	default:
   331  		t.Fatalf("Unexpected network: %q", net)
   332  	}
   333  }
   334  
   335  func checkSecondListener(t *testing.T, net, laddr string, err error, l interface{}) {
   336  	switch net {
   337  	case "tcp", "tcp4", "tcp6":
   338  		if err == nil {
   339  			l.(*TCPListener).Close()
   340  			t.Fatalf("Second Listen(%q, %q) should fail", net, laddr)
   341  		}
   342  	case "udp", "udp4", "udp6":
   343  		if err == nil {
   344  			l.(*UDPConn).Close()
   345  			t.Fatalf("Second ListenPacket(%q, %q) should fail", net, laddr)
   346  		}
   347  	default:
   348  		t.Fatalf("Unexpected network: %q", net)
   349  	}
   350  }
   351  
   352  func checkDualStackSecondListener(t *testing.T, net, laddr string, xerr, err error, l interface{}) {
   353  	switch net {
   354  	case "tcp", "tcp4", "tcp6":
   355  		if xerr == nil && err != nil || xerr != nil && err == nil {
   356  			t.Fatalf("Second Listen(%q, %q) returns %v, expected %v", net, laddr, err, xerr)
   357  		}
   358  		if err == nil {
   359  			l.(*TCPListener).Close()
   360  		}
   361  	case "udp", "udp4", "udp6":
   362  		if xerr == nil && err != nil || xerr != nil && err == nil {
   363  			t.Fatalf("Second ListenPacket(%q, %q) returns %v, expected %v", net, laddr, err, xerr)
   364  		}
   365  		if err == nil {
   366  			l.(*UDPConn).Close()
   367  		}
   368  	default:
   369  		t.Fatalf("Unexpected network: %q", net)
   370  	}
   371  }
   372  
   373  func checkDualStackAddrFamily(t *testing.T, net, laddr string, fd *netFD) {
   374  	switch a := fd.laddr.(type) {
   375  	case *TCPAddr:
   376  		// If a node under test supports both IPv6 capability
   377  		// and IPv6 IPv4-mapping capability, we can assume
   378  		// that the node listens on a wildcard address with an
   379  		// AF_INET6 socket.
   380  		if supportsIPv4map && fd.laddr.(*TCPAddr).isWildcard() {
   381  			if fd.family != syscall.AF_INET6 {
   382  				t.Fatalf("Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
   383  			}
   384  		} else {
   385  			if fd.family != a.family() {
   386  				t.Fatalf("Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, a.family())
   387  			}
   388  		}
   389  	case *UDPAddr:
   390  		// If a node under test supports both IPv6 capability
   391  		// and IPv6 IPv4-mapping capability, we can assume
   392  		// that the node listens on a wildcard address with an
   393  		// AF_INET6 socket.
   394  		if supportsIPv4map && fd.laddr.(*UDPAddr).isWildcard() {
   395  			if fd.family != syscall.AF_INET6 {
   396  				t.Fatalf("ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
   397  			}
   398  		} else {
   399  			if fd.family != a.family() {
   400  				t.Fatalf("ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, a.family())
   401  			}
   402  		}
   403  	default:
   404  		t.Fatalf("Unexpected protocol address type: %T", a)
   405  	}
   406  }
   407  
   408  var prohibitionaryDialArgTests = []struct {
   409  	net  string
   410  	addr string
   411  }{
   412  	{"tcp6", "127.0.0.1"},
   413  	{"tcp6", "[::ffff:127.0.0.1]"},
   414  }
   415  
   416  func TestProhibitionaryDialArgs(t *testing.T) {
   417  	switch runtime.GOOS {
   418  	case "plan9":
   419  		t.Skipf("skipping test on %q", runtime.GOOS)
   420  	}
   421  	// This test requires both IPv6 and IPv6 IPv4-mapping functionality.
   422  	if !supportsIPv4map || testing.Short() || !*testExternal {
   423  		return
   424  	}
   425  
   426  	l, port := usableListenPort(t, "tcp", "[::]")
   427  	defer l.Close()
   428  
   429  	for _, tt := range prohibitionaryDialArgTests {
   430  		c, err := Dial(tt.net, tt.addr+":"+port)
   431  		if err == nil {
   432  			c.Close()
   433  			t.Fatalf("Dial(%q, %q) should fail", tt.net, tt.addr)
   434  		}
   435  	}
   436  }
   437  
   438  func TestWildWildcardListener(t *testing.T) {
   439  	switch runtime.GOOS {
   440  	case "plan9":
   441  		t.Skipf("skipping test on %q", runtime.GOOS)
   442  	}
   443  
   444  	if testing.Short() || !*testExternal {
   445  		t.Skip("skipping test to avoid external network")
   446  	}
   447  
   448  	defer func() {
   449  		if p := recover(); p != nil {
   450  			t.Fatalf("Listen, ListenPacket or protocol-specific Listen panicked: %v", p)
   451  		}
   452  	}()
   453  
   454  	if ln, err := Listen("tcp", ""); err == nil {
   455  		ln.Close()
   456  	}
   457  	if ln, err := ListenPacket("udp", ""); err == nil {
   458  		ln.Close()
   459  	}
   460  	if ln, err := ListenTCP("tcp", nil); err == nil {
   461  		ln.Close()
   462  	}
   463  	if ln, err := ListenUDP("udp", nil); err == nil {
   464  		ln.Close()
   465  	}
   466  	if ln, err := ListenIP("ip:icmp", nil); err == nil {
   467  		ln.Close()
   468  	}
   469  }