-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lib: emit events about connection messages
Fixes: #250 PR-URL: #252 Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com> Reviewed-By: Dmytro Nechai <nechaido@gmail.com> Reviewed-By: Timur Shemsedinov <timur.shemsedinov@gmail.com> Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
- Loading branch information
1 parent
2ccdc66
commit 575be0b
Showing
2 changed files
with
247 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
'use strict'; | ||
|
||
const test = require('tap'); | ||
const net = require('net'); | ||
|
||
const jstp = require('../..'); | ||
|
||
const app = require('../fixtures/application'); | ||
|
||
const application = new jstp.Application(app.name, app.interfaces); | ||
const serverConfig = { | ||
applications: [application], | ||
authPolicy: app.authCallback, | ||
}; | ||
|
||
let server; | ||
let connection; | ||
|
||
test.beforeEach((done) => { | ||
server = jstp.net.createServer(serverConfig); | ||
server.listen(0, () => { | ||
const port = server.address().port; | ||
jstp.net.connect(app.name, null, port, 'localhost', (error, conn) => { | ||
test.assertNot(error, 'must connect to server and perform handshake'); | ||
connection = conn; | ||
done(); | ||
}); | ||
}); | ||
}); | ||
|
||
test.afterEach((done) => { | ||
if (connection) { | ||
connection.close(); | ||
connection = null; | ||
} | ||
server.close(); | ||
done(); | ||
}); | ||
|
||
test.test('must emit server and client events upon anonymous handshake', | ||
(test) => { | ||
test.plan(7); | ||
|
||
const client = { | ||
application: new jstp.Application('jstp', {}), | ||
}; | ||
|
||
server.once('connect', (serverConnection) => { | ||
serverConnection.on('handshakeRequest', | ||
(applicationName, authStrategy) => { | ||
test.equal(applicationName, app.name, | ||
'application name must match'); | ||
test.equal(authStrategy, 'anonymous', | ||
'auth strategy must be anonymous by default'); | ||
} | ||
); | ||
}); | ||
|
||
const port = server.address().port; | ||
const socket = net.connect(port); | ||
socket.on('error', () => { | ||
test.fail('must create socket and connect to server'); | ||
}); | ||
socket.on('connect', () => { | ||
const transport = new jstp.net.Transport(socket); | ||
const connection = new jstp.Connection(transport, null, client); | ||
|
||
connection.on('handshake', (error, ok) => { | ||
test.assertNot(error, 'handshake must not return an error'); | ||
test.equal(ok, app.sessionId, | ||
'session id must be equal to the one provided by authCallback'); | ||
}); | ||
|
||
connection.handshake(app.name, null, null, (error) => { | ||
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'); | ||
connection.close(); | ||
}); | ||
}); | ||
} | ||
); | ||
|
||
test.test('must emit server and client events login authentication strategy', | ||
(test) => { | ||
test.plan(7); | ||
|
||
const client = { | ||
application: new jstp.Application('jstp', {}), | ||
}; | ||
|
||
server.once('connect', (serverConnection) => { | ||
serverConnection.on('handshakeRequest', | ||
(applicationName, authStrategy) => { | ||
test.equal(applicationName, app.name, | ||
'application name must match'); | ||
test.equal(authStrategy, 'login', | ||
'authentication strategy must be \'login\''); | ||
} | ||
); | ||
}); | ||
|
||
const port = server.address().port; | ||
const socket = net.connect(port); | ||
socket.on('error', () => { | ||
test.fail('must create socket and connect to server'); | ||
}); | ||
socket.on('connect', () => { | ||
const transport = new jstp.net.Transport(socket); | ||
const connection = new jstp.Connection(transport, null, client); | ||
|
||
connection.on('handshake', (error, ok) => { | ||
test.assertNot(error, 'handshake must not return an error'); | ||
test.equal(ok, app.sessionId, | ||
'session id must be equal to the one provided by authCallback'); | ||
}); | ||
|
||
connection.handshake(app.name, app.login, app.password, (error) => { | ||
test.assertNot(error, 'handshake must not return an error'); | ||
test.equal(connection.username, app.login, 'username must match'); | ||
test.equal(connection.sessionId, app.sessionId, | ||
'session id must be equal to the one provided by authCallback'); | ||
connection.close(); | ||
}); | ||
}); | ||
} | ||
); | ||
|
||
test.test('must emit event on call without arguments and with a return value', | ||
(test) => { | ||
test.plan(5); | ||
|
||
const iface = 'calculator'; | ||
const methodName = 'answer'; | ||
const args = []; | ||
|
||
server.getClients()[0].on('call', | ||
(actualInterfaceName, actualMethodName, actualArgs) => { | ||
test.equal(actualInterfaceName, iface, | ||
'method interface must match'); | ||
test.equal(actualMethodName, methodName, | ||
'method name must be equal to the called one'); | ||
test.strictSame(actualArgs, args, | ||
'method arguments must be equal to the passed ones'); | ||
} | ||
); | ||
|
||
connection.on('callback', (error, ok) => { | ||
test.assertNot(error, 'callMethod must not return an error'); | ||
test.strictSame(ok, [42], 'ok contents must match'); | ||
}); | ||
|
||
connection.callMethod(iface, methodName, args); | ||
} | ||
); | ||
|
||
test.test('must emit event upon inspect message', (test) => { | ||
const expectedInterfaces = Object.keys(app.interfaces); | ||
const expectedTests = expectedInterfaces.length; | ||
|
||
test.plan(expectedTests); | ||
server.getClients()[0].on('inspect', (interfaceName) => { | ||
test.assert(expectedInterfaces.includes(interfaceName), | ||
'inspect event interface must be one of expected'); | ||
}); | ||
|
||
expectedInterfaces.forEach((iface) => { | ||
connection.inspectInterface(iface); | ||
}); | ||
}); | ||
|
||
test.test('must emit messages in development mode', (test) => { | ||
test.plan(4); | ||
|
||
const clientOutgoingMessage = { call: [1, 'calculator'], answer: [] }; | ||
const serverOutgoingMessage = { callback: [1], ok: [42] }; | ||
|
||
server.getClients()[0].on('outgoingMessage', (message) => { | ||
test.strictSame(message, serverOutgoingMessage, | ||
'server outgoing message must match'); | ||
}); | ||
server.getClients()[0].on('incomingMessage', (message) => { | ||
test.strictSame(message, clientOutgoingMessage, | ||
'server incoming message must match the one sent from client'); | ||
}); | ||
connection.on('outgoingMessage', (message) => { | ||
test.strictSame(message, clientOutgoingMessage, | ||
'client outgoing message must match'); | ||
}); | ||
connection.on('incomingMessage', (message) => { | ||
test.strictSame(message, serverOutgoingMessage, | ||
'client incoming message must match the one sent from server'); | ||
}); | ||
|
||
connection.callMethod('calculator', 'answer', []); | ||
}); | ||
|
||
test.test('must emit heartbeat messages in development mode', (test) => { | ||
test.plan(2); | ||
|
||
server.getClients()[0].on('heartbeat', (message) => { | ||
test.strictSame(message, {}, 'heartbeat message must match on server side'); | ||
}); | ||
connection.on('heartbeat', (message) => { | ||
test.strictSame(message, {}, 'heartbeat message must match on client side'); | ||
}); | ||
|
||
connection.startHeartbeat(100); | ||
}); |