github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/ipaddr/ipaddr_test.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package ipaddr 12 13 import ( 14 "math" 15 "net" 16 "strings" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/util/uint128" 20 ) 21 22 func TestIPAddrParseInet(t *testing.T) { 23 testCases := []struct { 24 s string 25 exp *IPAddr 26 err string 27 }{ 28 // Basic IPv4. 29 {"192.168.1.2", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 32}, ""}, 30 // Test we preserve masked bits. 31 {"192.168.1.2/16", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 16}, ""}, 32 // Test the ability to have following '.'. 33 {"192.168.1.2.", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 32}, ""}, 34 {"192.168.1.2./10", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 10}, ""}, 35 // Basic IPv6. 36 {"2001:4f8:3:ba::/64", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("2001:4f8:3:ba::")))), Mask: 64}, ""}, 37 {"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("2001:4f8:3:ba:2e0:81ff:fe22:d1f1")))), Mask: 128}, ""}, 38 {"::ffff:1.2.3.1/120", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 120}, ""}, 39 {"::ffff:1.2.3.1/128", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 128}, ""}, 40 {"::ffff:1.2.3.1/128", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 128}, ""}, 41 {"::ffff:1.2.3.1/20", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 20}, ""}, 42 {"::ffff:1.2.3.1/120", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 120}, ""}, 43 {"::1", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::1")))), Mask: 128}, ""}, 44 {"9ec6:78fc:c3ae:a65a:9ac7:2081:ac81:e0aa/101", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("9ec6:78fc:c3ae:a65a:9ac7:2081:ac81:e0aa")))), Mask: 101}, ""}, 45 46 // Test bad IPs. 47 {"abc", nil, "invalid IP"}, 48 {"", nil, "invalid IP"}, 49 {"20000", nil, "invalid IP"}, 50 {"123.abc", nil, "invalid IP"}, 51 {"123.2000", nil, "invalid IP"}, 52 {"192.168", nil, "invalid IP"}, 53 {"192.168.0.0.0", nil, "invalid IP"}, 54 {"192.168.0.2/a", nil, "invalid mask"}, 55 {"192.168.0.2/100", nil, "invalid mask"}, 56 {"192.168.0.a/20", nil, "invalid IP"}, 57 58 // Edge cases. 59 {"0.0.0.0", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4zero))), Mask: 32}, ""}, 60 {"0.0.0.0/32", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4zero))), Mask: 32}, ""}, 61 {"0.0.0.0/0", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4zero))), Mask: 0}, ""}, 62 {"0.0.0.0/10", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4zero))), Mask: 10}, ""}, 63 64 {"255.255.255.255", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4bcast))), Mask: 32}, ""}, 65 {"255.255.255.255/32", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4bcast))), Mask: 32}, ""}, 66 {"255.255.255.255/0", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4bcast))), Mask: 0}, ""}, 67 {"255.255.255.255/10", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4bcast))), Mask: 10}, ""}, 68 69 {"::0", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.IPv6zero))), Mask: 128}, ""}, 70 {"::0/0", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.IPv6zero))), Mask: 0}, ""}, 71 {"::0/10", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.IPv6zero))), Mask: 10}, ""}, 72 73 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")))), Mask: 128}, ""}, 74 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/0", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")))), Mask: 0}, ""}, 75 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/10", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")))), Mask: 10}, ""}, 76 77 // Postgres compatibility edge cases: IPv4 missing octets. 78 {"192.168/24", nil, "mask is larger than provided octets"}, 79 {"192/10", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.0.0.0")))), Mask: 10}, ""}, 80 {"192.168/23", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.0.0")))), Mask: 23}, ""}, 81 {"192.168./10", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.0.0")))), Mask: 10}, ""}, 82 } 83 for i, testCase := range testCases { 84 var actual IPAddr 85 if err := ParseINet(testCase.s, &actual); err != nil { 86 if len(testCase.err) > 0 { 87 if !strings.Contains(err.Error(), testCase.err) { 88 t.Errorf("%d: ParseINet(%s) caused an incorrect error actual:%s, expected:%s", i, testCase.s, 89 err, testCase.err) 90 } 91 } else { 92 t.Errorf("%d: ParseINet(%s) caused an unexpected error:%s", i, testCase.s, err) 93 } 94 } else if testCase.exp != nil && !actual.Equal(testCase.exp) { 95 t.Errorf("%d: ParseINet(%s) actual:%v does not match expected:%v", i, testCase.s, actual, 96 testCase.exp) 97 } 98 } 99 } 100 101 func TestIPAddrBinaryMarshalling(t *testing.T) { 102 testCases := []struct { 103 input *IPAddr 104 }{ 105 {&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 32}}, 106 {&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 16}}, 107 {&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 32}}, 108 {&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 10}}, 109 {&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("2001:4f8:3:ba::")))), Mask: 64}}, 110 {&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("2001:4f8:3:ba:2e0:81ff:fe22:d1f1")))), Mask: 128}}, 111 {&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 120}}, 112 {&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 128}}, 113 {&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 128}}, 114 {&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::1")))), Mask: 128}}, 115 {&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.0.0")))), Mask: 23}}, 116 {&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.0.0")))), Mask: 10}}, 117 } 118 for i, testCase := range testCases { 119 var data []byte 120 data = testCase.input.ToBuffer(data) 121 var actual IPAddr 122 if remaining, err := actual.FromBuffer(data); err != nil { 123 t.Errorf("%d: UnmarshalBinary(%s) caused an unexpected error:%s", i, testCase.input, err) 124 } else if !actual.Equal(testCase.input) { 125 t.Errorf("%d: Binary marshaling round trip failed. actual:%v does not match expected:%v", i, actual, testCase.input) 126 } else if len(remaining) != 0 { 127 t.Errorf("%d: Binary marshaling left extraneous bytes in buffer. Leftover len: %d bytes: %s", i, len(remaining), remaining) 128 } 129 } 130 } 131 132 func TestIPAddrGetFamily(t *testing.T) { 133 testCases := []struct { 134 s string 135 exp IPFamily 136 }{ 137 // Basic IPv4 138 {"192.168.1.2", IPv4family}, 139 {"192.168.1.2/16", IPv4family}, 140 // Basic IPv6 141 {"2001:4f8:3:ba::/64", IPv6family}, 142 {"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", IPv6family}, 143 {"::ffff:1.2.3.1/120", IPv6family}, 144 {"::ffff:1.2.3.1/128", IPv6family}, 145 {"::ffff:1.2.3.1/128", IPv6family}, 146 {"::1", IPv6family}, 147 148 // Postgres compatibility edge cases: IPv4 missing octets 149 {"192.168/24", IPv4family}, 150 {"192/10", IPv4family}, 151 {"192.168/23", IPv4family}, 152 {"192.168./10", IPv4family}, 153 } 154 for i, testCase := range testCases { 155 actual := getFamily(testCase.s) 156 157 if actual != testCase.exp { 158 t.Errorf("%d: getFamily(%q) actual:%v does not match expected:%v", i, testCase.s, actual, 159 testCase.exp) 160 } 161 } 162 } 163 164 func TestIPAddrCompare(t *testing.T) { 165 testCases := []struct { 166 s1 string 167 s2 string 168 exp int 169 }{ 170 // Basic IPv4 171 {"192.168.1.2", "192.168.1.2", 0}, 172 {"192.168.1.2", "192.168.1.3", -1}, 173 {"192.168.1.2", "192.168.1.1", 1}, 174 {"192.168.1.2", "192.168.0.2", 1}, 175 {"192.168.1.2", "192.168.1.2/16", 1}, 176 {"192.168.1.2/17", "192.168.1.2/16", 1}, 177 {"192.168.1.2/17", "192.168.1.3/1", 1}, 178 {"192.168.1.2/1", "192.168.1.3/17", -1}, 179 {"192.168.1.2", "::ffff:192.168.1.2", -1}, 180 {"::ffff:192.168.1.2", "192.168.1.2", 1}, 181 {"::ffff:192.168.1.2", "::ffff:192.168.1.2", 0}, 182 {"c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", 0}, 183 {"6e32:8a01:373b:c9ce:8ed5:9f7f:dc7e:5cfc", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", -1}, 184 {"192.168.1.2", "192.168.1.2", 0}, 185 } 186 for i, testCase := range testCases { 187 var ip1 IPAddr 188 var ip2 IPAddr 189 if err := ParseINet(testCase.s1, &ip1); err != nil { 190 t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1) 191 } 192 if err := ParseINet(testCase.s2, &ip2); err != nil { 193 t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2) 194 } 195 196 if actual := ip1.Compare(&ip2); actual != testCase.exp { 197 t.Errorf("%d: Compare(%q, %q) actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual, 198 testCase.exp) 199 } 200 } 201 } 202 203 func TestIPAddrEqual(t *testing.T) { 204 testCases := []struct { 205 s1 string 206 s2 string 207 exp bool 208 }{ 209 // Basic IPv4 210 {"192.168.1.2", "192.168.1.2", true}, 211 {"192.168.1.2", "192.168.1.3", false}, 212 {"192.168.1.2", "192.168.1.2/10", false}, 213 {"192.168.1.2", "::ffff:192.168.1.2", false}, 214 {"192.168.1.2", "::ffff:192.168.1.2", false}, 215 {"0.0.0.0", "0.0.0.0", true}, 216 {"0.0.0.0/0", "0.0.0.0/0", true}, 217 {"0.0.0.0/0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128", false}, 218 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128", true}, 219 } 220 for i, testCase := range testCases { 221 var ip1 IPAddr 222 var ip2 IPAddr 223 if err := ParseINet(testCase.s1, &ip1); err != nil { 224 t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1) 225 } 226 if err := ParseINet(testCase.s2, &ip2); err != nil { 227 t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2) 228 } 229 230 if actual := ip1.Equal(&ip2); actual != testCase.exp { 231 t.Errorf("%d: Equal(%q, %q) actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual, 232 testCase.exp) 233 } 234 } 235 } 236 237 func TestIPAddrString(t *testing.T) { 238 testCases := []struct { 239 s string 240 exp string 241 }{ 242 {"0.0.0.0", "0.0.0.0"}, 243 {"::0", "::"}, 244 {"255.255.255.255", "255.255.255.255"}, 245 {"192.168.1.2", "192.168.1.2"}, 246 {"192.168.1.2/10", "192.168.1.2/10"}, 247 // Test omission of mask 248 {"192.168.1.2/32", "192.168.1.2"}, 249 {"::ffff/128", "::ffff"}, 250 251 // Test retention of IPv6 format if IPv4-mapped IPv6 for postgres compatibility 252 {"::ffff:192.168.1.2", "::ffff:192.168.1.2"}, 253 {"::ffff:192.168.1.2/120", "::ffff:192.168.1.2/120"}, 254 } 255 for i, testCase := range testCases { 256 var ip IPAddr 257 if err := ParseINet(testCase.s, &ip); err != nil { 258 t.Fatalf("%d: Bad test input s:%s", i, testCase.s) 259 } 260 actual := ip.String() 261 if actual != testCase.exp { 262 t.Errorf("%d: String(%q) actual:%v does not match expected:%v", i, testCase.s, actual, 263 testCase.exp) 264 } 265 } 266 } 267 268 func TestIPAddrBroadcast(t *testing.T) { 269 testCases := []struct { 270 s string 271 exp string 272 }{ 273 // Basic IPv4 274 {"192.168.1.2", "192.168.1.2"}, 275 {"192.168.1.2/16", "192.168.255.255/16"}, 276 {"192.168.1.2/10", "192.191.255.255/10"}, 277 {"192.0.0.0/10", "192.63.255.255/10"}, 278 // Basic IPv6 279 {"2001:4f8:3:ba::/64", "2001:4f8:3:ba:ffff:ffff:ffff:ffff/64"}, 280 {"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", "2001:4f8:3:ba:2e0:81ff:fe22:d1f1"}, 281 {"::ffff:1.2.3.1/120", "::ffff:1.2.3.255/120"}, 282 {"::ffff:1.2.3.1/128", "::ffff:1.2.3.1"}, 283 {"::ffff:1.2.3.1/20", "0:fff:ffff:ffff:ffff:ffff:ffff:ffff/20"}, 284 {"::1", "::1"}, 285 } 286 for i, testCase := range testCases { 287 var ip IPAddr 288 if err := ParseINet(testCase.s, &ip); err != nil { 289 t.Fatalf("%d: bad test case: %s got error %s", i, testCase.s, err) 290 } 291 actual := ip.Broadcast() 292 if actual.String() != testCase.exp { 293 t.Errorf("%d: Broadcast(%s) actual:%s does not match expected:%s", i, testCase.s, actual.String(), 294 testCase.exp) 295 } 296 } 297 } 298 299 func TestIPAddrHostmask(t *testing.T) { 300 testCases := []struct { 301 s string 302 exp string 303 }{ 304 // Basic IPv4 305 {"192.168.1.2", "0.0.0.0"}, 306 {"192.168.1.2/16", "0.0.255.255"}, 307 {"192.168.1.2/10", "0.63.255.255"}, 308 {"192.168.1.2/0", "255.255.255.255"}, 309 // Basic IPv6 310 {"2001:4f8:3:ba::/64", "::ffff:ffff:ffff:ffff"}, 311 {"2001:4f8:3:ba::/0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"}, 312 {"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", "::"}, 313 {"::ffff:1.2.3.1/120", "::ff"}, 314 {"::ffff:1.2.3.1/128", "::"}, 315 {"::ffff:1.2.3.1/20", "0:fff:ffff:ffff:ffff:ffff:ffff:ffff"}, 316 } 317 for i, testCase := range testCases { 318 var ip IPAddr 319 if err := ParseINet(testCase.s, &ip); err != nil { 320 t.Fatalf("%d: bad test case: %s got error %s", i, testCase.s, err) 321 } 322 323 var expIP IPAddr 324 if err := ParseINet(testCase.exp, &expIP); err != nil { 325 t.Fatalf("%d: bad test case: %s got error %s", i, testCase.exp, err) 326 } 327 328 actual := ip.Hostmask() 329 if actual.String() != testCase.exp { 330 t.Errorf("%d: Hostmask(%s) actual:%#v does not match expected:%#v", i, testCase.s, actual, 331 expIP) 332 } 333 } 334 } 335 336 func TestIPAddrNetmask(t *testing.T) { 337 testCases := []struct { 338 s string 339 exp string 340 }{ 341 // Basic IPv4 342 {"192.168.1.2", "255.255.255.255"}, 343 {"192.168.1.2/16", "255.255.0.0"}, 344 {"192.168.1.2/10", "255.192.0.0"}, 345 {"192.168.1.2/0", "0.0.0.0"}, 346 // Basic IPv6 347 {"2001:4f8:3:ba::/64", "ffff:ffff:ffff:ffff::"}, 348 {"2001:4f8:3:ba::/0", "::"}, 349 {"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"}, 350 {"::ffff:1.2.3.1/120", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00"}, 351 {"::ffff:1.2.3.1/20", "ffff:f000::"}, 352 } 353 for i, testCase := range testCases { 354 var ip IPAddr 355 if err := ParseINet(testCase.s, &ip); err != nil { 356 t.Fatalf("%d: bad test case: %s got error %s", i, testCase.s, err) 357 } 358 359 actual := ip.Netmask() 360 if actual.String() != testCase.exp { 361 t.Errorf("%d: Netmask(%s) actual:%s does not match expected:%s", i, testCase.s, actual, 362 testCase.exp) 363 } 364 } 365 } 366 367 func TestComplement(t *testing.T) { 368 testCases := []struct { 369 s string 370 exp string 371 }{ 372 {"192.168.1.2", "63.87.254.253"}, 373 {"192.168.1.2/16", "63.87.254.253/16"}, 374 {"192.168.1.2/10", "63.87.254.253/10"}, 375 {"192.168.1.2/0", "63.87.254.253/0"}, 376 // Basic IPv6 377 {"2001:4f8:3:ba::/64", "dffe:fb07:fffc:ff45:ffff:ffff:ffff:ffff/64"}, 378 {"2001:4f8:3:ba::/0", "dffe:fb07:fffc:ff45:ffff:ffff:ffff:ffff/0"}, 379 {"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", "dffe:fb07:fffc:ff45:fd1f:7e00:1dd:2e0e"}, 380 {"::ffff:1.2.3.1/120", "ffff:ffff:ffff:ffff:ffff:0:fefd:fcfe/120"}, 381 {"::ffff:1.2.3.1/20", "ffff:ffff:ffff:ffff:ffff:0:fefd:fcfe/20"}, 382 } 383 for i, testCase := range testCases { 384 var ip IPAddr 385 if err := ParseINet(testCase.s, &ip); err != nil { 386 t.Fatalf("%d: bad test case: %s got error %s", i, testCase.s, err) 387 } 388 389 actual := ip.Complement() 390 if actual.String() != testCase.exp { 391 t.Errorf("%d: Complement(%s) actual:%s does not match expected:%s", i, testCase.s, actual, 392 testCase.exp) 393 } 394 } 395 } 396 397 func TestAnd(t *testing.T) { 398 testCases := []struct { 399 s1 string 400 s2 string 401 exp string 402 }{ 403 {"192.168.1.2", "192.168.1.2", "192.168.1.2"}, 404 {"255.255.255.250", "0.0.0.5", "0.0.0.0"}, 405 {"255.255.255.250/2", "0.5.0.5/17", "0.5.0.0/17"}, 406 {"192.168.1.2/17", "192.168.1.2/16", "192.168.1.2/17"}, 407 {"192.168.1.2/17", "192.168.1.3/1", "192.168.1.2/17"}, 408 {"192.168.1.2/1", "192.168.1.3/17", "192.168.1.2/17"}, 409 {"::ffff:192.168.1.2", "::ffff:192.168.1.2", "::ffff:192.168.1.2"}, 410 {"0000:0564:0000:0aab:0000:0000:0060:0005", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005", "0:564:0:aab::60:5"}, 411 {"c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d/99", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d"}, 412 {"6e32:8a01:373b:c9ce:8ed5:9f7f:dc7e:5cfc", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", "4232:8801:1418:c082:290:8b79:c424:47c"}, 413 {"8000:0000:0000:0000:0000:0000:0000:0005/68", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005/7", "8000::5/68"}, 414 } 415 for i, testCase := range testCases { 416 var ip1, ip2, exp IPAddr 417 if err := ParseINet(testCase.s1, &ip1); err != nil { 418 t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1) 419 } 420 if err := ParseINet(testCase.s2, &ip2); err != nil { 421 t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2) 422 } 423 if err := ParseINet(testCase.exp, &exp); err != nil { 424 t.Fatalf("%d: Bad test input exp:%s", i, testCase.exp) 425 } 426 427 actual, err := ip1.And(&ip2) 428 if err != nil { 429 t.Fatalf("%d: Bad test input s1:%s AND s2:%s", i, testCase.s1, testCase.s2) 430 } 431 if !actual.Equal(&exp) { 432 t.Errorf("%d: And(%q, %q) actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual, 433 testCase.exp) 434 } 435 } 436 } 437 438 func TestOr(t *testing.T) { 439 testCases := []struct { 440 s1 string 441 s2 string 442 exp string 443 }{ 444 {"192.168.1.2", "192.168.1.2", "192.168.1.2"}, 445 {"255.255.255.250", "0.0.0.5", "255.255.255.255"}, 446 {"255.255.255.250/2", "0.5.0.5/17", "255.255.255.255/17"}, 447 {"192.168.1.2/17", "192.168.1.2/16", "192.168.1.2/17"}, 448 {"192.168.1.2/17", "192.168.1.3/1", "192.168.1.3/17"}, 449 {"192.168.1.2/1", "192.168.1.3/17", "192.168.1.3/17"}, 450 {"::ffff:192.168.1.2", "::ffff:192.168.1.2", "::ffff:192.168.1.2"}, 451 {"0000:0564:0000:0aab:0000:0000:0060:0005", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:5"}, 452 {"c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d/99", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d"}, 453 {"6e32:8a01:373b:c9ce:8ed5:9f7f:dc7e:5cfc", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", "ef3e:9a67:7fbb:f9ee:8ef7:bfff:dfff:5efd"}, 454 {"8000:0000:0000:0000:0000:0000:0000:0005/68", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005/7", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:5/68"}, 455 } 456 for i, testCase := range testCases { 457 var ip1, ip2, exp IPAddr 458 if err := ParseINet(testCase.s1, &ip1); err != nil { 459 t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1) 460 } 461 if err := ParseINet(testCase.s2, &ip2); err != nil { 462 t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2) 463 } 464 if err := ParseINet(testCase.exp, &exp); err != nil { 465 t.Fatalf("%d: Bad test input exp:%s", i, testCase.exp) 466 } 467 468 actual, err := ip1.Or(&ip2) 469 if err != nil { 470 t.Fatalf("%d: Bad test input s1:%s AND s2:%s", i, testCase.s1, testCase.s2) 471 } 472 if !actual.Equal(&exp) { 473 t.Errorf("%d: Or(%q, %q) actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual, 474 testCase.exp) 475 } 476 } 477 } 478 479 func TestAdd(t *testing.T) { 480 testCases := []struct { 481 s string 482 i int64 483 exp string 484 }{ 485 {"0.0.0.0", 4294967295, "255.255.255.255"}, 486 {"255.255.255.255", -4294967295, "0.0.0.0"}, 487 {"192.168.1.2", 184836468, "203.172.98.118"}, 488 {"192.168.1.2/17", 184836468, "203.172.98.118/17"}, 489 {"::ffff:192.168.1.2", 4684658846864486648, "::4104:4066:5de7:b1fa"}, 490 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", -9223372036854775807, "ffff:ffff:ffff:ffff:8000::"}, 491 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", -9223372036854775808, "ffff:ffff:ffff:ffff:7fff:ffff:ffff:ffff"}, 492 {"ffff:ffff:ffff:ffff:8000::/99", 9223372036854775807, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/99"}, 493 {"0:0:0:0000:8000:0:0:0", math.MinInt64, "::"}, 494 {"8000:0000:0000:0000:0000:0000:0000:0005/68", -5, "8000::/68"}, 495 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005/7", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:000f/7"}, 496 {"::5/68", -5, "::/68"}, 497 {"::5/68", 5, "::a/68"}, 498 } 499 for i, testCase := range testCases { 500 var ip1, exp IPAddr 501 if err := ParseINet(testCase.s, &ip1); err != nil { 502 t.Fatalf("%d: Bad test input s:%s", i, testCase.s) 503 } 504 if err := ParseINet(testCase.exp, &exp); err != nil { 505 t.Fatalf("%d: Bad test input exp:%s", i, testCase.exp) 506 } 507 508 actual, err := ip1.Add(testCase.i) 509 if err != nil { 510 t.Fatalf("%d: Bad test input s:%s + i:%d", i, testCase.s, testCase.i) 511 } 512 if !actual.Equal(&exp) { 513 t.Errorf("%d: %q + %d actual:%v does not match expected:%v", i, testCase.s, testCase.i, actual, 514 testCase.exp) 515 } 516 } 517 518 errTestCases := []struct { 519 s string 520 i int64 521 }{ 522 {"0.0.0.0", 4294967296}, 523 {"255.255.255.255", -4294967296}, 524 {"192.168.1.2", 1848364646486484868}, 525 {"192.168.1.2/17", -18483646544568}, 526 {"::ffff:192.168.1.2", -4684658846864486648}, 527 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 9223372036854775807}, 528 {"ffff:ffff:ffff:ffff:8000:0000:0000:0001/99", 9223372036854775807}, 529 {"0:0:0:0:7fff:ffff:ffff:ffff", -9223372036854775808}, 530 {"0:0:0:0:7fff:ffff:ffff:ffff/48", -9223372036854775808}, 531 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 1}, 532 {"0:0:0:0000:0800:0:0:0", math.MinInt64}, 533 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005/7", 4484545610}, 534 {"::5/68", -6}, 535 } 536 for i, errTestCase := range errTestCases { 537 var ip1 IPAddr 538 if err := ParseINet(errTestCase.s, &ip1); err != nil { 539 t.Fatalf("%d: Bad test input s:%s", i, errTestCase.s) 540 } 541 542 actual, err1 := ip1.Add(errTestCase.i) 543 if err1 == nil { 544 t.Fatalf("%d: s:%s + i:%d should return Error, but return valid INet value: %v", i, errTestCase.s, errTestCase.i, actual) 545 } 546 } 547 } 548 549 func TestSub(t *testing.T) { 550 testCases := []struct { 551 s string 552 i int64 553 exp string 554 }{ 555 {"0.0.0.0", -4294967295, "255.255.255.255"}, 556 {"255.255.255.255", 4294967295, "0.0.0.0"}, 557 {"192.168.1.2", -184836468, "203.172.98.118"}, 558 {"203.172.98.118/30", 184836468, "192.168.1.2/30"}, 559 {"::4104:4066:5de7:b1fa", 4684658846864486648, "::ffff:192.168.1.2"}, 560 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 9223372036854775807, "ffff:ffff:ffff:ffff:8000::"}, 561 {"ffff:ffff:ffff:ffff:7fff:ffff:ffff:ffff", -9223372036854775808, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"}, 562 {"ffff:ffff:ffff:ffff:8000::/1", -9223372036854775807, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/1"}, 563 {"0:0:0:0000:8000:0:0:0", math.MinInt64, "0:0:0:0001::"}, 564 {"8000:0000:0000:0000:0000:0000:0000:0005/68", 5, "8000::/68"}, 565 {"::5/128", 5, "::"}, 566 {"::5/0", -5, "::a/0"}, 567 } 568 for i, testCase := range testCases { 569 var ip1, exp IPAddr 570 if err := ParseINet(testCase.s, &ip1); err != nil { 571 t.Fatalf("%d: Bad test input s:%s", i, testCase.s) 572 } 573 if err := ParseINet(testCase.exp, &exp); err != nil { 574 t.Fatalf("%d: Bad test input exp:%s", i, testCase.exp) 575 } 576 577 actual, err := ip1.Sub(testCase.i) 578 if err != nil { 579 t.Fatalf("%d: Bad test input s:%s + i:%d", i, testCase.s, testCase.i) 580 } 581 if !actual.Equal(&exp) { 582 t.Errorf("%d: %q - %d actual:%v does not match expected:%v", i, testCase.s, testCase.i, actual, 583 testCase.exp) 584 } 585 } 586 } 587 588 func TestContains(t *testing.T) { 589 testCases := []struct { 590 s1 string 591 s2 string 592 exp bool 593 }{ 594 {"192.168.162.1", "192.168.162.1", false}, 595 {"192.168.162.1/20", "192.168.162.1", true}, 596 597 {"192.168.200.95", "192.168.162.1", false}, 598 {"192.168.200.95/8", "192.168.162.1", true}, 599 {"192.168.200.95/16", "192.168.162.1", true}, 600 {"192.168.200.95/17", "192.168.162.1", true}, 601 {"192.168.200.95/18", "192.168.162.1", false}, 602 {"192.168.200.95/24", "192.168.162.1", false}, 603 {"192.168.200.95/32", "192.168.162.1", false}, 604 605 {"192.168.200.95", "192.168.2.1/24", false}, 606 {"192.168.200.95/8", "192.168.2.1/24", true}, 607 {"192.168.200.95/16", "192.168.2.1/24", true}, 608 {"192.168.200.95/17", "192.168.2.1/24", false}, 609 {"192.168.200.95/18", "192.168.2.1/24", false}, 610 {"192.168.200.95/24", "192.168.2.1/24", false}, 611 {"192.168.200.95/32", "192.168.2.1/24", false}, 612 613 {"192.168.200.95", "192.168.2.1/8", false}, 614 {"192.168.200.95/8", "192.168.2.1/8", false}, 615 {"192.168.200.95/16", "192.168.2.1/8", false}, 616 {"192.168.200.95/17", "192.168.2.1/8", false}, 617 {"192.168.200.95/18", "192.168.2.1/8", false}, 618 {"192.168.200.95/24", "192.168.2.1/8", false}, 619 {"192.168.200.95/32", "192.168.2.1/8", false}, 620 {"2001:0db8:0500:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false}, 621 {"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", true}, 622 {"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0500:5000:0000:0001/50", false}, 623 } 624 for i, testCase := range testCases { 625 var ip1, ip2 IPAddr 626 if err := ParseINet(testCase.s1, &ip1); err != nil { 627 t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1) 628 } 629 if err := ParseINet(testCase.s2, &ip2); err != nil { 630 t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2) 631 } 632 633 actual := ip1.Contains(&ip2) 634 635 if actual != testCase.exp { 636 t.Errorf("%d: %q >> %q actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual, 637 testCase.exp) 638 } 639 } 640 } 641 642 func TestContainsOrEquals(t *testing.T) { 643 testCases := []struct { 644 s1 string 645 s2 string 646 exp bool 647 }{ 648 {"192.168.162.1", "192.168.162.1", true}, 649 {"192.168.162.1/20", "192.168.162.1", true}, 650 651 {"192.168.200.95", "192.168.162.1", false}, 652 {"192.168.200.95/8", "192.168.162.1", true}, 653 {"192.168.200.95/16", "192.168.162.1", true}, 654 {"192.168.200.95/17", "192.168.162.1", true}, 655 {"192.168.200.95/18", "192.168.162.1", false}, 656 {"192.168.200.95/24", "192.168.162.1", false}, 657 {"192.168.200.95/32", "192.168.162.1", false}, 658 659 {"192.168.200.95", "192.168.2.1/24", false}, 660 {"192.168.200.95/8", "192.168.2.1/24", true}, 661 {"192.168.200.95/16", "192.168.2.1/24", true}, 662 {"192.168.200.95/17", "192.168.2.1/24", false}, 663 {"192.168.200.95/18", "192.168.2.1/24", false}, 664 {"192.168.200.95/24", "192.168.2.1/24", false}, 665 {"192.168.200.95/32", "192.168.2.1/24", false}, 666 667 {"192.168.200.95", "192.168.2.1/8", false}, 668 {"192.168.200.95/8", "192.168.2.1/8", true}, 669 {"192.168.200.95/16", "192.168.2.1/8", false}, 670 {"192.168.200.95/17", "192.168.2.1/8", false}, 671 {"192.168.200.95/18", "192.168.2.1/8", false}, 672 {"192.168.200.95/24", "192.168.2.1/8", false}, 673 {"192.168.200.95/32", "192.168.2.1/8", false}, 674 {"2001:0db8:0500:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false}, 675 {"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", true}, 676 {"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0500:5000:0000:0001/50", true}, 677 } 678 for i, testCase := range testCases { 679 var ip1, ip2 IPAddr 680 if err := ParseINet(testCase.s1, &ip1); err != nil { 681 t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1) 682 } 683 if err := ParseINet(testCase.s2, &ip2); err != nil { 684 t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2) 685 } 686 687 actual := ip1.ContainsOrEquals(&ip2) 688 689 if actual != testCase.exp { 690 t.Errorf("%d: %q >>= %q actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual, 691 testCase.exp) 692 } 693 } 694 } 695 696 func TestContainedBy(t *testing.T) { 697 testCases := []struct { 698 s1 string 699 s2 string 700 exp bool 701 }{ 702 {"192.168.162.1", "192.168.162.1", false}, 703 {"192.168.162.1/20", "192.168.162.1", false}, 704 705 {"192.168.200.95", "192.168.162.1", false}, 706 {"192.168.200.95/8", "192.168.162.1", false}, 707 {"192.168.200.95/16", "192.168.162.1", false}, 708 {"192.168.200.95/17", "192.168.162.1", false}, 709 {"192.168.200.95/18", "192.168.162.1", false}, 710 {"192.168.200.95/24", "192.168.162.1", false}, 711 {"192.168.200.95/32", "192.168.162.1", false}, 712 713 {"192.168.200.95", "192.168.2.1/24", false}, 714 {"192.168.200.95/8", "192.168.2.1/24", false}, 715 {"192.168.200.95/16", "192.168.2.1/24", false}, 716 {"192.168.200.95/17", "192.168.2.1/24", false}, 717 {"192.168.200.95/18", "192.168.2.1/24", false}, 718 {"192.168.200.95/24", "192.168.2.1/24", false}, 719 {"192.168.200.95/32", "192.168.2.1/24", false}, 720 721 {"192.168.200.95", "192.168.2.1/8", true}, 722 {"192.168.200.95/8", "192.168.2.1/8", false}, 723 {"192.168.200.95/16", "192.168.2.1/8", true}, 724 {"192.168.200.95/17", "192.168.2.1/8", true}, 725 {"192.168.200.95/18", "192.168.2.1/8", true}, 726 {"192.168.200.95/24", "192.168.2.1/8", true}, 727 {"192.168.200.95/32", "192.168.2.1/8", true}, 728 {"2001:0db8:0500:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false}, 729 {"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false}, 730 {"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0500:5000:0000:0001/50", false}, 731 } 732 for i, testCase := range testCases { 733 var ip1, ip2 IPAddr 734 if err := ParseINet(testCase.s1, &ip1); err != nil { 735 t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1) 736 } 737 if err := ParseINet(testCase.s2, &ip2); err != nil { 738 t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2) 739 } 740 741 actual := ip1.ContainedBy(&ip2) 742 743 if actual != testCase.exp { 744 t.Errorf("%d: %q << %q actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual, 745 testCase.exp) 746 } 747 } 748 } 749 750 func TestContainedByOrEquals(t *testing.T) { 751 testCases := []struct { 752 s1 string 753 s2 string 754 exp bool 755 }{ 756 {"192.168.162.1", "192.168.162.1", true}, 757 {"192.168.162.1/20", "192.168.162.1", false}, 758 759 {"192.168.200.95", "192.168.162.1", false}, 760 {"192.168.200.95/8", "192.168.162.1", false}, 761 {"192.168.200.95/16", "192.168.162.1", false}, 762 {"192.168.200.95/17", "192.168.162.1", false}, 763 {"192.168.200.95/18", "192.168.162.1", false}, 764 {"192.168.200.95/24", "192.168.162.1", false}, 765 {"192.168.200.95/32", "192.168.162.1", false}, 766 767 {"192.168.200.95", "192.168.2.1/24", false}, 768 {"192.168.200.95/8", "192.168.2.1/24", false}, 769 {"192.168.200.95/16", "192.168.2.1/24", false}, 770 {"192.168.200.95/17", "192.168.2.1/24", false}, 771 {"192.168.200.95/18", "192.168.2.1/24", false}, 772 {"192.168.200.95/24", "192.168.2.1/24", false}, 773 {"192.168.200.95/32", "192.168.2.1/24", false}, 774 775 {"192.168.200.95", "192.168.2.1/8", true}, 776 {"192.168.200.95/8", "192.168.2.1/8", true}, 777 {"192.168.200.95/16", "192.168.2.1/8", true}, 778 {"192.168.200.95/17", "192.168.2.1/8", true}, 779 {"192.168.200.95/18", "192.168.2.1/8", true}, 780 {"192.168.200.95/24", "192.168.2.1/8", true}, 781 {"192.168.200.95/32", "192.168.2.1/8", true}, 782 {"2001:0db8:0500:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false}, 783 {"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false}, 784 {"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0500:5000:0000:0001/50", true}, 785 } 786 for i, testCase := range testCases { 787 var ip1, ip2 IPAddr 788 if err := ParseINet(testCase.s1, &ip1); err != nil { 789 t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1) 790 } 791 if err := ParseINet(testCase.s2, &ip2); err != nil { 792 t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2) 793 } 794 795 actual := ip1.ContainedByOrEquals(&ip2) 796 797 if actual != testCase.exp { 798 t.Errorf("%d: %q <<= %q actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual, 799 testCase.exp) 800 } 801 } 802 } 803 804 func TestContainsOrContainedBy(t *testing.T) { 805 testCases := []struct { 806 s1 string 807 s2 string 808 exp bool 809 }{ 810 {"192.168.162.1", "192.168.162.1", true}, 811 {"192.168.162.1/20", "192.168.162.1", true}, 812 813 {"192.168.200.95", "192.168.162.1", false}, 814 {"192.168.200.95/8", "192.168.162.1", true}, 815 {"192.168.200.95/16", "192.168.162.1", true}, 816 {"192.168.200.95/17", "192.168.162.1", true}, 817 {"192.168.200.95/18", "192.168.162.1", false}, 818 {"192.168.200.95/24", "192.168.162.1", false}, 819 {"192.168.200.95/32", "192.168.162.1", false}, 820 821 {"192.168.200.95", "192.168.2.1/24", false}, 822 {"192.168.200.95/8", "192.168.2.1/24", true}, 823 {"192.168.200.95/16", "192.168.2.1/24", true}, 824 {"192.168.200.95/17", "192.168.2.1/24", false}, 825 {"192.168.200.95/18", "192.168.2.1/24", false}, 826 {"192.168.200.95/24", "192.168.2.1/24", false}, 827 {"192.168.200.95/32", "192.168.2.1/24", false}, 828 829 {"192.168.200.95", "192.168.2.1/8", true}, 830 {"192.168.200.95/8", "192.168.2.1/8", true}, 831 {"192.168.200.95/16", "192.168.2.1/8", true}, 832 {"192.168.200.95/17", "192.168.2.1/8", true}, 833 {"192.168.200.95/18", "192.168.2.1/8", true}, 834 {"192.168.200.95/24", "192.168.2.1/8", true}, 835 {"192.168.200.95/32", "192.168.2.1/8", true}, 836 {"192.168.200.95/32", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false}, 837 {"2001:0db8:0500:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false}, 838 {"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", true}, 839 {"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0500:5000:0000:0001/50", true}, 840 } 841 for i, testCase := range testCases { 842 var ip1, ip2 IPAddr 843 if err := ParseINet(testCase.s1, &ip1); err != nil { 844 t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1) 845 } 846 if err := ParseINet(testCase.s2, &ip2); err != nil { 847 t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2) 848 } 849 850 actual := ip1.ContainsOrContainedBy(&ip2) 851 852 if actual != testCase.exp { 853 t.Errorf("%d: %q && %q actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual, 854 testCase.exp) 855 } 856 } 857 } 858 859 func TestSubIPAddr(t *testing.T) { 860 testCases := []struct { 861 s1 string 862 s2 string 863 exp int64 864 }{ 865 {"0.0.0.0", "255.255.255.255", -4294967295}, 866 {"255.255.255.255", "0.0.0.0", 4294967295}, 867 {"192.168.1.2", "203.172.98.118", -184836468}, 868 {"203.172.98.118/17", "192.168.1.2/1", 184836468}, 869 {"::4104:4066:5de7:b1fa", "::ffff:192.168.1.2/44", 4684658846864486648}, 870 {"ffff:ffff:ffff:ffff:8000::/7", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", -9223372036854775807}, 871 {"ffff:ffff:ffff:ffff:7fff:ffff:ffff:ffff", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", -9223372036854775808}, 872 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/91", "ffff:ffff:ffff:ffff:8000::/99", 9223372036854775807}, 873 {"::", "0:0:0:0000:8000:0:0:0", math.MinInt64}, 874 {"8000::/68", "8000:0000:0000:0000:0000:0000:0000:0005/68", -5}, 875 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:000f/57", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005/7", 10}, 876 {"::/68", "::5/68", -5}, 877 {"::a/68", "::5/68", 5}, 878 } 879 for i, testCase := range testCases { 880 var ip1, ip2 IPAddr 881 if err := ParseINet(testCase.s1, &ip1); err != nil { 882 t.Fatalf("%d: Bad test input s:%s", i, testCase.s1) 883 } 884 if err := ParseINet(testCase.s2, &ip2); err != nil { 885 t.Fatalf("%d: Bad test input exp:%s", i, testCase.s2) 886 } 887 888 actual, err := ip1.SubIPAddr(&ip2) 889 if err != nil { 890 t.Fatalf("%d: Bad test input s1: %s - s2: %s", i, testCase.s1, testCase.s2) 891 } 892 if actual != testCase.exp { 893 t.Errorf("%d: %s - %s actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual, 894 testCase.exp) 895 } 896 } 897 898 errTestCases := []struct { 899 s1 string 900 s2 string 901 }{ 902 {"2323:5475:9894:8745:4104:4066:5de7:b1fa", "::ffff:192.168.1.2"}, 903 {"ffff:ffff:ffff:ffff:7fff:ffff:ffff:fffe", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/99"}, 904 {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/99", "ffff:ffff:ffff:ffff:7fff:ffff:ffff:ffff/91"}, 905 {"::", "0:0:0:0000:8000:0:0:0001"}, 906 {"0:0:0:0000:8000:0:0:0000", "::"}, 907 {"192.168.1.2/5", "::"}, 908 {"0:0:0:0000:8000:0:0:0000/4", "192.168.1.2"}, 909 {"10:0:0:0000:8000:0:0:0000", "10::"}, 910 {"10::", "10:0:0:0000:8000:0:0:0001"}, 911 } 912 for i, errTestCase := range errTestCases { 913 var ip1, ip2 IPAddr 914 if err := ParseINet(errTestCase.s1, &ip1); err != nil { 915 t.Fatalf("%d: Bad test input s:%s", i, errTestCase.s1) 916 } 917 if err := ParseINet(errTestCase.s2, &ip2); err != nil { 918 t.Fatalf("%d: Bad test input s:%s", i, errTestCase.s2) 919 } 920 921 actual, err1 := ip1.SubIPAddr(&ip2) 922 if err1 == nil { 923 t.Fatalf("%d: s:%s - s:%s should return Error, but returns int64:%v", i, errTestCase.s1, errTestCase.s2, actual) 924 } 925 } 926 }