UNPKG

amqplib

Version:

An AMQP 0-9-1 (e.g., RabbitMQ) library and client.

156 lines (132 loc) 4.87 kB
const { describe, it, afterEach } = require('node:test'); const assert = require('node:assert'); const net = require('node:net'); const connect = require('../lib/connect').connect; const defs = require('../lib/defs'); const { plain, amqplain } = require('../lib/credentials') const { latch, runServer } = require('./lib/util'); describe('Connect', () => { describe('Connect API', () => { let connection; afterEach((_t, done) => { if (connection) connection.close(() => done()) else done(); }); it('Connection refused', (_t, done) => { connect('amqp://localhost:23450', {}, (err) => { assert.strictEqual(err.code, 'ECONNREFUSED'); done(); }); }); // %% this ought to fail the promise, rather than throwing an error it('bad URL', (_t, done) => { assert.throws(() => connect('blurble'), (err) => { assert.match(err.message, /Expected amqp: or amqps: as the protocol/); return true; }); done(); }); it('wrongly typed open option', (_t, done) => { connect('amqp://localhost?frameMax=NOT_A_NUMBER', {}, (err) => { assert.match(err.message, /Field 'frameMax' is the wrong type/); done(); }); }); it('serverProperties', (_t, done) => { connect({ protocol: 'amqp', hostname: 'localhost' }, {}, (err, _connection) => { connection = _connection; assert.ifError(err); assert.equal(connection.serverProperties.product, 'RabbitMQ'); done(); }); }); it('using custom heartbeat option', (_t, done) => { connect({ heartbeat: 20 }, {}, (err, _connection) => { assert.ifError(err); connection = _connection; assert.strictEqual(connection.heartbeat, 20); done(); }); }); it('wrongly typed heartbeat option', (_t, done) => { connect('amqp://localhost?heartbeat=NOT_A_NUMBER', {}, (err) => { assert.match(err.message, /Field 'heartbeat' is the wrong type/); done(); }); }); it('using plain credentials', (_t, done) => { connect('amqp://localhost', { credentials: plain('guest', 'guest') }, (err, _connection) => { assert.ifError(err); connection = _connection; done(); }); }); it('using amqplain credentials', (_t, done) => { connect('amqp://localhost', { credentials: amqplain('guest', 'guest') }, (err, _connection) => { assert.ifError(err); connection = _connection; done(); }); }); it('ipv6', (_t, done) => { connect('amqp://[::1]', {}, (err, _connection) => { assert.ifError(err); connection = _connection; done(); }); }); it('using unsupported mechanism', (_t, done) => { const credentials = { mechanism: 'UNSUPPORTED', response: () => Buffer.from('') }; connect('amqp://localhost', { credentials }, (err) => { assert.match(err.message, /SASL mechanism UNSUPPORTED is not provided by the server/); done(); }); }); it('with a given connection timeout', (_t, done) => { const timeoutServer = net.createServer(() => { }).listen(31991); connect('amqp://localhost:31991', { timeout: 50 }, (err) => { timeoutServer.close(); assert.match(err.message, /ETIMEDOUT/); done(); }); }); }); describe('Errors on connect', () => { let server; afterEach(() => { if (server) server.close(); }); it('closes underlying connection on authentication error', (_t, done) => { const decrementLatch = latch(2, done); server = net.createServer((socket) => { socket.once('data', (protocolHeader) => { assert.deepStrictEqual(protocolHeader, Buffer.from(`AMQP${String.fromCharCode(0, 0, 9, 1)}`)); runServer(socket, (send, wait) => { send(defs.ConnectionStart, { versionMajor: 0, versionMinor: 9, serverProperties: {}, mechanisms: Buffer.from('PLAIN'), locales: Buffer.from('en_US'), }); wait(defs.ConnectionStartOk)().then(() => { send(defs.ConnectionClose, { replyCode: 403, replyText: 'ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN', classId: 0, methodId: 0, }); }); }); }); // Wait for the connection to be closed after the authentication error socket.once('end', () => decrementLatch()); }); server.listen(0); connect(`amqp://localhost:${server.address().port}`, {}, (err) => { assert.match(err.message, /Handshake terminated by server: 403 \(ACCESS-REFUSED\)/); decrementLatch(); }); }); }); });