Source file src/net/ipsock_test.go

     1  // Copyright 2013 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  package net
     6  
     7  import (
     8  	"reflect"
     9  	"testing"
    10  )
    11  
    12  var testInetaddr = func(ip IPAddr) Addr { return &TCPAddr{IP: ip.IP, Port: 5682, Zone: ip.Zone} }
    13  
    14  var addrListTests = []struct {
    15  	filter    func(IPAddr) bool
    16  	ips       []IPAddr
    17  	inetaddr  func(IPAddr) Addr
    18  	first     Addr
    19  	primaries addrList
    20  	fallbacks addrList
    21  	err       error
    22  }{
    23  	{
    24  		nil,
    25  		[]IPAddr{
    26  			{IP: IPv4(127, 0, 0, 1)},
    27  			{IP: IPv6loopback},
    28  		},
    29  		testInetaddr,
    30  		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
    31  		addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
    32  		addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
    33  		nil,
    34  	},
    35  	{
    36  		nil,
    37  		[]IPAddr{
    38  			{IP: IPv6loopback},
    39  			{IP: IPv4(127, 0, 0, 1)},
    40  		},
    41  		testInetaddr,
    42  		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
    43  		addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
    44  		addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
    45  		nil,
    46  	},
    47  	{
    48  		nil,
    49  		[]IPAddr{
    50  			{IP: IPv4(127, 0, 0, 1)},
    51  			{IP: IPv4(192, 168, 0, 1)},
    52  		},
    53  		testInetaddr,
    54  		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
    55  		addrList{
    56  			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
    57  			&TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
    58  		},
    59  		nil,
    60  		nil,
    61  	},
    62  	{
    63  		nil,
    64  		[]IPAddr{
    65  			{IP: IPv6loopback},
    66  			{IP: ParseIP("fe80::1"), Zone: "eth0"},
    67  		},
    68  		testInetaddr,
    69  		&TCPAddr{IP: IPv6loopback, Port: 5682},
    70  		addrList{
    71  			&TCPAddr{IP: IPv6loopback, Port: 5682},
    72  			&TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
    73  		},
    74  		nil,
    75  		nil,
    76  	},
    77  	{
    78  		nil,
    79  		[]IPAddr{
    80  			{IP: IPv4(127, 0, 0, 1)},
    81  			{IP: IPv4(192, 168, 0, 1)},
    82  			{IP: IPv6loopback},
    83  			{IP: ParseIP("fe80::1"), Zone: "eth0"},
    84  		},
    85  		testInetaddr,
    86  		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
    87  		addrList{
    88  			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
    89  			&TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
    90  		},
    91  		addrList{
    92  			&TCPAddr{IP: IPv6loopback, Port: 5682},
    93  			&TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
    94  		},
    95  		nil,
    96  	},
    97  	{
    98  		nil,
    99  		[]IPAddr{
   100  			{IP: IPv6loopback},
   101  			{IP: ParseIP("fe80::1"), Zone: "eth0"},
   102  			{IP: IPv4(127, 0, 0, 1)},
   103  			{IP: IPv4(192, 168, 0, 1)},
   104  		},
   105  		testInetaddr,
   106  		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
   107  		addrList{
   108  			&TCPAddr{IP: IPv6loopback, Port: 5682},
   109  			&TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
   110  		},
   111  		addrList{
   112  			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
   113  			&TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
   114  		},
   115  		nil,
   116  	},
   117  	{
   118  		nil,
   119  		[]IPAddr{
   120  			{IP: IPv4(127, 0, 0, 1)},
   121  			{IP: IPv6loopback},
   122  			{IP: IPv4(192, 168, 0, 1)},
   123  			{IP: ParseIP("fe80::1"), Zone: "eth0"},
   124  		},
   125  		testInetaddr,
   126  		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
   127  		addrList{
   128  			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
   129  			&TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
   130  		},
   131  		addrList{
   132  			&TCPAddr{IP: IPv6loopback, Port: 5682},
   133  			&TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
   134  		},
   135  		nil,
   136  	},
   137  	{
   138  		nil,
   139  		[]IPAddr{
   140  			{IP: IPv6loopback},
   141  			{IP: IPv4(127, 0, 0, 1)},
   142  			{IP: ParseIP("fe80::1"), Zone: "eth0"},
   143  			{IP: IPv4(192, 168, 0, 1)},
   144  		},
   145  		testInetaddr,
   146  		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
   147  		addrList{
   148  			&TCPAddr{IP: IPv6loopback, Port: 5682},
   149  			&TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
   150  		},
   151  		addrList{
   152  			&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
   153  			&TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
   154  		},
   155  		nil,
   156  	},
   157  
   158  	{
   159  		ipv4only,
   160  		[]IPAddr{
   161  			{IP: IPv4(127, 0, 0, 1)},
   162  			{IP: IPv6loopback},
   163  		},
   164  		testInetaddr,
   165  		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
   166  		addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
   167  		nil,
   168  		nil,
   169  	},
   170  	{
   171  		ipv4only,
   172  		[]IPAddr{
   173  			{IP: IPv6loopback},
   174  			{IP: IPv4(127, 0, 0, 1)},
   175  		},
   176  		testInetaddr,
   177  		&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
   178  		addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
   179  		nil,
   180  		nil,
   181  	},
   182  
   183  	{
   184  		ipv6only,
   185  		[]IPAddr{
   186  			{IP: IPv4(127, 0, 0, 1)},
   187  			{IP: IPv6loopback},
   188  		},
   189  		testInetaddr,
   190  		&TCPAddr{IP: IPv6loopback, Port: 5682},
   191  		addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
   192  		nil,
   193  		nil,
   194  	},
   195  	{
   196  		ipv6only,
   197  		[]IPAddr{
   198  			{IP: IPv6loopback},
   199  			{IP: IPv4(127, 0, 0, 1)},
   200  		},
   201  		testInetaddr,
   202  		&TCPAddr{IP: IPv6loopback, Port: 5682},
   203  		addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
   204  		nil,
   205  		nil,
   206  	},
   207  
   208  	{nil, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
   209  
   210  	{ipv4only, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
   211  	{ipv4only, []IPAddr{{IP: IPv6loopback}}, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
   212  
   213  	{ipv6only, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
   214  	{ipv6only, []IPAddr{{IP: IPv4(127, 0, 0, 1)}}, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
   215  }
   216  
   217  func TestAddrList(t *testing.T) {
   218  	if !supportsIPv4() || !supportsIPv6() {
   219  		t.Skip("both IPv4 and IPv6 are required")
   220  	}
   221  
   222  	for i, tt := range addrListTests {
   223  		addrs, err := filterAddrList(tt.filter, tt.ips, tt.inetaddr, "ADDR")
   224  		if !reflect.DeepEqual(err, tt.err) {
   225  			t.Errorf("#%v: got %v; want %v", i, err, tt.err)
   226  		}
   227  		if tt.err != nil {
   228  			if len(addrs) != 0 {
   229  				t.Errorf("#%v: got %v; want 0", i, len(addrs))
   230  			}
   231  			continue
   232  		}
   233  		first := addrs.first(isIPv4)
   234  		if !reflect.DeepEqual(first, tt.first) {
   235  			t.Errorf("#%v: got %v; want %v", i, first, tt.first)
   236  		}
   237  		primaries, fallbacks := addrs.partition(isIPv4)
   238  		if !reflect.DeepEqual(primaries, tt.primaries) {
   239  			t.Errorf("#%v: got %v; want %v", i, primaries, tt.primaries)
   240  		}
   241  		if !reflect.DeepEqual(fallbacks, tt.fallbacks) {
   242  			t.Errorf("#%v: got %v; want %v", i, fallbacks, tt.fallbacks)
   243  		}
   244  		expectedLen := len(primaries) + len(fallbacks)
   245  		if len(addrs) != expectedLen {
   246  			t.Errorf("#%v: got %v; want %v", i, len(addrs), expectedLen)
   247  		}
   248  	}
   249  }
   250  
   251  func TestAddrListPartition(t *testing.T) {
   252  	addrs := addrList{
   253  		&IPAddr{IP: ParseIP("fe80::"), Zone: "eth0"},
   254  		&IPAddr{IP: ParseIP("fe80::1"), Zone: "eth0"},
   255  		&IPAddr{IP: ParseIP("fe80::2"), Zone: "eth0"},
   256  	}
   257  	cases := []struct {
   258  		lastByte  byte
   259  		primaries addrList
   260  		fallbacks addrList
   261  	}{
   262  		{0, addrList{addrs[0]}, addrList{addrs[1], addrs[2]}},
   263  		{1, addrList{addrs[0], addrs[2]}, addrList{addrs[1]}},
   264  		{2, addrList{addrs[0], addrs[1]}, addrList{addrs[2]}},
   265  		{3, addrList{addrs[0], addrs[1], addrs[2]}, nil},
   266  	}
   267  	for i, tt := range cases {
   268  		// Inverting the function's output should not affect the outcome.
   269  		for _, invert := range []bool{false, true} {
   270  			primaries, fallbacks := addrs.partition(func(a Addr) bool {
   271  				ip := a.(*IPAddr).IP
   272  				return (ip[len(ip)-1] == tt.lastByte) != invert
   273  			})
   274  			if !reflect.DeepEqual(primaries, tt.primaries) {
   275  				t.Errorf("#%v: got %v; want %v", i, primaries, tt.primaries)
   276  			}
   277  			if !reflect.DeepEqual(fallbacks, tt.fallbacks) {
   278  				t.Errorf("#%v: got %v; want %v", i, fallbacks, tt.fallbacks)
   279  			}
   280  		}
   281  	}
   282  }
   283  

View as plain text