github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/net/addrselect_test.go (about)

     1  // Copyright 2015 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 darwin dragonfly freebsd linux netbsd openbsd solaris
     6  
     7  package net
     8  
     9  import (
    10  	"reflect"
    11  	"testing"
    12  )
    13  
    14  func TestSortByRFC6724(t *testing.T) {
    15  	tests := []struct {
    16  		in      []IPAddr
    17  		srcs    []IP
    18  		want    []IPAddr
    19  		reverse bool // also test it starting backwards
    20  	}{
    21  		// Examples from RFC 6724 section 10.2:
    22  
    23  		// Prefer matching scope.
    24  		{
    25  			in: []IPAddr{
    26  				{IP: ParseIP("2001:db8:1::1")},
    27  				{IP: ParseIP("198.51.100.121")},
    28  			},
    29  			srcs: []IP{
    30  				ParseIP("2001:db8:1::2"),
    31  				ParseIP("169.254.13.78"),
    32  			},
    33  			want: []IPAddr{
    34  				{IP: ParseIP("2001:db8:1::1")},
    35  				{IP: ParseIP("198.51.100.121")},
    36  			},
    37  			reverse: true,
    38  		},
    39  
    40  		// Prefer matching scope.
    41  		{
    42  			in: []IPAddr{
    43  				{IP: ParseIP("2001:db8:1::1")},
    44  				{IP: ParseIP("198.51.100.121")},
    45  			},
    46  			srcs: []IP{
    47  				ParseIP("fe80::1"),
    48  				ParseIP("198.51.100.117"),
    49  			},
    50  			want: []IPAddr{
    51  				{IP: ParseIP("198.51.100.121")},
    52  				{IP: ParseIP("2001:db8:1::1")},
    53  			},
    54  			reverse: true,
    55  		},
    56  
    57  		// Prefer higher precedence.
    58  		{
    59  			in: []IPAddr{
    60  				{IP: ParseIP("2001:db8:1::1")},
    61  				{IP: ParseIP("10.1.2.3")},
    62  			},
    63  			srcs: []IP{
    64  				ParseIP("2001:db8:1::2"),
    65  				ParseIP("10.1.2.4"),
    66  			},
    67  			want: []IPAddr{
    68  				{IP: ParseIP("2001:db8:1::1")},
    69  				{IP: ParseIP("10.1.2.3")},
    70  			},
    71  			reverse: true,
    72  		},
    73  
    74  		// Prefer smaller scope.
    75  		{
    76  			in: []IPAddr{
    77  				{IP: ParseIP("2001:db8:1::1")},
    78  				{IP: ParseIP("fe80::1")},
    79  			},
    80  			srcs: []IP{
    81  				ParseIP("2001:db8:1::2"),
    82  				ParseIP("fe80::2"),
    83  			},
    84  			want: []IPAddr{
    85  				{IP: ParseIP("fe80::1")},
    86  				{IP: ParseIP("2001:db8:1::1")},
    87  			},
    88  			reverse: true,
    89  		},
    90  
    91  		// Issue 13283.  Having a 10/8 source address does not
    92  		// mean we should prefer 23/8 destination addresses.
    93  		{
    94  			in: []IPAddr{
    95  				{IP: ParseIP("54.83.193.112")},
    96  				{IP: ParseIP("184.72.238.214")},
    97  				{IP: ParseIP("23.23.172.185")},
    98  				{IP: ParseIP("75.101.148.21")},
    99  				{IP: ParseIP("23.23.134.56")},
   100  				{IP: ParseIP("23.21.50.150")},
   101  			},
   102  			srcs: []IP{
   103  				ParseIP("10.2.3.4"),
   104  				ParseIP("10.2.3.4"),
   105  				ParseIP("10.2.3.4"),
   106  				ParseIP("10.2.3.4"),
   107  				ParseIP("10.2.3.4"),
   108  				ParseIP("10.2.3.4"),
   109  			},
   110  			want: []IPAddr{
   111  				{IP: ParseIP("54.83.193.112")},
   112  				{IP: ParseIP("184.72.238.214")},
   113  				{IP: ParseIP("23.23.172.185")},
   114  				{IP: ParseIP("75.101.148.21")},
   115  				{IP: ParseIP("23.23.134.56")},
   116  				{IP: ParseIP("23.21.50.150")},
   117  			},
   118  			reverse: false,
   119  		},
   120  
   121  		// Prefer longer common prefixes, but only for IPv4 address
   122  		// pairs in the same special-purpose block.
   123  		{
   124  			in: []IPAddr{
   125  				{IP: ParseIP("1.2.3.4")},
   126  				{IP: ParseIP("10.55.0.1")},
   127  				{IP: ParseIP("10.66.0.1")},
   128  			},
   129  			srcs: []IP{
   130  				ParseIP("1.2.3.5"),
   131  				ParseIP("10.66.1.2"),
   132  				ParseIP("10.66.1.2"),
   133  			},
   134  			want: []IPAddr{
   135  				{IP: ParseIP("10.66.0.1")},
   136  				{IP: ParseIP("10.55.0.1")},
   137  				{IP: ParseIP("1.2.3.4")},
   138  			},
   139  			reverse: true,
   140  		},
   141  	}
   142  	for i, tt := range tests {
   143  		inCopy := make([]IPAddr, len(tt.in))
   144  		copy(inCopy, tt.in)
   145  		srcCopy := make([]IP, len(tt.in))
   146  		copy(srcCopy, tt.srcs)
   147  		sortByRFC6724withSrcs(inCopy, srcCopy)
   148  		if !reflect.DeepEqual(inCopy, tt.want) {
   149  			t.Errorf("test %d:\nin = %s\ngot: %s\nwant: %s\n", i, tt.in, inCopy, tt.want)
   150  		}
   151  		if tt.reverse {
   152  			copy(inCopy, tt.in)
   153  			copy(srcCopy, tt.srcs)
   154  			for j := 0; j < len(inCopy)/2; j++ {
   155  				k := len(inCopy) - j - 1
   156  				inCopy[j], inCopy[k] = inCopy[k], inCopy[j]
   157  				srcCopy[j], srcCopy[k] = srcCopy[k], srcCopy[j]
   158  			}
   159  			sortByRFC6724withSrcs(inCopy, srcCopy)
   160  			if !reflect.DeepEqual(inCopy, tt.want) {
   161  				t.Errorf("test %d, starting backwards:\nin = %s\ngot: %s\nwant: %s\n", i, tt.in, inCopy, tt.want)
   162  			}
   163  		}
   164  
   165  	}
   166  
   167  }
   168  
   169  func TestRFC6724PolicyTableClassify(t *testing.T) {
   170  	tests := []struct {
   171  		ip   IP
   172  		want policyTableEntry
   173  	}{
   174  		{
   175  			ip: ParseIP("127.0.0.1"),
   176  			want: policyTableEntry{
   177  				Prefix:     &IPNet{IP: ParseIP("::ffff:0:0"), Mask: CIDRMask(96, 128)},
   178  				Precedence: 35,
   179  				Label:      4,
   180  			},
   181  		},
   182  		{
   183  			ip: ParseIP("2601:645:8002:a500:986f:1db8:c836:bd65"),
   184  			want: policyTableEntry{
   185  				Prefix:     &IPNet{IP: ParseIP("::"), Mask: CIDRMask(0, 128)},
   186  				Precedence: 40,
   187  				Label:      1,
   188  			},
   189  		},
   190  		{
   191  			ip: ParseIP("::1"),
   192  			want: policyTableEntry{
   193  				Prefix:     &IPNet{IP: ParseIP("::1"), Mask: CIDRMask(128, 128)},
   194  				Precedence: 50,
   195  				Label:      0,
   196  			},
   197  		},
   198  		{
   199  			ip: ParseIP("2002::ab12"),
   200  			want: policyTableEntry{
   201  				Prefix:     &IPNet{IP: ParseIP("2002::"), Mask: CIDRMask(16, 128)},
   202  				Precedence: 30,
   203  				Label:      2,
   204  			},
   205  		},
   206  	}
   207  	for i, tt := range tests {
   208  		got := rfc6724policyTable.Classify(tt.ip)
   209  		if !reflect.DeepEqual(got, tt.want) {
   210  			t.Errorf("%d. Classify(%s) = %v; want %v", i, tt.ip, got, tt.want)
   211  		}
   212  	}
   213  }
   214  
   215  func TestRFC6724ClassifyScope(t *testing.T) {
   216  	tests := []struct {
   217  		ip   IP
   218  		want scope
   219  	}{
   220  		{ParseIP("127.0.0.1"), scopeLinkLocal},   // rfc6724#section-3.2
   221  		{ParseIP("::1"), scopeLinkLocal},         // rfc4007#section-4
   222  		{ParseIP("169.254.1.2"), scopeLinkLocal}, // rfc6724#section-3.2
   223  		{ParseIP("fec0::1"), scopeSiteLocal},
   224  		{ParseIP("8.8.8.8"), scopeGlobal},
   225  
   226  		{ParseIP("ff02::"), scopeLinkLocal},  // IPv6 multicast
   227  		{ParseIP("ff05::"), scopeSiteLocal},  // IPv6 multicast
   228  		{ParseIP("ff04::"), scopeAdminLocal}, // IPv6 multicast
   229  		{ParseIP("ff0e::"), scopeGlobal},     // IPv6 multicast
   230  
   231  		{IPv4(0xe0, 0, 0, 0), scopeGlobal},       // IPv4 link-local multicast as 16 bytes
   232  		{IPv4(0xe0, 2, 2, 2), scopeGlobal},       // IPv4 global multicast as 16 bytes
   233  		{IPv4(0xe0, 0, 0, 0).To4(), scopeGlobal}, // IPv4 link-local multicast as 4 bytes
   234  		{IPv4(0xe0, 2, 2, 2).To4(), scopeGlobal}, // IPv4 global multicast as 4 bytes
   235  	}
   236  	for i, tt := range tests {
   237  		got := classifyScope(tt.ip)
   238  		if got != tt.want {
   239  			t.Errorf("%d. classifyScope(%s) = %x; want %x", i, tt.ip, got, tt.want)
   240  		}
   241  	}
   242  }
   243  
   244  func TestRFC6724CommonPrefixLength(t *testing.T) {
   245  	tests := []struct {
   246  		a, b IP
   247  		want int
   248  	}{
   249  		{ParseIP("fe80::1"), ParseIP("fe80::2"), 64},
   250  		{ParseIP("fe81::1"), ParseIP("fe80::2"), 15},
   251  		{ParseIP("127.0.0.1"), ParseIP("fe80::1"), 0}, // diff size
   252  		{IPv4(1, 2, 3, 4), IP{1, 2, 3, 4}, 32},
   253  		{IP{1, 2, 255, 255}, IP{1, 2, 0, 0}, 16},
   254  		{IP{1, 2, 127, 255}, IP{1, 2, 0, 0}, 17},
   255  		{IP{1, 2, 63, 255}, IP{1, 2, 0, 0}, 18},
   256  		{IP{1, 2, 31, 255}, IP{1, 2, 0, 0}, 19},
   257  		{IP{1, 2, 15, 255}, IP{1, 2, 0, 0}, 20},
   258  		{IP{1, 2, 7, 255}, IP{1, 2, 0, 0}, 21},
   259  		{IP{1, 2, 3, 255}, IP{1, 2, 0, 0}, 22},
   260  		{IP{1, 2, 1, 255}, IP{1, 2, 0, 0}, 23},
   261  		{IP{1, 2, 0, 255}, IP{1, 2, 0, 0}, 24},
   262  	}
   263  	for i, tt := range tests {
   264  		got := commonPrefixLen(tt.a, tt.b)
   265  		if got != tt.want {
   266  			t.Errorf("%d. commonPrefixLen(%s, %s) = %d; want %d", i, tt.a, tt.b, got, tt.want)
   267  		}
   268  	}
   269  
   270  }
   271  
   272  func mustParseCIDRs(t *testing.T, blocks ...string) []*IPNet {
   273  	res := make([]*IPNet, len(blocks))
   274  	for i, block := range blocks {
   275  		var err error
   276  		_, res[i], err = ParseCIDR(block)
   277  		if err != nil {
   278  			t.Fatalf("ParseCIDR(%s) failed: %v", block, err)
   279  		}
   280  	}
   281  	return res
   282  }
   283  
   284  func TestSameIPv4SpecialPurposeBlock(t *testing.T) {
   285  	blocks := mustParseCIDRs(t,
   286  		"10.0.0.0/8",
   287  		"127.0.0.0/8",
   288  		"169.254.0.0/16",
   289  		"172.16.0.0/12",
   290  		"192.168.0.0/16",
   291  	)
   292  
   293  	addrs := []struct {
   294  		ip    IP
   295  		block int // index or -1
   296  	}{
   297  		{IP{1, 2, 3, 4}, -1},
   298  		{IP{2, 3, 4, 5}, -1},
   299  		{IP{10, 2, 3, 4}, 0},
   300  		{IP{10, 6, 7, 8}, 0},
   301  		{IP{127, 0, 0, 1}, 1},
   302  		{IP{127, 255, 255, 255}, 1},
   303  		{IP{169, 254, 77, 99}, 2},
   304  		{IP{169, 254, 44, 22}, 2},
   305  		{IP{169, 255, 0, 1}, -1},
   306  		{IP{172, 15, 5, 6}, -1},
   307  		{IP{172, 16, 32, 41}, 3},
   308  		{IP{172, 31, 128, 9}, 3},
   309  		{IP{172, 32, 88, 100}, -1},
   310  		{IP{192, 168, 1, 1}, 4},
   311  		{IP{192, 168, 128, 42}, 4},
   312  		{IP{192, 169, 1, 1}, -1},
   313  	}
   314  
   315  	for i, addr := range addrs {
   316  		for j, block := range blocks {
   317  			got := block.Contains(addr.ip)
   318  			want := addr.block == j
   319  			if got != want {
   320  				t.Errorf("%d/%d. %s.Contains(%s): got %v, want %v", i, j, block, addr.ip, got, want)
   321  			}
   322  		}
   323  	}
   324  
   325  	for i, addr1 := range addrs {
   326  		for j, addr2 := range addrs {
   327  			got := sameIPv4SpecialPurposeBlock(addr1.ip, addr2.ip)
   328  			want := addr1.block >= 0 && addr1.block == addr2.block
   329  			if got != want {
   330  				t.Errorf("%d/%d. sameIPv4SpecialPurposeBlock(%s, %s): got %v, want %v", i, j, addr1.ip, addr2.ip, got, want)
   331  			}
   332  		}
   333  	}
   334  }