mqtt 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,30 @@
1
+ # Monkey patch to add stubbed string encoding functions to Ruby 1.8
2
+
3
+ class String
4
+ def force_encoding(encoding)
5
+ @encoding = encoding
6
+ self
7
+ end
8
+
9
+ def encoding
10
+ @encoding ||= Encoding::ASCII_8BIT
11
+ end
12
+
13
+ def encode(encoding)
14
+ new = self.dup
15
+ new.force_encoding(encoding)
16
+ end
17
+ end
18
+
19
+ class Encoding
20
+ def initialize(name)
21
+ @name = name
22
+ end
23
+
24
+ def to_s
25
+ @name
26
+ end
27
+
28
+ UTF_8 = Encoding.new("UTF-8")
29
+ ASCII_8BIT = Encoding.new("ASCII-8BIT")
30
+ end
@@ -1,3 +1,3 @@
1
1
  module MQTT
2
- VERSION = "0.0.9"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -63,7 +63,7 @@ describe MQTT::Client do
63
63
  end
64
64
  end
65
65
 
66
- describe "when calling the 'connect' method" do
66
+ describe "when calling the 'connect' method on a client" do
67
67
  before(:each) do
68
68
  TCPSocket.stub(:new).and_return(@socket)
69
69
  Thread.stub(:new)
@@ -160,6 +160,30 @@ describe MQTT::Client do
160
160
 
161
161
  end
162
162
 
163
+ describe "calling 'connect' on the class" do
164
+ before(:each) do
165
+ TCPSocket.stub(:new).and_return(@socket)
166
+ MQTT::Client.stub(:new).and_return(@client)
167
+ Thread.stub(:new)
168
+ @client.stub(:receive_connack)
169
+ end
170
+
171
+ it "should create a new client object" do
172
+ MQTT::Client.should_receive(:new).once
173
+ MQTT::Client.connect
174
+ end
175
+
176
+ it "should call connect new client object" do
177
+ @client.should_receive(:connect).once
178
+ MQTT::Client.connect
179
+ end
180
+
181
+ it "should return the new client object" do
182
+ client = MQTT::Client.connect
183
+ client.class.should == MQTT::Client
184
+ end
185
+ end
186
+
163
187
  describe "when calling the 'receive_connack' method" do
164
188
  before(:each) do
165
189
  @client.instance_variable_set(:@socket, @socket)
@@ -302,7 +326,7 @@ describe MQTT::Client do
302
326
  @socket.string.should == "\x82\x0e\x00\x01\x00\x03a/b\x00\x00\x03c/d\x01"
303
327
  end
304
328
  end
305
-
329
+
306
330
  describe "when calling the 'queue_length' method" do
307
331
  it "should return 0 if there are no incoming messages waiting" do
308
332
  @client.queue_length.should == 0
@@ -320,7 +344,6 @@ describe MQTT::Client do
320
344
  end
321
345
  end
322
346
 
323
-
324
347
  describe "when calling the 'queue_emtpy?' method" do
325
348
  it "should return return true if there no incoming messages waiting" do
326
349
  @client.queue_empty?.should be_true
@@ -351,6 +374,59 @@ describe MQTT::Client do
351
374
  payload.should == 'payload1'
352
375
  @client.queue_empty?.should be_true
353
376
  end
377
+
378
+ context "with a block" do
379
+ it "should successfull receive a more than 1 message" do
380
+ inject_packet(:topic => 'topic0', :payload => 'payload0')
381
+ inject_packet(:topic => 'topic1', :payload => 'payload1')
382
+ payloads = []
383
+ @client.get do |topic,payload|
384
+ payloads << payload
385
+ break if payloads.size > 1
386
+ end
387
+ payloads.size.should == 2
388
+ payloads.should == ['payload0', 'payload1']
389
+ end
390
+ end
391
+ end
392
+
393
+ describe "when calling the 'get_packet' method" do
394
+ before(:each) do
395
+ @client.instance_variable_set(:@socket, @socket)
396
+ end
397
+
398
+ it "should successfull receive a valid PUBLISH packet with a QoS 0" do
399
+ inject_packet(:topic => 'topic0', :payload => 'payload0', :qos => 0)
400
+ packet = @client.get_packet
401
+ packet.class.should == MQTT::Packet::Publish
402
+ packet.qos.should == 0
403
+ packet.topic.should == 'topic0'
404
+ packet.payload.should == 'payload0'
405
+ end
406
+
407
+ it "should successfull receive a valid PUBLISH packet with a QoS 1" do
408
+ inject_packet(:topic => 'topic1', :payload => 'payload1', :qos => 1)
409
+ packet = @client.get_packet
410
+ packet.class.should == MQTT::Packet::Publish
411
+ packet.qos.should == 1
412
+ packet.topic.should == 'topic1'
413
+ packet.payload.should == 'payload1'
414
+ @client.queue_empty?.should be_true
415
+ end
416
+
417
+ context "with a block" do
418
+ it "should successfull receive a more than 1 packet" do
419
+ inject_packet(:topic => 'topic0', :payload => 'payload0')
420
+ inject_packet(:topic => 'topic1', :payload => 'payload1')
421
+ packets = []
422
+ @client.get_packet do |packet|
423
+ packets << packet
424
+ break if packets.size > 1
425
+ end
426
+ packets.size.should == 2
427
+ packets.map{|p| p.payload}.should == ['payload0', 'payload1']
428
+ end
429
+ end
354
430
  end
