pio 0.3.0 → 0.4.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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +46 -12
  3. data/README.md +131 -116
  4. data/Rakefile +7 -92
  5. data/examples/arp_new.rb +16 -0
  6. data/examples/arp_read.rb +4 -0
  7. data/examples/dhcp_new.rb +30 -0
  8. data/examples/dhcp_read.rb +4 -0
  9. data/examples/icmp_new.rb +21 -0
  10. data/examples/icmp_read.rb +4 -0
  11. data/examples/lldp_new.rb +4 -0
  12. data/examples/lldp_read.rb +4 -0
  13. data/lib/pio.rb +6 -12
  14. data/lib/pio/arp.rb +7 -19
  15. data/lib/pio/arp/frame.rb +8 -12
  16. data/lib/pio/arp/message.rb +12 -25
  17. data/lib/pio/arp/reply.rb +30 -30
  18. data/lib/pio/arp/request.rb +30 -29
  19. data/lib/pio/dhcp.rb +58 -0
  20. data/lib/pio/dhcp/ack.rb +12 -0
  21. data/lib/pio/dhcp/boot_reply.rb +16 -0
  22. data/lib/pio/dhcp/boot_reply_options.rb +75 -0
  23. data/lib/pio/dhcp/boot_request.rb +16 -0
  24. data/lib/pio/dhcp/boot_request_options.rb +69 -0
  25. data/lib/pio/dhcp/common_options.rb +71 -0
  26. data/lib/pio/dhcp/csum_util.rb +83 -0
  27. data/lib/pio/dhcp/dhcp_field.rb +48 -0
  28. data/lib/pio/dhcp/dhcp_tlv_options.rb +84 -0
  29. data/lib/pio/dhcp/discover.rb +12 -0
  30. data/lib/pio/dhcp/field_util.rb +102 -0
  31. data/lib/pio/dhcp/frame.rb +95 -0
  32. data/lib/pio/dhcp/message.rb +79 -0
  33. data/lib/pio/dhcp/offer.rb +12 -0
  34. data/lib/pio/dhcp/optional_tlv.rb +74 -0
  35. data/lib/pio/dhcp/request.rb +12 -0
  36. data/lib/pio/dhcp/type/dhcp_client_id.rb +21 -0
  37. data/lib/pio/dhcp/type/dhcp_param_list.rb +22 -0
  38. data/lib/pio/dhcp/type/dhcp_string.rb +21 -0
  39. data/lib/pio/icmp.rb +7 -18
  40. data/lib/pio/icmp/frame.rb +38 -40
  41. data/lib/pio/icmp/message.rb +10 -61
  42. data/lib/pio/icmp/options.rb +25 -0
  43. data/lib/pio/icmp/reply.rb +34 -7
  44. data/lib/pio/icmp/request.rb +43 -7
  45. data/lib/pio/ipv4_address.rb +5 -8
  46. data/lib/pio/lldp.rb +22 -62
  47. data/lib/pio/lldp/chassis_id_tlv.rb +7 -13
  48. data/lib/pio/lldp/end_of_lldpdu_value.rb +3 -9
  49. data/lib/pio/lldp/frame.rb +6 -12
  50. data/lib/pio/lldp/management_address_value.rb +4 -10
  51. data/lib/pio/lldp/optional_tlv.rb +5 -10
  52. data/lib/pio/lldp/options.rb +37 -0
  53. data/lib/pio/lldp/organizationally_specific_value.rb +2 -8
  54. data/lib/pio/lldp/port_description_value.rb +2 -8
  55. data/lib/pio/lldp/port_id_tlv.rb +6 -12
  56. data/lib/pio/lldp/system_capabilities_value.rb +2 -8
  57. data/lib/pio/lldp/system_description_value.rb +2 -8
  58. data/lib/pio/lldp/system_name_value.rb +2 -8
  59. data/lib/pio/lldp/ttl_tlv.rb +5 -11
  60. data/lib/pio/mac.rb +4 -9
  61. data/lib/pio/message_type_selector.rb +22 -0
  62. data/lib/pio/options.rb +65 -0
  63. data/lib/pio/parse_error.rb +6 -0
  64. data/lib/pio/type/ethernet_header.rb +3 -2
  65. data/lib/pio/type/ip_address.rb +4 -9
  66. data/lib/pio/type/ipv4_header.rb +12 -17
  67. data/lib/pio/type/mac_address.rb +5 -10
  68. data/lib/pio/type/udp_header.rb +18 -0
  69. data/lib/pio/version.rb +3 -8
  70. data/pio.gemspec +12 -10
  71. data/spec/pio/arp/reply/options_spec.rb +145 -0
  72. data/spec/pio/arp/reply_spec.rb +77 -113
  73. data/spec/pio/arp/request/options_spec.rb +115 -0
  74. data/spec/pio/arp/request_spec.rb +74 -96
  75. data/spec/pio/arp_spec.rb +71 -105
  76. data/spec/pio/dhcp/ack_spec.rb +189 -0
  77. data/spec/pio/dhcp/discover_spec.rb +165 -0
  78. data/spec/pio/dhcp/offer_spec.rb +189 -0
  79. data/spec/pio/dhcp/request_spec.rb +173 -0
  80. data/spec/pio/dhcp_spec.rb +609 -0
  81. data/spec/pio/icmp/reply_spec.rb +102 -95
  82. data/spec/pio/icmp/request_spec.rb +86 -78
  83. data/spec/pio/icmp_spec.rb +153 -146
  84. data/spec/pio/ipv4_address_spec.rb +2 -7
  85. data/spec/pio/lldp/options_spec.rb +188 -0
  86. data/spec/pio/lldp_spec.rb +181 -208
  87. data/spec/pio/mac_spec.rb +3 -8
  88. data/spec/spec_helper.rb +4 -10
  89. metadata +69 -17
  90. data/.gitignore +0 -20
  91. data/.rspec +0 -3
  92. data/.rubocop.yml +0 -1
  93. data/.travis.yml +0 -13
  94. data/Gemfile +0 -37
  95. data/Guardfile +0 -24
  96. data/lib/pio/message_util.rb +0 -19
  97. data/lib/pio/type/config.reek +0 -4
  98. data/lib/pio/util.rb +0 -21
  99. data/pio.org +0 -668
  100. data/pio.org_archive +0 -943
  101. data/rubocop-todo.yml +0 -9
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ module Pio
4
+ # Raised when the packet data is in wrong format.
5
+ class ParseError < StandardError; end
6
+ end
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: utf-8
2
+
2
3
  require 'pio/type/mac_address'
