ipaddress_2 0.11.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64e253cbf0ced3857087c448ed2308037465bb3ed59162c0b90348df5f3986c7
4
- data.tar.gz: c2c11d0cf5e6a2811097e5365cf14f19d53052d98e5ba2abf7565ac24365b353
3
+ metadata.gz: 359df425a73931023ee0026c8fdb2819f43117e24e1aa24b5ff7bb3d7f6121f6
4
+ data.tar.gz: db06b07d89444432225af2e82529a0eca395cda6e42ed59bf0cf443befc914c8
5
5
  SHA512:
6
- metadata.gz: 9f399ef081ca059f28e465e969f3b1f430a2eecd0d9b171d74b5d2191e9aee83cd09c5fb68fcda7d8d71457a5621803e33a67c19a700383f6e330ce4f772973e
7
- data.tar.gz: acbced5a8b91d5c5da3b123d69d22a3d701e37f92365250f7328788749639bcca5559053ecf4019095b12e2d3b0b6c44d8f21b55cac3bcc856df8583102b9494
6
+ metadata.gz: b537db60dfaf772c2162d3c1f52c0066b0737af5811fa0ac1894aa86414ce86950f4bba00c8aa3c3a1c1171937de26848933020ce428f5b7df04611a08bcf19f
7
+ data.tar.gz: e2632e98d23618da97172f711d1736d7b6845105cb53412c42db5caa6326edc66b9e1f1ec2319f61855d1c54f3fa743df02cd653a6fd86f933b4f5d9944392f3
data/.travis.yml CHANGED
@@ -4,6 +4,8 @@ rvm:
4
4
  - 2.4
5
5
  - 2.5
6
6
  - 2.6
7
+ - 2.7
8
+ - 3.0
7
9
  install:
8
10
  - gem install bundler
9
11
  - gem install rake
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## 0.14.0
4
+
5
+ ### Enhancements
6
+ * include? will now accept a string. Will also work for include_all?
7
+
8
+ ## 0.13.0
9
+
10
+ ### Enhancements
11
+ * Provide arithmetic operations on IPv4 and IPv6
12
+
13
+ ## 0.12.1
14
+
15
+ ### Bugfix
16
+ * Remove dup from IPv6 summarization to slightly improve performance
17
+
18
+ ## 0.12.0
19
+
20
+ ### Enhancements
21
+ * Added 'last' to IPv6
22
+ * Added 'broadcast' to IPv6
23
+
24
+ ## 0.11.1
25
+
26
+ ### Bugfix
27
+ * Fix prefix change in find\_adjacent
28
+
3
29
  ## 0.11.0
4
30
 
5
31
  ### Enhancements
@@ -26,6 +52,6 @@
26
52
  ### Bugfix
27
53
  * Removed duplicate link_local? in IPv6
28
54
 
