mosquitto 0.2

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.
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