ruby-ip 0.9.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.
@@ -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