Skip to content

Commit

Permalink
feat(MockServer): add refactored MockServer
Browse files Browse the repository at this point in the history
Currently only supports response sequences, and is otherwise a
general refactoring of the existing mock_amqp.js MockServer with
the addition of promisifying the setup/teardown methods
  • Loading branch information
mbroadst committed Jul 26, 2015
1 parent 27af8aa commit 3652c5c
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 0 deletions.
59 changes: 59 additions & 0 deletions test/unit/client.test.js
@@ -0,0 +1,59 @@
'use strict';

var AMQPClient = require('../../lib').Client,
MockServer = require('./mocks').Server,

constants = require('../../lib/constants'),

SaslFrames = require('../../lib/frames/sasl_frame'),
OpenFrame = require('../../lib/frames/open_frame'),
CloseFrame = require('../../lib/frames/close_frame'),

DefaultPolicy = require('../../lib/policies/default_policy'),
AMQPError = require('../../lib/types/amqp_error'),

expect = require('chai').expect,
test = require('./test-fixture');

DefaultPolicy.connect.options.containerId = 'test';


describe('Client', function() {
describe('#connect()', function() {

beforeEach(function() {
if (!!test.server) test.server = undefined;
if (!!test.client) test.client = undefined;
test.client = new AMQPClient();
test.server = new MockServer();
return test.server.setup();
});

afterEach(function() {
if (!test.server) return;
return test.server.teardown()
.then(function() {
test.server = undefined;
});
});

it('should connect then disconnect', function() {
test.server.setResponseSequence([
constants.saslVersion,
[
new SaslFrames.SaslMechanisms(['PLAIN']),
new SaslFrames.SaslOutcome({code: constants.saslOutcomes.ok})
],
constants.amqpVersion,
new OpenFrame(DefaultPolicy.connect.options),
new CloseFrame(new AMQPError(AMQPError.ConnectionForced, 'test'))
]);

return test.client.connect(test.config.address)
.then(function() {
return test.client.disconnect();
});
});

});
});
1 change: 1 addition & 0 deletions test/unit/mocks/index.js
Expand Up @@ -2,6 +2,7 @@

module.exports = {
Client: require('./client'),
Server: require('./server'),
Connection: require('./connection'),
Session: require('./session'),
SenderLink: require('./sender_link'),
Expand Down
119 changes: 119 additions & 0 deletions test/unit/mocks/server.js
@@ -0,0 +1,119 @@
'use strict';
var _ = require('lodash'),
Promise = require('bluebird'),
BufferList = require('bl'),
net = require('net'),

debug = require('debug')('amqp10:mock:server'),

FrameBase = require('../../../lib/frames/frame'),
SaslFrame = require('../../../lib/frames/sasl_frame').SaslFrame,

tu = require('../testing_utils');


function MockServer(options) {
this._server = null;
this._client = null;
this._responses = [];

_.defaults(this, options, {
port: 4321,
serverGoesFirst: false
});
}

MockServer.prototype.setup = function() {
var self = this;
return new Promise(function(resolve, reject) {
self.server = net.createServer(function(c) {
debug('connection established');
self._client = c;

if (self.serverGoesFirst) {
self._sendNextResponse();
}

c.on('end', function() {
debug('connection terminated');
self._client = undefined;
});

c.on('data', function(d) {
self._sendNextResponse();
});
});

self.server.on('error', function(err) {
reject(err);
});

self.server.listen(self.port, function() {
debug('server listening on ' + self.port);
resolve();
});
});
};

MockServer.prototype.teardown = function() {
var self = this;
return new Promise(function(resolve, reject) {
if (!self._server) resolve();

self.server.close(function(err) {
if (!!err) return reject(err);

debug('server shutting down');
self.server = undefined;
resolve();
});
});
};

function convertSequenceFramesToBuffers(frame) {
if (frame instanceof FrameBase.AMQPFrame ||
frame instanceof SaslFrame) {
return tu.convertFrameToBuffer(frame);
} else if (Array.isArray(frame)) {
return [frame[0], convertSequenceFramesToBuffers(frame[1])];
}

return frame;
}

MockServer.prototype.setResponseSequence = function(responses) {
this._responses = responses.map(convertSequenceFramesToBuffers);
};

MockServer.prototype._sendNextResponse = function() {
var self = this,
response = this._responses.unshift();

if (Array.isArray(response)) {
response.forEach(function(r) { self._sendResponse(r); });
} else {
self._sendResponse(response);
}
};

MockServer.prototype._sendResponse = function(response) {
if (!response) {
debug('no data to send');
return;
}

if (typeof response !== 'string') {
this._client.write(response);
return;
}

switch(response) {
case 'disconnect': this._client.end(); break;
default:
this._client.write(response, 'utf8', function() {
debug('wrote: ' + response);
});
}
};

module.exports = MockServer;
12 changes: 12 additions & 0 deletions test/unit/test-fixture.js
@@ -0,0 +1,12 @@
'use strict';
var chai = require('chai');
chai.config.includeStack = true; // turn on stack traces

var config = {
address: (process.env.SERVER ? 'amqp://'+process.env.SERVER : 'amqp://localhost'),
defaultLink: 'amq.topic'
};

module.exports = {
config: config
};

0 comments on commit 3652c5c

Please sign in to comment.