From ddf8fe5b1a9c750490dca98fb9ffaaf8017f87e0 Mon Sep 17 00:00:00 2001 From: Ivan Tivonenko Date: Wed, 25 Nov 2015 05:58:48 +0200 Subject: [PATCH] add unit tests for RippleAPIBroadcast --- test/broadcast-api-test.js | 62 +++++++++++++++++++++++++++++ test/mock-rippled.js | 1 + test/setup-api.js | 81 +++++++++++++++++++++++++------------- 3 files changed, 116 insertions(+), 28 deletions(-) create mode 100644 test/broadcast-api-test.js diff --git a/test/broadcast-api-test.js b/test/broadcast-api-test.js new file mode 100644 index 00000000..993d3f3d --- /dev/null +++ b/test/broadcast-api-test.js @@ -0,0 +1,62 @@ +/* eslint-disable max-nested-callbacks */ +'use strict'; +const _ = require('lodash'); +const assert = require('assert-diff'); +const setupAPI = require('./setup-api'); +const responses = require('./fixtures').responses; +const ledgerClosed = require('./fixtures/rippled/ledger-close'); +const RippleAPI = require('ripple-api').RippleAPI; +const schemaValidator = RippleAPI._PRIVATE.schemaValidator; + +function checkResult(expected, schemaName, response) { + if (expected.txJSON) { + assert(response.txJSON); + assert.deepEqual(JSON.parse(response.txJSON), JSON.parse(expected.txJSON)); + } + assert.deepEqual(_.omit(response, 'txJSON'), _.omit(expected, 'txJSON')); + if (schemaName) { + schemaValidator.schemaValidate(schemaName, response); + } + return response; +} + +describe('RippleAPIBroadcast', function() { + beforeEach(setupAPI.setupBroadcast); + afterEach(setupAPI.teardown); + + it('base', function() { + const expected = {request_server_info: 1}; + this.mocks.forEach(mock => mock.expect(_.assign({}, expected))); + assert(this.api.isConnected()); + return this.api.getServerInfo().then( + _.partial(checkResult, responses.getServerInfo, 'getServerInfo')); + }); + + it('ledger', function(done) { + let gotLedger = 0; + this.api.on('ledger', () => { + gotLedger++; + }); + const ledgerNext = _.assign({}, ledgerClosed); + ledgerNext.ledger_index++; + this.mocks.forEach(mock => mock.socket.send(JSON.stringify(ledgerNext))); + + setTimeout(() => { + console.log('-- ledgerVersion', this.api.ledgerVersion); + assert.strictEqual(gotLedger, 1); + done(); + }, 50); + + }); + + it('error propagation', function(done) { + this.api.once('error', (type, info) => { + assert.strictEqual(type, 'type'); + assert.strictEqual(info, 'info'); + done(); + }); + this.mocks[1].socket.send( + JSON.stringify({error: 'type', error_message: 'info'})); + }); + +}); diff --git a/test/mock-rippled.js b/test/mock-rippled.js index 93f22277..3b41b636 100644 --- a/test/mock-rippled.js +++ b/test/mock-rippled.js @@ -71,6 +71,7 @@ module.exports = function(port) { }; mock.on('connection', function(conn) { + this.socket = conn; conn.on('message', function(requestJSON) { const request = JSON.parse(requestJSON); mock.emit('request_' + request.command, request, conn); diff --git a/test/setup-api.js b/test/setup-api.js index 14d29446..60030cb6 100644 --- a/test/setup-api.js +++ b/test/setup-api.js @@ -1,52 +1,77 @@ 'use strict'; const net = require('net'); const RippleAPI = require('ripple-api').RippleAPI; +const RippleAPIBroadcast = require('ripple-api').RippleAPIBroadcast; const ledgerClosed = require('./fixtures/rippled/ledger-close'); const createMockRippled = require('./mock-rippled'); // using a free port instead of a constant port enables parallelization -function getFreePort(callback) { - const server = net.createServer(); - let port; - server.on('listening', function() { - port = server.address().port; - server.close(); +function getFreePort() { + return new Promise((resolve, reject) => { + const server = net.createServer(); + let port; + server.on('listening', function() { + port = server.address().port; + server.close(); + }); + server.on('close', function() { + resolve(port); + }); + server.on('error', function(error) { + reject(error); + }); + server.listen(0); }); - server.on('close', function() { - callback(null, port); - }); - server.on('error', function(error) { - callback(error); - }); - server.listen(0); } -function setupMockRippledConnection(testcase, port, done) { - testcase.mockRippled = createMockRippled(port); - testcase.api = new RippleAPI({server: 'ws://localhost:' + port}); - testcase.api.connect().then(() => { - testcase.api.once('ledger', () => done()); - testcase.api.connection._ws.emit('message', JSON.stringify(ledgerClosed)); - }).catch(done); +function setupMockRippledConnection(testcase, port) { + return new Promise((resolve, reject) => { + testcase.mockRippled = createMockRippled(port); + testcase.api = new RippleAPI({server: 'ws://localhost:' + port}); + testcase.api.connect().then(() => { + testcase.api.once('ledger', () => resolve()); + testcase.api.connection._ws.emit('message', JSON.stringify(ledgerClosed)); + }).catch(reject); + }); } -function setup(done) { - getFreePort((error, port) => { - if (error) { - throw new Error('Unable to obtain a free port: ' + error); - } - setupMockRippledConnection(this, port, done); +function setupMockRippledConnectionForBroadcast(testcase, ports) { + return new Promise((resolve, reject) => { + const servers = ports.map(port => 'ws://localhost:' + port); + testcase.mocks = ports.map(port => createMockRippled(port)); + testcase.api = new RippleAPIBroadcast(servers); + testcase.api.connect().then(() => { + testcase.api.once('ledger', () => resolve()); + testcase.mocks[0].socket.send(JSON.stringify(ledgerClosed)); + }).catch(reject); + }); +} + +function setup() { + return getFreePort().then(port => { + return setupMockRippledConnection(this, port); + }); +} + +function setupBroadcast() { + return Promise.all([getFreePort(), getFreePort()]).then(ports => { + return setupMockRippledConnectionForBroadcast(this, ports); }); } function teardown(done) { this.api.disconnect().then(() => { - this.mockRippled.close(); + if (this.mockRippled !== undefined) { + this.mockRippled.close(); + } else { + this.mocks.forEach(mock => mock.close()); + } setImmediate(done); }).catch(done); } module.exports = { setup: setup, - teardown: teardown + teardown: teardown, + setupBroadcast: setupBroadcast };