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 }