aedes 0.51.3 → 1.0.1

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 (68) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.github/actions/sticky-pr-comment/action.yml +55 -0
  3. package/.github/workflows/benchmark-compare-serial.yml +60 -0
  4. package/.github/workflows/ci.yml +12 -17
  5. package/.release-it.json +18 -0
  6. package/.taprc +15 -6
  7. package/README.md +6 -4
  8. package/aedes.d.ts +0 -6
  9. package/aedes.js +270 -242
  10. package/benchmarks/README.md +33 -0
  11. package/benchmarks/pingpong.js +94 -25
  12. package/benchmarks/receiver.js +77 -0
  13. package/benchmarks/report.js +150 -0
  14. package/benchmarks/runBenchmarks.js +118 -0
  15. package/benchmarks/sender.js +86 -0
  16. package/benchmarks/server.js +19 -18
  17. package/checkVersion.js +20 -0
  18. package/docs/Aedes.md +66 -8
  19. package/docs/Client.md +3 -4
  20. package/docs/Examples.md +39 -22
  21. package/docs/MIGRATION.md +50 -0
  22. package/eslint.config.js +8 -0
  23. package/example.js +51 -40
  24. package/examples/clusters/index.js +28 -23
  25. package/examples/clusters/package.json +10 -6
  26. package/lib/client.js +405 -306
  27. package/lib/handlers/connect.js +42 -38
  28. package/lib/handlers/index.js +9 -11
  29. package/lib/handlers/ping.js +2 -3
  30. package/lib/handlers/puback.js +5 -5
  31. package/lib/handlers/publish.js +29 -14
  32. package/lib/handlers/pubrec.js +9 -17
  33. package/lib/handlers/pubrel.js +34 -25
  34. package/lib/handlers/subscribe.js +47 -43
  35. package/lib/handlers/unsubscribe.js +16 -19
  36. package/lib/qos-packet.js +14 -17
  37. package/lib/utils.js +5 -12
  38. package/lib/write.js +4 -5
  39. package/package.json +139 -136
  40. package/test/auth.js +468 -804
  41. package/test/basic.js +613 -575
  42. package/test/bridge.js +44 -40
  43. package/test/client-pub-sub.js +531 -504
  44. package/test/close_socket_by_other_party.js +137 -102
  45. package/test/connect.js +487 -484
  46. package/test/drain-timeout.js +593 -0
  47. package/test/drain-toxiproxy.js +620 -0
  48. package/test/events.js +173 -145
  49. package/test/helper.js +351 -73
  50. package/test/keep-alive.js +40 -67
  51. package/test/meta.js +257 -210
  52. package/test/not-blocking.js +93 -197
  53. package/test/qos1.js +464 -554
  54. package/test/qos2.js +308 -393
  55. package/test/regr-21.js +39 -21
  56. package/test/require.cjs +22 -0
  57. package/test/retain.js +349 -398
  58. package/test/topics.js +176 -183
  59. package/test/types/aedes.test-d.ts +4 -8
  60. package/test/will.js +310 -428
  61. package/types/instance.d.ts +40 -35
  62. package/types/packet.d.ts +10 -10
  63. package/.coveralls.yml +0 -1
  64. package/benchmarks/bombing.js +0 -34
  65. package/benchmarks/bombingQoS1.js +0 -36
  66. package/benchmarks/throughputCounter.js +0 -23
  67. package/benchmarks/throughputCounterQoS1.js +0 -33
  68. package/types/.eslintrc.json +0 -47
