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/qos1.js CHANGED
@@ -1,24 +1,31 @@
1
- 'use strict'
2
-
3
- const { test } = require('tap')
4
- const concat = require('concat-stream')
5
- const { setup, connect, subscribe } = require('./helper')
6
- const Faketimers = require('@sinonjs/fake-timers')
7
- const aedes = require('../')
8
-
9
- test('publish QoS 1', function (t) {
1
+ import { test } from 'node:test'
2
+ import { once } from 'node:events'
3
+ import {
4
+ checkNoPacket,
5
+ connect,
6
+ createAndConnect,
7
+ createPubSub,
8
+ delay,
9
+ nextPacket,
10
+ publish,
11
+ setup,
12
+ subscribe,
13
+ } from './helper.js'
14
+ import { Aedes } from '../aedes.js'
15
+
16
+ test('publish QoS 1', async (t) => {
10
17
  t.plan(1)
11
18
 
12
- const s = connect(setup())
13
- t.teardown(s.broker.close.bind(s.broker))
14
-
19
+ const s = await createAndConnect(t)
15
20
  const expected = {
16
21
  cmd: 'puback',
17
22
  messageId: 42,
18
23
  qos: 0,
19
24
  dup: false,
20
25
  length: 2,
21
- retain: false
26
+ retain: false,
27
+ payload: null,
28
+ topic: null
22
29
  }
23
30
 
24
31
  s.inStream.write({
@@ -29,19 +36,17 @@ test('publish QoS 1', function (t) {
29
36
  messageId: 42
30
37
  })
31
38
 
32
- s.outStream.on('data', function (packet) {
33
- t.same(packet, expected, 'packet must match')
34
- })
39
+ const packet = await nextPacket(s)
40
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
35
41
  })
36
42
 
37
- test('publish QoS 1 throws error', function (t) {
43
+ test('publish QoS 1 throws error', async (t) => {
38
44
  t.plan(1)
39
45
 
40
- const s = connect(setup())
41
- t.teardown(s.broker.close.bind(s.broker))
46
+ const s = await createAndConnect(t)
42
47
 
43
- s.broker.persistence.subscriptionsByTopic = function (packet, done) {
44
- return done(new Error('Throws error'))
48
+ s.broker.persistence.subscriptionsByTopic = async () => {
49
+ throw new Error('Throws error')
45
50
  }
46
51
 
47
52
  s.inStream.write({
@@ -52,18 +57,18 @@ test('publish QoS 1 throws error', function (t) {
52
57
  messageId: 42
53
58
  })
54
59
 
55
- s.broker.on('error', function (err) {
56
- t.equal('Throws error', err.message, 'Throws error')
57
- })
60
+ const [err] = await once(s.broker, 'error')
61
+ t.assert.equal(err.message, 'Throws error', 'Throws error')
58
62
  })
59
63
 
60
- test('publish QoS 1 throws error on write', function (t) {
61
- t.plan(1)
64
+ test('publish QoS 1 throws error on write', async (t) => {
65
+ t.plan(2)
62
66
 
63
- const s = connect(setup())
64
- t.teardown(s.broker.close.bind(s.broker))
67
+ const broker = await Aedes.createBroker()
68
+ t.after(() => broker.close())
69
+ const s = setup(broker)
65
70
 
66
- s.broker.on('client', function (client) {
71
+ s.broker.on('client', (client) => {
67
72
  client.connected = false
68
73
  client.connecting = false
69
74
 
@@ -76,22 +81,24 @@ test('publish QoS 1 throws error on write', function (t) {
76
81
  })
77
82
  })
78
83
 
79
- s.broker.on('clientError', function (client, err) {
80
- t.equal(err.message, 'connection closed', 'throws error')
81
- })
82
- })
84
+ connect(s, { noWait: true }) // don't wait for connect to complete
83
85
 
84
- test('publish QoS 1 and check offline queue', function (t) {
85
- t.plan(13)
86
+ const [client, err] = await once(broker, 'clientError')
87
+ t.assert.ok(client)
88
+ t.assert.equal(err.message, 'connection closed', 'throws error')
89
+ })
86
90
 
87
- const broker = aedes()
88
- t.teardown(broker.close.bind(broker))
91
+ test('publish QoS 1 and check offline queue', async (t) => {
92
+ t.plan(14)
89
93
 
90
- const publisher = connect(setup(broker), { clean: false })
91
94
  const subscriberClient = {
92
95
  id: 'abcde'
93
96
  }
94
- const subscriber = connect(setup(broker), { clean: false, clientId: subscriberClient.id })
97
+ const { broker, publisher, subscriber } = await createPubSub(t, {
98
+ publisher: { clean: false },
99
+ subscriber: { clean: false, clientId: subscriberClient.id }
100
+ })
101
+
95
102
  const expected = {
96
103
  cmd: 'publish',
97
104
  topic: 'hello',
@@ -105,7 +112,9 @@ test('publish QoS 1 and check offline queue', function (t) {
105
112
  qos: 0,
106
113
  dup: false,
107
114
  length: 2,
108
- messageId: 10
115
+ messageId: 10,
116
+ topic: null,
117
+ payload: null
109
118
  }
110
119
  const sent = {
111
120
  cmd: 'publish',
@@ -117,53 +126,48 @@ test('publish QoS 1 and check offline queue', function (t) {
117
126
  dup: false
118
127
  }
119
128
  const queue = []
120
- subscribe(t, subscriber, 'hello', 1, function () {
121
- publisher.outStream.on('data', function (packet) {
122
- t.same(packet, expectedAck, 'ack packet must patch')
123
- })
124
- subscriber.outStream.on('data', function (packet) {
125
- queue.push(packet)
126
- delete packet.payload
127
- delete packet.length
128
- t.not(packet.messageId, undefined, 'messageId is assigned a value')
129
- t.not(packet.messageId, 10, 'messageId should be unique')
130
- expected.messageId = packet.messageId
131
- t.same(packet, expected, 'publish packet must patch')
132
- if (queue.length === 2) {
133
- setImmediate(() => {
134
- for (let i = 0; i < queue.length; i++) {
135
- broker.persistence.outgoingClearMessageId(subscriberClient, queue[i], function (_, origPacket) {
136
- if (origPacket) {
137
- delete origPacket.brokerId
138
- delete origPacket.brokerCounter
139
- delete origPacket.payload
140
- delete origPacket.messageId
141
- delete sent.payload
142
- delete sent.messageId
143
- t.same(origPacket, sent, 'origPacket must match')
144
- }
145
- })
146
- }
147
- })
148
- }
149
- })
150
- publisher.inStream.write(sent)
151
- sent.payload = 'world2world'
152
- publisher.inStream.write(sent)
153
- })
154
- })
129
+ await subscribe(t, subscriber, 'hello', 1)
130
+ const puback = await publish(t, publisher, sent)
131
+ t.assert.deepEqual(structuredClone(puback), expectedAck, 'ack packet must match')
132
+ sent.payload = 'world2world'
133
+ await publish(t, publisher, sent)
134
+ for (let i = 0; i < 2; i++) {
135
+ const packet = await nextPacket(subscriber)
136
+ queue.push(packet)
137
+ delete packet.payload
138
+ delete packet.length
139
+ t.assert.ok(packet.messageId, 'messageId is assigned a value')
140
+ t.assert.ok(packet.messageId !== 10, 'messageId should be unique')
141
+ expected.messageId = packet.messageId
142
+ t.assert.deepEqual(structuredClone(packet), expected, 'publish packet must match')
143
+ }
155
144
 
156
- test('publish QoS 1 and empty offline queue', function (t) {
157
- t.plan(13)
145
+ for (const packet of queue) {
146
+ const origPacket = await broker.persistence.outgoingClearMessageId(subscriberClient, packet)
147
+ if (origPacket) {
148
+ delete origPacket.brokerId
149
+ delete origPacket.brokerCounter
150
+ delete origPacket.payload
151
+ delete origPacket.messageId
152
+ delete sent.payload
153
+ delete sent.messageId
154
+ t.assert.deepEqual(origPacket, sent, 'origPacket must match')
155
+ }
156
+ }
157
+ })
158
158
 
159
- const broker = aedes()
160
- t.teardown(broker.close.bind(broker))
159
+ test('publish QoS 1 and empty offline queue', async (t) => {
160
+ t.plan(14)
161
161
 
162
- const publisher = connect(setup(broker), { clean: false })
163
162
  const subscriberClient = {
164
163
  id: 'abcde'
165
164
  }
166
- const subscriber = connect(setup(broker), { clean: false, clientId: subscriberClient.id })
165
+
166
+ const { broker, publisher, subscriber } = await createPubSub(t, {
167
+ publisher: { clean: false },
168
+ subscriber: { clean: false, clientId: subscriberClient.id }
169
+ })
170
+
167
171
  const expected = {
168
172
  cmd: 'publish',
169
173
  topic: 'hello',
@@ -177,7 +181,9 @@ test('publish QoS 1 and empty offline queue', function (t) {
177
181
  qos: 0,
178
182
  dup: false,
179
183
  length: 2,
180
- messageId: 10
184
+ messageId: 10,
185
+ topic: null,
186
+ payload: null
181
187
  }
182
188
  const sent = {
183
189
  cmd: 'publish',
@@ -189,44 +195,35 @@ test('publish QoS 1 and empty offline queue', function (t) {
189
195
  dup: false
190
196
  }
191
197
  const queue = []
192
- subscribe(t, subscriber, 'hello', 1, function () {
193
- publisher.outStream.on('data', function (packet) {
194
- t.same(packet, expectedAck, 'ack packet must patch')
195
- })
196
- subscriber.outStream.on('data', function (packet) {
197
- queue.push(packet)
198
- delete packet.payload
199
- delete packet.length
200
- t.not(packet.messageId, undefined, 'messageId is assigned a value')
201
- t.not(packet.messageId, 10, 'messageId should be unique')
202
- expected.messageId = packet.messageId
203
- t.same(packet, expected, 'publish packet must patch')
204
- if (queue.length === 2) {
205
- setImmediate(() => {
206
- broker.clients[subscriberClient.id].emptyOutgoingQueue(function () {
207
- for (let i = 0; i < queue.length; i++) {
208
- broker.persistence.outgoingClearMessageId(subscriberClient, queue[i], function (_, origPacket) {
209
- t.equal(!!origPacket, false, 'Packet has been removed')
210
- })
211
- }
212
- })
213
- })
214
- }
215
- })
216
- publisher.inStream.write(sent)
217
- sent.payload = 'world2world'
218
- publisher.inStream.write(sent)
198
+ await subscribe(t, subscriber, 'hello', 1)
199
+ const puback = await publish(t, publisher, sent)
200
+ t.assert.deepEqual(structuredClone(puback), expectedAck, 'ack packet must match')
201
+ sent.payload = 'world2world'
202
+ await publish(t, publisher, sent)
203
+ for (let i = 0; i < 2; i++) {
204
+ const packet = await nextPacket(subscriber)
205
+ queue.push(packet)
206
+ delete packet.payload
207
+ delete packet.length
208
+ t.assert.ok(packet.messageId, 'messageId is assigned a value')
209
+ t.assert.ok(packet.messageId !== 10, 'messageId should be unique')
210
+ expected.messageId = packet.messageId
211
+ t.assert.deepEqual(structuredClone(packet), expected, 'publish packet must match')
212
+ }
213
+ await new Promise(resolve => {
214
+ broker.clients[subscriberClient.id].emptyOutgoingQueue(resolve)
219
215
  })
220
- })
221
216
 
222
- test('subscribe QoS 1', function (t) {
223
- t.plan(5)
217
+ for (const packet of queue) {
218
+ const origPacket = await broker.persistence.outgoingClearMessageId(subscriberClient, packet)
219
+ t.assert.equal(!!origPacket, false, 'Packet has been removed')
220
+ }
221
+ })
224
222
 
225
- const broker = aedes()
226
- t.teardown(broker.close.bind(broker))
223
+ test('subscribe QoS 1', async (t) => {
224
+ t.plan(6)
227
225
 
228
- const publisher = connect(setup(broker))
229
- const subscriber = connect(setup(broker))
226
+ const { publisher, subscriber } = await createPubSub(t)
230
227
  const expected = {
231
228
  cmd: 'publish',
232
229
  topic: 'hello',
@@ -237,35 +234,28 @@ test('subscribe QoS 1', function (t) {
237
234
  retain: false
238
235
  }
239
236
 
240
- subscribe(t, subscriber, 'hello', 1, function () {
241
- subscriber.outStream.once('data', function (packet) {
242
- subscriber.inStream.write({
243
- cmd: 'puback',
244
- messageId: packet.messageId
245
- })
246
- t.not(packet.messageId, 42, 'messageId must differ')
247
- delete packet.messageId
248
- t.same(packet, expected, 'packet must match')
249
- })
250
-
251
- publisher.inStream.write({
252
- cmd: 'publish',
253
- topic: 'hello',
254
- payload: 'world',
255
- qos: 1,
256
- messageId: 42
257
- })
237
+ await subscribe(t, subscriber, 'hello', 1)
238
+ publish(t, publisher, {
239
+ cmd: 'publish',
240
+ topic: 'hello',
241
+ payload: 'world',
242
+ qos: 1,
243
+ messageId: 42
258
244
  })
245
+ const packet = await nextPacket(subscriber)
246
+ subscriber.inStream.write({
247
+ cmd: 'puback',
248
+ messageId: packet.messageId
249
+ })
250
+ t.assert.ok(packet.messageId !== 42, 'messageId must differ')
251
+ delete packet.messageId
252
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
259
253
  })
260
254
 
261
- test('subscribe QoS 0, but publish QoS 1', function (t) {
262
- t.plan(4)
263
-
264
- const broker = aedes()
265
- t.teardown(broker.close.bind(broker))
255
+ test('subscribe QoS 0, but publish QoS 1', async (t) => {
256
+ t.plan(5)
266
257
 
267
- const publisher = connect(setup(broker))
268
- const subscriber = connect(setup(broker))
258
+ const { publisher, subscriber } = await createPubSub(t)
269
259
  const expected = {
270
260
  cmd: 'publish',
271
261
  topic: 'hello',
@@ -276,28 +266,27 @@ test('subscribe QoS 0, but publish QoS 1', function (t) {
276
266
  retain: false
277
267
  }
278
268
 
279
- subscribe(t, subscriber, 'hello', 0, function () {
280
- subscriber.outStream.once('data', function (packet) {
281
- t.same(packet, expected, 'packet must match')
282
- })
269
+ await subscribe(t, subscriber, 'hello', 0)
283
270
 
284
- publisher.inStream.write({
285
- cmd: 'publish',
286
- topic: 'hello',
287
- payload: 'world',
288
- qos: 1,
289
- messageId: 42
290
- })
271
+ publish(t, publisher, {
272
+ cmd: 'publish',
273
+ topic: 'hello',
274
+ payload: 'world',
275
+ qos: 1,
276
+ messageId: 42
291
277
  })
278
+
279
+ const packet = await nextPacket(subscriber)
280
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
292
281
  })
293
282
 
294
- test('restore QoS 1 subscriptions not clean', function (t) {
283
+ test('restore QoS 1 subscriptions not clean', async (t) => {
295
284
  t.plan(7)
296
285
 
297
- const broker = aedes()
298
- t.teardown(broker.close.bind(broker))
286
+ const { broker, publisher, subscriber } = await createPubSub(t, {
287
+ subscriber: { clean: false, clientId: 'abcde' }
288
+ })
299
289
 
300
- let subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' })
301
290
  const expected = {
302
291
  cmd: 'publish',
303
292
  topic: 'hello',
@@ -308,45 +297,36 @@ test('restore QoS 1 subscriptions not clean', function (t) {
308
297
  retain: false
309
298
  }
310
299
 
311
- subscribe(t, subscriber, 'hello', 1, function () {
312
- subscriber.inStream.end()
313
-
314
- const publisher = connect(setup(broker))
315
-
316
- subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' }, function (connect) {
317
- t.equal(connect.sessionPresent, true, 'session present is set to true')
318
- publisher.inStream.write({
319
- cmd: 'publish',
320
- topic: 'hello',
321
- payload: 'world',
322
- qos: 1,
323
- messageId: 42
324
- })
325
- })
326
-
327
- publisher.outStream.once('data', function (packet) {
328
- t.equal(packet.cmd, 'puback')
329
- })
300
+ await subscribe(t, subscriber, 'hello', 1)
301
+ subscriber.inStream.end()
302
+ const subscriber2 = setup(broker)
303
+ const connack = await connect(subscriber2, { connect: { clean: false, clientId: 'abcde' } })
304
+ t.assert.equal(connack.sessionPresent, true, 'session present is set to true')
305
+ await publish(t, publisher, {
306
+ cmd: 'publish',
307
+ topic: 'hello',
308
+ payload: 'world',
309
+ qos: 1,
310
+ messageId: 42
311
+ })
330
312
 
331
- subscriber.outStream.once('data', function (packet) {
332
- subscriber.inStream.write({
333
- cmd: 'puback',
334
- messageId: packet.messageId
335
- })
336
- t.not(packet.messageId, 42, 'messageId must differ')
337
- delete packet.messageId
338
- t.same(packet, expected, 'packet must match')
339
- })
313
+ const packet = await nextPacket(subscriber2)
314
+ subscriber2.inStream.write({
315
+ cmd: 'puback',
316
+ messageId: packet.messageId
340
317
  })
318
+ t.assert.ok(packet.messageId !== 42, 'messageId must differ')
319
+ delete packet.messageId
320
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
341
321
  })
342
322
 
343
- test('restore multiple QoS 1 subscriptions not clean w/ authorizeSubscribe', function (t) {
323
+ test('restore multiple QoS 1 subscriptions not clean w/ authorizeSubscribe', async (t) => {
344
324
  t.plan(11)
345
325
 
346
- const broker = aedes()
347
- t.teardown(broker.close.bind(broker))
326
+ const { broker, publisher, subscriber } = await createPubSub(t, {
327
+ subscriber: { clean: false, clientId: 'abcde' }
328
+ })
348
329
 
349
- let subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' })
350
330
  const expected = {
351
331
  cmd: 'publish',
352
332
  topic: 'foo',
@@ -356,103 +336,85 @@ test('restore multiple QoS 1 subscriptions not clean w/ authorizeSubscribe', fun
356
336
  length: 10,
357
337
  retain: false
358
338
  }
359
- const publisher = connect(setup(broker))
360
-
361
- subscribe(t, subscriber, 'hello', 1, function () {
362
- subscribe(t, subscriber, 'foo', 1, function () {
363
- subscriber.inStream.end()
364
- broker.authorizeSubscribe = function (client, sub, done) {
365
- done(null, sub.topic === 'hello' ? 123 : sub)
366
- }
367
- subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' }, function (connect) {
368
- t.equal(connect.sessionPresent, true, 'session present is set to true')
369
- publisher.inStream.write({
370
- cmd: 'publish',
371
- topic: 'hello',
372
- payload: 'world',
373
- qos: 1,
374
- messageId: 42
375
- })
376
- publisher.inStream.write({
377
- cmd: 'publish',
378
- topic: 'foo',
379
- payload: 'bar',
380
- qos: 1,
381
- messageId: 48
382
- })
383
- })
384
- publisher.outStream.on('data', function (packet) {
385
- t.equal(packet.cmd, 'puback')
386
- })
387
339
 
388
- subscriber.outStream.on('data', function (packet) {
389
- subscriber.inStream.write({
390
- cmd: 'puback',
391
- messageId: packet.messageId
392
- })
393
- t.not(packet.messageId, 48, 'messageId must differ')
394
- delete packet.messageId
395
- t.same(packet, expected, 'packet must match')
396
- })
397
- })
340
+ await subscribe(t, subscriber, 'hello', 1)
341
+ await subscribe(t, subscriber, 'foo', 1)
342
+ subscriber.inStream.end()
343
+ broker.authorizeSubscribe = (client, sub, done) => {
344
+ done(null, sub.topic === 'hello' ? 123 : sub)
345
+ }
346
+ const subscriber2 = setup(broker)
347
+ const connack = await connect(subscriber2, { connect: { clean: false, clientId: 'abcde' } })
348
+ t.assert.equal(connack.sessionPresent, true, 'session present is set to true')
349
+ publish(t, publisher, {
350
+ cmd: 'publish',
351
+ topic: 'hello',
352
+ payload: 'world',
353
+ qos: 1,
354
+ messageId: 42
355
+ })
356
+ publish(t, publisher, {
357
+ cmd: 'publish',
358
+ topic: 'foo',
359
+ payload: 'bar',
360
+ qos: 1,
361
+ messageId: 48
398
362
  })
399
- })
400
-
401
- test('remove stored subscriptions if connected with clean=true', function (t) {
402
- t.plan(5)
403
-
404
- const broker = aedes()
405
- t.teardown(broker.close.bind(broker))
406
-
407
- let subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' })
408
363
 
409
- subscribe(t, subscriber, 'hello', 1, function () {
410
- subscriber.inStream.end()
364
+ const packet = await nextPacket(subscriber2)
365
+ subscriber.inStream.write({
366
+ cmd: 'puback',
367
+ messageId: packet.messageId
368
+ })
369
+ t.assert.ok((packet.messageId !== 48), 'messageId must differ')
370
+ delete packet.messageId
371
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
372
+ })
411
373
 
412
- const publisher = connect(setup(broker))
374
+ test('remove stored subscriptions if connected with clean=true', async (t) => {
375
+ t.plan(7)
413
376
 
414
- subscriber = connect(setup(broker), { clean: true, clientId: 'abcde' }, function (packet) {
415
- t.equal(packet.sessionPresent, false, 'session present is set to false')
416
- publisher.inStream.write({
417
- cmd: 'publish',
418
- topic: 'hello',
419
- payload: 'world',
420
- qos: 1,
421
- messageId: 42
422
- })
377
+ const { broker, publisher, subscriber } = await createPubSub(t, {
378
+ subscriber: { clean: false, clientId: 'abcde' }
379
+ })
423
380
 
424
- subscriber.inStream.end()
425
-
426
- subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' }, function (connect) {
427
- t.equal(connect.sessionPresent, false, 'session present is set to false')
428
- publisher.inStream.write({
429
- cmd: 'publish',
430
- topic: 'hello',
431
- payload: 'world',
432
- qos: 1,
433
- messageId: 43
434
- })
435
- })
381
+ await subscribe(t, subscriber, 'hello', 1)
382
+ subscriber.inStream.end()
436
383
 
437
- subscriber.outStream.once('data', function (packet) {
438
- t.fail('publish received')
439
- })
440
- })
384
+ const subscriber2 = setup(broker)
385
+ const connack = await connect(subscriber2, { connect: { clean: true, clientId: 'abcde' } })
386
+ t.assert.equal(connack.sessionPresent, false, 'session present is set to false')
387
+ publisher.inStream.write({
388
+ cmd: 'publish',
389
+ topic: 'hello',
390
+ payload: 'world',
391
+ qos: 1,
392
+ messageId: 42
393
+ })
394
+ subscriber2.inStream.end()
441
395
 
442
- subscriber.outStream.once('data', function (packet) {
443
- t.fail('publish received')
444
- })
396
+ const subscriber3 = setup(broker)
397
+ const connack2 = await connect(subscriber3, { connect: { clean: false, clientId: 'abcde' } })
398
+ t.assert.equal(connack2.sessionPresent, false, 'session present is set to false')
399
+ publisher.inStream.write({
400
+ cmd: 'publish',
401
+ topic: 'hello',
402
+ payload: 'world',
403
+ qos: 1,
404
+ messageId: 43
445
405
  })
406
+ await checkNoPacket(t, subscriber2, 10)
407
+ await checkNoPacket(t, subscriber3, 10)
446
408
  })
447
409
 
448
- test('resend publish on non-clean reconnect QoS 1', function (t) {
410
+ test('resend publish on non-clean reconnect QoS 1', async (t) => {
449
411
  t.plan(8)
450
412
 
451
- const broker = aedes()
452
- t.teardown(broker.close.bind(broker))
453
-
454
413
  const opts = { clean: false, clientId: 'abcde' }
455
- let subscriber = connect(setup(broker), opts)
414
+ const { broker, publisher, subscriber } = await createPubSub(t, {
415
+ subscriber: opts
416
+ })
417
+
456
418
  const subscriberClient = {
457
419
  id: opts.clientId
458
420
  }
@@ -466,105 +428,91 @@ test('resend publish on non-clean reconnect QoS 1', function (t) {
466
428
  retain: false
467
429
  }
468
430
 
469
- subscribe(t, subscriber, 'hello', 1, function () {
470
- subscriber.inStream.end()
471
-
472
- const publisher = connect(setup(broker))
431
+ await subscribe(t, subscriber, 'hello', 1)
432
+ subscriber.inStream.end()
433
+ publisher.inStream.write({
434
+ cmd: 'publish',
435
+ topic: 'hello',
436
+ payload: 'world',
437
+ qos: 1,
438
+ messageId: 42
439
+ })
440
+ publisher.inStream.write({
441
+ cmd: 'publish',
442
+ topic: 'hello',
443
+ payload: 'world world',
444
+ qos: 1,
445
+ messageId: 42
446
+ })
447
+ const puback = await nextPacket(publisher)
448
+ t.assert.equal(puback.cmd, 'puback')
473
449
 
474
- publisher.inStream.write({
475
- cmd: 'publish',
476
- topic: 'hello',
477
- payload: 'world',
478
- qos: 1,
479
- messageId: 42
480
- })
481
- publisher.inStream.write({
482
- cmd: 'publish',
483
- topic: 'hello',
484
- payload: 'world world',
485
- qos: 1,
486
- messageId: 42
487
- })
488
- publisher.outStream.once('data', function (packet) {
489
- t.equal(packet.cmd, 'puback')
490
-
491
- subscriber = connect(setup(broker), opts)
492
-
493
- subscriber.outStream.once('data', function (packet) {
494
- subscriber.inStream.write({
495
- cmd: 'puback',
496
- messageId: packet.messageId
497
- })
498
- t.not(packet.messageId, 42, 'messageId must differ')
499
- delete packet.messageId
500
- t.same(packet, expected, 'packet must match')
501
- setImmediate(() => {
502
- const stream = broker.persistence.outgoingStream(subscriberClient)
503
- stream.pipe(concat(function (list) {
504
- t.equal(list.length, 1, 'should remain one item in queue')
505
- t.same(list[0].payload, Buffer.from('world world'), 'packet must match')
506
- }))
507
- })
508
- })
509
- })
450
+ const subscriber2 = setup(broker)
451
+ await connect(subscriber2, { connect: opts })
452
+ const packet = await nextPacket(subscriber2)
453
+ subscriber2.inStream.write({
454
+ cmd: 'puback',
455
+ messageId: packet.messageId
510
456
  })
457
+ t.assert.ok(packet.messageId !== 42, 'messageId must differ')
458
+ delete packet.messageId
459
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
460
+ await delay(0) // give aedes the time to process the pubAck
461
+ const stream = broker.persistence.outgoingStream(subscriberClient)
462
+ const list = await stream.toArray()
463
+ t.assert.equal(list.length, 1, 'should remain one item in queue')
464
+ t.assert.deepEqual(list[0].payload, Buffer.from('world world'), 'packet must match')
511
465
  })
512
466
 
513
- test('resend many publish on non-clean reconnect QoS 1', function (t) {
514
- t.plan(4)
515
- const broker = aedes()
516
- const clock = Faketimers.createClock()
517
-
518
- t.teardown(() => {
519
- broker.close.bind(broker)
520
- clock.reset.bind(clock)
521
- })
467
+ test('resend many publish on non-clean reconnect QoS 1', async (t) => {
468
+ t.plan(5)
522
469
 
523
470
  const opts = { clean: false, clientId: 'abcde' }
524
- let subscriber = connect(setup(broker), opts)
525
- const publisher = connect(setup(broker))
526
- const { through } = require('../lib/utils')
527
- const total = through().writableHighWaterMark * 2
471
+ const { broker, publisher, subscriber } = await createPubSub(t, {
472
+ subscriber: opts
473
+ })
528
474
 
475
+ const total = publisher.inStream.writableHighWaterMark * 2
529
476
  let received = 0
530
- clock.setTimeout(() => {
531
- broker.close()
532
- t.equal(received, total)
533
- }, total)
534
477
 
535
- subscribe(t, subscriber, 'hello', 1, function () {
536
- subscriber.inStream.end()
478
+ await subscribe(t, subscriber, 'hello', 1)
479
+ subscriber.inStream.end()
537
480
 
538
- for (let sent = 0; sent < total; sent++) {
539
- publisher.inStream.write({
540
- cmd: 'publish',
541
- topic: 'hello',
542
- payload: 'message-' + sent,
543
- qos: 1,
544
- messageId: 42 + sent
545
- })
546
- }
547
- publisher.outStream.once('data', function (packet) {
548
- subscriber = connect(setup(broker), opts)
549
- subscriber.outStream.on('data', function (packet) {
550
- subscriber.inStream.write({
551
- cmd: 'puback',
552
- messageId: packet.messageId
553
- })
554
- received++
555
- clock.tick(1)
556
- })
481
+ for (let sent = 0; sent < total; sent++) {
482
+ publisher.inStream.write({
483
+ cmd: 'publish',
484
+ topic: 'hello',
485
+ payload: 'message-' + sent,
486
+ qos: 1,
487
+ messageId: 42 + sent
557
488
  })
558
- })
489
+ }
490
+
491
+ await nextPacket(publisher)
492
+ const subscriber2 = setup(broker)
493
+ await connect(subscriber2, { connect: opts })
494
+ for await (const packet of subscriber2.outStream) {
495
+ subscriber2.inStream.write({
496
+ cmd: 'puback',
497
+ messageId: packet.messageId
498
+ })
499
+ received++
500
+ if (received === total) {
501
+ break
502
+ }
503
+ }
504
+ await checkNoPacket(t, subscriber2, 10) // just make sure there are not more packets
505
+ t.assert.equal(received, total)
559
506
  })
560
507
 
561
- test('do not resend QoS 1 packets at each reconnect', function (t) {
562
- t.plan(6)
508
+ test('do not resend QoS 1 packets at each reconnect', async (t) => {
509
+ t.plan(7)
563
510
 
564
- const broker = aedes()
565
- t.teardown(broker.close.bind(broker))
511
+ const opts = { clean: false, clientId: 'abcde' }
512
+ const { broker, publisher, subscriber } = await createPubSub(t, {
513
+ subscriber: opts
514
+ })
566
515
 
567
- let subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' })
568
516
  const expected = {
569
517
  cmd: 'publish',
570
518
  topic: 'hello',
@@ -575,84 +523,65 @@ test('do not resend QoS 1 packets at each reconnect', function (t) {
575
523
  retain: false
576
524
  }
577
525
 
578
- subscribe(t, subscriber, 'hello', 1, function () {
579
- subscriber.inStream.end()
580
-
581
- const publisher = connect(setup(broker))
582
-
583
- publisher.inStream.write({
584
- cmd: 'publish',
585
- topic: 'hello',
586
- payload: 'world',
587
- qos: 1,
588
- messageId: 42
589
- })
590
-
591
- publisher.outStream.once('data', function (packet) {
592
- t.equal(packet.cmd, 'puback')
526
+ await subscribe(t, subscriber, 'hello', 1)
527
+ subscriber.inStream.end()
593
528
 
594
- subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' })
595
-
596
- subscriber.outStream.once('data', function (packet) {
597
- subscriber.inStream.end({
598
- cmd: 'puback',
599
- messageId: packet.messageId
600
- })
601
-
602
- t.not(packet.messageId, 42, 'messageId must differ')
603
- delete packet.messageId
604
- t.same(packet, expected, 'packet must match')
605
-
606
- const subscriber2 = connect(setup(broker), { clean: false, clientId: 'abcde' })
607
-
608
- subscriber2.outStream.once('data', function (packet) {
609
- t.fail('this should never happen')
610
- })
611
- })
612
- })
529
+ await publish(t, publisher, {
530
+ cmd: 'publish',
531
+ topic: 'hello',
532
+ payload: 'world',
533
+ qos: 1,
534
+ messageId: 42
613
535
  })
614
- })
615
536
 
616
- test('do not resend QoS 1 packets if reconnect is clean', function (t) {
617
- t.plan(4)
537
+ const subscriber2 = setup(broker)
538
+ await connect(subscriber2, { connect: opts })
618
539
 
619
- const broker = aedes()
620
- t.teardown(broker.close.bind(broker))
621
-
622
- let subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' })
540
+ const packet = await nextPacket(subscriber2)
541
+ subscriber2.inStream.end({
542
+ cmd: 'puback',
543
+ messageId: packet.messageId
544
+ })
623
545
 
624
- subscribe(t, subscriber, 'hello', 1, function () {
625
- subscriber.inStream.end()
546
+ t.assert.ok(packet.messageId !== 42, 'messageId must differ')
547
+ delete packet.messageId
548
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
626
549
 
627
- const publisher = connect(setup(broker))
550
+ const subscriber3 = setup(broker)
551
+ await connect(subscriber3, { connect: opts })
552
+ await checkNoPacket(t, subscriber3, 10)
553
+ })
628
554
 
629
- publisher.inStream.write({
630
- cmd: 'publish',
631
- topic: 'hello',
632
- payload: 'world',
633
- qos: 1,
634
- messageId: 42
635
- })
555
+ test('do not resend QoS 1 packets if reconnect is clean', async (t) => {
556
+ t.plan(5)
636
557
 
637
- publisher.outStream.once('data', function (packet) {
638
- t.equal(packet.cmd, 'puback')
558
+ const { broker, publisher, subscriber } = await createPubSub(t, {
559
+ subscriber: { clean: false, clientId: 'abcde' }
560
+ })
639
561
 
640
- subscriber = connect(setup(broker), { clean: true, clientId: 'abcde' })
562
+ await subscribe(t, subscriber, 'hello', 1)
563
+ subscriber.inStream.end()
641
564
 
642
- subscriber.outStream.once('data', function (packet) {
643
- t.fail('this should never happen')
644
- })
645
- })
565
+ await publish(t, publisher, {
566
+ cmd: 'publish',
567
+ topic: 'hello',
568
+ payload: 'world',
569
+ qos: 1,
570
+ messageId: 42
646
571
  })
572
+
573
+ const subscriber2 = setup(broker)
574
+ await connect(subscriber2, { connect: { clean: true, clientId: 'abcde' } })
575
+ await checkNoPacket(t, subscriber2, 10)
647
576
  })
648
577
 
649
- test('do not resend QoS 1 packets at reconnect if puback was received', function (t) {
650
- t.plan(5)
578
+ test('do not resend QoS 1 packets at reconnect if puback was received', async (t) => {
579
+ t.plan(6)
651
580
 
652
- const broker = aedes()
653
- t.teardown(broker.close.bind(broker))
581
+ const { broker, publisher, subscriber } = await createPubSub(t, {
582
+ subscriber: { clean: false, clientId: 'abcde' }
583
+ })
654
584
 
655
- let subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' })
656
585
  const expected = {
657
586
  cmd: 'publish',
658
587
  topic: 'hello',
@@ -663,105 +592,86 @@ test('do not resend QoS 1 packets at reconnect if puback was received', function
663
592
  retain: false
664
593
  }
665
594
 
666
- subscribe(t, subscriber, 'hello', 1, function () {
667
- const publisher = connect(setup(broker))
668
-
669
- publisher.inStream.write({
670
- cmd: 'publish',
671
- topic: 'hello',
672
- payload: 'world',
673
- qos: 1,
674
- messageId: 42
675
- })
595
+ await subscribe(t, subscriber, 'hello', 1)
596
+ await publish(t, publisher, {
597
+ cmd: 'publish',
598
+ topic: 'hello',
599
+ payload: 'world',
600
+ qos: 1,
601
+ messageId: 42
602
+ })
676
603
 
677
- publisher.outStream.once('data', function (packet) {
678
- t.equal(packet.cmd, 'puback')
679
- })
604
+ const packet = await nextPacket(subscriber)
605
+ subscriber.inStream.end({
606
+ cmd: 'puback',
607
+ messageId: packet.messageId
608
+ })
680
609
 
681
- subscriber.outStream.once('data', function (packet) {
682
- subscriber.inStream.end({
683
- cmd: 'puback',
684
- messageId: packet.messageId
685
- })
610
+ delete packet.messageId
611
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
686
612
 
687
- delete packet.messageId
688
- t.same(packet, expected, 'packet must match')
613
+ const subscriber2 = setup(broker)
614
+ await connect(subscriber2, { connect: { clean: false, clientId: 'abcde' } })
615
+ await checkNoPacket(t, subscriber2, 10)
616
+ })
689
617
 
690
- subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' })
618
+ test('remove stored subscriptions after unsubscribe', async (t) => {
619
+ t.plan(7)
691
620
 
692
- subscriber.outStream.once('data', function (packet) {
693
- t.fail('this should never happen')
694
- })
695
- })
621
+ const { broker, publisher, subscriber } = await createPubSub(t, {
622
+ subscriber: { clean: false, clientId: 'abcde' }
696
623
  })
697
- })
698
624
 
699
- test('remove stored subscriptions after unsubscribe', function (t) {
700
- t.plan(5)
701
-
702
- const broker = aedes()
703
- t.teardown(broker.close.bind(broker))
625
+ await subscribe(t, subscriber, 'hello', 1)
626
+ subscriber.inStream.write({
627
+ cmd: 'unsubscribe',
628
+ messageId: 43,
629
+ unsubscriptions: ['hello']
630
+ })
704
631
 
705
- let subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' })
632
+ const packet = await nextPacket(subscriber)
633
+ t.assert.deepStrictEqual(structuredClone(packet), {
634
+ cmd: 'unsuback',
635
+ messageId: 43,
636
+ dup: false,
637
+ length: 2,
638
+ qos: 0,
639
+ retain: false,
640
+ payload: null,
641
+ topic: null
642
+ }, 'packet matches')
706
643
 
707
- subscribe(t, subscriber, 'hello', 1, function () {
708
- subscriber.inStream.write({
709
- cmd: 'unsubscribe',
710
- messageId: 43,
711
- unsubscriptions: ['hello']
712
- })
644
+ subscriber.inStream.end()
713
645
 
714
- subscriber.outStream.once('data', function (packet) {
715
- t.same(packet, {
716
- cmd: 'unsuback',
717
- messageId: 43,
718
- dup: false,
719
- length: 2,
720
- qos: 0,
721
- retain: false
722
- }, 'packet matches')
723
-
724
- subscriber.inStream.end()
725
-
726
- const publisher = connect(setup(broker))
727
-
728
- subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' }, function (packet) {
729
- t.equal(packet.sessionPresent, false, 'session present is set to false')
730
- publisher.inStream.write({
731
- cmd: 'publish',
732
- topic: 'hello',
733
- payload: 'world',
734
- qos: 1,
735
- messageId: 42
736
- })
737
-
738
- publisher.inStream.write({
739
- cmd: 'publish',
740
- topic: 'hello',
741
- payload: 'world',
742
- qos: 1,
743
- messageId: 43
744
- }, function () {
745
- subscriber.inStream.end()
746
- })
747
-
748
- subscriber.outStream.once('data', function (packet) {
749
- t.fail('publish received')
750
- })
751
- })
646
+ const subscriber2 = setup(broker)
647
+ const connack = await connect(subscriber2, { connect: { clean: false, clientId: 'abcde' } })
648
+ t.assert.equal(connack.sessionPresent, false, 'session present is set to false')
649
+ publisher.inStream.write({
650
+ cmd: 'publish',
651
+ topic: 'hello',
652
+ payload: 'world',
653
+ qos: 1,
654
+ messageId: 42
655
+ })
752
656
 
753
- subscriber.outStream.once('data', function (packet) {
754
- t.fail('publish received')
755
- })
756
- })
657
+ publisher.inStream.write({
658
+ cmd: 'publish',
659
+ topic: 'hello',
660
+ payload: 'world',
661
+ qos: 1,
662
+ messageId: 43
663
+ }, () => {
664
+ subscriber.inStream.end()
757
665
  })
666
+
667
+ await checkNoPacket(t, subscriber, 10)
668
+ await checkNoPacket(t, subscriber2, 10)
758
669
  })
759
670
 
760
- test('upgrade a QoS 0 subscription to QoS 1', function (t) {
671
+ test('upgrade a QoS 0 subscription to QoS 1', async (t) => {
761
672
  t.plan(8)
762
673
 
763
- const s = connect(setup())
764
- t.teardown(s.broker.close.bind(s.broker))
674
+ const s = await createAndConnect(t)
765
675
 
766
676
  const expected = {
767
677
  cmd: 'publish',
@@ -773,29 +683,26 @@ test('upgrade a QoS 0 subscription to QoS 1', function (t) {
773
683
  dup: false
774
684
  }
775
685
 
776
- subscribe(t, s, 'hello', 0, function () {
777
- subscribe(t, s, 'hello', 1, function () {
778
- s.outStream.once('data', function (packet) {
779
- t.ok(packet.messageId, 'has messageId')
780
- delete packet.messageId
781
- t.same(packet, expected, 'packet matches')
782
- })
686
+ await subscribe(t, s, 'hello', 0)
687
+ await subscribe(t, s, 'hello', 1)
783
688
 
784
- s.broker.publish({
785
- cmd: 'publish',
786
- topic: 'hello',
787
- payload: 'world',
788
- qos: 1
789
- })
790
- })
689
+ s.broker.publish({
690
+ cmd: 'publish',
691
+ topic: 'hello',
692
+ payload: 'world',
693
+ qos: 1
791
694
  })
695
+
696
+ const packet = await nextPacket(s)
697
+ t.assert.ok(packet.messageId, 'has messageId')
698
+ delete packet.messageId
699
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
792
700
  })
793
701
 
794
- test('downgrade QoS 0 publish on QoS 1 subsciption', function (t) {
702
+ test('downgrade QoS 0 publish on QoS 1 subsciption', async (t) => {
795
703
  t.plan(4)
796
704
 
797
- const s = connect(setup())
798
- t.teardown(s.broker.close.bind(s.broker))
705
+ const s = await createAndConnect(t)
799
706
 
800
707
  const expected = {
801
708
  cmd: 'publish',
@@ -807,26 +714,23 @@ test('downgrade QoS 0 publish on QoS 1 subsciption', function (t) {
807
714
  dup: false
808
715
  }
809
716
 
810
- subscribe(t, s, 'hello', 1, function () {
811
- s.outStream.once('data', function (packet) {
812
- t.same(packet, expected, 'packet matches')
813
- })
814
- s.broker.publish({
815
- cmd: 'publish',
816
- topic: 'hello',
817
- payload: 'world',
818
- qos: 0
819
- })
717
+ await subscribe(t, s, 'hello', 1)
718
+
719
+ s.broker.publish({
720
+ cmd: 'publish',
721
+ topic: 'hello',
722
+ payload: 'world',
723
+ qos: 0
820
724
  })
725
+
726
+ const packet = await nextPacket(s)
727
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
821
728
  })
822
729
 
823
- test('subscribe and publish QoS 1 in parallel', function (t) {
730
+ test('subscribe and publish QoS 1 in parallel', async (t) => {
824
731
  t.plan(5)
825
732
 
826
- const broker = aedes()
827
- t.teardown(broker.close.bind(broker))
828
-
829
- const s = connect(setup(broker))
733
+ const s = await createAndConnect(t)
830
734
  const expected = {
831
735
  cmd: 'publish',
832
736
  topic: 'hello',
@@ -837,28 +741,9 @@ test('subscribe and publish QoS 1 in parallel', function (t) {
837
741
  retain: false
838
742
  }
839
743
 
840
- broker.on('clientError', function (client, err) {
744
+ s.broker.on('clientError', (client, err) => {
841
745
  console.log(err.stack)
842
- // t.fail('no client error')
843
- })
844
-
845
- s.outStream.once('data', function (packet) {
846
- t.equal(packet.cmd, 'puback')
847
- t.equal(packet.messageId, 42, 'messageId must match')
848
- s.outStream.on('data', function (packet) {
849
- if (packet.cmd === 'suback') {
850
- t.same(packet.granted, [1])
851
- t.equal(packet.messageId, 24)
852
- }
853
- if (packet.cmd === 'publish') {
854
- s.inStream.write({
855
- cmd: 'puback',
856
- messageId: packet.messageId
857
- })
858
- delete packet.messageId
859
- t.same(packet, expected, 'packet must match')
860
- }
861
- })
746
+ t.fail('no client error')
862
747
  })
863
748
 
864
749
  s.inStream.write({
@@ -877,4 +762,29 @@ test('subscribe and publish QoS 1 in parallel', function (t) {
877
762
  qos: 1,
878
763
  messageId: 42
879
764
  })
765
+
766
+ let counter = 0
767
+ for await (const packet of s.outStream) {
768
+ counter++
769
+ if (counter === 1) {
770
+ t.assert.equal(packet.cmd, 'puback')
771
+ t.assert.equal(packet.messageId, 42, 'messageId must match')
772
+ }
773
+
774
+ if (packet.cmd === 'suback') {
775
+ t.assert.deepEqual(structuredClone(packet).granted, [1])
776
+ t.assert.equal(packet.messageId, 24)
777
+ }
778
+ if (packet.cmd === 'publish') {
779
+ s.inStream.write({
780
+ cmd: 'puback',
781
+ messageId: packet.messageId
782
+ })
783
+ delete packet.messageId
784
+ t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
785
+ }
786
+ if (counter === 3) {
787
+ break
788
+ }
789
+ }
880
790
  })