3
4
 
4
5
  module Pio
@@ -11,7 +12,7 @@ module Pio
11
12
  class_eval do
12
13
  mac_address :destination_mac
13
14
  mac_address :source_mac
14
- uint16 :ether_type, :value => options[:ether_type]
15
+ uint16 :ether_type, value: options[:ether_type]
15
16
  end
16
17
  end
17
18
  end
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: utf-8
2
+
2
3
  require 'bindata'
3
4
  require 'pio/ipv4_address'
4
5
 
@@ -6,21 +7,15 @@ module Pio
6
7
  module Type
7
8
  # IP address
8
9
  class IpAddress < BinData::Primitive
9
- array :octets, :type => :uint8, :initial_length => 4
10
+ array :octets, type: :uint8, initial_length: 4
10
11
 
11
12
  def set(value)
12
13
  self.octets = value
13
14
  end
14
15
 
15
16
  def get
16
- IPv4Address.new octets.map { | each | sprintf('%d', each) }.join('.')
17
+ IPv4Address.new octets.map { | each | format('%d', each) }.join('.')
17
18
  end
18
19
  end
19
20
  end
20
21
  end
21
-
22
- ### Local variables:
23
- ### mode: Ruby
24
- ### coding: utf-8-unix
25
- ### indent-tabs-mode: nil
26
- ### End:
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: utf-8
2
+
2
3
  require 'pio/type/ip_address'
