aedes 0.51.2 → 1.0.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.
Files changed (67) hide show
  1. package/.github/actions/sticky-pr-comment/action.yml +55 -0
  2. package/.github/workflows/benchmark-compare-serial.yml +60 -0
  3. package/.github/workflows/ci.yml +12 -17
  4. package/.release-it.json +18 -0
  5. package/.taprc +15 -6
  6. package/README.md +6 -4
  7. package/aedes.d.ts +0 -6
  8. package/aedes.js +270 -238
  9. package/benchmarks/README.md +33 -0
  10. package/benchmarks/pingpong.js +94 -25
  11. package/benchmarks/receiver.js +77 -0
  12. package/benchmarks/report.js +150 -0
  13. package/benchmarks/runBenchmarks.js +118 -0
  14. package/benchmarks/sender.js +86 -0
  15. package/benchmarks/server.js +19 -18
  16. package/checkVersion.js +20 -0
  17. package/docs/Aedes.md +66 -8
  18. package/docs/Client.md +3 -4
  19. package/docs/Examples.md +39 -22
  20. package/docs/MIGRATION.md +50 -0
  21. package/eslint.config.js +8 -0
  22. package/example.js +51 -40
  23. package/examples/clusters/index.js +28 -23
  24. package/examples/clusters/package.json +10 -6
  25. package/lib/client.js +405 -306
  26. package/lib/handlers/connect.js +42 -38
  27. package/lib/handlers/index.js +9 -11
  28. package/lib/handlers/ping.js +2 -3
  29. package/lib/handlers/puback.js +5 -5
  30. package/lib/handlers/publish.js +29 -14
  31. package/lib/handlers/pubrec.js +9 -17
  32. package/lib/handlers/pubrel.js +34 -25
  33. package/lib/handlers/subscribe.js +54 -43
  34. package/lib/handlers/unsubscribe.js +16 -19
  35. package/lib/qos-packet.js +14 -17
  36. package/lib/utils.js +5 -12
  37. package/lib/write.js +4 -5
  38. package/package.json +134 -136
  39. package/test/auth.js +468 -804
  40. package/test/basic.js +613 -575
  41. package/test/bridge.js +44 -40
  42. package/test/client-pub-sub.js +531 -504
  43. package/test/close_socket_by_other_party.js +137 -102
  44. package/test/connect.js +487 -484
  45. package/test/drain-timeout.js +593 -0
  46. package/test/drain-toxiproxy.js +620 -0
  47. package/test/events.js +174 -144
  48. package/test/helper.js +351 -73
  49. package/test/keep-alive.js +40 -67
  50. package/test/meta.js +257 -210
  51. package/test/not-blocking.js +93 -197
  52. package/test/qos1.js +464 -554
  53. package/test/qos2.js +308 -393
  54. package/test/regr-21.js +39 -21
  55. package/test/require.cjs +22 -0
  56. package/test/retain.js +349 -398
  57. package/test/topics.js +176 -183
  58. package/test/types/aedes.test-d.ts +4 -8
  59. package/test/will.js +310 -428
  60. package/types/instance.d.ts +40 -35
  61. package/types/packet.d.ts +10 -10
  62. package/.coveralls.yml +0 -1
  63. package/benchmarks/bombing.js +0 -34
  64. package/benchmarks/bombingQoS1.js +0 -36
  65. package/benchmarks/throughputCounter.js +0 -23
  66. package/benchmarks/throughputCounterQoS1.js +0 -33
  67. package/types/.eslintrc.json +0 -47
package/test/will.js CHANGED
@@ -1,134 +1,127 @@
1
- 'use strict'
2
-
3
- const { test } = require('tap')
4
- const memory = require('aedes-persistence')
5
- const Faketimers = require('@sinonjs/fake-timers')
6
- const { setup, connect, noError } = require('./helper')
7
- const aedes = require('../')
1
+ import { test } from 'node:test'
2
+ import { once } from 'node:events'
3
+ import {
4
+ connect,
5
+ createAndConnect,
6
+ delay,
7
+ setup,
8
+ } from './helper.js'
9
+ import memory from 'aedes-persistence'
10
+ import { Aedes } from '../aedes.js'
11
+
12
+ async function memorySetup (opts) {
13
+ const persistence = memory()
14
+ await persistence.setup(opts)
15
+ return persistence
16
+ }
8
17
 
