qubitro-mqtt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2014 @@
1
+ # encoding: BINARY
2
+ # Encoding is set to binary, so that the binary packets aren't validated as UTF-8
3
+
4
+ $:.unshift(File.dirname(__FILE__))
5
+
6
+ require 'spec_helper'
7
+
8
+ describe MQTT::Packet do
9
+
10
+ describe "when creating a new packet" do
11
+ it "should allow you to set the packet flags as a hash parameter" do
12
+ packet = MQTT::Packet.new( :flags => [true, false, true, false] )
13
+ expect(packet.flags).to eq([true, false, true, false])
14
+ end
15
+
16
+ it "should have a custom inspect method" do
17
+ packet = MQTT::Packet.new
18
+ expect(packet.inspect).to eq('#<MQTT::Packet>')
19
+ end
20
+
21
+ it "should have a type_id method to get the integer ID of the packet type" do
22
+ packet = MQTT::Packet::Pingreq.new
23
+ expect(packet.type_id).to eq(12)
24
+ end
25
+ end
26
+
27
+ it "should let you change attributes using the update_attributes method" do
28
+ packet = MQTT::Packet.new(:flags => [false, false, false, true])
29
+ packet.update_attributes(:flags => [false, false, true, true])
30
+ expect(packet.flags).to eq([false, false, true, true])
31
+ end
32
+
33
+ describe "protected methods" do
34
+ let(:packet) { MQTT::Packet.new }
35
+
36
+ it "should provide a encode_bytes method to get some bytes as Integers" do
37
+ data = packet.send(:encode_bytes, 0x48, 0x65, 0x6c, 0x6c, 'o'.unpack('C1')[0])
38
+ expect(data).to eq('Hello')
39
+ end
40
+
41
+ it "should provide a encode_bits method to encode an array of bits to a string" do
42
+ data = packet.send(:encode_bits, [false, true, true, false, true, false, true, false])
43
+ expect(data).to eq('V')
44
+ end
45
+
46
+ it "should provide a add_short method to get a big-endian unsigned 16-bit integer" do
47
+ data = packet.send(:encode_short, 1024)
48
+ expect(data).to eq("\x04\x00")
49
+ expect(data.encoding.to_s).to eq("ASCII-8BIT")
50
+ end
51
+
52
+ it "should raise an error if too big argument for encode_short" do
53
+ expect {
54
+ data = packet.send(:encode_short, 0x10000)
55
+ }.to raise_error(
56
+ 'Value too big for short'
57
+ )
58
+ end
59
+
60
+ it "should provide a add_string method to get a string preceeded by its length" do
61
+ data = packet.send(:encode_string, 'quack')
62
+ expect(data).to eq("\x00\x05quack")
63
+ expect(data.encoding.to_s).to eq("ASCII-8BIT")
64
+ end
65
+
66
+ it "should provide a shift_short method to get a 16-bit unsigned integer" do
67
+ buffer = "\x22\x8Bblahblah"
68
+ expect(packet.send(:shift_short,buffer)).to eq(8843)
69
+ expect(buffer).to eq('blahblah')
70
+ end
71
+
72
+ it "should provide a shift_byte method to get one byte as integers" do
73
+ buffer = "\x01blahblah"
74
+ expect(packet.send(:shift_byte,buffer)).to eq(1)
75
+ expect(buffer).to eq('blahblah')
76
+ end
77
+
78
+ it "should provide a shift_byte method to get one byte as integers" do
79
+ buffer = "Yblahblah"
80
+ expect(packet.send(:shift_bits, buffer)).to eq([true, false, false, true, true, false, true, false])
81
+ expect(buffer).to eq('blahblah')
82
+ end
83
+
84
+ it "should provide a shift_string method to get a string preceeded by its length" do
85
+ buffer = "\x00\x05Hello World"
86
+ expect(packet.send(:shift_string,buffer)).to eq("Hello")
87
+ expect(buffer).to eq(' World')
88
+ end
89
+ end
90
+
91
+ describe "deprecated attributes" do
92
+ it "should still have a message_id method that is that same as id" do
93
+ packet = MQTT::Packet.new
94
+ packet.message_id = 1234
95
+ expect(packet.message_id).to eq(1234)
96
+ expect(packet.id).to eq(1234)
97
+ packet.id = 4321
98
+ expect(packet.message_id).to eq(4321)
99
+ expect(packet.id).to eq(4321)
100
+ end
101
+ end
102
+ end
103
+
104
+ describe MQTT::Packet::Publish do
105
+ describe "when creating a packet" do
106
+ it "should allow you to set the packet QoS level as a hash parameter" do
107
+ packet = MQTT::Packet::Publish.new( :qos => 2 )
108
+ expect(packet.qos).to eq(2)
109
+ end
110
+
111
+ it "should allow you to set the packet retain flag as a hash parameter" do
112
+ packet = MQTT::Packet::Publish.new( :retain => true )
113
+ expect(packet.retain).to be_truthy
114
+ end
115
+
116
+ it "should raise an exception the QoS is greater than 2" do
117
+ expect {
118
+ packet = MQTT::Packet::Publish.new( :qos => 3 )
119
+ }.to raise_error(
120
+ 'Invalid QoS value: 3'
121
+ )
122
+ end
123
+
124
+ it "should raise an exception the QoS is less than 0" do
125
+ expect {
126
+ packet = MQTT::Packet::Publish.new( :qos => -1 )
127
+ }.to raise_error(
128
+ 'Invalid QoS value: -1'
129
+ )
130
+ end
131
+ end
132
+
133
+ describe "when setting attributes on a packet" do
134
+ let(:packet) {
135
+ MQTT::Packet::Publish.new(
136
+ :duplicate => false,
137
+ :qos => 0,
138
+ :retain => false
139
+ )
140
+ }
141
+
142
+ it "should let you change the dup flag of a packet" do
143
+ packet.duplicate = true
144
+ expect(packet.duplicate).to be_truthy
145
+ end
146
+
147
+ it "should let you change the dup flag of a packet using an integer" do
148
+ packet.duplicate = 1
149
+ expect(packet.duplicate).to be_truthy
150
+ end
151
+
152
+ it "should let you change the QoS value of a packet" do
153
+ packet.qos = 1
154
+ expect(packet.qos).to eq(1)
155
+ end
156
+
157
+ it "should let you change the retain flag of a packet" do
158
+ packet.retain = true
159
+ expect(packet.retain).to be_truthy
160
+ end
161
+
162
+ it "should let you change the retain flag of a packet using an integer" do
163
+ packet.retain = 1
164
+ expect(packet.retain).to be_truthy
165
+ end
166
+ end
167
+
168
+ describe "when serialising a packet" do
169
+ it "should output the correct bytes for a packet with default QoS and no flags" do
170
+ packet = MQTT::Packet::Publish.new( :topic => 'test', :payload => 'hello world' )
171
+ expect(packet.to_s).to eq("\x30\x11\x00\x04testhello world")
172
+ end
173
+
174
+ it "should output the correct bytes for a packet with QoS 1 and no flags" do
175
+ packet = MQTT::Packet::Publish.new( :id => 5, :qos => 1, :topic => 'a/b', :payload => 'hello world' )
176
+ expect(packet.to_s).to eq("\x32\x12\x00\x03a/b\x00\x05hello world")
177
+ end
178
+
179
+ it "should output the correct bytes for a packet with QoS 2 and retain flag set" do
180
+ packet = MQTT::Packet::Publish.new( :id => 5, :qos => 2, :retain => true, :topic => 'c/d', :payload => 'hello world' )
181
+ expect(packet.to_s).to eq("\x35\x12\x00\x03c/d\x00\x05hello world")
182
+ end
183
+
184
+ it "should output the correct bytes for a packet with QoS 2 and dup flag set" do
185
+ packet = MQTT::Packet::Publish.new( :id => 5, :qos => 2, :duplicate => true, :topic => 'c/d', :payload => 'hello world' )
186
+ expect(packet.to_s).to eq("\x3C\x12\x00\x03c/d\x00\x05hello world")
187
+ end
188
+
189
+ it "should output the correct bytes for a packet with an empty payload" do
190
+ packet = MQTT::Packet::Publish.new( :topic => 'test' )
191
+ expect(packet.to_s).to eq("\x30\x06\x00\x04test")
192
+ end
193
+
194
+ it "should output a string as binary / 8-bit ASCII" do
195
+ packet = MQTT::Packet::Publish.new( :topic => 'test', :payload => 'hello world' )
196
+ expect(packet.to_s.encoding.to_s).to eq("ASCII-8BIT")
197
+ end
198
+
199
+ it "should support passing in non-strings to the topic and payload" do
200
+ packet = MQTT::Packet::Publish.new( :topic => :symbol, :payload => 1234 )
201
+ expect(packet.to_s).to eq("\x30\x0c\x00\x06symbol1234")
202
+ end
203
+
204
+ it "should raise an exception when there is no topic name" do
205
+ expect {
206
+ MQTT::Packet::Publish.new.to_s
207
+ }.to raise_error(
208
+ 'Invalid topic name when serialising packet'
209
+ )
210
+ end
211
+
212
+ it "should raise an exception when there is an empty topic name" do
213
+ expect {
214
+ MQTT::Packet::Publish.new( :topic => '' ).to_s
215
+ }.to raise_error(
216
+ 'Invalid topic name when serialising packet'
217
+ )
218
+ end
219
+ end
220
+
221
+ describe "when serialising an oversized packet" do
222
+ it "should raise an exception when body is bigger than 256MB" do
223
+ expect {
224
+ packet = MQTT::Packet::Publish.new( :topic => 'test', :payload => 'x'*268435455 )
225
+ packet.to_s
226
+ }.to raise_error(
227
+ 'Error serialising packet: body is more than 256MB'
228
+ )
229
+ end
230
+ end
231
+
232
+ describe "when parsing a packet with QoS 0" do
233
+ let(:packet) { MQTT::Packet.parse( "\x30\x11\x00\x04testhello world" ) }
234
+
235
+ it "should correctly create the right type of packet object" do
236
+ expect(packet.class).to eq(MQTT::Packet::Publish)
237
+ end
238
+
239
+ it "should set the QoS level correctly" do
240
+ expect(packet.qos).to eq(0)
241
+ end
242
+
243
+ it "should set the RETAIN flag correctly" do
244
+ expect(packet.retain).to be_falsey
245
+ end
246
+
247
+ it "should set the DUP flag correctly" do
248
+ expect(packet.duplicate).to be_falsey
249
+ end
250
+
251
+ it "should set the topic name correctly" do
252
+ expect(packet.topic).to eq('test')
253
+ expect(packet.topic.encoding.to_s).to eq('UTF-8')
254
+ end
255
+
256
+ it "should set the payload correctly" do
257
+ expect(packet.payload).to eq('hello world')
258
+ expect(packet.payload.encoding.to_s).to eq('ASCII-8BIT')
259
+ end
260
+ end
261
+
262
+ describe "when parsing a packet with QoS 2 and retain and dup flags set" do
263
+ let(:packet) { MQTT::Packet.parse( "\x3D\x12\x00\x03c/d\x00\x05hello world" ) }
264
+
265
+ it "should correctly create the right type of packet object" do
266
+ expect(packet.class).to eq(MQTT::Packet::Publish)
267
+ end
268
+
269
+ it "should set the QoS level correctly" do
270
+ expect(packet.qos).to eq(2)
271
+ end
272
+
273
+ it "should set the RETAIN flag correctly" do
274
+ expect(packet.retain).to be_truthy
275
+ end
276
+
277
+ it "should set the DUP flag correctly" do
278
+ expect(packet.duplicate).to be_truthy
279
+ end
280
+
281
+ it "should set the topic name correctly" do
282
+ expect(packet.topic).to eq('c/d')
283
+ expect(packet.topic.encoding.to_s).to eq('UTF-8')
284
+ end
285
+
286
+ it "should set the payload correctly" do
287
+ expect(packet.payload).to eq('hello world')
288
+ expect(packet.payload.encoding.to_s).to eq('ASCII-8BIT')
289
+ end
290
+ end
291
+
292
+ describe "when parsing a packet with an empty payload" do
293
+ let(:packet) { MQTT::Packet.parse( "\x30\x06\x00\x04test" ) }
294
+
295
+ it "should correctly create the right type of packet object" do
296
+ expect(packet.class).to eq(MQTT::Packet::Publish)
297
+ end
298
+
299
+ it "should set the topic name correctly" do
300
+ expect(packet.topic).to eq('test')
301
+ end
302
+
303
+ it "should set the payload correctly" do
304
+ expect(packet.payload).to be_empty
305
+ end
306
+ end
307
+
308
+ describe "when parsing a packet with a QoS value of 3" do
309
+ it "should raise an exception" do
310
+ expect {
311
+ packet = MQTT::Packet.parse( "\x36\x12\x00\x03a/b\x00\x05hello world" )
312
+ }.to raise_error(
313
+ MQTT::ProtocolException,
314
+ 'Invalid packet: QoS value of 3 is not allowed'
315
+ )
316
+ end
317
+ end
318
+
319
+ describe "when parsing a packet with QoS value of 0 and DUP set" do
320
+ it "should raise an exception" do
321
+ expect {
322
+ packet = MQTT::Packet.parse( "\x38\x10\x00\x03a/bhello world" )
323
+ }.to raise_error(
324
+ MQTT::ProtocolException,
325
+ 'Invalid packet: DUP cannot be set for QoS 0'
326
+ )
327
+ end
328
+ end
329
+
330
+ describe "when parsing a packet with a body of 314 bytes" do
331
+ let(:packet) {
332
+ # 0x30 = publish
333
+ # 0xC1 = (65 * 1)
334
+ # 0x02 = (2 * 128)
335
+ MQTT::Packet.parse( "\x30\xC1\x02\x00\x05topic" + ('x' * 314) )
336
+ }
337
+
338
+ it "should parse the packet type correctly" do
339
+ expect(packet.class).to eq(MQTT::Packet::Publish)
340
+ end
341
+
342
+ it "should get the topic name correctly" do
343
+ expect(packet.topic).to eq('topic')
344
+ end
345
+
346
+ it "should get the body length correctly" do
347
+ expect(packet.payload.bytesize).to eq(314)
348
+ end
349
+ end
350
+
351
+ describe "when parsing a packet with a body of 16kbytes" do
352
+ let(:packet) do
353
+ # 0x30 = publish
354
+ # 0x87 = (7 * 1)
355
+ # 0x80 = (0 * 128)
356
+ # 0x01 = (1 * 16384)
357
+ MQTT::Packet.parse( "\x30\x87\x80\x01\x00\x05topic" + ('x'*16384) )
358
+ end
359
+
360
+ it "should parse the packet type correctly" do
361
+ expect(packet.class).to eq(MQTT::Packet::Publish)
362
+ end
363
+
364
+ it "should get the topic name correctly" do
365
+ expect(packet.topic).to eq('topic')
366
+ end
367
+
368
+ it "should get the body length correctly" do
369
+ expect(packet.payload.bytesize).to eq(16384)
370
+ end
371
+ end
372
+
373
+ describe "processing a packet containing UTF-8 character" do
374
+ let(:packet) do
375
+ MQTT::Packet::Publish.new(
376
+ :topic => "Test ①".force_encoding("UTF-8"),
377
+ :payload => "Snowman: ☃".force_encoding("UTF-8")
378
+ )
379
+ end
380
+
381
+ it "should have the correct topic byte length" do
382
+ expect(packet.topic.bytesize).to eq(8)
383
+ end
384
+
385
+ it "should have the correct topic string length", :unless => RUBY_VERSION =~ /^1\.8/ do
386
+ # Ruby 1.8 doesn't support UTF-8 properly
387
+ expect(packet.topic.length).to eq(6)
388
+ end
389
+
390
+ it "should have the correct payload byte length" do
391
+ expect(packet.payload.bytesize).to eq(12)
392
+ end
393
+
394
+ it "should have the correct payload string length", :unless => RUBY_VERSION =~ /^1\.8/ do
395
+ # Ruby 1.8 doesn't support UTF-8 properly
396
+ expect(packet.payload.length).to eq(10)
397
+ end
398
+
399
+ it "should encode to MQTT packet correctly" do
400
+ expect(packet.to_s).to eq("\x30\x16\x00\x08Test \xE2\x91\xA0Snowman: \xE2\x98\x83".force_encoding('BINARY'))
401
+ end
402
+
403
+ it "should parse the serialised packet" do
404
+ packet2 = MQTT::Packet.parse( packet.to_s )
405
+ expect(packet2.topic).to eq("Test ①".force_encoding('UTF-8'))
406
+ expect(packet2.payload).to eq("Snowman: ☃".force_encoding('BINARY'))
407
+ end
408
+ end
409
+
410
+ describe "reading a packet from a socket" do
411
+ let(:socket) { StringIO.new("\x30\x11\x00\x04testhello world") }
412
+ let(:packet) { MQTT::Packet.read(socket) }
413
+
414
+ it "should correctly create the right type of packet object" do
415
+ expect(packet.class).to eq(MQTT::Packet::Publish)
416
+ end
417
+
418
+ it "should set the body length is read correctly" do
419
+ expect(packet.body_length).to eq(17)
420
+ end
421
+
422
+ it "should set the QoS level correctly" do
423
+ expect(packet.qos).to eq(0)
424
+ end
425
+
426
+ it "should set the RETAIN flag correctly" do
427
+ expect(packet.retain).to be_falsey
428
+ end
429
+
430
+ it "should set the DUP flag correctly" do
431
+ expect(packet.duplicate).to be_falsey
432
+ end
433
+
434
+ it "should set the topic name correctly" do
435
+ expect(packet.topic).to eq('test')
436
+ expect(packet.topic.encoding.to_s).to eq('UTF-8')
437
+ end
438
+
439
+ it "should set the payload correctly" do
440
+ expect(packet.payload).to eq('hello world')
441
+ expect(packet.payload.encoding.to_s).to eq('ASCII-8BIT')
442
+ end
443
+ end
444
+
445
+ describe "when calling the inspect method" do
446
+ it "should output the payload, if it is less than 16 bytes" do
447
+ packet = MQTT::Packet::Publish.new( :topic => "topic", :payload => "payload" )
448
+ expect(packet.inspect).to eq("#<MQTT::Packet::Publish: d0, q0, r0, m0, 'topic', 'payload'>")
449
+ end
450
+
451
+ it "should output the length of the payload, if it is more than 16 bytes" do
452
+ packet = MQTT::Packet::Publish.new( :topic => "topic", :payload => 'x'*32 )
453
+ expect(packet.inspect).to eq("#<MQTT::Packet::Publish: d0, q0, r0, m0, 'topic', ... (32 bytes)>")
454
+ end
455
+
456
+ it "should only output the length of a binary payload" do
457
+ packet = MQTT::Packet.parse("\x31\x12\x00\x04test\x8D\xF8\x09\x40\xC4\xE7\x4f\xF0\xFF\x30\xE0\xE7")
458
+ expect(packet.inspect).to eq("#<MQTT::Packet::Publish: d0, q0, r1, m0, 'test', ... (12 bytes)>")
459
+ end
460
+ end
461
+ end
462
+
463
+ describe MQTT::Packet::Connect do
464
+ describe "when serialising a packet" do
465
+ it "should output the correct bytes for a packet with no flags" do
466
+ packet = MQTT::Packet::Connect.new( :client_id => 'myclient' )
467
+ expect(packet.to_s).to eq("\020\026\x00\x06MQIsdp\x03\x02\x00\x0f\x00\x08myclient")
468
+ end
469
+
470
+ it "should output the correct bytes for a packet with clean session turned off" do
471
+ packet = MQTT::Packet::Connect.new(
472
+ :client_id => 'myclient',
473
+ :clean_session => false
474
+ )
475
+ expect(packet.to_s).to eq("\020\026\x00\x06MQIsdp\x03\x00\x00\x0f\x00\x08myclient")
476
+ end
477
+
478
+ context "protocol version 3.1.0" do
479
+ it "should raise an exception when there is no client identifier" do
480
+ expect {
481
+ MQTT::Packet::Connect.new(:version => '3.1.0', :client_id => '').to_s
482
+ }.to raise_error(
483
+ 'Client identifier too short while serialising packet'
484
+ )
485
+ end
486
+
487
+ it "should raise an exception when the client identifier is too long" do
488
+ expect {
489
+ client_id = '0EB8D2FE7C254715B4467C5B2ECAD100'
490
+ MQTT::Packet::Connect.new(:version => '3.1.0', :client_id => client_id).to_s
491
+ }.to raise_error(
492
+ 'Client identifier too long when serialising packet'
493
+ )
494
+ end
495
+ end
496
+
497
+ context "protocol version 3.1.1" do
498
+ it "should allow no client identifier" do
499
+ packet = MQTT::Packet::Connect.new(
500
+ :version => '3.1.1',
501
+ :client_id => '',
502
+ :clean_session => true
503
+ )
504
+ expect(packet.to_s).to eq("\020\014\x00\x04MQTT\x04\x02\x00\x0f\x00\x00")
505
+ end
506
+
507
+ it "should allow a 32 character client identifier" do
508
+ client_id = '0EB8D2FE7C254715B4467C5B2ECAD100'
509
+ packet = MQTT::Packet::Connect.new(
510
+ :version => '3.1.1',
511
+ :client_id => client_id,
512
+ :clean_session => true
513
+ )
514
+ expect(packet.to_s).to eq("\x10,\x00\x04MQTT\x04\x02\x00\x0F\x00\x200EB8D2FE7C254715B4467C5B2ECAD100")
515
+ end
516
+ end
517
+
518
+ it "should raise an exception if the keep alive value is less than 0" do
519
+ expect {
520
+ MQTT::Packet::Connect.new(:client_id => 'test', :keep_alive => -2).to_s
521
+ }.to raise_error(
522
+ 'Invalid keep-alive value: cannot be less than 0'
523
+ )
524
+ end
525
+
526
+ it "should output the correct bytes for a packet with a Will" do
527
+ packet = MQTT::Packet::Connect.new(
528
+ :client_id => 'myclient',
529
+ :clean_session => true,
530
+ :will_qos => 1,
531
+ :will_retain => false,
532
+ :will_topic => 'topic',
533
+ :will_payload => 'hello'
534
+ )
535
+ expect(packet.to_s).to eq(
536
+ "\x10\x24"+
537
+ "\x00\x06MQIsdp"+
538
+ "\x03\x0e\x00\x0f"+
539
+ "\x00\x08myclient"+
540
+ "\x00\x05topic\x00\x05hello"
541
+ )
542
+ end
543
+
544
+ it "should output the correct bytes for a packet with a username and password" do
545
+ packet = MQTT::Packet::Connect.new(
546
+ :client_id => 'myclient',
547
+ :username => 'username',
548
+ :password => 'password'
549
+ )
550
+ expect(packet.to_s).to eq(
551
+ "\x10\x2A"+
552
+ "\x00\x06MQIsdp"+
553
+ "\x03\xC2\x00\x0f"+
554
+ "\x00\x08myclient"+
555
+ "\x00\x08username"+
556
+ "\x00\x08password"
557
+ )
558
+ end
559
+
560
+ it "should output the correct bytes for a packet with everything" do
561
+ packet = MQTT::Packet::Connect.new(
562
+ :client_id => '12345678901234567890123',
563
+ :clean_session => true,
564
+ :keep_alive => 65535,
565
+ :will_qos => 2,
566
+ :will_retain => true,
567
+ :will_topic => 'will_topic',
568
+ :will_payload => 'will_message',
569
+ :username => 'user0123456789',
570
+ :password => 'pass0123456789'
571
+ )
572
+ expect(packet.to_s).to eq(
573
+ "\x10\x5F"+ # fixed header (2)
574
+ "\x00\x06MQIsdp"+ # protocol name (8)
575
+ "\x03\xf6"+ # protocol level + flags (2)
576
+ "\xff\xff"+ # keep alive (2)
577
+ "\x00\x1712345678901234567890123"+ # client identifier (25)
578
+ "\x00\x0Awill_topic"+ # will topic (12)
579
+ "\x00\x0Cwill_message"+ # will message (14)
580
+ "\x00\x0Euser0123456789"+ # username (16)
581
+ "\x00\x0Epass0123456789"
582
+ ) # password (16)
583
+ end
584
+
585
+ context 'protocol version 3.1.1' do
586
+ it "should output the correct bytes for a packet with no flags" do
587
+ packet = MQTT::Packet::Connect.new( :version => '3.1.1', :client_id => 'myclient' )
588
+ expect(packet.to_s).to eq("\020\024\x00\x04MQTT\x04\x02\x00\x0f\x00\x08myclient")
589
+ end
590
+ end
591
+
592
+ context 'an invalid protocol version number' do
593
+ it "should raise a protocol exception" do
594
+ expect {
595
+ packet = MQTT::Packet::Connect.new( :version => 'x.x.x', :client_id => 'myclient' )
596
+ }.to raise_error(
597
+ ArgumentError,
598
+ "Unsupported protocol version: x.x.x"
599
+ )
600
+ end
601
+ end
602
+
603
+ end
604
+
605
+ describe "when parsing a simple 3.1.0 Connect packet" do
606
+ let(:packet) do
607
+ MQTT::Packet.parse(
608
+ "\x10\x16\x00\x06MQIsdp\x03\x00\x00\x0a\x00\x08myclient"
609
+ )
610
+ end
611
+
612
+ it "should correctly create the right type of packet object" do
613
+ expect(packet.class).to eq(MQTT::Packet::Connect)
614
+ end
615
+
616
+ it "should set the fixed header flags of the packet correctly" do
617
+ expect(packet.flags).to eq([false, false, false, false])
618
+ end
619
+
620
+ it "should set the Protocol Name of the packet correctly" do
621
+ expect(packet.protocol_name).to eq('MQIsdp')
622
+ expect(packet.protocol_name.encoding.to_s).to eq('UTF-8')
623
+ end
624
+
625
+ it "should set the Protocol Level of the packet correctly" do
626
+ expect(packet.protocol_level).to eq(3)
627
+ end
628
+
629
+ it "should set the Protocol version of the packet correctly" do
630
+ expect(packet.version).to eq('3.1.0')
631
+ end
632
+
633
+ it "should set the Client Identifier of the packet correctly" do
634
+ expect(packet.client_id).to eq('myclient')
635
+ expect(packet.client_id.encoding.to_s).to eq('UTF-8')
636
+ end
637
+
638
+ it "should set the Keep Alive timer of the packet correctly" do
639
+ expect(packet.keep_alive).to eq(10)
640
+ end
641
+
642
+ it "should set not have the clean session flag set" do
643
+ expect(packet.clean_session).to be_falsey
644
+ end
645
+
646
+ it "should set the the username field of the packet to nil" do
647
+ expect(packet.username).to be_nil
648
+ end
649
+
650
+ it "should set the the password field of the packet to nil" do
651
+ expect(packet.password).to be_nil
652
+ end
653
+ end
654
+
655
+ describe "when parsing a simple 3.1.1 Connect packet" do
656
+ let(:packet) do
657
+ MQTT::Packet.parse(
658
+ "\x10\x14\x00\x04MQTT\x04\x00\x00\x0a\x00\x08myclient"
659
+ )
660
+ end
661
+
662
+ it "should correctly create the right type of packet object" do
663
+ expect(packet.class).to eq(MQTT::Packet::Connect)
664
+ end
665
+
666
+ it "should set the fixed header flags of the packet correctly" do
667
+ expect(packet.flags).to eq([false, false, false, false])
668
+ end
669
+
670
+ it "should set the Protocol Name of the packet correctly" do
671
+ expect(packet.protocol_name).to eq('MQTT')
672
+ expect(packet.protocol_name.encoding.to_s).to eq('UTF-8')
673
+ end
674
+
675
+ it "should set the Protocol Level of the packet correctly" do
676
+ expect(packet.protocol_level).to eq(4)
677
+ end
678
+
679
+ it "should set the Protocol version of the packet correctly" do
680
+ expect(packet.version).to eq('3.1.1')
681
+ end
682
+
683
+ it "should set the Client Identifier of the packet correctly" do
684
+ expect(packet.client_id).to eq('myclient')
685
+ expect(packet.client_id.encoding.to_s).to eq('UTF-8')
686
+ end
687
+
688
+ it "should set the Keep Alive timer of the packet correctly" do
689
+ expect(packet.keep_alive).to eq(10)
690
+ end
691
+
692
+ it "should set not have the clean session flag set" do
693
+ expect(packet.clean_session).to be_falsey
694
+ end
695
+
696
+ it "should set the the username field of the packet to nil" do
697
+ expect(packet.username).to be_nil
698
+ end
699
+
700
+ it "should set the the password field of the packet to nil" do
701
+ expect(packet.password).to be_nil
702
+ end
703
+ end
704
+
705
+ describe "when parsing a Connect packet with the clean session flag set" do
706
+ let(:packet) do
707
+ MQTT::Packet.parse(
708
+ "\x10\x16\x00\x06MQIsdp\x03\x02\x00\x0a\x00\x08myclient"
709
+ )
710
+ end
711
+
712
+ it "should set the clean session flag" do
713
+ expect(packet.clean_session).to be_truthy
714
+ end
715
+ end
716
+
717
+ describe "when parsing a Connect packet with a Will and Testament" do
718
+ let(:packet) do
719
+ MQTT::Packet.parse(
720
+ "\x10\x24\x00\x06MQIsdp\x03\x0e\x00\x0a\x00\x08myclient\x00\x05topic\x00\x05hello"
721
+ )
722
+ end
723
+
724
+ it "should correctly create the right type of packet object" do
725
+ expect(packet.class).to eq(MQTT::Packet::Connect)
726
+ end
727
+
728
+ it "should set the fixed header flags of the packet correctly" do
729
+ expect(packet.flags).to eq([false, false, false, false])
730
+ end
731
+
732
+ it "should set the Protocol Name of the packet correctly" do
733
+ expect(packet.protocol_name).to eq('MQIsdp')
734
+ expect(packet.protocol_name.encoding.to_s).to eq('UTF-8')
735
+ end
736
+
737
+ it "should set the Protocol Level of the packet correctly" do
738
+ expect(packet.protocol_level).to eq(3)
739
+ end
740
+
741
+ it "should set the Protocol version of the packet correctly" do
742
+ expect(packet.version).to eq('3.1.0')
743
+ end
744
+
745
+ it "should set the Client Identifier of the packet correctly" do
746
+ expect(packet.client_id).to eq('myclient')
747
+ expect(packet.client_id.encoding.to_s).to eq('UTF-8')
748
+ end
749
+
750
+ it "should set the clean session flag should be set" do
751
+ expect(packet.clean_session).to be_truthy
752
+ end
753
+
754
+ it "should set the QoS of the Will should be 1" do
755
+ expect(packet.will_qos).to eq(1)
756
+ end
757
+
758
+ it "should set the Will retain flag should be false" do
759
+ expect(packet.will_retain).to be_falsey
760
+ end
761
+
762
+ it "should set the Will topic of the packet correctly" do
763
+ expect(packet.will_topic).to eq('topic')
764
+ expect(packet.will_topic.encoding.to_s).to eq('UTF-8')
765
+ end
766
+
767
+ it "should set the Will payload of the packet correctly" do
768
+ expect(packet.will_payload).to eq('hello')
769
+ expect(packet.will_payload.encoding.to_s).to eq('UTF-8')
770
+ end
771
+ end
772
+
773
+ describe "when parsing a Connect packet with a username and password" do
774
+ let(:packet) do
775
+ MQTT::Packet.parse(
776
+ "\x10\x2A"+
777
+ "\x00\x06MQIsdp"+
778
+ "\x03\xC0\x00\x0a"+
779
+ "\x00\x08myclient"+
780
+ "\x00\x08username"+
781
+ "\x00\x08password"
782
+ )
783
+ end
784
+
785
+ it "should correctly create the right type of packet object" do
786
+ expect(packet.class).to eq(MQTT::Packet::Connect)
787
+ end
788
+
789
+ it "should set the fixed header flags of the packet correctly" do
790
+ expect(packet.flags).to eq([false, false, false, false])
791
+ end
792
+
793
+ it "should set the Protocol Name of the packet correctly" do
794
+ expect(packet.protocol_name).to eq('MQIsdp')
795
+ expect(packet.protocol_name.encoding.to_s).to eq('UTF-8')
796
+ end
797
+
798
+ it "should set the Protocol Level of the packet correctly" do
799
+ expect(packet.protocol_level).to eq(3)
800
+ end
801
+
802
+ it "should set the Protocol version of the packet correctly" do
803
+ expect(packet.version).to eq('3.1.0')
804
+ end
805
+
806
+ it "should set the Client Identifier of the packet correctly" do
807
+ expect(packet.client_id).to eq('myclient')
808
+ expect(packet.client_id.encoding.to_s).to eq('UTF-8')
809
+ end
810
+
811
+ it "should set the Keep Alive Timer of the packet correctly" do
812
+ expect(packet.keep_alive).to eq(10)
813
+ end
814
+
815
+ it "should set the Username of the packet correctly" do
816
+ expect(packet.username).to eq('username')
817
+ expect(packet.username.encoding.to_s).to eq('UTF-8')
818
+ end
819
+
820
+ it "should set the Username of the packet correctly" do
821
+ expect(packet.password).to eq('password')
822
+ expect(packet.password.encoding.to_s).to eq('UTF-8')
823
+ end
824
+ end
825
+
826
+ describe "when parsing a Connect that has a username but no password" do
827
+ let(:packet) do
828
+ MQTT::Packet.parse(
829
+ "\x10\x20\x00\x06MQIsdp\x03\x80\x00\x0a\x00\x08myclient\x00\x08username"
830
+ )
831
+ end
832
+
833
+ it "should set the Username of the packet correctly" do
834
+ expect(packet.username).to eq('username')
835
+ expect(packet.username.encoding.to_s).to eq('UTF-8')
836
+ end
837
+
838
+ it "should set the Username of the packet correctly" do
839
+ expect(packet.password).to be_nil
840
+ end
841
+ end
842
+
843
+ describe "when parsing a Connect that has a password but no username" do
844
+ let(:packet) do
845
+ MQTT::Packet.parse(
846
+ "\x10\x20\x00\x06MQIsdp\x03\x40\x00\x0a\x00\x08myclient\x00\x08password"
847
+ )
848
+ end
849
+
850
+ it "should set the Username of the packet correctly" do
851
+ expect(packet.username).to be_nil
852
+ end
853
+
854
+ it "should set the Username of the packet correctly" do
855
+ expect(packet.password).to eq('password')
856
+ expect(packet.password.encoding.to_s).to eq('UTF-8')
857
+ end
858
+ end
859
+
860
+ describe "when parsing a Connect packet has the username and password flags set but doesn't have the fields" do
861
+ let(:packet) do
862
+ MQTT::Packet.parse(
863
+ "\x10\x16\x00\x06MQIsdp\x03\xC0\x00\x0a\x00\x08myclient"
864
+ )
865
+ end
866
+
867
+ it "should set the Username of the packet correctly" do
868
+ expect(packet.username).to be_nil
869
+ end
870
+
871
+ it "should set the Username of the packet correctly" do
872
+ expect(packet.password).to be_nil
873
+ end
874
+ end
875
+
876
+ describe "when parsing a Connect packet with every option set" do
877
+ let(:packet) do
878
+ MQTT::Packet.parse(
879
+ "\x10\x5F"+ # fixed header (2)
880
+ "\x00\x06MQIsdp"+ # protocol name (8)
881
+ "\x03\xf6"+ # protocol level + flags (2)
882
+ "\xff\xff"+ # keep alive (2)
883
+ "\x00\x1712345678901234567890123"+ # client identifier (25)
884
+ "\x00\x0Awill_topic"+ # will topic (12)
885
+ "\x00\x0Cwill_message"+ # will message (14)
886
+ "\x00\x0Euser0123456789"+ # username (16)
887
+ "\x00\x0Epass0123456789" # password (16)
888
+ )
889
+ end
890
+
891
+ it "should correctly create the right type of packet object" do
892
+ expect(packet.class).to eq(MQTT::Packet::Connect)
893
+ end
894
+
895
+ it "should set the fixed header flags of the packet correctly" do
896
+ expect(packet.flags).to eq([false, false, false, false])
897
+ end
898
+
899
+ it "should set the Protocol Name of the packet correctly" do
900
+ expect(packet.protocol_name).to eq('MQIsdp')
901
+ expect(packet.protocol_name.encoding.to_s).to eq('UTF-8')
902
+ end
903
+
904
+ it "should set the Protocol Level of the packet correctly" do
905
+ expect(packet.protocol_level).to eq(3)
906
+ end
907
+
908
+ it "should set the Protocol version of the packet correctly" do
909
+ expect(packet.version).to eq('3.1.0')
910
+ end
911
+
912
+ it "should set the Keep Alive Timer of the packet correctly" do
913
+ expect(packet.keep_alive).to eq(65535)
914
+ end
915
+
916
+ it "should set the Client Identifier of the packet correctly" do
917
+ expect(packet.client_id).to eq('12345678901234567890123')
918
+ expect(packet.client_id.encoding.to_s).to eq('UTF-8')
919
+ end
920
+
921
+ it "should set the Will QoS of the packet correctly" do
922
+ expect(packet.will_qos).to eq(2)
923
+ end
924
+
925
+ it "should set the Will retain flag of the packet correctly" do
926
+ expect(packet.will_retain).to be_truthy
927
+ end
928
+
929
+ it "should set the Will topic of the packet correctly" do
930
+ expect(packet.will_topic).to eq('will_topic')
931
+ expect(packet.will_topic.encoding.to_s).to eq('UTF-8')
932
+ end
933
+
934
+ it "should set the Will payload of the packet correctly" do
935
+ expect(packet.will_payload).to eq('will_message')
936
+ expect(packet.will_payload.encoding.to_s).to eq('UTF-8')
937
+ end
938
+
939
+ it "should set the Username of the packet correctly" do
940
+ expect(packet.username).to eq('user0123456789')
941
+ expect(packet.username.encoding.to_s).to eq('UTF-8')
942
+ end
943
+
944
+ it "should set the Username of the packet correctly" do
945
+ expect(packet.password).to eq('pass0123456789')
946
+ expect(packet.password.encoding.to_s).to eq('UTF-8')
947
+ end
948
+ end
949
+
950
+ describe "when parsing packet with an unknown protocol name" do
951
+ it "should raise a protocol exception" do
952
+ expect {
953
+ packet = MQTT::Packet.parse(
954
+ "\x10\x16\x00\x06FooBar\x03\x00\x00\x0a\x00\x08myclient"
955
+ )
956
+ }.to raise_error(
957
+ MQTT::ProtocolException,
958
+ "Unsupported protocol: FooBar/3"
959
+ )
960
+ end
961
+ end
962
+
963
+ describe "when parsing packet with an unknown protocol level" do
964
+ it "should raise a protocol exception" do
965
+ expect {
966
+ packet = MQTT::Packet.parse(
967
+ "\x10\x16\x00\x06MQIsdp\x02\x00\x00\x0a\x00\x08myclient"
968
+ )
969
+ }.to raise_error(
970
+ MQTT::ProtocolException,
971
+ "Unsupported protocol: MQIsdp/2"
972
+ )
973
+ end
974
+ end
975
+
976
+ describe "when parsing packet with invalid fixed header flags" do
977
+ it "should raise a protocol exception" do
978
+ expect {
979
+ MQTT::Packet.parse(
980
+ "\x13\x16\x00\x06MQIsdp\x03\x00\x00\x0a\x00\x08myclient"
981
+ )
982
+ }.to raise_error(
983
+ MQTT::ProtocolException,
984
+ "Invalid flags in CONNECT packet header"
985
+ )
986
+ end
987
+ end
988
+
989
+ describe "when calling the inspect method" do
990
+ it "should output correct string for the default options" do
991
+ packet = MQTT::Packet::Connect.new
992
+ expect(packet.inspect).to eq("#<MQTT::Packet::Connect: keep_alive=15, clean, client_id=''>")
993
+ end
994
+
995
+ it "should output correct string when parameters are given" do
996
+ packet = MQTT::Packet::Connect.new(
997
+ :keep_alive => 10,
998
+ :client_id => 'c123',
999
+ :clean_session => false,
1000
+ :username => 'foo'
1001
+ )
1002
+ expect(packet.inspect).to eq("#<MQTT::Packet::Connect: keep_alive=10, client_id='c123', username='foo'>")
1003
+ end
1004
+ end
1005
+
1006
+ describe "deprecated attributes" do
1007
+ it "should still have a protocol_version method that is that same as protocol_level" do
1008
+ packet = MQTT::Packet::Connect.new
1009
+ packet.protocol_version = 5
1010
+ expect(packet.protocol_version).to eq(5)
1011
+ expect(packet.protocol_level).to eq(5)
1012
+ packet.protocol_version = 4
1013
+ expect(packet.protocol_version).to eq(4)
1014
+ expect(packet.protocol_level).to eq(4)
1015
+ end
1016
+ end
1017
+ end
1018
+
1019
+ describe MQTT::Packet::Connack do
1020
+
1021
+ describe "when setting attributes on a packet" do
1022
+ let(:packet) { MQTT::Packet::Connack.new }
1023
+
1024
+ it "should let you change the session present flag of a packet" do
1025
+ packet.session_present = true
1026
+ expect(packet.session_present).to be_truthy
1027
+ end
1028
+
1029
+ it "should let you change the session present flag of a packet using an integer" do
1030
+ packet.session_present = 1
1031
+ expect(packet.session_present).to be_truthy
1032
+ end
1033
+
1034
+ it "should let you change the return code of a packet" do
1035
+ packet.return_code = 3
1036
+ expect(packet.return_code).to eq(3)
1037
+ end
1038
+ end
1039
+
1040
+ describe "when serialising a packet" do
1041
+ it "should output the correct bytes for a sucessful connection acknowledgement packet without Session Present set" do
1042
+ packet = MQTT::Packet::Connack.new( :return_code => 0x00, :session_present => false )
1043
+ expect(packet.to_s).to eq("\x20\x02\x00\x00")
1044
+ end
1045
+
1046
+ it "should output the correct bytes for a sucessful connection acknowledgement packet with Session Present set" do
1047
+ packet = MQTT::Packet::Connack.new( :return_code => 0x00, :session_present => true )
1048
+ expect(packet.to_s).to eq("\x20\x02\x01\x00")
1049
+ end
1050
+ end
1051
+
1052
+ describe "when parsing a successful Connection Accepted packet" do
1053
+ let(:packet) do
1054
+ MQTT::Packet.parse( "\x20\x02\x00\x00" )
1055
+ end
1056
+
1057
+ it "should correctly create the right type of packet object" do
1058
+ expect(packet.class).to eq(MQTT::Packet::Connack)
1059
+ end
1060
+
1061
+ it "should set the fixed header flags of the packet correctly" do
1062
+ expect(packet.flags).to eq([false, false, false, false])
1063
+ end
1064
+
1065
+ it "should set the Session Pression flag of the packet correctly" do
1066
+ expect(packet.session_present).to eq(false)
1067
+ end
1068
+
1069
+ it "should set the return code of the packet correctly" do
1070
+ expect(packet.return_code).to eq(0x00)
1071
+ end
1072
+
1073
+ it "should set the return message of the packet correctly" do
1074
+ expect(packet.return_msg).to match(/Connection Accepted/i)
1075
+ end
1076
+ end
1077
+
1078
+ describe "when parsing a successful Connection Accepted packet with Session Present set" do
1079
+ let(:packet) do
1080
+ MQTT::Packet.parse( "\x20\x02\x01\x00" )
1081
+ end
1082
+
1083
+ it "should correctly create the right type of packet object" do
1084
+ expect(packet.class).to eq(MQTT::Packet::Connack)
1085
+ end
1086
+
1087
+ it "should set the fixed header flags of the packet correctly" do
1088
+ expect(packet.flags).to eq([false, false, false, false])
1089
+ end
1090
+
1091
+ it "should set the Session Pression flag of the packet correctly" do
1092
+ expect(packet.session_present).to eq(true)
1093
+ end
1094
+
1095
+ it "should set the return code of the packet correctly" do
1096
+ expect(packet.return_code).to eq(0x00)
1097
+ end
1098
+
1099
+ it "should set the return message of the packet correctly" do
1100
+ expect(packet.return_msg).to match(/Connection Accepted/i)
1101
+ end
1102
+ end
1103
+
1104
+ describe "when parsing a unacceptable protocol version packet" do
1105
+ let(:packet) do
1106
+ MQTT::Packet.parse( "\x20\x02\x00\x01" )
1107
+ end
1108
+
1109
+ it "should correctly create the right type of packet object" do
1110
+ expect(packet.class).to eq(MQTT::Packet::Connack)
1111
+ end
1112
+
1113
+ it "should set the return code of the packet correctly" do
1114
+ expect(packet.return_code).to eq(0x01)
1115
+ end
1116
+
1117
+ it "should set the return message of the packet correctly" do
1118
+ expect(packet.return_msg).to match(/unacceptable protocol version/i)
1119
+ end
1120
+ end
1121
+
1122
+ describe "when parsing a client identifier rejected packet" do
1123
+ let(:packet) { MQTT::Packet.parse( "\x20\x02\x00\x02" ) }
1124
+
1125
+ it "should correctly create the right type of packet object" do
1126
+ expect(packet.class).to eq(MQTT::Packet::Connack)
1127
+ end
1128
+
1129
+ it "should set the return code of the packet correctly" do
1130
+ expect(packet.return_code).to eq(0x02)
1131
+ end
1132
+
1133
+ it "should set the return message of the packet correctly" do
1134
+ expect(packet.return_msg).to match(/client identifier rejected/i)
1135
+ end
1136
+ end
1137
+
1138
+ describe "when parsing a server unavailable packet" do
1139
+ let(:packet) do
1140
+ MQTT::Packet.parse( "\x20\x02\x00\x03" )
1141
+ end
1142
+
1143
+ it "should correctly create the right type of packet object" do
1144
+ expect(packet.class).to eq(MQTT::Packet::Connack)
1145
+ end
1146
+
1147
+ it "should set the return code of the packet correctly" do
1148
+ expect(packet.return_code).to eq(0x03)
1149
+ end
1150
+
1151
+ it "should set the return message of the packet correctly" do
1152
+ expect(packet.return_msg).to match(/server unavailable/i)
1153
+ end
1154
+ end
1155
+
1156
+ describe "when parsing a server unavailable packet" do
1157
+ let(:packet) do
1158
+ MQTT::Packet.parse( "\x20\x02\x00\x04" )
1159
+ end
1160
+
1161
+ it "should correctly create the right type of packet object" do
1162
+ expect(packet.class).to eq(MQTT::Packet::Connack)
1163
+ end
1164
+
1165
+ it "should set the return code of the packet correctly" do
1166
+ expect(packet.return_code).to eq(0x04)
1167
+ end
1168
+
1169
+ it "should set the return message of the packet correctly" do
1170
+ expect(packet.return_msg).to match(/bad user name or password/i)
1171
+ end
1172
+ end
1173
+
1174
+ describe "when parsing a server unavailable packet" do
1175
+ let(:packet) do
1176
+ MQTT::Packet.parse( "\x20\x02\x00\x05" )
1177
+ end
1178
+
1179
+ it "should correctly create the right type of packet object" do
1180
+ expect(packet.class).to eq(MQTT::Packet::Connack)
1181
+ end
1182
+
1183
+ it "should set the return code of the packet correctly" do
1184
+ expect(packet.return_code).to eq(0x05)
1185
+ end
1186
+
1187
+ it "should set the return message of the packet correctly" do
1188
+ expect(packet.return_msg).to match(/not authorised/i)
1189
+ end
1190
+ end
1191
+
1192
+ describe "when parsing an unknown connection refused packet" do
1193
+ let(:packet) { MQTT::Packet.parse( "\x20\x02\x00\x10" ) }
1194
+
1195
+ it "should correctly create the right type of packet object" do
1196
+ expect(packet.class).to eq(MQTT::Packet::Connack)
1197
+ end
1198
+
1199
+ it "should set the return code of the packet correctly" do
1200
+ expect(packet.return_code).to eq(0x10)
1201
+ end
1202
+
1203
+ it "should set the return message of the packet correctly" do
1204
+ expect(packet.return_msg).to match(/Connection refused: error code 16/i)
1205
+ end
1206
+ end
1207
+
1208
+ describe "when parsing packet with invalid Connack flags set" do
1209
+ it "should raise an exception" do
1210
+ expect {
1211
+ packet = MQTT::Packet.parse( "\x20\x02\xff\x05" )
1212
+ }.to raise_error(
1213
+ MQTT::ProtocolException,
1214
+ "Invalid flags in Connack variable header"
1215
+ )
1216
+ end
1217
+ end
1218
+
1219
+ describe "when parsing packet with extra bytes on the end" do
1220
+ it "should raise an exception" do
1221
+ expect {
1222
+ packet = MQTT::Packet.parse( "\x20\x03\x00\x00\x00" )
1223
+ }.to raise_error(
1224
+ MQTT::ProtocolException,
1225
+ "Extra bytes at end of Connect Acknowledgment packet"
1226
+ )
1227
+ end
1228
+ end
1229
+
1230
+ describe "when parsing packet with invalid fixed header flags" do
1231
+ it "should raise a protocol exception" do
1232
+ expect {
1233
+ MQTT::Packet.parse( "\x23\x02\x00\x00" )
1234
+ }.to raise_error(
1235
+ MQTT::ProtocolException,
1236
+ "Invalid flags in CONNACK packet header"
1237
+ )
1238
+ end
1239
+ end
1240
+
1241
+ describe "when calling the inspect method" do
1242
+ it "should output the right string when the return code is 0" do
1243
+ packet = MQTT::Packet::Connack.new( :return_code => 0x00 )
1244
+ expect(packet.inspect).to eq("#<MQTT::Packet::Connack: 0x00>")
1245
+ end
1246
+ it "should output the right string when the return code is 0x0F" do
1247
+ packet = MQTT::Packet::Connack.new( :return_code => 0x0F )
1248
+ expect(packet.inspect).to eq("#<MQTT::Packet::Connack: 0x0F>")
1249
+ end
1250
+ end
1251
+ end
1252
+
1253
+ describe MQTT::Packet::Puback do
1254
+ describe "when serialising a packet" do
1255
+ it "should output the correct bytes for a packet with no flags" do
1256
+ packet = MQTT::Packet::Puback.new( :id => 0x1234 )
1257
+ expect(packet.to_s).to eq("\x40\x02\x12\x34")
1258
+ end
1259
+ end
1260
+
1261
+ describe "when parsing a packet" do
1262
+ let(:packet) { MQTT::Packet.parse( "\x40\x02\x12\x34" ) }
1263
+
1264
+ it "should correctly create the right type of packet object" do
1265
+ expect(packet.class).to eq(MQTT::Packet::Puback)
1266
+ end
1267
+
1268
+ it "should set the message id of the packet correctly" do
1269
+ expect(packet.id).to eq(0x1234)
1270
+ end
1271
+ end
1272
+
1273
+ describe "when parsing packet with extra bytes on the end" do
1274
+ it "should raise an exception" do
1275
+ expect {
1276
+ packet = MQTT::Packet.parse( "\x40\x03\x12\x34\x00" )
1277
+ }.to raise_error(
1278
+ MQTT::ProtocolException,
1279
+ "Extra bytes at end of Publish Acknowledgment packet"
1280
+ )
1281
+ end
1282
+ end
1283
+
1284
+ describe "when parsing packet with invalid fixed header flags" do
1285
+ it "should raise a protocol exception" do
1286
+ expect {
1287
+ MQTT::Packet.parse( "\x43\x02\x12\x34" )
1288
+ }.to raise_error(
1289
+ MQTT::ProtocolException,
1290
+ "Invalid flags in PUBACK packet header"
1291
+ )
1292
+ end
1293
+ end
1294
+
1295
+ it "should output the right string when calling inspect" do
1296
+ packet = MQTT::Packet::Puback.new( :id => 0x1234 )
1297
+ expect(packet.inspect).to eq("#<MQTT::Packet::Puback: 0x1234>")
1298
+ end
1299
+ end
1300
+
1301
+ describe MQTT::Packet::Pubrec do
1302
+ describe "when serialising a packet" do
1303
+ it "should output the correct bytes for a packet with no flags" do
1304
+ packet = MQTT::Packet::Pubrec.new( :id => 0x1234 )
1305
+ expect(packet.to_s).to eq("\x50\x02\x12\x34")
1306
+ end
1307
+ end
1308
+
1309
+ describe "when parsing a packet" do
1310
+ let(:packet) { MQTT::Packet.parse( "\x50\x02\x12\x34" ) }
1311
+
1312
+ it "should correctly create the right type of packet object" do
1313
+ expect(packet.class).to eq(MQTT::Packet::Pubrec)
1314
+ end
1315
+
1316
+ it "should set the message id of the packet correctly" do
1317
+ expect(packet.id).to eq(0x1234)
1318
+ end
1319
+ end
1320
+
1321
+ describe "when parsing packet with extra bytes on the end" do
1322
+ it "should raise an exception" do
1323
+ expect {
1324
+ packet = MQTT::Packet.parse( "\x50\x03\x12\x34\x00" )
1325
+ }.to raise_error(
1326
+ MQTT::ProtocolException,
1327
+ "Extra bytes at end of Publish Received packet"
1328
+ )
1329
+ end
1330
+ end
1331
+
1332
+ describe "when parsing packet with invalid fixed header flags" do
1333
+ it "should raise a protocol exception" do
1334
+ expect {
1335
+ MQTT::Packet.parse( "\x53\x02\x12\x34" )
1336
+ }.to raise_error(
1337
+ MQTT::ProtocolException,
1338
+ "Invalid flags in PUBREC packet header"
1339
+ )
1340
+ end
1341
+ end
1342
+
1343
+ it "should output the right string when calling inspect" do
1344
+ packet = MQTT::Packet::Pubrec.new( :id => 0x1234 )
1345
+ expect(packet.inspect).to eq("#<MQTT::Packet::Pubrec: 0x1234>")
1346
+ end
1347
+ end
1348
+
1349
+ describe MQTT::Packet::Pubrel do
1350
+ describe "when serialising a packet" do
1351
+ it "should output the correct bytes for a packet with no flags" do
1352
+ packet = MQTT::Packet::Pubrel.new( :id => 0x1234 )
1353
+ expect(packet.to_s).to eq("\x62\x02\x12\x34")
1354
+ end
1355
+ end
1356
+
1357
+ describe "when parsing a packet" do
1358
+ let(:packet) { MQTT::Packet.parse( "\x62\x02\x12\x34" ) }
1359
+
1360
+ it "should correctly create the right type of packet object" do
1361
+ expect(packet.class).to eq(MQTT::Packet::Pubrel)
1362
+ end
1363
+
1364
+ it "should set the message id of the packet correctly" do
1365
+ expect(packet.id).to eq(0x1234)
1366
+ end
1367
+ end
1368
+
1369
+ describe "when parsing packet with extra bytes on the end" do
1370
+ it "should raise an exception" do
1371
+ expect {
1372
+ packet = MQTT::Packet.parse( "\x62\x03\x12\x34\x00" )
1373
+ }.to raise_error(
1374
+ MQTT::ProtocolException,
1375
+ "Extra bytes at end of Publish Release packet"
1376
+ )
1377
+ end
1378
+ end
1379
+
1380
+ describe "when parsing packet with invalid fixed header flags" do
1381
+ it "should raise a protocol exception" do
1382
+ expect {
1383
+ MQTT::Packet.parse( "\x60\x02\x12\x34" )
1384
+ }.to raise_error(
1385
+ MQTT::ProtocolException,
1386
+ "Invalid flags in PUBREL packet header"
1387
+ )
1388
+ end
1389
+ end
1390
+
1391
+ it "should output the right string when calling inspect" do
1392
+ packet = MQTT::Packet::Pubrel.new( :id => 0x1234 )
1393
+ expect(packet.inspect).to eq("#<MQTT::Packet::Pubrel: 0x1234>")
1394
+ end
1395
+ end
1396
+
1397
+ describe MQTT::Packet::Pubcomp do
1398
+ describe "when serialising a packet" do
1399
+ it "should output the correct bytes for a packet with no flags" do
1400
+ packet = MQTT::Packet::Pubcomp.new( :id => 0x1234 )
1401
+ expect(packet.to_s).to eq("\x70\x02\x12\x34")
1402
+ end
1403
+ end
1404
+
1405
+ describe "when parsing a packet" do
1406
+ let(:packet) { MQTT::Packet.parse( "\x70\x02\x12\x34" ) }
1407
+
1408
+ it "should correctly create the right type of packet object" do
1409
+ expect(packet.class).to eq(MQTT::Packet::Pubcomp)
1410
+ end
1411
+
1412
+ it "should set the message id of the packet correctly" do
1413
+ expect(packet.id).to eq(0x1234)
1414
+ end
1415
+ end
1416
+
1417
+ describe "when parsing packet with extra bytes on the end" do
1418
+ it "should raise an exception" do
1419
+ expect {
1420
+ MQTT::Packet.parse( "\x70\x03\x12\x34\x00" )
1421
+ }.to raise_error(
1422
+ MQTT::ProtocolException,
1423
+ "Extra bytes at end of Publish Complete packet"
1424
+ )
1425
+ end
1426
+ end
1427
+
1428
+ describe "when parsing packet with invalid fixed header flags" do
1429
+ it "should raise a protocol exception" do
1430
+ expect {
1431
+ MQTT::Packet.parse( "\x72\x02\x12\x34" )
1432
+ }.to raise_error(
1433
+ MQTT::ProtocolException,
1434
+ "Invalid flags in PUBCOMP packet header"
1435
+ )
1436
+ end
1437
+ end
1438
+
1439
+ it "should output the right string when calling inspect" do
1440
+ packet = MQTT::Packet::Pubcomp.new( :id => 0x1234 )
1441
+ expect(packet.inspect).to eq("#<MQTT::Packet::Pubcomp: 0x1234>")
1442
+ end
1443
+ end
1444
+
1445
+ describe MQTT::Packet::Subscribe do
1446
+ describe "setting the packet's topics" do
1447
+ let(:packet) { MQTT::Packet::Subscribe.new }
1448
+
1449
+ it "should be able to set the topics from a String 'a/b'" do
1450
+ packet.topics = 'a/b'
1451
+ expect(packet.topics).to eq([["a/b", 0]])
1452
+ end
1453
+
1454
+ it "should be able to set the multiple topics from an array ['a/b', 'b/c']" do
1455
+ packet.topics = ['a/b', 'b/c']
1456
+ expect(packet.topics).to eq([["a/b", 0], ['b/c', 0]])
1457
+ end
1458
+
1459
+ it "should be able to set the topics from a Hash {'a/b' => 0, 'b/c' => 1}" do
1460
+ packet.topics = {'a/b' => 0, 'b/c' => 1}
1461
+ expect(packet.topics).to eq([["a/b", 0], ["b/c", 1]])
1462
+ end
1463
+
1464
+ it "should be able to set the topics from a single level array ['a/b', 0]" do
1465
+ packet.topics = ['a/b', 0]
1466
+ expect(packet.topics).to eq([["a/b", 0]])
1467
+ end
1468
+
1469
+ it "should be able to set the topics from a two level array [['a/b' => 0], ['b/c' => 1]]" do
1470
+ packet.topics = [['a/b', 0], ['b/c', 1]]
1471
+ expect(packet.topics).to eq([['a/b', 0], ['b/c', 1]])
1472
+ end
1473
+
1474
+ it "should raise an exception when setting topic with a non-string" do
1475
+ expect {
1476
+ packet.topics = 56
1477
+ }.to raise_error(
1478
+ 'Invalid topics input: 56'
1479
+ )
1480
+ end
1481
+ end
1482
+
1483
+ describe "when serialising a packet" do
1484
+ it "should output the correct bytes for a packet with a single topic" do
1485
+ packet = MQTT::Packet::Subscribe.new( :id => 1, :topics => 'a/b' )
1486
+ expect(packet.to_s).to eq("\x82\x08\x00\x01\x00\x03a/b\x00")
1487
+ end
1488
+
1489
+ it "should output the correct bytes for a packet with multiple topics" do
1490
+ packet = MQTT::Packet::Subscribe.new( :id => 6, :topics => [['a/b', 0], ['c/d', 1]] )
1491
+ expect(packet.to_s).to eq("\x82\x0e\000\x06\x00\x03a/b\x00\x00\x03c/d\x01")
1492
+ end
1493
+
1494
+ it "should raise an exception when no topics are given" do
1495
+ expect {
1496
+ MQTT::Packet::Subscribe.new.to_s
1497
+ }.to raise_error(
1498
+ 'no topics given when serialising packet'
1499
+ )
1500
+ end
1501
+ end
1502
+
1503
+ describe "when parsing a packet with a single topic" do
1504
+ let(:packet) { MQTT::Packet.parse( "\x82\x08\x00\x01\x00\x03a/b\x00" ) }
1505
+
1506
+ it "should correctly create the right type of packet object" do
1507
+ expect(packet.class).to eq(MQTT::Packet::Subscribe)
1508
+ end
1509
+
1510
+ it "should set the fixed header flags of the packet correctly" do
1511
+ expect(packet.flags).to eq([false, true, false, false])
1512
+ end
1513
+
1514
+ it "should set the Message ID correctly" do
1515
+ expect(packet.id).to eq(1)
1516
+ end
1517
+
1518
+ it "should set the topic name correctly" do
1519
+ expect(packet.topics).to eq([['a/b',0]])
1520
+ end
1521
+ end
1522
+
1523
+ describe "when parsing a packet with a two topics" do
1524
+ let(:packet) { MQTT::Packet.parse( "\x82\x0e\000\x06\x00\x03a/b\x00\x00\x03c/d\x01" ) }
1525
+
1526
+ it "should correctly create the right type of packet object" do
1527
+ expect(packet.class).to eq(MQTT::Packet::Subscribe)
1528
+ end
1529
+
1530
+ it "should set the fixed header flags of the packet correctly" do
1531
+ expect(packet.flags).to eq([false, true, false, false])
1532
+ end
1533
+
1534
+ it "should set the Message ID correctly" do
1535
+ expect(packet.id).to eq(6)
1536
+ end
1537
+
1538
+ it "should set the topic name correctly" do
1539
+ expect(packet.topics).to eq([['a/b',0],['c/d',1]])
1540
+ end
1541
+ end
1542
+
1543
+ describe "when parsing packet with invalid fixed header flags" do
1544
+ it "should raise a protocol exception" do
1545
+ expect {
1546
+ MQTT::Packet.parse( "\x80\x08\x00\x01\x00\x03a/b\x00" )
1547
+ }.to raise_error(
1548
+ MQTT::ProtocolException,
1549
+ "Invalid flags in SUBSCRIBE packet header"
1550
+ )
1551
+ end
1552
+ end
1553
+
1554
+ describe "when calling the inspect method" do
1555
+ it "should output correct string for a single topic" do
1556
+ packet = MQTT::Packet::Subscribe.new(:topics => 'test')
1557
+ expect(packet.inspect).to eq("#<MQTT::Packet::Subscribe: 0x00, 'test':0>")
1558
+ end
1559
+
1560
+ it "should output correct string for multiple topics" do
1561
+ packet = MQTT::Packet::Subscribe.new(:topics => {'a' => 1, 'b' => 0, 'c' => 2})
1562
+ expect(packet.inspect).to eq("#<MQTT::Packet::Subscribe: 0x00, 'a':1, 'b':0, 'c':2>")
1563
+ end
1564
+ end
1565
+ end
1566
+
1567
+ describe MQTT::Packet::Suback do
1568
+ describe "when serialising a packet" do
1569
+ it "should output the correct bytes for an acknowledgement to a single topic" do
1570
+ packet = MQTT::Packet::Suback.new( :id => 5, :return_codes => 0 )
1571
+ expect(packet.to_s).to eq("\x90\x03\x00\x05\x00")
1572
+ end
1573
+
1574
+ it "should output the correct bytes for an acknowledgement to a two topics" do
1575
+ packet = MQTT::Packet::Suback.new( :id => 6 , :return_codes => [0,1] )
1576
+ expect(packet.to_s).to eq("\x90\x04\x00\x06\x00\x01")
1577
+ end
1578
+
1579
+ it "should raise an exception when no granted QoSs are given" do
1580
+ expect {
1581
+ MQTT::Packet::Suback.new( :id => 7 ).to_s
1582
+ }.to raise_error(
1583
+ 'no granted QoS given when serialising packet'
1584
+ )
1585
+ end
1586
+
1587
+ it "should raise an exception if the granted QoS is not an integer" do
1588
+ expect {
1589
+ MQTT::Packet::Suback.new( :id => 8, :return_codes => :foo ).to_s
1590
+ }.to raise_error(
1591
+ 'return_codes should be an integer or an array of return codes'
1592
+ )
1593
+ end
1594
+ end
1595
+
1596
+ describe "when parsing a packet with a single QoS value of 0" do
1597
+ let(:packet) { MQTT::Packet.parse( "\x90\x03\x12\x34\x00" ) }
1598
+
1599
+ it "should correctly create the right type of packet object" do
1600
+ expect(packet.class).to eq(MQTT::Packet::Suback)
1601
+ end
1602
+
1603
+ it "should set the message id of the packet correctly" do
1604
+ expect(packet.id).to eq(0x1234)
1605
+ end
1606
+
1607
+ it "should set the Granted QoS of the packet correctly" do
1608
+ expect(packet.return_codes).to eq([0])
1609
+ end
1610
+ end
1611
+
1612
+ describe "when parsing a packet with two QoS values" do
1613
+ let(:packet) { MQTT::Packet.parse( "\x90\x04\x12\x34\x01\x01" ) }
1614
+
1615
+ it "should correctly create the right type of packet object" do
1616
+ expect(packet.class).to eq(MQTT::Packet::Suback)
1617
+ end
1618
+
1619
+ it "should set the message id of the packet correctly" do
1620
+ expect(packet.id).to eq(0x1234)
1621
+ end
1622
+
1623
+ it "should set the Granted QoS of the packet correctly" do
1624
+ expect(packet.return_codes).to eq([1,1])
1625
+ end
1626
+ end
1627
+
1628
+ describe "when parsing packet with invalid fixed header flags" do
1629
+ it "should raise a protocol exception" do
1630
+ expect {
1631
+ MQTT::Packet.parse( "\x92\x03\x12\x34\x00" )
1632
+ }.to raise_error(
1633
+ MQTT::ProtocolException,
1634
+ "Invalid flags in SUBACK packet header"
1635
+ )
1636
+ end
1637
+ end
1638
+
1639
+ describe "when calling the inspect method" do
1640
+ it "should output correct string for a single granted qos" do
1641
+ packet = MQTT::Packet::Suback.new(:id => 0x1234, :return_codes => 0)
1642
+ expect(packet.inspect).to eq("#<MQTT::Packet::Suback: 0x1234, rc=0x00>")
1643
+ end
1644
+
1645
+ it "should output correct string for multiple topics" do
1646
+ packet = MQTT::Packet::Suback.new(:id => 0x1235, :return_codes => [0,1,2])
1647
+ expect(packet.inspect).to eq("#<MQTT::Packet::Suback: 0x1235, rc=0x00,0x01,0x02>")
1648
+ end
1649
+ end
1650
+
1651
+ describe "deprecated attributes" do
1652
+ it "should still have a granted_qos method that is that same as return_codes" do
1653
+ packet = MQTT::Packet::Suback.new
1654
+ packet.granted_qos = [0,1,2]
1655
+ expect(packet.granted_qos).to eq([0,1,2])
1656
+ expect(packet.return_codes).to eq([0,1,2])
1657
+ packet.return_codes = [0,1,0]
1658
+ expect(packet.granted_qos).to eq([0,1,0])
1659
+ expect(packet.return_codes).to eq([0,1,0])
1660
+ end
1661
+ end
1662
+ end
1663
+
1664
+ describe MQTT::Packet::Unsubscribe do
1665
+ describe "when serialising a packet" do
1666
+ it "should output the correct bytes for a packet with single topic" do
1667
+ packet = MQTT::Packet::Unsubscribe.new( :id => 5, :topics => 'a/b' )
1668
+ expect(packet.to_s).to eq("\xa2\x07\x00\x05\x00\x03a/b")
1669
+ end
1670
+
1671
+ it "should output the correct bytes for a packet with multiple topics" do
1672
+ packet = MQTT::Packet::Unsubscribe.new( :id => 6, :topics => ['a/b','c/d'] )
1673
+ expect(packet.to_s).to eq("\xa2\x0c\000\006\000\003a/b\000\003c/d")
1674
+ end
1675
+
1676
+ it "should raise an exception when no topics are given" do
1677
+ expect {
1678
+ MQTT::Packet::Unsubscribe.new.to_s
1679
+ }.to raise_error(
1680
+ 'no topics given when serialising packet'
1681
+ )
1682
+ end
1683
+ end
1684
+
1685
+ describe "when parsing a packet" do
1686
+ let(:packet) { MQTT::Packet.parse( "\xa2\f\000\005\000\003a/b\000\003c/d" ) }
1687
+
1688
+ it "should correctly create the right type of packet object" do
1689
+ expect(packet.class).to eq(MQTT::Packet::Unsubscribe)
1690
+ end
1691
+
1692
+ it "should set the fixed header flags of the packet correctly" do
1693
+ expect(packet.flags).to eq([false, true, false, false])
1694
+ end
1695
+
1696
+ it "should set the topic name correctly" do
1697
+ expect(packet.topics).to eq(['a/b','c/d'])
1698
+ end
1699
+ end
1700
+
1701
+ describe "when parsing packet with invalid fixed header flags" do
1702
+ it "should raise a protocol exception" do
1703
+ expect {
1704
+ MQTT::Packet.parse( "\xa0\x07\x00\x05\x00\x03a/b" )
1705
+ }.to raise_error(
1706
+ MQTT::ProtocolException,
1707
+ "Invalid flags in UNSUBSCRIBE packet header"
1708
+ )
1709
+ end
1710
+ end
1711
+
1712
+ describe "when calling the inspect method" do
1713
+ it "should output correct string for a single topic" do
1714
+ packet = MQTT::Packet::Unsubscribe.new(:topics => 'test')
1715
+ expect(packet.inspect).to eq("#<MQTT::Packet::Unsubscribe: 0x00, 'test'>")
1716
+ end
1717
+
1718
+ it "should output correct string for multiple topics" do
1719
+ packet = MQTT::Packet::Unsubscribe.new( :id => 42, :topics => ['a', 'b', 'c'] )
1720
+ expect(packet.inspect).to eq("#<MQTT::Packet::Unsubscribe: 0x2A, 'a', 'b', 'c'>")
1721
+ end
1722
+ end
1723
+ end
1724
+
1725
+ describe MQTT::Packet::Unsuback do
1726
+ describe "when serialising a packet" do
1727
+ it "should output the correct bytes for a packet with no flags" do
1728
+ packet = MQTT::Packet::Unsuback.new( :id => 0x1234 )
1729
+ expect(packet.to_s).to eq("\xB0\x02\x12\x34")
1730
+ end
1731
+ end
1732
+
1733
+ describe "when parsing a packet" do
1734
+ let(:packet) do
1735
+ MQTT::Packet.parse( "\xB0\x02\x12\x34" )
1736
+ end
1737
+
1738
+ it "should correctly create the right type of packet object" do
1739
+ expect(packet.class).to eq(MQTT::Packet::Unsuback)
1740
+ end
1741
+
1742
+ it "should set the message id of the packet correctly" do
1743
+ expect(packet.id).to eq(0x1234)
1744
+ end
1745
+ end
1746
+
1747
+ describe "when parsing packet with extra bytes on the end" do
1748
+ it "should raise an exception" do
1749
+ expect {
1750
+ packet = MQTT::Packet.parse( "\xB0\x03\x12\x34\x00" )
1751
+ }.to raise_error(
1752
+ MQTT::ProtocolException,
1753
+ "Extra bytes at end of Unsubscribe Acknowledgment packet"
1754
+ )
1755
+ end
1756
+ end
1757
+
1758
+ describe "when parsing packet with invalid fixed header flags" do
1759
+ it "should raise a protocol exception" do
1760
+ expect {
1761
+ MQTT::Packet.parse( "\xB2\x02\x12\x34" )
1762
+ }.to raise_error(
1763
+ MQTT::ProtocolException,
1764
+ "Invalid flags in UNSUBACK packet header"
1765
+ )
1766
+ end
1767
+ end
1768
+
1769
+ it "should output the right string when calling inspect" do
1770
+ packet = MQTT::Packet::Unsuback.new( :id => 0x1234 )
1771
+ expect(packet.inspect).to eq("#<MQTT::Packet::Unsuback: 0x1234>")
1772
+ end
1773
+ end
1774
+
1775
+ describe MQTT::Packet::Pingreq do
1776
+ describe "when serialising a packet" do
1777
+ it "should output the correct bytes for a packet with no flags" do
1778
+ packet = MQTT::Packet::Pingreq.new
1779
+ expect(packet.to_s).to eq("\xC0\x00")
1780
+ end
1781
+ end
1782
+
1783
+ describe "when parsing a packet" do
1784
+ it "should correctly create the right type of packet object" do
1785
+ packet = MQTT::Packet.parse( "\xC0\x00" )
1786
+ expect(packet.class).to eq(MQTT::Packet::Pingreq)
1787
+ end
1788
+
1789
+ it "should raise an exception if the packet has a payload" do
1790
+ expect {
1791
+ MQTT::Packet.parse( "\xC0\x05hello" )
1792
+ }.to raise_error(
1793
+ 'Extra bytes at end of Ping Request packet'
1794
+ )
1795
+ end
1796
+ end
1797
+
1798
+ describe "when parsing packet with invalid fixed header flags" do
1799
+ it "should raise a protocol exception" do
1800
+ expect {
1801
+ MQTT::Packet.parse( "\xC2\x00" )
1802
+ }.to raise_error(
1803
+ MQTT::ProtocolException,
1804
+ "Invalid flags in PINGREQ packet header"
1805
+ )
1806
+ end
1807
+ end
1808
+
1809
+ it "should output the right string when calling inspect" do
1810
+ packet = MQTT::Packet::Pingreq.new
1811
+ expect(packet.inspect).to eq("#<MQTT::Packet::Pingreq>")
1812
+ end
1813
+ end
1814
+
1815
+ describe MQTT::Packet::Pingresp do
1816
+ describe "when serialising a packet" do
1817
+ it "should output the correct bytes for a packet with no flags" do
1818
+ packet = MQTT::Packet::Pingresp.new
1819
+ expect(packet.to_s).to eq("\xD0\x00")
1820
+ end
1821
+ end
1822
+
1823
+ describe "when parsing a packet" do
1824
+ it "should correctly create the right type of packet object" do
1825
+ packet = MQTT::Packet.parse( "\xD0\x00" )
1826
+ expect(packet.class).to eq(MQTT::Packet::Pingresp)
1827
+ end
1828
+
1829
+ it "should raise an exception if the packet has a payload" do
1830
+ expect {
1831
+ MQTT::Packet.parse( "\xD0\x05hello" )
1832
+ }.to raise_error(
1833
+ 'Extra bytes at end of Ping Response packet'
1834
+ )
1835
+ end
1836
+ end
1837
+
1838
+ describe "when parsing packet with invalid fixed header flags" do
1839
+ it "should raise a protocol exception" do
1840
+ expect {
1841
+ MQTT::Packet.parse( "\xD2\x00" )
1842
+ }.to raise_error(
1843
+ MQTT::ProtocolException,
1844
+ "Invalid flags in PINGRESP packet header"
1845
+ )
1846
+ end
1847
+ end
1848
+
1849
+ it "should output the right string when calling inspect" do
1850
+ packet = MQTT::Packet::Pingresp.new
1851
+ expect(packet.inspect).to eq("#<MQTT::Packet::Pingresp>")
1852
+ end
1853
+ end
1854
+
1855
+
1856
+ describe MQTT::Packet::Disconnect do
1857
+ describe "when serialising a packet" do
1858
+ it "should output the correct bytes for a packet with no flags" do
1859
+ packet = MQTT::Packet::Disconnect.new
1860
+ expect(packet.to_s).to eq("\xE0\x00")
1861
+ end
1862
+ end
1863
+
1864
+ describe "when parsing a packet" do
1865
+ it "should correctly create the right type of packet object" do
1866
+ packet = MQTT::Packet.parse( "\xE0\x00" )
1867
+ expect(packet.class).to eq(MQTT::Packet::Disconnect)
1868
+ end
1869
+
1870
+ it "should raise an exception if the packet has a payload" do
1871
+ expect {
1872
+ MQTT::Packet.parse( "\xE0\x05hello" )
1873
+ }.to raise_error(
1874
+ 'Extra bytes at end of Disconnect packet'
1875
+ )
1876
+ end
1877
+ end
1878
+
1879
+ describe "when parsing packet with invalid fixed header flags" do
1880
+ it "should raise a protocol exception" do
1881
+ expect {
1882
+ MQTT::Packet.parse( "\xE2\x00" )
1883
+ }.to raise_error(
1884
+ MQTT::ProtocolException,
1885
+ "Invalid flags in DISCONNECT packet header"
1886
+ )
1887
+ end
1888
+ end
1889
+
1890
+ it "should output the right string when calling inspect" do
1891
+ packet = MQTT::Packet::Disconnect.new
1892
+ expect(packet.inspect).to eq("#<MQTT::Packet::Disconnect>")
1893
+ end
1894
+ end
1895
+
1896
+
1897
+ describe "Serialising an invalid packet" do
1898
+ context "that has a no type" do
1899
+ it "should raise an exception" do
1900
+ expect {
1901
+ MQTT::Packet.new.to_s
1902
+ }.to raise_error(
1903
+ RuntimeError,
1904
+ "Invalid packet type: MQTT::Packet"
1905
+ )
1906
+ end
1907
+ end
1908
+ end
1909
+
1910
+ describe "Reading in an invalid packet from a socket" do
1911
+ context "that has 0 length" do
1912
+ it "should raise an exception" do
1913
+ expect {
1914
+ socket = StringIO.new
1915
+ MQTT::Packet.read(socket)
1916
+ }.to raise_error(
1917
+ MQTT::ProtocolException,
1918
+ "Failed to read byte from socket"
1919
+ )
1920
+ end
1921
+ end
1922
+
1923
+ context "that has an incomplete packet length header" do
1924
+ it "should raise an exception" do
1925
+ expect {
1926
+ socket = StringIO.new("\x30\xFF")
1927
+ MQTT::Packet.read(socket)
1928
+ }.to raise_error(
1929
+ MQTT::ProtocolException,
1930
+ "Failed to read byte from socket"
1931
+ )
1932
+ end
1933
+ end
1934
+
1935
+ context "that has the maximum number of bytes in the length header" do
1936
+ it "should raise an exception" do
1937
+ expect {
1938
+ socket = StringIO.new("\x30\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF")
1939
+ MQTT::Packet.read(socket)
1940
+ }.to raise_error(
1941
+ MQTT::ProtocolException,
1942
+ "Failed to parse packet - input buffer (4) is not the same as the body length header (268435455)"
1943
+ )
1944
+ end
1945
+ end
1946
+ end
1947
+
1948
+ describe "Parsing an invalid packet" do
1949
+ context "that has no length" do
1950
+ it "should raise an exception" do
1951
+ expect {
1952
+ MQTT::Packet.parse( "" )
1953
+ }.to raise_error(
1954
+ MQTT::ProtocolException,
1955
+ "Invalid packet: less than 2 bytes long"
1956
+ )
1957
+ end
1958
+ end
1959
+
1960
+ context "that has an invalid type identifier" do
1961
+ it "should raise an exception" do
1962
+ expect {
1963
+ MQTT::Packet.parse( "\x00\x00" )
1964
+ }.to raise_error(
1965
+ MQTT::ProtocolException,
1966
+ "Invalid packet type identifier: 0"
1967
+ )
1968
+ end
1969
+ end
1970
+
1971
+ context "that has an incomplete packet length header" do
1972
+ it "should raise an exception" do
1973
+ expect {
1974
+ MQTT::Packet.parse( "\x30\xFF" )
1975
+ }.to raise_error(
1976
+ MQTT::ProtocolException,
1977
+ "The packet length header is incomplete"
1978
+ )
1979
+ end
1980
+ end
1981
+
1982
+ context "that has too many bytes in the length field" do
1983
+ it "should raise an exception" do
1984
+ expect {
1985
+ MQTT::Packet.parse( "\x30\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" )
1986
+ }.to raise_error(
1987
+ MQTT::ProtocolException,
1988
+ 'Failed to parse packet - input buffer (4) is not the same as the body length header (268435455)'
1989
+ )
1990
+ end
1991
+ end
1992
+
1993
+ context "that has a bigger buffer than expected" do
1994
+ it "should raise an exception" do
1995
+ expect {
1996
+ MQTT::Packet.parse( "\x30\x11\x00\x04testhello big world" )
1997
+ }.to raise_error(
1998
+ MQTT::ProtocolException,
1999
+ "Failed to parse packet - input buffer (21) is not the same as the body length header (17)"
2000
+ )
2001
+ end
2002
+ end
2003
+
2004
+ context "that has a smaller buffer than expected" do
2005
+ it "should raise an exception" do
2006
+ expect {
2007
+ MQTT::Packet.parse( "\x30\x11\x00\x04testhello" )
2008
+ }.to raise_error(
2009
+ MQTT::ProtocolException,
2010
+ "Failed to parse packet - input buffer (11) is not the same as the body length header (17)"
2011
+ )
2012
+ end
2013
+ end
2014
+ end