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
@@ -1,159 +1,166 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: utf-8
2
+
2
3
  require 'pio'
3
4
 
4
- describe Pio::Icmp do
5
- context '.read' do
6
- subject { Pio::Icmp.read(data.pack('C*')) }
5
+ describe Pio::ICMP do
6
+ Then { Pio::ICMP == Pio::Icmp }
7
+ end
7
8
 
8
- context 'with Icmp request frame' do
9
- let(:data) do
10
- [
11
- # Destination MAC
12
- 0x24, 0xdb, 0xac, 0x41, 0xe5, 0x5b,
13
- # Source MAC
14
- 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1,
15
- # EtherType
16
- 0x08, 0x00,
17
- # IP Version&IP Header Length
18
- 0x45,
19
- # IP Type Of Service
20
- 0x00,
21
- # IP Total Length
22
- 0x00, 0x3c,
23
- # IP Identifier
24
- 0x39, 0xd3,
25
- # IP Flag&IP Fragment
26
- 0x00, 0x00,
27
- # IP TTL
28
- 0x80,
29
- # IP Protocol
30
- 0x01,
31
- # IP Header Checksum
32
- 0x2e, 0xd0,
33
- # IP Source Address
34
- 0xc0, 0xa8, 0x01, 0x66,
35
- # IP Destination Address
36
- 0x08, 0x08, 0x08, 0x08,
37
- # ICMP Type
38
- 0x08,
39
- # ICMP Code
40
- 0x00,
41
- # ICMP Checksum
42
- 0x4c, 0x5b,
43
- # ICMP Identifier
44
- 0x01, 0x00,
45
- # ICMP Sequence Number
46
- 0x00, 0x01,
47
- # Echo Data
48
- 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
49
- 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
50
- 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
51
- 0x73, 0x74, 0x75, 0x76, 0x77, 0x61,
52
- 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
53
- 0x68, 0x69
54
- ]
55
- end
9
+ describe Pio::Icmp, '.read' do
10
+ context 'with an ICMP request frame' do
11
+ Given(:icmp_request_dump) do
12
+ [
13
+ # Destination MAC
14
+ 0x24, 0xdb, 0xac, 0x41, 0xe5, 0x5b,
15
+ # Source MAC
16
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1,
17
+ # EtherType
18
+ 0x08, 0x00,
19
+ # IP Version&IP Header Length
20
+ 0x45,
21
+ # IP Type Of Service
22
+ 0x00,
23
+ # IP Total Length
24
+ 0x00, 0x3c,
25
+ # IP Identifier
26
+ 0x39, 0xd3,
27
+ # IP Flag&IP Fragment
28
+ 0x00, 0x00,
29
+ # IP TTL
30
+ 0x80,
31
+ # IP Protocol
32
+ 0x01,
33
+ # IP Header Checksum
34
+ 0x2e, 0xd0,
35
+ # IP Source Address
36
+ 0xc0, 0xa8, 0x01, 0x66,
37
+ # IP Destination Address
38
+ 0x08, 0x08, 0x08, 0x08,
39
+ # ICMP Type
40
+ 0x08,
41
+ # ICMP Code
42
+ 0x00,
43
+ # ICMP Checksum
44
+ 0x4c, 0x5b,
45
+ # ICMP Identifier
46
+ 0x01, 0x00,
47
+ # ICMP Sequence Number
48
+ 0x00, 0x01,
49
+ # Echo Data
50
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
51
+ 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
52
+ 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
53
+ 0x73, 0x74, 0x75, 0x76, 0x77, 0x61,
54
+ 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
55
+ 0x68, 0x69
56
+ ].pack('C*')
57
+ end
56
58
 
