@@ -5,12 +5,12 @@ import { Aedes } from '../aedes.js'
5
5
6
6
let clients = 0
7
7
8
- export function setup ( broker ) {
8
+ export function setup ( broker ) {
9
9
const [ client , server ] = duplexPair ( )
10
10
const inStream = new Transform (
11
11
{
12
12
objectMode : true ,
13
- transform ( chunk , enc , callback ) {
13
+ transform ( chunk , enc , callback ) {
14
14
this . push ( mqtt . generate ( chunk ) )
15
15
callback ( )
16
16
}
@@ -47,7 +47,7 @@ export function setup (broker) {
47
47
* @returns {Object } the connack packet
48
48
*/
49
49
50
- export async function connect ( s , opts = { } ) {
50
+ export async function connect ( s , opts = { } ) {
51
51
const connect = opts . connect || { }
52
52
connect . cmd = 'connect'
53
53
connect . protocolId = connect . protocolId || 'MQTT'
@@ -60,6 +60,7 @@ export async function connect (s, opts = {}) {
60
60
const expectedReturnCode = opts . expectedReturnCode || 0
61
61
const verifyIsConnack = opts . verifyIsConnack !== false
62
62
const verifyReturnedOk = verifyIsConnack ? opts . verifyReturnedOk !== false : false
63
+ const noWait = opts . noWait
63
64
64
65
if ( opts . autoClientId ) {
65
66
connect . clientId = 'my-client-' + clients ++
@@ -74,6 +75,9 @@ export async function connect (s, opts = {}) {
74
75
}
75
76
76
77
s . inStream . write ( connect )
78
+ if ( noWait ) {
79
+ return
80
+ }
77
81
const { value : connack } = await s . outStream . next ( )
78
82
if ( verifyIsConnack && connack ?. cmd !== 'connack' ) {
79
83
throw new Error ( 'Expected connack' )
@@ -89,21 +93,40 @@ export async function connect (s, opts = {}) {
89
93
* @param {Object } t - Test assertion object
90
94
* @returns {Object } Connection state
91
95
*/
92
- export async function createAndConnect ( t , opts = { } ) {
96
+ export async function createAndConnect ( t , opts = { } ) {
93
97
const broker = await Aedes . createBroker ( opts . broker )
94
98
t . after ( ( ) => broker . close ( ) )
95
99
const s = setup ( broker )
96
100
await connect ( s , opts )
97
101
return s
98
102
}
99
103
104
+ /**
105
+ * Creates a new MQTT connection and establishes it for publisher and subscriber
106
+ * @param {Object } t - Test assertion object
107
+ * @returns {Object } Connection state { broker, publisher, subscriber }
108
+ */
109
+ export async function createPubSub ( t , opts = { } ) {
110
+ const publisherOpts = opts . publisher || { clientId : 'publisher' }
111
+ const subscriberOpts = opts . subscriber || { clientId : 'subscriber' }
112
+
113
+ const broker = await Aedes . createBroker ( )
114
+ t . after ( ( ) => broker . close ( ) )
115
+
116
+ const publisher = setup ( broker )
117
+ const subscriber = setup ( broker )
118
+ await connect ( publisher , { connect : publisherOpts } )
119
+ await connect ( subscriber , { connect : subscriberOpts } )
120
+ return { broker, publisher, subscriber }
121
+ }
122
+
100
123
/**
101
124
* Sets up error handling for the broker connection
102
125
* @param {Object } s - The connection state object
103
126
* @param {Object } t - Test assertion object
104
127
* @returns {Object } Connection state with error handling
105
128
*/
106
- export function noError ( s , t ) {
129
+ export function noError ( s , t ) {
107
130
s . broker . on ( 'clientError' , ( client , err ) => {
108
131
if ( err ) throw err
109
132
t . assert . equal ( err , undefined , 'must not error' )
@@ -116,25 +139,54 @@ export function noError (s, t) {
116
139
* @param {Object } packet - The packet to publish
117
140
* @returns {Promise } - Promise that resolves when the packet is published
118
141
*/
119
- export async function brokerPublish ( s , packet ) {
142
+ export async function brokerPublish ( s , packet ) {
120
143
return new Promise ( ( resolve ) => {
121
144
s . broker . publish ( packet , ( ) => {
122
145
setImmediate ( resolve )
123
146
} )
124
147
} )
125
148
}
126
149
150
+ /**
151
+ * publish a packet to the broker
152
+ * @param {Object } t - Test assertion object
153
+ * @param {Object } s - The connection state object
154
+ * @param {Object } packet - The packet to publish
155
+ * @returns {Promise } - Promise that resolves when the packet is published
156
+ */
157
+ export async function publish ( t , s , packet ) {
158
+ s . inStream . write ( packet )
159
+ if ( packet . qos === 1 ) {
160
+ const { value : puback } = await s . outStream . next ( )
161
+ t . assert . equal ( puback . cmd , 'puback' )
162
+ return puback
163
+ }
164
+ if ( packet . qos === 2 ) {
165
+ const { value : pubrec } = await s . outStream . next ( )
166
+ t . assert . equal ( pubrec . cmd , 'pubrec' )
167
+ s . inStream . write ( {
168
+ cmd : 'pubrel' ,
169
+ messageId : pubrec . messageId
170
+ } )
171
+ const { value : pubcomp } = await s . outStream . next ( )
172
+ t . assert . equal ( pubcomp . cmd , 'pubcomp' )
173
+ return pubcomp
174
+ }
175
+ return null
176
+ }
127
177
/**
128
178
* Subscribes to a single MQTT topic
129
179
* @param {Object } t - Test assertion object
130
180
* @param {Object } subscriber - The subscriber client
131
181
* @param {string } topic - Topic to subscribe to
132
182
* @param {number } qos - Quality of Service level
183
+ * @param {number } messageId - Message ID for the subscription
184
+ * @returns {Object } The subscription packet
133
185
*/
134
- export async function subscribe ( t , subscriber , topic , qos ) {
186
+ export async function subscribe ( t , subscriber , topic , qos , messageId = 24 ) {
135
187
subscriber . inStream . write ( {
136
188
cmd : 'subscribe' ,
137
- messageId : 24 ,
189
+ messageId,
138
190
subscriptions : [ {
139
191
topic,
140
192
qos
@@ -144,7 +196,7 @@ export async function subscribe (t, subscriber, topic, qos) {
144
196
const { value : packet } = await subscriber . outStream . next ( )
145
197
t . assert . equal ( packet . cmd , 'suback' )
146
198
t . assert . equal ( packet . granted [ 0 ] , qos )
147
- t . assert . equal ( packet . messageId , 24 )
199
+ t . assert . equal ( packet . messageId , messageId )
148
200
return packet
149
201
}
150
202
@@ -155,7 +207,7 @@ export async function subscribe (t, subscriber, topic, qos) {
155
207
* @param {Array<Object> } subs - Array of subscription objects with topic and qos
156
208
* @param {Array<number> } expectedGranted - Expected QoS levels granted
157
209
*/
158
- export async function subscribeMultiple ( t , subscriber , subs , expectedGranted ) {
210
+ export async function subscribeMultiple ( t , subscriber , subs , expectedGranted ) {
159
211
subscriber . inStream . write ( {
160
212
cmd : 'subscribe' ,
161
213
messageId : 24 ,
@@ -176,7 +228,7 @@ export async function subscribeMultiple (t, subscriber, subs, expectedGranted) {
176
228
* @param {Error } err - Error to throw on timeout
177
229
* @returns {Promise } Promise that rejects if timeout occurs
178
230
*/
179
- export async function withTimeout ( promise , timeoutMs , timeoutResult ) {
231
+ export async function withTimeout ( promise , timeoutMs , timeoutResult ) {
180
232
const timeoutPromise = delay ( timeoutMs , timeoutResult )
181
233
return Promise . race ( [ promise , timeoutPromise ] )
182
234
}
@@ -187,7 +239,7 @@ export async function withTimeout (promise, timeoutMs, timeoutResult) {
187
239
* @param {Object } opts - low and high water mark
188
240
* @returns {AsyncGenerator } An async generator that yields MQTT packets
189
241
*/
190
- async function * packetGenerator ( parser , sourceStream , opts = {
242
+ async function * packetGenerator ( parser , sourceStream , opts = {
191
243
highWaterMark : 2 ,
192
244
lowWaterMark : 0
193
245
} ) {
@@ -264,7 +316,7 @@ async function * packetGenerator (parser, sourceStream, opts = {
264
316
* @param {Object } s - The connection state object
265
317
* @returns
266
318
*/
267
- export async function nextPacket ( s ) {
319
+ export async function nextPacket ( s ) {
268
320
const { value : packet } = await s . outStream . next ( )
269
321
return packet
270
322
}
@@ -275,7 +327,7 @@ export async function nextPacket (s) {
275
327
* @param {number } timeoutMs - Timeout in milliseconds
276
328
* @returns
277
329
*/
278
- export async function nextPacketWithTimeOut ( s , timeoutMs ) {
330
+ export async function nextPacketWithTimeOut ( s , timeoutMs ) {
279
331
return withTimeout ( nextPacket ( s ) , timeoutMs , null )
280
332
}
281
333
@@ -286,7 +338,7 @@ export async function nextPacketWithTimeOut (s, timeoutMs) {
286
338
* @param {number } timeoutMs - Timeout in milliseconds
287
339
* @returns
288
340
*/
289
- export async function checkNoPacket ( t , s , timeoutMs = 10 ) {
341
+ export async function checkNoPacket ( t , s , timeoutMs = 10 ) {
290
342
const result = await nextPacketWithTimeOut ( s , timeoutMs )
291
343
t . assert . equal ( result , null , 'no packet received' )
292
344
}
@@ -297,7 +349,7 @@ export async function checkNoPacket (t, s, timeoutMs = 10) {
297
349
* @param {string } rawPacket - space separated string of hex values
298
350
* @example rawWrite(s, "10 0C 00 04 4D 51 54 54 04 00 00 00 00 00")
299
351
*/
300
- export function rawWrite ( s , rawPacket ) {
352
+ export function rawWrite ( s , rawPacket ) {
301
353
s . conn . write ( Buffer . from ( rawPacket . replace ( / / g, '' ) , 'hex' ) )
302
354
}
303
355
/**
0 commit comments