aedes 0.51.3 → 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 -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 +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 +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/client-pub-sub.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { test } from 'node:test'
|
|
2
|
+
import { once } from 'node:events'
|
|
3
|
+
import {
|
|
4
|
+
connect,
|
|
5
|
+
createAndConnect,
|
|
6
|
+
nextPacket,
|
|
7
|
+
nextPacketWithTimeOut,
|
|
8
|
+
setup,
|
|
9
|
+
subscribe,
|
|
10
|
+
} from './helper.js'
|
|
11
|
+
|
|
12
|
+
test('publish direct to a single client QoS 0', async (t) => {
|
|
8
13
|
t.plan(2)
|
|
9
14
|
|
|
10
|
-
const
|
|
11
|
-
t.teardown(broker.close.bind(broker))
|
|
15
|
+
const s = await createAndConnect(t)
|
|
12
16
|
|
|
13
17
|
const expected = {
|
|
14
18
|
cmd: 'publish',
|
|
@@ -20,78 +24,67 @@ test('publish direct to a single client QoS 0', function (t) {
|
|
|
20
24
|
retain: false
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
client.publish({
|
|
27
|
+
await new Promise(resolve => {
|
|
28
|
+
s.client.publish({
|
|
25
29
|
topic: 'hello',
|
|
26
30
|
payload: Buffer.from('world'),
|
|
27
31
|
qos: 0
|
|
28
|
-
},
|
|
29
|
-
t.
|
|
32
|
+
}, (err) => {
|
|
33
|
+
t.assert.ok(!err, 'no error')
|
|
34
|
+
resolve()
|
|
30
35
|
})
|
|
31
36
|
})
|
|
32
37
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
s.outStream.once('data', function (packet) {
|
|
36
|
-
t.same(packet, expected, 'packet matches')
|
|
37
|
-
})
|
|
38
|
+
const packet = await nextPacket(s)
|
|
39
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
38
40
|
})
|
|
39
41
|
|
|
40
|
-
test('publish direct to a single client throws error',
|
|
42
|
+
test('publish direct to a single client throws error', async (t) => {
|
|
41
43
|
t.plan(1)
|
|
42
44
|
|
|
43
|
-
const
|
|
44
|
-
t.teardown(broker.close.bind(broker))
|
|
45
|
+
const s = await createAndConnect(t, { connect: { clean: false } })
|
|
45
46
|
|
|
46
|
-
broker.persistence.outgoingEnqueue =
|
|
47
|
-
|
|
47
|
+
s.broker.persistence.outgoingEnqueue = async () => {
|
|
48
|
+
throw new Error('Throws error')
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
client.publish({
|
|
51
|
+
await new Promise(resolve => {
|
|
52
|
+
s.client.publish({
|
|
52
53
|
topic: 'hello',
|
|
53
54
|
payload: Buffer.from('world'),
|
|
54
55
|
qos: 1,
|
|
55
56
|
retain: false
|
|
56
|
-
},
|
|
57
|
-
t.
|
|
57
|
+
}, (err) => {
|
|
58
|
+
t.assert.equal('Throws error', err.message, 'throws error')
|
|
59
|
+
resolve()
|
|
58
60
|
})
|
|
59
61
|
})
|
|
60
|
-
|
|
61
|
-
connect(setup(broker), { clean: false })
|
|
62
62
|
})
|
|
63
63
|
|
|
64
|
-
test('publish direct to a single client throws error 2',
|
|
64
|
+
test('publish direct to a single client throws error 2', async (t) => {
|
|
65
65
|
t.plan(1)
|
|
66
66
|
|
|
67
|
-
const
|
|
68
|
-
t.teardown(broker.close.bind(broker))
|
|
67
|
+
const s = await createAndConnect(t, { connect: { clean: false } })
|
|
69
68
|
|
|
70
|
-
broker.persistence.outgoingUpdate =
|
|
71
|
-
|
|
69
|
+
s.broker.persistence.outgoingUpdate = async () => {
|
|
70
|
+
throw new Error('Throws error')
|
|
72
71
|
}
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}, () => {})
|
|
81
|
-
|
|
82
|
-
client.once('error', function (err) {
|
|
83
|
-
t.pass('Throws error', err.message, 'throws error')
|
|
84
|
-
})
|
|
85
|
-
})
|
|
73
|
+
s.client.publish({
|
|
74
|
+
topic: 'hello',
|
|
75
|
+
payload: Buffer.from('world'),
|
|
76
|
+
qos: 1,
|
|
77
|
+
retain: false
|
|
78
|
+
}, () => { })
|
|
86
79
|
|
|
87
|
-
|
|
80
|
+
const [err] = await once(s.client, 'error')
|
|
81
|
+
t.assert.equal('Throws error', err.message, 'throws error')
|
|
88
82
|
})
|
|
89
83
|
|
|
90
|
-
test('publish direct to a single client QoS 1',
|
|
84
|
+
test('publish direct to a single client QoS 1', async (t) => {
|
|
91
85
|
t.plan(2)
|
|
92
86
|
|
|
93
|
-
const
|
|
94
|
-
t.teardown(broker.close.bind(broker))
|
|
87
|
+
const s = await createAndConnect(t)
|
|
95
88
|
|
|
96
89
|
const expected = {
|
|
97
90
|
cmd: 'publish',
|
|
@@ -103,116 +96,131 @@ test('publish direct to a single client QoS 1', function (t) {
|
|
|
103
96
|
retain: false
|
|
104
97
|
}
|
|
105
98
|
|
|
106
|
-
|
|
107
|
-
client.publish({
|
|
99
|
+
const publishPacket = new Promise(resolve => {
|
|
100
|
+
s.client.publish({
|
|
108
101
|
topic: 'hello',
|
|
109
102
|
payload: Buffer.from('world'),
|
|
110
103
|
qos: 1
|
|
111
|
-
},
|
|
112
|
-
t.
|
|
104
|
+
}, (err) => {
|
|
105
|
+
t.assert.ok(!err, 'no error')
|
|
106
|
+
resolve()
|
|
113
107
|
})
|
|
114
108
|
})
|
|
115
109
|
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
s.outStream.once('data', function (packet) {
|
|
110
|
+
const processPacket = async () => {
|
|
111
|
+
const packet = await nextPacket(s)
|
|
119
112
|
expected.messageId = packet.messageId
|
|
120
|
-
t.
|
|
113
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
121
114
|
s.inStream.write({
|
|
122
115
|
cmd: 'puback',
|
|
123
116
|
messageId: packet.messageId
|
|
124
117
|
})
|
|
125
|
-
}
|
|
126
|
-
})
|
|
118
|
+
}
|
|
127
119
|
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
// run parallel
|
|
121
|
+
await Promise.all([
|
|
122
|
+
publishPacket,
|
|
123
|
+
processPacket()
|
|
124
|
+
])
|
|
125
|
+
})
|
|
130
126
|
|
|
131
|
-
|
|
132
|
-
t.
|
|
127
|
+
test('publish QoS 2 throws error in pubrel', async (t) => {
|
|
128
|
+
t.plan(3)
|
|
133
129
|
|
|
134
|
-
const s =
|
|
130
|
+
const s = await createAndConnect(t)
|
|
135
131
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
132
|
+
const clientError = async () => {
|
|
133
|
+
once(s.broker, 'clientError')
|
|
134
|
+
t.assert.ok(true, 'throws error')
|
|
135
|
+
}
|
|
139
136
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
137
|
+
const processPacket = async () => {
|
|
138
|
+
const packet = await nextPacket(s)
|
|
139
|
+
t.assert.equal(packet.cmd, 'publish', 'publish packet')
|
|
140
|
+
s.inStream.write({
|
|
141
|
+
cmd: 'pubrec',
|
|
142
|
+
messageId: packet.messageId
|
|
143
|
+
})
|
|
144
|
+
s.broker.persistence.outgoingUpdate = async () => {
|
|
145
|
+
throw new Error('error')
|
|
149
146
|
}
|
|
150
|
-
}
|
|
147
|
+
}
|
|
151
148
|
|
|
152
|
-
|
|
153
|
-
client.publish({
|
|
149
|
+
const publishPacket = new Promise(resolve => {
|
|
150
|
+
s.client.publish({
|
|
154
151
|
topic: 'hello',
|
|
155
152
|
payload: Buffer.from('world'),
|
|
156
153
|
qos: 2
|
|
157
|
-
},
|
|
158
|
-
t.
|
|
154
|
+
}, (err) => {
|
|
155
|
+
t.assert.ok(!err, 'no error')
|
|
156
|
+
resolve()
|
|
159
157
|
})
|
|
160
158
|
})
|
|
159
|
+
// run parallel
|
|
160
|
+
await Promise.all([
|
|
161
|
+
clientError(),
|
|
162
|
+
processPacket(),
|
|
163
|
+
publishPacket,
|
|
164
|
+
])
|
|
161
165
|
})
|
|
162
166
|
|
|
163
|
-
test('publish direct to a single client QoS 2',
|
|
164
|
-
t.plan(
|
|
167
|
+
test('publish direct to a single client QoS 2', async (t) => {
|
|
168
|
+
t.plan(5)
|
|
165
169
|
|
|
166
|
-
const
|
|
167
|
-
t.teardown(broker.close.bind(broker))
|
|
170
|
+
const s = await createAndConnect(t)
|
|
168
171
|
|
|
169
172
|
let publishCount = 0
|
|
170
173
|
let nonPublishCount = 0
|
|
171
174
|
|
|
172
|
-
|
|
173
|
-
client.publish({
|
|
175
|
+
const publishPacket = new Promise(resolve => {
|
|
176
|
+
s.client.publish({
|
|
174
177
|
topic: 'hello',
|
|
175
178
|
payload: Buffer.from('world'),
|
|
176
179
|
qos: 2
|
|
177
|
-
},
|
|
178
|
-
t.
|
|
180
|
+
}, (err) => {
|
|
181
|
+
t.assert.ok(!err, 'no error')
|
|
182
|
+
resolve()
|
|
179
183
|
})
|
|
180
|
-
client.on('error',
|
|
181
|
-
t.
|
|
184
|
+
s.client.on('error', (err) => {
|
|
185
|
+
t.assert.fail(err)
|
|
182
186
|
})
|
|
183
187
|
})
|
|
184
188
|
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
t.equal(
|
|
189
|
-
|
|
190
|
-
})
|
|
189
|
+
const checkOnClose = async () => {
|
|
190
|
+
await once(s.inStream, 'close')
|
|
191
|
+
t.assert.equal(publishCount, 1)
|
|
192
|
+
t.assert.equal(nonPublishCount, 1)
|
|
193
|
+
}
|
|
191
194
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
195
|
+
const processPacket = async () => {
|
|
196
|
+
const packet1 = await nextPacket(s)
|
|
197
|
+
t.assert.equal(packet1.cmd, 'publish', 'publish packet')
|
|
198
|
+
publishCount++
|
|
199
|
+
s.inStream.write({
|
|
200
|
+
cmd: 'pubrec',
|
|
201
|
+
messageId: packet1.messageId
|
|
202
|
+
})
|
|
203
|
+
const packet2 = await nextPacket(s)
|
|
204
|
+
t.assert.equal(packet2.cmd, 'pubrel', 'pubrel packet')
|
|
205
|
+
nonPublishCount++
|
|
206
|
+
s.inStream.write({
|
|
207
|
+
cmd: 'pubcomp',
|
|
208
|
+
messageId: packet2.messageId
|
|
209
|
+
})
|
|
210
|
+
s.inStream.destroy()
|
|
211
|
+
}
|
|
212
|
+
// run parallel
|
|
213
|
+
await Promise.all([
|
|
214
|
+
checkOnClose(),
|
|
215
|
+
processPacket(),
|
|
216
|
+
publishPacket,
|
|
217
|
+
])
|
|
208
218
|
})
|
|
209
219
|
|
|
210
|
-
test('emit a `ack` event on PUBACK for QoS 1 [clean=false]',
|
|
211
|
-
t.plan(
|
|
212
|
-
|
|
213
|
-
const broker = aedes()
|
|
214
|
-
t.teardown(broker.close.bind(broker))
|
|
220
|
+
test('emit a `ack` event on PUBACK for QoS 1 [clean=false]', async (t) => {
|
|
221
|
+
t.plan(4)
|
|
215
222
|
|
|
223
|
+
const s = await createAndConnect(t, { connect: { clean: false } })
|
|
216
224
|
const expected = {
|
|
217
225
|
cmd: 'publish',
|
|
218
226
|
topic: 'hello',
|
|
@@ -222,153 +230,187 @@ test('emit a `ack` event on PUBACK for QoS 1 [clean=false]', function (t) {
|
|
|
222
230
|
dup: false
|
|
223
231
|
}
|
|
224
232
|
|
|
225
|
-
|
|
226
|
-
client.publish({
|
|
233
|
+
const publishPacket = new Promise(resolve => {
|
|
234
|
+
s.client.publish({
|
|
227
235
|
topic: 'hello',
|
|
228
236
|
payload: Buffer.from('world'),
|
|
229
237
|
qos: 1
|
|
230
|
-
},
|
|
231
|
-
t.
|
|
238
|
+
}, (err) => {
|
|
239
|
+
t.assert.ok(!err, 'no error')
|
|
240
|
+
resolve()
|
|
232
241
|
})
|
|
233
242
|
})
|
|
234
243
|
|
|
235
|
-
|
|
244
|
+
const brokerAck = async () => {
|
|
245
|
+
const [packet] = await once(s.broker, 'ack')
|
|
236
246
|
expected.brokerId = packet.brokerId
|
|
237
247
|
expected.brokerCounter = packet.brokerCounter
|
|
238
248
|
expected.messageId = packet.messageId
|
|
239
|
-
t.
|
|
240
|
-
t.
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const s = connect(setup(broker), { clean: false })
|
|
249
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'ack packet is original packet')
|
|
250
|
+
t.assert.ok(true, 'got the ack event')
|
|
251
|
+
}
|
|
244
252
|
|
|
245
|
-
|
|
253
|
+
const processPacket = async () => {
|
|
254
|
+
const packet = await nextPacket(s)
|
|
255
|
+
t.assert.equal(packet.cmd, 'publish', 'publish packet')
|
|
246
256
|
s.inStream.write({
|
|
247
257
|
cmd: 'puback',
|
|
248
258
|
messageId: packet.messageId
|
|
249
259
|
})
|
|
250
|
-
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// run parallel
|
|
263
|
+
await Promise.all([
|
|
264
|
+
brokerAck(),
|
|
265
|
+
processPacket(),
|
|
266
|
+
publishPacket,
|
|
267
|
+
])
|
|
251
268
|
})
|
|
252
269
|
|
|
253
|
-
test('emit a `ack` event on PUBACK for QoS 1 [clean=true]',
|
|
254
|
-
t.plan(
|
|
270
|
+
test('emit a `ack` event on PUBACK for QoS 1 [clean=true]', async (t) => {
|
|
271
|
+
t.plan(4)
|
|
255
272
|
|
|
256
|
-
const
|
|
257
|
-
t.teardown(broker.close.bind(broker))
|
|
273
|
+
const s = await createAndConnect(t, { connect: { clean: true } })
|
|
258
274
|
|
|
259
|
-
|
|
260
|
-
client.publish({
|
|
275
|
+
const publishPacket = new Promise(resolve => {
|
|
276
|
+
s.client.publish({
|
|
261
277
|
topic: 'hello',
|
|
262
278
|
payload: Buffer.from('world'),
|
|
263
279
|
qos: 1
|
|
264
|
-
},
|
|
265
|
-
t.
|
|
280
|
+
}, (err) => {
|
|
281
|
+
t.assert.ok(!err, 'no error')
|
|
282
|
+
resolve()
|
|
266
283
|
})
|
|
267
284
|
})
|
|
268
285
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
t.
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const s = connect(setup(broker), { clean: true })
|
|
286
|
+
const brokerAck = async () => {
|
|
287
|
+
const [packet] = await once(s.broker, 'ack')
|
|
288
|
+
t.assert.equal(packet, undefined, 'ack packet is undefined')
|
|
289
|
+
t.assert.ok(true, 'got the ack event')
|
|
290
|
+
}
|
|
275
291
|
|
|
276
|
-
|
|
292
|
+
const processPacket = async () => {
|
|
293
|
+
const packet = await nextPacket(s)
|
|
294
|
+
t.assert.equal(packet.cmd, 'publish', 'publish packet')
|
|
277
295
|
s.inStream.write({
|
|
278
296
|
cmd: 'puback',
|
|
279
297
|
messageId: packet.messageId
|
|
280
298
|
})
|
|
281
|
-
}
|
|
299
|
+
}
|
|
300
|
+
// run parallel
|
|
301
|
+
await Promise.all([
|
|
302
|
+
brokerAck(),
|
|
303
|
+
processPacket(),
|
|
304
|
+
publishPacket,
|
|
305
|
+
])
|
|
282
306
|
})
|
|
283
307
|
|
|
284
|
-
test('emit a `ack` event on PUBCOMP for QoS 2 [clean=false]',
|
|
285
|
-
t.plan(
|
|
308
|
+
test('emit a `ack` event on PUBCOMP for QoS 2 [clean=false]', async (t) => {
|
|
309
|
+
t.plan(7)
|
|
286
310
|
|
|
287
|
-
const
|
|
288
|
-
t.teardown(broker.close.bind(broker))
|
|
311
|
+
const s = await createAndConnect(t, { connect: { clean: false } })
|
|
289
312
|
|
|
290
313
|
let messageId
|
|
291
314
|
let clientId
|
|
292
315
|
|
|
293
|
-
|
|
294
|
-
clientId = client.id
|
|
295
|
-
client.publish({
|
|
316
|
+
const publishPacket = new Promise(resolve => {
|
|
317
|
+
clientId = s.client.id
|
|
318
|
+
s.client.publish({
|
|
296
319
|
topic: 'hello',
|
|
297
320
|
payload: Buffer.from('world'),
|
|
298
321
|
qos: 2
|
|
299
|
-
},
|
|
300
|
-
t.
|
|
322
|
+
}, (err) => {
|
|
323
|
+
t.assert.ok(!err, 'no error')
|
|
324
|
+
resolve()
|
|
301
325
|
})
|
|
302
326
|
})
|
|
303
327
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
t.equal(
|
|
307
|
-
t.equal(packet.
|
|
308
|
-
t.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const s = connect(setup(broker), { clean: false })
|
|
328
|
+
const brokerAck = async () => {
|
|
329
|
+
const [packet, client] = await once(s.broker, 'ack')
|
|
330
|
+
t.assert.equal(client.id, clientId)
|
|
331
|
+
t.assert.equal(packet.messageId, messageId)
|
|
332
|
+
t.assert.equal(packet.cmd, 'pubrel', 'ack packet is pubrel')
|
|
333
|
+
t.assert.ok(true, 'got the ack event')
|
|
334
|
+
}
|
|
312
335
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
336
|
+
const processPacket = async () => {
|
|
337
|
+
const packet1 = await nextPacket(s)
|
|
338
|
+
t.assert.equal(packet1.cmd, 'publish', 'publish packet')
|
|
339
|
+
s.inStream.write({
|
|
340
|
+
cmd: 'pubrec',
|
|
341
|
+
messageId: packet1.messageId
|
|
342
|
+
})
|
|
343
|
+
const packet2 = await nextPacket(s)
|
|
344
|
+
t.assert.equal(packet2.cmd, 'pubrel', 'pubrel packet')
|
|
345
|
+
messageId = packet2.messageId
|
|
346
|
+
s.inStream.write({
|
|
347
|
+
cmd: 'pubcomp',
|
|
348
|
+
messageId: packet2.messageId
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
// run parallel
|
|
352
|
+
await Promise.all([
|
|
353
|
+
brokerAck(),
|
|
354
|
+
processPacket(),
|
|
355
|
+
publishPacket,
|
|
356
|
+
])
|
|
327
357
|
})
|
|
328
358
|
|
|
329
|
-
test('emit a `ack` event on PUBCOMP for QoS 2 [clean=true]',
|
|
330
|
-
t.plan(
|
|
359
|
+
test('emit a `ack` event on PUBCOMP for QoS 2 [clean=true]', async (t) => {
|
|
360
|
+
t.plan(6)
|
|
331
361
|
|
|
332
|
-
const
|
|
333
|
-
t.teardown(broker.close.bind(broker))
|
|
362
|
+
const s = await createAndConnect(t, { connect: { clean: true } })
|
|
334
363
|
|
|
335
|
-
|
|
336
|
-
client.publish({
|
|
364
|
+
const publishPacket = new Promise(resolve => {
|
|
365
|
+
s.client.publish({
|
|
337
366
|
topic: 'hello',
|
|
338
367
|
payload: Buffer.from('world'),
|
|
339
368
|
qos: 2
|
|
340
|
-
},
|
|
341
|
-
t.
|
|
369
|
+
}, (err) => {
|
|
370
|
+
t.assert.ok(!err, 'no error')
|
|
371
|
+
resolve()
|
|
342
372
|
})
|
|
343
373
|
})
|
|
344
374
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
t.
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
375
|
+
const brokerAck = async () => {
|
|
376
|
+
const [packet, client] = await once(s.broker, 'ack')
|
|
377
|
+
t.assert.ok(client, 'client is defined')
|
|
378
|
+
t.assert.equal(packet, undefined, 'ack packet is undefined')
|
|
379
|
+
t.assert.ok(true, 'got the ack event')
|
|
380
|
+
}
|
|
351
381
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
382
|
+
const processPacket = async () => {
|
|
383
|
+
const packet1 = await nextPacket(s)
|
|
384
|
+
t.assert.equal(packet1.cmd, 'publish', 'publish packet')
|
|
385
|
+
s.inStream.write({
|
|
386
|
+
cmd: 'pubrec',
|
|
387
|
+
messageId: packet1.messageId
|
|
388
|
+
})
|
|
389
|
+
const packet2 = await nextPacket(s)
|
|
390
|
+
t.assert.equal(packet2.cmd, 'pubrel', 'pubrel packet')
|
|
391
|
+
s.inStream.write({
|
|
392
|
+
cmd: 'pubcomp',
|
|
393
|
+
messageId: packet2.messageId
|
|
394
|
+
})
|
|
395
|
+
}
|
|
396
|
+
// run parallel
|
|
397
|
+
await Promise.all([
|
|
398
|
+
brokerAck(),
|
|
399
|
+
processPacket(),
|
|
400
|
+
publishPacket,
|
|
401
|
+
])
|
|
365
402
|
})
|
|
366
403
|
|
|
367
|
-
test('offline message support for direct publish',
|
|
404
|
+
test('offline message support for direct publish', async (t) => {
|
|
368
405
|
t.plan(2)
|
|
369
406
|
|
|
370
|
-
const
|
|
371
|
-
|
|
407
|
+
const opts = {
|
|
408
|
+
connect: {
|
|
409
|
+
clean: false,
|
|
410
|
+
clientId: 'abcde'
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
const s1 = await createAndConnect(t, opts)
|
|
372
414
|
|
|
373
415
|
const expected = {
|
|
374
416
|
cmd: 'publish',
|
|
@@ -379,43 +421,42 @@ test('offline message support for direct publish', function (t) {
|
|
|
379
421
|
qos: 1,
|
|
380
422
|
retain: false
|
|
381
423
|
}
|
|
382
|
-
const opts = {
|
|
383
|
-
clean: false,
|
|
384
|
-
clientId: 'abcde'
|
|
385
|
-
}
|
|
386
424
|
|
|
387
|
-
|
|
388
|
-
client.publish({
|
|
425
|
+
const publishPacket = new Promise(resolve => {
|
|
426
|
+
s1.client.publish({
|
|
389
427
|
topic: 'hello',
|
|
390
428
|
payload: Buffer.from('world'),
|
|
391
429
|
qos: 1
|
|
392
|
-
},
|
|
393
|
-
t.
|
|
430
|
+
}, (err) => {
|
|
431
|
+
t.assert.ok(!err, 'no error')
|
|
432
|
+
resolve()
|
|
394
433
|
})
|
|
395
434
|
})
|
|
396
435
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
cmd: 'puback',
|
|
406
|
-
messageId: packet.messageId
|
|
407
|
-
})
|
|
408
|
-
delete packet.messageId
|
|
409
|
-
t.same(packet, expected, 'packet must match')
|
|
436
|
+
const processPacket = async () => {
|
|
437
|
+
const packet1 = await nextPacket(s1)
|
|
438
|
+
// create a new subscriber, this will disconnect s1
|
|
439
|
+
const s2 = setup(s1.broker)
|
|
440
|
+
await connect(s2, opts)
|
|
441
|
+
s2.inStream.write({
|
|
442
|
+
cmd: 'puback',
|
|
443
|
+
messageId: packet1.messageId
|
|
410
444
|
})
|
|
411
|
-
|
|
445
|
+
const packet2 = await nextPacket(s2)
|
|
446
|
+
delete packet2.messageId
|
|
447
|
+
t.assert.deepEqual(structuredClone(packet2), expected, 'packet must match')
|
|
448
|
+
}
|
|
449
|
+
// run parallel
|
|
450
|
+
await Promise.all([
|
|
451
|
+
processPacket(),
|
|
452
|
+
publishPacket,
|
|
453
|
+
])
|
|
412
454
|
})
|
|
413
455
|
|
|
414
|
-
test('subscribe a client programmatically',
|
|
456
|
+
test('subscribe a client programmatically', async (t) => {
|
|
415
457
|
t.plan(3)
|
|
416
458
|
|
|
417
|
-
const
|
|
418
|
-
t.teardown(broker.close.bind(broker))
|
|
459
|
+
const s = await createAndConnect(t)
|
|
419
460
|
|
|
420
461
|
const expected = {
|
|
421
462
|
cmd: 'publish',
|
|
@@ -427,35 +468,31 @@ test('subscribe a client programmatically', function (t) {
|
|
|
427
468
|
retain: false
|
|
428
469
|
}
|
|
429
470
|
|
|
430
|
-
|
|
431
|
-
client.subscribe({
|
|
471
|
+
await new Promise(resolve => {
|
|
472
|
+
s.client.subscribe({
|
|
432
473
|
topic: 'hello',
|
|
433
474
|
qos: 0
|
|
434
|
-
},
|
|
435
|
-
t.
|
|
436
|
-
|
|
437
|
-
broker.publish({
|
|
475
|
+
}, (err) => {
|
|
476
|
+
t.assert.ok(!err, 'no error')
|
|
477
|
+
s.broker.publish({
|
|
438
478
|
topic: 'hello',
|
|
439
479
|
payload: Buffer.from('world'),
|
|
440
480
|
qos: 0
|
|
441
|
-
},
|
|
442
|
-
t.
|
|
481
|
+
}, (err) => {
|
|
482
|
+
t.assert.ok(!err, 'no error')
|
|
483
|
+
resolve()
|
|
443
484
|
})
|
|
444
485
|
})
|
|
445
486
|
})
|
|
446
487
|
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
s.outStream.once('data', function (packet) {
|
|
450
|
-
t.same(packet, expected, 'packet matches')
|
|
451
|
-
})
|
|
488
|
+
const packet = await nextPacket(s)
|
|
489
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
452
490
|
})
|
|
453
491
|
|
|
454
|
-
test('subscribe a client programmatically clears retain',
|
|
492
|
+
test('subscribe a client programmatically clears retain', async (t) => {
|
|
455
493
|
t.plan(3)
|
|
456
494
|
|
|
457
|
-
const
|
|
458
|
-
t.teardown(broker.close.bind(broker))
|
|
495
|
+
const s = await createAndConnect(t)
|
|
459
496
|
|
|
460
497
|
const expected = {
|
|
461
498
|
cmd: 'publish',
|
|
@@ -467,36 +504,46 @@ test('subscribe a client programmatically clears retain', function (t) {
|
|
|
467
504
|
retain: false
|
|
468
505
|
}
|
|
469
506
|
|
|
470
|
-
|
|
471
|
-
client.subscribe({
|
|
507
|
+
await new Promise(resolve => {
|
|
508
|
+
s.client.subscribe({
|
|
472
509
|
topic: 'hello',
|
|
473
510
|
qos: 0
|
|
474
|
-
},
|
|
475
|
-
t.
|
|
511
|
+
}, (err) => {
|
|
512
|
+
t.assert.ok(!err, 'no error')
|
|
476
513
|
|
|
477
|
-
broker.publish({
|
|
514
|
+
s.broker.publish({
|
|
478
515
|
topic: 'hello',
|
|
479
516
|
payload: Buffer.from('world'),
|
|
480
517
|
qos: 0,
|
|
481
518
|
retain: true
|
|
482
|
-
},
|
|
483
|
-
t.
|
|
519
|
+
}, (err) => {
|
|
520
|
+
t.assert.ok(!err, 'no error')
|
|
521
|
+
resolve()
|
|
484
522
|
})
|
|
485
523
|
})
|
|
486
524
|
})
|
|
487
525
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
526
|
+
// two packets are streamed
|
|
527
|
+
// - one with retain === true
|
|
528
|
+
// - one with retain === false
|
|
529
|
+
// the order varies depending on timing so we
|
|
530
|
+
// need to be able to handle both scenarios
|
|
531
|
+
|
|
532
|
+
for await (const packet of s.outStream) {
|
|
533
|
+
if (packet.retain === false) {
|
|
534
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
535
|
+
s.inStream.end({
|
|
536
|
+
cmd: 'disconnect'
|
|
537
|
+
})
|
|
538
|
+
break
|
|
539
|
+
}
|
|
540
|
+
}
|
|
493
541
|
})
|
|
494
542
|
|
|
495
|
-
test('subscribe a bridge programmatically keeps retain',
|
|
543
|
+
test('subscribe a bridge programmatically keeps retain', async (t) => {
|
|
496
544
|
t.plan(3)
|
|
497
545
|
|
|
498
|
-
const
|
|
499
|
-
t.teardown(broker.close.bind(broker))
|
|
546
|
+
const s = await createAndConnect(t)
|
|
500
547
|
|
|
501
548
|
const expected = {
|
|
502
549
|
cmd: 'publish',
|
|
@@ -508,71 +555,68 @@ test('subscribe a bridge programmatically keeps retain', function (t) {
|
|
|
508
555
|
retain: true
|
|
509
556
|
}
|
|
510
557
|
|
|
511
|
-
|
|
512
|
-
client.subscribe({
|
|
558
|
+
await new Promise(resolve => {
|
|
559
|
+
s.client.subscribe({
|
|
513
560
|
topic: 'hello',
|
|
514
561
|
qos: 0,
|
|
515
562
|
rap: true
|
|
516
|
-
},
|
|
517
|
-
t.
|
|
563
|
+
}, (err) => {
|
|
564
|
+
t.assert.ok(!err, 'no error')
|
|
518
565
|
|
|
519
|
-
broker.publish({
|
|
566
|
+
s.broker.publish({
|
|
520
567
|
topic: 'hello',
|
|
521
568
|
payload: Buffer.from('world'),
|
|
522
569
|
qos: 0,
|
|
523
570
|
retain: true
|
|
524
|
-
},
|
|
525
|
-
t.
|
|
571
|
+
}, (err) => {
|
|
572
|
+
t.assert.ok(!err, 'no error')
|
|
573
|
+
resolve()
|
|
526
574
|
})
|
|
527
575
|
})
|
|
528
576
|
})
|
|
529
577
|
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
})
|
|
578
|
+
const packet = await nextPacket(s)
|
|
579
|
+
if (packet.retain === true) {
|
|
580
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
581
|
+
}
|
|
535
582
|
})
|
|
536
583
|
|
|
537
|
-
test('subscribe throws error when QoS > 0',
|
|
584
|
+
test('subscribe throws error when QoS > 0', async (t) => {
|
|
538
585
|
t.plan(3)
|
|
539
586
|
|
|
540
|
-
const
|
|
541
|
-
t.teardown(broker.close.bind(broker))
|
|
587
|
+
const s = await createAndConnect(t)
|
|
542
588
|
|
|
543
|
-
|
|
544
|
-
client.subscribe({
|
|
589
|
+
await new Promise(resolve => {
|
|
590
|
+
s.client.subscribe({
|
|
545
591
|
topic: 'hello',
|
|
546
592
|
qos: 1
|
|
547
|
-
},
|
|
548
|
-
t.
|
|
593
|
+
}, (err) => {
|
|
594
|
+
t.assert.ok(!err, 'no error')
|
|
549
595
|
|
|
550
596
|
// makes writeQos throw error
|
|
551
|
-
client.connected = false
|
|
552
|
-
client.connecting = false
|
|
597
|
+
s.client.connected = false
|
|
598
|
+
s.client.connecting = false
|
|
553
599
|
|
|
554
|
-
broker.publish({
|
|
600
|
+
s.broker.publish({
|
|
555
601
|
topic: 'hello',
|
|
556
602
|
payload: Buffer.from('world'),
|
|
557
603
|
qos: 1
|
|
558
|
-
},
|
|
559
|
-
t.
|
|
604
|
+
}, (err) => {
|
|
605
|
+
t.assert.ok(!err, 'no error')
|
|
560
606
|
})
|
|
561
607
|
})
|
|
562
|
-
})
|
|
563
608
|
|
|
564
|
-
|
|
565
|
-
|
|
609
|
+
s.broker.on('clientError', (client, error) => {
|
|
610
|
+
t.assert.equal(error.message, 'connection closed', 'should throw clientError')
|
|
611
|
+
resolve()
|
|
612
|
+
})
|
|
566
613
|
})
|
|
567
|
-
|
|
568
|
-
connect(setup(broker))
|
|
569
614
|
})
|
|
570
615
|
|
|
571
|
-
test('subscribe a client programmatically - wildcard',
|
|
616
|
+
test('subscribe a client programmatically - wildcard', async (t) => {
|
|
572
617
|
t.plan(3)
|
|
573
618
|
|
|
574
|
-
const
|
|
575
|
-
t.teardown(broker.close.bind(broker))
|
|
619
|
+
const s = await createAndConnect(t)
|
|
576
620
|
|
|
577
621
|
const expected = {
|
|
578
622
|
cmd: 'publish',
|
|
@@ -584,143 +628,136 @@ test('subscribe a client programmatically - wildcard', function (t) {
|
|
|
584
628
|
retain: false
|
|
585
629
|
}
|
|
586
630
|
|
|
587
|
-
|
|
588
|
-
client.subscribe({
|
|
631
|
+
await new Promise(resolve => {
|
|
632
|
+
s.client.subscribe({
|
|
589
633
|
topic: '+/world/1',
|
|
590
634
|
qos: 0
|
|
591
|
-
},
|
|
592
|
-
t.
|
|
635
|
+
}, (err) => {
|
|
636
|
+
t.assert.ok(!err, 'no error')
|
|
593
637
|
|
|
594
|
-
broker.publish({
|
|
638
|
+
s.broker.publish({
|
|
595
639
|
topic: 'hello/world/1',
|
|
596
640
|
payload: Buffer.from('world'),
|
|
597
641
|
qos: 0
|
|
598
|
-
},
|
|
599
|
-
t.
|
|
642
|
+
}, (err) => {
|
|
643
|
+
t.assert.ok(!err, 'no error')
|
|
644
|
+
resolve()
|
|
600
645
|
})
|
|
601
646
|
})
|
|
602
647
|
})
|
|
603
648
|
|
|
604
|
-
const
|
|
605
|
-
|
|
606
|
-
s.outStream.once('data', function (packet) {
|
|
607
|
-
t.same(packet, expected, 'packet matches')
|
|
608
|
-
})
|
|
649
|
+
const packet = await nextPacket(s)
|
|
650
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
609
651
|
})
|
|
610
652
|
|
|
611
|
-
test('unsubscribe a client',
|
|
653
|
+
test('unsubscribe a client', async (t) => {
|
|
612
654
|
t.plan(2)
|
|
613
655
|
|
|
614
|
-
const
|
|
615
|
-
t.teardown(broker.close.bind(broker))
|
|
656
|
+
const s = await createAndConnect(t)
|
|
616
657
|
|
|
617
|
-
|
|
618
|
-
client.subscribe({
|
|
658
|
+
await new Promise(resolve => {
|
|
659
|
+
s.client.subscribe({
|
|
619
660
|
topic: 'hello',
|
|
620
661
|
qos: 0
|
|
621
|
-
},
|
|
622
|
-
t.
|
|
623
|
-
client.unsubscribe([{
|
|
662
|
+
}, (err) => {
|
|
663
|
+
t.assert.ok(!err, 'no error')
|
|
664
|
+
s.client.unsubscribe([{
|
|
624
665
|
topic: 'hello',
|
|
625
666
|
qos: 0
|
|
626
|
-
}],
|
|
627
|
-
t.
|
|
667
|
+
}], (err) => {
|
|
668
|
+
t.assert.ok(!err, 'no error')
|
|
669
|
+
resolve()
|
|
628
670
|
})
|
|
629
671
|
})
|
|
630
672
|
})
|
|
631
|
-
connect(setup(broker))
|
|
632
673
|
})
|
|
633
674
|
|
|
634
|
-
test('unsubscribe should not call removeSubscriptions when [clean=true]',
|
|
675
|
+
test('unsubscribe should not call removeSubscriptions when [clean=true]', async (t) => {
|
|
635
676
|
t.plan(2)
|
|
636
677
|
|
|
637
|
-
const
|
|
638
|
-
t.teardown(broker.close.bind(broker))
|
|
678
|
+
const s = await createAndConnect(t, { connect: { clean: true } })
|
|
639
679
|
|
|
640
|
-
broker.persistence.removeSubscriptions =
|
|
641
|
-
|
|
680
|
+
s.broker.persistence.removeSubscriptions = async () => {
|
|
681
|
+
throw new Error('remove subscription is called')
|
|
642
682
|
}
|
|
643
683
|
|
|
644
|
-
|
|
645
|
-
client.subscribe({
|
|
684
|
+
await new Promise(resolve => {
|
|
685
|
+
s.client.subscribe({
|
|
646
686
|
topic: 'hello',
|
|
647
687
|
qos: 1
|
|
648
|
-
},
|
|
649
|
-
t.
|
|
650
|
-
client.unsubscribe({
|
|
688
|
+
}, (err) => {
|
|
689
|
+
t.assert.ok(!err, 'no error')
|
|
690
|
+
s.client.unsubscribe({
|
|
651
691
|
unsubscriptions: [{
|
|
652
692
|
topic: 'hello',
|
|
653
693
|
qos: 1
|
|
654
694
|
}],
|
|
655
695
|
messageId: 42
|
|
656
|
-
},
|
|
657
|
-
t.
|
|
696
|
+
}, (err) => {
|
|
697
|
+
t.assert.ok(!err, 'no error')
|
|
698
|
+
resolve()
|
|
658
699
|
})
|
|
659
700
|
})
|
|
660
701
|
})
|
|
661
|
-
connect(setup(broker), { clean: true })
|
|
662
702
|
})
|
|
663
703
|
|
|
664
|
-
test('unsubscribe throws error',
|
|
704
|
+
test('unsubscribe throws error', async (t) => {
|
|
665
705
|
t.plan(2)
|
|
666
706
|
|
|
667
|
-
const
|
|
668
|
-
t.teardown(broker.close.bind(broker))
|
|
707
|
+
const s = await createAndConnect(t)
|
|
669
708
|
|
|
670
|
-
|
|
671
|
-
client.subscribe({
|
|
709
|
+
await new Promise(resolve => {
|
|
710
|
+
s.client.subscribe({
|
|
672
711
|
topic: 'hello',
|
|
673
712
|
qos: 0
|
|
674
|
-
},
|
|
675
|
-
t.
|
|
676
|
-
broker.unsubscribe =
|
|
713
|
+
}, (err) => {
|
|
714
|
+
t.assert.ok(!err, 'no error')
|
|
715
|
+
s.broker.unsubscribe = (topic, func, done) => {
|
|
677
716
|
done(new Error('error'))
|
|
678
717
|
}
|
|
679
|
-
client.unsubscribe({
|
|
718
|
+
s.client.unsubscribe({
|
|
680
719
|
topic: 'hello',
|
|
681
720
|
qos: 0
|
|
682
|
-
},
|
|
683
|
-
t.
|
|
721
|
+
}, () => {
|
|
722
|
+
t.assert.ok(true, 'throws error')
|
|
723
|
+
resolve()
|
|
684
724
|
})
|
|
685
725
|
})
|
|
686
726
|
})
|
|
687
|
-
connect(setup(broker))
|
|
688
727
|
})
|
|
689
728
|
|
|
690
|
-
test('unsubscribe throws error 2',
|
|
729
|
+
test('unsubscribe throws error 2', async (t) => {
|
|
691
730
|
t.plan(2)
|
|
692
731
|
|
|
693
|
-
const
|
|
694
|
-
t.teardown(broker.close.bind(broker))
|
|
732
|
+
const s = await createAndConnect(t)
|
|
695
733
|
|
|
696
|
-
|
|
697
|
-
client.subscribe({
|
|
734
|
+
await new Promise(resolve => {
|
|
735
|
+
s.client.subscribe({
|
|
698
736
|
topic: 'hello',
|
|
699
737
|
qos: 2
|
|
700
|
-
},
|
|
701
|
-
t.
|
|
702
|
-
broker.persistence.removeSubscriptions =
|
|
703
|
-
|
|
738
|
+
}, (err) => {
|
|
739
|
+
t.assert.ok(!err, 'no error')
|
|
740
|
+
s.broker.persistence.removeSubscriptions = async () => {
|
|
741
|
+
throw new Error('error')
|
|
704
742
|
}
|
|
705
|
-
client.unsubscribe({
|
|
743
|
+
s.client.unsubscribe({
|
|
706
744
|
unsubscriptions: [{
|
|
707
745
|
topic: 'hello',
|
|
708
746
|
qos: 2
|
|
709
747
|
}],
|
|
710
748
|
messageId: 42
|
|
711
|
-
},
|
|
712
|
-
t.
|
|
749
|
+
}, () => {
|
|
750
|
+
t.assert.ok(true, 'throws error')
|
|
751
|
+
resolve()
|
|
713
752
|
})
|
|
714
753
|
})
|
|
715
754
|
})
|
|
716
|
-
connect(setup(broker))
|
|
717
755
|
})
|
|
718
756
|
|
|
719
|
-
test('subscribe a client programmatically multiple topics',
|
|
757
|
+
test('subscribe a client programmatically multiple topics', async (t) => {
|
|
720
758
|
t.plan(3)
|
|
721
759
|
|
|
722
|
-
const
|
|
723
|
-
t.teardown(broker.close.bind(broker))
|
|
760
|
+
const s = await createAndConnect(t)
|
|
724
761
|
|
|
725
762
|
const expected = {
|
|
726
763
|
cmd: 'publish',
|
|
@@ -732,38 +769,34 @@ test('subscribe a client programmatically multiple topics', function (t) {
|
|
|
732
769
|
retain: false
|
|
733
770
|
}
|
|
734
771
|
|
|
735
|
-
|
|
736
|
-
client.subscribe([{
|
|
772
|
+
await new Promise(resolve => {
|
|
773
|
+
s.client.subscribe([{
|
|
737
774
|
topic: 'hello',
|
|
738
775
|
qos: 0
|
|
739
776
|
}, {
|
|
740
777
|
topic: 'aaa',
|
|
741
778
|
qos: 0
|
|
742
|
-
}],
|
|
743
|
-
t.
|
|
744
|
-
|
|
745
|
-
broker.publish({
|
|
779
|
+
}], (err) => {
|
|
780
|
+
t.assert.ok(!err, 'no error')
|
|
781
|
+
s.broker.publish({
|
|
746
782
|
topic: 'hello',
|
|
747
783
|
payload: Buffer.from('world'),
|
|
748
784
|
qos: 0
|
|
749
|
-
},
|
|
750
|
-
t.
|
|
785
|
+
}, (err) => {
|
|
786
|
+
t.assert.ok(!err, 'no error')
|
|
787
|
+
resolve()
|
|
751
788
|
})
|
|
752
789
|
})
|
|
753
790
|
})
|
|
754
791
|
|
|
755
|
-
const
|
|
756
|
-
|
|
757
|
-
s.outStream.once('data', function (packet) {
|
|
758
|
-
t.same(packet, expected, 'packet matches')
|
|
759
|
-
})
|
|
792
|
+
const packet = await nextPacket(s)
|
|
793
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
760
794
|
})
|
|
761
795
|
|
|
762
|
-
test('subscribe a client programmatically with full packet',
|
|
796
|
+
test('subscribe a client programmatically with full packet', async (t) => {
|
|
763
797
|
t.plan(3)
|
|
764
798
|
|
|
765
|
-
const
|
|
766
|
-
t.teardown(broker.close.bind(broker))
|
|
799
|
+
const s = await createAndConnect(t)
|
|
767
800
|
|
|
768
801
|
const expected = {
|
|
769
802
|
cmd: 'publish',
|
|
@@ -775,8 +808,8 @@ test('subscribe a client programmatically with full packet', function (t) {
|
|
|
775
808
|
retain: false
|
|
776
809
|
}
|
|
777
810
|
|
|
778
|
-
|
|
779
|
-
client.subscribe({
|
|
811
|
+
await new Promise(resolve => {
|
|
812
|
+
s.client.subscribe({
|
|
780
813
|
subscriptions: [{
|
|
781
814
|
topic: 'hello',
|
|
782
815
|
qos: 0
|
|
@@ -784,131 +817,122 @@ test('subscribe a client programmatically with full packet', function (t) {
|
|
|
784
817
|
topic: 'aaa',
|
|
785
818
|
qos: 0
|
|
786
819
|
}]
|
|
787
|
-
},
|
|
788
|
-
t.
|
|
820
|
+
}, (err) => {
|
|
821
|
+
t.assert.ok(!err, 'no error')
|
|
789
822
|
|
|
790
|
-
broker.publish({
|
|
823
|
+
s.broker.publish({
|
|
791
824
|
topic: 'hello',
|
|
792
825
|
payload: Buffer.from('world'),
|
|
793
826
|
qos: 0
|
|
794
|
-
},
|
|
795
|
-
t.
|
|
827
|
+
}, (err) => {
|
|
828
|
+
t.assert.ok(!err, 'no error')
|
|
829
|
+
resolve()
|
|
796
830
|
})
|
|
797
831
|
})
|
|
798
832
|
})
|
|
799
833
|
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
s.outStream.once('data', function (packet) {
|
|
803
|
-
t.same(packet, expected, 'packet matches')
|
|
804
|
-
})
|
|
834
|
+
const packet = await nextPacket(s)
|
|
835
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
805
836
|
})
|
|
806
837
|
|
|
807
|
-
test('get message when client connects',
|
|
838
|
+
test('get message when client connects', async (t) => {
|
|
808
839
|
t.plan(2)
|
|
809
840
|
|
|
810
841
|
const client1 = 'gav'
|
|
811
|
-
const
|
|
812
|
-
t
|
|
842
|
+
const client2 = 'friend'
|
|
843
|
+
const s = await createAndConnect(t, { connect: { clientId: client1 } })
|
|
813
844
|
|
|
814
|
-
|
|
815
|
-
client.subscribe({
|
|
845
|
+
await new Promise(resolve => {
|
|
846
|
+
s.client.subscribe({
|
|
816
847
|
subscriptions: [{
|
|
817
848
|
topic: '$SYS/+/new/clients',
|
|
818
849
|
qos: 0
|
|
819
850
|
}]
|
|
820
|
-
},
|
|
821
|
-
t.
|
|
851
|
+
}, (err) => {
|
|
852
|
+
t.assert.ok(!err, 'no error')
|
|
853
|
+
resolve()
|
|
822
854
|
})
|
|
823
855
|
})
|
|
824
856
|
|
|
825
|
-
const
|
|
857
|
+
const s2 = setup(s.broker)
|
|
858
|
+
await connect(s2, { connect: { clientId: client2 } })
|
|
826
859
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
})
|
|
860
|
+
const packet = await nextPacket(s)
|
|
861
|
+
t.assert.equal(client2, packet.payload.toString())
|
|
830
862
|
})
|
|
831
863
|
|
|
832
|
-
test('get message when client disconnects',
|
|
864
|
+
test('get message when client disconnects', async (t) => {
|
|
833
865
|
t.plan(2)
|
|
834
866
|
|
|
835
867
|
const client1 = 'gav'
|
|
836
868
|
const client2 = 'friend'
|
|
837
|
-
const
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
})
|
|
850
|
-
} else {
|
|
851
|
-
client.close()
|
|
852
|
-
}
|
|
869
|
+
const s = await createAndConnect(t, { connect: { clientId: client1 } })
|
|
870
|
+
|
|
871
|
+
await new Promise(resolve => {
|
|
872
|
+
s.client.subscribe({
|
|
873
|
+
subscriptions: [{
|
|
874
|
+
topic: '$SYS/+/disconnect/clients',
|
|
875
|
+
qos: 0
|
|
876
|
+
}]
|
|
877
|
+
}, (err) => {
|
|
878
|
+
t.assert.ok(!err, 'no error')
|
|
879
|
+
resolve()
|
|
880
|
+
})
|
|
853
881
|
})
|
|
854
882
|
|
|
855
|
-
const
|
|
856
|
-
connect(
|
|
883
|
+
const s2 = setup(s.broker)
|
|
884
|
+
await connect(s2, { connect: { clientId: client2 } })
|
|
885
|
+
s2.client.close()
|
|
857
886
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
})
|
|
887
|
+
const packet = await nextPacket(s)
|
|
888
|
+
t.assert.equal(client2, packet.payload.toString())
|
|
861
889
|
})
|
|
862
890
|
|
|
863
|
-
test('should not receive a message on negated subscription',
|
|
864
|
-
t.plan(
|
|
891
|
+
test('should not receive a message on negated subscription', async (t) => {
|
|
892
|
+
t.plan(5)
|
|
865
893
|
|
|
866
|
-
const
|
|
867
|
-
t.teardown(broker.close.bind(broker))
|
|
894
|
+
const s = await createAndConnect(t)
|
|
868
895
|
|
|
869
|
-
broker.authorizeSubscribe =
|
|
896
|
+
s.broker.authorizeSubscribe = (client, sub, callback) => {
|
|
870
897
|
callback(null, null)
|
|
871
898
|
}
|
|
872
899
|
|
|
873
|
-
|
|
874
|
-
broker.publish({
|
|
900
|
+
await new Promise(resolve => {
|
|
901
|
+
s.broker.publish({
|
|
875
902
|
topic: 'hello',
|
|
876
903
|
payload: Buffer.from('world'),
|
|
877
904
|
qos: 0,
|
|
878
905
|
retain: true
|
|
879
|
-
},
|
|
880
|
-
t.
|
|
881
|
-
client.subscribe([{
|
|
906
|
+
}, (err) => {
|
|
907
|
+
t.assert.ok(!err, 'no error')
|
|
908
|
+
s.client.subscribe([{
|
|
882
909
|
topic: 'hello',
|
|
883
910
|
qos: 0
|
|
884
911
|
},
|
|
885
912
|
{
|
|
886
913
|
topic: 'hello',
|
|
887
914
|
qos: 0
|
|
888
|
-
}],
|
|
889
|
-
t.
|
|
915
|
+
}], (err) => {
|
|
916
|
+
t.assert.ok(!err, 'no error')
|
|
917
|
+
resolve()
|
|
890
918
|
})
|
|
891
919
|
})
|
|
892
|
-
})
|
|
893
920
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
921
|
+
s.broker.on('subscribe', subs => {
|
|
922
|
+
t.assert.equal(subs.length, 1, 'Should dedupe subs')
|
|
923
|
+
t.assert.equal(subs[0].qos, 128, 'Qos should be 128 (Fail)')
|
|
924
|
+
})
|
|
897
925
|
})
|
|
898
926
|
|
|
899
|
-
const
|
|
900
|
-
|
|
901
|
-
t.fail('Packet should not be received')
|
|
902
|
-
})
|
|
927
|
+
const packet = await nextPacketWithTimeOut(s, 10)
|
|
928
|
+
t.assert.equal(packet, null, 'Packet should not be received')
|
|
903
929
|
})
|
|
904
930
|
|
|
905
|
-
test('programmatically add custom subscribe',
|
|
931
|
+
test('programmatically add custom subscribe', async (t) => {
|
|
906
932
|
t.plan(6)
|
|
907
933
|
|
|
908
|
-
const
|
|
909
|
-
t.teardown(broker.close.bind(broker))
|
|
934
|
+
const s = await createAndConnect(t, { connect: { clientId: 'my-client-xyz-7' } })
|
|
910
935
|
|
|
911
|
-
const s = connect(setup(broker), { clientId: 'my-client-xyz-7' })
|
|
912
936
|
const expected = {
|
|
913
937
|
cmd: 'publish',
|
|
914
938
|
topic: 'hello',
|
|
@@ -927,36 +951,39 @@ test('programmatically add custom subscribe', function (t) {
|
|
|
927
951
|
dup: false,
|
|
928
952
|
clientId: 'my-client-xyz-7'
|
|
929
953
|
}
|
|
930
|
-
|
|
931
|
-
broker.subscribe('hello', deliver, function () {
|
|
932
|
-
t.pass('subscribed')
|
|
933
|
-
})
|
|
934
|
-
s.outStream.on('data', function (packet) {
|
|
935
|
-
t.same(packet, expected, 'packet matches')
|
|
936
|
-
})
|
|
937
|
-
s.inStream.write({
|
|
938
|
-
cmd: 'publish',
|
|
939
|
-
topic: 'hello',
|
|
940
|
-
payload: 'world',
|
|
941
|
-
qos: 0,
|
|
942
|
-
messageId: 42
|
|
943
|
-
})
|
|
944
|
-
})
|
|
954
|
+
|
|
945
955
|
function deliver (packet, cb) {
|
|
946
956
|
deliverP.brokerId = s.broker.id
|
|
947
957
|
deliverP.brokerCounter = s.broker.counter
|
|
948
|
-
t.
|
|
958
|
+
t.assert.deepEqual(structuredClone(packet), deliverP, 'packet matches')
|
|
949
959
|
cb()
|
|
950
960
|
}
|
|
961
|
+
|
|
962
|
+
await subscribe(t, s, 'hello', 0)
|
|
963
|
+
await new Promise(resolve => {
|
|
964
|
+
s.broker.subscribe('hello', deliver, () => {
|
|
965
|
+
t.assert.ok(true, 'subscribed')
|
|
966
|
+
resolve()
|
|
967
|
+
})
|
|
968
|
+
})
|
|
969
|
+
|
|
970
|
+
s.inStream.write({
|
|
971
|
+
cmd: 'publish',
|
|
972
|
+
topic: 'hello',
|
|
973
|
+
payload: 'world',
|
|
974
|
+
qos: 0,
|
|
975
|
+
messageId: 42
|
|
976
|
+
})
|
|
977
|
+
|
|
978
|
+
const packet = await nextPacket(s)
|
|
979
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
951
980
|
})
|
|
952
981
|
|
|
953
|
-
test('custom function in broker.subscribe',
|
|
954
|
-
t.plan(
|
|
982
|
+
test('custom function in broker.subscribe', async (t) => {
|
|
983
|
+
t.plan(5)
|
|
955
984
|
|
|
956
|
-
const
|
|
957
|
-
t.teardown(broker.close.bind(broker))
|
|
985
|
+
const s = await createAndConnect(t, { connect: { clientId: 'my-client-xyz-6' } })
|
|
958
986
|
|
|
959
|
-
const s = setup(broker)
|
|
960
987
|
const expected = {
|
|
961
988
|
cmd: 'publish',
|
|
962
989
|
topic: 'hello',
|
|
@@ -967,44 +994,49 @@ test('custom function in broker.subscribe', function (t) {
|
|
|
967
994
|
messageId: undefined,
|
|
968
995
|
clientId: 'my-client-xyz-6'
|
|
969
996
|
}
|
|
970
|
-
|
|
971
|
-
broker.subscribe('hello', deliver, function () {
|
|
972
|
-
t.pass('subscribed')
|
|
973
|
-
})
|
|
974
|
-
s.inStream.write({
|
|
975
|
-
cmd: 'publish',
|
|
976
|
-
topic: 'hello',
|
|
977
|
-
payload: 'world',
|
|
978
|
-
qos: 1,
|
|
979
|
-
messageId: 42
|
|
980
|
-
})
|
|
981
|
-
})
|
|
982
|
-
broker.on('publish', function (packet, client) {
|
|
983
|
-
if (client) {
|
|
984
|
-
t.equal(packet.topic, 'hello')
|
|
985
|
-
t.equal(packet.messageId, 42)
|
|
986
|
-
}
|
|
987
|
-
})
|
|
997
|
+
|
|
988
998
|
function deliver (packet, cb) {
|
|
989
999
|
expected.brokerId = s.broker.id
|
|
990
1000
|
expected.brokerCounter = s.broker.counter
|
|
991
|
-
t.
|
|
1001
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
992
1002
|
cb()
|
|
993
1003
|
}
|
|
1004
|
+
|
|
1005
|
+
await new Promise(resolve => {
|
|
1006
|
+
s.broker.subscribe('hello', deliver, () => {
|
|
1007
|
+
t.assert.ok(true, 'subscribed')
|
|
1008
|
+
resolve()
|
|
1009
|
+
})
|
|
1010
|
+
})
|
|
1011
|
+
s.inStream.write({
|
|
1012
|
+
cmd: 'publish',
|
|
1013
|
+
topic: 'hello',
|
|
1014
|
+
payload: 'world',
|
|
1015
|
+
qos: 1,
|
|
1016
|
+
messageId: 42
|
|
1017
|
+
})
|
|
1018
|
+
|
|
1019
|
+
const [packet, client] = await once(s.broker, 'publish')
|
|
1020
|
+
t.assert.ok(client, 'client exists')
|
|
1021
|
+
t.assert.equal(packet.topic, 'hello')
|
|
1022
|
+
t.assert.equal(packet.messageId, 42)
|
|
994
1023
|
})
|
|
995
1024
|
|
|
996
|
-
test('custom function in broker.unsubscribe',
|
|
997
|
-
t.plan(
|
|
1025
|
+
test('custom function in broker.unsubscribe', async (t) => {
|
|
1026
|
+
t.plan(4)
|
|
1027
|
+
|
|
1028
|
+
const s = await createAndConnect(t)
|
|
998
1029
|
|
|
999
|
-
|
|
1000
|
-
|
|
1030
|
+
function deliver (packet, cb) {
|
|
1031
|
+
t.assert.fail('should not be called')
|
|
1032
|
+
cb()
|
|
1033
|
+
}
|
|
1001
1034
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
t.pass('unsubscribe')
|
|
1035
|
+
await new Promise(resolve => {
|
|
1036
|
+
s.broker.subscribe('hello', deliver, () => {
|
|
1037
|
+
t.assert.ok(true, 'subscribed')
|
|
1038
|
+
s.broker.unsubscribe('hello', deliver, () => {
|
|
1039
|
+
t.assert.ok(true, 'unsubscribe')
|
|
1008
1040
|
s.inStream.write({
|
|
1009
1041
|
cmd: 'publish',
|
|
1010
1042
|
topic: 'hello',
|
|
@@ -1012,16 +1044,11 @@ test('custom function in broker.unsubscribe', function (t) {
|
|
|
1012
1044
|
qos: 1,
|
|
1013
1045
|
messageId: 42
|
|
1014
1046
|
})
|
|
1047
|
+
resolve()
|
|
1015
1048
|
})
|
|
1016
1049
|
})
|
|
1017
1050
|
})
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
}
|
|
1022
|
-
})
|
|
1023
|
-
function deliver (packet, cb) {
|
|
1024
|
-
t.fail('should not be called')
|
|
1025
|
-
cb()
|
|
1026
|
-
}
|
|
1051
|
+
const [packet, client] = await once(s.broker, 'publish')
|
|
1052
|
+
t.assert.ok(client, 'client exists')
|
|
1053
|
+
t.assert.equal(packet.messageId, 42)
|
|
1027
1054
|
})
|