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.
- 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 -238
- 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 +54 -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 +134 -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 +174 -144
- 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/qos1.js
CHANGED
|
@@ -1,24 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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 =
|
|
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
|
-
|
|
33
|
-
|
|
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',
|
|
43
|
+
test('publish QoS 1 throws error', async (t) => {
|
|
38
44
|
t.plan(1)
|
|
39
45
|
|
|
40
|
-
const s =
|
|
41
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
46
|
+
const s = await createAndConnect(t)
|
|
42
47
|
|
|
43
|
-
s.broker.persistence.subscriptionsByTopic =
|
|
44
|
-
|
|
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
|
|
56
|
-
|
|
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',
|
|
61
|
-
t.plan(
|
|
64
|
+
test('publish QoS 1 throws error on write', async (t) => {
|
|
65
|
+
t.plan(2)
|
|
62
66
|
|
|
63
|
-
const
|
|
64
|
-
t.
|
|
67
|
+
const broker = await Aedes.createBroker()
|
|
68
|
+
t.after(() => broker.close())
|
|
69
|
+
const s = setup(broker)
|
|
65
70
|
|
|
66
|
-
s.broker.on('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
|
|
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
|
-
|
|
85
|
-
t.
|
|
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
|
-
|
|
88
|
-
t.
|
|
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
|
|
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
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
157
|
-
|
|
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
|
-
|
|
160
|
-
t.
|
|
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
|
-
|
|
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
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
223
|
-
|
|
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
|
-
|
|
226
|
-
t.
|
|
223
|
+
test('subscribe QoS 1', async (t) => {
|
|
224
|
+
t.plan(6)
|
|
227
225
|
|
|
228
|
-
const publisher =
|
|
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
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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',
|
|
262
|
-
t.plan(
|
|
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 =
|
|
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
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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',
|
|
283
|
+
test('restore QoS 1 subscriptions not clean', async (t) => {
|
|
295
284
|
t.plan(7)
|
|
296
285
|
|
|
297
|
-
const broker =
|
|
298
|
-
|
|
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
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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',
|
|
323
|
+
test('restore multiple QoS 1 subscriptions not clean w/ authorizeSubscribe', async (t) => {
|
|
344
324
|
t.plan(11)
|
|
345
325
|
|
|
346
|
-
const broker =
|
|
347
|
-
|
|
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
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
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
|
-
|
|
410
|
-
|
|
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
|
-
|
|
374
|
+
test('remove stored subscriptions if connected with clean=true', async (t) => {
|
|
375
|
+
t.plan(7)
|
|
413
376
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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
|
-
|
|
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
|
-
|
|
438
|
-
|
|
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
|
-
|
|
443
|
-
|
|
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',
|
|
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
|
-
|
|
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
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
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
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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',
|
|
514
|
-
t.plan(
|
|
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
|
-
|
|
525
|
-
|
|
526
|
-
|
|
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
|
|
536
|
-
|
|
478
|
+
await subscribe(t, subscriber, 'hello', 1)
|
|
479
|
+
subscriber.inStream.end()
|
|
537
480
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
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',
|
|
562
|
-
t.plan(
|
|
508
|
+
test('do not resend QoS 1 packets at each reconnect', async (t) => {
|
|
509
|
+
t.plan(7)
|
|
563
510
|
|
|
564
|
-
const
|
|
565
|
-
|
|
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
|
|
579
|
-
|
|
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
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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
|
-
|
|
617
|
-
|
|
537
|
+
const subscriber2 = setup(broker)
|
|
538
|
+
await connect(subscriber2, { connect: opts })
|
|
618
539
|
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
540
|
+
const packet = await nextPacket(subscriber2)
|
|
541
|
+
subscriber2.inStream.end({
|
|
542
|
+
cmd: 'puback',
|
|
543
|
+
messageId: packet.messageId
|
|
544
|
+
})
|
|
623
545
|
|
|
624
|
-
|
|
625
|
-
|
|
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
|
-
|
|
550
|
+
const subscriber3 = setup(broker)
|
|
551
|
+
await connect(subscriber3, { connect: opts })
|
|
552
|
+
await checkNoPacket(t, subscriber3, 10)
|
|
553
|
+
})
|
|
628
554
|
|
|
629
|
-
|
|
630
|
-
|
|
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
|
-
|
|
638
|
-
|
|
558
|
+
const { broker, publisher, subscriber } = await createPubSub(t, {
|
|
559
|
+
subscriber: { clean: false, clientId: 'abcde' }
|
|
560
|
+
})
|
|
639
561
|
|
|
640
|
-
|
|
562
|
+
await subscribe(t, subscriber, 'hello', 1)
|
|
563
|
+
subscriber.inStream.end()
|
|
641
564
|
|
|
642
|
-
|
|
643
|
-
|
|
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',
|
|
650
|
-
t.plan(
|
|
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 =
|
|
653
|
-
|
|
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
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
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
|
-
|
|
678
|
-
|
|
679
|
-
|
|
604
|
+
const packet = await nextPacket(subscriber)
|
|
605
|
+
subscriber.inStream.end({
|
|
606
|
+
cmd: 'puback',
|
|
607
|
+
messageId: packet.messageId
|
|
608
|
+
})
|
|
680
609
|
|
|
681
|
-
|
|
682
|
-
|
|
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
|
-
|
|
688
|
-
|
|
613
|
+
const subscriber2 = setup(broker)
|
|
614
|
+
await connect(subscriber2, { connect: { clean: false, clientId: 'abcde' } })
|
|
615
|
+
await checkNoPacket(t, subscriber2, 10)
|
|
616
|
+
})
|
|
689
617
|
|
|
690
|
-
|
|
618
|
+
test('remove stored subscriptions after unsubscribe', async (t) => {
|
|
619
|
+
t.plan(7)
|
|
691
620
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
})
|
|
695
|
-
})
|
|
621
|
+
const { broker, publisher, subscriber } = await createPubSub(t, {
|
|
622
|
+
subscriber: { clean: false, clientId: 'abcde' }
|
|
696
623
|
})
|
|
697
|
-
})
|
|
698
624
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
625
|
+
await subscribe(t, subscriber, 'hello', 1)
|
|
626
|
+
subscriber.inStream.write({
|
|
627
|
+
cmd: 'unsubscribe',
|
|
628
|
+
messageId: 43,
|
|
629
|
+
unsubscriptions: ['hello']
|
|
630
|
+
})
|
|
704
631
|
|
|
705
|
-
|
|
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
|
-
|
|
708
|
-
subscriber.inStream.write({
|
|
709
|
-
cmd: 'unsubscribe',
|
|
710
|
-
messageId: 43,
|
|
711
|
-
unsubscriptions: ['hello']
|
|
712
|
-
})
|
|
644
|
+
subscriber.inStream.end()
|
|
713
645
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
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
|
-
|
|
754
|
-
|
|
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',
|
|
671
|
+
test('upgrade a QoS 0 subscription to QoS 1', async (t) => {
|
|
761
672
|
t.plan(8)
|
|
762
673
|
|
|
763
|
-
const s =
|
|
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
|
|
777
|
-
|
|
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
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
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',
|
|
702
|
+
test('downgrade QoS 0 publish on QoS 1 subsciption', async (t) => {
|
|
795
703
|
t.plan(4)
|
|
796
704
|
|
|
797
|
-
const s =
|
|
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
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
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',
|
|
730
|
+
test('subscribe and publish QoS 1 in parallel', async (t) => {
|
|
824
731
|
t.plan(5)
|
|
825
732
|
|
|
826
|
-
const
|
|
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',
|
|
744
|
+
s.broker.on('clientError', (client, err) => {
|
|
841
745
|
console.log(err.stack)
|
|
842
|
-
|
|
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
|
})
|