mosquitto 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.travis.yml +29 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +25 -0
  6. data/LICENSE.md +13 -0
  7. data/README.md +244 -0
  8. data/Rakefile +42 -0
  9. data/TODO.md +19 -0
  10. data/examples/pub_sub.rb +41 -0
  11. data/ext/mosquitto/client.c +2163 -0
  12. data/ext/mosquitto/client.h +145 -0
  13. data/ext/mosquitto/extconf.rb +31 -0
  14. data/ext/mosquitto/message.c +168 -0
  15. data/ext/mosquitto/message.h +16 -0
  16. data/ext/mosquitto/mosquitto_ext.c +88 -0
  17. data/ext/mosquitto/mosquitto_ext.h +35 -0
  18. data/ext/mosquitto/mosquitto_prelude.h +26 -0
  19. data/ext/mosquitto/rubinius.h +6 -0
  20. data/ext/mosquitto/ruby18.h +6 -0
  21. data/ext/mosquitto/ruby19.h +9 -0
  22. data/ext/mosquitto/ruby2.h +6 -0
  23. data/lib/mosquitto.rb +11 -0
  24. data/lib/mosquitto/client.rb +8 -0
  25. data/lib/mosquitto/logging.rb +32 -0
  26. data/lib/mosquitto/version.rb +5 -0
  27. data/mosquitto.gemspec +23 -0
  28. data/test/helper.rb +59 -0
  29. data/test/ssl/all-ca.crt +75 -0
  30. data/test/ssl/client-expired.crt +61 -0
  31. data/test/ssl/client-revoked.crt +61 -0
  32. data/test/ssl/client-revoked.csr +12 -0
  33. data/test/ssl/client-revoked.key +15 -0
  34. data/test/ssl/client.crt +61 -0
  35. data/test/ssl/client.csr +12 -0
  36. data/test/ssl/client.key +15 -0
  37. data/test/ssl/crl.pem +10 -0
  38. data/test/ssl/demoCA/crlnumber +1 -0
  39. data/test/ssl/demoCA/index.txt +1 -0
  40. data/test/ssl/demoCA/index.txt.attr +1 -0
  41. data/test/ssl/demoCA/serial +1 -0
  42. data/test/ssl/gen.sh +70 -0
  43. data/test/ssl/mosquitto.org.crt +18 -0
  44. data/test/ssl/openssl.cnf +406 -0
  45. data/test/ssl/readme.txt +2 -0
  46. data/test/ssl/rootCA/crlnumber +1 -0
  47. data/test/ssl/rootCA/index.txt +2 -0
  48. data/test/ssl/rootCA/index.txt.attr +1 -0
  49. data/test/ssl/rootCA/serial +1 -0
  50. data/test/ssl/server-expired.crt +0 -0
  51. data/test/ssl/server.crt +60 -0
  52. data/test/ssl/server.csr +12 -0
  53. data/test/ssl/server.key +15 -0
  54. data/test/ssl/signingCA/crlnumber +1 -0
  55. data/test/ssl/signingCA/index.txt +4 -0
  56. data/test/ssl/signingCA/index.txt.attr +1 -0
  57. data/test/ssl/signingCA/serial +1 -0
  58. data/test/ssl/test-alt-ca.crt +58 -0
  59. data/test/ssl/test-alt-ca.key +15 -0
  60. data/test/ssl/test-bad-root-ca.crt +17 -0
  61. data/test/ssl/test-bad-root-ca.key +15 -0
  62. data/test/ssl/test-ca.srl +1 -0
  63. data/test/ssl/test-fake-root-ca.crt +17 -0
  64. data/test/ssl/test-fake-root-ca.key +15 -0
  65. data/test/ssl/test-root-ca.crt +17 -0
  66. data/test/ssl/test-root-ca.key +15 -0
  67. data/test/ssl/test-signing-ca.crt +58 -0
  68. data/test/ssl/test-signing-ca.key +15 -0
  69. data/test/test_callbacks.rb +93 -0
  70. data/test/test_client.rb +141 -0
  71. data/test/test_custom_logger.rb +30 -0
  72. data/test/test_integration.rb +572 -0
  73. data/test/test_loops.rb +56 -0
  74. data/test/test_mosquitto.rb +28 -0
  75. data/test/test_pub_sub.rb +51 -0
  76. data/test/test_threads.rb +69 -0
  77. data/test/test_tls.rb +67 -0
  78. metadata +203 -0