9
- function willConnect (s, opts, connected) {
10
- opts = opts || {}
18
+ function addWillToOpts (opts = {}) {
11
19
  opts.will = {
12
20
  topic: 'mywill',
13
21
  payload: Buffer.from('last will'),
14
22
  qos: 0,
15
23
  retain: false
16
24
  }
17
-
18
- return connect(s, opts, connected)
25
+ return opts
19
26
  }
20
27
 
21
- test('delivers a will', function (t) {
22
- t.plan(4)
28
+ async function oneWillFromBroker (broker) {
29
+ let received
30
+ const packet = await new Promise(resolve => {
31
+ received = willsFromBroker(broker, resolve)
32
+ })
33
+ return { packet, received }
34
+ }
23
35
 
24
- const opts = {}
25
- // willConnect populates opts with a will
26
- const s = willConnect(setup(),
27
- opts,
28
- function () {
29
- s.conn.destroy()
30
- }
31
- )
32
- t.teardown(s.broker.close.bind(s.broker))
33
-
34
- s.broker.mq.on('mywill', function (packet, cb) {
35
- t.equal(packet.topic, opts.will.topic, 'topic matches')
36
- t.same(packet.payload, opts.will.payload, 'payload matches')
37
- t.equal(packet.qos, opts.will.qos, 'qos matches')
38
- t.equal(packet.retain, opts.will.retain, 'retain matches')
36
+ function willsFromBroker (broker, resolve) {
37
+ const received = []
38
+ broker.mq.on('mywill', (packet, cb) => {
39
+ received.push(packet)
39
40
  cb()
41
+ if (resolve) {
42
+ resolve(packet)
43
+ resolve = null
44
+ }
40
45
  })
41
- })
46
+ return received
47
+ }
42
48
 
43
- test('calling close two times should not deliver two wills', function (t) {
49
+ test('delivers a will', async (t) => {
44
50
  t.plan(4)
45
51
 
46
- const opts = {}
47
- const broker = aedes()
48
- t.teardown(broker.close.bind(broker))
49
-
50
- broker.on('client', function (client) {
51
- client.close()
52
- client.close()
53
- })
52
+ const opts = addWillToOpts({})
53
+ const s = await createAndConnect(t, { connect: opts })
54
+ s.conn.destroy()
54
55
 
55
- broker.mq.on('mywill', onWill)
56
+ const { packet } = await oneWillFromBroker(s.broker)
57
+ t.assert.equal(packet.topic, opts.will.topic, 'topic matches')
58
+ t.assert.deepEqual(packet.payload, opts.will.payload, 'payload matches')
59
+ t.assert.equal(packet.qos, opts.will.qos, 'qos matches')
60
+ t.assert.equal(packet.retain, opts.will.retain, 'retain matches')
61
+ })
56
62
 
57
- // willConnect populates opts with a will
58
- willConnect(setup(broker), opts)
63
+ test('calling close two times should not deliver two wills', async (t) => {
64
+ t.plan(5)
59
65
 
60
- function onWill (packet, cb) {
61
- broker.mq.removeListener('mywill', onWill, function () {
62
- broker.mq.on('mywill', function (packet) {
63
- t.fail('the will must be delivered only once')
64
- })
65
- })
66
- t.equal(packet.topic, opts.will.topic, 'topic matches')
67
- t.same(packet.payload, opts.will.payload, 'payload matches')
68
- t.equal(packet.qos, opts.will.qos, 'qos matches')
69
- t.equal(packet.retain, opts.will.retain, 'retain matches')
70
- cb()
71
- }
66
+ const opts = addWillToOpts({})
67
+ const s = await createAndConnect(t, { connect: opts })
68
+
69
+ const received = willsFromBroker(s.broker)
70
+ s.client.close()
71
+ s.client.close()
72
+ await delay(10) // give Aedes some time to process, potentially twice
73
+ t.assert.equal(received.length, 1, 'only one will has been delivered')
74
+ const packet = received[0]
75
+ t.assert.equal(packet.topic, opts.will.topic, 'topic matches')
76
+ t.assert.deepEqual(packet.payload, opts.will.payload, 'payload matches')
77
+ t.assert.equal(packet.qos, opts.will.qos, 'qos matches')
78
+ t.assert.equal(packet.retain, opts.will.retain, 'retain matches')
72
79
  })
73
80
 
74
- test('delivers old will in case of a crash', function (t) {
81
+ test('delivers old will in case of a crash', async (t) => {
75
82
  t.plan(8)
76
83
 
77
- const persistence = memory()
84
+ const persistence = await memorySetup({ id: 'anotherBroker' })
78
85
  const will = {
79
86
  topic: 'mywill',
80
87
  payload: Buffer.from('last will'),
81
88
  qos: 0,
82
89
  retain: false
83
90
  }
91
+ await persistence.putWill({ id: 'myClientId42' }, will)
84
92
 
85
- persistence.broker = {
86
- id: 'anotherBroker'
87
- }
88
-
89
- persistence.putWill({
90
- id: 'myClientId42'
91
- }, will, function (err) {
92
- t.error(err, 'no error')
93
-
94
- let authorized = false
95
- const interval = 10 // ms, so that the will check happens fast!
96
- const broker = aedes({
97
- persistence,
98
- heartbeatInterval: interval,
99
- authorizePublish: function (client, packet, callback) {
100
- t.strictSame(client, null, 'client must be null')
101
- authorized = true
102
- callback(null)
103
- }
104
- })
105
- t.teardown(broker.close.bind(broker))
106
-
107
- const start = Date.now()
108
-
109
- broker.mq.on('mywill', check)
110
-
111
- function check (packet, cb) {
112
- broker.mq.removeListener('mywill', check, function () {
113
- broker.mq.on('mywill', function (packet) {
114
- t.fail('the will must be delivered only once')
115
- })
116
- })
117
- t.ok(Date.now() - start >= 3 * interval, 'the will needs to be emitted after 3 heartbeats')
118
- t.equal(packet.topic, will.topic, 'topic matches')
119
- t.same(packet.payload, will.payload, 'payload matches')
120
- t.equal(packet.qos, will.qos, 'qos matches')
121
- t.equal(packet.retain, will.retain, 'retain matches')
122
- t.equal(authorized, true, 'authorization called')
123
- cb()
93
+ let authorized = false
94
+ const interval = 10 // ms, so that the will check happens fast!
95
+ const broker = await Aedes.createBroker({
96
+ persistence,
97
+ heartbeatInterval: interval,
98
+ authorizePublish: (client, packet, callback) => {
99
+ t.assert.equal(client, null, 'client must be null')
100
+ authorized = true
101
+ callback(null)
124
102
  }
125
103
  })
104
+
105
+ t.after(() => broker.close())
106
+
107
+ const start = Date.now()
108
+
109
+ const { packet, received } = await oneWillFromBroker(broker)
110
+ t.assert.ok(Date.now() - start >= 3 * interval, 'the will needs to be emitted after 3 heartbeats')
111
+ t.assert.equal(packet.topic, will.topic, 'topic matches')
112
+ t.assert.deepEqual(packet.payload, will.payload, 'payload matches')
113
+ t.assert.equal(packet.qos, will.qos, 'qos matches')
114
+ t.assert.equal(packet.retain, will.retain, 'retain matches')
115
+ t.assert.equal(authorized, true, 'authorization called')
116
+ await delay(10) // give Aedes some time to process, potentially twice
117
+ t.assert.equal(received.length, 1, 'only one will has been delivered')
126
118
  })
127
119
 
128
- test('deliver old will without authorization in case of a crash', function (t) {
129
- t.plan(2)
120
+ test('deliver old will without authorization in case of a crash', async (t) => {
121
+ t.plan(1)
122
+
123
+ const persistence = await memorySetup({ id: 'anotherBroker' })
130
124
 
131
- const persistence = memory()
132
125
  const will = {
133
126
  topic: 'mywill',
134
127
  payload: Buffer.from('last will'),
@@ -136,346 +129,257 @@ test('deliver old will without authorization in case of a crash', function (t) {
136
129
  retain: false
137
130
  }
138
131
 
139
- persistence.broker = {
140
- id: 'anotherBroker'
141
- }
142
-
143
- persistence.putWill({
144
- id: 'myClientId42'
145
- }, will, function (err) {
146
- t.error(err, 'no error')
147
-
148
- const interval = 10 // ms, so that the will check happens fast!
149
- const broker = aedes({
150
- persistence,
151
- heartbeatInterval: interval,
152
- authorizePublish: function (client, packet, callback) {
153
- t.strictSame(client, null, 'client must be null')
154
- callback(new Error())
155
- }
156
- })
157
-
158
- t.teardown(broker.close.bind(broker))
132
+ await persistence.putWill({ id: 'myClientId42' }, will)
159
133
 
160
- broker.mq.on('mywill', check)
161
-
162
- function check (packet, cb) {
163
- t.fail('received will without authorization')
164
- cb()
134
+ const interval = 10 // ms, so that the will check happens fast!
135
+ const broker = await Aedes.createBroker({
136
+ persistence,
137
+ heartbeatInterval: interval,
138
+ authorizePublish: function (client, packet, callback) {
139
+ t.assert.equal(client, null, 'client must be null')
140
+ callback(new Error())
165
141
  }
166
142
  })
143
+ t.after(() => broker.close())
144
+ const received = willsFromBroker(broker)
145
+ await delay(10) // give Aedes some time to process to ensure that no will is send
146
+ t.assert.equal(received.length, 0, 'no will has been delivered')
167
147
  })
168
148
 
169
- test('delete old broker', function (t) {
149
+ test('delete old broker', async (t) => {
170
150
  t.plan(1)
171
151
 
172
- const clock = Faketimers.install()
173
-
174
152
  const heartbeatInterval = 100
175
- const broker = aedes({
153
+ const broker = await Aedes.createBroker({
176
154
  heartbeatInterval
177
155
  })
178
- t.teardown(broker.close.bind(broker))
156
+ t.after(() => broker.close())
179
157
 
180
158
  const brokerId = 'dummyBroker'
181
159
 
182
160
  broker.brokers[brokerId] = Date.now() - heartbeatInterval * 3.5
183
161
 
184
- setTimeout(() => {
185
- t.equal(broker.brokers[brokerId], undefined, 'Broker deleted')
186
- }, heartbeatInterval * 4)
187
-
188
- clock.tick(heartbeatInterval * 4)
189
-
190
- clock.uninstall()
162
+ await delay(heartbeatInterval * 4)
163
+ t.assert.equal(broker.brokers[brokerId], undefined, 'Broker deleted')
191
164
  })
192
165
 
193
- test('store the will in the persistence', function (t) {
194
- t.plan(5)
166
+ test('store the will in the persistence', async (t) => {
167
+ t.plan(4)
195
168
 
196
- const opts = {
169
+ const opts = addWillToOpts({
197
170
  clientId: 'abcde'
198
- }
199
-
200
- // willConnect populates opts with a will
201
- const s = willConnect(setup(), opts)
202
- t.teardown(s.broker.close.bind(s.broker))
203
-
204
- s.broker.on('client', function () {
205
- // this is connack
206
- s.broker.persistence.getWill({
207
- id: opts.clientId
208
- }, function (err, packet) {
209
- t.error(err, 'no error')
210
- t.same(packet.topic, opts.will.topic, 'will topic matches')
211
- t.same(packet.payload, opts.will.payload, 'will payload matches')
212
- t.same(packet.qos, opts.will.qos, 'will qos matches')
213
- t.same(packet.retain, opts.will.retain, 'will retain matches')
214
- })
215
171
  })
216
- })
217
172
 
218
- test('delete the will in the persistence after publish', function (t) {
219
- t.plan(2)
173
+ const s = await createAndConnect(t, { connect: opts })
220
174
 
221
- const opts = {
222
- clientId: 'abcde'
223
- }
175
+ const packet = await s.broker.persistence.getWill({ id: opts.clientId })
176
+ t.assert.deepEqual(structuredClone(packet).topic, opts.will.topic, 'will topic matches')
177
+ t.assert.deepEqual(structuredClone(packet).payload, opts.will.payload, 'will payload matches')
178
+ t.assert.deepEqual(structuredClone(packet).qos, opts.will.qos, 'will qos matches')
179
+ t.assert.deepEqual(structuredClone(packet).retain, opts.will.retain, 'will retain matches')
180
+ })
224
181
 
225
- const broker = aedes()
226
- t.teardown(broker.close.bind(broker))
182
+ test('delete the will in the persistence after publish', async (t) => {
183
+ t.plan(1)
227
184
 
228
- broker.on('client', function (client) {
229
- setImmediate(function () {
230
- client.close()
231
- })
185
+ const opts = addWillToOpts({
186
+ clientId: 'abcde'
232
187
  })
233
188
 
234
- broker.mq.on('mywill', check)
235
-
236
- // willConnect populates opts with a will
237
- willConnect(setup(broker), opts)
189
+ const s = await createAndConnect(t, { connect: opts })
238
190
 
239
- function check (packet, cb) {
240
- broker.mq.removeListener('mywill', check, function () {
241
- broker.persistence.getWill({
242
- id: opts.clientId
243
- }, function (err, p) {
244
- t.error(err, 'no error')
245
- t.notOk(p, 'packet is empty')
246
- })
247
- })
248
- cb()
249
- }
191
+ await new Promise(resolve => {
192
+ willsFromBroker(s.broker, resolve) // setup the listener
193
+ s.client.close()
194
+ })
195
+ const packet = await s.broker.persistence.getWill({ id: opts.clientId })
196
+ t.assert.ok(!packet, 'packet is empty')
250
197
  })
251
198
 
252
- test('delivers a will with authorization', function (t) {
253
- t.plan(6)
199
+ test('delivers a will with authorization', async (t) => {
200
+ t.plan(7)
254
201
 
255
202
  let authorized = false
256
- const opts = {}
257
- // willConnect populates opts with a will
258
- const s = willConnect(
259
- setup(aedes({
203
+
204
+ const opts = addWillToOpts({})
205
+ const s = await createAndConnect(t, {
206
+ broker: {
260
207
  authorizePublish: (client, packet, callback) => {
261
208
  authorized = true
262
209
  callback(null)
263
210
  }
264
- })),
265
- opts,
266
- function () {
267
- s.conn.destroy()
268
- }
269
- )
270
- t.teardown(s.broker.close.bind(s.broker))
271
-
272
- s.broker.on('clientDisconnect', function (client) {
273
- t.equal(client.connected, false)
211
+ },
212
+ connect: opts
274
213
  })
275
214
 
276
- s.broker.mq.on('mywill', function (packet, cb) {
277
- t.equal(packet.topic, opts.will.topic, 'topic matches')
278
- t.same(packet.payload, opts.will.payload, 'payload matches')
279
- t.equal(packet.qos, opts.will.qos, 'qos matches')
280
- t.equal(packet.retain, opts.will.retain, 'retain matches')
281
- t.equal(authorized, true, 'authorization called')
282
- cb()
283
- })
215
+ const received = willsFromBroker(s.broker)
216
+ s.conn.destroy()
217
+
218
+ const [client] = await once(s.broker, 'clientDisconnect')
219
+ t.assert.equal(client.connected, false)
220
+ t.assert.equal(received.length, 1, 'only one will has been delivered')
221
+ const packet = received[0]
222
+ t.assert.equal(packet.topic, opts.will.topic, 'topic matches')
223
+ t.assert.deepEqual(packet.payload, opts.will.payload, 'payload matches')
224
+ t.assert.equal(packet.qos, opts.will.qos, 'qos matches')
225
+ t.assert.equal(packet.retain, opts.will.retain, 'retain matches')
226
+ t.assert.equal(authorized, true, 'authorization called')
284
227
  })
285
228
 
286
- test('delivers a will waits for authorization', function (t) {
287
- t.plan(6)
229
+ test('delivers a will waits for authorization', async (t) => {
230
+ t.plan(7)
288
231
 
289
232
  let authorized = false
290
- const opts = {}
291
- // willConnect populates opts with a will
292
- const s = willConnect(
293
- setup(aedes({
233
+ const opts = addWillToOpts({})
234
+ const s = await createAndConnect(t, {
235
+ broker: {
294
236
  authorizePublish: (client, packet, callback) => {
295
237
  authorized = true
296
238
  setImmediate(() => { callback(null) })
297
239
  }
298
- })),
299
- opts,
300
- function () {
301
- s.conn.destroy()
302
- }
303
- )
304
- t.teardown(s.broker.close.bind(s.broker))
305
-
306
- s.broker.on('clientDisconnect', function () {
307
- t.pass('client is disconnected')
308
- })
309
-
310
- s.broker.mq.on('mywill', function (packet, cb) {
311
- t.equal(packet.topic, opts.will.topic, 'topic matches')
312
- t.same(packet.payload, opts.will.payload, 'payload matches')
313
- t.equal(packet.qos, opts.will.qos, 'qos matches')
314
- t.equal(packet.retain, opts.will.retain, 'retain matches')
315
- t.equal(authorized, true, 'authorization called')
316
- cb()
240
+ },
241
+ connect: opts
317
242
  })
243
+ const received = willsFromBroker(s.broker)
244
+ s.conn.destroy()
245
+
246
+ const [client] = await once(s.broker, 'clientDisconnect')
247
+ t.assert.equal(client.connected, false)
248
+ t.assert.equal(authorized, true, 'authorization called')
249
+ await delay(10) // give Aedes time to complete authorizePublish
250
+ t.assert.equal(received.length, 1, 'only one will has been delivered')
251
+ const packet = received[0]
252
+ t.assert.equal(packet.topic, opts.will.topic, 'topic matches')
253
+ t.assert.deepEqual(structuredClone(packet).payload, opts.will.payload, 'payload matches')
254
+ t.assert.equal(packet.qos, opts.will.qos, 'qos matches')
255
+ t.assert.equal(packet.retain, opts.will.retain, 'retain matches')
318
256
  })
319
257
 
320
- test('does not deliver a will without authorization', function (t) {
321
- t.plan(1)
258
+ test('does not deliver a will without authorization', async (t) => {
259
+ t.plan(2)
322
260
 
323
261
  let authorized = false
324
- const opts = {}
325
- // willConnect populates opts with a will
326
- const s = willConnect(
327
- setup(aedes({
328
- authorizePublish: (username, packet, callback) => {
262
+ const opts = addWillToOpts({})
263
+ const s = await createAndConnect(t, {
264
+ broker: {
265
+ authorizePublish: (client, packet, callback) => {
329
266
  authorized = true
330
267
  callback(new Error())
331
268
  }
332
- })),
333
- opts,
334
- function () {
335
- s.conn.destroy()
336
- }
337
- )
338
- t.teardown(s.broker.close.bind(s.broker))
339
-
340
- s.broker.on('clientDisconnect', function () {
341
- t.equal(authorized, true, 'authorization called')
269
+ },
270
+ connect: opts
342
271
  })
272
+ const received = willsFromBroker(s.broker)
273
+ s.conn.destroy()
343
274
 
344
- s.broker.mq.on('mywill', function (packet, cb) {
345
- t.fail('received will without authorization')
346
- cb()
347
- })
275
+ await once(s.broker, 'clientDisconnect')
276
+ t.assert.equal(authorized, true, 'authorization called')
277
+ await delay(10) // give Aedes time to complete authorizePublish
278
+ t.assert.equal(received.length, 0, 'received no will without authorization')
348
279
  })
349
280
 
350
- test('does not deliver a will without authentication', function (t) {
351
- t.plan(1)
281
+ test('does not deliver a will without authentication', async (t) => {
282
+ t.plan(2)
352
283
 
353
284
  let authenticated = false
354
- const opts = {}
355
- // willConnect populates opts with a will
356
- const s = willConnect(
357
- setup(aedes({
285
+ const opts = addWillToOpts({})
286
+ const s = await createAndConnect(t, {
287
+ broker: {
358
288
  authenticate: (client, username, password, callback) => {
359
289
  authenticated = true
360
290
  callback(new Error(), false)
361
291
  }
362
- })),
363
- opts
364
- )
365
- t.teardown(s.broker.close.bind(s.broker))
366
-
367
- s.broker.on('clientError', function () {
368
- t.equal(authenticated, true, 'authentication called')
369
- t.end()
370
- })
371
-
372
- s.broker.mq.on('mywill', function (packet, cb) {
373
- t.fail('received will without authentication')
374
- cb()
292
+ },
293
+ connect: opts,
294
+ expectedReturnCode: 5
375
295
  })
296
+ const received = willsFromBroker(s.broker)
297
+ await once(s.broker, 'clientError')
298
+ t.assert.equal(authenticated, true, 'authentication called')
299
+ await delay(10) // give Aedes time to complete authenticate
300
+ t.assert.equal(received.length, 0, 'received no will without authentication')
376
301
  })
377
302
 
378
- test('does not deliver will if broker is closed during authentication', function (t) {
379
- t.plan(0)
303
+ test('does not deliver will if broker is closed during authentication', async (t) => {
304
+ t.plan(2)
380
305
 
381
- const opts = { keepalive: 1 }
306
+ const opts = addWillToOpts({ keepalive: 1 })
382
307
 
383
- const broker = aedes({
384
- authenticate: function (client, username, password, callback) {
385
- setTimeout(function () {
386
- callback(null, true)
387
- })
388
- broker.close()
389
- }
390
- })
308
+ const broker = await Aedes.createBroker()
309
+ broker.authenticate = (client, username, password, callback) => {
310
+ setImmediate(() => {
311
+ callback(null, true)
312
+ })
313
+ broker.close()
314
+ }
391
315
 
392
- broker.on('keepaliveTimeout', function () {
393
- t.fail('keepalive timer shoud not be set')
316
+ broker.on('keepaliveTimeout', () => {
317
+ t.assert.fail('keepalive timer shoud not be set')
394
318
  })
395
319
 
396
- broker.mq.on('mywill', function (packet, cb) {
397
- t.fail('Received will when it was not expected')
398
- cb()
399
- })
320
+ const received = willsFromBroker(broker)
400
321
 
401
- willConnect(setup(broker), opts)
322
+ const s = setup(broker)
323
+ await connect(s, { connect: opts, noWait: true })
324
+ await delay(1) // give Aedes some time to close the broker
325
+ t.assert.equal(broker.closed, true, 'broker closed')
326
+ t.assert.equal(received.length, 0, 'received no will')
402
327
  })
403
328
 
404
329
  // [MQTT-3.14.4-3]
405
- test('does not deliver will when client sends a DISCONNECT', function (t) {
406
- t.plan(0)
407
-
408
- const broker = aedes()
409
- t.teardown(broker.close.bind(broker))
410
-
411
- const s = noError(willConnect(setup(broker), {}, function () {
412
- s.inStream.end({
413
- cmd: 'disconnect'
414
- })
415
- }), t)
330
+ test('does not deliver will when client sends a DISCONNECT', async (t) => {
331
+ t.plan(2)
416
332
 
417
- s.broker.mq.on('mywill', function (packet, cb) {
418
- t.fail(packet)
419
- cb()
333
+ const opts = addWillToOpts({ keepalive: 1 })
334
+ const s = await createAndConnect(t, { connect: opts })
335
+ const received = willsFromBroker(s.broker)
336
+ s.inStream.write({
337
+ cmd: 'disconnect'
420
338
  })
339
+
340
+ await once(s.broker, 'clientDisconnect')
341
+ t.assert.ok(!s.client.connected, 'disconnected')
342
+ t.assert.equal(received.length, 0, 'received no will')
421
343
  })
422
344
 
423
- test('deletes from persistence on DISCONNECT', function (t) {
424
- t.plan(2)
345
+ test('deletes from persistence on DISCONNECT', async (t) => {
346
+ t.plan(1)
425
347
 
426
- const opts = {
348
+ const opts = addWillToOpts({
427
349
  clientId: 'abcde'
428
- }
429
- const broker = aedes()
430
- t.teardown(broker.close.bind(broker))
431
-
432
- const s = noError(willConnect(setup(broker), opts, function () {
433
- s.inStream.end({
434
- cmd: 'disconnect'
435
- })
436
- }), t)
437
-
438
- s.broker.persistence.getWill({
439
- id: opts.clientId
440
- }, function (err, packet) {
441
- t.error(err, 'no error')
442
- t.notOk(packet)
443
350
  })
351
+ const s = await createAndConnect(t, { connect: opts })
352
+ s.inStream.end({
353
+ cmd: 'disconnect'
354
+ })
355
+ await once(s.broker, 'clientDisconnect')
356
+ const packet = await s.broker.persistence.getWill({ id: opts.clientId })
357
+ t.assert.ok(!packet, 'no packet present')
444
358
  })
445
359
 
446
- test('does not store multiple will with same clientid', function (t) {
447
- t.plan(4)
448
-
449
- const opts = { clientId: 'abcde' }
450
-
451
- const broker = aedes()
360
+ test('does not store multiple will with same clientid', async (t) => {
361
+ t.plan(2)
452
362
 
453
- let s = noError(willConnect(setup(broker), opts, function () {
454
- // gracefully close client so no will is sent
455
- s.inStream.end({
456
- cmd: 'disconnect'
457
- })
458
- }), t)
459
-
460
- broker.on('clientDisconnect', function (client) {
461
- // reconnect same client with will
462
- s = willConnect(setup(broker), opts, function () {
463
- // check that there are not 2 will messages for the same clientid
464
- s.broker.persistence.delWill({ id: opts.clientId }, function (err, packet) {
465
- t.error(err, 'no error')
466
- t.equal(packet.clientId, opts.clientId, 'will packet found')
467
- s.broker.persistence.delWill({ id: opts.clientId }, function (err, packet) {
468
- t.error(err, 'no error')
469
- t.equal(!!packet, false, 'no duplicated packets')
470
- broker.close()
471
- })
472
- })
473
- })
363
+ const opts = addWillToOpts({
364
+ clientId: 'abcde'
474
365
  })
366
+ const s = await createAndConnect(t, { connect: opts })
367
+ s.inStream.end({
368
+ cmd: 'disconnect'
369
+ })
370
+ await once(s.broker, 'clientDisconnect')
371
+ const s2 = setup(s.broker)
372
+ await connect(s2, { connect: opts })
373
+
374
+ // check that there are not 2 will messages for the same clientid
375
+ const packet1 = await s.broker.persistence.delWill({ id: opts.clientId })
376
+ t.assert.equal(packet1.clientId, opts.clientId, 'will packet found')
377
+ const packet2 = await s.broker.persistence.delWill({ id: opts.clientId })
378
+ t.assert.ok(!packet2, 'no duplicate will packets')
475
379
  })
476
380
 
477
- test('don\'t delivers a will if broker alive', function (t) {
478
- const persistence = memory()
381
+ test('don\'t deliver a will if broker alive', async (t) => {
382
+ t.plan(6)
479
383
  const will = {
480
384
  topic: 'mywill',
481
385
  payload: Buffer.from('last will'),
@@ -485,50 +389,42 @@ test('don\'t delivers a will if broker alive', function (t) {
485
389
 
486
390
  const oldBroker = 'broker1'
487
391
 
488
- persistence.broker = {
489
- id: oldBroker
490
- }
491
-
492
- persistence.putWill({
493
- id: 'myClientId42'
494
- }, will, function (err) {
495
- t.error(err, 'no error')
496
-
497
- const opts = {
498
- persistence,
499
- heartbeatInterval: 10
500
- }
501
-
502
- let count = 0
503
-
504
- const broker = aedes(opts)
505
- t.teardown(broker.close.bind(broker))
392
+ const persistence = await memorySetup({ id: oldBroker })
393
+ await persistence.putWill({ id: 'myClientId42' }, will)
506
394
 
507
- const streamWill = persistence.streamWill
508
- persistence.streamWill = function () {
509
- // don't pass broker.brokers to streamWill
510
- return streamWill.call(persistence)
511
- }
395
+ const opts = {
396
+ persistence,
397
+ heartbeatInterval: 10
398
+ }
512
399
 
513
- broker.mq.on('mywill', function (packet, cb) {
514
- t.fail('Will received')
515
- cb()
516
- })
400
+ const broker = await Aedes.createBroker(opts)
401
+ t.after(() => broker.close())
517
402
 
518
- broker.mq.on('$SYS/+/heartbeat', function () {
519
- t.pass('Heartbeat received')
403
+ const streamWill = persistence.streamWill
404
+ persistence.streamWill = () => {
405
+ // don't pass broker.brokers to streamWill
406
+ return streamWill.call(persistence)
407
+ }
408
+ // catch any wills published
409
+ const received = willsFromBroker(broker)
410
+
411
+ // let the broker run for 5 heartbeats
412
+ let count = 0
413
+ await new Promise((resolve) => {
414
+ broker.mq.on('$SYS/+/heartbeat', () => {
415
+ t.assert.ok(true, 'Heartbeat received')
520
416
  broker.brokers[oldBroker] = Date.now()
521
-
522
417
  if (++count === 5) {
523
- t.end()
418
+ resolve()
524
419
  }
525
420
  })
526
421
  })
422
+ t.assert.equal(received.length, 0, 'received no will')
527
423
  })
528
424
 
529
- test('handle will publish error', function (t) {
530
- t.plan(2)
531
- const persistence = memory()
425
+ test('handle will publish error', async (t) => {
426
+ t.plan(1)
427
+
532
428
  const will = {
533
429
  topic: 'mywill',
534
430
  payload: Buffer.from('last will'),
@@ -536,36 +432,29 @@ test('handle will publish error', function (t) {
536
432
  retain: false
537
433
  }
538
434
 
539
- persistence.broker = {
540
- id: 'broker1'
541
- }
435
+ const persistence = await memorySetup({ id: 'broker1' })
436
+ await persistence.putWill({ id: 'myClientId42' }, will)
542
437
 
543
- persistence.putWill({
544
- id: 'myClientId42'
545
- }, will, function (err) {
546
- t.error(err, 'no error')
547
-
548
- const opts = {
549
- persistence,
550
- heartbeatInterval: 10
551
- }
438
+ const opts = {
439
+ persistence,
440
+ heartbeatInterval: 10
441
+ }
552
442
 
553
- persistence.delWill = function (client, cb) {
554
- cb(new Error('Throws error'))
555
- }
443
+ // fake an error
444
+ persistence.delWill = async client => {
445
+ throw new Error('Throws error')
446
+ }
556
447
 
557
- const broker = aedes(opts)
558
- t.teardown(broker.close.bind(broker))
448
+ const broker = await Aedes.createBroker(opts)
449
+ t.after(() => broker.close())
559
450
 
560
- broker.once('error', function (err) {
561
- t.equal('Throws error', err.message, 'throws error')
562
- })
563
- })
451
+ const [err] = await once(broker, 'error')
452
+ t.assert.equal('Throws error', err.message, 'throws error')
564
453
  })
565
454
 
566
- test('handle will publish error 2', function (t) {
567
- t.plan(2)
568
- const persistence = memory()
455
+ test('handle will publish error 2', async (t) => {
456
+ t.plan(1)
457
+
569
458
  const will = {
570
459
  topic: 'mywill',
571
460
  payload: Buffer.from('last will'),
@@ -573,29 +462,22 @@ test('handle will publish error 2', function (t) {
573
462
  retain: true
574
463
  }
575
464
 
576
- persistence.broker = {
577
- id: 'broker1'
578
- }
579
-
580
- persistence.putWill({
581
- id: 'myClientId42'
582
- }, will, function (err) {
583
- t.error(err, 'no error')
465
+ const persistence = await memorySetup({ id: 'broker1' })
466
+ await persistence.putWill({ id: 'myClientId42' }, will)
584
467
 
585
- const opts = {
586
- persistence,
587
- heartbeatInterval: 10
588
- }
468
+ const opts = {
469
+ persistence,
470
+ heartbeatInterval: 10
471
+ }
589
472
 
590
- persistence.storeRetained = function (packet, cb) {
591
- cb(new Error('Throws error'))
592
- }
473
+ // fake error
474
+ persistence.storeRetained = async packet => {
475
+ throw new Error('Throws error')
476
+ }
593
477
 
594
- const broker = aedes(opts)
595
- t.teardown(broker.close.bind(broker))
478
+ const broker = await Aedes.createBroker(opts)
479
+ t.after(() => broker.close())
596
480
 
597
- broker.once('error', function (err) {
598
- t.equal('Throws error', err.message, 'throws error')
599
- })
600
- })
481
+ const [err] = await once(broker, 'error')
482
+ t.assert.equal('Throws error', err.message, 'throws error')
601
483
  })