ipaddress 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,392 @@
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_attributes
78
+ @valid_ipv4.each do |arg,attr|
79
+ ip = @klass.new(arg)
80
+ assert_equal attr.first, ip.address
81
+ assert_equal attr.last, ip.prefix.to_i
82
+ end
83
+ end
84
+
85
+ def test_octets
86
+ ip = @klass.new("10.1.2.3/8")
87
+ assert_equal ip.octets, [10,1,2,3]
88
+ end
89
+
90
+ def test_initialize_should_require_ip
91
+ assert_raise(ArgumentError) { @klass.new }
92
+ end
93
+
94
+ def test_method_data
95
+ assert_equal "\254\020\n\001", @ip.data
96
+ end
97
+
98
+ def test_method_to_s
99
+ @valid_ipv4.each do |arg,attr|
100
+ ip = @klass.new(arg)
101
+ assert_equal attr.join("/"), ip.to_s
102
+ end
103
+ end
104
+
105
+ def test_netmask
106
+ @netmask_values.each do |addr,mask|
107
+ ip = @klass.new(addr)
108
+ assert_equal mask, ip.netmask
109
+ end
110
+ end
111
+
112
+ def test_method_to_u32
113
+ @decimal_values.each do |addr,int|
114
+ ip = @klass.new(addr)
115
+ assert_equal int, ip.to_u32
116
+ end
117
+ end
118
+
119
+ def test_method_network?
120
+ assert_equal true, @network.network?
121
+ assert_equal false, @ip.network?
122
+ end
123
+
124
+ def test_method_broadcast
125
+ @broadcast.each do |addr,bcast|
126
+ ip = @klass.new(addr)
127
+ assert_instance_of @klass, ip.broadcast
128
+ assert_equal bcast, ip.broadcast.to_s
129
+ end
130
+ end
131
+
132
+ def test_method_network
133
+ @networks.each do |addr,net|
134
+ ip = @klass.new addr
135
+ assert_instance_of @klass, ip.network
136
+ assert_equal net, ip.network.to_s
137
+ end
138
+ end
139
+
140
+ def test_method_bits
141
+ ip = @klass.new("127.0.0.1")
142
+ assert_equal "01111111000000000000000000000001", ip.bits
143
+ end
144
+
145
+ def test_method_first
146
+ ip = @klass.new("192.168.100.0/24")
147
+ assert_instance_of @klass, ip.first
148
+ assert_equal "192.168.100.1/24", ip.first.to_s
149
+ ip = @klass.new("192.168.100.50/24")
150
+ assert_instance_of @klass, ip.first
151
+ assert_equal "192.168.100.1/24", ip.first.to_s
152
+ end
153
+
154
+ def test_method_last
155
+ ip = @klass.new("192.168.100.0/24")
156
+ assert_instance_of @klass, ip.last
157
+ assert_equal "192.168.100.254/24", ip.last.to_s
158
+ ip = @klass.new("192.168.100.50/24")
159
+ assert_instance_of @klass, ip.last
160
+ assert_equal "192.168.100.254/24", ip.last.to_s
161
+ end
162
+
163
+ def test_method_each_host
164
+ ip = @klass.new("10.0.0.1/29")
165
+ arr = []
166
+ ip.each_host {|i| arr << i.to_s}
167
+ expected = ["10.0.0.1/29","10.0.0.2/29","10.0.0.3/29",
168
+ "10.0.0.4/29","10.0.0.5/29","10.0.0.6/29"]
169
+ assert_equal expected, arr
170
+ end
171
+
172
+ def test_method_each
173
+ ip = @klass.new("10.0.0.1/29")
174
+ arr = []
175
+ ip.each {|i| arr << i.to_s}
176
+ expected = ["10.0.0.0/29","10.0.0.1/29","10.0.0.2/29",
177
+ "10.0.0.3/29","10.0.0.4/29","10.0.0.5/29",
178
+ "10.0.0.6/29","10.0.0.7/29"]
179
+ assert_equal expected, arr
180
+ end
181
+
182
+ def test_method_size
183
+ ip = @klass.new("10.0.0.1/29")
184
+ assert_equal 8, ip.size
185
+ end
186
+
187
+ def test_method_hosts
188
+ ip = @klass.new("10.0.0.1/29")
189
+ expected = ["10.0.0.1/29","10.0.0.2/29","10.0.0.3/29",
190
+ "10.0.0.4/29","10.0.0.5/29","10.0.0.6/29"]
191
+ assert_equal expected, ip.hosts.map {|i| i.to_s}
192
+ end
193
+
194
+ def test_method_network_u32
195
+ assert_equal 2886732288, @ip.network_u32
196
+ end
197
+
198
+ def test_method_broadcast_u32
199
+ assert_equal 2886732543, @ip.broadcast_u32
200
+ end
201
+
202
+ def test_method_include?
203
+ ip = @klass.new("192.168.10.100/24")
204
+ addr = @klass.new("192.168.10.102/24")
205
+ assert_equal true, ip.include?(addr)
206
+ assert_equal false, ip.include?(@klass.new("172.16.0.48"))
207
+ ip = @klass.new("10.0.0.0/8")
208
+ assert_equal true, ip.include?(@klass.new("10.0.0.0/9"))
209
+ assert_equal true, ip.include?(@klass.new("10.1.1.1/32"))
210
+ assert_equal true, ip.include?(@klass.new("10.1.1.1/9"))
211
+ assert_equal false, ip.include?(@klass.new("172.16.0.0/16"))
212
+ assert_equal false, ip.include?(@klass.new("10.0.0.0/7"))
213
+ assert_equal false, ip.include?(@klass.new("5.5.5.5/32"))
214
+ assert_equal false, ip.include?(@klass.new("11.0.0.0/8"))
215
+ ip = @klass.new("13.13.0.0/13")
216
+ assert_equal false, ip.include?(@klass.new("13.16.0.0/32"))
217
+ end
218
+
219
+ def test_method_octet
220
+ assert_equal 172, @ip[0]
221
+ assert_equal 16, @ip[1]
222
+ assert_equal 10, @ip[2]
223
+ assert_equal 1, @ip[3]
224
+ end
225
+
226
+ def test_method_a?
227
+ assert_equal true, @class_a.a?
228
+ assert_equal false, @class_b.a?
229
+ assert_equal false, @class_c.a?
230
+ end
231
+
232
+ def test_method_b?
233
+ assert_equal true, @class_b.b?
234
+ assert_equal false, @class_a.b?
235
+ assert_equal false, @class_c.b?
236
+ end
237
+
238
+ def test_method_c?
239
+ assert_equal true, @class_c.c?
240
+ assert_equal false, @class_a.c?
241
+ assert_equal false, @class_b.c?
242
+ end
243
+
244
+ def test_method_to_ipv6
245
+ assert_equal "ac10:0a01", @ip.to_ipv6
246
+ end
247
+
248
+ def test_method_reverse
249
+ assert_equal "1.10.16.172.in-addr.arpa", @ip.reverse
250
+ end
251
+
252
+ def test_method_comparabble
253
+ ip1 = @klass.new("10.1.1.1/8")
254
+ ip2 = @klass.new("10.1.1.1/16")
255
+ ip3 = @klass.new("172.16.1.1/14")
256
+ ip4 = @klass.new("10.1.1.1/8")
257
+
258
+ # ip1 should be major than ip2
259
+ assert_equal true, ip1 > ip2
260
+ assert_equal false, ip1 < ip2
261
+ assert_equal false, ip2 > ip1
262
+ # ip2 should be minor than ip3
263
+ assert_equal true, ip2 < ip3
264
+ assert_equal false, ip2 > ip3
265
+ # ip1 should be minor than ip3
266
+ assert_equal true, ip1 < ip3
267
+ assert_equal false, ip1 > ip3
268
+ assert_equal false, ip3 < ip1
269
+ # ip1 should be equal to itself
270
+ assert_equal true, ip1 == ip1
271
+ # ip1 should be equal to ip4
272
+ assert_equal true, ip1 == ip4
273
+ # test sorting
274
+ arr = ["10.1.1.1/16","10.1.1.1/8","172.16.1.1/14"]
275
+ assert_equal arr, [ip1,ip2,ip3].sort.map{|s| s.to_s}
276
+ end
277
+
278
+ def test_method_minus
279
+ ip1 = @klass.new("10.1.1.1/8")
280
+ ip2 = @klass.new("10.1.1.10/8")
281
+ assert_equal 9, ip2 - ip1
282
+ assert_equal 9, ip1 - ip2
283
+ end
284
+
285
+ def test_method_plus
286
+ ip1 = @klass.new("172.16.10.1/24")
287
+ ip2 = @klass.new("172.16.11.2/24")
288
+ assert_equal "172.16.10.0/23", (ip1 + ip2).to_s
289
+ ip2 = @klass.new("172.16.12.2/24")
290
+ assert_equal [ip1.network.to_s,ip2.network.to_s], (ip1 + ip2).map{|i| i.to_s}
291
+ end
292
+
293
+
294
+ def test_method_netmask_equal
295
+ ip = @klass.new("10.1.1.1/16")
296
+ assert_equal 16, ip.prefix.to_i
297
+ ip.netmask = "255.255.255.0"
298
+ assert_equal 24, ip.prefix.to_i
299
+ end
300
+
301
+ def test_method_subnet
302
+ assert_raise(ArgumentError) {@ip.subnet(0)}
303
+ assert_raise(ArgumentError) {@ip.subnet(257)}
304
+
305
+ arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
306
+ "172.16.10.96/27", "172.16.10.128/27", "172.16.10.160/27",
307
+ "172.16.10.192/27", "172.16.10.224/27"]
308
+ assert_equal arr, @network.subnet(8).map {|s| s.to_s}
309
+ arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
310
+ "172.16.10.96/27", "172.16.10.128/27", "172.16.10.160/27",
311
+ "172.16.10.192/26"]
312
+ assert_equal arr, @network.subnet(7).map {|s| s.to_s}
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/26", "172.16.10.192/26"]
315
+ assert_equal arr, @network.subnet(6).map {|s| s.to_s}
316
+ arr = ["172.16.10.0/27", "172.16.10.32/27", "172.16.10.64/27",
317
+ "172.16.10.96/27", "172.16.10.128/25"]
318
+ assert_equal arr, @network.subnet(5).map {|s| s.to_s}
319
+ arr = ["172.16.10.0/26", "172.16.10.64/26", "172.16.10.128/26",
320
+ "172.16.10.192/26"]
321
+ assert_equal arr, @network.subnet(4).map {|s| s.to_s}
322
+ arr = ["172.16.10.0/26", "172.16.10.64/26", "172.16.10.128/25"]
323
+ assert_equal arr, @network.subnet(3).map {|s| s.to_s}
324
+ arr = ["172.16.10.0/25", "172.16.10.128/25"]
325
+ assert_equal arr, @network.subnet(2).map {|s| s.to_s}
326
+ arr = ["172.16.10.0/24"]
327
+ assert_equal arr, @network.subnet(1).map {|s| s.to_s}
328
+ end
329
+
330
+ def test_method_supernet
331
+ assert_raise(ArgumentError) {@ip.supernet(0)}
332
+ assert_raise(ArgumentError) {@ip.supernet(24)}
333
+ assert_equal "172.16.10.0/23", @ip.supernet(23).to_s
334
+ assert_equal "172.16.8.0/22", @ip.supernet(22).to_s
335
+ end
336
+
337
+ def test_classmethod_parse_u32
338
+ @decimal_values.each do |addr,int|
339
+ ip = @klass.parse_u32(int)
340
+ ip.prefix = addr.split("/").last.to_i
341
+ assert_equal ip.to_s, addr
342
+ end
343
+ end
344
+
345
+ def test_classhmethod_extract
346
+ str = "foobar172.16.10.1barbaz"
347
+ assert_equal "172.16.10.1/16", @klass.extract(str).to_s
348
+ end
349
+
350
+ def test_classmethod_summarize
351
+
352
+ # Should return self if only one network given
353
+ assert_equal @ip, @klass.summarize(@ip)
354
+
355
+ # Summarize homogeneous networks
356
+ ip1 = @klass.new("172.16.10.1/24")
357
+ ip2 = @klass.new("172.16.11.2/24")
358
+ assert_equal "172.16.10.0/23", @klass.summarize(ip1,ip2).to_s
359
+
360
+ ip1 = @klass.new("10.0.0.1/24")
361
+ ip2 = @klass.new("10.0.1.1/24")
362
+ ip3 = @klass.new("10.0.2.1/24")
363
+ ip4 = @klass.new("10.0.3.1/24")
364
+ assert_equal "10.0.0.0/22", @klass.summarize(ip1,ip2,ip3,ip4).to_s
365
+
366
+ # Summarize non homogeneous networks
367
+ ip1 = @klass.new("10.0.1.1/24")
368
+ ip2 = @klass.new("10.0.2.1/24")
369
+ ip3 = @klass.new("10.0.3.1/24")
370
+ ip4 = @klass.new("10.0.4.1/24")
371
+ result = ["10.0.1.0/24","10.0.2.0/23","10.0.4.0/24"]
372
+ assert_equal result, @klass.summarize(ip1,ip2,ip3,ip4).map{|i| i.to_s}
373
+
374
+ ip1 = @klass.new("10.0.1.1/24")
375
+ ip2 = @klass.new("10.10.2.1/24")
376
+ ip3 = @klass.new("172.16.0.1/24")
377
+ ip4 = @klass.new("172.16.1.1/24")
378
+ result = ["10.0.1.0/24","10.10.2.0/24","172.16.0.0/23"]
379
+ assert_equal result, @klass.summarize(ip1,ip2,ip3,ip4).map{|i| i.to_s}
380
+
381
+ end
382
+
383
+ def test_classmethod_parse_data
384
+ ip = @klass.parse_data "\254\020\n\001"
385
+ assert_instance_of @klass, ip
386
+ assert_equal "172.16.10.1", ip.address
387
+ assert_equal "172.16.10.1/16", ip.to_s
388
+ end
389
+
390
+ end # class IPv4Test
391
+
392
+