diff --git a/Gruntfile.js b/Gruntfile.js index 643b29d7c64..5213af23bf7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -69,7 +69,7 @@ module.exports = function(grunt) { 'The specified tag is not supported.\n\nExample: `grunt mocha:::[section]` or `npm test -- mocha:::[section]`\n\n- Where tag can be one of default | unstable | slow | extensive (required)\n- Where suite can be one of unit | integration | functional | network (required)\n- Where section can be one of get | post | ws (optional)' ); } - return `./node_modules/.bin/_mocha --bail test/network/index.js ${filter}`; + return `./node_modules/.bin/_mocha test/network/index.js ${filter}`; } var toExecute = [tagFilter, suite, section] .filter(val => val) diff --git a/test/network/scenarios/common.js b/test/network/scenarios/common.js index 30ea29f87a9..dd573242bec 100644 --- a/test/network/scenarios/common.js +++ b/test/network/scenarios/common.js @@ -17,6 +17,9 @@ const childProcess = require('child_process'); const utils = require('../utils'); +const NODE_FINISHED_SYNC_REGEX = /Finished sync/; +const NODE_FINISHED_SYNC_TIMEOUT = 40000; + const getPeersStatus = peers => { return Promise.all( peers.map(peer => { @@ -52,7 +55,7 @@ const getAllPeers = sockets => { ); }; -module.exports = { +const common = { setMonitoringSocketsConnections: (params, configurations) => { // eslint-disable-next-line mocha/no-top-level-hooks before(done => { @@ -78,13 +81,60 @@ module.exports = { getAllPeers, stopNode: nodeName => { - return childProcess.execSync(`pm2 stop ${nodeName}`); + return new Promise((resolve, reject) => { + childProcess.exec(`node_modules/.bin/pm2 stop ${nodeName}`, err => { + if (err) { + return reject( + new Error(`Failed to stop node ${nodeName}: ${err.message}`) + ); + } + resolve(); + }); + }); }, startNode: nodeName => { - childProcess.execSync(`pm2 start ${nodeName}`); + return new Promise((resolve, reject) => { + childProcess.exec(`node_modules/.bin/pm2 start ${nodeName}`, err => { + if (err) { + return reject( + new Error(`Failed to start node ${nodeName}: ${err.message}`) + ); + } + + const pm2LogProcess = childProcess.spawn('node_modules/.bin/pm2', [ + 'logs', + nodeName, + ]); + + const nodeReadyTimeout = setTimeout(() => { + pm2LogProcess.stdout.removeAllListeners('data'); + pm2LogProcess.removeAllListeners('error'); + reject(new Error(`Failed to start node ${nodeName} before timeout`)); + }, NODE_FINISHED_SYNC_TIMEOUT); + + pm2LogProcess.once('error', err => { + clearTimeout(nodeReadyTimeout); + pm2LogProcess.stdout.removeAllListeners('data'); + reject(new Error(`Failed to start node ${nodeName}: ${err.message}`)); + }); + pm2LogProcess.stdout.on('data', data => { + const dataString = data.toString(); + // Make sure that all nodes have fully synced before we + // run the test cases. + if (NODE_FINISHED_SYNC_REGEX.test(dataString)) { + clearTimeout(nodeReadyTimeout); + pm2LogProcess.stdout.removeAllListeners('error'); + pm2LogProcess.stdout.removeAllListeners('data'); + resolve(); + } + }); + }); + }); }, restartNode: nodeName => { - return childProcess.execSync(`pm2 restart ${nodeName}`); + return common.stopNode(nodeName).then(() => { + return common.startNode(nodeName); + }); }, getNodesStatus: (sockets, cb) => { getAllPeers(sockets) @@ -109,3 +159,5 @@ module.exports = { }); }, }; + +module.exports = common; diff --git a/test/network/scenarios/p2p/peer_disconnect.js b/test/network/scenarios/p2p/peer_disconnect.js index 30b0bf69bac..c9b36d5e3d3 100644 --- a/test/network/scenarios/p2p/peer_disconnect.js +++ b/test/network/scenarios/p2p/peer_disconnect.js @@ -54,10 +54,10 @@ module.exports = function( describe('when a node is stopped', () => { before(done => { - common.stopNode('node_1'); - setTimeout(() => { - done(); - }, 2000); + common + .stopNode('node_1') + .then(done) + .catch(done); }); it(`peer manager should remove peer from the list and there should be ${EXPECTED_TOTAL_CONNECTIONS_AFTER_REMOVING_PEER} established connections from 500[0-9] ports`, done => { @@ -85,10 +85,10 @@ module.exports = function( describe('when a stopped node is started', () => { before(done => { - common.startNode('node_1'); - setTimeout(() => { - done(); - }, 2000); + common + .startNode('node_1') + .then(done) + .catch(done); }); it(`there should be ${EXPECTED_TOTAL_CONNECTIONS} established connections from 500[0-9] ports`, done => { @@ -115,24 +115,22 @@ module.exports = function( // To validate peers holding socket connection // Need to keep one peer so that we can validate // Duplicate socket connection exists or not - it('stop all the nodes in the network except node_0', done => { + it('stop all the nodes in the network except node_0', () => { + const peersPromises = []; for (let i = 1; i < TOTAL_PEERS; i++) { - common.stopNode(`node_${i}`); + peersPromises.push(common.stopNode(`node_${i}`)); } - setTimeout(() => { - console.info('Wait for nodes to be stopped'); - done(); - }, 10000); + console.info('Wait for nodes to be stopped'); + return Promise.all(peersPromises); }); - it('start all nodes that were stopped', done => { + it('start all nodes that were stopped', () => { + const peersPromises = []; for (let i = 1; i < TOTAL_PEERS; i++) { - common.startNode(`node_${i}`); + peersPromises.push(common.startNode(`node_${i}`)); } - setTimeout(() => { - console.info('Wait for nodes to be started'); - done(); - }, 10000); + console.info('Wait for nodes to be started'); + return Promise.all(peersPromises); }); describe('after all the node restarts', () => { diff --git a/test/network/scenarios/p2p/peers_blacklist.js b/test/network/scenarios/p2p/peers_blacklist.js index c6c7be47106..00c2ff251ff 100644 --- a/test/network/scenarios/p2p/peers_blacklist.js +++ b/test/network/scenarios/p2p/peers_blacklist.js @@ -82,10 +82,14 @@ module.exports = function( JSON.stringify(params.configurations[0], null, 4) ); // Restart the node to load the just changed configuration - common.restartNode('node_0'); - setTimeout(() => { - blockchainReady(done, null, null, 'http://127.0.0.1:4000'); - }, 8000); + common + .restartNode('node_0') + .then(() => { + blockchainReady(done, null, null, 'http://127.0.0.1:4000'); + }) + .catch(err => { + done(err.message); + }); }); it(`there should be ${EXPECTED_TOTAL_CONNECTIONS_AFTER_BLACKLISTING} established connections from 500[0-9] ports`, done => { @@ -153,10 +157,14 @@ module.exports = function( JSON.stringify(params.configurations[0], null, 4) ); // Restart the node to load the just changed configuration - common.restartNode('node_0'); - setTimeout(() => { - blockchainReady(done, null, null, 'http://127.0.0.1:4000'); - }, 8000); + common + .restartNode('node_0') + .then(() => { + blockchainReady(done, null, null, 'http://127.0.0.1:4000'); + }) + .catch(err => { + done(err.message); + }); }); it(`there should be ${EXPECTED_TOTAL_CONNECTIONS} established connections from 500[0-9] ports`, done => {