relevance_ipaddress 0.5.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/.document +5 -0
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +875 -0
- data/Rakefile +89 -0
- data/VERSION +1 -0
- data/lib/ipaddress.rb +52 -0
- data/lib/ipaddress/extensions/extensions.rb +16 -0
- data/lib/ipaddress/ipbase.rb +83 -0
- data/lib/ipaddress/ipv4.rb +849 -0
- data/lib/ipaddress/ipv6.rb +683 -0
- data/lib/ipaddress/prefix.rb +200 -0
- data/test/ipaddress/extensions/extensions_test.rb +18 -0
- data/test/ipaddress/ipbase_test.rb +28 -0
- data/test/ipaddress/ipv4_test.rb +400 -0
- data/test/ipaddress/ipv6_test.rb +290 -0
- data/test/ipaddress/prefix_test.rb +139 -0
- data/test/ipaddress_test.rb +38 -0
- data/test/test_helper.rb +33 -0
- metadata +92 -0
@@ -0,0 +1,200 @@
|
|
1
|
+
module IPAddress
|
2
|
+
|
3
|
+
#
|
4
|
+
# =NAME
|
5
|
+
#
|
6
|
+
# IPAddress::Prefix
|
7
|
+
#
|
8
|
+
# =SYNOPSIS
|
9
|
+
#
|
10
|
+
# Parent class for Prefix32 and Prefix128
|
11
|
+
#
|
12
|
+
# =DESCRIPTION
|
13
|
+
#
|
14
|
+
# IPAddresS::Prefix is the parent class for IPAddress::Prefix32
|
15
|
+
# and IPAddress::Prefix128, defining some modules in common for
|
16
|
+
# both the subclasses.
|
17
|
+
#
|
18
|
+
# IPAddress::Prefix shouldn't be accesses directly, unless
|
19
|
+
# for particular needs.
|
20
|
+
#
|
21
|
+
class Prefix
|
22
|
+
|
23
|
+
include Comparable
|
24
|
+
|
25
|
+
attr_reader :prefix
|
26
|
+
|
27
|
+
def initialize(num)
|
28
|
+
@prefix = num.to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"#@prefix"
|
33
|
+
end
|
34
|
+
alias_method :inspect, :to_s
|
35
|
+
|
36
|
+
def to_i
|
37
|
+
@prefix
|
38
|
+
end
|
39
|
+
|
40
|
+
def <=>(oth)
|
41
|
+
@prefix <=> oth.to_i
|
42
|
+
end
|
43
|
+
|
44
|
+
end # class Prefix
|
45
|
+
|
46
|
+
|
47
|
+
class Prefix32 < Prefix
|
48
|
+
|
49
|
+
#
|
50
|
+
# Creates a new prefix object for 32 bits IPv4 addresses
|
51
|
+
#
|
52
|
+
# prefix = IPAddress::Prefix32.new 24
|
53
|
+
# #=> 24
|
54
|
+
#
|
55
|
+
def initialize(num)
|
56
|
+
unless (1..32).include? num
|
57
|
+
raise ArgumentError, "Prefix must be in range 1..128, got: #{num}"
|
58
|
+
end
|
59
|
+
super(num)
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Transforms the prefix into a string of bits
|
64
|
+
# representing the netmask
|
65
|
+
#
|
66
|
+
# prefix = IPAddress::Prefix32.new 24
|
67
|
+
#
|
68
|
+
# prefix.bits
|
69
|
+
# #=> "11111111111111111111111100000000"
|
70
|
+
#
|
71
|
+
def bits
|
72
|
+
"1" * @prefix + "0" * (32 - @prefix)
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Gives the prefix in IPv4 dotted decimal format,
|
77
|
+
# i.e. the canonical netmask we're all used to
|
78
|
+
#
|
79
|
+
# prefix = IPAddress::Prefix32.new 24
|
80
|
+
#
|
81
|
+
# prefix.to_ip
|
82
|
+
# #=> "255.255.255.0"
|
83
|
+
#
|
84
|
+
def to_ip
|
85
|
+
[bits].pack("B*").unpack("CCCC").join(".")
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# An array of octets of the IPv4 dotted decimal
|
90
|
+
# format
|
91
|
+
#
|
92
|
+
# prefix = IPAddress::Prefix32.new 24
|
93
|
+
#
|
94
|
+
# prefix.octets
|
95
|
+
# #=> [255, 255, 255, 0]
|
96
|
+
#
|
97
|
+
def octets
|
98
|
+
to_ip.split(".").map{|i| i.to_i}
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Unsigned 32 bits decimal number representing
|
103
|
+
# the prefix
|
104
|
+
#
|
105
|
+
# prefix = IPAddress::Prefix32.new 24
|
106
|
+
#
|
107
|
+
# prefix.to_u32
|
108
|
+
# #=> 4294967040
|
109
|
+
#
|
110
|
+
def to_u32
|
111
|
+
[bits].pack("B*").unpack("N").first
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
# Shortcut for the octecs in the dotted decimal
|
116
|
+
# representation
|
117
|
+
#
|
118
|
+
# prefix = IPAddress::Prefix32.new 24
|
119
|
+
#
|
120
|
+
# prefix[2]
|
121
|
+
# #=> 255
|
122
|
+
#
|
123
|
+
def [](index)
|
124
|
+
octets[index]
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# The hostmask is the contrary of the subnet mask,
|
129
|
+
# as it shows the bits that can change within the
|
130
|
+
# hosts
|
131
|
+
#
|
132
|
+
# prefix = IPAddress::Prefix32.new 24
|
133
|
+
#
|
134
|
+
# prefix.hostmask
|
135
|
+
# #=> "0.0.0.255"
|
136
|
+
#
|
137
|
+
def hostmask
|
138
|
+
[~to_u32].pack("N").unpack("CCCC").join(".")
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# Creates a new prefix by parsing a netmask in
|
143
|
+
# dotted decimal form
|
144
|
+
#
|
145
|
+
# prefix = IPAddress::Prefix32::parse_netmask "255.255.255.0"
|
146
|
+
# #=> 24
|
147
|
+
#
|
148
|
+
def self.parse_netmask(netmask)
|
149
|
+
octets = netmask.split(".").map{|i| i.to_i}
|
150
|
+
num = octets.pack("C"*octets.size).unpack("B*").first.count "1"
|
151
|
+
return IPAddress::Prefix.new(num)
|
152
|
+
end
|
153
|
+
|
154
|
+
end # class Prefix32 < Prefix
|
155
|
+
|
156
|
+
class Prefix128 < Prefix
|
157
|
+
|
158
|
+
#
|
159
|
+
# Creates a new prefix object for 128 bits IPv6 addresses
|
160
|
+
#
|
161
|
+
# prefix = IPAddress::Prefix128.new 64
|
162
|
+
# #=> 64
|
163
|
+
#
|
164
|
+
def initialize(num=128)
|
165
|
+
unless (1..128).include? num.to_i
|
166
|
+
raise ArgumentError, "Prefix must be in range 1..128, got: #{num}"
|
167
|
+
end
|
168
|
+
super(num.to_i)
|
169
|
+
end
|
170
|
+
|
171
|
+
#
|
172
|
+
# Transforms the prefix into a string of bits
|
173
|
+
# representing the netmask
|
174
|
+
#
|
175
|
+
# prefix = IPAddress::Prefix128.new 64
|
176
|
+
#
|
177
|
+
# prefix.bits
|
178
|
+
# #=> "1111111111111111111111111111111111111111111111111111111111111111"
|
179
|
+
# "0000000000000000000000000000000000000000000000000000000000000000"
|
180
|
+
#
|
181
|
+
def bits
|
182
|
+
"1" * @prefix + "0" * (128 - @prefix)
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# Unsigned 128 bits decimal number representing
|
187
|
+
# the prefix
|
188
|
+
#
|
189
|
+
# prefix = IPAddress::Prefix128.new 64
|
190
|
+
#
|
191
|
+
# prefix.to_u128
|
192
|
+
# #=> 340282366920938463444927863358058659840
|
193
|
+
#
|
194
|
+
def to_u128
|
195
|
+
eval "0b#{bits}.to_i"
|
196
|
+
end
|
197
|
+
|
198
|
+
end # class Prefix123 < Prefix
|
199
|
+
|
200
|
+
end # module IPAddress
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ExtensionsTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_method_power_of_2?
|
6
|
+
assert_equal true, 16.power_of_2?
|
7
|
+
assert_equal false, 20.power_of_2?
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_method_closest_power_of_2
|
11
|
+
assert_equal 8, 6.closest_power_of_2
|
12
|
+
assert_equal 16, 13.closest_power_of_2
|
13
|
+
assert_equal 32, 24.closest_power_of_2
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class IpaddressTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
must "be valid ip" do
|
6
|
+
assert_equal true, IPAddress::valid?("10.0.0.1")
|
7
|
+
assert_equal true, IPAddress::valid?("10.0.0.0")
|
8
|
+
assert_equal true, IPAddress::valid?("2002::1")
|
9
|
+
assert_equal true, IPAddress::valid?("dead:beef:cafe:babe::f0ad")
|
10
|
+
end
|
11
|
+
|
12
|
+
must "be valid netmask" do
|
13
|
+
assert_equal true, IPAddress::valid_ipv4_netmask?("255.255.255.0")
|
14
|
+
end
|
15
|
+
|
16
|
+
must "be invalid netmask" do
|
17
|
+
assert_equal false, IPAddress::valid_ipv4_netmask?("10.0.0.1")
|
18
|
+
end
|
19
|
+
|
20
|
+
must "be invalid" do
|
21
|
+
assert_equal false, IPAddress::valid?("10.0.0.256")
|
22
|
+
assert_equal false, IPAddress::valid?("10.0.0.0.0")
|
23
|
+
assert_equal false, IPAddress::valid?("10.0.0")
|
24
|
+
assert_equal false, IPAddress::valid?("10.0")
|
25
|
+
assert_equal false, IPAddress::valid?("2002:::1")
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,400 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class IPv4Test < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@klass = IPAddress::IPv4
|
7
|
+
|
8
|
+
@valid_ipv4 = {
|
9
|
+
"10.0.0.0" => ["10.0.0.0", 8],
|
10
|
+
"10.0.0.1" => ["10.0.0.1", 8],
|
11
|
+
"10.0.0.1/24" => ["10.0.0.1", 24],
|
12
|
+
"10.0.0.1/255.255.255.0" => ["10.0.0.1", 24]}
|
13
|
+
|
14
|
+
@invalid_ipv4 = ["10.0.0.256",
|
15
|
+
"10.0.0.0.0",
|
16
|
+
"10.0.0",
|
17
|
+
"10.0"]
|
18
|
+
|
19
|
+
@valid_ipv4_range = ["10.0.0.1-254",
|
20
|
+
"10.0.1-254.0",
|
21
|
+
"10.1-254.0.0"]
|
22
|
+
|
23
|
+
@netmask_values = {
|
24
|
+
"10.0.0.0/8" => "255.0.0.0",
|
25
|
+
"172.16.0.0/16" => "255.255.0.0",
|
26
|
+
"192.168.0.0/24" => "255.255.255.0",
|
27
|
+
"192.168.100.4/30" => "255.255.255.252"}
|
28
|
+
|
29
|
+
@decimal_values ={
|
30
|
+
"10.0.0.0/8" => 167772160,
|
31
|
+
"172.16.0.0/16" => 2886729728,
|
32
|
+
"192.168.0.0/24" => 3232235520,
|
33
|
+
"192.168.100.4/30" => 3232261124}
|
34
|
+
|
35
|
+
@ip = @klass.new("172.16.10.1/24")
|
36
|
+
@network = @klass.new("172.16.10.0/24")
|
37
|
+
|
38
|
+
@broadcast = {
|
39
|
+
"10.0.0.0/8" => "10.255.255.255/8",
|
40
|
+
"172.16.0.0/16" => "172.16.255.255/16",
|
41
|
+
"192.168.0.0/24" => "192.168.0.255/24",
|
42
|
+
"192.168.100.4/30" => "192.168.100.7/30"}
|
43
|
+
|
44
|
+
@networks = {
|
45
|
+
"10.5.4.3/8" => "10.0.0.0/8",
|
46
|
+
"172.16.5.4/16" => "172.16.0.0/16",
|
47
|
+
"192.168.4.3/24" => "192.168.4.0/24",
|
48
|
+
"192.168.100.5/30" => "192.168.100.4/30"}
|
49
|
+
|
50
|
+
@class_a = @klass.new("10.0.0.1/8")
|
51
|
+
@class_b = @klass.new("172.16.0.1/16")
|
52
|
+
@class_c = @klass.new("192.168.0.1/24")
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_initialize
|
57
|
+
@valid_ipv4.keys.each do |i|
|
58
|
+
ip = @klass.new(i)
|
59
|
+
assert_instance_of @klass, ip
|
60
|
+
end
|
61
|
+
assert_instance_of IPAddress::Prefix32, @ip.prefix
|
62
|
+
assert_raise (ArgumentError) do
|
63
|
+
@klass.new
|
64
|
+
end
|
65
|
+
assert_nothing_raised do
|
66
|
+
@klass.new "10.0.0.0/8"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_initialize_format_error
|
71
|
+
@invalid_ipv4.each do |i|
|
72
|
+
assert_raise(ArgumentError) {@klass.new(i)}
|
73
|
+
end
|
74
|
+
assert_raise (ArgumentError) {@klass.new("10.0.0.0/asd")}
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_initialize_without_prefix
|
78
|
+
assert_nothing_raised do
|
79
|
+
@klass.new("10.10.0.0")
|
80
|
+
end
|
81
|
+
ip = @klass.new("10.10.0.0")
|
82
|
+
assert_instance_of IPAddress::Prefix32, ip.prefix
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_attributes
|
86
|
+
@valid_ipv4.each do |arg,attr|
|
87
|
+
ip = @klass.new(arg)
|
88
|
+
assert_equal attr.first, ip.address
|
89
|
+
assert_equal attr.last, ip.prefix.to_i
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_octets
|
94
|
+
ip = @klass.new("10.1.2.3/8")
|
95
|
+
assert_equal ip.octets, [10,1,2,3]
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_initialize_should_require_ip
|
99
|
+
assert_raise(ArgumentError) { @klass.new }
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_method_data
|
103
|
+
assert_equal "\254\020\n\001", @ip.data
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_method_to_s
|
107
|
+
@valid_ipv4.each do |arg,attr|
|
108
|
+
ip = @klass.new(arg)
|
109
|
+
assert_equal attr.join("/"), ip.to_s
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_netmask
|
114
|
+
@netmask_values.each do |addr,mask|
|
115
|
+
ip = @klass.new(addr)
|
116
|
+
assert_equal mask, ip.netmask
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_method_to_u32
|
121
|
+
@decimal_values.each do |addr,int|
|
122
|
+
ip = @klass.new(addr)
|
123
|
+
assert_equal int, ip.to_u32
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_method_network?
|
128
|
+
assert_equal true, @network.network?
|
129
|
+
assert_equal false, @ip.network?
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_method_broadcast
|
133
|
+
@broadcast.each do |addr,bcast|
|
134
|
+
ip = @klass.new(addr)
|
135
|
+
assert_instance_of @klass, ip.broadcast
|
136
|
+
assert_equal bcast, ip.broadcast.to_s
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_method_network
|
141
|
+
@networks.each do |addr,net|
|
142
|
+
ip = @klass.new addr
|
143
|
+
assert_instance_of @klass, ip.network
|
144
|
+
assert_equal net, ip.network.to_s
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_method_bits
|
149
|
+
ip = @klass.new("127.0.0.1")
|
150
|
+
assert_equal "01111111000000000000000000000001", ip.bits
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_method_first
|
154
|
+
ip = @klass.new("192.168.100.0/24")
|
155
|
+
assert_instance_of @klass, ip.first
|
156
|
+
assert_equal "192.168.100.1/24", ip.first.to_s
|
157
|
+
ip = @klass.new("192.168.100.50/24")
|
158
|
+
assert_instance_of @klass, ip.first
|
159
|
+
assert_equal "192.168.100.1/24", ip.first.to_s
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_method_last
|
163
|
+
ip = @klass.new("192.168.100.0/24")
|
164
|
+
assert_instance_of @klass, ip.last
|
165
|
+
assert_equal "192.168.100.254/24", ip.last.to_s
|
166
|
+
ip = @klass.new("192.168.100.50/24")
|
167
|
+
assert_instance_of @klass, ip.last
|
168
|
+
assert_equal "192.168.100.254/24", ip.last.to_s
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_method_each_host
|
172
|
+
ip = @klass.new("10.0.0.1/29")
|
173
|
+
arr = []
|
174
|
+
ip.each_host {|i| arr << i.to_s}
|
175
|
+
expected = ["10.0.0.1/29","10.0.0.2/29","10.0.0.3/29",
|
176
|
+
"10.0.0.4/29","10.0.0.5/29","10.0.0.6/29"]
|
177
|
+
assert_equal expected, arr
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_method_each
|
181
|
+
ip = @klass.new("10.0.0.1/29")
|
182
|
+
arr = []
|
183
|
+
ip.each {|i| arr << i.to_s}
|
184
|
+
expected = ["10.0.0.0/29","10.0.0.1/29","10.0.0.2/29",
|
185
|
+
"10.0.0.3/29","10.0.0.4/29","10.0.0.5/29",
|
186
|
+
"10.0.0.6/29","10.0.0.7/29"]
|
187
|
+
assert_equal expected, arr
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_method_size
|
191
|
+
ip = @klass.new("10.0.0.1/29")
|
192
|
+
assert_equal 8, ip.size
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_method_hosts
|
196
|
+
ip = @klass.new("10.0.0.1/29")
|
197
|
+
expected = ["10.0.0.1/29","10.0.0.2/29","10.0.0.3/29",
|
198
|
+
"10.0.0.4/29","10.0.0.5/29","10.0.0.6/29"]
|
199
|
+
assert_equal expected, ip.hosts.map {|i| i.to_s}
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_method_network_u32
|
203
|
+
assert_equal 2886732288, @ip.network_u32
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_method_broadcast_u32
|
207
|
+
assert_equal 2886732543, @ip.broadcast_u32
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_method_include?
|
211
|
+
ip = @klass.new("192.168.10.100/24")
|
212
|
+
addr = @klass.new("192.168.10.102/24")
|
213
|
+
assert_equal true, ip.include?(addr)
|
214
|
+
assert_equal false, ip.include?(@klass.new("172.16.0.48"))
|
215
|
+
ip = @klass.new("10.0.0.0/8")
|
216
|
+
assert_equal true, ip.include?(@klass.new("10.0.0.0/9"))
|
217
|
+
assert_equal true, ip.include?(@klass.new("10.1.1.1/32"))
|
218
|
+
assert_equal true, ip.include?(@klass.new("10.1.1.1/9"))
|
219
|
+
assert_equal false, ip.include?(@klass.new("172.16.0.0/16"))
|
220
|
+
assert_equal false, ip.include?(@klass.new("10.0.0.0/7"))
|
221
|
+
assert_equal false, ip.include?(@klass.new("5.5.5.5/32"))
|
222
|
+
assert_equal false, ip.include?(@klass.new("11.0.0.0/8"))
|
223
|
+
ip = @klass.new("13.13.0.0/13")
|
224
|
+
assert_equal false, ip.include?(@klass.new("13.16.0.0/32"))
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_method_octet
|
228
|
+
assert_equal 172, @ip[0]
|
229
|
+
assert_equal 16, @ip[1]
|
230
|
+
assert_equal 10, @ip[2]
|
231
|
+
assert_equal 1, @ip[3]
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_method_a?
|
235
|
+
assert_equal true, @class_a.a?
|
236
|
+
assert_equal false, @class_b.a?
|
237
|
+
assert_equal false, @class_c.a?
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_method_b?
|
241
|
+
assert_equal true, @class_b.b?
|
242
|
+
assert_equal false, @class_a.b?
|
243
|
+
assert_equal false, @class_c.b?
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_method_c?
|
247
|
+
assert_equal true, @class_c.c?
|
248
|
+
assert_equal false, @class_a.c?
|
249
|
+
assert_equal false, @class_b.c?
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_method_to_ipv6
|
253
|
+
assert_equal "ac10:0a01", @ip.to_ipv6
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_method_reverse
|
257
|
+
assert_equal "1.10.16.172.in-addr.arpa", @ip.reverse
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_method_comparabble
|
261
|
+
ip1 = @klass.new("10.1.1.1/8")
|
262
|
+
ip2 = @klass.new("10.1.1.1/16")
|
263
|
+
ip3 = @klass.new("172.16.1.1/14")
|
264
|
+
ip4 = @klass.new("10.1.1.1/8")
|
265
|
+
|
266
|
+
# ip1 should be major than ip2
|
267
|
+
assert_equal true, ip1 > ip2
|
268
|
+
assert_equal false, ip1 < ip2
|
269
|
+
assert_equal false, ip2 > ip1
|
270
|
+
# ip2 should be minor than ip3
|
271
|
+
assert_equal true, ip2 < ip3
|
272
|
+
assert_equal false, ip2 > ip3
|
273
|
+
# ip1 should be minor than ip3
|
274
|
+
assert_equal true, ip1 < ip3
|
275
|
+
assert_equal false, ip1 > ip3
|
276
|
+
assert_equal false, ip3 < ip1
|
277
|
+
# ip1 should be equal to itself
|
278
|
+
assert_equal true, ip1 == ip1
|
279
|
+
# ip1 should be equal to ip4
|
280
|
+
assert_equal true, ip1 == ip4
|
281
|
+
# test sorting
|
282
|
+
arr = ["10.1.1.1/16","10.1.1.1/8","172.16.1.1/14"]
|
283
|
+
assert_equal arr, [ip1,ip2,ip3].sort.map{|s| s.to_s}
|
284
|
+
end
|
285
|
+
|
286
|
+
def test_method_minus
|
287
|
+
ip1 = @klass.new("10.1.1.1/8")
|
288
|
+
ip2 = @klass.new("10.1.1.10/8")
|
289
|
+
assert_equal 9, ip2 - ip1
|
290
|
+
assert_equal 9, ip1 - ip2
|
291
|
+
end
|
292
|
+
|
293
|
+
def test_method_plus
|
294
|
+
ip1 = @klass.new("172.16.10.1/24")
|
295
|
+
ip2 = @klass.new("172.16.11.2/24")
|
296
|
+
assert_equal "172.16.10.0/23", (ip1 + ip2).to_s
|
297
|
+
ip2 = @klass.new("172.16.12.2/24")
|
298
|
+
assert_equal [ip1.network.to_s,ip2.network.to_s], (ip1 + ip2).map{|i| i.to_s}
|
299
|
+
end
|
300
|
+
|
301
|
+
|
302
|
+
def test_method_netmask_equal
|
303
|
+
ip = @klass.new("10.1.1.1/16")
|
304
|
+
assert_equal 16, ip.prefix.to_i
|
305
|
+
ip.netmask = "255.255.255.0"
|
306
|
+
assert_equal 24, ip.prefix.to_i
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_method_subnet
|
310
|
+
assert_raise(ArgumentError) {@ip.subnet(0)}
|
311
|
+
assert_raise(ArgumentError) {@ip.subnet(257)}
|
312
|
+
|
313
|
+
arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
|
314
|
+
"172.16.10.96/27", "172.16.10.128/27", "172.16.10.160/27",
|
315
|
+
"172.16.10.192/27", "172.16.10.224/27"]
|
316
|
+
assert_equal arr, @network.subnet(8).map {|s| s.to_s}
|
317
|
+
arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
|
318
|
+
"172.16.10.96/27", "172.16.10.128/27", "172.16.10.160/27",
|
319
|
+
"172.16.10.192/26"]
|
320
|
+
assert_equal arr, @network.subnet(7).map {|s| s.to_s}
|
321
|
+
arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
|
322
|
+
"172.16.10.96/27", "172.16.10.128/26", "172.16.10.192/26"]
|
323
|
+
assert_equal arr, @network.subnet(6).map {|s| s.to_s}
|
324
|
+
arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
|
325
|
+
"172.16.10.96/27", "172.16.10.128/25"]
|
326
|
+
assert_equal arr, @network.subnet(5).map {|s| s.to_s}
|
327
|
+
arr = ["172.16.10.0/26", "172.16.10.64/26", "172.16.10.128/26",
|
328
|
+
"172.16.10.192/26"]
|
329
|
+
assert_equal arr, @network.subnet(4).map {|s| s.to_s}
|
330
|
+
arr = ["172.16.10.0/26", "172.16.10.64/26", "172.16.10.128/25"]
|
331
|
+
assert_equal arr, @network.subnet(3).map {|s| s.to_s}
|
332
|
+
arr = ["172.16.10.0/25", "172.16.10.128/25"]
|
333
|
+
assert_equal arr, @network.subnet(2).map {|s| s.to_s}
|
334
|
+
arr = ["172.16.10.0/24"]
|
335
|
+
assert_equal arr, @network.subnet(1).map {|s| s.to_s}
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_method_supernet
|
339
|
+
assert_raise(ArgumentError) {@ip.supernet(0)}
|
340
|
+
assert_raise(ArgumentError) {@ip.supernet(24)}
|
341
|
+
assert_equal "172.16.10.0/23", @ip.supernet(23).to_s
|
342
|
+
assert_equal "172.16.8.0/22", @ip.supernet(22).to_s
|
343
|
+
end
|
344
|
+
|
345
|
+
def test_classmethod_parse_u32
|
346
|
+
@decimal_values.each do |addr,int|
|
347
|
+
ip = @klass.parse_u32(int)
|
348
|
+
ip.prefix = addr.split("/").last.to_i
|
349
|
+
assert_equal ip.to_s, addr
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def test_classhmethod_extract
|
354
|
+
str = "foobar172.16.10.1barbaz"
|
355
|
+
assert_equal "172.16.10.1/16", @klass.extract(str).to_s
|
356
|
+
end
|
357
|
+
|
358
|
+
def test_classmethod_summarize
|
359
|
+
|
360
|
+
# Should return self if only one network given
|
361
|
+
assert_equal @ip, @klass.summarize(@ip)
|
362
|
+
|
363
|
+
# Summarize homogeneous networks
|
364
|
+
ip1 = @klass.new("172.16.10.1/24")
|
365
|
+
ip2 = @klass.new("172.16.11.2/24")
|
366
|
+
assert_equal "172.16.10.0/23", @klass.summarize(ip1,ip2).to_s
|
367
|
+
|
368
|
+
ip1 = @klass.new("10.0.0.1/24")
|
369
|
+
ip2 = @klass.new("10.0.1.1/24")
|
370
|
+
ip3 = @klass.new("10.0.2.1/24")
|
371
|
+
ip4 = @klass.new("10.0.3.1/24")
|
372
|
+
assert_equal "10.0.0.0/22", @klass.summarize(ip1,ip2,ip3,ip4).to_s
|
373
|
+
|
374
|
+
# Summarize non homogeneous networks
|
375
|
+
ip1 = @klass.new("10.0.1.1/24")
|
376
|
+
ip2 = @klass.new("10.0.2.1/24")
|
377
|
+
ip3 = @klass.new("10.0.3.1/24")
|
378
|
+
ip4 = @klass.new("10.0.4.1/24")
|
379
|
+
result = ["10.0.1.0/24","10.0.2.0/23","10.0.4.0/24"]
|
380
|
+
assert_equal result, @klass.summarize(ip1,ip2,ip3,ip4).map{|i| i.to_s}
|
381
|
+
|
382
|
+
ip1 = @klass.new("10.0.1.1/24")
|
383
|
+
ip2 = @klass.new("10.10.2.1/24")
|
384
|
+
ip3 = @klass.new("172.16.0.1/24")
|
385
|
+
ip4 = @klass.new("172.16.1.1/24")
|
386
|
+
result = ["10.0.1.0/24","10.10.2.0/24","172.16.0.0/23"]
|
387
|
+
assert_equal result, @klass.summarize(ip1,ip2,ip3,ip4).map{|i| i.to_s}
|
388
|
+
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_classmethod_parse_data
|
392
|
+
ip = @klass.parse_data "\254\020\n\001"
|
393
|
+
assert_instance_of @klass, ip
|
394
|
+
assert_equal "172.16.10.1", ip.address
|
395
|
+
assert_equal "172.16.10.1/16", ip.to_s
|
396
|
+
end
|
397
|
+
|
398
|
+
end # class IPv4Test
|
399
|
+
|
400
|
+
|