Skip to content

Commit

Permalink
test: migrate handshake and server tests
Browse files Browse the repository at this point in the history
Refs: #145
Refs: #146
Refs: #53
PR-URL: #183
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
  • Loading branch information
nechaido authored and belochub committed Jan 22, 2018
1 parent 15cf815 commit 58a7827
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 231 deletions.
46 changes: 46 additions & 0 deletions test/fixtures/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';

const jstp = require('../..');

const name = 'testApp';
const login = 'login';
const password = 'password';
const sessionId = '12892e85-5bd7-4c77-a0c5-a0aecfcbc93a';

const interfaces = {};

const authCallback = (
connection, application, strategy, credentials, callback
) => {
if (application.name !== name) {
return callback(new jstp.RemoteError(jstp.ERR_APP_NOT_FOUND));
}

let username = null;
let success = false;

if (strategy === 'anonymous') {
success = true;
}

if (strategy === 'login' &&
credentials[0] === login &&
credentials[1] === password) {
success = true;
username = login;
}

if (!success) {
callback(new jstp.RemoteError(jstp.ERR_AUTH_FAILED));
}
callback(null, username, sessionId);
};

module.exports = {
name,
interfaces,
login,
password,
sessionId,
authCallback
};
109 changes: 109 additions & 0 deletions test/node/connection-handshake.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
'use strict';

const test = require('tap');

const jstp = require('../..');

const app = require('../fixtures/application');
const application = new jstp.Application(app.name, app.interfaces);

const Transport = require('../unit/mock/transport');

let server;
let client;

test.beforeEach((done) => {
server = jstp.tcp.createServer(0, [application], app.authCallback);
server.listen(() => {
const port = server.address().port;
client = jstp.tcp.createClient({ host: 'localhost', port });
done();
});
});

test.afterEach((done) => {
if (client.connection) {
client.disconnect();
}
server.close();
done();
});

test.test('must perform a handshake', (test) => {
client.connect((error, connection) => {
test.assertNot(error, 'must connect to server');
connection.handshake(app.name, null, null, (error, sessionId) => {
test.assertNot(error, 'handshake must not return an error');
test.equal(connection.username, null, 'username must be null');
test.equal(sessionId, app.sessionId,
'session id must be equal to the one provided by authCallback');
test.end();
});
});
});

test.test('must perform an anonymous handshake', (test) => {
client.connectAndHandshake(app.name, null, null, (error, connection) => {
test.assertNot(error, 'handshake must not return an error');
test.equal(connection.username, null, 'username must be null');
test.equal(connection.sessionId, app.sessionId,
'session id must be equal to the one provided by authCallback');
test.end();
});
});


test.test('must perform a handshake with credentials', (test) => {
client.connectAndHandshake(app.name, app.login, app.password,
(error, connection) => {
test.assertNot(error, 'handshake must not return an error');
test.equal(connection.username, app.login,
'username must be same as the one passed with handshake');
test.equal(connection.sessionId, app.sessionId,
'session id must be equal to the one provided by authCallback');
test.end();
}
);
});

test.test('must not perform a handshake with invalid credentials', (test) => {
client.connectAndHandshake(app.name, app.login, '__incorrect__', (error) => {
test.assert(error, 'handshake must return an error');
test.equal(error.code, jstp.ERR_AUTH_FAILED,
'error code must be ERR_AUTH_FAILED');
test.end();
});
});

test.test('must handle nonexistent application error', (test) => {
client.connectAndHandshake('nonexistentApp', null, null, (error) => {
test.assert(error, 'handshake must return an error');
test.equal(error.code, jstp.ERR_APP_NOT_FOUND,
'error code must be ERR_APP_NOT_FOUND');
test.end();
});
});

test.test('must not accept handshakes on a client', (test) => {
const transport = new Transport();

const handshake = {
handshake: [0, app.name],
};
const response = {
handshake: [0],
error: [jstp.ERR_NOT_A_SERVER]
};

transport.on('dataSent', (data) => {
test.equal(data, jstp.stringify(response),
'client must return ERR_NOT_A_SERVER');
test.end();
});

// `connection` is being used in an implicit way
// `connection._processHandshakeRequest` is being tested
// eslint-disable-next-line no-unused-vars
const connection = new jstp.Connection(transport, null, {});
transport.emitPacket(handshake);
});
189 changes: 0 additions & 189 deletions test/unit/connection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,195 +65,6 @@ describe('JSTP Connection', () => {
new jstp.Connection(clientTransportMock, null, clientMock);
});