57
- its('destination_mac.to_s') { should eq '24:db:ac:41:e5:5b' }
58
- its('source_mac.to_s') { should eq '00:26:82:eb:ea:d1' }
59
- its(:ether_type) { should eq 0x0800 }
60
- its(:ip_version) { should eq 0x4 }
61
- its(:ip_header_length) { should eq 0x5 }
62
- its(:ip_type_of_service) { should eq 0x0 }
63
- its(:ip_total_length) { should eq 60 }
64
- its(:ip_identifier) { should eq 0x39d3 }
65
- its(:ip_fragment) { should eq 0 }
66
- its(:ip_ttl) { should eq 128 }
67
- its(:ip_protocol) { should eq 1 }
68
- its(:ip_header_checksum) { should eq 0x2ed0 }
69
- its('ip_source_address.to_s') { should eq '192.168.1.102' }
70
- its('ip_destination_address.to_s') { should eq '8.8.8.8' }
71
- its(:icmp_type) { should eq 8 }
72
- its(:icmp_code) { should eq 0 }
73
- its(:icmp_checksum) { should eq 0x4c5b }
74
- its(:icmp_identifier) { should eq 0x0100 }
75
- its(:icmp_sequence_number) { should eq 0x0001 }
76
- its(:echo_data) { should eq 'abcdefghijklmnopqrstuvwabcdefghi' }
59
+ When(:icmp_request) do
60
+ Pio::Icmp.read(icmp_request_dump)
77
61
  end
78
62
 
79
- context 'with Icmp reply frame' do
80
- let(:data) do
81
- [
82
- # Destination MAC
83
- 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1,
84
- # Source MAC
85
- 0x24, 0xdb, 0xac, 0x41, 0xe5, 0x5b,
86
- # EtherType
87
- 0x08, 0x00,
88
- # IP Version&IP Header Length
89
- 0x45,
90
- # IP Type Of Service
91
- 0x00,
92
- # IP Total Length
93
- 0x00, 0x3c,
94
- # IP Identifier
95
- 0x00, 0x00,
96
- # IP Flag&IP Fragment
97
- 0x00, 0x00,
98
- # IP TTL
99
- 0x2d,
100
- # IP Protocol
101
- 0x01,
102
- # IP Header Checksum
103
- 0xbb, 0xa3,
104
- # IP Source Address
105
- 0x08, 0x08, 0x08, 0x08,
106
- # IP Destination Address
107
- 0xc0, 0xa8, 0x01, 0x66,
108
- # ICMP Type
109
- 0x00,
110
- # ICMP Code
111
- 0x00,
112
- # ICMP Checksum
113
- 0x54, 0x5b,
114
- # ICMP Identifier
115
- 0x01, 0x00,
116
- # ICMP Sequence Number
117
- 0x00, 0x01,
118
- 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
119
- 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
120
- 0x75, 0x76, 0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
121
- 0x68, 0x69
122
- ]
123
- end
63
+ Then { icmp_request.class == Pio::Icmp::Request }
64
+ Then { icmp_request.destination_mac.to_s == '24:db:ac:41:e5:5b' }
65
+ Then { icmp_request.source_mac.to_s == '00:26:82:eb:ea:d1' }
66
+ Then { icmp_request.ether_type == 0x0800 }
67
+ Then { icmp_request.ip_version == 0x4 }
68
+ Then { icmp_request.ip_header_length == 0x5 }
69
+ Then { icmp_request.ip_type_of_service == 0x0 }
70
+ Then { icmp_request.ip_total_length == 60 }
71
+ Then { icmp_request.ip_identifier == 0x39d3 }
72
+ Then { icmp_request.ip_fragment == 0 }
73
+ Then { icmp_request.ip_ttl == 128 }
74
+ Then { icmp_request.ip_protocol == 1 }
75
+ Then { icmp_request.ip_header_checksum == 0x2ed0 }
76
+ Then { icmp_request.ip_source_address.to_s == '192.168.1.102' }
77
+ Then { icmp_request.ip_destination_address.to_s == '8.8.8.8' }
78
+ Then { icmp_request.icmp_type == 8 }
79
+ Then { icmp_request.icmp_code == 0 }
80
+ Then { icmp_request.icmp_checksum == 0x4c5b }
81
+ Then { icmp_request.icmp_identifier == 0x0100 }
82
+ Then { icmp_request.icmp_sequence_number == 0x0001 }
83
+ Then { icmp_request.echo_data == 'abcdefghijklmnopqrstuvwabcdefghi' }
84
+ end
124
85
 