355
431
 
356
432
  describe "when calling the 'unsubscribe' method" do
@@ -1,3 +1,6 @@
1
+ # encoding: BINARY
2
+ # Encoding is set to binary, so that the binary packets aren't validated as UTF-8
3
+
1
4
  $:.unshift(File.dirname(__FILE__))
2
5
 
3
6
  require 'spec_helper'
@@ -20,6 +23,27 @@ describe MQTT::Packet do
20
23
  packet = MQTT::Packet.new( :retain => true )
21
24
  packet.retain.should be_true
22
25
  end
26
+
27
+ it "should have a custom inspect method" do
28
+ packet = MQTT::Packet.new
29
+ packet.inspect.should == '#<MQTT::Packet>'
30
+ end
31
+
32
+ it "should throw an exception the QoS is greater than 2" do
33
+ lambda {
34
+ packet = MQTT::Packet.new( :qos => 3 )
35
+ }.should raise_error(
36
+ 'Invalid QoS value: 3'
37
+ )
38
+ end
39
+
40
+ it "should throw an exception the QoS is less than 0" do
41
+ lambda {
42
+ packet = MQTT::Packet.new( :qos => -1 )
43
+ }.should raise_error(
44
+ 'Invalid QoS value: -1'
45
+ )
46
+ end
23
47
  end
24
48
 
25
49
  describe "when setting packet parameters" do
@@ -76,11 +100,13 @@ describe MQTT::Packet do
76
100
  it "should provide a add_short method to get a big-endian unsigned 16-bit integer" do
77
101
  data = @packet.send(:encode_short, 1024)
78
102
  data.should == "\x04\x00"
103
+ data.encoding.to_s.should == "ASCII-8BIT"
79
104
  end
80
105
 
81
106
  it "should provide a add_string method to get a string preceeded by its length" do
82
107
  data = @packet.send(:encode_string, 'quack')
83
108
  data.should == "\x00\x05quack"
109
+ data.encoding.to_s.should == "ASCII-8BIT"
84
110
  end
85
111
 
86
112
  it "should provide a shift_short method to get a 16-bit unsigned integer" do
@@ -125,6 +151,16 @@ describe MQTT::Packet::Publish do
125
151
  packet.to_s.should == "\x3C\x12\x00\x03c/d\x00\x05hello world"
126
152
  end
127
153
 
154
+ it "should output a string as binary / 8-bit ASCII" do
155
+ packet = MQTT::Packet::Publish.new( :topic => 'test', :payload => 'hello world' )
156
+ packet.to_s.encoding.to_s.should == "ASCII-8BIT"
157
+ end
158
+
159
+ it "should support passing in non-strings to the topic and payload" do
160
+ packet = MQTT::Packet::Publish.new( :topic => :symbol, :payload => 1234 )
161
+ packet.to_s.should == "\x30\x0c\x00\x06symbol1234"
162
+ end
163
+
128
164
  it "should throw an exception when there is no topic name" do
129
165
  lambda {
130
166
  MQTT::Packet::Publish.new.to_s
@@ -132,6 +168,25 @@ describe MQTT::Packet::Publish do
132
168
  'Invalid topic name when serialising packet'
133
169
  )
134
170
  end
