amqplib 2.2.0 → 2.3.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/CHANGELOG.md +12 -0
- package/callback_api.d.ts +2 -2
- package/index.d.ts +1 -1
- package/lib/callback_model.js +3 -22
- package/lib/channel.js +27 -1
- package/lib/channel_model.js +4 -29
- package/lib/connect.js +8 -0
- package/lib/connection.js +25 -1
- package/lib/frame.js +5 -1
- package/lib/properties.d.ts +4 -0
- package/package.json +12 -2
- package/.claude/commands/lint-disable.md +0 -9
- package/.claude/commands/lint-enable.md +0 -12
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -41
- package/.github/workflows/publish.yml +0 -113
- package/.github/workflows/test.yml +0 -54
- package/CLAUDE.md +0 -12
- package/Makefile +0 -42
- package/bin/amqp-rabbitmq-0.9.1.json +0 -483
- package/bin/generate-defs.js +0 -734
- package/biome.json +0 -51
- package/lefthook.yml +0 -17
- package/test/bitset.test.js +0 -65
- package/test/callback_api.test.js +0 -439
- package/test/channel.test.js +0 -918
- package/test/channel_api.test.js +0 -599
- package/test/codec.test.js +0 -171
- package/test/connect.test.js +0 -155
- package/test/connection.test.js +0 -772
- package/test/data.test.js +0 -33
- package/test/frame.test.js +0 -180
- package/test/lib/data.js +0 -249
- package/test/lib/util.js +0 -223
- package/test/mux.test.js +0 -258
- package/test/recovery.test.js +0 -799
- package/test/uri_spec.test.js +0 -210
package/test/channel.test.js
DELETED
|
@@ -1,918 +0,0 @@
|
|
|
1
|
-
const { describe, it, beforeEach, afterEach } = require('node:test');
|
|
2
|
-
const assert = require('node:assert');
|
|
3
|
-
const promisify = require('node:util').promisify;
|
|
4
|
-
const Channel = require('../lib/channel').Channel;
|
|
5
|
-
const Connection = require('../lib/connection').Connection;
|
|
6
|
-
const util = require('./lib/util');
|
|
7
|
-
const latch = util.latch;
|
|
8
|
-
const completes = util.completes;
|
|
9
|
-
const handshake = util.handshake;
|
|
10
|
-
const defs = require('../lib/defs');
|
|
11
|
-
const OPEN_OPTS = require('./lib/data').OPEN_OPTS;
|
|
12
|
-
|
|
13
|
-
const LOG_ERRORS = process.env.LOG_ERRORS;
|
|
14
|
-
|
|
15
|
-
function baseChannelTest(client, server) {
|
|
16
|
-
return (_t, done) => {
|
|
17
|
-
const decrementLatch = latch(2, done);
|
|
18
|
-
const pair = util.socketPair();
|
|
19
|
-
const c = new Connection(pair.client);
|
|
20
|
-
|
|
21
|
-
if (LOG_ERRORS) c.on('error', console.warn);
|
|
22
|
-
|
|
23
|
-
c.open(OPEN_OPTS, (err, _ok) => {
|
|
24
|
-
if (err === null) client(c, decrementLatch);
|
|
25
|
-
else decrementLatch(err);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
pair.server.read(8); // discard the protocol header
|
|
29
|
-
util.runServer(pair.server, (send, wait) => {
|
|
30
|
-
handshake(send, wait).then(() => {
|
|
31
|
-
server(send, wait, decrementLatch);
|
|
32
|
-
}, decrementLatch);
|
|
33
|
-
});
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function channelTest(client, server) {
|
|
38
|
-
return baseChannelTest(
|
|
39
|
-
(conn, done) => {
|
|
40
|
-
const ch = new Channel(conn);
|
|
41
|
-
if (LOG_ERRORS) ch.on('error', console.warn);
|
|
42
|
-
client(ch, done, conn);
|
|
43
|
-
},
|
|
44
|
-
(send, wait, done) => {
|
|
45
|
-
channel_handshake(send, wait)
|
|
46
|
-
.then((ch) => server(send, wait, done, ch))
|
|
47
|
-
.then(null, done); // so you can return a promise to let
|
|
48
|
-
// errors bubble out
|
|
49
|
-
},
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function channel_handshake(send, wait) {
|
|
54
|
-
return wait(defs.ChannelOpen)().then((open) => {
|
|
55
|
-
assert.notEqual(0, open.channel);
|
|
56
|
-
send(defs.ChannelOpenOk, { channelId: Buffer.from('') }, open.channel);
|
|
57
|
-
return open.channel;
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// fields for deliver and publish and get-ok
|
|
62
|
-
const DELIVER_FIELDS = {
|
|
63
|
-
consumerTag: 'fake',
|
|
64
|
-
deliveryTag: 1,
|
|
65
|
-
redelivered: false,
|
|
66
|
-
exchange: 'foo',
|
|
67
|
-
routingKey: 'bar',
|
|
68
|
-
replyCode: defs.constants.NO_ROUTE,
|
|
69
|
-
replyText: 'derp',
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
function open(ch) {
|
|
73
|
-
ch.allocate();
|
|
74
|
-
return promisify((cb) => {
|
|
75
|
-
ch._rpc(defs.ChannelOpen, { outOfBand: '' }, defs.ChannelOpenOk, cb);
|
|
76
|
-
})();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
describe('Channel', () => {
|
|
80
|
-
|
|
81
|
-
describe('channel open and close', () => {
|
|
82
|
-
it('open', channelTest(
|
|
83
|
-
(ch, cb) => open(ch).then((ok) => {
|
|
84
|
-
assert.equal(ok.id, defs.ChannelOpenOk);
|
|
85
|
-
cb();
|
|
86
|
-
}),
|
|
87
|
-
(_send, _wait, cb) => cb()
|
|
88
|
-
));
|
|
89
|
-
|
|
90
|
-
it('bad server', baseChannelTest(
|
|
91
|
-
(c, cb) => {
|
|
92
|
-
const ch = new Channel(c);
|
|
93
|
-
assert.rejects(() => open(ch), (err) => {
|
|
94
|
-
assert.match(err.message, /Expected ChannelOpenOk; got <ChannelCloseOk channel:1>/);
|
|
95
|
-
return true;
|
|
96
|
-
}).then(() => cb());
|
|
97
|
-
}, (send, wait, cb) =>
|
|
98
|
-
wait(defs.ChannelOpen)()
|
|
99
|
-
.then((open) => send(defs.ChannelCloseOk, {}, open.channel))
|
|
100
|
-
.then(cb)
|
|
101
|
-
)
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
it('open, close', channelTest(
|
|
105
|
-
(ch, cb) => {
|
|
106
|
-
open(ch)
|
|
107
|
-
.then(() => new Promise((resolve) => {
|
|
108
|
-
ch.closeBecause('Bye', defs.constants.REPLY_SUCCESS, resolve);
|
|
109
|
-
}))
|
|
110
|
-
.then(cb);
|
|
111
|
-
}, (send, wait, cb, ch) =>
|
|
112
|
-
wait(defs.ChannelClose)()
|
|
113
|
-
.then((_close) => send(defs.ChannelCloseOk, {}, ch))
|
|
114
|
-
.then(cb)
|
|
115
|
-
)
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
it('server close', channelTest(
|
|
119
|
-
(ch, cb) => {
|
|
120
|
-
ch.once('error', (err) => {
|
|
121
|
-
assert.match(err.message, /Channel closed by server: 504 \(CHANNEL-ERROR\)/);
|
|
122
|
-
assert.strictEqual(504, err.code);
|
|
123
|
-
assert.strictEqual(0, err.classId);
|
|
124
|
-
assert.strictEqual(0, err.methodId);
|
|
125
|
-
cb();
|
|
126
|
-
});
|
|
127
|
-
open(ch);
|
|
128
|
-
}, (send, wait, cb, ch) => {
|
|
129
|
-
send(defs.ChannelClose, {
|
|
130
|
-
replyText: 'Forced close',
|
|
131
|
-
replyCode: defs.constants.CHANNEL_ERROR,
|
|
132
|
-
classId: 0,
|
|
133
|
-
methodId: 0,
|
|
134
|
-
}, ch);
|
|
135
|
-
wait(defs.ChannelCloseOk)().then(cb);
|
|
136
|
-
}));
|
|
137
|
-
|
|
138
|
-
it('overlapping channel/server close', channelTest(
|
|
139
|
-
(ch, cb, conn) => {
|
|
140
|
-
const decrementLatch = latch(2, cb);
|
|
141
|
-
conn.once('error', (err) => {
|
|
142
|
-
assert.match(err.message, /Connection closed: 541 \(INTERNAL-ERROR\)/);
|
|
143
|
-
decrementLatch();
|
|
144
|
-
});
|
|
145
|
-
ch.on('close', (err) => {
|
|
146
|
-
assert.ifError(err);
|
|
147
|
-
decrementLatch();
|
|
148
|
-
});
|
|
149
|
-
open(ch)
|
|
150
|
-
.then(() => ch.closeBecause('Bye', defs.constants.REPLY_SUCCESS));
|
|
151
|
-
}, (send, wait, cb, _ch) => {
|
|
152
|
-
wait(defs.ChannelClose)()
|
|
153
|
-
.then(() => send(defs.ConnectionClose, {
|
|
154
|
-
replyText: 'Got there first',
|
|
155
|
-
replyCode: defs.constants.INTERNAL_ERROR,
|
|
156
|
-
classId: 0,
|
|
157
|
-
methodId: 0,
|
|
158
|
-
}, 0)
|
|
159
|
-
)
|
|
160
|
-
.then(wait(defs.ConnectionCloseOk))
|
|
161
|
-
.then(cb);
|
|
162
|
-
}));
|
|
163
|
-
|
|
164
|
-
it('double close', channelTest((ch, cb) => {
|
|
165
|
-
open(ch)
|
|
166
|
-
.then(() => {
|
|
167
|
-
ch.closeBecause('First close', defs.constants.REPLY_SUCCESS);
|
|
168
|
-
// NB no synchronisation, we do this straight away
|
|
169
|
-
assert.throws(() => {
|
|
170
|
-
ch.closeBecause('Second close', defs.constants.REPLY_SUCCESS);
|
|
171
|
-
}, (err) => {
|
|
172
|
-
assert.match(err.message, /Channel closing/);
|
|
173
|
-
return true;
|
|
174
|
-
});
|
|
175
|
-
})
|
|
176
|
-
.then(cb);
|
|
177
|
-
}, (send, wait, cb, ch) => {
|
|
178
|
-
wait(defs.ChannelClose)()
|
|
179
|
-
.then(() => send(defs.ChannelCloseOk, {}, ch))
|
|
180
|
-
.then(cb);
|
|
181
|
-
}));
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
describe('channel machinery', () => {
|
|
185
|
-
it('RPC', channelTest((ch, cb) => {
|
|
186
|
-
const decrementLatch = latch(3, cb);
|
|
187
|
-
open(ch)
|
|
188
|
-
.then(() => {
|
|
189
|
-
const fields = { prefetchCount: 10, prefetchSize: 0, global: false };
|
|
190
|
-
ch._rpc(defs.BasicQos, fields, defs.BasicQosOk, decrementLatch);
|
|
191
|
-
ch._rpc(defs.BasicQos, fields, defs.BasicQosOk, decrementLatch);
|
|
192
|
-
ch._rpc(defs.BasicQos, fields, defs.BasicQosOk, decrementLatch);
|
|
193
|
-
})
|
|
194
|
-
}, (send, wait, cb, ch) => {
|
|
195
|
-
function sendOk() {
|
|
196
|
-
send(defs.BasicQosOk, {}, ch);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return wait(defs.BasicQos)()
|
|
200
|
-
.then(sendOk)
|
|
201
|
-
.then(wait(defs.BasicQos))
|
|
202
|
-
.then(sendOk)
|
|
203
|
-
.then(wait(defs.BasicQos))
|
|
204
|
-
.then(sendOk)
|
|
205
|
-
.then(cb);
|
|
206
|
-
}));
|
|
207
|
-
|
|
208
|
-
it('Bad RPC', channelTest(
|
|
209
|
-
(ch, cb) => {
|
|
210
|
-
// We want to see the RPC rejected and the channel closed (with an error)
|
|
211
|
-
const decrementLatch = latch(2, cb);
|
|
212
|
-
ch.once('error', (err) => {
|
|
213
|
-
assert.match(err.message, /Expected BasicRecoverOk; got <BasicGetEmpty channel:1>/);
|
|
214
|
-
assert.strictEqual(505, err.code);
|
|
215
|
-
assert.strictEqual(60, err.classId);
|
|
216
|
-
assert.strictEqual(72, err.methodId);
|
|
217
|
-
decrementLatch();
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
open(ch).then(() => {
|
|
221
|
-
ch._rpc(defs.BasicRecover, { requeue: true }, defs.BasicRecoverOk, (err) => {
|
|
222
|
-
assert.match(err.message, /Expected BasicRecoverOk; got <BasicGetEmpty channel:1>/);
|
|
223
|
-
decrementLatch();
|
|
224
|
-
});
|
|
225
|
-
}, decrementLatch);
|
|
226
|
-
},
|
|
227
|
-
(send, wait, cb, ch) =>
|
|
228
|
-
wait()()
|
|
229
|
-
.then(() => send(defs.BasicGetEmpty, { clusterId: '' }, ch))
|
|
230
|
-
// oh wait! that was wrong! expect a channel close
|
|
231
|
-
.then(wait(defs.ChannelClose))
|
|
232
|
-
.then(() => send(defs.ChannelCloseOk, {}, ch))
|
|
233
|
-
.then(cb),
|
|
234
|
-
));
|
|
235
|
-
|
|
236
|
-
it('RPC on closed channel', channelTest(
|
|
237
|
-
(ch, cb) => {
|
|
238
|
-
open(ch);
|
|
239
|
-
|
|
240
|
-
const close = new Promise((resolve) => {
|
|
241
|
-
ch.once('error', (err) => {
|
|
242
|
-
assert.match(err.message, /Channel closed by server: 504 \(CHANNEL-ERROR\)/);
|
|
243
|
-
assert.strictEqual(504, err.code);
|
|
244
|
-
assert.strictEqual(0, err.classId);
|
|
245
|
-
assert.strictEqual(0, err.methodId);
|
|
246
|
-
resolve();
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
function failureCb(resolve, reject) {
|
|
251
|
-
return (err) => {
|
|
252
|
-
if (err !== null) resolve();
|
|
253
|
-
else reject();
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const fail1 = new Promise((resolve, reject) =>
|
|
258
|
-
ch._rpc(defs.BasicRecover, { requeue: true }, defs.BasicRecoverOk, failureCb(resolve, reject)),
|
|
259
|
-
);
|
|
260
|
-
|
|
261
|
-
const fail2 = new Promise((resolve, reject) =>
|
|
262
|
-
ch._rpc(defs.BasicRecover, { requeue: true }, defs.BasicRecoverOk, failureCb(resolve, reject)),
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
Promise.all([close, fail1, fail2]).then(cb);
|
|
266
|
-
},
|
|
267
|
-
(send, wait, cb, ch) => {
|
|
268
|
-
wait(defs.BasicRecover)()
|
|
269
|
-
.then(() => {
|
|
270
|
-
send(defs.ChannelClose, {
|
|
271
|
-
replyText: 'Nuh-uh!',
|
|
272
|
-
replyCode: defs.constants.CHANNEL_ERROR,
|
|
273
|
-
methodId: 0,
|
|
274
|
-
classId: 0,
|
|
275
|
-
}, ch);
|
|
276
|
-
return wait(defs.ChannelCloseOk);
|
|
277
|
-
})
|
|
278
|
-
.then(cb);
|
|
279
|
-
},
|
|
280
|
-
));
|
|
281
|
-
|
|
282
|
-
it('publish all < single chunk threshold', channelTest(
|
|
283
|
-
(ch, cb) => {
|
|
284
|
-
open(ch)
|
|
285
|
-
.then(() => {
|
|
286
|
-
ch.sendMessage({
|
|
287
|
-
exchange: 'foo',
|
|
288
|
-
routingKey: 'bar',
|
|
289
|
-
mandatory: false,
|
|
290
|
-
immediate: false,
|
|
291
|
-
ticket: 0,
|
|
292
|
-
}, {}, Buffer.from('foobar'));
|
|
293
|
-
})
|
|
294
|
-
.then(cb);
|
|
295
|
-
},
|
|
296
|
-
(_send, wait, cb, _ch) => {
|
|
297
|
-
wait(defs.BasicPublish)()
|
|
298
|
-
.then(wait(defs.BasicProperties))
|
|
299
|
-
.then(wait()) // content frame
|
|
300
|
-
.then((f) => {
|
|
301
|
-
assert.equal('foobar', f.content.toString());
|
|
302
|
-
})
|
|
303
|
-
.then(cb);
|
|
304
|
-
},
|
|
305
|
-
));
|
|
306
|
-
|
|
307
|
-
it('publish content > single chunk threshold', channelTest(
|
|
308
|
-
(ch, cb) => {
|
|
309
|
-
open(ch);
|
|
310
|
-
completes(() => {
|
|
311
|
-
ch.sendMessage(
|
|
312
|
-
{
|
|
313
|
-
exchange: 'foo',
|
|
314
|
-
routingKey: 'bar',
|
|
315
|
-
mandatory: false,
|
|
316
|
-
immediate: false,
|
|
317
|
-
ticket: 0,
|
|
318
|
-
},
|
|
319
|
-
{},
|
|
320
|
-
Buffer.alloc(3000),
|
|
321
|
-
);
|
|
322
|
-
}, cb);
|
|
323
|
-
}, (_send, wait, cb, _ch) => {
|
|
324
|
-
wait(defs.BasicPublish)()
|
|
325
|
-
.then(wait(defs.BasicProperties))
|
|
326
|
-
.then(wait()) // content frame
|
|
327
|
-
.then((f) => {
|
|
328
|
-
assert.equal(3000, f.content.length);
|
|
329
|
-
})
|
|
330
|
-
.then(cb);
|
|
331
|
-
}
|
|
332
|
-
));
|
|
333
|
-
|
|
334
|
-
it('publish method & headers > threshold', channelTest(
|
|
335
|
-
(ch, cb) => {
|
|
336
|
-
open(ch);
|
|
337
|
-
completes(() => {
|
|
338
|
-
ch.sendMessage({
|
|
339
|
-
exchange: 'foo',
|
|
340
|
-
routingKey: 'bar',
|
|
341
|
-
mandatory: false,
|
|
342
|
-
immediate: false,
|
|
343
|
-
ticket: 0,
|
|
344
|
-
}, {
|
|
345
|
-
headers: { foo: Buffer.alloc(3000) },
|
|
346
|
-
}, Buffer.from('foobar'));
|
|
347
|
-
}, cb);
|
|
348
|
-
}, (_send, wait, cb, _ch) => {
|
|
349
|
-
wait(defs.BasicPublish)()
|
|
350
|
-
.then(wait(defs.BasicProperties))
|
|
351
|
-
.then(wait()) // content frame
|
|
352
|
-
.then((f) => {
|
|
353
|
-
assert.equal('foobar', f.content.toString());
|
|
354
|
-
})
|
|
355
|
-
.then(cb);
|
|
356
|
-
}
|
|
357
|
-
));
|
|
358
|
-
|
|
359
|
-
it('publish zero-length message', channelTest((ch, cb) => {
|
|
360
|
-
open(ch);
|
|
361
|
-
completes(() => {
|
|
362
|
-
ch.sendMessage({
|
|
363
|
-
exchange: 'foo',
|
|
364
|
-
routingKey: 'bar',
|
|
365
|
-
mandatory: false,
|
|
366
|
-
immediate: false,
|
|
367
|
-
ticket: 0,
|
|
368
|
-
}, {}, Buffer.alloc(0));
|
|
369
|
-
ch.sendMessage({
|
|
370
|
-
exchange: 'foo',
|
|
371
|
-
routingKey: 'bar',
|
|
372
|
-
mandatory: false,
|
|
373
|
-
immediate: false,
|
|
374
|
-
ticket: 0,
|
|
375
|
-
}, {}, Buffer.alloc(0));
|
|
376
|
-
}, cb);
|
|
377
|
-
}, (_send, wait, cb, _ch) => {
|
|
378
|
-
wait(defs.BasicPublish)()
|
|
379
|
-
.then(wait(defs.BasicProperties))
|
|
380
|
-
// no content frame for a zero-length message
|
|
381
|
-
.then(wait(defs.BasicPublish))
|
|
382
|
-
.then(cb);
|
|
383
|
-
}));
|
|
384
|
-
|
|
385
|
-
it('delivery', channelTest((ch, cb) => {
|
|
386
|
-
open(ch);
|
|
387
|
-
ch.on('delivery', (m) => {
|
|
388
|
-
completes(() => {
|
|
389
|
-
assert.equal('barfoo', m.content.toString());
|
|
390
|
-
}, cb);
|
|
391
|
-
});
|
|
392
|
-
}, (send, _wait, cb, ch) => {
|
|
393
|
-
completes(() => {
|
|
394
|
-
send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('barfoo'));
|
|
395
|
-
}, cb);
|
|
396
|
-
}));
|
|
397
|
-
|
|
398
|
-
it('zero byte msg', channelTest(
|
|
399
|
-
(ch, cb) => {
|
|
400
|
-
open(ch);
|
|
401
|
-
ch.on('delivery', (m) => {
|
|
402
|
-
completes(() => {
|
|
403
|
-
assert.deepEqual(Buffer.alloc(0), m.content);
|
|
404
|
-
}, cb);
|
|
405
|
-
});
|
|
406
|
-
},
|
|
407
|
-
(send, _wait, cb, ch) => {
|
|
408
|
-
completes(() => {
|
|
409
|
-
send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from(''));
|
|
410
|
-
}, cb);
|
|
411
|
-
}
|
|
412
|
-
));
|
|
413
|
-
|
|
414
|
-
it('bad delivery', channelTest((ch, cb) => {
|
|
415
|
-
const decrementLatch = latch(2, cb);
|
|
416
|
-
ch.on('error', (err) => {
|
|
417
|
-
assert.match(err.message, /Expected headers frame after delivery/);
|
|
418
|
-
assert.strictEqual(505, err.code);
|
|
419
|
-
assert.strictEqual(60, err.classId);
|
|
420
|
-
assert.strictEqual(60, err.methodId);
|
|
421
|
-
decrementLatch();
|
|
422
|
-
});
|
|
423
|
-
ch.on('close', decrementLatch);
|
|
424
|
-
open(ch);
|
|
425
|
-
}, (send, wait, cb, ch) => {
|
|
426
|
-
send(defs.BasicDeliver, DELIVER_FIELDS, ch);
|
|
427
|
-
// now send another deliver without having sent the content
|
|
428
|
-
send(defs.BasicDeliver, DELIVER_FIELDS, ch);
|
|
429
|
-
return wait(defs.ChannelClose)()
|
|
430
|
-
.then(() => send(defs.ChannelCloseOk, {}, ch))
|
|
431
|
-
.then(cb);
|
|
432
|
-
}));
|
|
433
|
-
|
|
434
|
-
it('bad content send', channelTest((ch, cb) => {
|
|
435
|
-
completes(() => {
|
|
436
|
-
open(ch);
|
|
437
|
-
assert.throws(() => {
|
|
438
|
-
ch.sendMessage({ routingKey: 'foo', exchange: 'amq.direct' }, {}, null);
|
|
439
|
-
}, (err) => {
|
|
440
|
-
assert.match(err.message, /content is not a buffer/);
|
|
441
|
-
return true;
|
|
442
|
-
});
|
|
443
|
-
}, cb);
|
|
444
|
-
}, (_send, _wait, cb, _ch) => cb()));
|
|
445
|
-
|
|
446
|
-
it('bad properties send', channelTest((ch, cb) => {
|
|
447
|
-
completes(() => {
|
|
448
|
-
open(ch);
|
|
449
|
-
assert.throws(() => {
|
|
450
|
-
ch.sendMessage({ routingKey: 'foo', exchange: 'amq.direct' }, { contentEncoding: 7 }, Buffer.from('foobar'));
|
|
451
|
-
}, (err) => {
|
|
452
|
-
assert.match(err.message, /Field 'contentEncoding' is the wrong type/);
|
|
453
|
-
return true;
|
|
454
|
-
});
|
|
455
|
-
}, cb);
|
|
456
|
-
}, (_send, _wait, cb, _ch) => cb()));
|
|
457
|
-
|
|
458
|
-
it('bad consumer', channelTest((ch, cb) => {
|
|
459
|
-
const decrementLatch = latch(2, cb);
|
|
460
|
-
ch.on('delivery', () => {
|
|
461
|
-
throw new Error('I am a bad consumer');
|
|
462
|
-
});
|
|
463
|
-
ch.on('error', (err) => {
|
|
464
|
-
assert.match(err.message, /I am a bad consumer/);
|
|
465
|
-
assert.strictEqual(541, err.code);
|
|
466
|
-
assert.strictEqual(undefined, err.classId);
|
|
467
|
-
assert.strictEqual(undefined, err.methodId);
|
|
468
|
-
decrementLatch();
|
|
469
|
-
});
|
|
470
|
-
ch.on('close', decrementLatch);
|
|
471
|
-
open(ch);
|
|
472
|
-
}, (send, wait, cb, ch) => {
|
|
473
|
-
send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('barfoo'));
|
|
474
|
-
return wait(defs.ChannelClose)()
|
|
475
|
-
.then(() => send(defs.ChannelCloseOk, {}, ch))
|
|
476
|
-
.then(cb);
|
|
477
|
-
}));
|
|
478
|
-
|
|
479
|
-
it('bad send in consumer', channelTest((ch, cb) => {
|
|
480
|
-
const decrementLatch = latch(2, cb);
|
|
481
|
-
ch.on('delivery', () => {
|
|
482
|
-
ch.sendMessage({ routingKey: 'foo', exchange: 'amq.direct' }, {}, null); // can't send null
|
|
483
|
-
});
|
|
484
|
-
ch.on('error', (err) => {
|
|
485
|
-
assert.match(err.message, /content is not a buffer/);
|
|
486
|
-
assert.strictEqual(541, err.code);
|
|
487
|
-
assert.strictEqual(undefined, err.classId);
|
|
488
|
-
assert.strictEqual(undefined, err.methodId);
|
|
489
|
-
decrementLatch();
|
|
490
|
-
});
|
|
491
|
-
ch.on('close', decrementLatch);
|
|
492
|
-
open(ch);
|
|
493
|
-
}, (send, wait, cb, ch) => {
|
|
494
|
-
const decrementLatch = latch(2, cb);
|
|
495
|
-
completes(() => {
|
|
496
|
-
send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('barfoo'));
|
|
497
|
-
}, decrementLatch);
|
|
498
|
-
return wait(defs.ChannelClose)()
|
|
499
|
-
.then(() => send(defs.ChannelCloseOk, {}, ch))
|
|
500
|
-
.then(decrementLatch);
|
|
501
|
-
}));
|
|
502
|
-
|
|
503
|
-
it('return', channelTest((ch, cb) => {
|
|
504
|
-
ch.on('return', (m) => {
|
|
505
|
-
completes(() => {
|
|
506
|
-
assert.equal('barfoo', m.content.toString());
|
|
507
|
-
}, cb);
|
|
508
|
-
});
|
|
509
|
-
open(ch);
|
|
510
|
-
}, (send, _wait, cb, ch) => {
|
|
511
|
-
completes(() => {
|
|
512
|
-
send(defs.BasicReturn, DELIVER_FIELDS, ch, Buffer.from('barfoo'));
|
|
513
|
-
}, cb);
|
|
514
|
-
}));
|
|
515
|
-
|
|
516
|
-
it('cancel', channelTest((ch, cb) => {
|
|
517
|
-
ch.on('cancel', (f) => {
|
|
518
|
-
completes(() => {
|
|
519
|
-
assert.equal('product of society', f.consumerTag);
|
|
520
|
-
}, cb);
|
|
521
|
-
});
|
|
522
|
-
open(ch);
|
|
523
|
-
}, (send, _wait, cb, ch) => {
|
|
524
|
-
completes(() => {
|
|
525
|
-
send(defs.BasicCancel, {
|
|
526
|
-
consumerTag: 'product of society',
|
|
527
|
-
nowait: false,
|
|
528
|
-
}, ch);
|
|
529
|
-
}, cb);
|
|
530
|
-
}));
|
|
531
|
-
|
|
532
|
-
function confirmTest(variety, method) {
|
|
533
|
-
return it(`confirm ${variety}`, channelTest((ch, done) => {
|
|
534
|
-
ch.on(variety, (f) => {
|
|
535
|
-
completes(() => {
|
|
536
|
-
assert.equal(1, f.deliveryTag);
|
|
537
|
-
}, done);
|
|
538
|
-
});
|
|
539
|
-
open(ch);
|
|
540
|
-
}, (send, _wait, done, ch) => {
|
|
541
|
-
completes(() => {
|
|
542
|
-
send(method, {
|
|
543
|
-
deliveryTag: 1,
|
|
544
|
-
multiple: false,
|
|
545
|
-
}, ch);
|
|
546
|
-
}, done);
|
|
547
|
-
}));
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
confirmTest('ack', defs.BasicAck);
|
|
551
|
-
confirmTest('nack', defs.BasicNack);
|
|
552
|
-
|
|
553
|
-
it('out-of-order acks', channelTest((ch, cb) => {
|
|
554
|
-
const decrementLatch = latch(3, () => {
|
|
555
|
-
completes(() => {
|
|
556
|
-
assert.equal(0, ch.unconfirmed.length);
|
|
557
|
-
assert.equal(4, ch.lwm);
|
|
558
|
-
}, cb);
|
|
559
|
-
});
|
|
560
|
-
ch.pushConfirmCallback(decrementLatch);
|
|
561
|
-
ch.pushConfirmCallback(decrementLatch);
|
|
562
|
-
ch.pushConfirmCallback(decrementLatch);
|
|
563
|
-
open(ch);
|
|
564
|
-
}, (send, _wait, cb, ch) => {
|
|
565
|
-
completes(() => {
|
|
566
|
-
send(defs.BasicAck, { deliveryTag: 2, multiple: false }, ch);
|
|
567
|
-
send(defs.BasicAck, { deliveryTag: 3, multiple: false }, ch);
|
|
568
|
-
send(defs.BasicAck, { deliveryTag: 1, multiple: false }, ch);
|
|
569
|
-
}, cb);
|
|
570
|
-
}));
|
|
571
|
-
|
|
572
|
-
it('not all out-of-order acks', channelTest((ch, cb) => {
|
|
573
|
-
const decrementLatch = latch(2, () => {
|
|
574
|
-
completes(() => {
|
|
575
|
-
assert.equal(1, ch.unconfirmed.length);
|
|
576
|
-
assert.equal(3, ch.lwm);
|
|
577
|
-
}, cb);
|
|
578
|
-
});
|
|
579
|
-
ch.pushConfirmCallback(decrementLatch); // tag = 1
|
|
580
|
-
ch.pushConfirmCallback(decrementLatch); // tag = 2
|
|
581
|
-
ch.pushConfirmCallback(() => {
|
|
582
|
-
assert.fail('Confirm callback should not be called');
|
|
583
|
-
});
|
|
584
|
-
open(ch);
|
|
585
|
-
}, (send, _wait, cb, ch) => {
|
|
586
|
-
completes(() => {
|
|
587
|
-
send(defs.BasicAck, { deliveryTag: 2, multiple: false }, ch);
|
|
588
|
-
send(defs.BasicAck, { deliveryTag: 1, multiple: false }, ch);
|
|
589
|
-
}, cb);
|
|
590
|
-
}));
|
|
591
|
-
|
|
592
|
-
// Regression test for https://github.com/amqp-node/amqplib/issues/191
|
|
593
|
-
// pushConfirmCallback stores `false` for publishes with no callback.
|
|
594
|
-
// The close drain used `while (cb)` which stops at the first `false`,
|
|
595
|
-
// silently dropping all callbacks that follow it.
|
|
596
|
-
it('invokes all pending callbacks on close even when some publishes had no callback', channelTest((ch, cb) => {
|
|
597
|
-
let called = 0;
|
|
598
|
-
const countErr = (err) => { if (err) called++; };
|
|
599
|
-
ch.pushConfirmCallback(countErr); // tag = 1 — has callback
|
|
600
|
-
ch.pushConfirmCallback(null); // tag = 2 — no callback, stored as `false`
|
|
601
|
-
ch.pushConfirmCallback(countErr); // tag = 3 — has callback, dropped by while(cb) bug
|
|
602
|
-
open(ch).then(() => {
|
|
603
|
-
ch.toClosed('test close');
|
|
604
|
-
completes(() => {
|
|
605
|
-
assert.equal(2, called);
|
|
606
|
-
}, cb);
|
|
607
|
-
}, cb);
|
|
608
|
-
}, (_send, _wait, cb) => {
|
|
609
|
-
cb();
|
|
610
|
-
}));
|
|
611
|
-
});
|
|
612
|
-
|
|
613
|
-
describe('Event handler errors - without handler-error listener', () => {
|
|
614
|
-
let prevUncaughtExceptionListeners;
|
|
615
|
-
|
|
616
|
-
beforeEach(() => {
|
|
617
|
-
prevUncaughtExceptionListeners = process.rawListeners('uncaughtException').slice();
|
|
618
|
-
process.removeAllListeners('uncaughtException');
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
afterEach(() => {
|
|
622
|
-
prevUncaughtExceptionListeners.forEach((h) => process.on('uncaughtException', h));
|
|
623
|
-
});
|
|
624
|
-
|
|
625
|
-
it('throw in close handler kills the connection without handler-error listener', channelTest((ch, cb, conn) => {
|
|
626
|
-
const expectedErr = new Error('user close handler explodes');
|
|
627
|
-
let connErrorSeen = false;
|
|
628
|
-
// The throw propagates to acceptLoop → frameError → onSocketError → connection.emit('error')
|
|
629
|
-
conn.on('error', (err) => {
|
|
630
|
-
assert.strictEqual(err, expectedErr);
|
|
631
|
-
connErrorSeen = true;
|
|
632
|
-
});
|
|
633
|
-
// The ChannelCloseOk buffered before the kill is flushed by the mux after the
|
|
634
|
-
// stream is ended, producing ERR_STREAM_PUSH_AFTER_EOF. Absorb it and use it
|
|
635
|
-
// as the signal to end the test, since it fires after the conn error.
|
|
636
|
-
process.once('uncaughtException', (err) => {
|
|
637
|
-
assert.strictEqual(err.code, 'ERR_STREAM_PUSH_AFTER_EOF');
|
|
638
|
-
assert.ok(connErrorSeen);
|
|
639
|
-
cb();
|
|
640
|
-
});
|
|
641
|
-
ch.once('error', (err) => { assert.match(err.message, /Channel closed by server/); });
|
|
642
|
-
ch.on('close', () => { throw expectedErr; });
|
|
643
|
-
open(ch);
|
|
644
|
-
}, (send, _wait, cb, ch) => {
|
|
645
|
-
completes(() => {
|
|
646
|
-
send(defs.ChannelClose, {
|
|
647
|
-
replyText: 'Forced close',
|
|
648
|
-
replyCode: defs.constants.CHANNEL_ERROR,
|
|
649
|
-
classId: 0,
|
|
650
|
-
methodId: 0,
|
|
651
|
-
}, ch);
|
|
652
|
-
}, cb);
|
|
653
|
-
}));
|
|
654
|
-
|
|
655
|
-
it('throw in error handler becomes uncaught exception', channelTest((ch, cb) => {
|
|
656
|
-
const expectedErr = new Error('user error handler explodes');
|
|
657
|
-
process.once('uncaughtException', (err) => {
|
|
658
|
-
assert.strictEqual(err, expectedErr);
|
|
659
|
-
cb();
|
|
660
|
-
});
|
|
661
|
-
ch.on('error', () => { throw expectedErr; });
|
|
662
|
-
open(ch);
|
|
663
|
-
}, (send, wait, cb, ch) => {
|
|
664
|
-
send(defs.ChannelClose, {
|
|
665
|
-
replyText: 'Forced close',
|
|
666
|
-
replyCode: defs.constants.CHANNEL_ERROR,
|
|
667
|
-
classId: 0,
|
|
668
|
-
methodId: 0,
|
|
669
|
-
}, ch);
|
|
670
|
-
wait(defs.ChannelCloseOk)().then(cb, cb);
|
|
671
|
-
}));
|
|
672
|
-
|
|
673
|
-
it('throw in drain handler becomes uncaught exception', channelTest((ch, cb) => {
|
|
674
|
-
const expectedErr = new Error('user drain handler explodes');
|
|
675
|
-
process.once('uncaughtException', (err) => {
|
|
676
|
-
assert.strictEqual(err, expectedErr);
|
|
677
|
-
cb();
|
|
678
|
-
});
|
|
679
|
-
ch.on('drain', () => { throw expectedErr; });
|
|
680
|
-
// Call outside a Promise chain so the throw becomes an uncaughtException
|
|
681
|
-
open(ch).then(() => setImmediate(() => ch.onBufferDrain()));
|
|
682
|
-
}, (_send, _wait, cb) => { cb(); }));
|
|
683
|
-
|
|
684
|
-
it('throw in ack handler becomes uncaught exception', channelTest((ch, cb) => {
|
|
685
|
-
const expectedErr = new Error('user ack handler explodes');
|
|
686
|
-
process.once('uncaughtException', (err) => {
|
|
687
|
-
assert.strictEqual(err, expectedErr);
|
|
688
|
-
cb();
|
|
689
|
-
});
|
|
690
|
-
ch.on('ack', () => { throw expectedErr; });
|
|
691
|
-
open(ch);
|
|
692
|
-
}, (send, _wait, cb, ch) => {
|
|
693
|
-
completes(() => {
|
|
694
|
-
send(defs.BasicAck, { deliveryTag: 1, multiple: false }, ch);
|
|
695
|
-
}, cb);
|
|
696
|
-
}));
|
|
697
|
-
|
|
698
|
-
it('throw in nack handler becomes uncaught exception', channelTest((ch, cb) => {
|
|
699
|
-
const expectedErr = new Error('user nack handler explodes');
|
|
700
|
-
process.once('uncaughtException', (err) => {
|
|
701
|
-
assert.strictEqual(err, expectedErr);
|
|
702
|
-
cb();
|
|
703
|
-
});
|
|
704
|
-
ch.on('nack', () => { throw expectedErr; });
|
|
705
|
-
open(ch);
|
|
706
|
-
}, (send, _wait, cb, ch) => {
|
|
707
|
-
completes(() => {
|
|
708
|
-
send(defs.BasicNack, { deliveryTag: 1, multiple: false, requeue: false }, ch);
|
|
709
|
-
}, cb);
|
|
710
|
-
}));
|
|
711
|
-
|
|
712
|
-
it('throw in cancel handler becomes uncaught exception', channelTest((ch, cb) => {
|
|
713
|
-
const expectedErr = new Error('user cancel handler explodes');
|
|
714
|
-
process.once('uncaughtException', (err) => {
|
|
715
|
-
assert.strictEqual(err, expectedErr);
|
|
716
|
-
cb();
|
|
717
|
-
});
|
|
718
|
-
ch.on('cancel', () => { throw expectedErr; });
|
|
719
|
-
open(ch);
|
|
720
|
-
}, (send, _wait, cb, ch) => {
|
|
721
|
-
completes(() => {
|
|
722
|
-
send(defs.BasicCancel, { consumerTag: 'tag', nowait: false }, ch);
|
|
723
|
-
}, cb);
|
|
724
|
-
}));
|
|
725
|
-
|
|
726
|
-
it('throw in delivery handler closes channel with error', channelTest((ch, cb) => {
|
|
727
|
-
// acceptMessageFrame catches the throw and routes it to closeWithError,
|
|
728
|
-
// which fires channel 'error' then 'close' — it does NOT become an uncaughtException.
|
|
729
|
-
const expectedErr = new Error('user delivery handler explodes');
|
|
730
|
-
const decrementLatch = latch(2, cb);
|
|
731
|
-
ch.on('error', (err) => {
|
|
732
|
-
assert.strictEqual(err, expectedErr);
|
|
733
|
-
decrementLatch();
|
|
734
|
-
});
|
|
735
|
-
ch.on('close', decrementLatch);
|
|
736
|
-
ch.on('delivery', () => { throw expectedErr; });
|
|
737
|
-
open(ch);
|
|
738
|
-
}, (send, wait, cb, ch) => {
|
|
739
|
-
send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('hello'));
|
|
740
|
-
wait(defs.ChannelClose)()
|
|
741
|
-
.then(() => send(defs.ChannelCloseOk, {}, ch))
|
|
742
|
-
.then(cb, cb);
|
|
743
|
-
}));
|
|
744
|
-
|
|
745
|
-
it('throw in return handler closes channel with error', channelTest((ch, cb) => {
|
|
746
|
-
// acceptMessageFrame catches the throw and routes it to closeWithError.
|
|
747
|
-
const expectedErr = new Error('user return handler explodes');
|
|
748
|
-
const decrementLatch = latch(2, cb);
|
|
749
|
-
ch.on('error', (err) => {
|
|
750
|
-
assert.strictEqual(err, expectedErr);
|
|
751
|
-
decrementLatch();
|
|
752
|
-
});
|
|
753
|
-
ch.on('close', decrementLatch);
|
|
754
|
-
ch.on('return', () => { throw expectedErr; });
|
|
755
|
-
open(ch);
|
|
756
|
-
}, (send, wait, cb, ch) => {
|
|
757
|
-
send(defs.BasicReturn, DELIVER_FIELDS, ch, Buffer.from('hello'));
|
|
758
|
-
wait(defs.ChannelClose)()
|
|
759
|
-
.then(() => send(defs.ChannelCloseOk, {}, ch))
|
|
760
|
-
.then(cb, cb);
|
|
761
|
-
}));
|
|
762
|
-
});
|
|
763
|
-
|
|
764
|
-
describe('Event handler errors - with handler-error listener', () => {
|
|
765
|
-
let prevUncaughtExceptionListeners;
|
|
766
|
-
|
|
767
|
-
beforeEach(() => {
|
|
768
|
-
prevUncaughtExceptionListeners = process.rawListeners('uncaughtException').slice();
|
|
769
|
-
process.removeAllListeners('uncaughtException');
|
|
770
|
-
});
|
|
771
|
-
|
|
772
|
-
afterEach(() => {
|
|
773
|
-
prevUncaughtExceptionListeners.forEach((h) => process.on('uncaughtException', h));
|
|
774
|
-
});
|
|
775
|
-
|
|
776
|
-
it('throw in close handler is delivered via handler-error event', channelTest((ch, cb) => {
|
|
777
|
-
const expectedErr = new Error('user close handler explodes');
|
|
778
|
-
ch.on('handler-error', (err, event) => {
|
|
779
|
-
assert.strictEqual(err, expectedErr);
|
|
780
|
-
assert.strictEqual(event, 'close');
|
|
781
|
-
cb();
|
|
782
|
-
});
|
|
783
|
-
// A server-initiated ChannelClose always fires 'error' before 'close' (line 291 in channel.js).
|
|
784
|
-
// Handle it so only the throw from the close handler reaches handler-error.
|
|
785
|
-
ch.once('error', (err) => { assert.match(err.message, /Channel closed by server/); });
|
|
786
|
-
ch.on('close', () => { throw expectedErr; });
|
|
787
|
-
open(ch);
|
|
788
|
-
}, (send, wait, cb, ch) => {
|
|
789
|
-
send(defs.ChannelClose, {
|
|
790
|
-
replyText: 'Forced close',
|
|
791
|
-
replyCode: defs.constants.CHANNEL_ERROR,
|
|
792
|
-
classId: 0,
|
|
793
|
-
methodId: 0,
|
|
794
|
-
}, ch);
|
|
795
|
-
wait(defs.ChannelCloseOk)().then(cb, cb);
|
|
796
|
-
}));
|
|
797
|
-
|
|
798
|
-
it('throw in error handler is delivered via handler-error event', channelTest((ch, cb) => {
|
|
799
|
-
const expectedErr = new Error('user error handler explodes');
|
|
800
|
-
ch.on('handler-error', (err, event) => {
|
|
801
|
-
assert.strictEqual(err, expectedErr);
|
|
802
|
-
assert.strictEqual(event, 'error');
|
|
803
|
-
cb();
|
|
804
|
-
});
|
|
805
|
-
ch.on('error', () => { throw expectedErr; });
|
|
806
|
-
open(ch);
|
|
807
|
-
}, (send, wait, cb, ch) => {
|
|
808
|
-
send(defs.ChannelClose, {
|
|
809
|
-
replyText: 'Forced close',
|
|
810
|
-
replyCode: defs.constants.CHANNEL_ERROR,
|
|
811
|
-
classId: 0,
|
|
812
|
-
methodId: 0,
|
|
813
|
-
}, ch);
|
|
814
|
-
wait(defs.ChannelCloseOk)().then(cb, cb);
|
|
815
|
-
}));
|
|
816
|
-
|
|
817
|
-
it('throw in drain handler is delivered via handler-error event', channelTest((ch, cb) => {
|
|
818
|
-
const expectedErr = new Error('user drain handler explodes');
|
|
819
|
-
ch.on('handler-error', (err, event) => {
|
|
820
|
-
assert.strictEqual(err, expectedErr);
|
|
821
|
-
assert.strictEqual(event, 'drain');
|
|
822
|
-
cb();
|
|
823
|
-
});
|
|
824
|
-
ch.on('drain', () => { throw expectedErr; });
|
|
825
|
-
open(ch).then(() => setImmediate(() => ch.onBufferDrain()));
|
|
826
|
-
}, (_send, _wait, cb) => { cb(); }));
|
|
827
|
-
|
|
828
|
-
it('throw in ack handler is delivered via handler-error event', channelTest((ch, cb) => {
|
|
829
|
-
const expectedErr = new Error('user ack handler explodes');
|
|
830
|
-
ch.on('handler-error', (err, event) => {
|
|
831
|
-
assert.strictEqual(err, expectedErr);
|
|
832
|
-
assert.strictEqual(event, 'ack');
|
|
833
|
-
cb();
|
|
834
|
-
});
|
|
835
|
-
ch.on('ack', () => { throw expectedErr; });
|
|
836
|
-
open(ch);
|
|
837
|
-
}, (send, _wait, cb, ch) => {
|
|
838
|
-
completes(() => {
|
|
839
|
-
send(defs.BasicAck, { deliveryTag: 1, multiple: false }, ch);
|
|
840
|
-
}, cb);
|
|
841
|
-
}));
|
|
842
|
-
|
|
843
|
-
it('throw in nack handler is delivered via handler-error event', channelTest((ch, cb) => {
|
|
844
|
-
const expectedErr = new Error('user nack handler explodes');
|
|
845
|
-
ch.on('handler-error', (err, event) => {
|
|
846
|
-
assert.strictEqual(err, expectedErr);
|
|
847
|
-
assert.strictEqual(event, 'nack');
|
|
848
|
-
cb();
|
|
849
|
-
});
|
|
850
|
-
ch.on('nack', () => { throw expectedErr; });
|
|
851
|
-
open(ch);
|
|
852
|
-
}, (send, _wait, cb, ch) => {
|
|
853
|
-
completes(() => {
|
|
854
|
-
send(defs.BasicNack, { deliveryTag: 1, multiple: false, requeue: false }, ch);
|
|
855
|
-
}, cb);
|
|
856
|
-
}));
|
|
857
|
-
|
|
858
|
-
it('throw in cancel handler is delivered via handler-error event', channelTest((ch, cb) => {
|
|
859
|
-
const expectedErr = new Error('user cancel handler explodes');
|
|
860
|
-
ch.on('handler-error', (err, event) => {
|
|
861
|
-
assert.strictEqual(err, expectedErr);
|
|
862
|
-
assert.strictEqual(event, 'cancel');
|
|
863
|
-
cb();
|
|
864
|
-
});
|
|
865
|
-
ch.on('cancel', () => { throw expectedErr; });
|
|
866
|
-
open(ch);
|
|
867
|
-
}, (send, _wait, cb, ch) => {
|
|
868
|
-
completes(() => {
|
|
869
|
-
send(defs.BasicCancel, { consumerTag: 'tag', nowait: false }, ch);
|
|
870
|
-
}, cb);
|
|
871
|
-
}));
|
|
872
|
-
|
|
873
|
-
it('throw in delivery handler is delivered via handler-error event', channelTest((ch, cb) => {
|
|
874
|
-
const expectedErr = new Error('user delivery handler explodes');
|
|
875
|
-
ch.on('handler-error', (err, event) => {
|
|
876
|
-
assert.strictEqual(err, expectedErr);
|
|
877
|
-
assert.strictEqual(event, 'delivery');
|
|
878
|
-
cb();
|
|
879
|
-
});
|
|
880
|
-
ch.on('delivery', () => { throw expectedErr; });
|
|
881
|
-
open(ch);
|
|
882
|
-
}, (send, _wait, cb, ch) => {
|
|
883
|
-
completes(() => {
|
|
884
|
-
send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('hello'));
|
|
885
|
-
}, cb);
|
|
886
|
-
}));
|
|
887
|
-
|
|
888
|
-
it('throw in return handler is delivered via handler-error event', channelTest((ch, cb) => {
|
|
889
|
-
const expectedErr = new Error('user return handler explodes');
|
|
890
|
-
ch.on('handler-error', (err, event) => {
|
|
891
|
-
assert.strictEqual(err, expectedErr);
|
|
892
|
-
assert.strictEqual(event, 'return');
|
|
893
|
-
cb();
|
|
894
|
-
});
|
|
895
|
-
ch.on('return', () => { throw expectedErr; });
|
|
896
|
-
open(ch);
|
|
897
|
-
}, (send, _wait, cb, ch) => {
|
|
898
|
-
completes(() => {
|
|
899
|
-
send(defs.BasicReturn, DELIVER_FIELDS, ch, Buffer.from('hello'));
|
|
900
|
-
}, cb);
|
|
901
|
-
}));
|
|
902
|
-
|
|
903
|
-
it('throw in handler-error handler becomes uncaught exception', channelTest((ch, cb) => {
|
|
904
|
-
const expectedErr = new Error('handler-error handler explodes');
|
|
905
|
-
process.once('uncaughtException', (err) => {
|
|
906
|
-
assert.strictEqual(err, expectedErr);
|
|
907
|
-
cb();
|
|
908
|
-
});
|
|
909
|
-
ch.on('handler-error', () => { throw expectedErr; });
|
|
910
|
-
ch.on('ack', () => { throw new Error('user ack handler explodes'); });
|
|
911
|
-
open(ch);
|
|
912
|
-
}, (send, _wait, cb, ch) => {
|
|
913
|
-
completes(() => {
|
|
914
|
-
send(defs.BasicAck, { deliveryTag: 1, multiple: false }, ch);
|
|
915
|
-
}, cb);
|
|
916
|
-
}));
|
|
917
|
-
});
|
|
918
|
-
});
|