pax_global_header00006660000000000000000000000064134040060070014504gustar00rootroot0000000000000052 comment=2640711d748a1bea801b502d4861277425706721 flagged-respawn-1.0.1/000077500000000000000000000000001340400600700145515ustar00rootroot00000000000000flagged-respawn-1.0.1/.editorconfig000066400000000000000000000003261340400600700172270ustar00rootroot00000000000000# http://editorconfig.org root = true [*] indent_style = space indent_size = 2 charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true end_of_line = lf [*.md] trim_trailing_whitespace = false flagged-respawn-1.0.1/.eslintignore000066400000000000000000000000121340400600700172450ustar00rootroot00000000000000coverage/ flagged-respawn-1.0.1/.eslintrc000066400000000000000000000000301340400600700163660ustar00rootroot00000000000000{ "extends": "gulp" } flagged-respawn-1.0.1/.gitattributes000066400000000000000000000000161340400600700174410ustar00rootroot00000000000000* text eol=lf flagged-respawn-1.0.1/.gitignore000066400000000000000000000011621340400600700165410ustar00rootroot00000000000000# Logs logs *.log # Runtime data pids *.pid *.seed # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directory # Commenting this out is preferred by some people, see # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- node_modules # Users Environment Variables .lock-wscript # Garbage files .DS_Store flagged-respawn-1.0.1/.npmrc000066400000000000000000000000231340400600700156640ustar00rootroot00000000000000package-lock=false flagged-respawn-1.0.1/.travis.yml000066400000000000000000000003751340400600700166670ustar00rootroot00000000000000sudo: false language: node_js node_js: - '10' - '8' - '6' - '4' - '0.12' - '0.10' matrix: fast_finish: true script: if [ $(echo "${TRAVIS_NODE_VERSION}" | cut -d'.' -f1) -ge 4 ]; then npm run coveralls; else npm test; fi flagged-respawn-1.0.1/LICENSE000066400000000000000000000022421340400600700155560ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014-2018 Tyler Kellen , Blaine Bublitz , and Eric Schoffstall Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. flagged-respawn-1.0.1/README.md000066400000000000000000000121761340400600700160370ustar00rootroot00000000000000