171
+
172
+ it "should throw an exception when there is an empty topic name" do
173
+ lambda {
174
+ MQTT::Packet::Publish.new( :topic => '' ).to_s
175
+ }.should raise_error(
176
+ 'Invalid topic name when serialising packet'
177
+ )
178
+ end
179
+ end
180
+
181
+ describe "when serialising an oversized packet" do
182
+ it "should throw an exception when body is bigger than 256MB" do
183
+ lambda {
184
+ packet = MQTT::Packet::Publish.new( :topic => 'test', :payload => 'x'*268435455 )
185
+ packet.to_s
186
+ }.should raise_error(
187
+ 'Error serialising packet: body is more than 256MB'
188
+ )
189
+ end
135
190
  end
136
191
 
137
192
  describe "when parsing a packet with QOS 0" do
@@ -157,10 +212,12 @@ describe MQTT::Packet::Publish do
157
212
 
158
213
  it "should set the topic name correctly" do
159
214
  @packet.topic.should == 'test'
215
+ @packet.topic.encoding.to_s.should == 'UTF-8'
160
216
  end
161
217
 
162
218
  it "should set the payload correctly" do
163
219
  @packet.payload.should == 'hello world'
220
+ @packet.payload.encoding.to_s.should == 'ASCII-8BIT'
164
221
  end
165
222
  end
166
223
 
@@ -187,10 +244,22 @@ describe MQTT::Packet::Publish do
187
244
 
188
245
  it "should set the topic name correctly" do
189
246
  @packet.topic.should == 'c/d'
247
+ @packet.topic.encoding.to_s.should == 'UTF-8'
190
248
  end
191
249
 
192
250
  it "should set the payload correctly" do
193
251
  @packet.payload.should == 'hello world'
252
+ @packet.payload.encoding.to_s.should == 'ASCII-8BIT'
253
+ end
254
+ end
255
+
256
+ describe "when parsing a packet with a invalid QoS value" do
257
+ it "should throw an exception" do
258
+ lambda {
259
+ packet = MQTT::Packet.parse( "\x36\x12\x00\x03a/b\x00\x05hello world" )
260
+ }.should raise_error(
261
+ 'Invalid QoS value: 3'
262
+ )
194
263
  end
195
264
  end
196
265
 
@@ -211,7 +280,7 @@ describe MQTT::Packet::Publish do
211
280
  end
212
281
 
213
282
  it "should get the body length correctly" do
214
- @packet.payload.size.should == 314
283
+ @packet.payload.bytesize.should == 314
215
284
  end
216
285
  end
217
286
 
@@ -233,10 +302,95 @@ describe MQTT::Packet::Publish do
233
302
  end
234
303
 
235
304
  it "should get the body length correctly" do
236
- @packet.payload.size.should == 16384
305
+ @packet.payload.bytesize.should == 16384
306
+ end
307
+ end
308
+
309
+ describe "processing a packet containing UTF-8 character" do
310
+ before(:each) do
311
+ @packet = MQTT::Packet::Publish.new(
312
+ :topic => "Test ①".force_encoding("UTF-8"),
313
+ :payload => "Snowman: ☃".force_encoding("UTF-8")
314
+ )
315
+ end
316
+
317
+ it "should have the correct topic byte length" do
318
+ @packet.topic.bytesize.should == 8
319
+ end
320
+
321
+ it "should have the correct topic string length", :unless => RUBY_VERSION =~ /^1\.8/ do
322
+ # Ruby 1.8 doesn't support UTF-8 properly
323
+ @packet.topic.length.should == 6
324
+ end
325
+
326
+ it "should have the correct payload byte length" do
327
+ @packet.payload.bytesize.should == 12
328
+ end
329
+
330
+ it "should have the correct payload string length", :unless => RUBY_VERSION =~ /^1\.8/ do
331
+ # Ruby 1.8 doesn't support UTF-8 properly
332
+ @packet.payload.length.should == 10
333
+ end
334
+
335
+ it "should encode to MQTT packet correctly" do
336
+ @packet.to_s.should == "\x30\x16\x00\x08Test \xE2\x91\xA0Snowman: \xE2\x98\x83".force_encoding('BINARY')
337
+ end
338
+
339
+ it "should parse the serialised packet" do
340
+ packet2 = MQTT::Packet.parse( @packet.to_s )
341
+ packet2.topic.should == "Test ①".force_encoding('UTF-8')
342
+ packet2.payload.should == "Snowman: ☃".force_encoding('BINARY')
343
+ end
344
+ end
345
+
346
+ describe "reading a packet from a socket" do
347
+ before(:each) do
348
+ @socket = StringIO.new("\x30\x11\x00\x04testhello world")
349
+ @packet = MQTT::Packet.read(@socket)
350
+ end
351
+
352
+ it "should correctly create the right type of packet object" do
353
+ @packet.class.should == MQTT::Packet::Publish
354
+ end
355
+
356
+ it "should set the body length is read correctly" do
357
+ @packet.body_length.should == 17
358
+ end
359
+
360
+ it "should set the QOS level correctly" do
361
+ @packet.qos.should == 0
362
+ end
363
+
364
+ it "should set the RETAIN flag correctly" do
365
+ @packet.retain.should be_false
366
+ end
367
+
368
+ it "should set the DUP flag correctly" do
369
+ @packet.duplicate.should be_false
370
+ end
371
+
372
+ it "should set the topic name correctly" do
373
+ @packet.topic.should == 'test'
374
+ @packet.topic.encoding.to_s.should == 'UTF-8'
375
+ end
376
+
377
+ it "should set the payload correctly" do
378
+ @packet.payload.should == 'hello world'
379
+ @packet.payload.encoding.to_s.should == 'ASCII-8BIT'
237
380
  end
