diff options
-rw-r--r-- | CHANGELOG.rdoc | 3 | ||||
-rw-r--r-- | lib/ipaddress/ipv4.rb | 47 | ||||
-rw-r--r-- | lib/ipaddress/ipv6.rb | 37 | ||||
-rw-r--r-- | test/ipaddress/ipv4_test.rb | 25 | ||||
-rw-r--r-- | test/ipaddress/ipv6_test.rb | 30 |
5 files changed, 110 insertions, 32 deletions
diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 74d62fb..f20bdad 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,10 +1,13 @@ == ipaddress 0.8.0 CHANGED:: Removed extension methods and extension directory to easy integration with the stdlib +CHANGED:: Reworked IPv4#<=>, now intuitively sorts objects based on the prefix +CHANGED:: IPv4#supernet now returns "0.0.0.0/0" if supernetting with a prefix less than 1 NEW:: IPv6#network NEW:: Prefix128#host_prefix NEW:: IPv6#broadcast_u128 NEW:: IPv6#each +NEW:: IPv6#<=> == ipaddress 0.7.5 diff --git a/lib/ipaddress/ipv4.rb b/lib/ipaddress/ipv4.rb index e3f9ab7..76ece23 100644 --- a/lib/ipaddress/ipv4.rb +++ b/lib/ipaddress/ipv4.rb @@ -426,14 +426,22 @@ module IPAddress; end # - # Spaceship operator to compare IP addresses + # Spaceship operator to compare IPv4 objects # - # An IP address is considered to be minor if it - # has a greater prefix (thus smaller hosts - # portion) and a smaller u32 value. + # Comparing IPv4 addresses is useful to ordinate + # them into lists that match our intuitive + # perception of ordered IP addresses. + # + # The first comparison criteria is the u32 value. + # For example, 10.100.100.1 will be considered + # to be less than 172.16.0.1, because, in a ordered list, + # we expect 10.100.100.1 to come before 172.16.0.1. # - # For example, "10.100.100.1/8" is smaller than - # "172.16.0.1/16", but it's bigger than "10.100.100.1/16". + # The second criteria, in case two IPv4 objects + # have identical addresses, is the prefix. An higher + # prefix will be considered greater than a lower + # prefix. This is because we expect to see + # 10.100.100.0/24 come before 10.100.100.0/25. # # Example: # @@ -443,22 +451,15 @@ module IPAddress; # # ip1 < ip2 # #=> true - # ip1 < ip3 + # ip1 > ip3 # #=> false # + # [ip1,ip2,ip3].sort.map{|i| i.to_string} + # #=> ["10.100.100.1/8","10.100.100.1/16","172.16.0.1/16"] + # def <=>(oth) - if to_u32 > oth.to_u32 - return 1 - elsif to_u32 < oth.to_u32 - return -1 - else - if prefix < oth.prefix - return 1 - elsif prefix > oth.prefix - return -1 - end - end - return 0 + return prefix <=> oth.prefix if to_u32 == oth.to_u32 + to_u32 <=> oth.to_u32 end # @@ -643,11 +644,13 @@ module IPAddress; # # ip.supernet(22).to_string # #=> "172.16.8.0/22" - # + # + # If +new_prefix+ is less than 1, returns 0.0.0.0/0 + # def supernet(new_prefix) - raise ArgumentError, "Can't supernet a /1 network" if new_prefix < 1 raise ArgumentError, "New prefix must be smaller than existing prefix" if new_prefix >= @prefix.to_i - self.class.new(@address+"/#{new_prefix}").network + return self.class.new("0.0.0.0/0") if new_prefix < 1 + return self.class.new(@address+"/#{new_prefix}").network end # diff --git a/lib/ipaddress/ipv6.rb b/lib/ipaddress/ipv6.rb index eb4b13c..2532003 100644 --- a/lib/ipaddress/ipv6.rb +++ b/lib/ipaddress/ipv6.rb @@ -446,6 +446,43 @@ module IPAddress; end # + # Spaceship operator to compare IPv6 objects + # + # Comparing IPv6 addresses is useful to ordinate + # them into lists that match our intuitive + # perception of ordered IP addresses. + # + # The first comparison criteria is the u128 value. + # For example, 2001:db8:1::1 will be considered + # to be less than 2001:db8:2::1, because, in a ordered list, + # we expect 2001:db8:1::1 to come before 2001:db8:2::1. + # + # The second criteria, in case two IPv6 objects + # have identical addresses, is the prefix. An higher + # prefix will be considered greater than a lower + # prefix. This is because we expect to see + # 2001:db8:1::1/64 come before 2001:db8:1::1/65 + # + # Example: + # + # ip1 = IPAddress "2001:db8:1::1/64" + # ip2 = IPAddress "2001:db8:2::1/64" + # ip3 = IPAddress "2001:db8:1::1/65" + # + # ip1 < ip2 + # #=> true + # ip1 < ip3 + # #=> false + # + # [ip1,ip2,ip3].sort.map{|i| i.to_string} + # #=> ["2001:db8:1::1/64","2001:db8:1::1/65","2001:db8:2::1/64"] + # + def <=>(oth) + return prefix <=> oth.prefix if to_u128 == oth.to_u128 + to_u128 <=> oth.to_u128 + end + + # # Returns the address portion of an IP in binary format, # as a string containing a sequence of 0 and 1 # diff --git a/test/ipaddress/ipv4_test.rb b/test/ipaddress/ipv4_test.rb index 8cb3b8f..c6d6dfb 100644 --- a/test/ipaddress/ipv4_test.rb +++ b/test/ipaddress/ipv4_test.rb @@ -304,20 +304,20 @@ class IPv4Test < Test::Unit::TestCase assert_equal "1.10.16.172.in-addr.arpa", @ip.reverse end - def test_method_comparabble + def test_method_compare ip1 = @klass.new("10.1.1.1/8") ip2 = @klass.new("10.1.1.1/16") ip3 = @klass.new("172.16.1.1/14") ip4 = @klass.new("10.1.1.1/8") - # ip1 should be major than ip2 - assert_equal true, ip1 > ip2 - assert_equal false, ip1 < ip2 - assert_equal false, ip2 > ip1 - # ip2 should be minor than ip3 + # ip2 should be greater than ip1 + assert_equal true, ip1 < ip2 + assert_equal false, ip1 > ip2 + assert_equal false, ip2 < ip1 + # ip2 should be less than ip3 assert_equal true, ip2 < ip3 assert_equal false, ip2 > ip3 - # ip1 should be minor than ip3 + # ip1 should be less than ip3 assert_equal true, ip1 < ip3 assert_equal false, ip1 > ip3 assert_equal false, ip3 < ip1 @@ -326,7 +326,13 @@ class IPv4Test < Test::Unit::TestCase # ip1 should be equal to ip4 assert_equal true, ip1 == ip4 # test sorting - arr = ["10.1.1.1/16","10.1.1.1/8","172.16.1.1/14"] + arr = ["10.1.1.1/8","10.1.1.1/16","172.16.1.1/14"] + assert_equal arr, [ip1,ip2,ip3].sort.map{|s| s.to_string} + # test same prefix + ip1 = @klass.new("10.0.0.0/24") + ip2 = @klass.new("10.0.0.0/16") + ip3 = @klass.new("10.0.0.0/8") + arr = ["10.0.0.0/8","10.0.0.0/16","10.0.0.0/24"] assert_equal arr, [ip1,ip2,ip3].sort.map{|s| s.to_string} end @@ -401,8 +407,9 @@ class IPv4Test < Test::Unit::TestCase end def test_method_supernet - assert_raise(ArgumentError) {@ip.supernet(0)} assert_raise(ArgumentError) {@ip.supernet(24)} + assert_equal "0.0.0.0/0", @ip.supernet(0).to_string + assert_equal "0.0.0.0/0", @ip.supernet(-2).to_string assert_equal "172.16.10.0/23", @ip.supernet(23).to_string assert_equal "172.16.8.0/22", @ip.supernet(22).to_string end diff --git a/test/ipaddress/ipv6_test.rb b/test/ipaddress/ipv6_test.rb index 898938f..9d9ff3e 100644 --- a/test/ipaddress/ipv6_test.rb +++ b/test/ipaddress/ipv6_test.rb @@ -224,7 +224,35 @@ class IPv6Test < Test::Unit::TestCase "2001:db8::6","2001:db8::7"] assert_equal expected, arr end - + + def test_method_compare + ip1 = @klass.new("2001:db8:1::1/64") + ip2 = @klass.new("2001:db8:2::1/64") + ip3 = @klass.new("2001:db8:1::2/64") + ip4 = @klass.new("2001:db8:1::1/65") + + # ip2 should be greater than ip1 + assert_equal true, ip2 > ip1 + assert_equal false, ip1 > ip2 + assert_equal false, ip2 < ip1 + # ip3 should be less than ip2 + assert_equal true, ip2 > ip3 + assert_equal false, ip2 < ip3 + # ip1 should be less than ip3 + assert_equal true, ip1 < ip3 + assert_equal false, ip1 > ip3 + assert_equal false, ip3 < ip1 + # ip1 should be equal to itself + assert_equal true, ip1 == ip1 + # ip4 should be greater than ip1 + assert_equal true, ip1 < ip4 + assert_equal false, ip1 > ip4 + # test sorting + arr = ["2001:db8:1::1/64","2001:db8:1::1/65", + "2001:db8:1::2/64","2001:db8:2::1/64"] + assert_equal arr, [ip1,ip2,ip3,ip4].sort.map{|s| s.to_string} + end + def test_classmethod_expand compressed = "2001:db8:0:cd30::" expanded = "2001:0db8:0000:cd30:0000:0000:0000:0000" |