ruby-ip 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+ require 'ip/base'
3
+ require 'ip/cpal'
4
+
5
+ class IPTestRPAL < Test::Unit::TestCase
6
+ context "v4" do
7
+ setup do
8
+ @addr = IP.new("1.2.3.4/24@foo")
9
+ end
10
+
11
+ should "build from cpal" do
12
+ res = IP.from_cpal(["bar", "v4", 0x01020304, 26])
13
+ assert_equal IP::V4, res.class
14
+ assert_equal "1.2.3.4/26@bar", res.to_s
15
+ end
16
+
17
+ should "have to_cpal" do
18
+ assert_equal ["foo","v4", 0x01020304, 24], @addr.to_cpal
19
+ end
20
+
21
+ should "have to_cphl" do
22
+ assert_equal ["foo","v4", "01020304", 24], @addr.to_cphl
23
+ end
24
+ end
25
+
26
+ context "v6" do
27
+ should "build from cpal" do
28
+ res = IP.from_cpal(["bar", "v6", 0xdeadbeef000000000000000000000123, 48])
29
+ assert_equal IP::V6, res.class
30
+ assert_equal "dead:beef::123/48@bar", res.to_s
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,521 @@
1
+ require 'test_helper'
2
+ require 'ip/base'
3
+
4
+ class IPTest < Test::Unit::TestCase
5
+ context "v4" do
6
+ should "build from string" do
7
+ res = IP.new("1.2.3.4/26")
8
+ assert_equal IP::V4, res.class
9
+ assert_equal "1.2.3.4/26", res.to_s
10
+ assert_equal "1.2.3.4/26", res.to_addrlen
11
+ assert_equal 0x01020304, res.to_i
12
+ assert_equal 26, res.pfxlen
13
+ assert_nil res.ctx
14
+ end
15
+
16
+ should "build from string with ctx" do
17
+ res = IP.new("1.2.3.4/26@nat")
18
+ assert_equal IP::V4, res.class
19
+ assert_equal "1.2.3.4/26@nat", res.to_s
20
+ assert_equal "1.2.3.4/26", res.to_addrlen
21
+ assert_equal 0x01020304, res.to_i
22
+ assert_equal 26, res.pfxlen
23
+ assert_equal "nat", res.ctx
24
+ end
25
+
26
+ should "build from array" do
27
+ res = IP.new(["v4", 0x01020304])
28
+ assert_equal IP::V4, res.class
29
+ assert_equal "1.2.3.4", res.to_s
30
+ assert_equal 32, res.pfxlen
31
+ end
32
+
33
+ should "build from array with pfxlen" do
34
+ res = IP.new(["v4", 0x01020304, 26])
35
+ assert_equal IP::V4, res.class
36
+ assert_equal "1.2.3.4/26", res.to_s
37
+ end
38
+
39
+ should "build from array with pfxlen and ctx" do
40
+ res = IP.new(["v4", 0x01020304, 26, "bar"])
41
+ assert_equal IP::V4, res.class
42
+ assert_equal "1.2.3.4/26@bar", res.to_s
43
+ end
44
+
45
+ should "build from array with hex, pfxlen and ctx" do
46
+ res = IP.new(["v4", "01020304", 26, "bar"])
47
+ assert_equal IP::V4, res.class
48
+ assert_equal "1.2.3.4/26@bar", res.to_s
49
+ end
50
+
51
+ should "build direct from integer" do
52
+ res = IP::V4.new(0x01020304)
53
+ assert_equal "1.2.3.4", res.to_s
54
+ assert_equal 32, res.pfxlen
55
+ assert_nil res.ctx
56
+ end
57
+
58
+ should "build direct from integer, pfxlen, ctx" do
59
+ res = IP::V4.new(0x01020304, 24, "foo")
60
+ assert_equal "1.2.3.4/24@foo", res.to_s
61
+ end
62
+
63
+ should "build from another IP" do
64
+ s1 = IP.new("1.2.3.4/24@foo")
65
+ s2 = IP.new(s1)
66
+ assert_equal s1, s2
67
+ assert_not_equal s1.object_id, s2.object_id
68
+ end
69
+
70
+ should "disallow invalid addr" do
71
+ assert_raises(ArgumentError) { IP::V4.new(1 << 32) }
72
+ assert_raises(ArgumentError) { IP::V4.new(-1) }
73
+ end
74
+
75
+ should "disallow invalid pfxlen" do
76
+ assert_raises(ArgumentError) { IP.new("1.2.3.4/33") }
77
+ end
78
+
79
+ context "address not on subnet boundary" do
80
+ setup do
81
+ @addr = IP.new("1.2.3.4/24@foo")
82
+ end
83
+
84
+ should "have to_s" do
85
+ assert_equal "1.2.3.4/24@foo", @addr.to_s
86
+ end
87
+
88
+ should "have to_addrlen" do
89
+ assert_equal "1.2.3.4/24", @addr.to_addrlen
90
+ end
91
+
92
+ should "have to_addr" do
93
+ assert_equal "1.2.3.4", @addr.to_addr
94
+ end
95
+
96
+ should "have to_i" do
97
+ assert_equal 0x01020304, @addr.to_i
98
+ end
99
+
100
+ should "have to_a" do
101
+ assert_equal ["v4", 0x01020304, 24, "foo"], @addr.to_a
102
+ end
103
+
104
+ should "have to_ah" do
105
+ assert_equal ["v4", "01020304", 24, "foo"], @addr.to_ah
106
+ end
107
+
108
+ should "have to_hex" do
109
+ assert_equal "01020304", @addr.to_hex
110
+ end
111
+
112
+ should "have inspect" do
113
+ assert_equal "#<IP::V4 1.2.3.4/24@foo>", @addr.inspect
114
+ end
115
+
116
+ should "have pfxlen" do
117
+ assert_equal 24, @addr.pfxlen
118
+ end
119
+
120
+ should "have proto" do
121
+ assert_equal "v4", @addr.proto
122
+ end
123
+
124
+ should "have to_range" do
125
+ assert_equal((0x01020300 .. 0x010203ff), @addr.to_range)
126
+ end
127
+
128
+ should "have size" do
129
+ assert_equal 256, @addr.size
130
+ end
131
+
132
+ should "have ctx reader" do
133
+ assert_equal "foo", @addr.ctx
134
+ end
135
+
136
+ should "have ctx writer" do
137
+ @addr.ctx = "bar"
138
+ assert_equal "bar", @addr.ctx
139
+ end
140
+
141
+ should "have network" do
142
+ assert_equal "1.2.3.0/24@foo", @addr.network.to_s
143
+ assert_equal "1.2.3.9/24@foo", @addr.network(9).to_s
144
+ end
145
+
146
+ should "have broadcast" do
147
+ assert_equal "1.2.3.255/24@foo", @addr.broadcast.to_s
148
+ assert_equal "1.2.3.252/24@foo", @addr.broadcast(-3).to_s
149
+ end
150
+
151
+ should "have mask" do
152
+ assert_equal 0x000000ff, @addr.mask
153
+ end
154
+
155
+ should "have netmask" do
156
+ assert_equal "255.255.255.0", @addr.netmask.to_s
157
+ end
158
+
159
+ should "have wildmask" do
160
+ assert_equal "0.0.0.255", @addr.wildmask.to_s
161
+ end
162
+
163
+ should "perform mask!" do
164
+ res = @addr.mask!
165
+ assert_equal "1.2.3.0/24@foo", res.to_s
166
+ assert_equal "1.2.3.0/24@foo", @addr.to_s # mutates object
167
+ end
168
+
169
+ should "have offset" do
170
+ assert @addr.offset?
171
+ assert_equal 4, @addr.offset
172
+ @addr.reset_pfxlen!
173
+ assert_equal "1.2.3.4@foo", @addr.to_s
174
+ end
175
+
176
+ should "have +" do
177
+ assert_equal ["v4", 0x01020309, 24, "foo"], (@addr + 5).to_a
178
+ assert_equal ["v4", 0x01020304, 24, "foo"], @addr.to_a
179
+ end
180
+
181
+ should "have -" do
182
+ assert_equal ["v4", 0x010202ff, 24, "foo"], (@addr - 5).to_a
183
+ assert_equal ["v4", 0x01020304, 24, "foo"], @addr.to_a
184
+ end
185
+
186
+ should "have &" do
187
+ assert_equal ["v4", 0x00000304, 24, "foo"], (@addr & 0xffff).to_a
188
+ assert_equal ["v4", 0x01020304, 24, "foo"], @addr.to_a
189
+ end
190
+
191
+ should "have |" do
192
+ assert_equal ["v4", 0x01020307, 24, "foo"], (@addr | 7).to_a
193
+ assert_equal ["v4", 0x01020304, 24, "foo"], @addr.to_a
194
+ end
195
+
196
+ should "have ^" do
197
+ assert_equal ["v4", 0x010203fb, 24, "foo"], (@addr ^ 255).to_a
198
+ assert_equal ["v4", 0x01020304, 24, "foo"], @addr.to_a
199
+ end
200
+
201
+ should "have ~" do
202
+ assert_equal ["v4", 0xfefdfcfb, 24, "foo"], (~@addr).to_a
203
+ assert_equal ["v4", 0x01020304, 24, "foo"], @addr.to_a
204
+ end
205
+
206
+ should "have pfxlen writer" do
207
+ assert_equal 0xffffff00, @addr.netmask.to_i
208
+ @addr.pfxlen = 29
209
+ assert_equal 0xfffffff8, @addr.netmask.to_i
210
+ assert_equal "1.2.3.4/29@foo", @addr.to_s
211
+ assert_raises(ArgumentError) { @addr.pfxlen = 33 }
212
+ end
213
+
214
+ should "have native" do
215
+ assert_equal @addr, @addr.native
216
+ end
217
+ end
218
+
219
+ context "address on subnet boundary" do
220
+ setup do
221
+ @addr = IP.new("1.2.3.4/30")
222
+ end
223
+
224
+ should "have inspect" do
225
+ assert_equal "#<IP::V4 1.2.3.4/30>", @addr.inspect
226
+ end
227
+
228
+ should "perform mask!" do
229
+ @addr.mask!
230
+ assert_equal "1.2.3.4/30", @addr.to_s
231
+ end
232
+
233
+ should "have offset" do
234
+ assert !@addr.offset?
235
+ assert_equal 0, @addr.offset
236
+ end
237
+ end
238
+
239
+ context "single IP" do
240
+ setup do
241
+ @addr = IP.new("1.2.3.4")
242
+ end
243
+
244
+ should "have inspect" do
245
+ assert_equal "#<IP::V4 1.2.3.4>", @addr.inspect
246
+ end
247
+
248
+ should "have pfxlen" do
249
+ assert_equal 32, @addr.pfxlen
250
+ end
251
+
252
+ should "have size" do
253
+ assert_equal 1, @addr.size
254
+ end
255
+
256
+ should "have offset" do
257
+ assert !@addr.offset?
258
+ assert_equal 0, @addr.offset
259
+ end
260
+ end
261
+ end
262
+
263
+ context "v6 normal" do
264
+ should "build from string" do
265
+ res = IP.new("dead:beef::123/48")
266
+ assert_equal IP::V6, res.class
267
+ assert_equal "dead:beef::123/48", res.to_s
268
+ assert_equal "dead:beef::123/48", res.to_addrlen
269
+ assert_equal 0xdeadbeef000000000000000000000123, res.to_i
270
+ assert_equal 48, res.pfxlen
271
+ assert_equal "v6", res.proto
272
+ assert_nil res.ctx
273
+ end
274
+
275
+ should "build from string with ctx" do
276
+ res = IP.new("dead:beef::123/48@nat")
277
+ assert_equal IP::V6, res.class
278
+ assert_equal "dead:beef::123/48@nat", res.to_s
279
+ assert_equal "dead:beef::123/48", res.to_addrlen
280
+ assert_equal 0xdeadbeef000000000000000000000123, res.to_i
281
+ assert_equal 48, res.pfxlen
282
+ assert_equal "nat", res.ctx
283
+ end
284
+
285
+ should "build from array" do
286
+ res = IP.new(["v6", 0xdeadbeef000000000000000000000123])
287
+ assert_equal IP::V6, res.class
288
+ assert_equal "dead:beef::123", res.to_s
289
+ assert_equal 128, res.pfxlen
290
+ assert_nil res.ctx
291
+ end
292
+
293
+ should "build from array with pfxlen" do
294
+ res = IP.new(["v6", 0xdeadbeef000000000000000000000123, 48])
295
+ assert_equal IP::V6, res.class
296
+ assert_equal "dead:beef::123/48", res.to_s
297
+ end
298
+
299
+ should "build from array with pfxlen and ctx" do
300
+ res = IP.new(["v6", 0xdeadbeef000000000000000000000123, 48, "bar"])
301
+ assert_equal IP::V6, res.class
302
+ assert_equal "dead:beef::123/48@bar", res.to_s
303
+ end
304
+
305
+ should "build from array with hex, pfxlen and ctx" do
306
+ res = IP.new(["v6", "deadbeef000000000000000000000123", 48, "bar"])
307
+ assert_equal IP::V6, res.class
308
+ assert_equal "dead:beef::123/48@bar", res.to_s
309
+ end
310
+
311
+ should "build direct from integer" do
312
+ res = IP::V6.new(0xdeadbeef000000000000000000000123)
313
+ assert_equal "dead:beef::123", res.to_s
314
+ assert_equal 128, res.pfxlen
315
+ assert_nil res.ctx
316
+ end
317
+
318
+ should "build direct from integer, pfxlen, ctx" do
319
+ res = IP::V6.new(0xdeadbeef000000000000000000000123, 24, "foo")
320
+ assert_equal "dead:beef::123/24@foo", res.to_s
321
+ assert_equal 24, res.pfxlen
322
+ assert_equal "foo", res.ctx
323
+ end
324
+
325
+ should "build from another IP" do
326
+ s1 = IP.new("dead:beef::123/48@foo")
327
+ s2 = IP.new(s1)
328
+ assert_equal s1, s2
329
+ assert_not_equal s1.object_id, s2.object_id
330
+ end
331
+
332
+ should "disallow invalid addr" do
333
+ assert_raises(ArgumentError) { IP::V6.new(1 << 128) }
334
+ assert_raises(ArgumentError) { IP::V6.new(-1) }
335
+ end
336
+
337
+ should "disallow invalid pfxlen" do
338
+ assert_raises(ArgumentError) { IP.new("dead:beef::123/129@foo") }
339
+ end
340
+
341
+ should "have pfxlen writer" do
342
+ res = IP::V6.new(0xdeadbeef000000000000000000000123, 24, "foo")
343
+ res.pfxlen = 120
344
+ assert_equal "dead:beef::123/120@foo", res.to_s
345
+ assert_raises(ArgumentError) { res.pfxlen = 129 }
346
+ end
347
+
348
+ should "have native" do
349
+ res = IP::V6.new(0xdeadbeef000000000000000000000123, 24, "foo")
350
+ assert_equal res, res.native
351
+ end
352
+ end
353
+
354
+ context "v6 ::0" do
355
+ setup do
356
+ @addr = IP::V6.new(0)
357
+ end
358
+
359
+ should "format" do
360
+ assert_equal "::", @addr.to_s
361
+ end
362
+
363
+ should "have native" do
364
+ assert_equal @addr, @addr.native
365
+ end
366
+ end
367
+
368
+ context "v6 ::1" do
369
+ setup do
370
+ @addr = IP::V6.new(1)
371
+ end
372
+
373
+ should "format" do
374
+ assert_equal "::1", @addr.to_s
375
+ end
376
+
377
+ should "have native" do
378
+ assert_equal @addr, @addr.native
379
+ end
380
+ end
381
+
382
+ context "v6 compat" do
383
+ setup do
384
+ @addr = IP.new("::1.2.3.4/120@xxx")
385
+ end
386
+
387
+ should "parse" do
388
+ assert_equal 0x01020304, @addr.to_i
389
+ assert_equal "xxx", @addr.ctx
390
+ end
391
+
392
+ should "format" do
393
+ assert_equal "::1.2.3.4/120@xxx", @addr.to_s
394
+ end
395
+
396
+ should "have native" do
397
+ a2 = @addr.native
398
+ assert_equal "1.2.3.4/24@xxx", a2.to_s
399
+ end
400
+ end
401
+
402
+ context "v6 mapped" do
403
+ setup do
404
+ @addr = IP.new("::ffff:1.2.3.4/120@xxx")
405
+ end
406
+
407
+ should "parse" do
408
+ assert_equal 0xffff01020304, @addr.to_i
409
+ assert_equal "xxx", @addr.ctx
410
+ end
411
+
412
+ should "format" do
413
+ assert_equal "::ffff:1.2.3.4/120@xxx", @addr.to_s
414
+ end
415
+
416
+ should "have native" do
417
+ a2 = @addr.native
418
+ assert_equal "1.2.3.4/24@xxx", a2.to_s
419
+ end
420
+ end
421
+
422
+ context "comparing" do
423
+ setup do
424
+ @a1 = IP.new("1.2.3.4")
425
+ end
426
+
427
+ should "compare equal with same" do
428
+ assert_equal @a1, IP.new("1.2.3.4")
429
+ end
430
+
431
+ should "order v4 before v6" do
432
+ assert @a1 < IP.new("::1")
433
+ end
434
+
435
+ should "compare < >" do
436
+ @a2 = IP.new("2.3.4.5")
437
+ assert @a1 < @a2
438
+ assert @a2 > @a1
439
+ end
440
+
441
+ should "use prefix as tiebreaker" do
442
+ @a2 = IP.new("1.2.3.4/30")
443
+ assert @a1 > @a2 # @a1 has /32 prefix length
444
+ end
445
+
446
+ should "use ctx as tiebreaker" do
447
+ @a2 = IP.new("1.2.3.4@bar")
448
+ @a3 = IP.new("1.2.3.4@foo")
449
+ assert @a1 < @a2 # @a1 has no ctx
450
+ assert @a2 < @a3
451
+ end
452
+ end
453
+
454
+ context "hashing" do
455
+ should "implement eql?" do
456
+ assert IP.new("1.2.3.96@tst").eql?(IP.new("1.2.3.96@tst"))
457
+ end
458
+
459
+ should "implement hash" do
460
+ assert_equal IP.new("1.2.3.96@tst").hash, IP.new("1.2.3.96@tst").hash
461
+ end
462
+
463
+ should "be able to use IP as hash key" do
464
+ @hash = {IP.new("1.2.3.96@tst")=>1, IP.new("1.2.3.111@tst")=>2}
465
+ assert_equal 1, @hash[IP.new("1.2.3.96@tst")]
466
+ assert_equal 2, @hash[IP.new("1.2.3.111@tst")]
467
+ end
468
+ end
469
+
470
+ PARSE_TESTS = [
471
+ # ipv4
472
+ [["v4", 0x01020304, 32], "1.2.3.4"],
473
+ [["v4", 0xffffffff, 32], "255.255.255.255"],
474
+ [nil, "255.255.255.256"],
475
+ [["v4", 0x01020304, 29], "1.2.3.4/29"],
476
+ [nil, "1.2.3.4/33"],
477
+ # ipv6
478
+ [nil, "Abc"],
479
+ [["v6", 0x0abc0000000000000000000000000000, 128], "Abc::"],
480
+ [["v6", 0x0abc0000000000000000000000000000, 128], "[Abc::]"],
481
+ [["v6", 0x00000000000000000000000000000abc, 128], "::Abc"],
482
+ [nil, "Abcde::"],
483
+ [["v6", 0x12340000000000000000000000000005, 128], "1234::5"],
484
+ [["v6", 0x11122223333444455556666777788889, 128], "1112:2223:3334:4445:5556:6667:7778:8889"],
485
+ [["v6", 0x11122223333400005556666777788889, 128], "1112:2223:3334::5556:6667:7778:8889"],
486
+ [nil, "1112:2223:3334:4445:5556:6667:7778"],
487
+ [["v6", 0x00000000000000000000000000000001, 96], "::1/96"],
488
+ [["v6", 0x00000000000000000000000000000001, 96], "[::1]/96"],
489
+ [nil, "[::1]/129"],
490
+ [["v6", 0xc0a80001, 128], "::192.168.0.1"],
491
+ [["v6", 0x01020304, 120], "::1.2.3.4/120"],
492
+ [["v6", 0xffff01020304, 126], "::ffff:1.2.3.4/126"],
493
+ [["v6", 0xffff01020304, 126], "::ffff:1.2.3.4/126"],
494
+ [["v6", 0xffff01020304, 120], "[::ffff:1.2.3.4]/120"],
495
+ ]
496
+
497
+ FORMAT_TESTS = [
498
+ ["1.2.3.4", ["v4",0x01020304,32]],
499
+ ["1.2.3.4/29", ["v4",0x01020304,29]],
500
+ ["::1.2.3.4", ["v6",0x00000000000000000000000001020304,128]],
501
+ ["abc::1/96", ["v6",0x0abc0000000000000000000000000001,96]],
502
+ ]
503
+
504
+ should "parse addresses" do
505
+ PARSE_TESTS.each do |exp,src|
506
+ res = IP.parse(src)
507
+ assert_equal exp, exp ? res.to_a : res, "Testing #{src.inspect}"
508
+ end
509
+ end
510
+
511
+ should "parse with routing context" do
512
+ res = IP.parse("1.2.3.4/28@foo")
513
+ assert_equal ["v4", 0x01020304, 28, "foo"], res.to_a
514
+ end
515
+
516
+ should "format addresses" do
517
+ FORMAT_TESTS.each do |exp,src|
518
+ assert_equal exp, IP.new(src).to_s, "Testing #{src.inspect}"
519
+ end
520
+ end
521
+ end