238
381
  end
239
382
 
383
+ describe "when calling the inspect method" do
384
+ it "should output the payload, if it is less than 16 bytes" do
385
+ packet = MQTT::Packet::Publish.new( :topic => "topic", :payload => "payload" )
386
+ packet.inspect.should == "#<MQTT::Packet::Publish: d0, q0, r0, m0, 'topic', 'payload'>"
387
+ end
388
+
389
+ it "should output the length of the payload, if it is more than 16 bytes" do
390
+ packet = MQTT::Packet::Publish.new( :topic => "topic", :payload => 'x'*32 )
391
+ packet.inspect.should == "#<MQTT::Packet::Publish: d0, q0, r0, m0, 'topic', ... (32 bytes)>"
392
+ end
393
+ end
240
394
  end
241
395
 
242
396
  describe MQTT::Packet::Connect do
@@ -262,6 +416,14 @@ describe MQTT::Packet::Connect do
262
416
  )
263
417
  end
264
418
 
419
+ it "should throw an exception if the keep alive value is less than 0" do
420
+ lambda {
421
+ MQTT::Packet::Connect.new(:client_id => 'test', :keep_alive => -2).to_s
422
+ }.should raise_error(
423
+ 'Invalid keep-alive value: cannot be less than 0'
424
+ )
425
+ end
426
+
265
427
  it "should output the correct bytes for a packet with a Will" do
