summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rdoc3
-rw-r--r--lib/ipaddress/ipv4.rb47
-rw-r--r--lib/ipaddress/ipv6.rb37
-rw-r--r--test/ipaddress/ipv4_test.rb25
-rw-r--r--test/ipaddress/ipv6_test.rb30
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"