# flagged-respawn [![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Travis Build Status][travis-image]][travis-url] [![AppVeyor Build Status][appveyor-image]][appveyor-url] [![Coveralls Status][coveralls-image]][coveralls-url] [![Gitter chat][gitter-image]][gitter-url] A tool for respawning node binaries when special flags are present. ## What is it? Say you wrote a command line tool that runs arbitrary javascript (e.g. task runner, test framework, etc). For the sake of discussion, let's pretend it's a testing harness you've named `testify`. Everything is going splendidly until one day you decide to test some code that relies on a feature behind a v8 flag in node (`--harmony`, for example). Without much thought, you run `testify --harmony spec tests.js`. It doesn't work. After digging around for a bit, you realize this produces a [`process.argv`](http://nodejs.org/docs/latest/api/process.html#process_process_argv) of: `['node', '/usr/local/bin/test', '--harmony', 'spec', 'tests.js']` Crap. The `--harmony` flag is in the wrong place! It should be applied to the **node** command, not our binary. What we actually wanted was this: `['node', '--harmony', '/usr/local/bin/test', 'spec', 'tests.js']` Flagged-respawn fixes this problem and handles all the edge cases respawning creates, such as: - Providing a method to determine if a respawn is needed. - Piping stderr/stdout from the child into the parent. - Making the parent process exit with the same code as the child. - If the child is killed, making the parent exit with the same signal. To see it in action, clone this repository and run `npm install` / `npm run respawn` / `npm run nospawn`. ## Sample Usage ```js #!/usr/bin/env node const flaggedRespawn = require('flagged-respawn'); // get a list of all possible v8 flags for the running version of node const v8flags = require('v8flags').fetch(); flaggedRespawn(v8flags, process.argv, function (ready, child) { if (ready) { console.log('Running!'); // your cli code here } else { console.log('Special flags found, respawning.'); } if (process.pid !== child.pid) { console.log('Respawned to PID:', child.pid); } }); ``` ## API ### flaggedRespawn(flags, argv, [ forcedFlags, ] callback) : Void Respawns the script itself when *argv* has special flag contained in *flags* and/or *forcedFlags* is not empty. Because members of *flags* and *forcedFlags* are passed to `node` command, each of them needs to be a node flag or a V8 flag. #### Forbid respawning If `--no-respawning` flag is given in *argv*, this function does not respawned even if *argv* contains members of flags or *forcedFlags* is not empty. (This flag is also used internally to prevent from respawning more than once). #### Parameter: | Parameter | Type | Description | |:--------------|:------:|:----------------------------------------------------| | *flags* | Array | An array of node flags and V8 flags which are available when present in *argv*. | | *argv* | Array | Command line arguments to respawn. | | *forcedFlags* | Array or String | An array of node flags or a string of a single flag and V8 flags for respawning forcely. | | *callback* | function | A called function when not respawning or after respawned. | * **callback(ready, proc, argv) : Void** *callback* function is called both when respawned or not, and it can be distinguished by callback's argument: *ready*. (*ready* indicates whether a process spawned its child process (false) or not (true), but it does not indicate whether a process is a spawned child process or not. *ready* for a spawned child process is true.) *argv* is an array of command line arguments which is respawned (when *ready* is false) or is passed current process except flags within *flags* and `--no-respawning` (when *ready* is true). **Parameter:** | Parameter | Type | Description | |:----------|:-------:|:--------------------------| | *ready* | boolean | True, if not respawning and is ready to execute main function. | | *proc* | object | Child process object if respawned, otherwise current process object. | | *argv* | Array | An array of command line arguments. | ## License MIT [downloads-image]: http://img.shields.io/npm/dm/flagged-respawn.svg [npm-url]: https://www.npmjs.com/package/flagged-respawn [npm-image]: http://img.shields.io/npm/v/flagged-respawn.svg [travis-url]: https://travis-ci.org/gulpjs/flagged-respawn [travis-image]: http://img.shields.io/travis/gulpjs/flagged-respawn.svg?label=travis-ci [appveyor-url]: https://ci.appveyor.com/project/gulpjs/flagged-respawn [appveyor-image]: https://img.shields.io/appveyor/ci/gulpjs/flagged-respawn.svg?label=appveyor [coveralls-url]: https://coveralls.io/r/gulpjs/flagged-respawn [coveralls-image]: http://img.shields.io/coveralls/gulpjs/flagged-respawn/master.svg [gitter-url]: https://gitter.im/gulpjs/gulp [gitter-image]: https://badges.gitter.im/gulpjs/gulp.svg flagged-respawn-1.0.1/appveyor.yml000066400000000000000000000007541340400600700171470ustar00rootroot00000000000000# http://www.appveyor.com/docs/appveyor-yml # http://www.appveyor.com/docs/lang/nodejs-iojs environment: matrix: # node.js - nodejs_version: "0.10" - nodejs_version: "0.12" - nodejs_version: "4" - nodejs_version: "6" - nodejs_version: "8" - nodejs_version: "10" install: - ps: Install-Product node $env:nodejs_version - npm install test_script: - node --version - npm --version - cmd: npm test build: off # build version format version: "{build}" flagged-respawn-1.0.1/index.js000066400000000000000000000023621340400600700162210ustar00rootroot00000000000000var reorder = require('./lib/reorder'); var respawn = require('./lib/respawn'); var remover = require('./lib/remover'); var FORBID_RESPAWNING_FLAG = '--no-respawning'; module.exports = function(flags, argv, forcedFlags, execute) { if (!flags) { throw new Error('You must specify flags to respawn with.'); } if (!argv) { throw new Error('You must specify an argv array.'); } if (typeof forcedFlags === 'function') { execute = forcedFlags; forcedFlags = []; } if (typeof forcedFlags === 'string') { forcedFlags = [forcedFlags]; } if (!Array.isArray(forcedFlags)) { forcedFlags = []; } var index = argv.indexOf(FORBID_RESPAWNING_FLAG); if (index >= 0) { argv = argv.slice(0, index).concat(argv.slice(index + 1)); argv = remover(flags, argv); execute(true, process, argv); return; } var proc = process; var reordered = reorder(flags, argv); var ready = JSON.stringify(argv) === JSON.stringify(reordered); if (forcedFlags.length) { reordered = reordered.slice(0, 1) .concat(forcedFlags) .concat(reordered.slice(1)); ready = false; } if (!ready) { reordered.push(FORBID_RESPAWNING_FLAG); proc = respawn(reordered); } execute(ready, proc, reordered); }; flagged-respawn-1.0.1/lib/000077500000000000000000000000001340400600700153175ustar00rootroot00000000000000flagged-respawn-1.0.1/lib/is-v8flags.js000066400000000000000000000005051340400600700176400ustar00rootroot00000000000000function isV8flags(flag, v8flags) { return v8flags.indexOf(replaceSeparatorsFromDashesToUnderscores(flag)) >= 0; } function replaceSeparatorsFromDashesToUnderscores(flag) { var arr = /^(-+)(.*)$/.exec(flag); if (!arr) { return flag; } return arr[1] + arr[2].replace(/\-/g, '_'); } module.exports = isV8flags; flagged-respawn-1.0.1/lib/remover.js000066400000000000000000000004611340400600700173350ustar00rootroot00000000000000var isV8flags = require('./is-v8flags'); module.exports = function(flags, argv) { var args = argv.slice(0, 1); for (var i = 1, n = argv.length; i < n; i++) { var arg = argv[i]; var flag = arg.split('=')[0]; if (!isV8flags(flag, flags)) { args.push(arg); } } return args; }; flagged-respawn-1.0.1/lib/reorder.js000066400000000000000000000005661340400600700173260ustar00rootroot00000000000000var isV8flags = require('./is-v8flags'); module.exports = function(flags, argv) { if (!argv) { argv = process.argv; } var args = [argv[1]]; argv.slice(2).forEach(function(arg) { var flag = arg.split('=')[0]; if (isV8flags(flag, flags)) { args.unshift(arg); } else { args.push(arg); } }); args.unshift(argv[0]); return args; }; flagged-respawn-1.0.1/lib/respawn.js000066400000000000000000000006241340400600700173360ustar00rootroot00000000000000var spawn = require('child_process').spawn; module.exports = function(argv) { var child = spawn(argv[0], argv.slice(1), { stdio: 'inherit' }); child.on('exit', function(code, signal) { process.on('exit', function() { /* istanbul ignore if */ if (signal) { process.kill(process.pid, signal); } else { process.exit(code); } }); }); return child; }; flagged-respawn-1.0.1/package.json000066400000000000000000000023471340400600700170450ustar00rootroot00000000000000{ "name": "flagged-respawn", "version": "1.0.1", "description": "A tool for respawning node binaries when special flags are present.", "author": "Gulp Team (http://gulpjs.com/)", "contributors": [ "Takayuki Sato ", "Bertrand Marron ", "Tyler Kellen ", "Blaine Bublitz " ], "repository": "gulpjs/flagged-respawn", "license": "MIT", "engines": { "node": ">= 0.10" }, "main": "index.js", "files": [ "index.js", "lib/", "LICENSE" ], "scripts": { "lint": "eslint .", "pretest": "npm run lint", "test": "mocha --async-only", "cover": "nyc --reporter=lcov --reporter=text-summary npm test", "coveralls": "npm run cover && istanbul-coveralls", "respawn": "node test/bin/respawner --harmony test", "nospawn": "node test/bin/respawner test" }, "dependencies": {}, "devDependencies": { "eslint": "^2.13.0", "eslint-config-gulp": "^3.0.1", "expect": "^1.20.2", "istanbul": "^0.4.3", "istanbul-coveralls": "^1.0.3", "mocha": "^3.5.3", "nyc": "^11.3.0", "v8flags": "^3.0.1" }, "keywords": [ "respawn", "flags" ] } flagged-respawn-1.0.1/test/000077500000000000000000000000001340400600700155305ustar00rootroot00000000000000flagged-respawn-1.0.1/test/.eslintrc000066400000000000000000000001031340400600700173460ustar00rootroot00000000000000{ "extends": "gulp/test", "rules": { "no-console": 0 } } flagged-respawn-1.0.1/test/bin/000077500000000000000000000000001340400600700163005ustar00rootroot00000000000000flagged-respawn-1.0.1/test/bin/callback-params.js000066400000000000000000000007311340400600700216540ustar00rootroot00000000000000#!/usr/bin/env node var flaggedRespawn = require('../../'); var v8flags = require('v8flags'); // get a list of all possible v8 flags for the running version of node v8flags(function(err, flags) { if (err) { console.error(err); return; } flaggedRespawn(flags, process.argv, function(ready, child) { var result = { ready: ready, child_pid: child.pid, process_pid: process.pid, }; console.log(JSON.stringify(result)); }); }); flagged-respawn-1.0.1/test/bin/exit_code.js000066400000000000000000000003271340400600700206030ustar00rootroot00000000000000#!/usr/bin/env node var flaggedRespawn = require('../../'); flaggedRespawn(['--harmony'], process.argv, function(ready) { if (ready) { setTimeout(function() { process.exit(100); }, 100); } }); flagged-respawn-1.0.1/test/bin/forbid-respawning.js000066400000000000000000000011141340400600700222530ustar00rootroot00000000000000#!/usr/bin/env node var flaggedRespawn = require('../../'); var v8flags = require('v8flags'); // get a list of all possible v8 flags for the running version of node v8flags(function(err, flags) { if (err) { console.error(err); return; } var argv = process.argv.concat('--no-respawning'); flaggedRespawn(flags, argv, function(ready, child) { if (ready) { console.log('Running!'); } else { console.log('Special flags found, respawning.'); } if (child.pid !== process.pid) { console.log('Respawned to PID:', child.pid); } }); }); flagged-respawn-1.0.1/test/bin/force-and-forbid-respawning.js000066400000000000000000000007531340400600700241170ustar00rootroot00000000000000#!/usr/bin/env node var flaggedRespawn = require('../../'); var v8flags = require('v8flags'); // get a list of all possible v8 flags for the running version of node v8flags(function(err, flags) { if (err) { console.error(err); return; } var argv = process.argv.concat('--no-respawning'); flaggedRespawn(flags, argv, ['--trace-deprecation'], function(ready) { if (ready) { console.log('Running!'); } else { console.log('Respawning!'); } }); }); flagged-respawn-1.0.1/test/bin/force-respawning-string.js000066400000000000000000000006731340400600700234210ustar00rootroot00000000000000#!/usr/bin/env node var flaggedRespawn = require('../../'); var v8flags = require('v8flags'); // get a list of all possible v8 flags for the running version of node v8flags(function(err, flags) { if (err) { console.error(err); return; } flaggedRespawn(flags, process.argv, '--trace-deprecation', function(ready) { if (ready) { console.log('Running!'); } else { console.log('Respawning!'); } }); }); flagged-respawn-1.0.1/test/bin/force-respawning.js000066400000000000000000000006751340400600700221170ustar00rootroot00000000000000#!/usr/bin/env node var flaggedRespawn = require('../../'); var v8flags = require('v8flags'); // get a list of all possible v8 flags for the running version of node v8flags(function(err, flags) { if (err) { console.error(err); return; } flaggedRespawn(flags, process.argv, ['--trace-deprecation'], function(ready) { if (ready) { console.log('Running!'); } else { console.log('Respawning!'); } }); }); flagged-respawn-1.0.1/test/bin/print-args.js000066400000000000000000000007501340400600700207260ustar00rootroot00000000000000#!/usr/bin/env node var flaggedRespawn = require('../..'); var v8flags = require('v8flags'); v8flags(function(err, flags) { if (err) { console.error(err); return; } flaggedRespawn(flags, process.argv, [ '--trace-deprecation', /* '--require', 'v8flags', '--v8-pool-size=2', */ ], function(ready, child, args) { if (ready) { console.log('cli args passed to app:', args.join(' ')); } else { console.log('Respawning!'); } }); }); flagged-respawn-1.0.1/test/bin/respawner.js000066400000000000000000000010361340400600700206440ustar00rootroot00000000000000#!/usr/bin/env node var flaggedRespawn = require('../../'); var v8flags = require('v8flags'); // get a list of all possible v8 flags for the running version of node v8flags(function(err, flags) { if (err) { console.error(err); return; } flaggedRespawn(flags, process.argv, function(ready, child) { if (ready) { console.log('Running!'); } else { console.log('Special flags found, respawning.'); } if (child.pid !== process.pid) { console.log('Respawned to PID:', child.pid); } }); }); flagged-respawn-1.0.1/test/bin/signal.js000066400000000000000000000004371340400600700201170ustar00rootroot00000000000000#!/usr/bin/env node var flaggedRespawn = require('../../'); flaggedRespawn(['--harmony'], process.argv, function(ready, child) { if (ready) { setTimeout(function() { process.exit(); }, 100); } else { console.log('got child!'); child.kill('SIGHUP'); } }); flagged-respawn-1.0.1/test/index.js000066400000000000000000000262451340400600700172060ustar00rootroot00000000000000var expect = require('expect'); var exec = require('child_process').exec; var os = require('os'); var path = require('path'); var reorder = require('../lib/reorder'); var isV8flags = require('../lib/is-v8flags'); var remover = require('../lib/remover'); var flaggedRespawn = require('../'); describe('flaggedRespawn', function() { var flags = ['--harmony', '--use_strict', '--stack_size']; describe('isV8flags', function() { it('should return true when flag is in v8flags', function(done) { expect(isV8flags('--harmony', flags)).toEqual(true); expect(isV8flags('--use_strict', flags)).toEqual(true); expect(isV8flags('--stack_size', flags)).toEqual(true); done(); }); it('should ignore separator differences of "-" and "_"', function(done) { expect(isV8flags('--use-strict', flags)).toEqual(true); expect(isV8flags('--stack-size', flags)).toEqual(true); done(); }); it('should return false when flag is not in v8flags', function(done) { expect(isV8flags('--aaa', flags)).toEqual(false); expect(isV8flags('__use_strict', flags)).toEqual(false); done(); }); }); describe('reorder', function() { it('should re-order args, placing special flags first', function(done) { var needsRespawn = ['node', 'file.js', '--flag', '--harmony', 'command']; var noRespawnNeeded = ['node', 'bin/flagged-respawn', 'thing']; expect(reorder(flags, needsRespawn)).toEqual(['node', '--harmony', 'file.js', '--flag', 'command']); expect(reorder(flags, noRespawnNeeded)).toEqual(noRespawnNeeded); done(); }); it('should keep flags values when not placed first', function(done) { var args = ['node', 'file.js', '--stack_size=2048']; var expected = ['node', '--stack_size=2048', 'file.js']; expect(reorder(flags, args)).toEqual(expected); done(); }); it('should re-order args when flag separators are dashes', function(done) { var args = ['node', 'file.js', '--stack-size=2048']; var expected = ['node', '--stack-size=2048', 'file.js']; expect(reorder(flags, args)).toEqual(expected); done(); }); it('should ignore special flags when they are in the correct position', function(done) { var args = ['node', '--harmony', 'file.js', '--flag']; expect(reorder(flags, reorder(flags, args))).toEqual(args); done(); }); it('defaults to process.argv if none specified', function(done) { expect(reorder(flags)).toEqual(process.argv); done(); }); }); describe('remover', function() { it('should remove args included in flags', function(done) { var needsRespawn = ['node', 'file.js', '--flag', '--harmony', 'command']; var noRespawnNeeded = ['node', 'bin/flagged-respawn', 'thing']; expect(remover(flags, needsRespawn)).toEqual(['node', 'file.js', '--flag', 'command']); expect(reorder(flags, noRespawnNeeded)).toEqual(noRespawnNeeded); done(); }); it('should remove a arg even when the arg has value', function(done) { var args = ['node', 'file.js', '--stack_size=2048']; var expected = ['node', 'file.js']; expect(remover(flags, args)).toEqual(expected); done(); }); it('should remove special flags when they are in the correct position', function(done) { var args = ['node', '--harmony', 'file.js', '--flag']; var expected = ['node', 'file.js', '--flag']; expect(reorder(flags, remover(flags, args))).toEqual(expected); done(); }); }); describe('main export', function() { it('should throw if no flags are specified', function(done) { expect(function() { flaggedRespawn(); }).toThrow(); done(); }); it('should throw if no argv is specified', function(done) { expect(function() { flaggedRespawn(flags); }).toThrow(); done(); }); it('should respawn and pipe stderr/stdout to parent', function(done) { exec('node ./test/bin/respawner.js --harmony', function(err, stdout) { expect(stdout.replace(/[0-9]/g, '')).toEqual('Special flags found, respawning.\nRespawned to PID: \nRunning!\n'); done(); }); }); it('should respawn and pass exit code from child to parent', function(done) { exec('node ./test/bin/exit_code.js --harmony', function(err) { expect(err.code).toEqual(100); done(); }); }); it('should respawn; if child is killed, parent should exit with same signal', function(done) { // Because travis and nyc hates this if (process.env.TRAVIS || process.env.NYC_PARENT_PID) { this.skip(); return; } exec('node ./test/bin/signal.js --harmony', function(err) { switch (os.platform()) { // err.signal is null on Windows and Linux. // Is this related to the issue #12378 of nodejs/node? case 'win32': case 'linux': { expect(err.signal).toEqual(null); break; } default: { expect(err.signal).toEqual('SIGHUP'); break; } } done(); }); }); it('should call back with ready as true when respawn is not needed', function(done) { var argv = ['node', './test/bin/respawner']; flaggedRespawn(flags, argv, function(ready) { expect(ready).toEqual(true); }); done(); }); it('should call back with ready as false when respawn is needed', function(done) { var argv = ['node', './test/bin/callback-params', '--harmony']; exec(argv.join(' '), function(err, stdout, stderr) { expect(err).toEqual(null); expect(stderr).toEqual(''); var results = stdout.slice(0, -1).split('\n'); expect(results.length).toEqual(2); expect(JSON.parse(results[0]).ready).toEqual(false); expect(JSON.parse(results[1]).ready).toEqual(true); done(); }); }); it('should call back with the child process when ready', function(done) { var argv = ['node', './test/bin/callback-params', '--harmony']; exec(argv.join(' '), function(err, stdout, stderr) { expect(err).toEqual(null); expect(stderr).toEqual(''); var results = stdout.slice(0, -1).split('\n'); expect(results.length).toEqual(2); var params = JSON.parse(results[0]); expect(params.child_pid).toNotEqual(params.process_pid); params = JSON.parse(results[1]); expect(params.child_pid).toEqual(params.process_pid); done(); }); }); it('should call back with own process when respawn not needed', function(done) { var argv = ['node', './test/bin/respawner']; flaggedRespawn(flags, argv, function(ready, child) { expect(child.pid).toEqual(process.pid); }); done(); }); }); describe('force and forbid respawning', function() { it('forbid respawning with --no-respawning flag', function(done) { var cmd = [ 'node', path.resolve(__dirname, 'bin/respawner.js'), '--harmony', '--no-respawning', ].join(' '); exec(cmd, function cb(err, stdout, stderr) { expect(err).toEqual(null); expect(stderr).toEqual(''); expect(stdout).toEqual('Running!\n'); done(); }); }); it('always forbid respawning with inner --no-respawning', function(done) { var cmd = [ 'node', path.resolve(__dirname, 'bin/forbid-respawning.js'), '--harmony', ].join(' '); exec(cmd, function cb(err, stdout, stderr) { expect(err).toEqual(null); expect(stderr).toEqual(''); expect(stdout).toEqual('Running!\n'); done(); }); }); it('should force respawning with node flags (array)', function(done) { var cmd = [ 'node', path.resolve(__dirname, 'bin/force-respawning.js'), ].join(' '); exec(cmd, function cb(err, stdout, stderr) { expect(err).toEqual(null); expect(stderr).toEqual(''); expect(stdout).toEqual('Respawning!\nRunning!\n'); done(); }); }); it('should force respawning with node flags (string)', function(done) { var cmd = [ 'node', path.resolve(__dirname, 'bin/force-respawning-string.js'), ].join(' '); exec(cmd, function cb(err, stdout, stderr) { expect(err).toEqual(null); expect(stderr).toEqual(''); expect(stdout).toEqual('Respawning!\nRunning!\n'); done(); }); }); it('should take priority to forbidding than forcing', function(done) { exec('node ./test/bin/force-and-forbid-respawning.js', cb); function cb(err, stdout, stderr) { expect(err).toEqual(null); expect(stderr).toEqual(''); expect(stdout).toEqual('Running!\n'); done(); } }); }); describe('cli args which are passed to app', function() { it('should pass args except v8flags, forced node flags, --no-respawning when respawned', function(done) { var script = path.resolve(__dirname, 'bin/print-args.js'); var cmd = [ '"' + process.argv[0] + '"', script, 'aaa', '--harmony', '-q', '1234', '--cwd', 'bbb/ccc/ddd', '--prof_browser_mode', '-V', ].join(' '); var message = 'Respawning!\n' + 'cli args passed to app: ' + [process.argv[0], script, 'aaa', '-q', '1234', '--cwd', 'bbb/ccc/ddd', '-V'].join(' ') + '\n'; exec(cmd, function cb(err, stdout, stderr) { expect(err).toEqual(null); expect(stderr).toEqual(''); expect(stdout).toEqual(message); done(); }); }); it('should pass args except v8flags, forced node flags, --no-respawning when not respawned', function(done) { var script = path.resolve(__dirname, 'bin/print-args.js'); var cmd = [ '"' + process.argv[0] + '"', script, 'aaa', '--harmony', '-q', '1234', '--cwd', 'bbb/ccc/ddd', '--prof-browser-mode', '-V', '--no-respawning', ].join(' '); var message = 'cli args passed to app: ' + [ process.argv[0], script, 'aaa', '-q', '1234', '--cwd', 'bbb/ccc/ddd', '-V', ].join(' ') + '\n'; exec(cmd, function cb(err, stdout, stderr) { expect(err).toEqual(null); expect(stderr).toEqual(''); expect(stdout).toEqual(message); done(); }); }); }); describe('parameter checks', function() { it('should throw an error when flags is nullish', function(done) { var argv = ['node', './test/bin/respawner']; var exec = function() {}; expect(function() { flaggedRespawn(null, argv, exec); }).toThrow(Error); expect(function() { flaggedRespawn(flags, undefined, exec); }).toThrow(Error); done(); }); it('will not respawn if forced flags is not string or array', function(done) { var argv = ['node', './test/bin/respawner']; flaggedRespawn(flags, argv, {}, function(ready, child) { expect(ready).toEqual(true); expect(child.pid).toEqual(process.pid); done(); }); }); }); });