266
428
  packet = MQTT::Packet::Connect.new(
267
429
  :client_id => 'myclient',
@@ -337,6 +499,7 @@ describe MQTT::Packet::Connect do
337
499
 
338
500
  it "should set the Protocol Name of the packet correctly" do
339
501
  @packet.protocol_name.should == 'MQIsdp'
502
+ @packet.protocol_name.encoding.to_s.should == 'UTF-8'
340
503
  end
341
504
 
342
505
  it "should set the Protocol Version of the packet correctly" do
@@ -345,6 +508,7 @@ describe MQTT::Packet::Connect do
345
508
 
346
509
  it "should set the Client Identifier of the packet correctly" do
347
510
  @packet.client_id.should == 'myclient'
511
+ @packet.client_id.encoding.to_s.should == 'UTF-8'
348
512
  end
349
513
 
350
514
  it "should set the Keep Alive timer of the packet correctly" do
@@ -393,6 +557,7 @@ describe MQTT::Packet::Connect do
393
557
 
394
558
  it "should set the Protocol Name of the packet correctly" do
395
559
  @packet.protocol_name.should == 'MQIsdp'
560
+ @packet.protocol_name.encoding.to_s.should == 'UTF-8'
396
561
  end
397
562
 
398
563
  it "should set the Protocol Version of the packet correctly" do
@@ -401,6 +566,7 @@ describe MQTT::Packet::Connect do
401
566
 
402
567
  it "should set the Client Identifier of the packet correctly" do
403
568
  @packet.client_id.should == 'myclient'
569
+ @packet.client_id.encoding.to_s.should == 'UTF-8'
404
570
  end
405
571
 
406
572
  it "should set the clean session flag should be set" do
@@ -417,10 +583,12 @@ describe MQTT::Packet::Connect do
417
583
 
418
584
  it "should set the Will topic of the packet correctly" do
419
585
  @packet.will_topic.should == 'topic'
586
+ @packet.will_topic.encoding.to_s.should == 'UTF-8'
420
587
  end
421
588
 
422
589
  it "should set the Will payload of the packet correctly" do
423
590
  @packet.will_payload.should == 'hello'
591
+ @packet.will_payload.encoding.to_s.should == 'UTF-8'
424
592
  end
425
593
  end
426
594
 
@@ -446,6 +614,7 @@ describe MQTT::Packet::Connect do
446
614
 
447
615
  it "should set the Protocol Name of the packet correctly" do
448
616
  @packet.protocol_name.should == 'MQIsdp'
617
+ @packet.protocol_name.encoding.to_s.should == 'UTF-8'
449
618
  end
450
619
 
451
620
  it "should set the Protocol Version of the packet correctly" do
@@ -454,7 +623,8 @@ describe MQTT::Packet::Connect do
454
623
 
455
624
  it "should set the Client Identifier of the packet correctly" do
456
625
  @packet.client_id.should == 'myclient'
457
- end
626
+ @packet.client_id.encoding.to_s.should == 'UTF-8'
627
+ end
458
628
 
459
629
  it "should set the Keep Alive Timer of the packet correctly" do
460
630
  @packet.keep_alive.should == 10
@@ -462,10 +632,12 @@ describe MQTT::Packet::Connect do
462
632
 
463
633
  it "should set the Username of the packet correctly" do
464
634
  @packet.username.should == 'username'
635
+ @packet.username.encoding.to_s.should == 'UTF-8'
465
636
  end
466
637
 
467
638
  it "should set the Username of the packet correctly" do
468
639
  @packet.password.should == 'password'
640
+ @packet.password.encoding.to_s.should == 'UTF-8'
469
641
  end
470
642
  end
471
643
 
@@ -478,6 +650,7 @@ describe MQTT::Packet::Connect do
478
650
 
479
651
  it "should set the Username of the packet correctly" do
480
652
  @packet.username.should == 'username'
653
+ @packet.username.encoding.to_s.should == 'UTF-8'
481
654
  end
482
655
 
483
656
  it "should set the Username of the packet correctly" do
@@ -498,6 +671,7 @@ describe MQTT::Packet::Connect do
498
671
 
499
672
  it "should set the Username of the packet correctly" do
500
673
  @packet.password.should == 'password'
674
+ @packet.password.encoding.to_s.should == 'UTF-8'
501
675
  end
502
676
  end
503
677
 
@@ -542,6 +716,7 @@ describe MQTT::Packet::Connect do
542
716
 
543
717
  it "should set the Protocol Name of the packet correctly" do
544
718
  @packet.protocol_name.should == 'MQIsdp'
719
+ @packet.protocol_name.encoding.to_s.should == 'UTF-8'
545
720
  end
546
721
 
547
722
  it "should set the Protocol Version of the packet correctly" do
@@ -554,6 +729,7 @@ describe MQTT::Packet::Connect do
554
729
 
555
730
  it "should set the Client Identifier of the packet correctly" do
556
731
  @packet.client_id.should == '12345678901234567890123'
732
+ @packet.client_id.encoding.to_s.should == 'UTF-8'
557
733
  end
558
734
 
559
735
  it "should set the Will QoS of the packet correctly" do
@@ -566,21 +742,67 @@ describe MQTT::Packet::Connect do
566
742
 
567
743
  it "should set the Will topic of the packet correctly" do
568
744
  @packet.will_topic.should == 'will_topic'
745
+ @packet.will_topic.encoding.to_s.should == 'UTF-8'
569
746
  end
570
747
 
571
748
  it "should set the Will payload of the packet correctly" do
572
749
  @packet.will_payload.should == 'will_message'
750
+ @packet.will_payload.encoding.to_s.should == 'UTF-8'
573
751
  end
574
752
 
575
753
  it "should set the Username of the packet correctly" do
576
754
  @packet.username.should == 'user0123456789'
755
+ @packet.username.encoding.to_s.should == 'UTF-8'
577
756
  end
578
757
 
579
758
  it "should set the Username of the packet correctly" do
580
759
  @packet.password.should == 'pass0123456789'
760
+ @packet.password.encoding.to_s.should == 'UTF-8'
761
+ end
762
+ end
763
+
764
+ describe "when parsing packet with an unknown protocol name" do
765
+ it "should throw a protocol exception" do
766
+ lambda {
767
+ packet = MQTT::Packet.parse(
768
+ "\x10\x16\x00\x06FooBar\x03\x00\x00\x0a\x00\x08myclient"
769
+ )
770
+ }.should raise_error(
771
+ MQTT::ProtocolException,
772
+ "Unsupported protocol name: FooBar"
773
+ )
581
774
  end
582
775
  end
583
776
 
777
+ describe "when parsing packet with an unknown protocol version" do
778
+ it "should throw a protocol exception" do
779
+ lambda {
780
+ packet = MQTT::Packet.parse(
781
+ "\x10\x16\x00\x06MQIsdp\x02\x00\x00\x0a\x00\x08myclient"
782
+ )
783
+ }.should raise_error(
784
+ MQTT::ProtocolException,
785
+ "Unsupported protocol version: 2"
786
+ )
787
+ end
788
+ end
789
+
790
+ describe "when calling the inspect method" do
791
+ it "should output correct string for the default options" do
792
+ packet = MQTT::Packet::Connect.new
793
+ packet.inspect.should == "#<MQTT::Packet::Connect: keep_alive=15, clean, client_id=''>"
794
+ end
795
+
796
+ it "should output correct string when parameters are given" do
797
+ packet = MQTT::Packet::Connect.new(
798
+ :keep_alive => 10,
799
+ :client_id => 'c123',
800
+ :clean_session => false,
801
+ :username => 'foo'
802
+ )
803
+ packet.inspect.should == "#<MQTT::Packet::Connect: keep_alive=10, client_id='c123', username='foo'>"
804
+ end
805
+ end
584
806
  end
585
807
 
586
808
  describe MQTT::Packet::Connack do
@@ -731,6 +953,17 @@ describe MQTT::Packet::Connack do
731
953
  )
732
954
  end
733
955
  end
956
+
957
+ describe "when calling the inspect method" do
958
+ it "should output the right string when the return code is 0" do
959
+ packet = MQTT::Packet::Connack.new( :return_code => 0x00 )
960
+ packet.inspect.should == "#<MQTT::Packet::Connack: 0x00>"
961
+ end
962
+ it "should output the right string when the return code is 0x0F" do
963
+ packet = MQTT::Packet::Connack.new( :return_code => 0x0F )
964
+ packet.inspect.should == "#<MQTT::Packet::Connack: 0x0F>"
965
+ end
966
+ end
734
967
  end
735
968
 
736
969
  describe MQTT::Packet::Puback do
@@ -765,6 +998,11 @@ describe MQTT::Packet::Puback do
765
998
  )
766
999
  end
767
1000
  end
1001
+
1002
+ it "should output the right string when calling inspect" do
1003
+ packet = MQTT::Packet::Puback.new( :message_id => 0x1234 )
1004
+ packet.inspect.should == "#<MQTT::Packet::Puback: 0x1234>"
1005
+ end
768
1006
  end
769
1007
 
770
1008
  describe MQTT::Packet::Pubrec do
@@ -799,6 +1037,11 @@ describe MQTT::Packet::Pubrec do
799
1037
  )
800
1038
  end
801
1039
  end
1040
+
1041
+ it "should output the right string when calling inspect" do
1042
+ packet = MQTT::Packet::Pubrec.new( :message_id => 0x1234 )
1043
+ packet.inspect.should == "#<MQTT::Packet::Pubrec: 0x1234>"
1044
+ end
802
1045
  end
803
1046
 
804
1047
  describe MQTT::Packet::Pubrel do
@@ -833,6 +1076,11 @@ describe MQTT::Packet::Pubrel do
833
1076
  )
834
1077
  end
835
1078
  end
1079
+
1080
+ it "should output the right string when calling inspect" do
1081
+ packet = MQTT::Packet::Pubrel.new( :message_id => 0x1234 )
1082
+ packet.inspect.should == "#<MQTT::Packet::Pubrel: 0x1234>"
1083
+ end
836
1084
  end
837
1085
 
838
1086
  describe MQTT::Packet::Pubcomp do
@@ -867,6 +1115,11 @@ describe MQTT::Packet::Pubcomp do
867
1115
  )
868
1116
  end
869
1117
  end
1118
+
1119
+ it "should output the right string when calling inspect" do
1120
+ packet = MQTT::Packet::Pubcomp.new( :message_id => 0x1234 )
1121
+ packet.inspect.should == "#<MQTT::Packet::Pubcomp: 0x1234>"
1122
+ end
870
1123
  end
871
1124
 
872
1125
  describe MQTT::Packet::Subscribe do
@@ -972,6 +1225,18 @@ describe MQTT::Packet::Subscribe do
972
1225
  @packet.topics.should == [['a/b',0],['c/d',1]]
973
1226
  end
974
1227
  end
1228
+
1229
+ describe "when calling the inspect method" do
1230
+ it "should output correct string for a single topic" do
1231
+ packet = MQTT::Packet::Subscribe.new(:topics => 'test')
1232
+ packet.inspect.should == "#<MQTT::Packet::Subscribe: 0x00, 'test':0>"
1233
+ end
1234
+
1235
+ it "should output correct string for multiple topics" do
1236
+ packet = MQTT::Packet::Subscribe.new(:topics => {'a' => 1, 'b' => 0, 'c' => 2})
1237
+ packet.inspect.should == "#<MQTT::Packet::Subscribe: 0x00, 'a':1, 'b':0, 'c':2>"
1238
+ end
1239
+ end
975
1240
  end
976
1241
 
977
1242
  describe MQTT::Packet::Suback do
@@ -1038,6 +1303,18 @@ describe MQTT::Packet::Suback do
1038
1303
  @packet.granted_qos.should == [1,1]
1039
1304
  end
1040
1305
  end
1306
+
1307
+ describe "when calling the inspect method" do
1308
+ it "should output correct string for a single granted qos" do
1309
+ packet = MQTT::Packet::Suback.new(:message_id => 0x1234, :granted_qos => 0)
1310
+ packet.inspect.should == "#<MQTT::Packet::Suback: 0x1234, qos=0>"
1311
+ end
1312
+
1313
+ it "should output correct string for multiple topics" do
1314
+ packet = MQTT::Packet::Suback.new(:message_id => 0x1235, :granted_qos => [0,1,2])
1315
+ packet.inspect.should == "#<MQTT::Packet::Suback: 0x1235, qos=0,1,2>"
1316
+ end
1317
+ end
1041
1318
  end
1042
1319
 
1043
1320
  describe MQTT::Packet::Unsubscribe do
@@ -1078,6 +1355,18 @@ describe MQTT::Packet::Unsubscribe do
1078
1355
  @packet.topics.should == ['a/b','c/d']
1079
1356
  end
1080
1357
  end
1358
+
1359
+ describe "when calling the inspect method" do
1360
+ it "should output correct string for a single topic" do
1361
+ packet = MQTT::Packet::Unsubscribe.new(:topics => 'test')
1362
+ packet.inspect.should == "#<MQTT::Packet::Unsubscribe: 0x00, 'test'>"
1363
+ end
1364
+
1365
+ it "should output correct string for multiple topics" do
1366
+ packet = MQTT::Packet::Unsubscribe.new(:message_id => 42, :topics => ['a', 'b', 'c'])
1367
+ packet.inspect.should == "#<MQTT::Packet::Unsubscribe: 0x2A, 'a', 'b', 'c'>"
1368
+ end
1369
+ end
1081
1370
  end
1082
1371
 
1083
1372
  describe MQTT::Packet::Unsuback do
@@ -1112,6 +1401,11 @@ describe MQTT::Packet::Unsuback do
1112
1401
  )
1113
1402
  end
1114
1403
  end
1404
+
1405
+ it "should output the right string when calling inspect" do
1406
+ packet = MQTT::Packet::Unsuback.new( :message_id => 0x1234 )
1407
+ packet.inspect.should == "#<MQTT::Packet::Unsuback: 0x1234>"
1408
+ end
1115
1409
  end
1116
1410
 
1117
1411
  describe MQTT::Packet::Pingreq do
@@ -1136,6 +1430,11 @@ describe MQTT::Packet::Pingreq do
1136
1430
  )
1137
1431
  end
1138
1432
  end
1433
+
1434
+ it "should output the right string when calling inspect" do
1435
+ packet = MQTT::Packet::Pingreq.new
1436
+ packet.inspect.should == "#<MQTT::Packet::Pingreq>"
1437
+ end
1139
1438
  end
1140
1439
 
1141
1440
  describe MQTT::Packet::Pingresp do
@@ -1160,6 +1459,11 @@ describe MQTT::Packet::Pingresp do
1160
1459
  )
1161
1460
  end
1162
1461
  end
1462
+
1463
+ it "should output the right string when calling inspect" do
1464
+ packet = MQTT::Packet::Pingresp.new
1465
+ packet.inspect.should == "#<MQTT::Packet::Pingresp>"
1466
+ end
1163
1467
  end
1164
1468
 
1165
1469
 
@@ -1185,6 +1489,11 @@ describe MQTT::Packet::Disconnect do
1185
1489
  )
1186
1490
  end
1187
1491
  end
1492
+
1493
+ it "should output the right string when calling inspect" do
1494
+ packet = MQTT::Packet::Disconnect.new
1495
+ packet.inspect.should == "#<MQTT::Packet::Disconnect>"
1496
+ end
1188
1497
  end
1189
1498
 
1190
1499
 
@@ -1201,24 +1510,60 @@ describe "Serialising an invalid packet" do
1201
1510
  end
1202
1511
  end
1203
1512
 
1204
- describe "Reading in an invalid packet" do
1513
+ describe "Reading in an invalid packet from a socket" do
1205
1514
  context "that has 0 length" do
1206
1515
  it "should throw an exception" do
1207
1516
  lambda {
1208
- data = StringIO.new
1209
- MQTT::Packet.read(data)
1517
+ socket = StringIO.new
1518
+ MQTT::Packet.read(socket)
1519
+ }.should raise_error(
1520
+ MQTT::ProtocolException,
1521
+ "Failed to read byte from socket"
1522
+ )
1523
+ end
1524
+ end
1525
+
1526
+ context "that has an incomplete packet length header" do
1527
+ it "should throw an exception" do
1528
+ lambda {
1529
+ socket = StringIO.new("\x30\xFF")
1530
+ MQTT::Packet.read(socket)
1531
+ }.should raise_error(
1532
+ MQTT::ProtocolException,
1533
+ "Failed to read byte from socket"
1534
+ )
1535
+ end
1536
+ end
1537
+
1538
+ context "that has the maximum number of bytes in the length header" do
1539
+ it "should throw an exception" do
1540
+ lambda {
1541
+ socket = StringIO.new("\x30\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF")
1542
+ MQTT::Packet.read(socket)
1210
1543
  }.should raise_error(
1211
- MQTT::ProtocolException
1544
+ MQTT::ProtocolException,
1545
+ "Failed to parse packet - input buffer (4) is not the same as the body length header (268435455)"
1212
1546
  )
1213
1547
  end
1214
1548
  end
1215
1549
  end
1216
1550
 
1217
1551
  describe "Parsing an invalid packet" do
1552
+ context "that has no length" do
1553
+ it "should throw an exception" do
1554
+ lambda {
1555
+ MQTT::Packet.parse( "" )
1556
+ }.should raise_error(
1557
+ MQTT::ProtocolException,
1558
+ "Invalid packet: less than 2 bytes long"
1559
+ )
1560
+ end
1561
+ end
1562
+
1218
1563
  context "that has an invalid type identifier" do
1219
1564
  it "should throw an exception" do
1220
1565
  lambda {
1221
- MQTT::Packet.parse( "\x00" )
1566
+ MQTT::Packet.parse( "\x00\x00" )
1222
1567
  }.should raise_error(
1223
1568
  MQTT::ProtocolException,
1224
1569
  "Invalid packet type identifier: 0"
@@ -1237,13 +1582,24 @@ describe "Parsing an invalid packet" do
1237
1582
  end
1238
1583
  end
1239
1584
 
1585
+ context "that has too many bytes in the length field" do
1586
+ it "should throw an exception" do
1587
+ lambda {
1588
+ MQTT::Packet.parse( "\x30\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" )
1589
+ }.should raise_error(
1590
+ MQTT::ProtocolException,
1591
+ 'Failed to parse packet - input buffer (4) is not the same as the body length header (268435455)'
1592
+ )
1593
+ end
1594
+ end
1595
+
1240
1596
  context "that has a bigger buffer than expected" do
1241
1597
  it "should throw an exception" do
1242
1598
  lambda {
1243
1599
  MQTT::Packet.parse( "\x30\x11\x00\x04testhello big world" )
1244
1600
  }.should raise_error(
1245
1601
  MQTT::ProtocolException,
1246
- "Failed to parse packet - input buffer (21) is not the same as the body length buffer (17)"
1602
+ "Failed to parse packet - input buffer (21) is not the same as the body length header (17)"
1247
1603
  )
1248
1604
  end
1249
1605
  end
@@ -1254,7 +1610,7 @@ describe "Parsing an invalid packet" do
1254
1610
  MQTT::Packet.parse( "\x30\x11\x00\x04testhello" )
1255
1611
  }.should raise_error(
1256
1612
  MQTT::ProtocolException,
1257
- "Failed to parse packet - input buffer (11) is not the same as the body length buffer (17)"
1613
+ "Failed to parse packet - input buffer (11) is not the same as the body length header (17)"
1258
1614
  )
1259
1615
  end
1260
1616
  end