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.
- package/.claude/settings.local.json +12 -0
- package/.github/actions/sticky-pr-comment/action.yml +55 -0
- package/.github/workflows/benchmark-compare-serial.yml +60 -0
- package/.github/workflows/ci.yml +12 -17
- package/.release-it.json +18 -0
- package/.taprc +15 -6
- package/README.md +6 -4
- package/aedes.d.ts +0 -6
- package/aedes.js +270 -242
- package/benchmarks/README.md +33 -0
- package/benchmarks/pingpong.js +94 -25
- package/benchmarks/receiver.js +77 -0
- package/benchmarks/report.js +150 -0
- package/benchmarks/runBenchmarks.js +118 -0
- package/benchmarks/sender.js +86 -0
- package/benchmarks/server.js +19 -18
- package/checkVersion.js +20 -0
- package/docs/Aedes.md +66 -8
- package/docs/Client.md +3 -4
- package/docs/Examples.md +39 -22
- package/docs/MIGRATION.md +50 -0
- package/eslint.config.js +8 -0
- package/example.js +51 -40
- package/examples/clusters/index.js +28 -23
- package/examples/clusters/package.json +10 -6
- package/lib/client.js +405 -306
- package/lib/handlers/connect.js +42 -38
- package/lib/handlers/index.js +9 -11
- package/lib/handlers/ping.js +2 -3
- package/lib/handlers/puback.js +5 -5
- package/lib/handlers/publish.js +29 -14
- package/lib/handlers/pubrec.js +9 -17
- package/lib/handlers/pubrel.js +34 -25
- package/lib/handlers/subscribe.js +47 -43
- package/lib/handlers/unsubscribe.js +16 -19
- package/lib/qos-packet.js +14 -17
- package/lib/utils.js +5 -12
- package/lib/write.js +4 -5
- package/package.json +139 -136
- package/test/auth.js +468 -804
- package/test/basic.js +613 -575
- package/test/bridge.js +44 -40
- package/test/client-pub-sub.js +531 -504
- package/test/close_socket_by_other_party.js +137 -102
- package/test/connect.js +487 -484
- package/test/drain-timeout.js +593 -0
- package/test/drain-toxiproxy.js +620 -0
- package/test/events.js +173 -145
- package/test/helper.js +351 -73
- package/test/keep-alive.js +40 -67
- package/test/meta.js +257 -210
- package/test/not-blocking.js +93 -197
- package/test/qos1.js +464 -554
- package/test/qos2.js +308 -393
- package/test/regr-21.js +39 -21
- package/test/require.cjs +22 -0
- package/test/retain.js +349 -398
- package/test/topics.js +176 -183
- package/test/types/aedes.test-d.ts +4 -8
- package/test/will.js +310 -428
- package/types/instance.d.ts +40 -35
- package/types/packet.d.ts +10 -10
- package/.coveralls.yml +0 -1
- package/benchmarks/bombing.js +0 -34
- package/benchmarks/bombingQoS1.js +0 -36
- package/benchmarks/throughputCounter.js +0 -23
- package/benchmarks/throughputCounterQoS1.js +0 -33
- package/types/.eslintrc.json +0 -47
package/test/qos2.js
CHANGED
|
@@ -1,87 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { test } from 'node:test'
|
|
2
|
+
import { once } from 'node:events'
|
|
3
|
+
import {
|
|
4
|
+
checkNoPacket,
|
|
5
|
+
connect,
|
|
6
|
+
createAndConnect,
|
|
7
|
+
createPubSub,
|
|
8
|
+
nextPacket,
|
|
9
|
+
publish,
|
|
10
|
+
setup,
|
|
11
|
+
subscribe,
|
|
12
|
+
} from './helper.js'
|
|
13
|
+
import { Aedes } from '../aedes.js'
|
|
14
|
+
import handle from '../lib/handlers/pubrec.js'
|
|
15
|
+
|
|
16
|
+
async function receive (t, subscriber, expected) {
|
|
17
|
+
const packet = await nextPacket(subscriber)
|
|
18
|
+
t.assert.ok(packet.messageId !== expected.messageId, 'messageId must differ')
|
|
9
19
|
const msgId = packet.messageId
|
|
20
|
+
delete packet.messageId
|
|
21
|
+
delete expected.messageId
|
|
22
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
|
|
10
23
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
t.same(packet, {
|
|
15
|
-
cmd: 'pubrec',
|
|
16
|
-
messageId: msgId,
|
|
17
|
-
length: 2,
|
|
18
|
-
dup: false,
|
|
19
|
-
retain: false,
|
|
20
|
-
qos: 0
|
|
21
|
-
}, 'pubrec must match')
|
|
22
|
-
|
|
23
|
-
s.inStream.write({
|
|
24
|
-
cmd: 'pubrel',
|
|
25
|
-
messageId: msgId
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
s.outStream.once('data', function (packet) {
|
|
29
|
-
t.same(packet, {
|
|
30
|
-
cmd: 'pubcomp',
|
|
31
|
-
messageId: msgId,
|
|
32
|
-
length: 2,
|
|
33
|
-
dup: false,
|
|
34
|
-
retain: false,
|
|
35
|
-
qos: 0
|
|
36
|
-
}, 'pubcomp must match')
|
|
37
|
-
|
|
38
|
-
if (done) {
|
|
39
|
-
done()
|
|
40
|
-
}
|
|
41
|
-
})
|
|
24
|
+
subscriber.inStream.write({
|
|
25
|
+
cmd: 'pubrec',
|
|
26
|
+
messageId: msgId
|
|
42
27
|
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function receive (t, subscriber, expected, done) {
|
|
46
|
-
subscriber.outStream.once('data', function (packet) {
|
|
47
|
-
t.not(packet.messageId, expected.messageId, 'messageId must differ')
|
|
48
|
-
|
|
49
|
-
const msgId = packet.messageId
|
|
50
|
-
delete packet.messageId
|
|
51
|
-
delete expected.messageId
|
|
52
|
-
t.same(packet, expected, 'packet must match')
|
|
53
28
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
29
|
+
const pubRel = await nextPacket(subscriber)
|
|
30
|
+
t.assert.deepStrictEqual(structuredClone(pubRel), {
|
|
31
|
+
cmd: 'pubrel',
|
|
32
|
+
messageId: msgId,
|
|
33
|
+
length: 2,
|
|
34
|
+
qos: 1,
|
|
35
|
+
retain: false,
|
|
36
|
+
dup: false,
|
|
37
|
+
payload: null,
|
|
38
|
+
topic: null
|
|
39
|
+
}, 'pubrel must match')
|
|
58
40
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
messageId: msgId
|
|
63
|
-
})
|
|
64
|
-
t.same(packet, {
|
|
65
|
-
cmd: 'pubrel',
|
|
66
|
-
messageId: msgId,
|
|
67
|
-
length: 2,
|
|
68
|
-
qos: 1,
|
|
69
|
-
retain: false,
|
|
70
|
-
dup: false
|
|
71
|
-
}, 'pubrel must match')
|
|
72
|
-
|
|
73
|
-
if (done) {
|
|
74
|
-
done()
|
|
75
|
-
}
|
|
76
|
-
})
|
|
41
|
+
subscriber.inStream.write({
|
|
42
|
+
cmd: 'pubcomp',
|
|
43
|
+
messageId: msgId
|
|
77
44
|
})
|
|
78
45
|
}
|
|
79
46
|
|
|
80
|
-
test('publish QoS 2',
|
|
47
|
+
test('publish QoS 2', async (t) => {
|
|
81
48
|
t.plan(2)
|
|
82
49
|
|
|
83
|
-
const s =
|
|
84
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
50
|
+
const s = await createAndConnect(t)
|
|
85
51
|
|
|
86
52
|
const packet = {
|
|
87
53
|
cmd: 'publish',
|
|
@@ -90,17 +56,13 @@ test('publish QoS 2', function (t) {
|
|
|
90
56
|
qos: 2,
|
|
91
57
|
messageId: 42
|
|
92
58
|
}
|
|
93
|
-
publish(t, s, packet)
|
|
59
|
+
await publish(t, s, packet)
|
|
94
60
|
})
|
|
95
61
|
|
|
96
|
-
test('subscribe QoS 2',
|
|
62
|
+
test('subscribe QoS 2', async (t) => {
|
|
97
63
|
t.plan(8)
|
|
98
64
|
|
|
99
|
-
const
|
|
100
|
-
t.teardown(broker.close.bind(broker))
|
|
101
|
-
|
|
102
|
-
const publisher = connect(setup(broker))
|
|
103
|
-
const subscriber = connect(setup(broker))
|
|
65
|
+
const { publisher, subscriber } = await createPubSub(t)
|
|
104
66
|
const toPublish = {
|
|
105
67
|
cmd: 'publish',
|
|
106
68
|
topic: 'hello',
|
|
@@ -112,20 +74,19 @@ test('subscribe QoS 2', function (t) {
|
|
|
112
74
|
retain: false
|
|
113
75
|
}
|
|
114
76
|
|
|
115
|
-
subscribe(t, subscriber, 'hello', 2
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
receive(t, subscriber, toPublish)
|
|
119
|
-
})
|
|
77
|
+
await subscribe(t, subscriber, 'hello', 2)
|
|
78
|
+
await publish(t, publisher, toPublish)
|
|
79
|
+
await receive(t, subscriber, toPublish)
|
|
120
80
|
})
|
|
121
81
|
|
|
122
|
-
test('publish QoS 2 throws error on write',
|
|
123
|
-
t.plan(
|
|
82
|
+
test('publish QoS 2 throws error on write', async (t) => {
|
|
83
|
+
t.plan(2)
|
|
124
84
|
|
|
125
|
-
const
|
|
126
|
-
t.
|
|
85
|
+
const broker = await Aedes.createBroker()
|
|
86
|
+
t.after(() => broker.close())
|
|
87
|
+
const s = setup(broker)
|
|
127
88
|
|
|
128
|
-
s.broker.on('client',
|
|
89
|
+
s.broker.on('client', (client) => {
|
|
129
90
|
client.connected = false
|
|
130
91
|
client.connecting = false
|
|
131
92
|
|
|
@@ -138,34 +99,34 @@ test('publish QoS 2 throws error on write', function (t) {
|
|
|
138
99
|
})
|
|
139
100
|
})
|
|
140
101
|
|
|
141
|
-
s
|
|
142
|
-
|
|
143
|
-
|
|
102
|
+
connect(s, { noWait: true }) // don't wait for connect to complete
|
|
103
|
+
|
|
104
|
+
const [client, err] = await once(broker, 'clientError')
|
|
105
|
+
t.assert.ok(client)
|
|
106
|
+
t.assert.equal(err.message, 'connection closed', 'throws error')
|
|
144
107
|
})
|
|
145
108
|
|
|
146
|
-
test('pubrec handler calls done when outgoingUpdate fails (clean=false)',
|
|
109
|
+
test('pubrec handler calls done when outgoingUpdate fails (clean=false)', async (t) => {
|
|
147
110
|
t.plan(1)
|
|
148
111
|
|
|
149
|
-
const s =
|
|
150
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
151
|
-
|
|
152
|
-
const handle = require('../lib/handlers/pubrec.js')
|
|
112
|
+
const s = await createAndConnect(t)
|
|
153
113
|
|
|
154
|
-
s.broker.persistence.outgoingUpdate =
|
|
155
|
-
|
|
114
|
+
s.broker.persistence.outgoingUpdate = async () => {
|
|
115
|
+
throw Error('throws error')
|
|
156
116
|
}
|
|
157
117
|
|
|
158
|
-
|
|
159
|
-
|
|
118
|
+
await new Promise((resolve) => {
|
|
119
|
+
handle(s.client, { messageId: 42 }, function done () {
|
|
120
|
+
t.assert.ok(true, 'calls done on error')
|
|
121
|
+
resolve()
|
|
122
|
+
})
|
|
160
123
|
})
|
|
161
124
|
})
|
|
162
125
|
|
|
163
|
-
test('client.publish with clean=true subscribption QoS 2',
|
|
126
|
+
test('client.publish with clean=true subscribption QoS 2', async (t) => {
|
|
164
127
|
t.plan(8)
|
|
165
128
|
|
|
166
|
-
const
|
|
167
|
-
t.teardown(broker.close.bind(broker))
|
|
168
|
-
|
|
129
|
+
const s = await createAndConnect(t, { connect: { clean: true } })
|
|
169
130
|
const toPublish = {
|
|
170
131
|
cmd: 'publish',
|
|
171
132
|
topic: 'hello',
|
|
@@ -176,35 +137,27 @@ test('client.publish with clean=true subscribption QoS 2', function (t) {
|
|
|
176
137
|
length: 14,
|
|
177
138
|
retain: false
|
|
178
139
|
}
|
|
179
|
-
let brokerClient = null
|
|
180
140
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
brokerClient.on('error', function (err) {
|
|
185
|
-
t.error(err)
|
|
186
|
-
})
|
|
141
|
+
s.client.on('error', err => {
|
|
142
|
+
t.assert.ok(!err)
|
|
187
143
|
})
|
|
188
144
|
|
|
189
|
-
|
|
145
|
+
await subscribe(t, s, 'hello', 2)
|
|
146
|
+
t.assert.ok(true, 'subscribed')
|
|
190
147
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
t.error(err)
|
|
148
|
+
await new Promise((resolve) => {
|
|
149
|
+
s.client.publish(toPublish, err => {
|
|
150
|
+
t.assert.ok(!err)
|
|
151
|
+
resolve()
|
|
196
152
|
})
|
|
197
153
|
})
|
|
154
|
+
await receive(t, s, toPublish)
|
|
198
155
|
})
|
|
199
156
|
|
|
200
|
-
test('call published method with client with QoS 2',
|
|
157
|
+
test('call published method with client with QoS 2', async (t) => {
|
|
201
158
|
t.plan(9)
|
|
202
159
|
|
|
203
|
-
const broker =
|
|
204
|
-
t.teardown(broker.close.bind(broker))
|
|
205
|
-
|
|
206
|
-
const publisher = connect(setup(broker))
|
|
207
|
-
const subscriber = connect(setup(broker))
|
|
160
|
+
const { broker, publisher, subscriber } = await createPubSub(t)
|
|
208
161
|
const toPublish = {
|
|
209
162
|
cmd: 'publish',
|
|
210
163
|
topic: 'hello',
|
|
@@ -216,31 +169,28 @@ test('call published method with client with QoS 2', function (t) {
|
|
|
216
169
|
retain: false
|
|
217
170
|
}
|
|
218
171
|
|
|
219
|
-
broker.published =
|
|
172
|
+
broker.published = (packet, client, cb) => {
|
|
220
173
|
// Client is null for all server publishes
|
|
221
174
|
if (packet.topic.split('/')[0] !== '$SYS') {
|
|
222
|
-
t.ok(client, 'client must be passed to published method')
|
|
175
|
+
t.assert.ok(client, 'client must be passed to published method')
|
|
223
176
|
cb()
|
|
224
177
|
}
|
|
225
178
|
}
|
|
226
179
|
|
|
227
|
-
subscribe(t, subscriber, 'hello', 2
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
receive(t, subscriber, toPublish)
|
|
231
|
-
})
|
|
180
|
+
await subscribe(t, subscriber, 'hello', 2)
|
|
181
|
+
await publish(t, publisher, toPublish)
|
|
182
|
+
await receive(t, subscriber, toPublish)
|
|
232
183
|
})
|
|
233
184
|
|
|
234
|
-
|
|
235
|
-
test(`authorized forward publish packets in QoS 2 [clean=${cleanSession}]`,
|
|
185
|
+
for (const cleanSession of [true, false]) {
|
|
186
|
+
test(`authorized forward publish packets in QoS 2 [clean=${cleanSession}]`, async (t) => {
|
|
236
187
|
t.plan(9)
|
|
237
188
|
|
|
238
|
-
const broker =
|
|
239
|
-
|
|
189
|
+
const { broker, publisher, subscriber } = await createPubSub(t, {
|
|
190
|
+
publisher: { clientId: 'my-client-xyz-8' },
|
|
191
|
+
subscriber: { clean: cleanSession, clientId: 'abcde' }
|
|
192
|
+
})
|
|
240
193
|
|
|
241
|
-
const opts = { clean: cleanSession }
|
|
242
|
-
const publisher = connect(setup(broker), { clientId: 'my-client-xyz-8' })
|
|
243
|
-
const subscriber = connect(setup(broker), { ...opts, clientId: 'abcde' })
|
|
244
194
|
const forwarded = {
|
|
245
195
|
cmd: 'publish',
|
|
246
196
|
topic: 'hello',
|
|
@@ -260,90 +210,74 @@ test('call published method with client with QoS 2', function (t) {
|
|
|
260
210
|
length: 14,
|
|
261
211
|
dup: false
|
|
262
212
|
}
|
|
263
|
-
broker.authorizeForward =
|
|
213
|
+
broker.authorizeForward = (client, packet) => {
|
|
264
214
|
forwarded.brokerId = broker.id
|
|
265
215
|
forwarded.brokerCounter = broker.counter
|
|
266
216
|
delete packet.nl
|
|
267
|
-
t.
|
|
217
|
+
t.assert.deepEqual(structuredClone(packet), forwarded, 'forwarded packet must match')
|
|
268
218
|
return packet
|
|
269
219
|
}
|
|
270
220
|
|
|
271
|
-
subscribe(t, subscriber, 'hello', 2
|
|
272
|
-
subscriber.outStream.once('data', function (packet) {
|
|
273
|
-
t.not(packet.messageId, 42)
|
|
274
|
-
delete packet.messageId
|
|
275
|
-
t.same(packet, expected, 'packet must match')
|
|
276
|
-
})
|
|
277
|
-
|
|
278
|
-
publish(t, publisher, {
|
|
279
|
-
cmd: 'publish',
|
|
280
|
-
topic: 'hello',
|
|
281
|
-
payload: Buffer.from('world'),
|
|
282
|
-
qos: 2,
|
|
283
|
-
retain: false,
|
|
284
|
-
messageId: 42,
|
|
285
|
-
dup: false
|
|
286
|
-
}, function () {
|
|
287
|
-
const stream = broker.persistence.outgoingStream({ id: 'abcde' })
|
|
288
|
-
stream.pipe(concat(function (list) {
|
|
289
|
-
if (cleanSession) {
|
|
290
|
-
t.equal(list.length, 0, 'should have empty item in queue')
|
|
291
|
-
} else {
|
|
292
|
-
t.equal(list.length, 1, 'should have one item in queue')
|
|
293
|
-
}
|
|
294
|
-
}))
|
|
295
|
-
})
|
|
296
|
-
})
|
|
297
|
-
})
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
;[true, false].forEach(function (cleanSession) {
|
|
301
|
-
test(`unauthorized forward publish packets in QoS 2 [clean=${cleanSession}]`, function (t) {
|
|
302
|
-
t.plan(6)
|
|
221
|
+
await subscribe(t, subscriber, 'hello', 2)
|
|
303
222
|
|
|
304
|
-
|
|
305
|
-
|
|
223
|
+
await publish(t, publisher, {
|
|
224
|
+
cmd: 'publish',
|
|
225
|
+
topic: 'hello',
|
|
226
|
+
payload: Buffer.from('world'),
|
|
227
|
+
qos: 2,
|
|
228
|
+
retain: false,
|
|
229
|
+
messageId: 42,
|
|
230
|
+
dup: false
|
|
231
|
+
})
|
|
306
232
|
|
|
307
|
-
const
|
|
233
|
+
const packet = await nextPacket(subscriber)
|
|
234
|
+
t.assert.ok(packet.messageId !== 42, 'messageId must differ')
|
|
235
|
+
delete packet.messageId
|
|
236
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
|
|
237
|
+
|
|
238
|
+
const stream = broker.persistence.outgoingStream({ id: 'abcde' })
|
|
239
|
+
const list = await stream.toArray()
|
|
240
|
+
if (cleanSession) {
|
|
241
|
+
t.assert.equal(list.length, 0, 'should have empty item in queue')
|
|
242
|
+
} else {
|
|
243
|
+
t.assert.equal(list.length, 1, 'should have one item in queue')
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
}
|
|
308
247
|
|
|
309
|
-
|
|
310
|
-
|
|
248
|
+
for (const cleanSession of [true, false]) {
|
|
249
|
+
test(`unauthorized forward publish packets in QoS 2 [clean=${cleanSession}]`, async (t) => {
|
|
250
|
+
t.plan(7)
|
|
311
251
|
|
|
312
|
-
broker
|
|
252
|
+
const { broker, publisher, subscriber } = await createPubSub(t, {
|
|
253
|
+
publisher: { clientId: 'my-client-xyz-8' },
|
|
254
|
+
subscriber: { clean: cleanSession, clientId: 'abcde' }
|
|
255
|
+
})
|
|
313
256
|
|
|
314
|
-
}
|
|
257
|
+
broker.authorizeForward = (client, packet) => { }
|
|
315
258
|
|
|
316
|
-
subscribe(t, subscriber, 'hello', 2
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
qos: 2,
|
|
326
|
-
retain: false,
|
|
327
|
-
messageId: 42,
|
|
328
|
-
dup: false
|
|
329
|
-
}, function () {
|
|
330
|
-
const stream = broker.persistence.outgoingStream({ id: 'abcde' })
|
|
331
|
-
stream.pipe(concat(function (list) {
|
|
332
|
-
t.equal(list.length, 0, 'should empty in queue')
|
|
333
|
-
}))
|
|
334
|
-
})
|
|
259
|
+
await subscribe(t, subscriber, 'hello', 2)
|
|
260
|
+
await publish(t, publisher, {
|
|
261
|
+
cmd: 'publish',
|
|
262
|
+
topic: 'hello',
|
|
263
|
+
payload: Buffer.from('world'),
|
|
264
|
+
qos: 2,
|
|
265
|
+
retain: false,
|
|
266
|
+
messageId: 42,
|
|
267
|
+
dup: false
|
|
335
268
|
})
|
|
269
|
+
await checkNoPacket(t, subscriber, 10)
|
|
270
|
+
|
|
271
|
+
const stream = broker.persistence.outgoingStream({ id: 'abcde' })
|
|
272
|
+
const list = await stream.toArray()
|
|
273
|
+
t.assert.equal(list.length, 0, 'should empty in queue')
|
|
336
274
|
})
|
|
337
|
-
}
|
|
275
|
+
}
|
|
338
276
|
|
|
339
|
-
test('subscribe QoS 0, but publish QoS 2',
|
|
277
|
+
test('subscribe QoS 0, but publish QoS 2', async (t) => {
|
|
340
278
|
t.plan(6)
|
|
341
279
|
|
|
342
|
-
const
|
|
343
|
-
t.teardown(broker.close.bind(broker))
|
|
344
|
-
|
|
345
|
-
const publisher = connect(setup(broker))
|
|
346
|
-
const subscriber = connect(setup(broker))
|
|
280
|
+
const { publisher, subscriber } = await createPubSub(t)
|
|
347
281
|
const expected = {
|
|
348
282
|
cmd: 'publish',
|
|
349
283
|
topic: 'hello',
|
|
@@ -354,31 +288,26 @@ test('subscribe QoS 0, but publish QoS 2', function (t) {
|
|
|
354
288
|
retain: false
|
|
355
289
|
}
|
|
356
290
|
|
|
357
|
-
subscribe(t, subscriber, 'hello', 0
|
|
358
|
-
subscriber.outStream.once('data', function (packet) {
|
|
359
|
-
t.same(packet, expected, 'packet must match')
|
|
360
|
-
})
|
|
291
|
+
await subscribe(t, subscriber, 'hello', 0)
|
|
361
292
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
})
|
|
293
|
+
await publish(t, publisher, {
|
|
294
|
+
cmd: 'publish',
|
|
295
|
+
topic: 'hello',
|
|
296
|
+
payload: Buffer.from('world'),
|
|
297
|
+
qos: 2,
|
|
298
|
+
retain: false,
|
|
299
|
+
messageId: 42,
|
|
300
|
+
dup: false
|
|
371
301
|
})
|
|
302
|
+
|
|
303
|
+
const packet = await nextPacket(subscriber)
|
|
304
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
|
|
372
305
|
})
|
|
373
306
|
|
|
374
|
-
test('subscribe QoS 1, but publish QoS 2',
|
|
307
|
+
test('subscribe QoS 1, but publish QoS 2', async (t) => {
|
|
375
308
|
t.plan(6)
|
|
376
309
|
|
|
377
|
-
const
|
|
378
|
-
t.teardown(broker.close.bind(broker))
|
|
379
|
-
|
|
380
|
-
const publisher = connect(setup(broker))
|
|
381
|
-
const subscriber = connect(setup(broker))
|
|
310
|
+
const { publisher, subscriber } = await createPubSub(t)
|
|
382
311
|
const expected = {
|
|
383
312
|
cmd: 'publish',
|
|
384
313
|
topic: 'hello',
|
|
@@ -389,31 +318,31 @@ test('subscribe QoS 1, but publish QoS 2', function (t) {
|
|
|
389
318
|
retain: false
|
|
390
319
|
}
|
|
391
320
|
|
|
392
|
-
subscribe(t, subscriber, 'hello', 1
|
|
393
|
-
subscriber.outStream.once('data', function (packet) {
|
|
394
|
-
delete packet.messageId
|
|
395
|
-
t.same(packet, expected, 'packet must match')
|
|
396
|
-
})
|
|
321
|
+
await subscribe(t, subscriber, 'hello', 1)
|
|
397
322
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
})
|
|
323
|
+
await publish(t, publisher, {
|
|
324
|
+
cmd: 'publish',
|
|
325
|
+
topic: 'hello',
|
|
326
|
+
payload: Buffer.from('world'),
|
|
327
|
+
qos: 2,
|
|
328
|
+
retain: false,
|
|
329
|
+
messageId: 42,
|
|
330
|
+
dup: false
|
|
407
331
|
})
|
|
332
|
+
|
|
333
|
+
const packet = await nextPacket(subscriber)
|
|
334
|
+
delete packet.messageId
|
|
335
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
|
|
408
336
|
})
|
|
409
337
|
|
|
410
|
-
test('restore QoS 2 subscriptions not clean',
|
|
338
|
+
test('restore QoS 2 subscriptions not clean', async (t) => {
|
|
411
339
|
t.plan(9)
|
|
412
340
|
|
|
413
|
-
const
|
|
414
|
-
|
|
341
|
+
const opts = { clean: false, clientId: 'abcde' }
|
|
342
|
+
const { broker, publisher, subscriber } = await createPubSub(t, {
|
|
343
|
+
subscriber: opts
|
|
344
|
+
})
|
|
415
345
|
|
|
416
|
-
let subscriber = connect(setup(broker), { clean: false, clientId: 'abcde' })
|
|
417
346
|
const expected = {
|
|
418
347
|
cmd: 'publish',
|
|
419
348
|
topic: 'hello',
|
|
@@ -425,28 +354,25 @@ test('restore QoS 2 subscriptions not clean', function (t) {
|
|
|
425
354
|
retain: false
|
|
426
355
|
}
|
|
427
356
|
|
|
428
|
-
subscribe(t, subscriber, 'hello', 2
|
|
429
|
-
|
|
357
|
+
await subscribe(t, subscriber, 'hello', 2)
|
|
358
|
+
subscriber.inStream.end()
|
|
430
359
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
receive(t, subscriber, expected)
|
|
439
|
-
})
|
|
360
|
+
const subscriber2 = setup(broker)
|
|
361
|
+
const connack = await connect(subscriber2, { connect: opts })
|
|
362
|
+
t.assert.equal(connack.sessionPresent, true, 'session present is set to true')
|
|
363
|
+
// getting a connack does not mean that the client setup has completed in Aedes
|
|
364
|
+
await once(broker, 'clientReady')
|
|
365
|
+
await publish(t, publisher, expected)
|
|
366
|
+
await receive(t, subscriber2, expected)
|
|
440
367
|
})
|
|
441
368
|
|
|
442
|
-
test('resend publish on non-clean reconnect QoS 2',
|
|
369
|
+
test('resend publish on non-clean reconnect QoS 2', async (t) => {
|
|
443
370
|
t.plan(8)
|
|
444
371
|
|
|
445
|
-
const broker = aedes()
|
|
446
|
-
t.teardown(broker.close.bind(broker))
|
|
447
|
-
|
|
448
372
|
const opts = { clean: false, clientId: 'abcde' }
|
|
449
|
-
|
|
373
|
+
const { broker, publisher, subscriber } = await createPubSub(t, {
|
|
374
|
+
subscriber: opts
|
|
375
|
+
})
|
|
450
376
|
const expected = {
|
|
451
377
|
cmd: 'publish',
|
|
452
378
|
topic: 'hello',
|
|
@@ -458,27 +384,22 @@ test('resend publish on non-clean reconnect QoS 2', function (t) {
|
|
|
458
384
|
retain: false
|
|
459
385
|
}
|
|
460
386
|
|
|
461
|
-
subscribe(t, subscriber, 'hello', 2
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
const publisher = connect(setup(broker))
|
|
465
|
-
|
|
466
|
-
publish(t, publisher, expected, function () {
|
|
467
|
-
subscriber = connect(setup(broker), opts)
|
|
387
|
+
await subscribe(t, subscriber, 'hello', 2)
|
|
388
|
+
subscriber.inStream.end()
|
|
468
389
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
})
|
|
390
|
+
await publish(t, publisher, expected)
|
|
391
|
+
const subscriber2 = setup(broker)
|
|
392
|
+
await connect(subscriber2, { connect: opts })
|
|
393
|
+
await receive(t, subscriber2, expected)
|
|
472
394
|
})
|
|
473
395
|
|
|
474
|
-
test('resend pubrel on non-clean reconnect QoS 2',
|
|
396
|
+
test('resend pubrel on non-clean reconnect QoS 2', async (t) => {
|
|
475
397
|
t.plan(9)
|
|
476
398
|
|
|
477
|
-
const broker = aedes()
|
|
478
|
-
t.teardown(broker.close.bind(broker))
|
|
479
|
-
|
|
480
399
|
const opts = { clean: false, clientId: 'abcde' }
|
|
481
|
-
|
|
400
|
+
const { broker, publisher, subscriber } = await createPubSub(t, {
|
|
401
|
+
subscriber: opts
|
|
402
|
+
})
|
|
482
403
|
const expected = {
|
|
483
404
|
cmd: 'publish',
|
|
484
405
|
topic: 'hello',
|
|
@@ -490,70 +411,66 @@ test('resend pubrel on non-clean reconnect QoS 2', function (t) {
|
|
|
490
411
|
retain: false
|
|
491
412
|
}
|
|
492
413
|
|
|
493
|
-
subscribe(t, subscriber, 'hello', 2
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
})
|
|
545
|
-
})
|
|
414
|
+
await subscribe(t, subscriber, 'hello', 2)
|
|
415
|
+
subscriber.inStream.end()
|
|
416
|
+
|
|
417
|
+
await publish(t, publisher, expected)
|
|
418
|
+
|
|
419
|
+
const subscriber2 = setup(broker)
|
|
420
|
+
await connect(subscriber2, { connect: opts })
|
|
421
|
+
|
|
422
|
+
const packet = await nextPacket(subscriber2)
|
|
423
|
+
t.assert.ok(packet.messageId !== expected.messageId, 'messageId must differ')
|
|
424
|
+
const msgId = packet.messageId
|
|
425
|
+
delete packet.messageId
|
|
426
|
+
delete expected.messageId
|
|
427
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet must match')
|
|
428
|
+
|
|
429
|
+
subscriber2.inStream.write({
|
|
430
|
+
cmd: 'pubrec',
|
|
431
|
+
messageId: msgId
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
const pubRel = await nextPacket(subscriber2)
|
|
435
|
+
t.assert.deepEqual(structuredClone(pubRel), {
|
|
436
|
+
cmd: 'pubrel',
|
|
437
|
+
messageId: msgId,
|
|
438
|
+
length: 2,
|
|
439
|
+
qos: 1,
|
|
440
|
+
retain: false,
|
|
441
|
+
dup: false,
|
|
442
|
+
payload: null,
|
|
443
|
+
topic: null
|
|
444
|
+
}, 'pubrel must match')
|
|
445
|
+
|
|
446
|
+
subscriber2.inStream.end()
|
|
447
|
+
const subscriber3 = setup(broker)
|
|
448
|
+
await connect(subscriber3, { connect: opts })
|
|
449
|
+
|
|
450
|
+
const pubRel2 = await nextPacket(subscriber3)
|
|
451
|
+
t.assert.deepEqual(structuredClone(pubRel2), {
|
|
452
|
+
cmd: 'pubrel',
|
|
453
|
+
messageId: msgId,
|
|
454
|
+
length: 2,
|
|
455
|
+
qos: 1,
|
|
456
|
+
retain: false,
|
|
457
|
+
dup: false,
|
|
458
|
+
payload: null,
|
|
459
|
+
topic: null
|
|
460
|
+
}, 'pubrel must match')
|
|
461
|
+
|
|
462
|
+
subscriber3.inStream.write({
|
|
463
|
+
cmd: 'pubcomp',
|
|
464
|
+
messageId: msgId
|
|
546
465
|
})
|
|
547
466
|
})
|
|
548
467
|
|
|
549
|
-
test
|
|
468
|
+
// this test does the same as it did before conversion from Tap
|
|
469
|
+
// but it does not seem to do what the title says
|
|
470
|
+
test('publish after disconnection', async (t) => {
|
|
550
471
|
t.plan(10)
|
|
551
472
|
|
|
552
|
-
const
|
|
553
|
-
t.teardown(broker.close.bind(broker))
|
|
554
|
-
|
|
555
|
-
const publisher = connect(setup(broker))
|
|
556
|
-
const subscriber = connect(setup(broker))
|
|
473
|
+
const { publisher, subscriber } = await createPubSub(t)
|
|
557
474
|
const toPublish = {
|
|
558
475
|
cmd: 'publish',
|
|
559
476
|
topic: 'hello',
|
|
@@ -575,24 +492,20 @@ test('publish after disconnection', function (t) {
|
|
|
575
492
|
retain: false
|
|
576
493
|
}
|
|
577
494
|
|
|
578
|
-
subscribe(t, subscriber, 'hello', 2
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
publish(t, publisher, toPublish2)
|
|
583
|
-
})
|
|
584
|
-
})
|
|
495
|
+
await subscribe(t, subscriber, 'hello', 2)
|
|
496
|
+
await publish(t, publisher, toPublish)
|
|
497
|
+
await receive(t, subscriber, toPublish)
|
|
498
|
+
await publish(t, publisher, toPublish2)
|
|
585
499
|
})
|
|
586
500
|
|
|
587
|
-
test('multiple publish and store one',
|
|
588
|
-
t.plan(
|
|
589
|
-
|
|
590
|
-
const broker = aedes()
|
|
501
|
+
test('multiple publish and store one', async (t) => {
|
|
502
|
+
t.plan(1)
|
|
591
503
|
|
|
592
504
|
const sid = {
|
|
593
505
|
id: 'abcde'
|
|
594
506
|
}
|
|
595
|
-
const s =
|
|
507
|
+
const s = await createAndConnect(t, { connect: { clientId: sid.id } })
|
|
508
|
+
|
|
596
509
|
const toPublish = {
|
|
597
510
|
cmd: 'publish',
|
|
598
511
|
topic: 'hello',
|
|
@@ -606,37 +519,25 @@ test('multiple publish and store one', function (t) {
|
|
|
606
519
|
let count = 5
|
|
607
520
|
while (count--) {
|
|
608
521
|
s.inStream.write(toPublish)
|
|
522
|
+
await nextPacket(s)
|
|
609
523
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
broker.close(function () {
|
|
614
|
-
broker.persistence.incomingGetPacket(sid, toPublish, function (err, origPacket) {
|
|
615
|
-
delete origPacket.brokerId
|
|
616
|
-
delete origPacket.brokerCounter
|
|
617
|
-
t.same(origPacket, toPublish, 'packet must match')
|
|
618
|
-
t.error(err)
|
|
619
|
-
})
|
|
620
|
-
})
|
|
524
|
+
|
|
525
|
+
await new Promise((resolve) => {
|
|
526
|
+
s.broker.close(resolve)
|
|
621
527
|
})
|
|
528
|
+
const origPacket = await s.broker.persistence.incomingGetPacket(sid, toPublish)
|
|
529
|
+
delete origPacket.brokerId
|
|
530
|
+
delete origPacket.brokerCounter
|
|
531
|
+
t.assert.deepEqual(origPacket, toPublish, 'packet must match')
|
|
622
532
|
})
|
|
623
533
|
|
|
624
|
-
test('packet is written to stream after being stored',
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
const broker = s.broker
|
|
534
|
+
test('packet is written to stream after being stored', async (t) => {
|
|
535
|
+
t.plan(3)
|
|
628
536
|
|
|
629
|
-
t
|
|
537
|
+
const s = await createAndConnect(t)
|
|
538
|
+
const persistence = s.broker.persistence
|
|
630
539
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
const fn = broker.persistence.incomingStorePacket.bind(broker.persistence)
|
|
634
|
-
|
|
635
|
-
s.broker.persistence.incomingStorePacket = function (client, packet, done) {
|
|
636
|
-
packetStored = true
|
|
637
|
-
t.pass('packet stored')
|
|
638
|
-
fn(client, packet, done)
|
|
639
|
-
}
|
|
540
|
+
t.mock.method(persistence, 'incomingStorePacket')
|
|
640
541
|
|
|
641
542
|
const packet = {
|
|
642
543
|
cmd: 'publish',
|
|
@@ -646,30 +547,19 @@ test('packet is written to stream after being stored', function (t) {
|
|
|
646
547
|
messageId: 42
|
|
647
548
|
}
|
|
648
549
|
|
|
649
|
-
publish(t, s, packet)
|
|
650
|
-
|
|
651
|
-
s.outStream.once('data', function (packet) {
|
|
652
|
-
t.equal(packet.cmd, 'pubrec', 'pubrec received')
|
|
653
|
-
t.equal(packetStored, true, 'after packet store')
|
|
654
|
-
t.end()
|
|
655
|
-
})
|
|
550
|
+
await publish(t, s, packet)
|
|
551
|
+
t.assert.equal(persistence.incomingStorePacket.mock.callCount(), 1, 'after packet store')
|
|
656
552
|
})
|
|
657
553
|
|
|
658
|
-
test('not send pubrec when persistence fails to store packet',
|
|
659
|
-
t.plan(
|
|
660
|
-
|
|
661
|
-
const s = connect(setup())
|
|
662
|
-
const broker = s.broker
|
|
554
|
+
test('not send pubrec when persistence fails to store packet', async (t) => {
|
|
555
|
+
t.plan(3)
|
|
663
556
|
|
|
664
|
-
t
|
|
557
|
+
const s = await createAndConnect(t)
|
|
665
558
|
|
|
666
|
-
s.broker.persistence.incomingStorePacket =
|
|
667
|
-
t.
|
|
668
|
-
|
|
559
|
+
s.broker.persistence.incomingStorePacket = async () => {
|
|
560
|
+
t.assert.ok(true, 'packet stored')
|
|
561
|
+
throw new Error('store error')
|
|
669
562
|
}
|
|
670
|
-
s.broker.on('clientError', function (client, err) {
|
|
671
|
-
t.equal(err.message, 'store error')
|
|
672
|
-
})
|
|
673
563
|
|
|
674
564
|
const packet = {
|
|
675
565
|
cmd: 'publish',
|
|
@@ -680,7 +570,32 @@ test('not send pubrec when persistence fails to store packet', function (t) {
|
|
|
680
570
|
}
|
|
681
571
|
|
|
682
572
|
s.inStream.write(packet)
|
|
683
|
-
s.
|
|
684
|
-
|
|
685
|
-
|
|
573
|
+
const [client, err] = await once(s.broker, 'clientError')
|
|
574
|
+
t.assert.ok(client, 'client exists')
|
|
575
|
+
t.assert.equal(err.message, 'store error')
|
|
576
|
+
})
|
|
577
|
+
|
|
578
|
+
test('send pubcomp when receiving pubrel even if incomingDelPacket throws (no packet in store)', async (t) => {
|
|
579
|
+
t.plan(2)
|
|
580
|
+
|
|
581
|
+
const s = await createAndConnect(t)
|
|
582
|
+
|
|
583
|
+
// Mock incomingDelPacket to throw an error (simulating no packet in store)
|
|
584
|
+
s.broker.persistence.incomingDelPacket = async () => {
|
|
585
|
+
throw new Error('packet not found in store')
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Send a PUBREL packet directly
|
|
589
|
+
const pubrelPacket = {
|
|
590
|
+
cmd: 'pubrel',
|
|
591
|
+
messageId: 42,
|
|
592
|
+
dup: false,
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
s.inStream.write(pubrelPacket)
|
|
596
|
+
|
|
597
|
+
// Should receive a PUBCOMP response despite the error in incomingDelPacket
|
|
598
|
+
const pubcompPacket = await nextPacket(s)
|
|
599
|
+
t.assert.equal(pubcompPacket.cmd, 'pubcomp', 'should send pubcomp')
|
|
600
|
+
t.assert.equal(pubcompPacket.messageId, 42, 'messageId should match')
|
|
686
601
|
})
|