3
4
 
4
5
  module Pio
@@ -9,18 +10,18 @@ module Pio
9
10
  def ipv4_header(options)
10
11
  endian :big
11
12
  class_eval do
12
- bit4 :ip_version, :initial_value => 0x4
13
- bit4 :ip_header_length, :initial_value => 0x5
14
- uint8 :ip_type_of_service, :initial_value => 0
13
+ bit4 :ip_version, initial_value: 0x4
14
+ bit4 :ip_header_length, initial_value: 0x5
15
+ uint8 :ip_type_of_service, initial_value: 0
15
16
  uint16be :ip_total_length,
16
- :initial_value => options[:ip_total_length]
17
- uint16be :ip_identifier, :initial_value => 0
18
- bit3 :ip_flag, :initial_value => 0
19
- bit13 :ip_fragment, :initial_value => 0
20
- uint8 :ip_ttl, :initial_value => 128
21
- uint8 :ip_protocol, :value => options[:ip_protocol]
17
+ initial_value: options[:ip_total_length]
18
+ uint16be :ip_identifier, initial_value: 0
19
+ bit3 :ip_flag, initial_value: 0
20
+ bit13 :ip_fragment, initial_value: 0
21
+ uint8 :ip_ttl, initial_value: 128
22
+ uint8 :ip_protocol, value: options[:ip_protocol]
22
23
  uint16be :ip_header_checksum,
23
- :initial_value => options[:ip_header_checksum]
24
+ initial_value: options[:ip_header_checksum]
24
25
  ip_address :ip_source_address
25
26
  ip_address :ip_destination_address
26
27
  end
@@ -29,9 +30,3 @@ module Pio
29
30
  end
30
31
  end
31
32
  end
32
-
33
- ### Local variables:
34
- ### mode: Ruby
35
- ### coding: utf-8-unix
36
- ### indent-tabs-mode: nil
37
- ### End:
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: utf-8
2
+
2
3
  require 'bindata'
3
4
  require 'pio/mac'
4
5
 
@@ -6,23 +7,17 @@ module Pio
6
7
  module Type
7
8
  # MAC address
8
9
  class MacAddress < BinData::Primitive
9
- array :octets, :type => :uint8, :initial_length => 6
10
+ array :octets, type: :uint8, initial_length: 6
10
11
 
11
12
  def set(value)
12
- self.octets = value
13
+ self.octets = value.to_a
13
14
  end
14
15
 
15
16
  def get
16
17
  Mac.new(octets.reduce('') do |str, each|
17
- str + sprintf('%02x', each)
18
+ str + format('%02x', each)
18
19
  end.hex)
19
20
  end
20
21
  end
21
22
  end
22
23
  end
23
-
24
- ### Local variables:
25
- ### mode: Ruby
26
- ### coding: utf-8-unix
27
- ### indent-tabs-mode: nil
28
- ### End:
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ module Pio
4
+ module Type
5
+ # UDP Header Format.
6
+ module UdpHeader
7
+ def udp_header(options)
8
+ endian :big
9
+ class_eval do
10
+ uint16be :udp_src_port
11
+ uint16be :udp_dst_port
12
+ uint16be :udp_length, initial_value: options[:udp_length]
13
+ uint16be :udp_checksum, initial_value: options[:udp_checksum]
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
data/lib/pio/version.rb CHANGED
@@ -1,12 +1,7 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: utf-8
2
+
2
3
  # Base module.
3
4
  module Pio
4
5
  # gem version.
5
- VERSION = '0.3.0'
6
+ VERSION = '0.4.0'.freeze
6
7
  end