125
- its('destination_mac.to_s') { should eq '00:26:82:eb:ea:d1' }
126
- its('source_mac.to_s') { should eq '24:db:ac:41:e5:5b' }
127
- its(:ether_type) { should eq 0x0800 }
128
- its(:ip_version) { should eq 0x4 }
129
- its(:ip_header_length) { should eq 0x5 }
130
- its(:ip_type_of_service) { should eq 0 }
131
- its(:ip_total_length) { should eq 60 }
132
- its(:ip_identifier) { should eq 0 }
133
- its(:ip_fragment) { should eq 0 }
134
- its(:ip_ttl) { should eq 45 }
135
- its(:ip_protocol) { should eq 1 }
136
- its(:ip_header_checksum) { should eq 0xbba3 }
137
- its('ip_source_address.to_s') { should eq '8.8.8.8' }
138
- its('ip_destination_address.to_s') { should eq '192.168.1.102' }
139
- its(:icmp_type) { should eq 0 }
140
- its(:icmp_code) { should eq 0 }
141
- its(:icmp_checksum) { should eq 0x545b }
142
- its(:icmp_identifier) { should eq 0x0100 }
143
- its(:icmp_sequence_number) { should eq 0x0001 }
144
- its(:echo_data) { should eq 'abcdefghijklmnopqrstuvwabcdefghi' }
86
+ context 'with an ICMP reply frame' do
87
+ Given(:icmp_reply_dump) do
88
+ [
89
+ # Destination MAC
90
+ 0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1,
91
+ # Source MAC
92
+ 0x24, 0xdb, 0xac, 0x41, 0xe5, 0x5b,
93
+ # EtherType
94
+ 0x08, 0x00,
95
+ # IP Version&IP Header Length
96
+ 0x45,
97
+ # IP Type Of Service
98
+ 0x00,
99
+ # IP Total Length
100
+ 0x00, 0x3c,
101
+ # IP Identifier
102
+ 0x00, 0x00,
103
+ # IP Flag&IP Fragment
104
+ 0x00, 0x00,
105
+ # IP TTL
106
+ 0x2d,
107
+ # IP Protocol
108
+ 0x01,
109
+ # IP Header Checksum
110
+ 0xbb, 0xa3,
111
+ # IP Source Address
112
+ 0x08, 0x08, 0x08, 0x08,
113
+ # IP Destination Address
114
+ 0xc0, 0xa8, 0x01, 0x66,
115
+ # ICMP Type
116
+ 0x00,
117
+ # ICMP Code
118
+ 0x00,
119
+ # ICMP Checksum
120
+ 0x54, 0x5b,
121
+ # ICMP Identifier
122
+ 0x01, 0x00,
123
+ # ICMP Sequence Number
124
+ 0x00, 0x01,
125
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
126
+ 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
127
+ 0x75, 0x76, 0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
128
+ 0x68, 0x69
129
+ ].pack('C*')
145
130
  end
146
131
 
147
- context 'with an invalid Icmp frame' do
148
- let(:data) { [] }
132
+ When(:icmp_reply) do
133
+ Pio::Icmp.read(icmp_reply_dump)
134
+ end
149
135
 
