pio 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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