ipaddress 0.7.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +13 -0
- data/README.rdoc +106 -80
- data/VERSION +1 -1
- data/ipaddress.gemspec +55 -0
- data/lib/ipaddress.rb +16 -2
- data/lib/ipaddress/ipv4.rb +76 -68
- data/lib/ipaddress/ipv6.rb +132 -22
- data/lib/ipaddress/prefix.rb +14 -1
- data/test/ipaddress/ipv4_test.rb +65 -43
- data/test/ipaddress/ipv6_test.rb +68 -2
- metadata +26 -48
- data/lib/ipaddress/extensions/extensions.rb +0 -22
- data/test/ipaddress/extensions/extensions_test.rb +0 -18
data/lib/ipaddress/ipv6.rb
CHANGED
@@ -22,7 +22,7 @@ module IPAddress;
|
|
22
22
|
# bits or two octect. For example, the following is a valid IPv6
|
23
23
|
# address:
|
24
24
|
#
|
25
|
-
#
|
25
|
+
# 2001:0db8:0000:0000:0008:0800:200c:417a
|
26
26
|
#
|
27
27
|
# Letters in an IPv6 address are usually written downcase, as per
|
28
28
|
# RFC. You can create a new IPv6 object using uppercase letters, but
|
@@ -42,7 +42,7 @@ module IPAddress;
|
|
42
42
|
# Using compression, the IPv6 address written above can be shorten into
|
43
43
|
# the following, equivalent, address
|
44
44
|
#
|
45
|
-
#
|
45
|
+
# 2001:db8::8:800:200c:417a
|
46
46
|
#
|
47
47
|
# This short version is often used in human representation.
|
48
48
|
#
|
@@ -51,7 +51,7 @@ module IPAddress;
|
|
51
51
|
# As we used to do with IPv4 addresses, an IPv6 address can be written
|
52
52
|
# using the prefix notation to specify the subnet mask:
|
53
53
|
#
|
54
|
-
#
|
54
|
+
# 2001:db8::8:800:200c:417a/64
|
55
55
|
#
|
56
56
|
# The /64 part means that the first 64 bits of the address are
|
57
57
|
# representing the network portion, and the last 64 bits are the host
|
@@ -75,9 +75,9 @@ module IPAddress;
|
|
75
75
|
#
|
76
76
|
# An IPv6 address can be expressed in any of the following forms:
|
77
77
|
#
|
78
|
-
# * "
|
79
|
-
# * "
|
80
|
-
# * "
|
78
|
+
# * "2001:0db8:0000:0000:0008:0800:200C:417A": IPv6 address with no compression
|
79
|
+
# * "2001:db8:0:0:8:800:200C:417A": IPv6 address with leading zeros compression
|
80
|
+
# * "2001:db8::8:800:200C:417A": IPv6 address with full compression
|
81
81
|
#
|
82
82
|
# In all these 3 cases, a new IPv6 address object will be created, using the default
|
83
83
|
# subnet mask /128
|
@@ -328,6 +328,36 @@ module IPAddress;
|
|
328
328
|
to_u128 & @prefix.to_u128
|
329
329
|
end
|
330
330
|
|
331
|
+
#
|
332
|
+
# Returns the broadcast address in Unsigned 128bits format
|
333
|
+
#
|
334
|
+
# ip6 = IPAddress "2001:db8::8:800:200c:417a/64"
|
335
|
+
#
|
336
|
+
# ip6.broadcast_u128
|
337
|
+
# #=> 42540766411282592875350729025363378175
|
338
|
+
#
|
339
|
+
# Please note that there is no Broadcast concept in IPv6
|
340
|
+
# addresses as in IPv4 addresses, and this method is just
|
341
|
+
# an helper to other functions.
|
342
|
+
#
|
343
|
+
def broadcast_u128
|
344
|
+
network_u128 + size - 1
|
345
|
+
end
|
346
|
+
|
347
|
+
#
|
348
|
+
# Returns the number of IP addresses included
|
349
|
+
# in the network. It also counts the network
|
350
|
+
# address and the broadcast address.
|
351
|
+
#
|
352
|
+
# ip6 = IPAddress("2001:db8::8:800:200c:417a/64")
|
353
|
+
#
|
354
|
+
# ip6.size
|
355
|
+
# #=> 18446744073709551616
|
356
|
+
#
|
357
|
+
def size
|
358
|
+
2 ** @prefix.host_prefix
|
359
|
+
end
|
360
|
+
|
331
361
|
#
|
332
362
|
# Checks whether a subnet includes the given IP address.
|
333
363
|
#
|
@@ -384,7 +414,74 @@ module IPAddress;
|
|
384
414
|
def mapped?
|
385
415
|
to_u128 >> 32 == 0xffff
|
386
416
|
end
|
387
|
-
|
417
|
+
|
418
|
+
#
|
419
|
+
# Iterates over all the IP addresses for the given
|
420
|
+
# network (or IP address).
|
421
|
+
#
|
422
|
+
# The object yielded is a new IPv6 object created
|
423
|
+
# from the iteration.
|
424
|
+
#
|
425
|
+
# ip6 = IPAddress("2001:db8::4/125")
|
426
|
+
#
|
427
|
+
# ip6.each do |i|
|
428
|
+
# p i.compressed
|
429
|
+
# end
|
430
|
+
# #=> "2001:db8::"
|
431
|
+
# #=> "2001:db8::1"
|
432
|
+
# #=> "2001:db8::2"
|
433
|
+
# #=> "2001:db8::3"
|
434
|
+
# #=> "2001:db8::4"
|
435
|
+
# #=> "2001:db8::5"
|
436
|
+
# #=> "2001:db8::6"
|
437
|
+
# #=> "2001:db8::7"
|
438
|
+
#
|
439
|
+
# WARNING: if the host portion is very large, this method
|
440
|
+
# can be very slow and possibly hang your system!
|
441
|
+
#
|
442
|
+
def each
|
443
|
+
(network_u128..broadcast_u128).each do |i|
|
444
|
+
yield self.class.parse_u128(i, @prefix)
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
#
|
449
|
+
# Spaceship operator to compare IPv6 objects
|
450
|
+
#
|
451
|
+
# Comparing IPv6 addresses is useful to ordinate
|
452
|
+
# them into lists that match our intuitive
|
453
|
+
# perception of ordered IP addresses.
|
454
|
+
#
|
455
|
+
# The first comparison criteria is the u128 value.
|
456
|
+
# For example, 2001:db8:1::1 will be considered
|
457
|
+
# to be less than 2001:db8:2::1, because, in a ordered list,
|
458
|
+
# we expect 2001:db8:1::1 to come before 2001:db8:2::1.
|
459
|
+
#
|
460
|
+
# The second criteria, in case two IPv6 objects
|
461
|
+
# have identical addresses, is the prefix. An higher
|
462
|
+
# prefix will be considered greater than a lower
|
463
|
+
# prefix. This is because we expect to see
|
464
|
+
# 2001:db8:1::1/64 come before 2001:db8:1::1/65
|
465
|
+
#
|
466
|
+
# Example:
|
467
|
+
#
|
468
|
+
# ip1 = IPAddress "2001:db8:1::1/64"
|
469
|
+
# ip2 = IPAddress "2001:db8:2::1/64"
|
470
|
+
# ip3 = IPAddress "2001:db8:1::1/65"
|
471
|
+
#
|
472
|
+
# ip1 < ip2
|
473
|
+
# #=> true
|
474
|
+
# ip1 < ip3
|
475
|
+
# #=> false
|
476
|
+
#
|
477
|
+
# [ip1,ip2,ip3].sort.map{|i| i.to_string}
|
478
|
+
# #=> ["2001:db8:1::1/64","2001:db8:1::1/65","2001:db8:2::1/64"]
|
479
|
+
#
|
480
|
+
def <=>(oth)
|
481
|
+
return prefix <=> oth.prefix if to_u128 == oth.to_u128
|
482
|
+
to_u128 <=> oth.to_u128
|
483
|
+
end
|
484
|
+
|
388
485
|
#
|
389
486
|
# Returns the address portion of an IP in binary format,
|
390
487
|
# as a string containing a sequence of 0 and 1
|
@@ -430,6 +527,19 @@ module IPAddress;
|
|
430
527
|
@address.gsub(":","-") + ".ipv6-literal.net"
|
431
528
|
end
|
432
529
|
|
530
|
+
#
|
531
|
+
# Returns a new IPv6 object with the network number
|
532
|
+
# for the given IP.
|
533
|
+
#
|
534
|
+
# ip = IPAddress "2001:db8:1:1:1:1:1:1/32"
|
535
|
+
#
|
536
|
+
# ip.network.to_string
|
537
|
+
# #=> "2001:db8::/32"
|
538
|
+
#
|
539
|
+
def network
|
540
|
+
self.class.parse_u128(network_u128, @prefix)
|
541
|
+
end
|
542
|
+
|
433
543
|
#
|
434
544
|
# Extract 16 bits groups from a string
|
435
545
|
#
|
@@ -470,18 +580,18 @@ module IPAddress;
|
|
470
580
|
# Creates a new IPv6 object from an
|
471
581
|
# unsigned 128 bits integer.
|
472
582
|
#
|
473
|
-
# ip6 = IPAddress::IPv6::parse_u128(
|
583
|
+
# ip6 = IPAddress::IPv6::parse_u128(42540766411282592856906245548098208122)
|
474
584
|
# ip6.prefix = 64
|
475
585
|
#
|
476
|
-
# ip6.
|
477
|
-
# #=> "
|
586
|
+
# ip6.to_string
|
587
|
+
# #=> "2001:db8::8:800:200c:417a/64"
|
478
588
|
#
|
479
589
|
# The +prefix+ parameter is optional:
|
480
590
|
#
|
481
|
-
# ip6 = IPAddress::IPv6::parse_u128(
|
591
|
+
# ip6 = IPAddress::IPv6::parse_u128(42540766411282592856906245548098208122, 64)
|
482
592
|
#
|
483
|
-
# ip6.
|
484
|
-
# #=> "
|
593
|
+
# ip6.to_string
|
594
|
+
# #=> "2001:db8::8:800:200c:417a/64"
|
485
595
|
#
|
486
596
|
def self.parse_u128(u128, prefix=128)
|
487
597
|
str = IN6FORMAT % (0..7).map{|i| (u128>>(112-16*i))&0xffff}
|
@@ -495,15 +605,15 @@ module IPAddress;
|
|
495
605
|
# ip6 = IPAddress::IPv6::parse_hex("20010db80000000000080800200c417a")
|
496
606
|
# ip6.prefix = 64
|
497
607
|
#
|
498
|
-
# ip6.
|
608
|
+
# ip6.to_string
|
499
609
|
# #=> "2001:db8::8:800:200c:417a/64"
|
500
610
|
#
|
501
611
|
# The +prefix+ parameter is optional:
|
502
612
|
#
|
503
613
|
# ip6 = IPAddress::IPv6::parse_hex("20010db80000000000080800200c417a", 64)
|
504
614
|
#
|
505
|
-
# ip6.
|
506
|
-
# #=> "
|
615
|
+
# ip6.to_string
|
616
|
+
# #=> "2001:db8::8:800:200c:417a/64"
|
507
617
|
#
|
508
618
|
def self.parse_hex(hex, prefix=128)
|
509
619
|
self.parse_u128(hex.hex, prefix)
|
@@ -605,14 +715,14 @@ module IPAddress;
|
|
605
715
|
#
|
606
716
|
# ip = IPAddress::IPv6::Loopback.new
|
607
717
|
#
|
608
|
-
# ip.
|
718
|
+
# ip.to_string
|
609
719
|
# #=> "::1/128"
|
610
720
|
#
|
611
721
|
# or by using the wrapper:
|
612
722
|
#
|
613
723
|
# ip = IPAddress "::1"
|
614
724
|
#
|
615
|
-
# ip.
|
725
|
+
# ip.to_string
|
616
726
|
# #=> "::1/128"
|
617
727
|
#
|
618
728
|
# Checking if an address is loopback is easy with the IPv6#loopback?
|
@@ -629,7 +739,7 @@ module IPAddress;
|
|
629
739
|
#
|
630
740
|
# ip = IPAddress::IPv6::Loopback.new
|
631
741
|
#
|
632
|
-
# ip.
|
742
|
+
# ip.to_string
|
633
743
|
# #=> "::1/128"
|
634
744
|
#
|
635
745
|
def initialize
|
@@ -668,7 +778,7 @@ module IPAddress;
|
|
668
778
|
# ip6.mapped?
|
669
779
|
# #=> true
|
670
780
|
#
|
671
|
-
# ip6.
|
781
|
+
# ip6.to_string
|
672
782
|
# #=> "::FFFF:172.16.10.1/128"
|
673
783
|
#
|
674
784
|
# Now with the +ipv4+ attribute, we can easily access the IPv4 portion
|
@@ -695,7 +805,7 @@ module IPAddress;
|
|
695
805
|
# That is, two colons and the IPv4 address. However, as by RFC, the ffff
|
696
806
|
# group will be automatically added at the beginning
|
697
807
|
#
|
698
|
-
# ip6.
|
808
|
+
# ip6.to_string
|
699
809
|
# => "::ffff:172.16.10.1/128"
|
700
810
|
#
|
701
811
|
# making it a mapped IPv6 compatible address.
|
@@ -718,7 +828,7 @@ module IPAddress;
|
|
718
828
|
#
|
719
829
|
# ip6 = IPAddress::IPv6::Mapped.new "::0d01:4403"
|
720
830
|
#
|
721
|
-
# ip6.
|
831
|
+
# ip6.to_string
|
722
832
|
# #=> "::ffff:13.1.68.3"
|
723
833
|
#
|
724
834
|
def initialize(str)
|
data/lib/ipaddress/prefix.rb
CHANGED
@@ -18,7 +18,7 @@ module IPAddress
|
|
18
18
|
# IPAddress::Prefix shouldn't be accesses directly, unless
|
19
19
|
# for particular needs.
|
20
20
|
#
|
21
|
-
class Prefix
|
21
|
+
class Prefix
|
22
22
|
|
23
23
|
include Comparable
|
24
24
|
|
@@ -247,6 +247,19 @@ module IPAddress
|
|
247
247
|
bits.to_i(2)
|
248
248
|
end
|
249
249
|
|
250
|
+
#
|
251
|
+
# Returns the length of the host portion
|
252
|
+
# of a netmask.
|
253
|
+
#
|
254
|
+
# prefix = Prefix128.new 96
|
255
|
+
#
|
256
|
+
# prefix.host_prefix
|
257
|
+
# #=> 32
|
258
|
+
#
|
259
|
+
def host_prefix
|
260
|
+
128 - @prefix
|
261
|
+
end
|
262
|
+
|
250
263
|
end # class Prefix123 < Prefix
|
251
264
|
|
252
265
|
end # module IPAddress
|
data/test/ipaddress/ipv4_test.rb
CHANGED
@@ -304,20 +304,20 @@ class IPv4Test < Test::Unit::TestCase
|
|
304
304
|
assert_equal "1.10.16.172.in-addr.arpa", @ip.reverse
|
305
305
|
end
|
306
306
|
|
307
|
-
def
|
307
|
+
def test_method_compare
|
308
308
|
ip1 = @klass.new("10.1.1.1/8")
|
309
309
|
ip2 = @klass.new("10.1.1.1/16")
|
310
310
|
ip3 = @klass.new("172.16.1.1/14")
|
311
311
|
ip4 = @klass.new("10.1.1.1/8")
|
312
312
|
|
313
|
-
#
|
314
|
-
assert_equal true, ip1
|
315
|
-
assert_equal false, ip1
|
316
|
-
assert_equal false, ip2
|
317
|
-
# ip2 should be
|
313
|
+
# ip2 should be greater than ip1
|
314
|
+
assert_equal true, ip1 < ip2
|
315
|
+
assert_equal false, ip1 > ip2
|
316
|
+
assert_equal false, ip2 < ip1
|
317
|
+
# ip2 should be less than ip3
|
318
318
|
assert_equal true, ip2 < ip3
|
319
319
|
assert_equal false, ip2 > ip3
|
320
|
-
# ip1 should be
|
320
|
+
# ip1 should be less than ip3
|
321
321
|
assert_equal true, ip1 < ip3
|
322
322
|
assert_equal false, ip1 > ip3
|
323
323
|
assert_equal false, ip3 < ip1
|
@@ -326,7 +326,13 @@ class IPv4Test < Test::Unit::TestCase
|
|
326
326
|
# ip1 should be equal to ip4
|
327
327
|
assert_equal true, ip1 == ip4
|
328
328
|
# test sorting
|
329
|
-
arr = ["10.1.1.1/
|
329
|
+
arr = ["10.1.1.1/8","10.1.1.1/16","172.16.1.1/14"]
|
330
|
+
assert_equal arr, [ip1,ip2,ip3].sort.map{|s| s.to_string}
|
331
|
+
# test same prefix
|
332
|
+
ip1 = @klass.new("10.0.0.0/24")
|
333
|
+
ip2 = @klass.new("10.0.0.0/16")
|
334
|
+
ip3 = @klass.new("10.0.0.0/8")
|
335
|
+
arr = ["10.0.0.0/8","10.0.0.0/16","10.0.0.0/24"]
|
330
336
|
assert_equal arr, [ip1,ip2,ip3].sort.map{|s| s.to_string}
|
331
337
|
end
|
332
338
|
|
@@ -371,41 +377,57 @@ class IPv4Test < Test::Unit::TestCase
|
|
371
377
|
assert_equal 24, ip.prefix.to_i
|
372
378
|
end
|
373
379
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
380
|
+
def test_method_split
|
381
|
+
assert_raise(ArgumentError) {@ip.split(0)}
|
382
|
+
assert_raise(ArgumentError) {@ip.split(257)}
|
383
|
+
|
384
|
+
assert_equal @ip.network, @ip.split(1).first
|
385
|
+
|
386
|
+
arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
|
387
|
+
"172.16.10.96/27", "172.16.10.128/27", "172.16.10.160/27",
|
388
|
+
"172.16.10.192/27", "172.16.10.224/27"]
|
389
|
+
assert_equal arr, @network.split(8).map {|s| s.to_string}
|
390
|
+
arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
|
391
|
+
"172.16.10.96/27", "172.16.10.128/27", "172.16.10.160/27",
|
392
|
+
"172.16.10.192/26"]
|
393
|
+
assert_equal arr, @network.split(7).map {|s| s.to_string}
|
394
|
+
arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
|
395
|
+
"172.16.10.96/27", "172.16.10.128/26", "172.16.10.192/26"]
|
396
|
+
assert_equal arr, @network.split(6).map {|s| s.to_string}
|
397
|
+
arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
|
398
|
+
"172.16.10.96/27", "172.16.10.128/25"]
|
399
|
+
assert_equal arr, @network.split(5).map {|s| s.to_string}
|
400
|
+
arr = ["172.16.10.0/26", "172.16.10.64/26", "172.16.10.128/26",
|
401
|
+
"172.16.10.192/26"]
|
402
|
+
assert_equal arr, @network.split(4).map {|s| s.to_string}
|
403
|
+
arr = ["172.16.10.0/26", "172.16.10.64/26", "172.16.10.128/25"]
|
404
|
+
assert_equal arr, @network.split(3).map {|s| s.to_string}
|
405
|
+
arr = ["172.16.10.0/25", "172.16.10.128/25"]
|
406
|
+
assert_equal arr, @network.split(2).map {|s| s.to_string}
|
407
|
+
arr = ["172.16.10.0/24"]
|
408
|
+
assert_equal arr, @network.split(1).map {|s| s.to_string}
|
409
|
+
end
|
410
|
+
|
411
|
+
def test_method_subnet
|
412
|
+
assert_raise(ArgumentError) {@network.subnet(23)}
|
413
|
+
assert_raise(ArgumentError) {@network.subnet(33)}
|
414
|
+
assert_nothing_raised {@ip.subnet(30)}
|
415
|
+
arr = ["172.16.10.0/26", "172.16.10.64/26", "172.16.10.128/26",
|
416
|
+
"172.16.10.192/26"]
|
417
|
+
assert_equal arr, @network.subnet(26).map {|s| s.to_string}
|
418
|
+
arr = ["172.16.10.0/25", "172.16.10.128/25"]
|
419
|
+
assert_equal arr, @network.subnet(25).map {|s| s.to_string}
|
420
|
+
arr = ["172.16.10.0/24"]
|
421
|
+
assert_equal arr, @network.subnet(24).map {|s| s.to_string}
|
422
|
+
end
|
423
|
+
|
424
|
+
def test_method_supernet
|
425
|
+
assert_raise(ArgumentError) {@ip.supernet(24)}
|
426
|
+
assert_equal "0.0.0.0/0", @ip.supernet(0).to_string
|
427
|
+
assert_equal "0.0.0.0/0", @ip.supernet(-2).to_string
|
428
|
+
assert_equal "172.16.10.0/23", @ip.supernet(23).to_string
|
429
|
+
assert_equal "172.16.8.0/22", @ip.supernet(22).to_string
|
430
|
+
end
|
409
431
|
|
410
432
|
def test_classmethod_parse_u32
|
411
433
|
@decimal_values.each do |addr,int|
|
data/test/ipaddress/ipv6_test.rb
CHANGED
@@ -32,6 +32,11 @@ class IPv6Test < Test::Unit::TestCase
|
|
32
32
|
|
33
33
|
@invalid_ipv6 = [":1:2:3:4:5:6:7",
|
34
34
|
":1:2:3:4:5:6:7"]
|
35
|
+
|
36
|
+
@networks = {
|
37
|
+
"2001:db8:1:1:1:1:1:1/32" => "2001:db8::/32",
|
38
|
+
"2001:db8:1:1:1:1:1::/32" => "2001:db8::/32",
|
39
|
+
"2001:db8::1/64" => "2001:db8::/64"}
|
35
40
|
|
36
41
|
@ip = @klass.new "2001:db8::8:800:200c:417a/64"
|
37
42
|
@network = @klass.new "2001:db8:8:800::/64"
|
@@ -122,7 +127,22 @@ class IPv6Test < Test::Unit::TestCase
|
|
122
127
|
def test_method_network_u128
|
123
128
|
assert_equal 42540766411282592856903984951653826560, @ip.network_u128
|
124
129
|
end
|
125
|
-
|
130
|
+
|
131
|
+
def test_method_broadcast_u128
|
132
|
+
assert_equal 42540766411282592875350729025363378175, @ip.broadcast_u128
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_method_size
|
136
|
+
ip = @klass.new("2001:db8::8:800:200c:417a/64")
|
137
|
+
assert_equal 2**64, ip.size
|
138
|
+
ip = @klass.new("2001:db8::8:800:200c:417a/32")
|
139
|
+
assert_equal 2**96, ip.size
|
140
|
+
ip = @klass.new("2001:db8::8:800:200c:417a/120")
|
141
|
+
assert_equal 2**8, ip.size
|
142
|
+
ip = @klass.new("2001:db8::8:800:200c:417a/124")
|
143
|
+
assert_equal 2**4, ip.size
|
144
|
+
end
|
145
|
+
|
126
146
|
def test_method_include?
|
127
147
|
assert_equal true, @ip.include?(@ip)
|
128
148
|
# test prefix on same address
|
@@ -186,7 +206,53 @@ class IPv6Test < Test::Unit::TestCase
|
|
186
206
|
assert_equal true, @klass.new("::1").loopback?
|
187
207
|
assert_equal false, @ip.loopback?
|
188
208
|
end
|
189
|
-
|
209
|
+
|
210
|
+
def test_method_network
|
211
|
+
@networks.each do |addr,net|
|
212
|
+
ip = @klass.new addr
|
213
|
+
assert_instance_of @klass, ip.network
|
214
|
+
assert_equal net, ip.network.to_string
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_method_each
|
219
|
+
ip = @klass.new("2001:db8::4/125")
|
220
|
+
arr = []
|
221
|
+
ip.each {|i| arr << i.compressed}
|
222
|
+
expected = ["2001:db8::","2001:db8::1","2001:db8::2",
|
223
|
+
"2001:db8::3","2001:db8::4","2001:db8::5",
|
224
|
+
"2001:db8::6","2001:db8::7"]
|
225
|
+
assert_equal expected, arr
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_method_compare
|
229
|
+
ip1 = @klass.new("2001:db8:1::1/64")
|
230
|
+
ip2 = @klass.new("2001:db8:2::1/64")
|
231
|
+
ip3 = @klass.new("2001:db8:1::2/64")
|
232
|
+
ip4 = @klass.new("2001:db8:1::1/65")
|
233
|
+
|
234
|
+
# ip2 should be greater than ip1
|
235
|
+
assert_equal true, ip2 > ip1
|
236
|
+
assert_equal false, ip1 > ip2
|
237
|
+
assert_equal false, ip2 < ip1
|
238
|
+
# ip3 should be less than ip2
|
239
|
+
assert_equal true, ip2 > ip3
|
240
|
+
assert_equal false, ip2 < ip3
|
241
|
+
# ip1 should be less than ip3
|
242
|
+
assert_equal true, ip1 < ip3
|
243
|
+
assert_equal false, ip1 > ip3
|
244
|
+
assert_equal false, ip3 < ip1
|
245
|
+
# ip1 should be equal to itself
|
246
|
+
assert_equal true, ip1 == ip1
|
247
|
+
# ip4 should be greater than ip1
|
248
|
+
assert_equal true, ip1 < ip4
|
249
|
+
assert_equal false, ip1 > ip4
|
250
|
+
# test sorting
|
251
|
+
arr = ["2001:db8:1::1/64","2001:db8:1::1/65",
|
252
|
+
"2001:db8:1::2/64","2001:db8:2::1/64"]
|
253
|
+
assert_equal arr, [ip1,ip2,ip3,ip4].sort.map{|s| s.to_string}
|
254
|
+
end
|
255
|
+
|
190
256
|
def test_classmethod_expand
|
191
257
|
compressed = "2001:db8:0:cd30::"
|
192
258
|
expanded = "2001:0db8:0000:cd30:0000:0000:0000:0000"
|