150
- it { expect { subject }.to raise_error(Pio::ParseError) }
136
+ Then { icmp_reply.class == Pio::Icmp::Reply }
137
+ Then { icmp_reply.destination_mac.to_s == '00:26:82:eb:ea:d1' }
138
+ Then { icmp_reply.source_mac.to_s == '24:db:ac:41:e5:5b' }
139
+ Then { icmp_reply.ether_type == 0x0800 }
140
+ Then { icmp_reply.ip_version == 0x4 }
141
+ Then { icmp_reply.ip_header_length == 0x5 }
142
+ Then { icmp_reply.ip_type_of_service == 0 }
143
+ Then { icmp_reply.ip_total_length == 60 }
144
+ Then { icmp_reply.ip_identifier == 0 }
145
+ Then { icmp_reply.ip_fragment == 0 }
146
+ Then { icmp_reply.ip_ttl == 45 }
147
+ Then { icmp_reply.ip_protocol == 1 }
148
+ Then { icmp_reply.ip_header_checksum == 0xbba3 }
149
+ Then { icmp_reply.ip_source_address.to_s == '8.8.8.8' }
150
+ Then { icmp_reply.ip_destination_address.to_s == '192.168.1.102' }
151
+ Then { icmp_reply.icmp_type == 0 }
152
+ Then { icmp_reply.icmp_code == 0 }
153
+ Then { icmp_reply.icmp_checksum == 0x545b }
154
+ Then { icmp_reply.icmp_identifier == 0x0100 }
155
+ Then { icmp_reply.icmp_sequence_number == 0x0001 }
156
+ Then { icmp_reply.echo_data == 'abcdefghijklmnopqrstuvwabcdefghi' }
157
+ end
158
+
159
+ context 'with an invalid ICMP packet' do
160
+ When(:result) do
161
+ Pio::Icmp.read('')
151
162
  end
163
+
164
+ Then { result == Failure(Pio::ParseError, 'End of file reached') }
152
165
  end
153
166
  end
154
-
155
- ### Local variables:
156
- ### mode: Ruby
157
- ### coding: utf-8-unix
158
- ### indent-tabs-mode: nil
159
- ### End:
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: utf-8
2
+
2
3
  require 'pio/ipv4_address'
3
4
 
4
5
  describe Pio::IPv4Address do
@@ -96,9 +97,3 @@ describe Pio::IPv4Address do
96
97
  end
97
98
  end
98
99
  end
99
-
100
- ### Local variables:
101
- ### mode: Ruby
102
- ### coding: utf-8-unix
103
- ### indent-tabs-mode: nil
104
- ### End:
@@ -0,0 +1,188 @@
1
+ # encoding: utf-8
2
+
3
+ require 'pio'
4
+
5
+ describe Pio::Lldp::Options, '.new' do
6
+ def options_with(user_options)
7
+ Pio::Lldp::Options.new(user_options)
8
+ end
9
+
10
+ Given(:mandatory_options) do
11
+ {
12
+ dpid: 0x192fa7b28d,
13
+ port_number: 1
14
+ }
15
+ end
16
+
17
+ context 'with :dpid and :port_number' do
18
+ Given(:options) { options_with(mandatory_options) }
19
+
20
+ describe '#to_hash' do
21
+ When(:result) { options.to_hash }
22
+
23
+ Then { result[:chassis_id] == 0x192fa7b28d }
24
+ Then { result[:port_id] == 1 }
25
+ Then do
26
+ result[:destination_mac] ==
27
+ Pio::Mac.new(Pio::Lldp::Options::DEFAULT_DESTINATION_MAC)
28
+ end
29
+ Then do
30
+ result[:source_mac] ==
31
+ Pio::Mac.new(Pio::Lldp::Options::DEFAULT_SOURCE_MAC)
32
+ end
33
+ end
34
+
35
+ context 'with :destination_mac' do
36
+ Given(:options) do
37
+ user_options =
38
+ mandatory_options.update(destination_mac: '06:05:04:03:02:01')
39
+ options_with(user_options)
40
+ end
41
+
42
+ describe '#to_hash' do
43
+ When(:result) do
44
+ options.to_hash
45
+ end
46
+
47
+ Then { result[:destination_mac] == Pio::Mac.new('06:05:04:03:02:01') }
48
+ And { result[:chassis_id] == 0x192fa7b28d }
49
+ And { result[:port_id] == 1 }
50
+ And do
51
+ result[:source_mac] ==
52
+ Pio::Mac.new(Pio::Lldp::Options::DEFAULT_SOURCE_MAC)
53
+ end
54
+ end
55
+ end
56
+
57
+ context 'with :source_mac' do
58
+ Given(:options) do
59
+ user_options =
60
+ mandatory_options.update(source_mac: '06:05:04:03:02:01')
61
+ options_with(user_options)
62
+ end
63
+
64
+ describe '#to_hash' do
65
+ When(:result) do
66
+ options.to_hash
67
+ end
68
+
69
+ Then { result[:source_mac] == Pio::Mac.new('06:05:04:03:02:01') }
70
+ And { result[:chassis_id] == 0x192fa7b28d }
71
+ And { result[:port_id] == 1 }
72
+ And do
73
+ result[:destination_mac] ==
74
+ Pio::Mac.new(Pio::Lldp::Options::DEFAULT_DESTINATION_MAC)
75
+ end
76
+ end
77
+ end
78
+
79
+ context 'with :destination_mac = nil' do
80
+ Given(:options) do
81
+ user_options = mandatory_options.update(destination_mac: nil)
82
+ options_with(user_options)
83
+ end
84
+
85
+ describe '#to_hash' do
86
+ When(:result) do
87
+ options.to_hash
88
+ end
89
+
90
+ Then do
91
+ result[:destination_mac] ==
92
+ Pio::Mac.new(Pio::Lldp::Options::DEFAULT_DESTINATION_MAC)
93
+ end
94
+ And { result[:chassis_id] == 0x192fa7b28d }
95
+ And { result[:port_id] == 1 }
96
+ And do
97
+ result[:source_mac] ==
98
+ Pio::Mac.new(Pio::Lldp::Options::DEFAULT_SOURCE_MAC)
99
+ end
100
+ end
101
+ end
102
+
103
+ context 'with :source_mac = nil' do
104
+ Given(:options) do
105
+ user_options = mandatory_options.update(source_mac: nil)
106
+ options_with(user_options)
107
+ end
108
+
109
+ describe '#to_hash' do
110
+ When(:result) do
111
+ options.to_hash
112
+ end
113
+
114
+ Then do
115
+ result[:source_mac] ==
116
+ Pio::Mac.new(Pio::Lldp::Options::DEFAULT_SOURCE_MAC)
117
+ end
118
+ And { result[:chassis_id] == 0x192fa7b28d }
119
+ And { result[:port_id] == 1 }
120
+ And do
121
+ result[:destination_mac] ==
122
+ Pio::Mac.new(Pio::Lldp::Options::DEFAULT_DESTINATION_MAC)
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ context 'when :dpid is not passed' do
129
+ Given(:user_options) do
130
+ mandatory_options.delete(:dpid)
131
+ mandatory_options
132
+ end
133
+
134
+ When(:result) do
135
+ options_with(user_options)
136
+ end
137
+
138
+ Then do
139
+ result ==
140
+ Failure(ArgumentError, 'The dpid option should be passed.')
141
+ end
142
+ end
143
+
144
+ context 'with :dpid = nil' do
145
+ Given(:user_options) do
146
+ mandatory_options.update(dpid: nil)
147
+ end
148
+
149
+ When(:result) do
150
+ options_with(user_options)
151
+ end
152
+
153
+ Then do
154
+ result == Failure(ArgumentError, "The dpid option shouldn't be nil.")
155
+ end
156
+ end
157
+
158
+ context 'when :port_number is not passed' do
159
+ Given(:user_options) do
160
+ mandatory_options.delete(:port_number)
161
+ mandatory_options
162
+ end
163
+
164
+ When(:result) do
165
+ options_with(user_options)
166
+ end
167
+
168
+ Then do
169
+ result ==
170
+ Failure(ArgumentError, 'The port_number option should be passed.')
171
+ end
172
+ end
173
+
174
+ context 'with :port_number = nil' do
175
+ Given(:user_options) do
176
+ mandatory_options.update(port_number: nil)
177
+ end
178
+
179
+ When(:result) do
180
+ options_with(user_options)
181
+ end
182
+
183
+ Then do
184
+ result ==
185
+ Failure(ArgumentError, "The port_number option shouldn't be nil.")
186
+ end
187
+ end
188
+ end