describe('handshake', () => {
it('must send anonymous handshake from a client', () => {
chai.spy.on(clientTransportMock, 'send');

const callback = chai.spy((error, sessionId) => {
expect(error).to.not.exist;
expect(sessionId).to.equal(constants.TEST_SESSION_ID);

expect(clientConnection.username).to.be.null;
expect(clientConnection.handshakeDone).to.be.true;

clientTransportMock.send.reset();
});

clientConnection.handshake(constants.TEST_APPLICATION,
null, null, callback);

expect(clientTransportMock.send)
.to.be.called.with(jstp.stringify({
handshake: [0, constants.TEST_APPLICATION]
}));

clientTransportMock.emitPacket({
handshake: [0],
ok: constants.TEST_SESSION_ID
});

expect(callback).to.be.called();
});

it('must send authenticated handshake from a client', () => {
chai.spy.on(clientTransportMock, 'send');

const callback = chai.spy((error, sessionId) => {
expect(error).to.not.exist;
expect(sessionId).to.equal(constants.TEST_SESSION_ID);

expect(clientConnection.username).to.eql(constants.TEST_USERNAME);
expect(clientConnection.handshakeDone).to.be.true;

clientTransportMock.send.reset();
});

clientConnection.handshake(constants.TEST_APPLICATION,
constants.TEST_USERNAME, constants.TEST_PASSWORD, callback);

const handshakeRequest = {
handshake: [0, constants.TEST_APPLICATION],
login: [constants.TEST_USERNAME, constants.TEST_PASSWORD]
};

expect(clientTransportMock.send)
.to.be.called.with(jstp.stringify(handshakeRequest));

clientTransportMock.emitPacket({
handshake: [0],
ok: constants.TEST_SESSION_ID
});

expect(callback).to.be.called();
});

it('must handle inexistent application error', () => {
const callback = chai.spy((error, sessionId) => {
expect(error.code).to.equal(jstp.ERR_APP_NOT_FOUND);
expect(sessionId).to.not.exist;

expect(clientConnection.username).to.be.null;
expect(clientConnection.handshakeDone).to.be.false;
});

clientConnection.handshake('invalidApp', 'user', 'password', callback);
clientTransportMock.emitPacket({
handshake: [0],
error: [jstp.ERR_APP_NOT_FOUND]
});

expect(callback).to.be.called();
});

it('must handle authentication error', () => {
const callback = chai.spy((error, sessionId) => {
expect(error.code).to.equal(jstp.ERR_AUTH_FAILED);
expect(sessionId).to.not.exist;

expect(clientConnection.username).to.be.null;
expect(clientConnection.handshakeDone).to.be.false;
});

clientConnection.handshake(constants.TEST_APPLICATION,
constants.TEST_USERNAME, constants.TEST_PASSWORD, callback);

clientTransportMock.emitPacket({
handshake: [0],
error: [jstp.ERR_AUTH_FAILED]
});

expect(callback).to.be.called();
});

it('must process anonymous handshake packets on server', () => {
const sendSpy = chai.spy.on(serverTransportMock, 'send');
const startSessionSpy = chai.spy.on(serverMock, 'startSession');

serverTransportMock.emitPacket({
handshake: [0, constants.TEST_APPLICATION]
});

expect(sendSpy).to.have.been.called.with(jstp.stringify({
handshake: [0],
ok: constants.TEST_SESSION_ID
}));

expect(startSessionSpy).to.have.been.called.with(
serverConnection, applicationMock);

sendSpy.reset();
startSessionSpy.reset();
});

it('must process authenticated handshake packets on a server', () => {
const sendSpy = chai.spy.on(serverTransportMock, 'send');
const startSessionSpy =
chai.spy.on(serverMock, 'startSession');

const packet = {
handshake: [0, constants.TEST_APPLICATION],
login: [constants.TEST_USERNAME, constants.TEST_PASSWORD]
};

serverTransportMock.emitPacket(packet);

expect(sendSpy).to.have.been.called.with(jstp.stringify({
handshake: [0],
ok: constants.TEST_SESSION_ID
}));

expect(startSessionSpy).to.have.been.called.with(
serverConnection, applicationMock, 'login',
[constants.TEST_USERNAME, constants.TEST_PASSWORD]);

sendSpy.reset();
startSessionSpy.reset();
});

it('must process handshake packets with invalid credentials', () => {
const sendSpy = chai.spy.on(serverTransportMock, 'end');
const startSessionSpy =
chai.spy.on(serverMock, 'startSession');

const password = 'illegal password';
const packet = {
handshake: [0, constants.TEST_APPLICATION],
login: [constants.TEST_USERNAME, password]
};

serverTransportMock.emitPacket(packet);

expect(sendSpy).to.have.been.called.with(jstp.stringify({
handshake: [0],
error: [jstp.ERR_AUTH_FAILED]
}));

expect(startSessionSpy).to.have.been.called.with(
serverConnection, applicationMock, 'login',
[constants.TEST_USERNAME, password]);

sendSpy.reset();
startSessionSpy.reset();
});

it('must not process handshakes on a client', () => {
const sendSpy = chai.spy.on(clientTransportMock, 'send');

const packet = {
handshake: [0, constants.TEST_APPLICATION],
};

clientTransportMock.emitPacket(packet);

expect(sendSpy).to.have.been.called.with(jstp.stringify({
handshake: [0],
error: [jstp.ERR_NOT_A_SERVER]
}));

sendSpy.reset();
});
});

describe('inspect', () => {
const methods = Object.keys(applicationMock).
filter(key => key.startsWith('method'));
Expand Down
42 changes: 0 additions & 42 deletions test/unit/server.test.js

This file was deleted.

0 comments on commit 58a7827

Please sign in to comment.