29
- Please check [CHANGELOG.rdoc](https://github.com/ipaddress2-gem/ipaddress2/blob/master/CHANGELOG.rdoc) for previous changes.
55
+ Please check [CHANGELOG.rdoc](https://github.com/ipaddress2-gem/ipaddress_2/blob/master/CHANGELOG.rdoc) for previous changes.
30
56
 
31
57
 
data/README.rdoc CHANGED
@@ -16,11 +16,11 @@ examples of typical usage.
16
16
 
17
17
  * Ruby 1.9.3 or later
18
18
 
19
- Please refer to {Travis CI}[https://travis-ci.org/ipaddress2-gem/ipaddress2] for Build Tests on specific versions of Ruby.
19
+ Please refer to {Travis CI}[https://travis-ci.org/ipaddress2-gem/ipaddress_2] for Build Tests on specific versions of Ruby.
20
20
 
21
- {<img src="https://travis-ci.org/ipaddress2-gem/ipaddress2.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/ipaddress2-gem/ipaddress2] {<img src="https://codeclimate.com/github/ipaddress2-gem/ipaddress2/badges/gpa.svg" />}[https://codeclimate.com/github/ipaddress2-gem/ipaddress2]
21
+ {<img src="https://travis-ci.org/ipaddress2-gem/ipaddress_2.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/ipaddress2-gem/ipaddress_2] {<img src="https://codeclimate.com/github/ipaddress2-gem/ipaddress_2/badges/gpa.svg" />}[https://codeclimate.com/github/ipaddress2-gem/ipaddress_2]
22
22
 
23
- If you want to contribute, please refer to {Contributing.md}[https://github.com/ipaddress2-gem/ipaddress2/blob/master/CONTRIBUTING.md].
23
+ If you want to contribute, please refer to {Contributing.md}[https://github.com/ipaddress2-gem/ipaddress_2/blob/master/CONTRIBUTING.md].
24
24
 
25
25
 
26
26
  == Installation
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.0
1
+ 0.14.0
data/ipaddress_2.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.version = IPAddress::VERSION
10
10
  s.require_paths = ["lib"]
11
11
  s.authors = ["bluemonk", "mikemackintosh"]
12
- s.description = "IPAddress2 is a Ruby library designed to make manipulation\n of IPv4 and IPv6 addresses both powerful and simple. It mantains\n a layer of compatibility with Ruby's own IPAddr, while\n addressing many of its issues."
12
+ s.description = "IPAddress2 is a Ruby library designed to make manipulation\n of IPv4 and IPv6 addresses both powerful and simple. It maintains\n a layer of compatibility with Ruby's own IPAddr, while\n addressing many of its issues."
13
13
  s.email = "adam@21eleven.com"
14
14
  s.extra_rdoc_files = [
15
15
  "CHANGELOG.rdoc",
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
17
17
  "README.rdoc"
18
18
  ]
19
19
  s.files = `git ls-files -z`.split("\x0")
20
- s.homepage = "https://github.com/ipaddress2-gem/ipaddress2"
20
+ s.homepage = "https://github.com/ipaddress2-gem/ipaddress_2"
21
21
 
22
22
  s.add_development_dependency "bundler"
23
23
  s.add_development_dependency "rake"
@@ -377,6 +377,18 @@ module IPAddress;
377
377
  def network
378
378
  self.class.parse_u32(network_u32, @prefix)
379
379
  end
380
+
381
+ #
382
+ # Returns a new IPv4 object containing only the host part of this IP.
383
+ #
384
+ # ip = IPAddress("172.16.10.64/24")
385
+ #
386
+ # ip.hostpart.to_s
387
+ # #=> "0.0.0.64"
388
+ #
389
+ def hostpart
390
+ self.class.parse_u32(hostpart_u32, 32)
391
+ end
380
392
 
381
393
  #
382
394
  # Returns a new IPv4 object with the
@@ -600,6 +612,18 @@ module IPAddress;
600
612
  def network_u32
601
613
  @u32 & @prefix.to_u32
602
614
  end
615
+
616
+ #
617
+ # Returns this address' host part in unsigned 32bits format
618
+ #
619
+ # ip = IPAddress("10.0.0.42/24")
620
+ #
621
+ # ip.host_u32
622
+ # #=> 42
623
+ #
624
+ def hostpart_u32
625
+ @u32 & ~@prefix.to_u32
626
+ end
603
627
 
604
628
  #
605
629
  # Returns the broadcast address in Unsigned 32bits format
@@ -616,7 +640,7 @@ module IPAddress;
616
640
  #
617
641
  # Checks whether a subnet includes the given IP address.
618
642
  #
619
- # Accepts an IPAddress::IPv4 object.
643
+ # Accepts an IPAddress::IPv4 object or a string.
620
644
  #
621
645
  # ip = IPAddress("192.168.10.100/24")
622
646
  #
@@ -628,13 +652,19 @@ module IPAddress;
628
652
  # ip.include? IPAddress("172.16.0.48/16")
629
653
  # #=> false
630
654
  #
655
+ # ip.include? "192.168.10.50"
656
+ # #=> true
657
+ #
631
658
  def include?(oth)
659
+ unless oth.is_a? IPAddress::IPv4
660
+ oth = IPv4.new(oth)
661
+ end
632
662
  @prefix <= oth.prefix and network_u32 == (oth.to_u32 & @prefix.to_u32)
633
663
  end
634
664
 
635
665
  #
636
666
  # Checks whether a subnet includes all the
637
- # given IPv4 objects.
667
+ # given IPv4 objects or strings.
638
668
  #
639
669
  # ip = IPAddress("192.168.10.100/24")
640
670
  #
@@ -644,6 +674,9 @@ module IPAddress;
644
674
  # ip.include_all?(addr1,addr2)
645
675
  # #=> true
646
676
  #
677
+ # ip.include_all?("192.168.10.102/24", "192.168.10.103/24")
678
+ # #=> true
679
+ #
647
680
  def include_all?(*others)
648
681
  others.all? {|oth| include?(oth)}
649
682
  end
@@ -886,6 +919,97 @@ module IPAddress;
886
919
  def +(oth)
887
920
  aggregate(*[self,oth].sort.map{|i| i.network})
888
921
  end
922
+
923
+ #
924
+ # Returns a new IPv4 object which is the result
925
+ # of advancing this IP address by a given value.
926
+ # In other words, this arithmetically adds IP addresses.
927
+ #
928
+ # Will raise an error if the resulting address is in a different subnet,
929
+ # except validating is set to false.
930
+ #
931
+ # Example:
932
+ #
933
+ # ip = IPAddress::IPv4.new("172.16.10.1/24")
934
+ # ip.add(5).to_string
935
+ # #=> "172.16.10.6/24"
936
+ def add(oth, validating=true)
937
+ oth = oth.to_i if oth.kind_of? IPAddress::IPv4 # oth shall be integer
938
+
939
+ new_obj = self.class.parse_u32(self.to_i + oth, prefix)
940
+
941
+ if validating and self.network_u32 != new_obj.network_u32
942
+ raise RuntimeError, "Subnet (/#{@prefix}) is not large enough."
943
+ end
944
+
945
+ new_obj
946
+ end
947
+
948
+ #
949
+ # Returns a new IPv4 object which is the result
950
+ # of decreasing this IP address by a given value.
951
+ # In other words, this arithmetically subtracts IP addresses.
952
+ #
953
+ # Will raise an error if the resulting address is in a different subnet,
954
+ # except validating is set to false.
955
+ #
956
+ # Example:
957
+ #
958
+ # ip = IPAddress::IPv4.new("172.16.10.10/24")
959
+ # ip.subtract(5).to_string
960
+ # #=> "172.16.10.5/24"
961
+ def subtract(oth, validating=true)
962
+ oth = oth.to_i if oth.kind_of? IPAddress::IPv4 # oth shall be integer
963
+ add(-oth, validating)
964
+ end
965
+
966
+ #
967
+ # Returns the network address of the n-th network succeeding this one.
968
+ #
969
+ # Example:
970
+ #
971
+ # ip = IPAddress::IPv4.new("172.16.10.0/24")
972
+ # ip.advance_network(24).to_string
973
+ # #=> "172.16.52.0/24"
974
+ def advance_network(amount)
975
+ IPAddress::IPv4.parse_u32(self.network.u32 + amount*self.size, @prefix)
976
+ end
977
+
978
+ #
979
+ # Returns the network address of the network succeeding this one.
980
+ #
981
+ # Example:
982
+ #
983
+ # ip = IPAddress::IPv4.new("172.16.10.0/24")
984
+ # ip.next_network.to_string
985
+ # #=> "172.16.11.0/24"
986
+ def next_network
987
+ advance_network 1
988
+ end
989
+
990
+ #
991
+ # Returns the network address of the n-th network preceeding this one.
992
+ #
993
+ # Example:
994
+ #
995
+ # ip = IPAddress::IPv4.new("172.16.10.0/24")
996
+ # ip.regress_network(5).to_string
997
+ # #=> "172.16.5.0/24"
998
+ def regress_network(amount)
999
+ advance_network(-amount)
1000
+ end
1001
+
1002
+ #
1003
+ # Returns the network address of the network preceeding this one.
1004
+ #
1005
+ # Example:
1006
+ #
1007
+ # ip = IPAddress::IPv4.new("172.16.10.0/24")
1008
+ # ip.previous_network.to_string
1009
+ # #=> "172.16.9.0/24"
1010
+ def previous_network
1011
+ regress_network 1
1012
+ end
889
1013
 
890
1014
  #
891
1015
  # Checks whether the ip address belongs to a
@@ -1164,7 +1288,9 @@ module IPAddress;
1164
1288
  return false if prefix == 0
1165
1289
  current_subnet = to_string
1166
1290
  self.prefix = @prefix - 1
1167
- (split.map{|i| i.to_string} - [current_subnet])[0]
1291
+ adjacent_subnet = (split.map{|i| i.to_string} - [current_subnet])[0]
1292
+ self.prefix = @prefix + 1
1293
+ return adjacent_subnet
1168
1294
  end
1169
1295
 
1170
1296
  #
@@ -246,6 +246,63 @@ module IPAddress;
246
246
  to_u128 | @prefix.to_u128 == @prefix.to_u128
247
247
  end
248
248
 
249
+ #
250
+ # Returns a new IPv6 object with the
251
+ # first host IP address in the range.
252
+ #
253
+ # Example: given the 2001:db8:8:800::/64 network, the first
254
+ # host IP address is 2001:db8:8:800::
255
+ #
256
+ # ip = IPAddress("2001:db8:8:800::/64")
257
+ #
258
+ # ip.first.to_s
259
+ # #=> "2001:db8:8:800::"
260
+ #
261
+ # The object IP doesn't need to be a network: the method
262
+ # automatically gets the network number from it
263
+ #
264
+ # ip = IPAddress("2001:db8:9:800::2/64")
265
+ #
266
+ # ip.first.to_s
267
+ # #=> "2001:db8:9:800::"
268
+ #
269
+ def first
270
+ if prefix == 128
271
+ return self
272
+ else
273
+ IPAddress::IPv6::parse_u128(network_u128)
274
+ end
275
+ end
276
+
277
+ #
278
+ # Like its sibling method IPv4#first, this method
279
+ # returns a new IPv4 object with the
280
+ # last host IP address in the range.
281
+ #
282
+ # Example: given the 192.168.100.0/24 network, the last
283
+ # host IP address is 192.168.100.254
284
+ #
285
+ # ip = IPAddress("2001:db8:8:800::/64")
286
+ #
287
+ # ip.last.to_s
288
+ # #=> "2001:db8:8:800:ffff:ffff:ffff:ffff"
289
+ #
290
+ # The object IP doesn't need to be a network: the method
291
+ # automatically gets the network number from it
292
+ #
293
+ # ip = IPAddress("2001:db8:9:800::2/64")
294
+ #
295
+ # ip.last.to_s
296
+ # #=> "2001:db8:9:800:ffff:ffff:ffff:ffff"
297
+ #
298
+ def last
299
+ if prefix == 128
300
+ return self
301
+ else
302
+ IPAddress::IPv6::parse_u128(broadcast_u128)
303
+ end
304
+ end
305
+
249
306
  #
250
307
  # Returns the 16-bits value specified by index
251
308
  #
@@ -337,8 +394,110 @@ module IPAddress;
337
394
  to_hex.reverse.gsub(/./){|c| c+"."} + "ip6.arpa"
338
395
  end
339
396
  alias_method :arpa, :reverse
397
+
398
+ #
399
+ # Returns a new IPv6 object which is the result
400
+ # of advancing this IP address by a given value.
401
+ # In other words, this arithmetically adds IP addresses.
402
+ #
403
+ # Will raise an error if the resulting address is in a different subnet,
404
+ # except validating is set to false.
405
+ #
406
+ # Example:
407
+ #
408
+ # ip = IPAddress::IPv6.new("fc42:1337::/64")
409
+ # ip.add(5).to_string
410
+ # #=> "fc42:1337::5/64"
411
+ def add(oth, validating=true)
412
+ oth = oth.to_i if oth.kind_of? IPAddress::IPv6 # oth shall be integer
413
+
414
+ new_obj = self.class.parse_u128(self.to_i + oth, prefix)
415
+
416
+ if validating and self.network_u128 != new_obj.network_u128
417
+ raise RuntimeError, "Subnet (/#{@prefix}) is not large enough."
418
+ end
419
+
420
+ new_obj
421
+ end
422
+
423
+ #
424
+ # Returns a new IPv6 object which is the result
425
+ # of decreasing this IP address by a given value.
426
+ # In other words, this arithmetically subtracts IP addresses.
427
+ #
428
+ # Will raise an error if the resulting address is in a different subnet,
429
+ # except validating is set to false.
430
+ #
431
+ # Example:
432
+ #
433
+ # ip = IPAddress::IPv6.new("fc42:1337::a/64")
434
+ # ip.subtract(5).to_string
435
+ # #=> "fc42:1337::5/64"
436
+ def subtract(oth, validating=true)
437
+ oth = oth.to_i if oth.kind_of? IPAddress::IPv6 # oth shall be integer
438
+ add(-oth, validating)
439
+ end
340
440
 
341
441
  #
442
+ # Returns the network address of the n-th network succeeding this one.
443
+ #
444
+ # Example:
445
+ #
446
+ # ip = IPAddress::IPv6.new("fc42:1337:0:0::/64")
447
+ # ip.advance_network(5).to_string
448
+ # #=> "fc42:1337:0:5::/64"
449
+ def advance_network(amount)
450
+ IPAddress::IPv6.parse_u128(self.network.to_i + amount*self.size, @prefix)
451
+ end
452
+
453
+ #
454
+ # Returns the network address of the network succeeding this one.
455
+ #
456
+ # Example:
457
+ #
458
+ # ip = IPAddress::IPv6.new("fc42:1337:0:0::/64")
459
+ # ip.next_network.to_string
460
+ # #=> "fc42:1337:0:1::/64"
461
+ def next_network
462
+ advance_network 1
463
+ end
464
+
465
+ #
466
+ # Returns the network address of the n-th network preceeding this one.
467
+ #
468
+ # Example:
469
+ #
470
+ # ip = IPAddress::IPv6.new("fc42:1337:0:5::/64")
471
+ # ip.regress_network(4).to_string
472
+ # #=> "fc42:1337:0:1::/64"
473
+ def regress_network(amount)
474
+ advance_network(-amount)
475
+ end
476
+
477
+ #
478
+ # Returns the network address of the network preceeding this one.
479
+ #
480
+ # Example:
481
+ #
482
+ # ip = IPAddress::IPv6.new("fc42:1337:0:5::/64")
483
+ # ip.previous_network.to_string
484
+ # #=> "fc42:1337:0:4::/64"
485
+ def previous_network
486
+ regress_network 1
487
+ end
488
+
489
+ #
490
+ # Returns a new IPv6 object containing only the host part of this IP.
491
+ #
492
+ # ip = IPAddress::IPv6.new("fc42:1337:0:5::7/64")
493
+ #
494
+ # ip.hostpart.to_s
495
+ # #=> "::7"
496
+ #
497
+ def hostpart
498
+ self.class.parse_u128(hostpart_u128, 128)
499
+ end
500
+
342
501
  # Splits a network into different subnets
343
502
  #
344
503
  # NOTE: Will allow you to split past /64 against RFC 5375
@@ -396,6 +555,18 @@ module IPAddress;
396
555
  def network_u128
397
556
  to_u128 & @prefix.to_u128
398
557
  end
558
+
559
+ #
560
+ # Returns this address' host part in unsigned 128bits format
561
+ #
562
+ # ip = IPAddress::IPv6.new("fc42:1337:0:5::7/64")
563
+ #
564
+ # ip.host_u128
565
+ # #=> 7
566
+ #
567
+ def hostpart_u128
568
+ to_u128 & ~@prefix.to_u128
569
+ end
399
570
 
400
571
  #
401
572
  # Returns the broadcast address in Unsigned 128bits format
@@ -441,13 +612,19 @@ module IPAddress;
441
612
  # ip6.include? IPAddress("2001:db8:1::8:800:200c:417a/76")
442
613
  # #=> false
443
614
  #
615
+ # ip6.include? "2001:db8::8:800:200c:1"
616
+ # #=> true
617
+ #
444
618
  def include?(oth)
619
+ unless oth.is_a? IPAddress::IPv6
620
+ oth = IPv6.new(oth)
621
+ end
445
622
  @prefix <= oth.prefix and network_u128 == self.class.new(oth.address+"/#@prefix").network_u128
446
623
  end
447
624
 
448
625
  #
449
626
  # Checks whether a subnet includes all the
450
- # given IPv4 objects.
627
+ # given IPv4 objects or strings.
451
628
  #
452
629
  # ip = IPAddress("2001:db8:8:800::1/64")
453
630
  #
@@ -457,6 +634,9 @@ module IPAddress;
457
634
  # ip.include_all?(addr1,addr2)
458
635
  # #=> true
459
636
  #
637
+ # ip.include_all?("2001:db8:8:800::2/64", "2001:db8:8:800::8/64")
638
+ # #=> true
639
+ #
460
640
  def include_all?(*others)
461
641
  others.all? {|oth| include?(oth)}
462
642
  end
@@ -771,6 +951,23 @@ module IPAddress;
771
951
  self.class.parse_u128(network_u128, @prefix)
772
952
  end
773
953
 
954
+ #
955
+ # Returns the broadcast address for the given IP.
956
+ # As this is IPv6 it is just the last IP
957
+ #
958
+ # ip = IPAddress("2001:db8:8:800::/64")
959
+ #
960
+ # ip.broadcast.to_s
961
+ # #=> "2001:db8:8:800::"
962
+ #
963
+ def broadcast
964
+ if prefix == 128
965
+ return self
966
+ else
967
+ IPAddress::IPv6::parse_u128(broadcast_u128)
968
+ end
969
+ end
970
+
774
971
  #
775
972
  # Extract 16 bits groups from a string
776
973
  #
@@ -915,9 +1112,10 @@ module IPAddress;
915
1112
  def self.summarize(*args)
916
1113
  # one network? no need to summarize
917
1114
  return [args.first.network] if args.size == 1
1115
+ args_size = args.size
918
1116
 
919
1117
  i = 0
920
- result = args.dup.sort.map{|ip| ip.network}
1118
+ result = args.sort.map{|ip| ip.network}
921
1119
  while i < result.size-1
922
1120
  sum = result[i] + result[i+1]
923
1121
  result[i..i+1] = sum.first if sum.size == 1
@@ -925,7 +1123,7 @@ module IPAddress;
925
1123
  end
926
1124
 
927
1125
  result.flatten!
928
- if result.size == args.size
1126
+ if result.size == args_size
929
1127
  # nothing more to summarize
930
1128
  return result
931
1129
  else
@@ -977,7 +1175,9 @@ module IPAddress;
977
1175
  return false if prefix == 0
978
1176
  current_subnet = to_string
979
1177
  self.prefix = @prefix - 1
980
- (split.map{|i| i.to_string} - [current_subnet])[0]
1178
+ adjacent_subnet = (split.map{|i| i.to_string} - [current_subnet])[0]
1179
+ self.prefix = @prefix + 1
1180
+ return adjacent_subnet
981
1181
  end
982
1182
 
983
1183
  private
@@ -1,3 +1,3 @@
1
1
  module IPAddress
2
- VERSION = "0.11.0"
2
+ VERSION = "0.14.0"
3
3
  end
@@ -327,7 +327,10 @@ class IPv4Test < Minitest::Test
327
327
  assert_equal false, ip.include?(@klass.new("5.5.5.5/32"))
328
328
  assert_equal false, ip.include?(@klass.new("11.0.0.0/8"))
329
329
  ip = @klass.new("13.13.0.0/13")
330
- assert_equal false, ip.include?(@klass.new("13.16.0.0/32"))
330
+ assert_equal false, ip.include?(@klass.new("13.16.0.0/32"))
331
+ ip = @klass.new("10.10.10.0/24")
332
+ assert_equal true, ip.include?("10.10.10.100")
333
+ assert_equal false, ip.include?("10.10.9.100")
331
334
  end
332
335
 
333
336
  def test_method_include_all?
@@ -336,6 +339,8 @@ class IPv4Test < Minitest::Test
336
339
  addr2 = @klass.new("192.168.10.103/24")
337
340
  assert_equal true, ip.include_all?(addr1,addr2)
338
341
  assert_equal false, ip.include_all?(addr1, @klass.new("13.16.0.0/32"))
342
+ assert_equal true, ip.include_all?("192.168.10.102/24", "192.168.10.103/24")
343
+ assert_equal false, ip.include_all?(addr1, "13.16.0.0/32")
339
344
  end
340
345
 
341
346
  def test_method_ipv4?
@@ -455,7 +460,7 @@ class IPv4Test < Minitest::Test
455
460
 
456
461
  ip2 = @klass.new("172.16.12.2/24")
457
462
  assert_equal [ip1.network.to_string, ip2.network.to_string],
458
- (ip1 + ip2).map{|i| i.to_string}
463
+ (ip1 + ip2).map{|i| i.to_string}
459
464
 
460
465
  ip1 = @klass.new("10.0.0.0/23")
461
466
  ip2 = @klass.new("10.0.2.0/24")
@@ -533,6 +538,57 @@ class IPv4Test < Minitest::Test
533
538
  assert_equal "172.16.8.0/22", @ip.supernet(22).to_string
534
539
  end
535
540
 
541
+ def test_method_add
542
+ ip = IPAddress::IPv4.new("172.16.10.1/24")
543
+ assert_equal ip.add(5), IPAddress::IPv4.new("172.16.10.6/24")
544
+ assert_equal ip.add(IPAddress::IPv4.new("0.0.0.5/6")), IPAddress::IPv4.new("172.16.10.6/24")
545
+ assert_equal ip.add(50), IPAddress::IPv4.new("172.16.10.51/24")
546
+ assert_equal ip.add(254), IPAddress::IPv4.new("172.16.10.255/24")
547
+ assert_raises(RuntimeError) {ip.add(255)}
548
+ assert_equal ip.add(255, false), IPAddress::IPv4.new("172.16.11.0/24")
549
+ assert_raises(RuntimeError) {ip.add(1000)}
550
+ ip = IPAddress::IPv4.new("172.16.10.1/30")
551
+ assert_equal ip.add(2), IPAddress::IPv4.new("172.16.10.3/30")
552
+ assert_raises(RuntimeError) {ip.add(3)}
553
+ end
554
+
555
+ def test_method_subtract
556
+ ip = IPAddress::IPv4.new("172.16.10.10/24")
557
+ assert_equal ip.subtract(5), IPAddress::IPv4.new("172.16.10.5/24")
558
+ assert_equal ip.subtract(IPAddress::IPv4.new("0.0.0.5/32")), IPAddress::IPv4.new("172.16.10.5/24")
559
+ assert_equal ip.subtract(10), IPAddress::IPv4.new("172.16.10.0/24")
560
+ assert_raises(RuntimeError) {ip.subtract(11)}
561
+ assert_equal ip.subtract(11, false), IPAddress::IPv4.new("172.16.9.255/24")
562
+ assert_raises(RuntimeError) {ip.subtract(IPAddress::IPv4.new("0.0.0.11/16"))}
563
+ end
564
+
565
+ def test_method_hostpart
566
+ ip = IPAddress::IPv4.new("172.16.10.64/24")
567
+ assert_equal ip.hostpart.to_s, "0.0.0.64"
568
+ ip = IPAddress::IPv4.new("172.16.10.130/25")
569
+ assert_equal ip.hostpart.to_s, "0.0.0.2"
570
+ end
571
+
572
+ def test_method_advance_network
573
+ ip = IPAddress::IPv4.new("172.16.10.64/24")
574
+ assert_equal ip.advance_network(42), IPAddress::IPv4.new("172.16.52.0/24")
575
+ end
576
+
577
+ def test_method_next_network
578
+ ip = IPAddress::IPv4.new("172.16.10.64/24")
579
+ assert_equal ip.next_network, IPAddress::IPv4.new("172.16.11.0/24")
580
+ end
581
+
582
+ def test_method_regress_network
583
+ ip = IPAddress::IPv4.new("172.16.10.64/24")
584
+ assert_equal ip.regress_network(5), IPAddress::IPv4.new("172.16.5.0/24")
585
+ end
586
+
587
+ def test_method_previous_network
588
+ ip = IPAddress::IPv4.new("172.16.10.64/24")
589
+ assert_equal ip.previous_network, IPAddress::IPv4.new("172.16.9.0/24")
590
+ end
591
+
536
592
  def test_classmethod_parse_u32
537
593
  @decimal_values.each do |addr,int|
538
594
  ip = @klass.parse_u32(int)
@@ -689,6 +745,7 @@ class IPv4Test < Minitest::Test
689
745
  def test_finds_adjacent_subnet
690
746
  ip = @klass.new("10.0.0.0/24")
691
747
  assert_equal "10.0.1.0/24", ip.find_adjacent_subnet
748
+ assert_equal 24, ip.prefix
692
749
  refute @klass.new("10.0.0.0/0").find_adjacent_subnet
693
750
  assert_equal "10.0.0.0/8", @klass.new("11.0.0.0/8").find_adjacent_subnet
694
751
  assert_equal "172.16.0.0/16", @klass.new("172.17.0.0/16").find_adjacent_subnet
@@ -128,6 +128,36 @@ class IPv6Test < Minitest::Test
128
128
  assert_equal bits, @ip.bits
129
129
  end
130
130
 
131
+ def test_method_first
132
+ ip = @klass.new("2001:db8:8:800::/64")
133
+ assert_instance_of @klass, ip.first
134
+ assert_equal "2001:db8:8:800::", ip.first.to_s
135
+ ip = @klass.new("2001:db8:8::/48")
136
+ assert_instance_of @klass, ip.first
137
+ assert_equal "2001:db8:8::", ip.first.to_s
138
+ ip = @klass.new("2001:db8::/32")
139
+ assert_instance_of @klass, ip.first
140
+ assert_equal "2001:db8::", ip.first.to_s
141
+ ip = @klass.new("2001:db8::8:800:200c:417a/64")
142
+ assert_instance_of @klass, ip.first
143
+ assert_equal "2001:db8::", ip.first.to_s
144
+ end
145
+
146
+ def test_method_last
147
+ ip = @klass.new("2001:db8:8:800::/64")
148
+ assert_instance_of @klass, ip.last
149
+ assert_equal "2001:db8:8:800:ffff:ffff:ffff:ffff", ip.last.to_s
150
+ ip = @klass.new("2001:db8:8::/48")
151
+ assert_instance_of @klass, ip.last
152
+ assert_equal "2001:db8:8:ffff:ffff:ffff:ffff:ffff", ip.last.to_s
153
+ ip = @klass.new("2001:db8::/32")
154
+ assert_instance_of @klass, ip.last
155
+ assert_equal "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff", ip.last.to_s
156
+ ip = @klass.new("2001:db8::8:800:200c:417a/64")
157
+ assert_instance_of @klass, ip.last
158
+ assert_equal "2001:db8::ffff:ffff:ffff:ffff", ip.last.to_s
159
+ end
160
+
131
161
  def test_method_prefix=()
132
162
  ip = @klass.new "2001:db8::8:800:200c:417a"
133
163
  assert_equal 128, ip.prefix
@@ -322,6 +352,9 @@ class IPv6Test < Minitest::Test
322
352
  not_included = @klass.new "2001:db8:1::8:800:200c:417a/76"
323
353
  assert_equal true, @ip.include?(included)
324
354
  assert_equal false, @ip.include?(not_included)
355
+ # string test
356
+ assert_equal true, @ip.include?("2001:db8::8:800:200c:2")
357
+ assert_equal false, @ip.include?("2001:db8:1::8:800:200c:417a")
325
358
  end
326
359
 
327
360
  def test_method_include_all?
@@ -330,6 +363,8 @@ class IPv6Test < Minitest::Test
330
363
  addr2 = @klass.new("2001:db8:8:800::8/64")
331
364
  assert_equal true, ip.include_all?(addr1,addr2)
332
365
  assert_equal false, ip.include_all?(addr1, @klass.new("2002:db8:8:800::2/64"))
366
+ assert_equal true, ip.include_all?("2001:db8:8:800::2/64", "2001:db8:8:800::8/64")
367
+ assert_equal false, ip.include_all?(addr1, "2002:db8:8:800::2/64")
333
368
  end
334
369
 
335
370
  def test_method_to_hex
@@ -399,6 +434,21 @@ class IPv6Test < Minitest::Test
399
434
  end
400
435
  end
401
436
 
437
+ def test_method_broadcast
438
+ ip = @klass.new("2001:db8:8:800::/64")
439
+ assert_instance_of @klass, ip.broadcast
440
+ assert_equal "2001:db8:8:800:ffff:ffff:ffff:ffff", ip.broadcast.to_s
441
+ ip = @klass.new("2001:db8:8::/48")
442
+ assert_instance_of @klass, ip.broadcast
443
+ assert_equal "2001:db8:8:ffff:ffff:ffff:ffff:ffff", ip.broadcast.to_s
444
+ ip = @klass.new("2001:db8::/32")
445
+ assert_instance_of @klass, ip.broadcast
446
+ assert_equal "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff", ip.broadcast.to_s
447
+ ip = @klass.new("2001:db8::8:800:200c:417a/64")
448
+ assert_instance_of @klass, ip.broadcast
449
+ assert_equal "2001:db8::ffff:ffff:ffff:ffff", ip.broadcast.to_s
450
+ end
451
+
402
452
  def test_method_network
403
453
  @networks.each do |addr,net|
404
454
  ip = @klass.new addr
@@ -572,13 +622,61 @@ class IPv6Test < Minitest::Test
572
622
 
573
623
  def test_finds_adjacent_subnet
574
624
  refute @klass.new("::/0").find_adjacent_subnet
625
+
626
+ ip = @klass.new("2001:db8::/32")
627
+ assert_equal "2001:db9::/32", ip.find_adjacent_subnet
628
+ assert_equal 32, ip.prefix
629
+
575
630
  assert_equal "2001:db9::/32", @klass.new("2001:db8::/32").find_adjacent_subnet
576
631
  assert_equal "2001:db8:0:1::/64", @klass.new("2001:db8::/64").find_adjacent_subnet
577
632
  assert_equal "2001:db8:8:2000::/51", @klass.new("2001:db8:8::/51").find_adjacent_subnet
578
- # assert_equal "", @klass.new("").find_adjacent_subnet
579
- # assert_equal "", @klass.new("").find_adjacent_subnet
580
633
  end
581
634
 
635
+ def test_method_add
636
+ ip = IPAddress::IPv6.new("fc42:1337::/64")
637
+ assert_equal ip.add(5), IPAddress::IPv6.new("fc42:1337::5/64")
638
+ assert_equal ip.add(IPAddress::IPv6.new("::5/42")), IPAddress::IPv6.new("fc42:1337::5/64")
639
+ assert_equal ip.add(50), IPAddress::IPv6.new("fc42:1337::32/64")
640
+ ip = IPAddress::IPv6.new("fc42:1337::/120")
641
+ assert_equal ip.add(2), IPAddress::IPv6.new("fc42:1337::2/120")
642
+ assert_raises(RuntimeError) {ip.add(256)}
643
+ assert_equal ip.add(256, false), IPAddress::IPv6.new("fc42:1337::100/120")
644
+ end
645
+
646
+ def test_method_subtract
647
+ ip = IPAddress::IPv6.new("fc42:1337::5/64")
648
+ assert_equal ip.subtract(5), IPAddress::IPv6.new("fc42:1337::/64")
649
+ assert_equal ip.subtract(IPAddress::IPv6.new("::5/12")), IPAddress::IPv6.new("fc42:1337::0/64")
650
+ assert_raises(RuntimeError) {ip.subtract(11)}
651
+ assert_raises(RuntimeError) {ip.subtract(IPAddress::IPv6.new("::11/66"))}
652
+ end
653
+
654
+ def test_method_hostpart
655
+ ip = IPAddress::IPv6.new("fc42:1337:0:5::7/64")
656
+ assert_equal ip.hostpart.to_s, "::7"
657
+ end
658
+
659
+ def test_method_advance_network
660
+ ip = IPAddress::IPv6.new("fc42:1337:0:0::/64")
661
+ assert_equal ip.advance_network(5), IPAddress::IPv6.new("fc42:1337:0:5::/64")
662
+ end
663
+
664
+ def test_method_next_network
665
+ ip = IPAddress::IPv6.new("fc42:1337:0:0::/64")
666
+ assert_equal ip.next_network, IPAddress::IPv6.new("fc42:1337:0:1::/64")
667
+ end
668
+
669
+ def test_method_regress_network
670
+ ip = IPAddress::IPv6.new("fc42:1337:0:5::/64")
671
+ assert_equal ip.regress_network(4), IPAddress::IPv6.new("fc42:1337:0:1::/64")
672
+ end
673
+
674
+ def test_method_previous_network
675
+ ip = IPAddress::IPv6.new("fc42:1337:0:5::/64")
676
+ assert_equal ip.previous_network, IPAddress::IPv6.new("fc42:1337:0:4::/64")
677
+ end
678
+
679
+
582
680
  end # class IPv6Test
583
681
 
584
682
  class IPv6UnspecifiedTest < Minitest::Test
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ipaddress_2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - bluemonk
8
8
  - mikemackintosh
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-01-22 00:00:00.000000000 Z
12
+ date: 2021-07-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: '0'
132
132
  description: |-
133
133
  IPAddress2 is a Ruby library designed to make manipulation
134
- of IPv4 and IPv6 addresses both powerful and simple. It mantains
134
+ of IPv4 and IPv6 addresses both powerful and simple. It maintains
135
135
  a layer of compatibility with Ruby's own IPAddr, while
136
136
  addressing many of its issues.
137
137
  email: adam@21eleven.com
@@ -168,11 +168,11 @@ files:
168
168
  - test/ipaddress_2/prefix_test.rb
169
169
  - test/ipaddress_2_test.rb
170
170
  - test/test_helper.rb
171
- homepage: https://github.com/ipaddress2-gem/ipaddress2
171
+ homepage: https://github.com/ipaddress2-gem/ipaddress_2
172
172
  licenses:
173
173
  - MIT
174
174
  metadata: {}
175
- post_install_message:
175
+ post_install_message:
176
176
  rdoc_options: []
177
177
  require_paths:
178
178
  - lib
@@ -187,9 +187,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
187
187
  - !ruby/object:Gem::Version
188
188
  version: '0'
189
189
  requirements: []
190
- rubyforge_project:
191
- rubygems_version: 2.7.8
192
- signing_key:
190
+ rubygems_version: 3.2.3
191
+ signing_key:
193
192
  specification_version: 4
194
193
  summary: IPv4/IPv6 address manipulation library
195
194
  test_files: []