7
-
8
- ### Local variables:
9
- ### mode: Ruby
10
- ### coding: utf-8
11
- ### indent-tabs-mode: nil
12
- ### End:
data/pio.gemspec CHANGED
@@ -1,8 +1,10 @@
1
+ # encoding: utf-8
2
+
1
3
  lib = File.expand_path('../lib', __FILE__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require 'pio/version'
4
6
 
5
- Gem::Specification.new do | gem |
7
+ Gem::Specification.new do |gem|
6
8
  gem.name = 'pio'
7
9
  gem.version = Pio::VERSION
8
10
  gem.summary = 'Packet parser and generator.'
@@ -14,18 +16,18 @@ Gem::Specification.new do | gem |
14
16
  gem.email = ['yasuhito@gmail.com']
15
17
  gem.homepage = 'http://github.com/trema/pio'
16
18
 
17
- gem.files = `git ls-files`.split("\n")
19
+ gem.files = %w(CONTRIBUTING.md LICENSE Rakefile pio.gemspec)
20
+ gem.files += Dir.glob('lib/**/*.rb')
21
+ gem.files += Dir.glob('bin/**/*')
22
+ gem.files += Dir.glob('spec/**/*')
23
+ gem.files += Dir.glob('examples/**/*')
18
24
 
19
25
  gem.require_paths = ['lib']
20
26
 
21
27
  gem.extra_rdoc_files = ['README.md']
22
- gem.test_files = `git ls-files -- {spec,features}/*`.split("\n")
28
+ gem.test_files = Dir.glob('spec/**/*')
23
29
 
24
- gem.add_dependency 'bindata', '~> 1.6.0'
30
+ gem.required_ruby_version = '>= 1.9.3'
31
+ gem.add_dependency 'bindata', '~> 2.0.0'
32
+ gem.add_development_dependency 'bundler', '~> 1.6.0'
25
33
  end
26
-
27
- ### Local variables:
28
- ### mode: Ruby
29
- ### coding: utf-8-unix
30
- ### indent-tabs-mode: nil
31
- ### End:
@@ -0,0 +1,145 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio'
4
+
5
+ describe Pio::Arp::Reply::Options, '.new' do
6
+ Given(:mandatory_options) do
7
+ {
8
+ source_mac: 0x00169d1d9cc4,
9
+ destination_mac: 0x002682ebead1,
10
+ sender_protocol_address: 0xc0a85303,
11
+ target_protocol_address: 0xc0a853fe
12
+ }
13
+ end
14
+
15
+ context 'with all mandatory options' do
16
+ Given(:options) do
17
+ Pio::Arp::Reply::Options.new(mandatory_options)
18
+ end
19
+
20
+ describe '#to_hash' do
21
+ When(:result) { options.to_hash }
22
+
23
+ Then { result[:source_mac] == Pio::Mac.new(0x00169d1d9cc4) }
24
+ Then { result[:destination_mac] == Pio::Mac.new(0x002682ebead1) }
25
+ Then do
26
+ result[:sender_protocol_address] == Pio::IPv4Address.new(0xc0a85303)
27
+ end
28
+ Then do
29
+ result[:target_protocol_address] == Pio::IPv4Address.new(0xc0a853fe)
30
+ end
31
+ end
32
+ end
33
+
34
+ context 'when source_mac is not passed' do
35
+ Given(:user_options) do
36
+ mandatory_options.delete(:source_mac)
37
+ mandatory_options
38
+ end
39
+
40
+ When(:result) { Pio::Arp::Reply::Options.new(user_options) }
41
+
42
+ Then do
43
+ result ==
44
+ Failure(ArgumentError, 'The source_mac option should be passed.')
45
+ end
46
+ end
47
+
48
+ context 'with source_mac = nil' do
49
+ Given(:user_options) do
50
+ mandatory_options.update(source_mac: nil)
51
+ mandatory_options
52
+ end
53
+
54
+ When(:result) { Pio::Arp::Reply::Options.new(user_options) }
55
+
56
+ Then do
57
+ result ==
58
+ Failure(ArgumentError, "The source_mac option shouldn't be nil.")
59
+ end
60
+ end
61
+
62
+ context 'when destination_mac is not passed' do
63
+ Given(:user_options) do
64
+ mandatory_options.delete(:destination_mac)
65
+ mandatory_options
66
+ end
67
+
68
+ When(:result) { Pio::Arp::Reply::Options.new(user_options) }
69
+
70
+ Then do
71
+ result ==
72
+ Failure(ArgumentError, 'The destination_mac option should be passed.')
73
+ end
74
+ end
75
+
76
+ context 'with destination_mac = nil' do
77
+ Given(:user_options) do
78
+ mandatory_options.update(destination_mac: nil)
79
+ mandatory_options
80
+ end
81
+
82
+ When(:result) { Pio::Arp::Reply::Options.new(user_options) }
83
+
84
+ Then do
85
+ result ==
86
+ Failure(ArgumentError, "The destination_mac option shouldn't be nil.")
87
+ end
88
+ end
89
+
90
+ context 'when sender_protocol_address is not passed' do
91
+ Given(:user_options) do
92
+ mandatory_options.delete(:sender_protocol_address)
93
+ mandatory_options
94
+ end
95
+
96
+ When(:result) { Pio::Arp::Reply::Options.new(user_options) }
97
+
98
+ Then do
99
+ result == Failure(ArgumentError,
100
+ 'The sender_protocol_address option should be passed.')
101
+ end
102
+ end
103
+
104
+ context 'with sender_protocol_address = nil' do
105
+ Given(:user_options) do
106
+ mandatory_options.update(sender_protocol_address: nil)
107
+ mandatory_options
108
+ end
109
+
110
+ When(:result) { Pio::Arp::Reply::Options.new(user_options) }
111
+
112
+ Then do
113
+ result == Failure(ArgumentError,
114
+ "The sender_protocol_address option shouldn't be nil.")
115
+ end
116
+ end
117
+
118
+ context 'when target_protocol_address is not passed' do
119
+ Given(:user_options) do
120
+ mandatory_options.delete(:target_protocol_address)
121
+ mandatory_options
122
+ end
123
+
124
+ When(:result) { Pio::Arp::Reply::Options.new(user_options) }
125
+
126
+ Then do
127
+ result == Failure(ArgumentError,
128
+ 'The target_protocol_address option should be passed.')
129
+ end
130
+ end
131
+
132
+ context 'with target_protocol_address = nil' do
133
+ Given(:user_options) do
134
+ mandatory_options.update(target_protocol_address: nil)
135
+ mandatory_options
136
+ end
137
+
138
+ When(:result) { Pio::Arp::Reply::Options.new(user_options) }
139
+
140
+ Then do
141
+ result == Failure(ArgumentError,
142
+ "The target_protocol_address option shouldn't be nil.")
143
+ end
144
+ end
145
+ end
@@ -1,137 +1,101 @@
1
- # -*- coding: utf-8 -*-
2
- require 'pio/arp/reply'
1
+ # encoding: utf-8
3
2
 
4
- describe Pio::Arp::Reply do
5
- context '.new' do
6
- subject do
3
+ require 'pio'
4
+
5
+ describe Pio::ARP::Reply do
6
+ Then { Pio::ARP::Reply == Pio::Arp::Reply }
7
+ end
8
+
9
+ describe Pio::Arp::Reply, '.new' do
10
+ ARP_REPLY_DUMP =
11
+ [
12
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # destination mac address
13
+ 0x00, 0x16, 0x9d, 0x1d, 0x9c, 0xc4, # source mac address
14
+ 0x08, 0x06, # ethernet type
15
+ 0x00, 0x01, # arp hardware type
16
+ 0x08, 0x00, # arp protocol type
17
+ 0x06, # hardware address size
18
+ 0x04, # protocol address size
19
+ 0x00, 0x02, # operational code
20
+ 0x00, 0x16, 0x9d, 0x1d, 0x9c, 0xc4, # sender hardware address
21
+ 0xc0, 0xa8, 0x53, 0xfe, # sender protocol address
22
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # target hardware address
23
+ 0xc0, 0xa8, 0x53, 0x03, # target protocol address
24
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # padding
25
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27
+ 0x00, 0x00, 0x00, 0x00
28
+ ].pack('C*')
29
+
30
+ context 'with String MAC and IP address' do
31
+ Given(:arp_reply) do
7
32
  Pio::Arp::Reply.new(
8
- :source_mac => source_mac,
9
- :destination_mac => destination_mac,
10
- :sender_protocol_address => sender_protocol_address,
11
- :target_protocol_address => target_protocol_address
33
+ source_mac: '00:16:9d:1d:9c:c4',
34
+ destination_mac: '00:26:82:eb:ea:d1',
35
+ sender_protocol_address: '192.168.83.254',
36
+ target_protocol_address: '192.168.83.3'
12
37
  )
13
38
  end
14
39
 
15
- let(:arp_reply_dump) do
16
- [
17
- 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # destination mac address
18
- 0x00, 0x16, 0x9d, 0x1d, 0x9c, 0xc4, # source mac address
19
- 0x08, 0x06, # ethernet type
20
- 0x00, 0x01, # arp hardware type
21
- 0x08, 0x00, # arp protocol type
22
- 0x06, # hardware address size
23
- 0x04, # protocol address size
24
- 0x00, 0x02, # operational code
25
- 0x00, 0x16, 0x9d, 0x1d, 0x9c, 0xc4, # sender hardware address
26
- 0xc0, 0xa8, 0x53, 0xfe, # sender protocol address
27
- 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # target hardware address
28
- 0xc0, 0xa8, 0x53, 0x03, # target protocol address
29
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # padding
30
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32
- 0x00, 0x00, 0x00, 0x00,
33
- ].pack('C*')
34
- end
35
-
36
- context 'with Integer MAC and IP address' do
37
- let(:source_mac) { 0x00169d1d9cc4 }
38
- let(:destination_mac) { 0x002682ebead1 }
39
- let(:sender_protocol_address) { 0xc0a853fe }
40
- let(:target_protocol_address) { 0xc0a85303 }
41
-
42
- context '#to_binary' do
43
- it 'returns an Arp Reply binary String' do
44
- expect(subject.to_binary).to eq arp_reply_dump
45
- end
40
+ describe '#to_binary' do
41
+ When(:result) { arp_reply.to_binary }
46
42
 
47
- it 'returns a valid ether frame with size = 64' do
48
- expect(subject.to_binary.size).to eq 64
49
- end
50
- end
43
+ Then { result == ARP_REPLY_DUMP }
44
+ And { result.size == 64 }
51
45
  end
46
+ end
52
47
 
53
- context 'with String MAC and Integer IP address' do
54
- let(:source_mac) { '00:16:9d:1d:9c:c4' }
55
- let(:destination_mac) { '00:26:82:eb:ea:d1' }
56
- let(:sender_protocol_address) { 0xc0a853fe }
57
- let(:target_protocol_address) { 0xc0a85303 }
58
-
59
- context '#to_binary' do
60
- it 'returns an Arp Reply binary String' do
61
- expect(subject.to_binary).to eq arp_reply_dump
62
- end
63
-
64
- it 'returns a valid ether frame with size = 64' do
65
- expect(subject.to_binary.size).to eq 64
66
- end
67
- end
48
+ context 'with Integer MAC address and IP address' do
49
+ Given(:arp_reply) do
50
+ Pio::Arp::Reply.new(
51
+ source_mac: 0x00169d1d9cc4,
52
+ destination_mac: 0x002682ebead1,
53
+ sender_protocol_address: 0xc0a853fe,
54
+ target_protocol_address: 0xc0a85303
55
+ )
68
56
  end
69
57
 
70
- context 'when Integer MAC and String IP address' do
71
- let(:source_mac) { 0x00169d1d9cc4 }
72
- let(:destination_mac) { 0x002682ebead1 }
73
- let(:sender_protocol_address) { '192.168.83.254' }
74
- let(:target_protocol_address) { '192.168.83.3' }
58
+ describe '#to_binary' do
59
+ When(:result) { arp_reply.to_binary }
75
60
 
76
- context '#to_binary' do
77
- it 'returns an Arp Reply binary String' do
78
- expect(subject.to_binary).to eq arp_reply_dump
79
- end
80
-
81
- it 'returns a valid ether frame with size = 64' do
82
- expect(subject.to_binary.size).to eq 64
83
- end
84
- end
61
+ Then { result == ARP_REPLY_DUMP }
62
+ And { result.size == 64 }
85
63
  end
64
+ end
86
65
 
87
- context 'when :source_mac is not set' do
88
- let(:source_mac) { nil }
89
- let(:destination_mac) { 0x002682ebead1 }
90
- let(:sender_protocol_address) { '192.168.83.3' }
91
- let(:target_protocol_address) { '192.168.83.254' }
92
-
93
- it 'raises an invalid MAC address error' do
94
- expect { subject }.to raise_error('Invalid MAC address: nil')
95
- end
66
+ context 'with String MAC and Integer IP address' do
67
+ Given(:arp_reply) do
68
+ Pio::Arp::Reply.new(
69
+ source_mac: '00:16:9d:1d:9c:c4',
70
+ destination_mac: '00:26:82:eb:ea:d1',
71
+ sender_protocol_address: 0xc0a853fe,
72
+ target_protocol_address: 0xc0a85303
73
+ )
96
74
  end
97
75
 
98
- context 'when :destination_mac is not set' do
99
- let(:source_mac) { 0x00169d1d9cc4 }
100
- let(:destination_mac) { nil }
101
- let(:sender_protocol_address) { '192.168.83.3' }
102
- let(:target_protocol_address) { '192.168.83.254' }
76
+ describe '#to_binary' do
77
+ When(:result) { arp_reply.to_binary }
103
78
 
104
- it 'raises an invalid MAC address error' do
105
- expect { subject }.to raise_error('Invalid MAC address: nil')
106
- end
79
+ Then { result == ARP_REPLY_DUMP }
80
+ And { result.size == 64 }
107
81
  end
82
+ end
108
83
 
109
- context 'when :sender_protocol_address is not set' do
110
- let(:source_mac) { 0x00169d1d9cc4 }
111
- let(:destination_mac) { 0x002682ebead1 }
112
- let(:sender_protocol_address) { nil }
113
- let(:target_protocol_address) { '192.168.83.254' }
114
-
115
- it 'raises an invalid IPv4 address error' do
116
- expect { subject }.to raise_error('Invalid IPv4 address: nil')
117
- end
84
+ context 'with Integer MAC and String IP address' do
85
+ Given(:arp_reply) do
86
+ Pio::Arp::Reply.new(
87
+ source_mac: 0x00169d1d9cc4,
88
+ destination_mac: 0x002682ebead1,
89
+ sender_protocol_address: '192.168.83.254',
90
+ target_protocol_address: '192.168.83.3'
91
+ )
118
92
  end
119
93
 
120
- context 'when :target_protocol_address is not set' do
121
- let(:source_mac) { 0x00169d1d9cc4 }
122
- let(:destination_mac) { 0x002682ebead1 }
123
- let(:sender_protocol_address) { '192.168.83.3' }
124
- let(:target_protocol_address) { nil }
94
+ describe '#to_binary' do
95
+ When(:result) { arp_reply.to_binary }
125
96
 
126
- it 'raises an invalid IPv4 address error' do
127
- expect { subject }.to raise_error('Invalid IPv4 address: nil')
128
- end
97
+ Then { result == ARP_REPLY_DUMP }
98
+ And { result.size == 64 }
129
99
  end
130
100
  end
131
101
  end
132
-
133
- ### Local variables:
134
- ### mode: Ruby
135
- ### coding: utf-8-unix
136
- ### indent-tabs-mode: nil
137
- ### End: