mqtt 0.0.9 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +21 -0
- data/NEWS +19 -0
- data/README +5 -1
- data/lib/mqtt.rb +6 -1
- data/lib/mqtt/client.rb +30 -2
- data/lib/mqtt/packet.rb +158 -45
- data/lib/mqtt/patches/string_encoding.rb +30 -0
- data/lib/mqtt/version.rb +1 -1
- data/spec/mqtt_client_spec.rb +79 -3
- data/spec/mqtt_packet_spec.rb +366 -10
- data/spec/zz_integration_spec.rb +145 -0
- metadata +23 -11
- data/COPYING +0 -56
- data/GPL +0 -340
@@ -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
|
data/lib/mqtt/version.rb
CHANGED
data/spec/mqtt_client_spec.rb
CHANGED
@@ -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
|
data/spec/mqtt_packet_spec.rb
CHANGED
@@ -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.
|
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.
|
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
|
-
|
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
|
-
|
1209
|
-
MQTT::Packet.read(
|
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
|
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
|
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
|