From 63e91f303e7dadf1b27c0e118473f5cac319a164 Mon Sep 17 00:00:00 2001 From: Andy Edwards Date: Thu, 15 Sep 2016 16:47:18 -0500 Subject: [PATCH 1/2] move all globals inside run() --- lib/supervisor.js | 544 +++++++++++++++++++++++----------------------- 1 file changed, 278 insertions(+), 266 deletions(-) diff --git a/lib/supervisor.js b/lib/supervisor.js index c4625b0..2dbdda9 100644 --- a/lib/supervisor.js +++ b/lib/supervisor.js @@ -1,33 +1,35 @@ var fs = require("fs"); var spawn = require("child_process").spawn; var path = require("path"); -var fileExtensionPattern; -var startChildProcess; -var noRestartOn = null; -var debug = true; -var verbose = false; -var restartVerbose = false; -var ignoredPaths = {}; -var ignoreSymLinks = false; -var forceWatchFlag = false; -var instantKillFlag = false; -var timestampFlag = false; -var interactive = true; -var log = console.log; -var crash_queued = false; -var harmony_default_parameters = false; -var harmony_destructuring = false; exports.run = run; function run (args) { + var fileExtensionPattern; + var startChildProcess; + var noRestartOn = null; + var debug = true; + var verbose = false; + var restartVerbose = false; + var ignoredPaths = {}; + var ignoreSymLinks = false; + var forceWatchFlag = false; + var instantKillFlag = false; + var timestampFlag = false; + var interactive = true; + var log = console.log; + var crash_queued = false; + var harmony_default_parameters = false; + var harmony_destructuring = false; + var arg, next, watch, ignore, pidFilePath, program, extensions, executor, poll_interval, debugFlag, debugBrkFlag, debugBrkFlagArg, harmony; while (arg = args.shift()) { if (arg === "--help" || arg === "-h" || arg === "-?") { return help(); } else if (arg === "--quiet" || arg === "-q") { debug = false; - log = function(){}; + log = function () { + }; } else if (arg === "--harmony") { harmony = true; } else if (arg === "--harmony_default_parameters") { @@ -58,7 +60,7 @@ function run (args) { noRestartOn = args.shift(); } else if (arg.indexOf("--debug") > -1 && arg.indexOf('--debug-brk') === -1) { debugFlag = arg; - } else if (arg.indexOf('--debug-brk')>=0) { + } else if (arg.indexOf('--debug-brk') >= 0) { debugBrkFlag = true; debugBrkFlagArg = arg; } else if (arg === "--force-watch") { @@ -93,7 +95,7 @@ function run (args) { extensions = "node,js"; if (programExt && extensions.indexOf(programExt) == -1) { // Support coffee and litcoffee extensions - if(programExt === "coffee" || programExt === "litcoffee") { + if (programExt === "coffee" || programExt === "litcoffee") { extensions += ",coffee,litcoffee"; } else { extensions += "," + programExt; @@ -130,8 +132,8 @@ function run (args) { // // verify if we have write access // - canWrite(pidFilePath, function(err) { - if ( err ) { + canWrite(pidFilePath, function (err) { + if (err) { log("Continuing..."); } else { fs.writeFileSync(pidFilePath, pid + '\n'); @@ -139,9 +141,9 @@ function run (args) { }); } - var deletePidFile = function(){ + var deletePidFile = function () { fs.exists(pidFilePath, function (exists) { - if ( exists ) { + if (exists) { log("Removing pid file"); fs.unlinkSync(pidFilePath); } else { @@ -153,14 +155,14 @@ function run (args) { try { // Pass kill signals through to child - [ "SIGTERM", "SIGINT", "SIGHUP", "SIGQUIT" ].forEach( function(signal) { + ["SIGTERM", "SIGINT", "SIGHUP", "SIGQUIT"].forEach(function (signal) { process.on(signal, function () { var child = exports.child; if (child) { - log("Received "+signal+", killing child process..."); + log("Received " + signal + ", killing child process..."); child.kill(signal); } - if (pidFilePath){ + if (pidFilePath) { deletePidFile(); } else { @@ -168,7 +170,7 @@ function run (args) { } }); }); - } catch(e) { + } catch (e) { // Windows doesn't support signals yet, so they simply don't get this handling. // https://github.com/joyent/node/issues/1553 } @@ -191,7 +193,7 @@ function run (args) { if (ignore) { log(" --ignore '" + ignore + "'"); } - if (pidFilePath){ + if (pidFilePath) { log(" --save-pid '" + pidFilePath + "'"); } log(" --extensions '" + extensions + "'"); @@ -200,22 +202,24 @@ function run (args) { // store the call to startProgramm in startChildProcess // in order to call it later - startChildProcess = function() { startProgram(program, executor); }; + startChildProcess = function () { + startProgram(program, executor); + }; // if we have a program, then run it, and restart when it crashes. // if we have a watch folder, then watch the folder for changes and restart the prog startChildProcess(); // If interaction has not been disabled, start the CLI - if(interactive) { + if (interactive) { // // Read input from stdin // var stdin = process.stdin; - stdin.setEncoding( 'utf8' ); - stdin.on('readable', function() { + stdin.setEncoding('utf8'); + stdin.on('readable', function () { var chunk = process.stdin.read(); // // Restart process when user inputs rs @@ -240,273 +244,281 @@ function run (args) { watchItems.forEach(function (watchItem) { watchItem = path.resolve(watchItem); - if ( ! ignoredPaths[watchItem] ) { + if (!ignoredPaths[watchItem]) { log("Watching directory '" + watchItem + "' for changes."); - if(interactive) { + if (interactive) { log("Press rs for restarting the process."); } - findAllWatchFiles(watchItem, function(f) { - watchGivenFile( f, poll_interval ); + findAllWatchFiles(watchItem, function (f) { + watchGivenFile(f, poll_interval); }); } }); -} // function print (m, n) { console.log(m+(!n?"\n":"")); return print; } -function print (m) { console.log(m); return print; } - -function help () { - print - ("") - ("Node Supervisor is used to restart programs when they crash.") - ("It can also be used to restart programs when a *.js file changes.") - ("") - ("Usage:") - (" supervisor [options] ") - (" supervisor [options] -- [args ...]") - ("") - ("Required:") - (" ") - (" The program to run.") - ("") - ("Options:") - (" -w|--watch ") - (" A comma-delimited list of folders or js files to watch for changes.") - (" When a change to a js file occurs, reload the program") - (" Default is '.'") - ("") - (" -i|--ignore ") - (" A comma-delimited list of folders to ignore for changes.") - (" No default") - ("") - (" --ignore-symlinks") - (" Enable symbolic links ignoring when looking for files to watch.") - ("") - (" -p|--poll-interval ") - (" How often to poll watched files for changes.") - (" Defaults to Node default.") - ("") - (" -e|--extensions ") - (" Specific file extensions to watch in addition to defaults.") - (" Used when --watch option includes folders") - (" Default is 'node,js'") - ("") - (" -x|--exec ") - (" The executable that runs the specified program.") - (" Default is 'node'") - ("") - (" --debug[=port]") - (" Start node with --debug flag. ") - ("") - (" --debug-brk[=port]") - (" Start node with --debug-brk[=port] flag.") - ("") - (" --harmony") - (" Start node with --harmony flag.") - ("") - (" --harmony_default_parameters") - (" Start node with --harmony_default_parameters flag.") - ("") - (" -n|--no-restart-on error|exit") - (" Don't automatically restart the supervised program if it ends.") - (" Supervisor will wait for a change in the source files.") - (" If \"error\", an exit code of 0 will still restart.") - (" If \"exit\", no restart regardless of exit code.") - (" If \"success\", no restart only if exit code is 0.") - ("") - (" -t|--non-interactive") - (" Disable interactive capacity.") - (" With this option, supervisor won't listen to stdin.") - ("") - (" -k|--instant-kill") - (" use SIGKILL (-9) to terminate child instead of the more gentle SIGTERM.") - ("") - (" --force-watch") - (" Use fs.watch instead of fs.watchFile.") - (" This may be useful if you see a high cpu load on a windows machine.") - ("") - (" -s|--timestamp") - (" Log timestamp after each run.") - (" Make it easy to tell when the task last ran.") - ("") - (" -h|--help|-?") - (" Display these usage instructions.") - ("") - (" -q|--quiet") - (" Suppress DEBUG messages") - ("") - (" -V|--verbose") - (" Show extra DEBUG messages") - ("") - ("Options available after start:") - ("rs - restart process.") - (" Useful for restarting supervisor eaven if no file has changed.") - ("") - ("Examples:") - (" supervisor myapp.js") - (" supervisor myapp.coffee") - (" supervisor -w scripts -e myext -x myrunner myapp") - (" supervisor -- server.js -h host -p port") - (""); -} - -function startProgram (prog, exec) { - log("Starting child process with '" + exec + " " + prog.join(" ") + "'"); - crash_queued = false; - var child = exports.child = spawn(exec, prog, {stdio: 'inherit'}); - // Support for Windows ".cmd" files - // On Windows 8.1, spawn can't launch apps without the .cmd extention - // If already retried, let the app crash ... :'( - if (process.platform === "win32" && exec.indexOf('.cmd') == -1) { - child.on('error', function (err) { - if (err.code === "ENOENT") - return startProgram(prog, exec + ".cmd"); - }); + function print(m) { + console.log(m); + return print; } - if (child.stdout) { - // node < 0.8 doesn't understand the 'inherit' option, so pass through manually - child.stdout.addListener("data", function (chunk) { chunk && console.log(chunk); }); - child.stderr.addListener("data", function (chunk) { chunk && console.error(chunk); }); + + function help() { + print + ("") + ("Node Supervisor is used to restart programs when they crash.") + ("It can also be used to restart programs when a *.js file changes.") + ("") + ("Usage:") + (" supervisor [options] ") + (" supervisor [options] -- [args ...]") + ("") + ("Required:") + (" ") + (" The program to run.") + ("") + ("Options:") + (" -w|--watch ") + (" A comma-delimited list of folders or js files to watch for changes.") + (" When a change to a js file occurs, reload the program") + (" Default is '.'") + ("") + (" -i|--ignore ") + (" A comma-delimited list of folders to ignore for changes.") + (" No default") + ("") + (" --ignore-symlinks") + (" Enable symbolic links ignoring when looking for files to watch.") + ("") + (" -p|--poll-interval ") + (" How often to poll watched files for changes.") + (" Defaults to Node default.") + ("") + (" -e|--extensions ") + (" Specific file extensions to watch in addition to defaults.") + (" Used when --watch option includes folders") + (" Default is 'node,js'") + ("") + (" -x|--exec ") + (" The executable that runs the specified program.") + (" Default is 'node'") + ("") + (" --debug[=port]") + (" Start node with --debug flag. ") + ("") + (" --debug-brk[=port]") + (" Start node with --debug-brk[=port] flag.") + ("") + (" --harmony") + (" Start node with --harmony flag.") + ("") + (" --harmony_default_parameters") + (" Start node with --harmony_default_parameters flag.") + ("") + (" -n|--no-restart-on error|exit") + (" Don't automatically restart the supervised program if it ends.") + (" Supervisor will wait for a change in the source files.") + (" If \"error\", an exit code of 0 will still restart.") + (" If \"exit\", no restart regardless of exit code.") + (" If \"success\", no restart only if exit code is 0.") + ("") + (" -t|--non-interactive") + (" Disable interactive capacity.") + (" With this option, supervisor won't listen to stdin.") + ("") + (" -k|--instant-kill") + (" use SIGKILL (-9) to terminate child instead of the more gentle SIGTERM.") + ("") + (" --force-watch") + (" Use fs.watch instead of fs.watchFile.") + (" This may be useful if you see a high cpu load on a windows machine.") + ("") + (" -s|--timestamp") + (" Log timestamp after each run.") + (" Make it easy to tell when the task last ran.") + ("") + (" -h|--help|-?") + (" Display these usage instructions.") + ("") + (" -q|--quiet") + (" Suppress DEBUG messages") + ("") + (" -V|--verbose") + (" Show extra DEBUG messages") + ("") + ("Options available after start:") + ("rs - restart process.") + (" Useful for restarting supervisor eaven if no file has changed.") + ("") + ("Examples:") + (" supervisor myapp.js") + (" supervisor myapp.coffee") + (" supervisor -w scripts -e myext -x myrunner myapp") + (" supervisor -- server.js -h host -p port") + (""); } - child.addListener("exit", function (code) { - logTimestamp(); - if (!crash_queued) { - log("Program " + exec + " " + prog.join(" ") + " exited with code " + code + "\n"); - exports.child = null; - if (noRestartOn == "exit" || noRestartOn == "error" && code !== 0 || noRestartOn == "success" && code === 0) return; + function startProgram(prog, exec) { + log("Starting child process with '" + exec + " " + prog.join(" ") + "'"); + crash_queued = false; + var child = exports.child = spawn(exec, prog, {stdio: 'inherit'}); + // Support for Windows ".cmd" files + // On Windows 8.1, spawn can't launch apps without the .cmd extention + // If already retried, let the app crash ... :'( + if (process.platform === "win32" && exec.indexOf('.cmd') == -1) { + child.on('error', function (err) { + if (err.code === "ENOENT") + return startProgram(prog, exec + ".cmd"); + }); } - startProgram(prog, exec); - }); -} + if (child.stdout) { + // node < 0.8 doesn't understand the 'inherit' option, so pass through manually + child.stdout.addListener("data", function (chunk) { + chunk && console.log(chunk); + }); + child.stderr.addListener("data", function (chunk) { + chunk && console.error(chunk); + }); + } + child.addListener("exit", function (code) { + logTimestamp(); -function logTimestamp() { - if (timestampFlag) { - // use console.log() directly rather than log() so that -q/--quiet - // does not override/silence it - console.log(Date().toString()); - } -} + if (!crash_queued) { + log("Program " + exec + " " + prog.join(" ") + " exited with code " + code + "\n"); + exports.child = null; + if (noRestartOn == "exit" || noRestartOn == "error" && code !== 0 || noRestartOn == "success" && code === 0) return; + } + startProgram(prog, exec); + }); + } -function crash () { + function logTimestamp() { + if (timestampFlag) { + // use console.log() directly rather than log() so that -q/--quiet + // does not override/silence it + console.log(Date().toString()); + } + } - if (crash_queued) - return; + function crash() { - crash_queued = true; - var child = exports.child; - setTimeout(function() { - if (child) { - if (instantKillFlag) { - log("crashing child with SIGKILL"); - process.kill(child.pid, "SIGKILL"); + if (crash_queued) + return; + + crash_queued = true; + var child = exports.child; + setTimeout(function () { + if (child) { + if (instantKillFlag) { + log("crashing child with SIGKILL"); + process.kill(child.pid, "SIGKILL"); + } else { + log("crashing child"); + process.kill(child.pid, "SIGTERM"); + } } else { - log("crashing child"); - process.kill(child.pid, "SIGTERM"); + log("restarting child"); + startChildProcess(); } - } else { - log("restarting child"); - startChildProcess(); - } - }, 50); -} + }, 50); + } -function crashWin (event, filename) { - var shouldCrash = true; - if( event === 'change' ) { - if (filename) { - filename = path.resolve(filename); - Object.keys(ignoredPaths).forEach(function (ignorePath) { - if ( filename.indexOf(ignorePath + '\\') === 0 || filename === ignorePath) { - shouldCrash = false; + function crashWin(event, filename) { + var shouldCrash = true; + if (event === 'change') { + if (filename) { + filename = path.resolve(filename); + Object.keys(ignoredPaths).forEach(function (ignorePath) { + if (filename.indexOf(ignorePath + '\\') === 0 || filename === ignorePath) { + shouldCrash = false; + } + }); + } + if (shouldCrash) { + if (verbose || restartVerbose) { + log("Changes detected" + (filename ? ": " + filename : "")); } - }); - } - if (shouldCrash) { - if (verbose || restartVerbose) { - log("Changes detected" + (filename ? ": " + filename : "")); + crash(); } - crash(); } } -} -/** - * Determine if a file can be written - */ -function canWrite(path, callback) { - fs.open(path, "w", function (err, fd) { - if (err) { - if (err.code === "EISDIR") { - log("Can't open " + path + ". It's a directory."); - } - if (err.code === "EACCESS") { - log("Can't open " + path + ". No access."); - } else { - log("Can't open " + path + "."); + + /** + * Determine if a file can be written + */ + function canWrite(path, callback) { + fs.open(path, "w", function (err, fd) { + if (err) { + if (err.code === "EISDIR") { + log("Can't open " + path + ". It's a directory."); + } + if (err.code === "EACCESS") { + log("Can't open " + path + ". No access."); + } else { + log("Can't open " + path + "."); + } + return callback(err); } - return callback(err); - } - fs.close(fd, function (err) { - if (err) return callback(err); - callback(null, true); + fs.close(fd, function (err) { + if (err) return callback(err); + callback(null, true); + }); }); - }); -} + } -var nodeVersion = process.version.split("."); + var nodeVersion = process.version.split("."); -var isWindowsWithoutWatchFile = process.platform === 'win32' && parseInt(nodeVersion[1]) <= 6; + var isWindowsWithoutWatchFile = process.platform === 'win32' && parseInt(nodeVersion[1]) <= 6; -function watchGivenFile (watch, poll_interval) { - if (isWindowsWithoutWatchFile || forceWatchFlag) { - fs.watch(watch, { persistent: true, interval: poll_interval }, crashWin); - } else { - fs.watchFile(watch, { persistent: true, interval: poll_interval }, function(oldStat, newStat) { - // we only care about modification time, not access time. - if ( newStat.mtime.getTime() !== oldStat.mtime.getTime() ) { - if (verbose) { - log("file changed: " + watch); + function watchGivenFile(watch, poll_interval) { + if (isWindowsWithoutWatchFile || forceWatchFlag) { + fs.watch(watch, {persistent: true, interval: poll_interval}, crashWin); + } else { + fs.watchFile(watch, {persistent: true, interval: poll_interval}, function (oldStat, newStat) { + // we only care about modification time, not access time. + if (newStat.mtime.getTime() !== oldStat.mtime.getTime()) { + if (verbose) { + log("file changed: " + watch); + } } - } - crash(); - }); - } - if (verbose) { - log("watching file '" + watch + "'"); + crash(); + }); + } + if (verbose) { + log("watching file '" + watch + "'"); + } } -} -var findAllWatchFiles = function(dir, callback) { - dir = path.resolve(dir); - if (ignoredPaths[dir]) - return; - fs[ignoreSymLinks ? 'lstat' : 'stat'](dir, function(err, stats) { - if (err) { - console.error('Error retrieving stats for file: ' + dir); - } else { - if (ignoreSymLinks && stats.isSymbolicLink()) { - log("Ignoring symbolic link '" + dir + "'."); - return; - } + var findAllWatchFiles = function (dir, callback) { + dir = path.resolve(dir); + if (ignoredPaths[dir]) + return; + fs[ignoreSymLinks ? 'lstat' : 'stat'](dir, function (err, stats) { + if (err) { + console.error('Error retrieving stats for file: ' + dir); + } else { + if (ignoreSymLinks && stats.isSymbolicLink()) { + log("Ignoring symbolic link '" + dir + "'."); + return; + } - if (stats.isDirectory()) { - if (isWindowsWithoutWatchFile || forceWatchFlag) callback(dir); - fs.readdir(dir, function(err, fileNames) { - if(err) { - console.error('Error reading path: ' + dir); + if (stats.isDirectory()) { + if (isWindowsWithoutWatchFile || forceWatchFlag) callback(dir); + fs.readdir(dir, function (err, fileNames) { + if (err) { + console.error('Error reading path: ' + dir); + } + else { + fileNames.forEach(function (fileName) { + findAllWatchFiles(path.join(dir, fileName), callback); + }); + } + }); + } else { + if ((!isWindowsWithoutWatchFile || !forceWatchFlag) && dir.match(fileExtensionPattern)) { + callback(dir); } - else { - fileNames.forEach(function (fileName) { - findAllWatchFiles(path.join(dir, fileName), callback); - }); - } - }); - } else { - if ((!isWindowsWithoutWatchFile || !forceWatchFlag) && dir.match(fileExtensionPattern)) { - callback(dir); } } - } - }); -}; + }); + }; +} From ae3c5d627be00d3db32dd86c04bd8720baaa61dd Mon Sep 17 00:00:00 2001 From: Andy Edwards Date: Mon, 10 Oct 2016 13:22:30 -0500 Subject: [PATCH 2/2] fix tests except for termination --- lib/supervisor.js | 28 +++++++++++------- test/supervisor.test.js | 63 +++++++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 34 deletions(-) diff --git a/lib/supervisor.js b/lib/supervisor.js index 2dbdda9..ce1b5cf 100644 --- a/lib/supervisor.js +++ b/lib/supervisor.js @@ -1,6 +1,7 @@ var fs = require("fs"); var spawn = require("child_process").spawn; var path = require("path"); +var log = console.log; exports.run = run; @@ -17,10 +18,11 @@ function run (args) { var instantKillFlag = false; var timestampFlag = false; var interactive = true; - var log = console.log; var crash_queued = false; var harmony_default_parameters = false; var harmony_destructuring = false; + var child; + var watchers = []; var arg, next, watch, ignore, pidFilePath, program, extensions, executor, poll_interval, debugFlag, debugBrkFlag, debugBrkFlagArg, harmony; while (arg = args.shift()) { @@ -157,7 +159,6 @@ function run (args) { // Pass kill signals through to child ["SIGTERM", "SIGINT", "SIGHUP", "SIGQUIT"].forEach(function (signal) { process.on(signal, function () { - var child = exports.child; if (child) { log("Received " + signal + ", killing child process..."); child.kill(signal); @@ -176,7 +177,6 @@ function run (args) { } process.on('exit', function () { - var child = exports.child; if (child) { log("Parent process exiting, terminating child..."); child.kill("SIGTERM"); @@ -359,7 +359,7 @@ function run (args) { function startProgram(prog, exec) { log("Starting child process with '" + exec + " " + prog.join(" ") + "'"); crash_queued = false; - var child = exports.child = spawn(exec, prog, {stdio: 'inherit'}); + child = spawn(exec, prog, {stdio: 'inherit'}); // Support for Windows ".cmd" files // On Windows 8.1, spawn can't launch apps without the .cmd extention // If already retried, let the app crash ... :'( @@ -383,7 +383,7 @@ function run (args) { if (!crash_queued) { log("Program " + exec + " " + prog.join(" ") + " exited with code " + code + "\n"); - exports.child = null; + child = null; if (noRestartOn == "exit" || noRestartOn == "error" && code !== 0 || noRestartOn == "success" && code === 0) return; } startProgram(prog, exec); @@ -404,7 +404,6 @@ function run (args) { return; crash_queued = true; - var child = exports.child; setTimeout(function () { if (child) { if (instantKillFlag) { @@ -471,9 +470,9 @@ function run (args) { function watchGivenFile(watch, poll_interval) { if (isWindowsWithoutWatchFile || forceWatchFlag) { - fs.watch(watch, {persistent: true, interval: poll_interval}, crashWin); + watchers.push(fs.watch(watch, {persistent: true, interval: poll_interval}, crashWin)); } else { - fs.watchFile(watch, {persistent: true, interval: poll_interval}, function (oldStat, newStat) { + watchers.push(fs.watchFile(watch, {persistent: true, interval: poll_interval}, function (oldStat, newStat) { // we only care about modification time, not access time. if (newStat.mtime.getTime() !== oldStat.mtime.getTime()) { if (verbose) { @@ -481,14 +480,14 @@ function run (args) { } } crash(); - }); + })); } if (verbose) { log("watching file '" + watch + "'"); } } - var findAllWatchFiles = function (dir, callback) { + function findAllWatchFiles(dir, callback) { dir = path.resolve(dir); if (ignoredPaths[dir]) return; @@ -521,4 +520,13 @@ function run (args) { } }); }; + + return { + kill: function kill() { + if (child) child.kill(); + watchers.forEach(function (watcher) { + watcher.close(); + }); + } + } } diff --git a/test/supervisor.test.js b/test/supervisor.test.js index b199000..4b4dca5 100644 --- a/test/supervisor.test.js +++ b/test/supervisor.test.js @@ -1,25 +1,20 @@ var logger = console.log; var logs = ""; console.log = function(msg){ -// logger(msg); + // logger(msg); logs += msg; }; -var testScript = "test/fixture.js" -var testCase = require('nodeunit').testCase; +var testScript = "test/fixture.js"; var supervisor = require('../lib/supervisor.js'); var assertValueExists = function(assertion, test){ test.ok(assertion); test.done(); - setTimeout(function(){ - logs = ""; - process.kill(); - }, 20) }; var tests = { - tearDown:function testGroupOneTearDown(cb){ + tearDown: function testGroupOneTearDown(cb) { logs = ""; console.log = logger; cb(); @@ -28,31 +23,51 @@ var tests = { test.ok(!!supervisor); test.done(); }, - "should accept a debug port when passed through": function(test){ + "should accept a debug port when passed through": function (test) { var EXPECTED = '--debug=1234'; - supervisor.run([ EXPECTED, "--no-restart-on", "exit", "--", testScript]); - assertValueExists(logs.indexOf(EXPECTED) > -1, test); + var child = supervisor.run([EXPECTED, "--no-restart-on", "exit", "--", testScript]); + try { + assertValueExists(logs.indexOf(EXPECTED) > -1, test); + } finally { + child.kill(); + } }, - "should use debug alone when no port number passed through": function(test){ + "should use debug alone when no port number passed through": function (test) { var EXPECTED = '--debug'; - supervisor.run([ EXPECTED, "--no-restart-on", "exit", "--", testScript]); - assertValueExists(logs.indexOf(EXPECTED) > -1, test); + var child = supervisor.run([EXPECTED, "--no-restart-on", "exit", "--", testScript]); + try { + assertValueExists(logs.indexOf(EXPECTED) > -1, test); + } finally { + child.kill(); + } }, - "should not overwrite with debug-brk value if debug-brk also passed through": function(test){ + "should not overwrite with debug-brk value if debug-brk also passed through": function (test) { var EXPECTED = '--debug=1236'; - supervisor.run([ EXPECTED, "--debug-brk", "--no-restart-on", "exit", "--", testScript]); - assertValueExists(logs.indexOf(EXPECTED) > -1, test); + var child = supervisor.run([EXPECTED, "--debug-brk", "--no-restart-on", "exit", "--", testScript]); + try { + assertValueExists(logs.indexOf(EXPECTED) > -1, test); + } finally { + child.kill(); + } }, - "should pass the debug-brk flag through": function(test){ + "should pass the debug-brk flag through": function (test) { var EXPECTED = '--debug-brk'; - supervisor.run([ EXPECTED, "--no-restart-on", "exit", "--", testScript]); - assertValueExists(logs.indexOf(EXPECTED) > -1, test); + var child = supervisor.run([EXPECTED, "--no-restart-on", "exit", "--", testScript]); + try { + assertValueExists(logs.indexOf(EXPECTED) > -1, test); + } finally { + child.kill(); + } }, - "should pass the debug-brk port number arg through with debug-brk flag": function(test){ + "should pass the debug-brk port number arg through with debug-brk flag": function (test) { var EXPECTED = '--debug-brk=5859'; - supervisor.run([ EXPECTED, "--no-restart-on", "exit", "--", testScript]); - assertValueExists(logs.indexOf(EXPECTED) > -1, test); + var child = supervisor.run([EXPECTED, "--no-restart-on", "exit", "--", testScript]); + try { + assertValueExists(logs.indexOf(EXPECTED) > -1, test); + } finally { + child.kill(); + } } }; -module.exports.testGroupOne = testCase(tests); +module.exports.testGroupOne = tests;