From 825b18cf71e98cb597d8409ec2f45c70527f96e5 Mon Sep 17 00:00:00 2001 From: Nicholas Dudfield Date: Mon, 3 Nov 2014 14:07:29 +0700 Subject: [PATCH] Add bin/stop-test.js shutdown testing script: This script launches rippled repeatedly and then issues a stop command after a variable amount of time. This is to test the shutdown of the application and catch errors. --- bin/stop-test.js | 133 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 bin/stop-test.js diff --git a/bin/stop-test.js b/bin/stop-test.js new file mode 100644 index 00000000000..45aa15e2717 --- /dev/null +++ b/bin/stop-test.js @@ -0,0 +1,133 @@ +/* -------------------------------- REQUIRES -------------------------------- */ + +var child = require("child_process"); +var assert = require("assert"); + +/* --------------------------------- CONFIG --------------------------------- */ + +if (process.argv[2] == null) { + [ + 'Usage: ', + '', + ' `node bin/stop-test.js i,j [rippled_path] [rippled_conf]`', + '', + ' Launch rippled and stop it after n seconds for all n in [i, j}', + ' For all even values of n launch rippled with `--fg`', + ' For values of n where n % 3 == 0 launch rippled with `--fg`\n', + 'Examples: ', + '', + ' $ node bin/stop-test.js 5,10', + (' $ node bin/stop-test.js 1,4 ' + + 'build/clang.debug/rippled $HOME/.confs/rippled.cfg') + ] + .forEach(function(l){console.log(l)}); + + process.exit(); +} else { + var testRange = process.argv[2].split(',').map(Number); + var rippledPath = process.argv[3] || 'build/rippled' + var rippledConf = process.argv[4] || 'rippled.cfg' +} + +var options = { + env: process.env, + stdio: 'ignore' // we could dump the child io when it fails abnormally +}; + +// default args +var conf_args = ['--conf='+rippledConf]; +var start_args = conf_args.concat([/*'--net'*/]) +var stop_args = conf_args.concat(['stop']); + +/* --------------------------------- HELPERS -------------------------------- */ + +function start(args) { + return child.spawn(rippledPath, args, options); +} +function stop(rippled) { child.execFile(rippledPath, stop_args, options)} +function secs_l8r(ms, f) {setTimeout(f, ms * 1000); } + +function show_results_and_exit(results) { + console.log(JSON.stringify(results, undefined, 2)); + process.exit(); +} + +var timeTakes = function (range) { + function sumRange(n) {return (n+1) * n /2} + var ret = sumRange(range[1]); + if (range[0] > 1) { + ret = ret - sumRange(range[0] - 1) + } + var stopping = (range[1] - range[0]) * 0.5; + return ret + stopping; +} + +/* ---------------------------------- TEST ---------------------------------- */ + +console.log("Test will take ~%s seconds", timeTakes(testRange)); + +(function oneTest(n /* seconds */, results) { + if (n >= testRange[1]) { + // show_results_and_exit(results); + console.log(JSON.stringify(results, undefined, 2)); + oneTest(testRange[0], []); + return; + } + + var args = start_args; + if (n % 2 == 0) {args = args.concat(['--fg'])} + if (n % 3 == 0) {args = args.concat(['--net'])} + + var result = {args: args, alive_for: n}; + results.push(result); + + console.log("\nLaunching `%s` with `%s` for %d seconds", + rippledPath, JSON.stringify(args), n); + + rippled = start(args); + console.log("Rippled pid: %d", rippled.pid); + + // defaults + var b4StopSent = false; + var stopSent = false; + var stop_took = null; + + rippled.once('exit', function(){ + if (!stopSent && !b4StopSent) { + console.warn('\nRippled exited itself b4 stop issued'); + process.exit(); + }; + + // The io handles close AFTER exit, may have implications for + // `stdio:'inherit'` option to `child.spawn`. + rippled.once('close', function() { + result.stop_took = (+new Date() - stop_took) / 1000; // seconds + console.log("Stopping after %d seconds took %s seconds", + n, result.stop_took); + oneTest(n+1, results); + }); + }); + + secs_l8r(n, function(){ + console.log("Stopping rippled after %d seconds", n); + + // possible race here ? + // seems highly unlikely, but I was having issues at one point + b4StopSent=true; + stop_took = (+new Date()); + // when does `exit` actually get sent? + stop(); + stopSent=true; + + // Sometimes we want to attach with a debugger. + if (process.env.ABORT_TESTS_ON_STALL != null) { + // We wait 30 seconds, and if it hasn't stopped, we abort the process + secs_l8r(30, function() { + if (result.stop_took == null) { + console.log("rippled has stalled"); + process.exit(); + }; + }); + } + }) +}(testRange[0], [])); \ No newline at end of file