go-mqtt 0.0.1

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