package/test/auth.js CHANGED
@@ -1,430 +1,151 @@
1
- 'use strict'
2
-
3
- const { test } = require('tap')
4
- const eos = require('end-of-stream')
5
- const Faketimers = require('@sinonjs/fake-timers')
6
- const Client = require('../lib/client')
7
- const { setup, connect, noError, subscribe, subscribeMultiple } = require('./helper')
8
- const aedes = require('../')
9
-
10
- test('authenticate successfully a client with username and password', function (t) {
11
- t.plan(4)
12
-
13
- const s = noError(setup())
14
- t.teardown(s.broker.close.bind(s.broker))
15
-
16
- s.broker.authenticate = function (client, username, password, cb) {
17
- t.type(client, Client, 'client is there')
18
- t.equal(username, 'my username', 'username is there')
19
- t.same(password, Buffer.from('my pass'), 'password is there')
1
+ import { test } from 'node:test'
2
+ import { once } from 'node:events'
3
+ import Client from '../lib/client.js'
4
+ import {
5
+ connect,
6
+ createAndConnect,
7
+ nextPacket,
8
+ nextPacketWithTimeOut,
9
+ setup,
10
+ subscribe,
11
+ subscribeMultiple,
12
+ } from './helper.js'
13
+ import { Aedes } from '../aedes.js'
14
+
15
+ async function testAuthenticationError (t, errObject, expectedReturnCode) {
16
+ const authenticate = (client, username, password, cb) => {
17
+ t.assert.equal(client instanceof Client, true, 'client is there')
18
+ t.assert.equal(username, 'my username', 'username is there')
19
+ t.assert.equal(password.toString(), 'my pass', 'password is there')
20
+ cb(errObject, null)
21
+ }
22
+ const broker = await Aedes.createBroker({ authenticate })
23
+ t.after(() => broker.close())
24
+ broker.on('clientReady', (client) => {
25
+ throw new Error('client should not ready')
26
+ })
27
+ const packet = await connect(setup(broker), { verifyReturnedOk: false })
28
+ t.assert.deepEqual(structuredClone(packet), {
29
+ cmd: 'connack',
30
+ returnCode: expectedReturnCode,
31
+ length: 2,
32
+ qos: 0,
33
+ retain: false,
34
+ dup: false,
35
+ topic: null,
36
+ payload: null,
37
+ sessionPresent: false
38
+ }, 'unsuccessful connack, unauthorized')
39
+ const [client, err] = await once(broker, 'clientError')
40
+ t.assert.equal(client.id, 'my-client')
41
+ t.assert.equal(err.errorCode, expectedReturnCode)
42
+ t.assert.equal(err.message, 'Auth error')
43
+ t.assert.equal(broker.connectedClients, 0, 'no connected clients')
44
+ }
45
+
46
+ test('authenticate successfully a client with username and password', async (t) => {
47
+ t.plan(5)
48
+ const authenticate = (client, username, password, cb) => {
49
+ t.assert.equal(client instanceof Client, true, 'client is there')
50
+ t.assert.equal(username, 'my username', 'username is there')
51
+ t.assert.equal(password.toString(), 'my pass', 'password is there')
20
52
  cb(null, true)
21
53
  }
22
-
23
- s.inStream.write({
24
- cmd: 'connect',
25
- protocolId: 'MQTT',
26
- protocolVersion: 4,
27
- clean: true,
28
- clientId: 'my-client',
29
- username: 'my username',
30
- password: 'my pass',
31
- keepalive: 0
32
- })
33
-
34
- s.outStream.on('data', function (packet) {
35
- t.same(packet, {
36
- cmd: 'connack',
37
- returnCode: 0,
38
- length: 2,
39
- qos: 0,
40
- retain: false,
41
- dup: false,
42
- topic: null,
43
- payload: null,
44
- sessionPresent: false
45
- }, 'successful connack')
46
- })
54
+ const broker = await Aedes.createBroker()
55
+ // explicitly override authenticate instead of passing it as a parameter
56
+ broker.authenticate = authenticate
57
+ t.after(() => broker.close())
58
+ const packet = await connect(setup(broker))
59
+ t.assert.deepEqual(structuredClone(packet), {
60
+ cmd: 'connack',
61
+ returnCode: 0,
62
+ length: 2,
63
+ qos: 0,
64
+ retain: false,
65
+ dup: false,
66
+ topic: null,
67
+ payload: null,
68
+ sessionPresent: false
69
+ }, 'successful connack')
70
+ t.assert.equal(broker.connectedClients, 1, 'one connected client')
47
71
  })
48
72
 
49
- test('authenticate unsuccessfully a client with username and password', function (t) {
50
- t.plan(6)
51
-
52
- const s = setup()
53
- t.teardown(s.broker.close.bind(s.broker))
54
-
55
- s.broker.authenticate = function (client, username, password, cb) {
56
- t.type(client, Client, 'client is there')
57
- t.equal(username, 'my username', 'username is there')
58
- t.same(password, Buffer.from('my pass'), 'password is there')
73
+ test('authenticate unsuccessfully a client with username and password', async (t) => {
74
+ t.plan(7)
75
+ const authenticate = (client, username, password, cb) => {
76
+ t.assert.equal(client instanceof Client, true, 'client is there')
77
+ t.assert.equal(username, 'my username', 'username is there')
78
+ t.assert.equal(password.toString(), 'my pass', 'password is there')
59
79
  cb(null, false)
60
80
  }
61
-
62
- s.broker.on('clientError', function (client, err) {
63
- t.equal(err.errorCode, 5)
64
- })
65
-
66
- s.broker.on('clientReady', function (client) {
67
- t.fail('client should not ready')
68
- })
69
-
70
- s.outStream.on('data', function (packet) {
71
- t.same(packet, {
72
- cmd: 'connack',
73
- returnCode: 5,
74
- length: 2,
75
- qos: 0,
76
- retain: false,
77
- dup: false,
78
- topic: null,
79
- payload: null,
80
- sessionPresent: false
81
- }, 'unsuccessful connack, unauthorized')
82
- })
83
-
84
- eos(s.outStream, function () {
85
- t.equal(s.broker.connectedClients, 0, 'no connected clients')
81
+ const broker = await Aedes.createBroker({ authenticate })
82
+ t.after(() => broker.close())
83
+ broker.on('clientReady', (client) => {
84
+ throw new Error('client should not ready')
86
85
  })
87
86
 
88
- s.inStream.write({
89
- cmd: 'connect',
90
- protocolId: 'MQTT',
91
- protocolVersion: 4,
92
- clean: true,
93
- clientId: 'my-client',
94
- username: 'my username',
95
- password: 'my pass',
96
- keepalive: 0
97
- })
87
+ const packet = await connect(setup(broker), { verifyReturnedOk: false })
88
+ t.assert.deepEqual(structuredClone(packet), {
89
+ cmd: 'connack',
90
+ returnCode: 5,
91
+ length: 2,
92
+ qos: 0,
93
+ retain: false,
94
+ dup: false,
95
+ topic: null,
96
+ payload: null,
97
+ sessionPresent: false
98
+ })
99
+ const [client, err] = await once(broker, 'clientError')
100
+ t.assert.equal(client.id, 'my-client')
101
+ t.assert.equal(err.errorCode, 5)
102
+ t.assert.equal(broker.connectedClients, 0, 'no connected clients')
98
103
  })
99
104
 
100
- test('authenticate errors', function (t) {
101
- t.plan(7)
102
-
103
- const s = setup()
104
- t.teardown(s.broker.close.bind(s.broker))
105
-
106
- s.broker.authenticate = function (client, username, password, cb) {
107
- t.type(client, Client, 'client is there')
108
- t.equal(username, 'my username', 'username is there')
109
- t.same(password, Buffer.from('my pass'), 'password is there')
110
- cb(new Error('this should happen!'))
111
- }
112
-
113
- s.broker.on('clientError', function (client, err) {
114
- t.equal(err.message, 'this should happen!')
115
- t.equal(err.errorCode, 5)
116
- })
117
-
118
- s.broker.on('clientReady', function (client) {
119
- t.fail('client should not ready')
120
- })
121
-
122
- s.outStream.on('data', function (packet) {
123
- t.same(packet, {
124
- cmd: 'connack',
125
- returnCode: 5,
126
- length: 2,
127
- qos: 0,
128
- retain: false,
129
- dup: false,
130
- topic: null,
131
- payload: null,
132
- sessionPresent: false
133
- }, 'unsuccessful connack, unauthorized')
134
- })
135
-
136
- eos(s.outStream, function () {
137
- t.equal(s.broker.connectedClients, 0, 'no connected clients')
138
- })
139
-
140
- s.inStream.write({
141
- cmd: 'connect',
142
- protocolId: 'MQTT',
143
- protocolVersion: 4,
144
- clean: true,
145
- clientId: 'my-client',
146
- username: 'my username',
147
- password: 'my pass',
148
- keepalive: 0
149
- })
105
+ test('authenticate errors', async (t) => {
106
+ t.plan(8)
107
+ const error = new Error('Auth error')
108
+ error.returnCode = 1
109
+ await testAuthenticationError(t, error, 5)
150
110
  })
151
111
 
152
- test('authentication error when return code 1 (unacceptable protocol version) is passed', function (t) {
153
- t.plan(7)
154
-
155
- const s = setup()
156
- t.teardown(s.broker.close.bind(s.broker))
157
-
158
- s.broker.authenticate = function (client, username, password, cb) {
159
- t.type(client, Client, 'client is there')
160
- t.equal(username, 'my username', 'username is there')
161
- t.same(password, Buffer.from('my pass'), 'password is there')
162
- const error = new Error('Auth error')
163
- error.returnCode = 1
164
- cb(error, null)
165
- }
166
-
167
- s.broker.on('clientError', function (client, err) {
168
- t.equal(err.message, 'Auth error')
169
- t.equal(err.errorCode, 5)
170
- })
171
-
172
- s.broker.on('clientReady', function (client) {
173
- t.fail('client should not ready')
174
- })
175
-
176
- s.outStream.on('data', function (packet) {
177
- t.same(packet, {
178
- cmd: 'connack',
179
- returnCode: 5,
180
- length: 2,
181
- qos: 0,
182
- retain: false,
183
- dup: false,
184
- topic: null,
185
- payload: null,
186
- sessionPresent: false
187
- }, 'unsuccessful connack, unauthorized')
188
- })
189
-
190
- eos(s.outStream, function () {
191
- t.equal(s.broker.connectedClients, 0, 'no connected clients')
192
- })
193
-
194
- s.inStream.write({
195
- cmd: 'connect',
196
- protocolId: 'MQTT',
197
- protocolVersion: 4,
198
- clean: true,
199
- clientId: 'my-client',
200
- username: 'my username',
201
- password: 'my pass',
202
- keepalive: 0
203
- })
112
+ test('authentication error when return code 1 (unacceptable protocol version) is passed', async (t) => {
113
+ t.plan(8)
114
+ const error = new Error('Auth error')
115
+ error.returnCode = 1
116
+ await testAuthenticationError(t, error, 5)
204
117
  })
205
118
 
206
- test('authentication error when return code 2 (identifier rejected) is passed', function (t) {
207
- t.plan(7)
208
-
209
- const s = setup()
210
- t.teardown(s.broker.close.bind(s.broker))
211
-
212
- s.broker.authenticate = function (client, username, password, cb) {
213
- t.type(client, Client, 'client is there')
214
- t.equal(username, 'my username', 'username is there')
215
- t.same(password, Buffer.from('my pass'), 'password is there')
216
- const error = new Error('Auth error')
217
- error.returnCode = 2
218
- cb(error, null)
219
- }
220
-
221
- s.broker.on('clientError', function (client, err) {
222
- t.equal(err.message, 'Auth error')
223
- t.equal(err.errorCode, 2)
224
- })
225
-
226
- s.broker.on('clientReady', function (client) {
227
- t.fail('client should not ready')
228
- })
229
-
230
- s.outStream.on('data', function (packet) {
231
- t.same(packet, {
232
- cmd: 'connack',
233
- returnCode: 2,
234
- length: 2,
235
- qos: 0,
236
- retain: false,
237
- dup: false,
238
- topic: null,
239
- payload: null,
240
- sessionPresent: false
241
- }, 'unsuccessful connack, identifier rejected')
242
- })
243
-
244
- eos(s.outStream, function () {
245
- t.equal(s.broker.connectedClients, 0, 'no connected clients')
246
- })
247
-
248
- s.inStream.write({
249
- cmd: 'connect',
250
- protocolId: 'MQTT',
251
- protocolVersion: 4,
252
- clean: true,
253
- clientId: 'my-client',
254
- username: 'my username',
255
- password: 'my pass',
256
- keepalive: 0
257
- })
119
+ test('authentication error when return code 2 (identifier rejected) is passed', async (t) => {
120
+ t.plan(8)
121
+ const error = new Error('Auth error')
122
+ error.returnCode = 2
123
+ await testAuthenticationError(t, error, 2)
258
124
  })
259
125
 
260
- test('authentication error when return code 3 (Server unavailable) is passed', function (t) {
261
- t.plan(7)
262
-
263
- const s = setup()
264
- t.teardown(s.broker.close.bind(s.broker))
265
-
266
- s.broker.authenticate = function (client, username, password, cb) {
267
- t.type(client, Client, 'client is there')
268
- t.equal(username, 'my username', 'username is there')
269
- t.same(password, Buffer.from('my pass'), 'password is there')
270
- const error = new Error('Auth error')
271
- error.returnCode = 3
272
- cb(error, null)
273
- }
274
-
275
- s.broker.on('clientError', function (client, err) {
276
- t.equal(err.message, 'Auth error')
277
- t.equal(err.errorCode, 3)
278
- })
279
-
280
- s.broker.on('clientReady', function (client) {
281
- t.fail('client should not ready')
282
- })
283
-
284
- s.outStream.on('data', function (packet) {
285
- t.same(packet, {
286
- cmd: 'connack',
287
- returnCode: 3,
288
- length: 2,
289
- qos: 0,
290
- retain: false,
291
- dup: false,
292
- topic: null,
293
- payload: null,
294
- sessionPresent: false
295
- }, 'unsuccessful connack, Server unavailable')
296
- })
297
-
298
- eos(s.outStream, function () {
299
- t.equal(s.broker.connectedClients, 0, 'no connected clients')
300
- })
301
-
302
- s.inStream.write({
303
- cmd: 'connect',
304
- protocolId: 'MQTT',
305
- protocolVersion: 4,
306
- clean: true,
307
- clientId: 'my-client',
308
- username: 'my username',
309
- password: 'my pass',
310
- keepalive: 0
311
- })
126
+ test('authentication error when return code 3 (Server unavailable) is passed', async (t) => {
127
+ t.plan(8)
128
+ const error = new Error('Auth error')
129
+ error.returnCode = 3
130
+ await testAuthenticationError(t, error, 3)
312
131
  })
313
132
 
314
- test('authentication error when return code 4 (bad user or password) is passed', function (t) {
315
- t.plan(7)
316
-
317
- const s = setup()
318
- t.teardown(s.broker.close.bind(s.broker))
319
-
320
- s.broker.authenticate = function (client, username, password, cb) {
321
- t.type(client, Client, 'client is there')
322
- t.equal(username, 'my username', 'username is there')
323
- t.same(password, Buffer.from('my pass'), 'password is there')
324
- const error = new Error('Auth error')
325
- error.returnCode = 4
326
- cb(error, null)
327
- }
328
-
329
- s.broker.on('clientError', function (client, err) {
330
- t.equal(err.message, 'Auth error')
331
- t.equal(err.errorCode, 4)
332
- })
333
-
334
- s.broker.on('clientReady', function (client) {
335
- t.fail('client should not ready')
336
- })
337
-
338
- s.outStream.on('data', function (packet) {
339
- t.same(packet, {
340
- cmd: 'connack',
341
- returnCode: 4,
342
- length: 2,
343
- qos: 0,
344
- retain: false,
345
- dup: false,
346
- topic: null,
347
- payload: null,
348
- sessionPresent: false
349
- }, 'unsuccessful connack, bad username or password')
350
- })
351
-
352
- eos(s.outStream, function () {
353
- t.equal(s.broker.connectedClients, 0, 'no connected clients')
354
- })
355
-
356
- s.inStream.write({
357
- cmd: 'connect',
358
- protocolId: 'MQTT',
359
- protocolVersion: 4,
360
- clean: true,
361
- clientId: 'my-client',
362
- username: 'my username',
363
- password: 'my pass',
364
- keepalive: 0
365
- })
133
+ test('authentication error when return code 4 (bad user or password) is passed', async (t) => {
134
+ t.plan(8)
135
+ const error = new Error('Auth error')
136
+ error.returnCode = 4
137
+ await testAuthenticationError(t, error, 4)
366
138
  })
367
139
 
368
- test('authentication error when non numeric return code is passed', function (t) {
369
- t.plan(7)
370
-
371
- const s = setup()
372
- t.teardown(s.broker.close.bind(s.broker))
373
-
374
- s.broker.authenticate = function (client, username, password, cb) {
375
- t.type(client, Client, 'client is there')
376
- t.equal(username, 'my username', 'username is there')
377
- t.same(password, Buffer.from('my pass'), 'password is there')
378
- const error = new Error('Non numeric error codes')
379
- error.returnCode = 'return Code'
380
- cb(error, null)
381
- }
382
-
383
- s.broker.on('clientError', function (client, err) {
384
- t.equal(err.message, 'Non numeric error codes')
385
- t.equal(err.errorCode, 5)
386
- })
387
-
388
- s.broker.on('clientReady', function (client) {
389
- t.fail('client should not ready')
390
- })
391
-
392
- s.outStream.on('data', function (packet) {
393
- t.same(packet, {
394
- cmd: 'connack',
395
- returnCode: 5,
396
- length: 2,
397
- qos: 0,
398
- retain: false,
399
- dup: false,
400
- topic: null,
401
- payload: null,
402
- sessionPresent: false
403
- }, 'unsuccessful connack, unauthorized')
404
- })
405
-
406
- eos(s.outStream, function () {
407
- t.equal(s.broker.connectedClients, 0, 'no connected clients')
408
- })
409
-
410
- s.inStream.write({
411
- cmd: 'connect',
412
- protocolId: 'MQTT',
413
- protocolVersion: 4,
414
- clean: true,
415
- clientId: 'my-client',
416
- username: 'my username',
417
- password: 'my pass',
418
- keepalive: 0
419
- })
140
+ test('authentication error when non numeric return code is passed', async (t) => {
141
+ t.plan(8)
142
+ const error = new Error('Auth error')
143
+ error.returnCode = 'return Code'
144
+ await testAuthenticationError(t, error, 5)
420
145
  })
421
146
 
422
- test('authorize publish', function (t) {
147
+ test('authorize publish', async (t) => {
423
148
  t.plan(4)
424
-
425
- const s = connect(setup(), { clientId: 'my-client-xyz' })
426
- t.teardown(s.broker.close.bind(s.broker))
427
-
428
149
  const expected = {
429
150
  cmd: 'publish',
430
151
  topic: 'hello',
@@ -435,47 +156,58 @@ test('authorize publish', function (t) {
435
156
  dup: false
436
157
  }
437
158
 
438
- s.broker.authorizePublish = function (client, packet, cb) {
439
- t.ok(client, 'client exists')
440
- t.same(packet, expected, 'packet matches')
159
+ const s = await createAndConnect(t)
160
+
161
+ s.broker.authorizePublish = (client, packet, cb) => {
162
+ t.assert.ok(client, 'client exists')
163
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
441
164
  cb()
442
165
  }
443
166
 
444
- s.broker.mq.on('hello', function (packet, cb) {
445
- t.notOk(Object.prototype.hasOwnProperty.call(packet, 'messageId'), 'should not contain messageId in QoS 0')
446
- expected.brokerId = s.broker.id
447
- expected.brokerCounter = s.broker.counter
448
- expected.clientId = 'my-client-xyz'
449
- delete expected.length
450
- t.same(packet, expected, 'packet matches')
451
- cb()
167
+ const packet = await new Promise((resolve) => {
168
+ s.broker.mq.on('hello', (packet, cb) => {
169
+ resolve(packet)
170
+ cb()
171
+ })
172
+ s.inStream.write({
173
+ cmd: 'publish',
174
+ topic: 'hello',
175
+ payload: 'world'
176
+ })
452
177
  })
453
-
454
178
  s.inStream.write({
455
179
  cmd: 'publish',
456
180
  topic: 'hello',
457
181
  payload: 'world'
458
182
  })
183
+
184
+ t.assert.equal(Object.hasOwn(packet, 'messageId'), false, 'should not contain messageId in QoS 0')
185
+ expected.brokerId = s.broker.id
186
+ expected.brokerCounter = s.broker.counter
187
+ expected.clientId = 'my-client'
188
+ delete expected.length
189
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet matches again')
459
190
  })
460
191
 
461
- test('authorize waits for authenticate', function (t) {
192
+ test('authorize waits for authenticate', async (t) => {
462
193
  t.plan(6)
463
194
 
464
- const s = setup(aedes({ clientId: 'my-client-xyz-2' }))
465
- t.teardown(s.broker.close.bind(s.broker))
195
+ const broker = await Aedes.createBroker()
196
+ t.after(() => broker.close())
197
+ const s = setup(broker)
466
198
 
467
- s.broker.authenticate = function (client, username, password, cb) {
468
- t.type(client, Client, 'client is there')
469
- process.nextTick(function () {
470
- t.equal(username, 'my username', 'username is there')
471
- t.same(password, Buffer.from('my pass'), 'password is there')
472
- client.authenticated = true
473
- cb(null, true)
474
- })
199
+ broker.authenticate = (client, username, password, cb) => {
200
+ t.assert.equal(client instanceof Client, true, 'client is there')
201
+ // process.nextTick(() => {
202
+ t.assert.equal(username, 'my username', 'username is there')
203
+ t.assert.equal(password.toString(), 'my pass', 'password is there')
204
+ client.authenticated = true
205
+ cb(null, true)
206
+ // })
475
207
  }
476
208
 
477
- s.broker.authorizePublish = function (client, packet, cb) {
478
- t.ok(client.authenticated, 'client authenticated')
209
+ broker.authorizePublish = (client, _packet, cb) => {
210
+ t.assert.equal(client.authenticated, true, 'client authenticated')
479
211
  cb()
480
212
  }
481
213
 
@@ -490,46 +222,39 @@ test('authorize waits for authenticate', function (t) {
490
222
  clientId: 'my-client'
491
223
  }
492
224
 
493
- s.broker.mq.on('hello', function (packet, cb) {
494
- t.notOk(Object.prototype.hasOwnProperty.call(packet, 'messageId'), 'should not contain messageId in QoS 0')
495
- expected.brokerId = s.broker.id
496
- expected.brokerCounter = s.broker.counter
497
- delete expected.length
498
- t.same(packet, expected, 'packet matches')
499
- cb()
500
- })
225
+ await new Promise((resolve) => {
226
+ s.broker.mq.on('hello', (packet, cb) => {
227
+ t.assert.equal(Object.hasOwn(packet, 'messageId'), false, 'should not contain messageId in QoS 0')
228
+ expected.brokerId = s.broker.id
229
+ expected.brokerCounter = s.broker.counter
230
+ delete expected.length
231
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet matches again')
232
+ cb()
233
+ resolve()
234
+ })
501
235
 
502
- s.inStream.write({
503
- cmd: 'connect',
504
- protocolId: 'MQTT',
505
- protocolVersion: 4,
506
- clean: true,
507
- clientId: 'my-client',
508
- username: 'my username',
509
- password: 'my pass',
510
- keepalive: 0
511
- })
236
+ s.inStream.write({
237
+ cmd: 'connect',
238
+ protocolId: 'MQTT',
239
+ protocolVersion: 4,
240
+ clean: true,
241
+ clientId: 'my-client',
242
+ username: 'my username',
243
+ password: 'my pass',
244
+ keepalive: 0
245
+ })
512
246
 
513
- s.inStream.write({
514
- cmd: 'publish',
515
- topic: 'hello',
516
- payload: 'world'
247
+ s.inStream.write({
248
+ cmd: 'publish',
249
+ topic: 'hello',
250
+ payload: 'world'
251
+ })
517
252
  })
518
253
  })
519
254
 
520
- test('authorize publish from configOptions', function (t) {
255
+ test('authorize publish from configOptions', async (t) => {
521
256
  t.plan(4)
522
257
 
523
- const s = connect(setup(aedes({
524
- clientId: 'my-client-xyz-3',
525
- authorizePublish: function (client, packet, cb) {
526
- t.ok(client, 'client exists')
527
- t.same(packet, expected, 'packet matches')
528
- cb()
529
- }
530
- })), { clientId: 'my-client-xyz-3' })
531
- t.teardown(s.broker.close.bind(s.broker))
532
-
533
258
  const expected = {
534
259
  cmd: 'publish',
535
260
  topic: 'hello',
@@ -540,29 +265,38 @@ test('authorize publish from configOptions', function (t) {
540
265
  dup: false
541
266
  }
542
267
 
543
- s.broker.mq.on('hello', function (packet, cb) {
544
- t.notOk(Object.prototype.hasOwnProperty.call(packet, 'messageId'), 'should not contain messageId in QoS 0')
545
- expected.brokerId = s.broker.id
546
- expected.brokerCounter = s.broker.counter
547
- expected.clientId = 'my-client-xyz-3'
548
- delete expected.length
549
- t.same(packet, expected, 'packet matches')
550
- cb()
268
+ const broker = await Aedes.createBroker({
269
+ authorizePublish: (client, packet, cb) => {
270
+ t.assert.ok(client, 'client exists')
271
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
272
+ cb()
273
+ }
551
274
  })
552
-
553
- s.inStream.write({
554
- cmd: 'publish',
555
- topic: 'hello',
556
- payload: 'world'
275
+ t.after(() => broker.close())
276
+ const s = setup(broker)
277
+ await connect(s)
278
+
279
+ await new Promise((resolve) => {
280
+ broker.mq.on('hello', (packet, cb) => {
281
+ t.assert.equal(Object.hasOwn(packet, 'messageId'), false, 'should not contain messageId in QoS 0')
282
+ expected.brokerId = s.broker.id
283
+ expected.brokerCounter = s.broker.counter
284
+ delete expected.length
285
+ delete packet.clientId
286
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet matches again')
287
+ cb()
288
+ resolve()
289
+ })
290
+ s.inStream.write({
291
+ cmd: 'publish',
292
+ topic: 'hello',
293
+ payload: 'world'
294
+ })
557
295
  })
558
296
  })
559
297
 
560
- test('do not authorize publish', function (t) {
298
+ test('do not authorize publish', async (t) => {
561
299
  t.plan(3)
562
-
563
- const s = connect(setup())
564
- t.teardown(s.broker.close.bind(s.broker))
565
-
566
300
  const expected = {
567
301
  cmd: 'publish',
568
302
  topic: 'hello',
@@ -573,28 +307,25 @@ test('do not authorize publish', function (t) {
573
307
  dup: false
574
308
  }
575
309
 
576
- s.broker.authorizePublish = function (client, packet, cb) {
577
- t.ok(client, 'client exists')
578
- t.same(packet, expected, 'packet matches')
310
+ const s = await createAndConnect(t)
311
+
312
+ s.broker.authorizePublish = (client, packet, cb) => {
313
+ t.assert.ok(client, 'client exists')
314
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
579
315
  cb(new Error('auth negated'))
580
316
  }
581
317
 
582
- eos(s.conn, function () {
583
- t.equal(s.broker.connectedClients, 0, 'no connected clients')
584
- })
585
-
586
318
  s.inStream.write({
587
319
  cmd: 'publish',
588
320
  topic: 'hello',
589
321
  payload: 'world'
590
322
  })
323
+ await once(s.broker, 'clientError')
324
+ t.assert.equal(s.broker.connectedClients, 0, 'no connected clients')
591
325
  })
592
326
 
593
- test('modify qos out of range in authorize publish ', function (t) {
594
- t.plan(2)
595
-
596
- const s = connect(setup(), { clientId: 'my-client-xyz-4' })
597
- t.teardown(s.broker.close.bind(s.broker))
327
+ test('modify qos out of range in authorize publish ', async (t) => {
328
+ t.plan(3)
598
329
 
599
330
  const expected = {
600
331
  cmd: 'publish',
@@ -607,105 +338,106 @@ test('modify qos out of range in authorize publish ', function (t) {
607
338
  clientId: 'my-client-xyz-4'
608
339
  }
609
340
 
610
- s.broker.authorizePublish = function (client, packet, cb) {
341
+ const s = await createAndConnect(t, { connect: { clientId: 'my-client-xyz-4' } })
342
+
343
+ s.broker.authorizePublish = (client, packet, cb) => {
611
344
  if (packet.topic === 'hello') { packet.qos = 10 }
612
345
  cb()
613
346
  }
614
347
 
615
- s.outStream.on('data', function (packet) {
616
- t.fail('should no data sent')
617
- })
618
- s.broker.mq.on('hello', function (packet, cb) {
619
- t.fail('should not publish')
620
- })
621
- s.broker.mq.on('foo', function (packet, cb) {
622
- t.notOk(Object.prototype.hasOwnProperty.call(packet, 'messageId'), 'should not contain messageId in QoS 0')
623
- expected.brokerId = s.broker.id
624
- expected.brokerCounter = s.broker.counter
625
- delete expected.length
626
- t.same(packet, expected, 'packet matches')
627
- cb()
348
+ s.broker.mq.on('hello', (packet, cb) => {
349
+ t.assert.fail('should not publish')
628
350
  })
629
351
 
630
- s.inStream.write({
631
- cmd: 'publish',
632
- topic: 'hello',
633
- payload: 'world'
634
- })
635
- s.inStream.write({
636
- cmd: 'publish',
637
- topic: 'foo',
638
- payload: 'bar'
352
+ await new Promise((resolve) => {
353
+ s.broker.mq.on('foo', (packet, cb) => {
354
+ t.assert.equal(Object.hasOwn(packet, 'messageId'), false, 'should not contain messageId in QoS 0')
355
+ expected.brokerId = s.broker.id
356
+ expected.brokerCounter = s.broker.counter
357
+ delete expected.length
358
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
359
+ resolve()
360
+ cb()
361
+ })
362
+
363
+ s.inStream.write({
364
+ cmd: 'publish',
365
+ topic: 'hello',
366
+ payload: 'world'
367
+ })
368
+ s.inStream.write({
369
+ cmd: 'publish',
370
+ topic: 'foo',
371
+ payload: 'bar'
372
+ })
639
373
  })
374
+ const result = await nextPacketWithTimeOut(s, 1)
375
+ t.assert.equal(result, null, 'no packet')
640
376
  })
641
377
 
642
- test('authorize subscribe', function (t) {
378
+ test('authorize subscribe', async (t) => {
643
379
  t.plan(5)
644
380
 
645
- const s = connect(setup())
646
- t.teardown(s.broker.close.bind(s.broker))
381
+ const s = await createAndConnect(t)
647
382
 
648
- s.broker.authorizeSubscribe = function (client, sub, cb) {
649
- t.ok(client, 'client exists')
650
- t.same(sub, {
383
+ s.broker.authorizeSubscribe = (client, sub, cb) => {
384
+ t.assert.ok(client, 'client exists')
385
+ t.assert.deepEqual(sub, {
651
386
  topic: 'hello',
652
387
  qos: 0
653
388
  }, 'topic matches')
654
389
  cb(null, sub)
655
390
  }
656
391
 
657
- subscribe(t, s, 'hello', 0)
392
+ await subscribe(t, s, 'hello', 0)
658
393
  })
659
394
 
660
- test('authorize subscribe multiple same topics with same qos', function (t) {
395
+ test('authorize subscribe multiple same topics with same qos', async (t) => {
661
396
  t.plan(4)
662
397
 
663
- const s = connect(setup())
664
- t.teardown(s.broker.close.bind(s.broker))
398
+ const s = await createAndConnect(t)
665
399
 
666
- s.broker.authorizeSubscribe = function (client, sub, cb) {
667
- t.same(sub, {
400
+ s.broker.authorizeSubscribe = (client, sub, cb) => {
401
+ t.assert.deepEqual(sub, {
668
402
  topic: 'hello',
669
403
  qos: 0
670
404
  }, 'topic matches')
671
405
  cb(null, sub)
672
406
  }
673
407
 
674
- subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'hello', qos: 0 }], [0])
408
+ await subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'hello', qos: 0 }], [0])
675
409
  })
676
410
 
677
- test('authorize subscribe multiple same topics with different qos', function (t) {
411
+ test('authorize subscribe multiple same topics with different qos', async (t) => {
678
412
  t.plan(4)
679
413
 
680
- const s = connect(setup())
681
- t.teardown(s.broker.close.bind(s.broker))
414
+ const s = await createAndConnect(t)
682
415
 
683
- s.broker.authorizeSubscribe = function (client, sub, cb) {
684
- t.same(sub, {
416
+ s.broker.authorizeSubscribe = (client, sub, cb) => {
417
+ t.assert.deepEqual(sub, {
685
418
  topic: 'hello',
686
419
  qos: 1
687
420
  }, 'topic matches')
688
421
  cb(null, sub)
689
422
  }
690
423
 
691
- subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'hello', qos: 1 }], [1])
424
+ await subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'hello', qos: 1 }], [1])
692
425
  })
693
426
 
694
- test('authorize subscribe multiple different topics', function (t) {
427
+ test('authorize subscribe multiple different topics', async (t) => {
695
428
  t.plan(7)
696
429
 
697
- const s = connect(setup())
698
- t.teardown(s.broker.close.bind(s.broker))
430
+ const s = await createAndConnect(t)
699
431
 
700
- s.broker.authorizeSubscribe = function (client, sub, cb) {
701
- t.ok(client, 'client exists')
432
+ s.broker.authorizeSubscribe = (client, sub, cb) => {
433
+ t.assert.ok(client, 'client exists')
702
434
  if (sub.topic === 'hello') {
703
- t.same(sub, {
435
+ t.assert.deepEqual(sub, {
704
436
  topic: 'hello',
705
437
  qos: 0
706
438
  }, 'topic matches')
707
439
  } else if (sub.topic === 'foo') {
708
- t.same(sub, {
440
+ t.assert.deepEqual(sub, {
709
441
  topic: 'foo',
710
442
  qos: 0
711
443
  }, 'topic matches')
@@ -713,66 +445,51 @@ test('authorize subscribe multiple different topics', function (t) {
713
445
  cb(null, sub)
714
446
  }
715
447
 
716
- subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'foo', qos: 0 }], [0, 0])
448
+ await subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'foo', qos: 0 }], [0, 0])
717
449
  })
718
450
 
719
- test('authorize subscribe from config options', function (t) {
451
+ test('authorize subscribe from config options', async (t) => {
720
452
  t.plan(5)
721
-
722
- const s = connect(setup(aedes({
723
- authorizeSubscribe: function (client, sub, cb) {
724
- t.ok(client, 'client exists')
725
- t.same(sub, {
453
+ const broker = await Aedes.createBroker({
454
+ authorizeSubscribe: (client, sub, cb) => {
455
+ t.assert.ok(client, 'client exists')
456
+ t.assert.deepEqual(sub, {
726
457
  topic: 'hello',
727
458
  qos: 0
728
459
  }, 'topic matches')
729
460
  cb(null, sub)
730
461
  }
731
- })))
732
- t.teardown(s.broker.close.bind(s.broker))
733
-
734
- subscribe(t, s, 'hello', 0)
462
+ })
463
+ t.after(() => broker.close())
464
+ const s = setup(broker)
465
+ await connect(s)
466
+ await subscribe(t, s, 'hello', 0)
735
467
  })
736
468
 
737
- test('negate subscription', function (t) {
469
+ test('negate subscription', async (t) => {
738
470
  t.plan(5)
739
471
 
740
- const s = connect(setup())
741
- t.teardown(s.broker.close.bind(s.broker))
472
+ const s = await createAndConnect(t)
742
473
 
743
- s.broker.authorizeSubscribe = function (client, sub, cb) {
744
- t.ok(client, 'client exists')
745
- t.same(sub, {
474
+ s.broker.authorizeSubscribe = (client, sub, cb) => {
475
+ t.assert.ok(client, 'client exists')
476
+ t.assert.deepEqual(sub, {
746
477
  topic: 'hello',
747
478
  qos: 0
748
479
  }, 'topic matches')
749
480
  cb(null, null)
750
481
  }
751
482
 
752
- s.inStream.write({
753
- cmd: 'subscribe',
754
- messageId: 24,
755
- subscriptions: [{
756
- topic: 'hello',
757
- qos: 0
758
- }]
759
- })
760
-
761
- s.outStream.once('data', function (packet) {
762
- t.equal(packet.cmd, 'suback')
763
- t.same(packet.granted, [128])
764
- t.equal(packet.messageId, 24)
765
- })
483
+ await subscribe(t, s, 'hello', 128)
766
484
  })
767
485
 
768
- test('negate multiple subscriptions', function (t) {
486
+ test('negate multiple subscriptions', async (t) => {
769
487
  t.plan(6)
770
488
 
771
- const s = connect(setup())
772
- t.teardown(s.broker.close.bind(s.broker))
489
+ const s = await createAndConnect(t)
773
490
 
774
- s.broker.authorizeSubscribe = function (client, sub, cb) {
775
- t.ok(client, 'client exists')
491
+ s.broker.authorizeSubscribe = (client, sub, cb) => {
492
+ t.assert.ok(client, 'client exists')
776
493
  cb(null, null)
777
494
  }
778
495
 
@@ -784,8 +501,8 @@ test('negate multiple subscriptions', function (t) {
784
501
  qos: 128
785
502
  }]
786
503
 
787
- s.broker.once('subscribe', function (subs, client) {
788
- t.same(subs, expectedSubs)
504
+ s.broker.once('subscribe', (subs, client) => {
505
+ t.assert.deepEqual(subs, expectedSubs)
789
506
  })
790
507
 
791
508
  s.inStream.write({
@@ -800,14 +517,13 @@ test('negate multiple subscriptions', function (t) {
800
517
  }]
801
518
  })
802
519
 
803
- s.outStream.once('data', function (packet) {
804
- t.equal(packet.cmd, 'suback')
805
- t.same(packet.granted, [128, 128])
806
- t.equal(packet.messageId, 24)
807
- })
520
+ const packet = await nextPacket(s)
521
+ t.assert.equal(packet.cmd, 'suback')
522
+ t.assert.deepEqual(packet.granted, [128, 128])
523
+ t.assert.equal(packet.messageId, 24)
808
524
  })
809
525
 
810
- test('negate subscription with correct persistence', function (t) {
526
+ test('negate subscription with correct persistence', async (t) => {
811
527
  t.plan(6)
812
528
 
813
529
  // rh, rap, nl are undefined because mqtt.parser is set to MQTT 3.1.1 and will thus erase these props from s.inStream.write
@@ -825,27 +541,16 @@ test('negate subscription with correct persistence', function (t) {
825
541
  nl: undefined
826
542
  }]
827
543
 
828
- const broker = aedes()
829
- t.teardown(broker.close.bind(broker))
544
+ const s = await createAndConnect(t, { connect: { clean: false, clientId: 'abcde' } })
830
545
 
831
- broker.authorizeSubscribe = function (client, sub, cb) {
832
- t.ok(client, 'client exists')
546
+ s.broker.authorizeSubscribe = (client, sub, cb) => {
547
+ t.assert.ok(client, 'client exists')
833
548
  if (sub.topic === 'hello') {
834
549
  sub = null
835
550
  }
836
551
  cb(null, sub)
837
552
  }
838
553
 
839
- const s = connect(setup(broker), { clean: false, clientId: 'abcde' })
840
- s.outStream.once('data', function (packet) {
841
- t.equal(packet.cmd, 'suback')
842
- t.same(packet.granted, [128, 0])
843
- broker.persistence.subscriptionsByClient(broker.clients.abcde, function (_, subs, client) {
844
- t.same(subs, expected)
845
- })
846
- t.equal(packet.messageId, 24)
847
- })
848
-
849
554
  s.inStream.write({
850
555
  cmd: 'subscribe',
851
556
  messageId: 24,
@@ -863,27 +568,31 @@ test('negate subscription with correct persistence', function (t) {
863
568
  nl: false
864
569
  }]
865
570
  })
571
+
572
+ const packet = await nextPacket(s)
573
+ t.assert.equal(packet.cmd, 'suback')
574
+ t.assert.deepEqual(packet.granted, [128, 0])
575
+ const subs = await s.broker.persistence.subscriptionsByClient(s.broker.clients.abcde)
576
+ t.assert.deepEqual(subs, expected)
577
+ t.assert.equal(packet.messageId, 24)
866
578
  })
867
579
 
868
- test('negate multiple subscriptions random times', function (t) {
580
+ test('negate multiple subscriptions random times', async (t) => {
869
581
  t.plan(5)
870
582
 
871
- const clock = Faketimers.createClock()
872
- const s = connect(setup())
873
- t.teardown(function () {
874
- clock.reset()
875
- s.broker.close()
876
- })
583
+ const s = await createAndConnect(t)
584
+ // mock timers automatically disables at end of test
585
+ t.mock.timers.enable({ apis: ['setTimeout'] })
877
586
 
878
- s.broker.authorizeSubscribe = function (client, sub, cb) {
879
- t.ok(client, 'client exists')
587
+ s.broker.authorizeSubscribe = (client, sub, cb) => {
588
+ t.assert.ok(client, 'client exists')
880
589
  if (sub.topic === 'hello') {
881
- clock.setTimeout(function () {
590
+ setTimeout(() => {
882
591
  cb(null, sub)
883
592
  }, 100)
884
593
  } else {
885
594
  cb(null, null)
886
- clock.tick(100)
595
+ t.mock.timers.tick(100)
887
596
  }
888
597
  }
889
598
 
@@ -899,91 +608,48 @@ test('negate multiple subscriptions random times', function (t) {
899
608
  }]
900
609
  })
901
610
 
902
- s.outStream.once('data', function (packet) {
903
- t.equal(packet.cmd, 'suback')
904
- t.same(packet.granted, [0, 128])
905
- t.equal(packet.messageId, 24)
906
- })
611
+ const packet = await nextPacket(s)
612
+ t.assert.equal(packet.cmd, 'suback')
613
+ t.assert.deepEqual(packet.granted, [0, 128])
614
+ t.assert.equal(packet.messageId, 24)
907
615
  })
908
616
 
909
- test('failed authentication does not disconnect other client with same clientId', function (t) {
910
- t.plan(3)
911
-
912
- const broker = aedes()
913
- t.teardown(broker.close.bind(broker))
617
+ test('failed authentication does not disconnect other client with same clientId', async (t) => {
618
+ t.plan(4)
914
619
 
620
+ const broker = await Aedes.createBroker()
621
+ t.after(() => broker.close())
915
622
  const s = setup(broker)
916
623
  const s0 = setup(broker)
917
624
 
918
- broker.authenticate = function (client, username, password, cb) {
625
+ broker.authenticate = (client, username, password, cb) => {
919
626
  cb(null, password.toString() === 'right')
920
627
  }
921
628
 
922
- s0.inStream.write({
923
- cmd: 'connect',
924
- protocolId: 'MQTT',
925
- protocolVersion: 4,
926
- clean: true,
927
- clientId: 'my-client',
928
- username: 'my username',
929
- password: 'right',
930
- keepalive: 0
931
- })
932
-
933
- s0.outStream.on('data', function (packet) {
934
- t.same(packet, {
935
- cmd: 'connack',
936
- returnCode: 0,
937
- length: 2,
938
- qos: 0,
939
- retain: false,
940
- dup: false,
941
- topic: null,
942
- payload: null,
943
- sessionPresent: false
944
- }, 'successful connack')
945
-
946
- s.inStream.write({
947
- cmd: 'connect',
948
- protocolId: 'MQTT',
949
- protocolVersion: 4,
950
- clean: true,
951
- clientId: 'my-client',
952
- username: 'my username',
953
- password: 'wrong',
954
- keepalive: 0
955
- })
956
- })
957
-
958
- const removeEos = eos(s0.outStream, function () {
959
- t.fail('ended before time')
960
- })
961
-
962
- s.outStream.on('data', function (packet) {
963
- t.same(packet, {
964
- cmd: 'connack',
965
- returnCode: 5,
966
- length: 2,
967
- qos: 0,
968
- retain: false,
969
- dup: false,
970
- topic: null,
971
- payload: null,
972
- sessionPresent: false
973
- }, 'unsuccessful connack')
974
- })
975
-
976
- eos(s.outStream, function () {
977
- t.pass('ended')
978
- removeEos()
979
- })
629
+ await connect(s0, { connect: { password: 'right' } })
630
+ const packet = await connect(s, { connect: { password: 'wrong' }, verifyReturnedOk: false })
631
+ t.assert.deepEqual(packet, {
632
+ cmd: 'connack',
633
+ returnCode: 5,
634
+ length: 2,
635
+ qos: 0,
636
+ retain: false,
637
+ dup: false,
638
+ topic: null,
639
+ payload: null,
640
+ sessionPresent: false
641
+ }, 'unsuccessful connack')
642
+ t.assert.equal(broker.connectedClients, 1, 'only one client connected')
643
+ await once(s.conn, 'close')
644
+ t.assert.equal(s0.conn.closed, false, 's0 is still connected')
645
+ t.assert.equal(s.conn.closed, true, 's has been disconnected')
980
646
  })
981
647
 
982
- test('unauthorized connection should not unregister the correct one with same clientId', function (t) {
983
- t.plan(4)
648
+ test('unauthorized connection should not unregister the correct one with same clientId', async (t) => {
649
+ t.plan(3)
984
650
 
985
- const broker = aedes({
986
- authenticate: function (client, username, password, callback) {
651
+ const broker = await Aedes.createBroker({
652
+ authenticate: (client, username, password, callback) => {
987
653
  if (username === 'correct') {
988
654
  callback(null, true)
989
655
  } else {
@@ -993,83 +659,71 @@ test('unauthorized connection should not unregister the correct one with same cl
993
659
  }
994
660
  }
995
661
  })
996
- t.teardown(broker.close.bind(broker))
997
-
998
- broker.on('clientError', function (client, err) {
999
- t.equal(err.message, 'bad user name or password')
1000
- t.equal(err.errorCode, 4)
1001
- t.equal(broker.connectedClients, 1, 'my-client still connected')
1002
- })
662
+ t.after(() => broker.close())
663
+ const s = setup(broker)
664
+ const s0 = setup(broker)
1003
665
 
1004
- connect(setup(broker), {
1005
- clientId: 'my-client',
1006
- username: 'correct'
1007
- }, function () {
1008
- t.equal(broker.connectedClients, 1, 'my-client connected')
1009
- connect(setup(broker), {
1010
- clientId: 'my-client',
1011
- username: 'unauthorized'
1012
- }, function () {
1013
- // other unauthorized connection with the same clientId should not unregister the correct one.
1014
- t.fail('unauthorized should not connect')
666
+ const catchClientError = new Promise(resolve => {
667
+ broker.on('clientError', (client, err) => {
668
+ t.assert.equal(err.message, 'bad user name or password')
669
+ t.assert.equal(err.errorCode, 4)
670
+ t.assert.equal(broker.connectedClients, 1, 'my-client still connected')
671
+ resolve()
1015
672
  })
1016
673
  })
674
+ const serialConnect = async () => {
675
+ await connect(s0, { connect: { username: 'correct' } })
676
+ await connect(s, { connect: { username: 'unauthorized' }, expectedReturnCode: 4 })
677
+ }
678
+ await Promise.all([
679
+ catchClientError,
680
+ serialConnect()
681
+ ])
1017
682
  })
1018
683
 
1019
- test('set authentication method in config options', function (t) {
1020
- t.plan(5)
684
+ test('set authentication method in config options', async (t) => {
685
+ t.plan(6)
1021
686
 
1022
- const s = setup(aedes({
1023
- authenticate: function (client, username, password, cb) {
1024
- t.type(client, Client, 'client is there')
1025
- t.equal(username, 'my username', 'username is there')
1026
- t.same(password, Buffer.from('my pass'), 'password is there')
687
+ const broker = await Aedes.createBroker({
688
+ authenticate: (client, username, password, cb) => {
689
+ t.assert.equal(client instanceof Client, true, 'client is there')
690
+ t.assert.equal(username, 'my username', 'username is there')
691
+ t.assert.deepEqual(password, Buffer.from('my pass'), 'password is there')
1027
692
  cb(null, false)
1028
693
  }
1029
- }))
1030
- t.teardown(s.broker.close.bind(s.broker))
1031
-
1032
- s.outStream.on('data', function (packet) {
1033
- t.same(packet, {
1034
- cmd: 'connack',
1035
- returnCode: 5,
1036
- length: 2,
1037
- qos: 0,
1038
- retain: false,
1039
- dup: false,
1040
- topic: null,
1041
- payload: null,
1042
- sessionPresent: false
1043
- }, 'unsuccessful connack')
1044
- })
1045
-
1046
- eos(s.outStream, function () {
1047
- t.equal(s.broker.connectedClients, 0, 'no connected clients')
1048
694
  })
695
+ t.after(() => broker.close())
696
+ const s = setup(broker)
697
+ const packet = await connect(s, { verifyReturnedOk: false })
1049
698
 
1050
- s.inStream.write({
1051
- cmd: 'connect',
1052
- protocolId: 'MQTT',
1053
- protocolVersion: 4,
1054
- clean: true,
1055
- clientId: 'my-client',
1056
- username: 'my username',
1057
- password: 'my pass',
1058
- keepalive: 0
1059
- })
699
+ t.assert.deepEqual(packet, {
700
+ cmd: 'connack',
701
+ returnCode: 5,
702
+ length: 2,
703
+ qos: 0,
704
+ retain: false,
705
+ dup: false,
706
+ topic: null,
707
+ payload: null,
708
+ sessionPresent: false
709
+ }, 'unsuccessful connack')
710
+ t.assert.equal(s.broker.connectedClients, 0, 'no connected clients')
711
+ await once(s.conn, 'close')
712
+ t.assert.equal(s.conn.closed, true, 's has been disconnected')
1060
713
  })
1061
714
 
1062
- test('change a topic name inside authorizeForward method in QoS 1 mode', function (t) {
715
+ test('change a topic name inside authorizeForward method in QoS 1 mode', async (t) => {
1063
716
  t.plan(3)
1064
717
 
1065
- const broker = aedes({
1066
- authorizeForward: function (client, packet) {
718
+ const broker = await Aedes.createBroker({
719
+ authorizeForward: (client, packet) => {
1067
720
  packet.payload = Buffer.from('another-world')
1068
721
  packet.messageId = 2
1069
722
  return packet
1070
723
  }
1071
724
  })
1072
- t.teardown(broker.close.bind(broker))
725
+ t.after(() => broker.close())
726
+ const s = setup(broker)
1073
727
 
1074
728
  const expected = {
1075
729
  cmd: 'publish',
@@ -1082,96 +736,106 @@ test('change a topic name inside authorizeForward method in QoS 1 mode', functio
1082
736
  messageId: 2
1083
737
  }
1084
738
 
1085
- broker.on('client', function (client) {
1086
- client.subscribe({
1087
- topic: 'hello',
1088
- qos: 1
1089
- }, function (err) {
1090
- t.error(err, 'no error')
1091
-
1092
- broker.publish({
739
+ const publishedOk = new Promise((resolve) => {
740
+ broker.on('client', (client) => {
741
+ client.subscribe({
1093
742
  topic: 'hello',
1094
- payload: Buffer.from('world'),
1095
743
  qos: 1
1096
- }, function (err) {
1097
- t.error(err, 'no error')
744
+ }, (err) => {
745
+ t.assert.equal(err, undefined, 'no error')
746
+
747
+ broker.publish({
748
+ topic: 'hello',
749
+ payload: Buffer.from('world'),
750
+ qos: 1
751
+ }, (err) => {
752
+ t.assert.equal(err, undefined, 'no error')
753
+ resolve()
754
+ })
1098
755
  })
1099
756
  })
1100
757
  })
1101
758
 
1102
- const s = connect(setup(broker))
1103
-
1104
- s.outStream.once('data', function (packet) {
1105
- t.same(packet, expected, 'packet matches')
1106
- })
759
+ await Promise.all([
760
+ publishedOk,
761
+ connect(s)
762
+ ])
763
+ const packet = await nextPacket(s)
764
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
1107
765
  })
1108
766
 
1109
- ;[true, false].forEach(function (cleanSession) {
1110
- test(`unauthorized forward publish in QoS 1 mode [clean=${cleanSession}]`, function (t) {
1111
- t.plan(2)
767
+ for (const cleanSession of [true, false]) {
768
+ test(`unauthorized forward publish in QoS 1 mode [clean=${cleanSession}]`, async (t) => {
769
+ t.plan(3)
1112
770
 
1113
- const broker = aedes({
1114
- authorizeForward: function (client, packet) {
771
+ const broker = await Aedes.createBroker({
772
+ authorizeForward: (_client, _packet) => {
1115
773
  return null
1116
774
  }
1117
775
  })
1118
- t.teardown(broker.close.bind(broker))
1119
-
1120
- broker.on('client', function (client) {
1121
- client.subscribe({
1122
- topic: 'hello',
1123
- qos: 1
1124
- }, function (err) {
1125
- t.error(err, 'no error')
776
+ t.after(() => broker.close())
777
+ const s = setup(broker)
1126
778
 
1127
- broker.publish({
779
+ const publishedOk = new Promise((resolve) => {
780
+ broker.on('client', (client) => {
781
+ client.subscribe({
1128
782
  topic: 'hello',
1129
- payload: Buffer.from('world'),
1130
783
  qos: 1
1131
- }, function (err) {
1132
- t.error(err, 'no error')
784
+ }, (err) => {
785
+ t.assert.equal(err, undefined, 'no error')
786
+ broker.publish({
787
+ topic: 'hello',
788
+ payload: Buffer.from('world'),
789
+ qos: 1
790
+ }, (err) => {
791
+ t.assert.equal(err, undefined, 'no error')
792
+ resolve()
793
+ })
1133
794
  })
1134
795
  })
1135
796
  })
1136
-
1137
- const s = connect(setup(broker), { clean: cleanSession })
1138
-
1139
- s.outStream.once('data', function (packet) {
1140
- t.fail('Should have not recieved this packet')
1141
- })
797
+ await Promise.all([
798
+ publishedOk,
799
+ connect(s, { connect: { clean: cleanSession } })
800
+ ])
801
+ const packet = await nextPacketWithTimeOut(s, 1)
802
+ t.assert.equal(packet, null, 'no packet')
1142
803
  })
1143
- })
804
+ }
1144
805
 
1145
- test('prevent publish in QoS 0 mode', function (t) {
1146
- t.plan(2)
806
+ test('prevent publish in QoS 0 mode', async (t) => {
807
+ t.plan(3)
1147
808
 
1148
- const broker = aedes({
1149
- authorizeForward: function (client, packet) {
809
+ const broker = await Aedes.createBroker({
810
+ authorizeForward: (client, packet) => {
1150
811
  return null
1151
812
  }
1152
813
  })
1153
- t.teardown(broker.close.bind(broker))
1154
-
1155
- broker.on('client', function (client) {
1156
- client.subscribe({
1157
- topic: 'hello',
1158
- qos: 0
1159
- }, function (err) {
1160
- t.error(err, 'no error')
814
+ t.after(() => broker.close())
815
+ const s = setup(broker)
1161
816
 
1162
- broker.publish({
817
+ const publishedOk = new Promise((resolve) => {
818
+ broker.on('client', (client) => {
819
+ client.subscribe({
1163
820
  topic: 'hello',
1164
- payload: Buffer.from('world'),
1165
- qos: 0
1166
- }, function (err) {
1167
- t.error(err, 'no error')
821
+ qos: 1
822
+ }, (err) => {
823
+ t.assert.equal(err, undefined, 'no error')
824
+ broker.publish({
825
+ topic: 'hello',
826
+ payload: Buffer.from('world'),
827
+ qos: 1
828
+ }, (err) => {
829
+ t.assert.equal(err, undefined, 'no error')
830
+ resolve()
831
+ })
1168
832
  })
1169
833
  })
1170
834
  })
1171
-
1172
- const s = connect(setup(broker))
1173
-
1174
- s.outStream.once('data', function (packet) {
1175
- t.fail('Should have not recieved this packet')
1176
- })
835
+ await Promise.all([
836
+ publishedOk,
837
+ connect(s)
838
+ ])
839
+ const packet = await nextPacketWithTimeOut(s, 1)
840
+ t.assert.equal(packet, null, 'no packet')
1177
841
  })