@@ -0,0 +1,141 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.dirname(__FILE__), 'helper')
4
+
5
+ class TestClient < MosquittoTestCase
6
+ def test_init
7
+ client = Mosquitto::Client.new
8
+ assert_instance_of Mosquitto::Client, client
9
+ client = Mosquitto::Client.new("test")
10
+ assert_raises TypeError do
11
+ Mosquitto::Client.new(:invalid)
12
+ end
13
+ end
14
+
15
+ def test_reinitialize
16
+ client = Mosquitto::Client.new
17
+ assert client.reinitialise("test")
18
+ assert_raises TypeError do
19
+ client.reinitialise(:invalid)
20
+ end
21
+ end
22
+
23
+ def test_will_set
24
+ client = Mosquitto::Client.new
25
+ assert client.will_set("will_set", "test", Mosquitto::AT_MOST_ONCE, true)
26
+ assert_raises TypeError do
27
+ client.will_set("will_set", :invalid, Mosquitto::AT_MOST_ONCE, true)
28
+ end
29
+ assert_raises Mosquitto::Error do
30
+ client.will_set("will_set", ('a' * 268435456), Mosquitto::AT_MOST_ONCE, true)
31
+ end
32
+ end
33
+
34
+ def test_will_clear
35
+ client = Mosquitto::Client.new
36
+ assert client.will_set("will_clear", "test", Mosquitto::AT_MOST_ONCE, true)
37
+ assert client.will_clear
38
+ end
39
+
40
+ def test_auth
41
+ client = Mosquitto::Client.new
42
+ assert client.auth("username", "password")
43
+ assert client.auth("username", nil)
44
+ assert_raises TypeError do
45
+ client.auth(:invalid, "password")
46
+ end
47
+ end
48
+
49
+ def test_connect
50
+ client = Mosquitto::Client.new
51
+ assert client.loop_start
52
+ assert_raises TypeError do
53
+ client.connect(:invalid, TEST_PORT, 10)
54
+ end
55
+ assert client.connect(TEST_HOST, TEST_PORT, 10)
56
+ ensure
57
+ client.loop_stop(true)
58
+ end
59
+
60
+ def test_connect_bind
61
+ client = Mosquitto::Client.new
62
+ assert client.loop_start
63
+ assert_raises TypeError do
64
+ client.connect_bind("localhost", TEST_PORT, 10, :invalid)
65
+ end
66
+ assert client.connect_bind(TEST_HOST, TEST_PORT, 10, "0.0.0.0")
67
+ ensure
68
+ client.loop_stop(true)
69
+ end
70
+
71
+ def test_connect_async
72
+ client = Mosquitto::Client.new
73
+ assert client.loop_start
74
+ assert_raises TypeError do
75
+ client.connect_async(:invalid, TEST_PORT, 10)
76
+ end
77
+ assert client.connect_async(TEST_HOST, TEST_PORT, 10)
78
+ client.wait_readable
79
+ assert client.socket != -1
80
+ ensure
81
+ client.loop_stop(true)
82
+ end
83
+
84
+ def test_connect_bind_async
85
+ client = Mosquitto::Client.new
86
+ assert client.loop_start
87
+ assert_raises TypeError do
88
+ client.connect_bind_async(TEST_HOST, TEST_PORT, 10, :invalid)
89
+ end
90
+ assert client.connect_bind_async(TEST_HOST, TEST_PORT, 10, '0.0.0.0')
91
+ client.wait_readable
92
+ assert client.socket != -1
93
+ ensure
94
+ client.loop_stop(true)
95
+ end
96
+
97
+ def test_disconnect
98
+ client = Mosquitto::Client.new
99
+ assert client.loop_start
100
+ assert_raises Mosquitto::Error do
101
+ client.disconnect
102
+ end
103
+ assert client.connect(TEST_HOST, TEST_PORT, 10)
104
+ assert client.disconnect
105
+ ensure
106
+ client.loop_stop(true)
107
+ end
108
+
109
+ def test_reconnect
110
+ client = Mosquitto::Client.new
111
+ assert_raises Mosquitto::Error do
112
+ client.reconnect
113
+ end
114
+ assert client.connect(TEST_HOST, TEST_PORT, 10)
115
+ assert client.reconnect
116
+ end
117
+
118
+ def test_reconnect_delay_set
119
+ client = Mosquitto::Client.new
120
+ assert_raises TypeError do
121
+ client.reconnect_delay_set(:invalid, 10, true)
122
+ end
123
+ assert client.reconnect_delay_set(2, 10, true)
124
+ end
125
+
126
+ def test_max_inflight_messages
127
+ client = Mosquitto::Client.new
128
+ assert_raises TypeError do
129
+ client.max_inflight_messages = :invalid
130
+ end
131
+ assert client.max_inflight_messages = 10
132
+ end
133
+
134
+ def test_message_retry
135
+ client = Mosquitto::Client.new
136
+ assert_raises TypeError do
137
+ client.message_retry = :invalid
138
+ end
139
+ assert client.message_retry = 10
140
+ end
141
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.dirname(__FILE__), 'helper')
4
+
5
+ require 'stringio'
6
+
7
+ class TestCustomLogger < MosquittoTestCase
8
+ def test_logger
9
+ log_dev = StringIO.new
10
+ logger = Logger.new(log_dev)
11
+ client = Mosquitto::Client.new
12
+
13
+ assert_raises ArgumentError do
14
+ client.logger = Object.new
15
+ end
16
+
17
+ client.logger = logger
18
+ client.loop_start
19
+ assert client.connect(TEST_HOST, TEST_PORT, 10)
20
+ assert client.subscribe(nil, "custom_logger", Mosquitto::AT_MOST_ONCE)
21
+ client.wait_readable
22
+
23
+ logs = log_dev.string
24
+ assert_match(/DEBUG/, logs)
25
+ assert_match(/sending CONNECT/, logs)
26
+ assert_match(/sending SUBSCRIBE/, logs)
27
+ assert_match(/custom_logger/, logs)
28
+ assert_match(/Client mosq/, logs)
29
+ end
30
+ end
@@ -0,0 +1,572 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.dirname(__FILE__), 'helper')
4
+
5
+ class TestIntegration < MosquittoTestCase
6
+ TOPICS = ["1/2/3", "a/b/c", "1/2", "1/2/3/this_is_a_long_topic_that_wasnt_working/before/4/5/6/7/8",
7
+ "1/2/3/this_is_a_long_topic_that_wasnt_working/before/4/5/6/7/8/#", "#", "1/2/./3", "*/>/#",
8
+ "a/+/#", "a/#", "+/+/+", "will/topic"]
9
+
10
+ CLIENT_IDS = %w(test_integration test_lwt test_clean_session test_duplicate)
11
+
12
+ def setup
13
+ @result = nil
14
+ @client = nil
15
+ connected = false
16
+ @client = Mosquitto::Client.new(nil, true)
17
+ @client.loop_start
18
+ @client.logger = Logger.new(STDOUT)
19
+ @client.on_connect do |rc|
20
+ connected = true
21
+ end
22
+ @client.on_message do |msg|
23
+ @result = msg.to_s
24
+ end
25
+ assert @client.connect(TEST_HOST, TEST_PORT, 10)
26
+ wait{ connected }
27
+ end
28
+
29
+ def teardown
30
+ disconnected, connected = false, false
31
+ @client.on_disconnect do |rc|
32
+ disconnected = true
33
+ end
34
+ @client.disconnect
35
+ wait{ disconnected }
36
+ @client.loop_stop(true)
37
+
38
+ CLIENT_IDS.each do |client_id|
39
+ disconnected = false
40
+ client = Mosquitto::Client.new(client_id)
41
+ client.loop_start
42
+ client.on_disconnect do |rc|
43
+ disconnected = true
44
+ end
45
+ client.on_connect do |rc|
46
+ assert client.disconnect
47
+ end
48
+ assert client.connect(TEST_HOST, TEST_PORT, 10)
49
+ wait{ disconnected }
50
+ client.loop_stop(true)
51
+ end
52
+
53
+ client = Mosquitto::Client.new("purge")
54
+ client.loop_start
55
+ client.on_connect do |rc|
56
+ connected = true
57
+ end
58
+ client.on_message do |msg|
59
+ if msg.retain?
60
+ assert client.publish(nil, msg.topic, "", Mosquitto::AT_LEAST_ONCE, true)
61
+ end
62
+ end
63
+ assert client.connect(TEST_HOST, TEST_PORT, 10)
64
+ wait{ connected }
65
+
66
+ TOPICS.each do |topic|
67
+ assert client.subscribe(nil, topic, Mosquitto::AT_MOST_ONCE)
68
+ end
69
+
70
+ sleep 5
71
+ client.disconnect
72
+ client.loop_stop(true)
73
+ end
74
+
75
+ def test_basic
76
+ # check basic pub/sub on QOS 0
77
+ expected = "hello mqtt broker on QOS 0"
78
+ @client.on_subscribe do |mid, granted_qos|
79
+ assert @client.publish(nil, "1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
80
+ end
81
+ assert @client.subscribe(nil, "1/2/3", Mosquitto::AT_MOST_ONCE)
82
+ wait{ @result }
83
+ assert_equal expected, @result
84
+ assert @client.unsubscribe(nil, "1/2/3")
85
+
86
+ # check basic pub/sub on QOS 1
87
+ @result = nil
88
+ expected = "hello mqtt broker on QOS 1"
89
+ @client.on_subscribe do |mid, granted_qos|
90
+ assert @client.publish(nil, "a/b/c", expected, Mosquitto::AT_LEAST_ONCE, false)
91
+ end
92
+ assert @client.subscribe(nil, "a/b/c", Mosquitto::AT_LEAST_ONCE)
93
+ wait{ @result }
94
+ assert_equal expected, @result
95
+ @client.unsubscribe(nil, "a/b/c")
96
+
97
+ # check basic pub/sub on QOS 2
98
+ @result = nil
99
+ expected = "hello mqtt broker on QOS 2"
100
+ @client.on_subscribe do |mid, granted_qos|
101
+ assert @client.publish(nil, "1/2", expected, Mosquitto::EXACTLY_ONCE, false)
102
+ end
103
+ assert @client.subscribe(nil, "1/2", Mosquitto::EXACTLY_ONCE)
104
+ wait{ @result }
105
+ assert_equal expected, @result
106
+ assert @client.unsubscribe(nil, "1/2")
107
+ end
108
+
109
+ def test_long_topic
110
+ # check a simple # subscribe works
111
+ @result = nil
112
+ expected = "hello mqtt broker on long topic"
113
+ @client.on_subscribe do |mid, granted_qos|
114
+ assert @client.publish(nil, "1/2/3/this_is_a_long_topic_that_wasnt_working/before/4/5/6/7/8", expected, Mosquitto::AT_MOST_ONCE, false)
115
+ end
116
+ assert @client.subscribe(nil, "1/2/3/this_is_a_long_topic_that_wasnt_working/before/4/5/6/7/8", Mosquitto::AT_MOST_ONCE)
117
+ wait{ @result }
118
+ assert_equal expected, @result
119
+ assert @client.unsubscribe(nil, "1/2/3/this_is_a_long_topic_that_wasnt_working/before/4/5/6/7/8")
120
+
121
+ @result = nil
122
+ expected = "hello mqtt broker on long topic with hash"
123
+ @client.on_subscribe do |mid, granted_qos|
124
+ assert @client.publish(nil, "1/2/3/this_is_a_long_topic_that_wasnt_working/before/4/5/6/7/8", expected, Mosquitto::AT_MOST_ONCE, false)
125
+ end
126
+ assert @client.subscribe(nil, "1/2/3/this_is_a_long_topic_that_wasnt_working/before/4/5/6/7/8/#", Mosquitto::AT_MOST_ONCE)
127
+ wait{ @result }
128
+ assert_equal expected, @result
129
+
130
+ @result = nil
131
+ expected = "hello mqtt broker on long topic with hash again"
132
+ assert @client.publish(nil, "1/2/3/this_is_a_long_topic_that_wasnt_working/before/4/5/6/7/8/9/10/0", expected, Mosquitto::AT_MOST_ONCE, false)
133
+ wait{ @result }
134
+ assert_equal expected, @result
135
+ assert @client.unsubscribe(nil, "1/2/3/this_is_a_long_topic_that_wasnt_working/before/4/5/6/7/8/#")
136
+ end
137
+
138
+ def test_overlapping_topics
139
+ # check a simple # subscribe works
140
+ @result = nil
141
+ expected = "hello mqtt broker on hash"
142
+ @client.on_subscribe do |mid, granted_qos|
143
+ assert @client.publish(nil, "a/b/c", expected, Mosquitto::AT_MOST_ONCE, false)
144
+ end
145
+ assert @client.subscribe(nil, "#", Mosquitto::AT_MOST_ONCE)
146
+ wait{ @result }
147
+ assert_equal expected, @result
148
+
149
+ @result = nil
150
+ expected = "hello mqtt broker on some other topic"
151
+ assert @client.publish(nil, "1/2/3/4/5/6", expected, Mosquitto::AT_MOST_ONCE, false)
152
+ wait{ @result }
153
+ assert_equal expected, @result
154
+
155
+ # now subscribe on a topic that overlaps the root # wildcard - we should still get everything
156
+ @result = nil
157
+ assert @client.subscribe(nil, "1/2/3", Mosquitto::AT_MOST_ONCE)
158
+ expected = "hello mqtt broker on explicit topic"
159
+ assert @client.publish(nil, "1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
160
+ wait{ @result }
161
+ assert_equal expected, @result
162
+
163
+ @result = nil
164
+ expected = "hello mqtt broker on some other topic"
165
+ assert @client.publish(nil, "a/b/c/d/e", expected, Mosquitto::AT_MOST_ONCE, false)
166
+ wait{ @result }
167
+ assert_equal expected, @result
168
+
169
+ # now unsub hash - we should only get called back on 1/2/3
170
+ @client.unsubscribe(nil, "#");
171
+ @result = nil
172
+ expected = "this should not come back..."
173
+ assert @client.publish(nil, "1/2/3/4", expected, Mosquitto::AT_MOST_ONCE, false)
174
+ sleep 1
175
+ assert_nil @result
176
+
177
+ @result = nil
178
+ expected = "this should not come back either..."
179
+ assert @client.publish(nil, "a/b/c", expected, Mosquitto::AT_MOST_ONCE, false)
180
+ sleep 1
181
+ assert_nil @result
182
+
183
+ # this should still come back since we are still subscribed on 1/2/3
184
+ @result = nil
185
+ expected = "we should still get this"
186
+ assert @client.publish(nil, "1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
187
+ wait{ @result }
188
+ assert_equal expected, @result
189
+ assert @client.unsubscribe(nil, "1/2/3")
190
+
191
+ # repeat the above full test but reverse the order of the subs
192
+ @result = nil
193
+ expected = "hello mqtt broker on hash"
194
+ @client.on_subscribe do |mid, granted_qos|
195
+ assert @client.publish(nil, "1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
196
+ end
197
+ assert @client.subscribe(nil, "1/2/3", Mosquitto::AT_MOST_ONCE)
198
+ wait{ @result }
199
+ assert_equal expected, @result
200
+
201
+ @result = nil
202
+ expected = "hello mqtt broker on a different topic - we shouldn't get this"
203
+ assert @client.publish(nil, "1/2/3/4/5/6", expected, Mosquitto::AT_MOST_ONCE, false)
204
+ sleep 1
205
+ assert_nil @result
206
+
207
+ @result = nil
208
+ expected = "hello mqtt broker on some other topic topic"
209
+ @client.on_subscribe do |mid, granted_qos|
210
+ assert @client.publish(nil, "a/b/c/d", expected, Mosquitto::AT_MOST_ONCE, false)
211
+ end
212
+ assert @client.subscribe(nil, "#", Mosquitto::AT_MOST_ONCE)
213
+ wait{ @result }
214
+ assert_equal expected, @result
215
+
216
+ @result = nil
217
+ expected = "hello mqtt broker on some other topic"
218
+ assert @client.publish(nil, "1/2/3/4/5/6", expected, Mosquitto::AT_MOST_ONCE, false)
219
+ wait{ @result }
220
+ assert_equal expected, @result
221
+
222
+ @client.unsubscribe(nil, "1/2/3")
223
+
224
+ @result = nil
225
+ expected = "this should come back..."
226
+ assert @client.publish(nil, "1/2/3/4/5/6", expected, Mosquitto::AT_MOST_ONCE, false)
227
+ wait{ @result }
228
+ assert_equal expected, @result
229
+
230
+ @result = nil
231
+ expected = "this should come back too..."
232
+ assert @client.publish(nil, "a/b/c", expected, Mosquitto::AT_MOST_ONCE, false)
233
+ wait{ @result }
234
+ assert_equal expected, @result
235
+
236
+ @result = nil
237
+ expected = "we should still get this as well."
238
+ assert @client.publish(nil, "1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
239
+ wait{ @result }
240
+ assert_equal expected, @result
241
+
242
+ assert @client.unsubscribe(nil, "#")
243
+ end
244
+
245
+ def test_dots
246
+ # check that dots are not treated differently
247
+ @result = nil
248
+ expected = "hello mqtt broker with a dot"
249
+ @client.on_subscribe do |mid, granted_qos|
250
+ assert @client.publish(nil, "1/2/./3", expected, Mosquitto::AT_MOST_ONCE, false)
251
+ end
252
+ assert @client.subscribe(nil, "1/2/./3", Mosquitto::AT_MOST_ONCE)
253
+ wait{ @result }
254
+ assert_equal expected, @result
255
+
256
+ @result = nil
257
+ expected = "should not get this"
258
+ assert @client.publish(nil, "1/2", expected, Mosquitto::AT_MOST_ONCE, false)
259
+ sleep 1
260
+ assert_nil @result
261
+
262
+ @result = nil
263
+ expected = "should not get this"
264
+ assert @client.publish(nil, "1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
265
+ sleep 1
266
+ assert_nil @result
267
+
268
+ @result = nil
269
+ expected = "should not get this"
270
+ assert @client.publish(nil, "1/2/./3/4", expected, Mosquitto::AT_MOST_ONCE, false)
271
+ sleep 1
272
+ assert_nil @result
273
+
274
+ assert @client.unsubscribe(nil, "1/2/./3")
275
+
276
+ @result = nil
277
+ expected = "should not get this"
278
+ assert @client.publish(nil, "1/2/./3", expected, Mosquitto::AT_MOST_ONCE, false)
279
+ sleep 1
280
+ assert_nil @result
281
+
282
+ @result = nil
283
+ expected = "should not get this"
284
+ assert @client.publish(nil, "1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
285
+ sleep 1
286
+ assert_nil @result
287
+
288
+ @result = nil
289
+ expected = "should not get this"
290
+ assert @client.publish(nil, "1/2/./3/4", expected, Mosquitto::AT_MOST_ONCE, false)
291
+ sleep 1
292
+ assert_nil @result
293
+ end
294
+
295
+ def test_active_mq_wildcards
296
+ # check that ActiveMQ native wildcards are not treated differently
297
+ @result = nil
298
+ expected = "hello mqtt broker with fake wildcards"
299
+ @client.on_subscribe do |mid, granted_qos|
300
+ assert @client.publish(nil, "*/>/1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
301
+ end
302
+ assert @client.subscribe(nil, "*/>/#", Mosquitto::AT_MOST_ONCE)
303
+ wait{ @result }
304
+ assert_equal expected, @result
305
+
306
+ @result = nil
307
+ expected = "should not get this"
308
+ assert @client.publish(nil, "1", expected, Mosquitto::AT_MOST_ONCE, false)
309
+ sleep 1
310
+ assert_nil @result
311
+
312
+ @result = nil
313
+ expected = "should not get this"
314
+ assert @client.publish(nil, "1/2", expected, Mosquitto::AT_MOST_ONCE, false)
315
+ sleep 1
316
+ assert_nil @result
317
+
318
+ @result = nil
319
+ expected = "should not get this"
320
+ assert @client.publish(nil, "1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
321
+ sleep 1
322
+ assert_nil @result
323
+
324
+ @result = nil
325
+ expected = "should not get this"
326
+ assert @client.publish(nil, "*/2", expected, Mosquitto::AT_MOST_ONCE, false)
327
+ sleep 1
328
+ assert_nil @result
329
+
330
+ @result = nil
331
+ expected = "should get this"
332
+ assert @client.publish(nil, "*/>/3", expected, Mosquitto::AT_MOST_ONCE, false)
333
+ wait{ @result }
334
+ assert_equal expected, @result
335
+
336
+ @result = nil
337
+ expected = "should get this"
338
+ assert @client.publish(nil, "*/>", expected, Mosquitto::AT_MOST_ONCE, false)
339
+ wait{ @result }
340
+ assert_equal expected, @result
341
+ end
342
+
343
+ def test_native_mqtt_wildcards
344
+ # check that hash works right with plus
345
+ @result = nil
346
+ expected = "sub on everything below a but not a"
347
+ @client.on_subscribe do |mid, granted_qos|
348
+ assert @client.publish(nil, "a/b", expected, Mosquitto::AT_MOST_ONCE, false)
349
+ end
350
+ assert @client.subscribe(nil, "a/+/#", Mosquitto::AT_MOST_ONCE)
351
+ wait{ @result }
352
+ assert_equal expected, @result
353
+
354
+ @result = nil
355
+ expected = "should not get this"
356
+ assert @client.publish(nil, "a", expected, Mosquitto::AT_MOST_ONCE, false)
357
+ sleep 1
358
+ assert_nil @result
359
+
360
+ assert @client.unsubscribe(nil, "a/+/#")
361
+ assert @client.subscribe(nil, "a/#", Mosquitto::AT_MOST_ONCE)
362
+
363
+ sleep 1
364
+
365
+ @result = nil
366
+ expected = "sub on everything below a including a"
367
+ assert @client.publish(nil, "a/b", expected, Mosquitto::AT_MOST_ONCE, false)
368
+ wait{ @result }
369
+ assert_equal expected, @result
370
+
371
+ @result = nil
372
+ expected = "sub on everything below a still including a"
373
+ assert @client.publish(nil, "a", expected, Mosquitto::AT_MOST_ONCE, false)
374
+ wait{ @result }
375
+ assert_equal expected, @result
376
+
377
+ @result = nil
378
+ expected = "sub on everything below a still including a - should not get b"
379
+ assert @client.publish(nil, "b", expected, Mosquitto::AT_MOST_ONCE, false)
380
+ sleep 1
381
+ assert_nil @result
382
+
383
+ assert @client.unsubscribe(nil, "a/#")
384
+ end
385
+
386
+ def test_wildcard_plus
387
+ # check that unsub of hash doesn't affect other subscriptions
388
+ @result = nil
389
+ expected = "should get this 1"
390
+ @client.on_subscribe do |mid, granted_qos|
391
+ assert @client.publish(nil, "1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
392
+ end
393
+ assert @client.subscribe(nil, "+/+/+", Mosquitto::AT_MOST_ONCE)
394
+ wait{ @result }
395
+ assert_equal expected, @result
396
+
397
+ @result = nil
398
+ expected = "should get this 2"
399
+ assert @client.publish(nil, "a/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
400
+ wait{ @result }
401
+ assert_equal expected, @result
402
+
403
+ @result = nil
404
+ expected = "should get this 3"
405
+ assert @client.publish(nil, "1/b/c", expected, Mosquitto::AT_MOST_ONCE, false)
406
+ wait{ @result }
407
+ assert_equal expected, @result
408
+
409
+ @result = nil
410
+ expected = "should not get this"
411
+ assert @client.publish(nil, "1/2", expected, Mosquitto::AT_MOST_ONCE, false)
412
+ sleep 1
413
+ assert_nil @result
414
+
415
+ @result = nil
416
+ expected = "should not get this either"
417
+ assert @client.publish(nil, "1/2/3/4", expected, Mosquitto::AT_MOST_ONCE, false)
418
+ sleep 1
419
+ assert_nil @result
420
+ end
421
+
422
+ def test_subs
423
+ assert @client.subscribe(nil, "1/2/3", Mosquitto::AT_MOST_ONCE)
424
+ assert @client.subscribe(nil, "a/+/#", Mosquitto::AT_MOST_ONCE)
425
+ assert @client.subscribe(nil, "#", Mosquitto::AT_MOST_ONCE)
426
+
427
+ sleep 1
428
+
429
+ @result = nil
430
+ expected = "should get everything"
431
+ assert @client.publish(nil, "1/2/3/4", expected, Mosquitto::AT_MOST_ONCE, false)
432
+ wait{ @result }
433
+ assert_equal expected, @result
434
+
435
+ @result = nil
436
+ expected = "should get everything"
437
+ assert @client.publish(nil, "a/1/2", expected, Mosquitto::AT_MOST_ONCE, false)
438
+ wait{ @result }
439
+ assert_equal expected, @result
440
+
441
+ assert @client.unsubscribe(nil, "a/+/#")
442
+ assert @client.unsubscribe(nil, "#")
443
+
444
+ sleep 1
445
+
446
+ @result = nil
447
+ expected = "should still get 1/2/3"
448
+ assert @client.publish(nil, "1/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
449
+ wait{ @result }
450
+ assert_equal expected, @result
451
+
452
+ @result = nil
453
+ expected = "should not get anything else"
454
+ assert @client.publish(nil, "a/2/3", expected, Mosquitto::AT_MOST_ONCE, false)
455
+ sleep 1
456
+ assert_nil @result
457
+
458
+ @result = nil
459
+ expected = "should not get anything else"
460
+ assert @client.publish(nil, "a", expected, Mosquitto::AT_MOST_ONCE, false)
461
+ sleep 1
462
+ assert_nil @result
463
+ end
464
+
465
+ def test_duplicate_client_id
466
+ client1_connected = false, client1_disconnected = false
467
+ client2 = nil
468
+ client1 = Mosquitto::Client.new("test_duplicate")
469
+ client1.loop_start
470
+ client1.logger = Logger.new(STDOUT)
471
+ client1.on_connect do |rc|
472
+ client1_connected = true
473
+ end
474
+ client1.on_disconnect do |rc|
475
+ client1_disconnected = true
476
+ client1.loop_stop(true)
477
+ client2.loop_stop(true)
478
+ end
479
+ client1.connect(TEST_HOST, TEST_PORT, 10)
480
+
481
+ client1.wait_readable
482
+
483
+ client2 = Mosquitto::Client.new("test_duplicate")
484
+ client2.loop_start
485
+ client2.logger = Logger.new(STDOUT)
486
+ client2.connect(TEST_HOST, TEST_PORT, 10)
487
+
488
+ client2.wait_readable
489
+
490
+ assert client1_connected
491
+ assert client1_disconnected
492
+ end
493
+
494
+ def test_clean_session
495
+ client1 = Mosquitto::Client.new("test_clean_session")
496
+ client1.logger = Logger.new(STDOUT)
497
+ client1.loop_start
498
+ client1.will_set("l/w/t", "This is an LWT", Mosquitto::AT_LEAST_ONCE, false)
499
+ client1.connect(TEST_HOST, TEST_PORT, 10)
500
+
501
+ assert client1.subscribe(nil, "a/b/c", Mosquitto::AT_LEAST_ONCE)
502
+
503
+ sleep 1
504
+
505
+ @result = nil
506
+ expected = "should not get anything on publish only after the subscribe"
507
+
508
+ client1.on_disconnect do |rc|
509
+ assert @client.publish(nil, "a/b/c", expected, Mosquitto::AT_LEAST_ONCE, false)
510
+ client1.connect(TEST_HOST, TEST_PORT, 10)
511
+ end
512
+
513
+ client1.disconnect
514
+
515
+ sleep 1
516
+
517
+ assert_nil @result
518
+ end
519
+
520
+ def test_retain
521
+ # publish message with retain
522
+ @result = nil
523
+ expected = "should not get anything on publish only after the subscribe"
524
+ assert @client.publish(nil, "a/b/c", expected, Mosquitto::AT_LEAST_ONCE, true)
525
+ sleep 1
526
+ assert_nil @result
527
+
528
+ result = nil
529
+ client1 = Mosquitto::Client.new(nil, true)
530
+ client1.logger = Logger.new(STDOUT)
531
+ client1.loop_start
532
+ client1.on_message do |msg|
533
+ result = msg.to_s
534
+ end
535
+ client1.connect(TEST_HOST, TEST_PORT, 10)
536
+ client1.wait_readable
537
+
538
+ assert client1.subscribe(nil, "a/b/c", Mosquitto::AT_LEAST_ONCE)
539
+
540
+ wait{ result }
541
+ assert_equal expected, result
542
+
543
+ client1.disconnect
544
+
545
+ sleep 1
546
+
547
+ result = nil
548
+ # clear retained message
549
+ assert @client.publish(nil, "a/b/c", "", Mosquitto::AT_LEAST_ONCE, true)
550
+ end
551
+
552
+ def test_lwt
553
+ assert @client.subscribe(nil, "will/topic", Mosquitto::AT_MOST_ONCE)
554
+
555
+ will = "This is an LWT"
556
+ client1 = Mosquitto::Client.new("test_lwt")
557
+ client1.logger = Logger.new(STDOUT)
558
+ client1.loop_start
559
+ client1.will_set("will/topic", will, Mosquitto::AT_LEAST_ONCE, false)
560
+ client1.on_connect do |rc|
561
+ client1.disconnect
562
+ client1.loop_stop(true)
563
+ end
564
+ client1.connect(TEST_HOST, TEST_PORT, 10)
565
+
566
+ client1.wait_readable
567
+
568
+ @result = nil
569
+ wait{ @result }
570
+ assert_equal will, @result
571
+ end
572
+ end