errors, child_process: use internal/errors codes

PR-URL: https://github.com/nodejs/node/pull/14998
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
This commit is contained in:
Jon Moss 2017-08-23 15:20:54 -07:00
parent 59e48329d0
commit b1e6c0d44c
9 changed files with 209 additions and 159 deletions

View File

@ -642,6 +642,17 @@ Node.js was unable to watch for the `SIGINT` signal.
A child process was closed before the parent received a reply. A child process was closed before the parent received a reply.
<a id="ERR_CHILD_PROCESS_IPC_REQUIRED"></a>
### ERR_CHILD_PROCESS_IPC_REQUIRED
Used when a child process is being forked without specifying an IPC channel.
<a id="ERR_CHILD_PROCESS_STDIO_MAXBUFFER"></a>
### ERR_CHILD_PROCESS_STDIO_MAXBUFFER
Used when the main process is trying to read data from the child process's
STDERR / STDOUT, and the data's length is longer than the `maxBuffer` option.
<a id="ERR_CONSOLE_WRITABLE_STREAM"></a> <a id="ERR_CONSOLE_WRITABLE_STREAM"></a>
### ERR_CONSOLE_WRITABLE_STREAM ### ERR_CONSOLE_WRITABLE_STREAM

View File

@ -29,6 +29,7 @@ const { createPromise,
const debug = util.debuglog('child_process'); const debug = util.debuglog('child_process');
const { Buffer } = require('buffer'); const { Buffer } = require('buffer');
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap'); const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
const errors = require('internal/errors');
const { errname } = process.binding('uv'); const { errname } = process.binding('uv');
const child_process = require('internal/child_process'); const child_process = require('internal/child_process');
const { const {
@ -46,7 +47,7 @@ function stdioStringToArray(option) {
case 'inherit': case 'inherit':
return [option, option, option, 'ipc']; return [option, option, option, 'ipc'];
default: default:
throw new TypeError('Incorrect value of stdio option: ' + option); throw new errors.TypeError('ERR_INVALID_OPT_VALUE', 'stdio', option);
} }
} }
@ -63,7 +64,9 @@ exports.fork = function(modulePath /*, args, options*/) {
if (pos < arguments.length && arguments[pos] != null) { if (pos < arguments.length && arguments[pos] != null) {
if (typeof arguments[pos] !== 'object') { if (typeof arguments[pos] !== 'object') {
throw new TypeError('Incorrect value of args option'); throw new errors.TypeError('ERR_INVALID_ARG_VALUE',
`arguments[${pos}]`,
arguments[pos]);
} }
options = util._extend({}, arguments[pos++]); options = util._extend({}, arguments[pos++]);
@ -91,7 +94,8 @@ exports.fork = function(modulePath /*, args, options*/) {
options.stdio = options.silent ? stdioStringToArray('pipe') : options.stdio = options.silent ? stdioStringToArray('pipe') :
stdioStringToArray('inherit'); stdioStringToArray('inherit');
} else if (options.stdio.indexOf('ipc') === -1) { } else if (options.stdio.indexOf('ipc') === -1) {
throw new TypeError('Forked processes must have an IPC channel'); throw new errors.Error('ERR_CHILD_PROCESS_IPC_REQUIRED',
'options.stdio');
} }
options.execPath = options.execPath || process.execPath; options.execPath = options.execPath || process.execPath;
@ -195,7 +199,7 @@ exports.execFile = function(file /*, args, options, callback*/) {
} }
if (!callback && pos < arguments.length && arguments[pos] != null) { if (!callback && pos < arguments.length && arguments[pos] != null) {
throw new TypeError('Incorrect value of args option'); throw new errors.TypeError('ERR_INVALID_ARG_VALUE', 'args', arguments[pos]);
} }
// Validate the timeout, if present. // Validate the timeout, if present.
@ -322,7 +326,8 @@ exports.execFile = function(file /*, args, options, callback*/) {
stdoutLen += encoding ? Buffer.byteLength(chunk, encoding) : chunk.length; stdoutLen += encoding ? Buffer.byteLength(chunk, encoding) : chunk.length;
if (stdoutLen > options.maxBuffer) { if (stdoutLen > options.maxBuffer) {
ex = new Error('stdout maxBuffer exceeded'); ex = new errors.RangeError('ERR_CHILD_PROCESS_STDIO_MAXBUFFER',
'stdout');
kill(); kill();
} else if (encoding) { } else if (encoding) {
_stdout += chunk; _stdout += chunk;
@ -340,7 +345,8 @@ exports.execFile = function(file /*, args, options, callback*/) {
stderrLen += encoding ? Buffer.byteLength(chunk, encoding) : chunk.length; stderrLen += encoding ? Buffer.byteLength(chunk, encoding) : chunk.length;
if (stderrLen > options.maxBuffer) { if (stderrLen > options.maxBuffer) {
ex = new Error('stderr maxBuffer exceeded'); ex = new errors.RangeError('ERR_CHILD_PROCESS_STDIO_MAXBUFFER',
'stderr');
kill(); kill();
} else if (encoding) { } else if (encoding) {
_stderr += chunk; _stderr += chunk;
@ -377,13 +383,13 @@ function _convertCustomFds(options) {
function normalizeSpawnArguments(file, args, options) { function normalizeSpawnArguments(file, args, options) {
if (typeof file !== 'string' || file.length === 0) if (typeof file !== 'string' || file.length === 0)
throw new TypeError('"file" argument must be a non-empty string'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'file', 'string', file);
if (Array.isArray(args)) { if (Array.isArray(args)) {
args = args.slice(0); args = args.slice(0);
} else if (args !== undefined && } else if (args !== undefined &&
(args === null || typeof args !== 'object')) { (args === null || typeof args !== 'object')) {
throw new TypeError('Incorrect value of args option'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'args', 'object', args);
} else { } else {
options = args; options = args;
args = []; args = [];
@ -392,41 +398,62 @@ function normalizeSpawnArguments(file, args, options) {
if (options === undefined) if (options === undefined)
options = {}; options = {};
else if (options === null || typeof options !== 'object') else if (options === null || typeof options !== 'object')
throw new TypeError('"options" argument must be an object'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'options',
'object',
options);
// Validate the cwd, if present. // Validate the cwd, if present.
if (options.cwd != null && if (options.cwd != null &&
typeof options.cwd !== 'string') { typeof options.cwd !== 'string') {
throw new TypeError('"cwd" must be a string'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'options.cwd',
'string',
options.cwd);
} }
// Validate detached, if present. // Validate detached, if present.
if (options.detached != null && if (options.detached != null &&
typeof options.detached !== 'boolean') { typeof options.detached !== 'boolean') {
throw new TypeError('"detached" must be a boolean'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'options.detached',
'boolean',
options.detached);
} }
// Validate the uid, if present. // Validate the uid, if present.
if (options.uid != null && !Number.isInteger(options.uid)) { if (options.uid != null && !Number.isInteger(options.uid)) {
throw new TypeError('"uid" must be an integer'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'options.uid',
'integer',
options.uid);
} }
// Validate the gid, if present. // Validate the gid, if present.
if (options.gid != null && !Number.isInteger(options.gid)) { if (options.gid != null && !Number.isInteger(options.gid)) {
throw new TypeError('"gid" must be an integer'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'options.gid',
'integer',
options.gid);
} }
// Validate the shell, if present. // Validate the shell, if present.
if (options.shell != null && if (options.shell != null &&
typeof options.shell !== 'boolean' && typeof options.shell !== 'boolean' &&
typeof options.shell !== 'string') { typeof options.shell !== 'string') {
throw new TypeError('"shell" must be a boolean or string'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'options.shell',
['boolean', 'string'],
options.shell);
} }
// Validate argv0, if present. // Validate argv0, if present.
if (options.argv0 != null && if (options.argv0 != null &&
typeof options.argv0 !== 'string') { typeof options.argv0 !== 'string') {
throw new TypeError('"argv0" must be a string'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'options.argv0',
'string',
options.argv0);
} }
// Validate windowsHide, if present. // Validate windowsHide, if present.
@ -438,7 +465,10 @@ function normalizeSpawnArguments(file, args, options) {
// Validate windowsVerbatimArguments, if present. // Validate windowsVerbatimArguments, if present.
if (options.windowsVerbatimArguments != null && if (options.windowsVerbatimArguments != null &&
typeof options.windowsVerbatimArguments !== 'boolean') { typeof options.windowsVerbatimArguments !== 'boolean') {
throw new TypeError('"windowsVerbatimArguments" must be a boolean'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'options.windowsVerbatimArguments',
'boolean',
options.windowsVerbatimArguments);
} }
// Make a shallow copy so we don't clobber the user's options object. // Make a shallow copy so we don't clobber the user's options object.
@ -549,10 +579,10 @@ function spawnSync(/*file, args, options*/) {
} else if (typeof input === 'string') { } else if (typeof input === 'string') {
pipe.input = Buffer.from(input, options.encoding); pipe.input = Buffer.from(input, options.encoding);
} else { } else {
throw new TypeError(util.format( throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'stdio[%d] should be Buffer, Uint8Array or string not %s', ('options.stdio[' + i + ']'),
i, ['Buffer', 'Uint8Array', 'string'],
typeof input)); input);
} }
} }
} }
@ -620,14 +650,20 @@ exports.execSync = execSync;
function validateTimeout(timeout) { function validateTimeout(timeout) {
if (timeout != null && !(Number.isInteger(timeout) && timeout >= 0)) { if (timeout != null && !(Number.isInteger(timeout) && timeout >= 0)) {
throw new TypeError('"timeout" must be an unsigned integer'); throw new errors.RangeError('ERR_VALUE_OUT_OF_RANGE',
'timeout',
'an unsigned integer',
timeout);
} }
} }
function validateMaxBuffer(maxBuffer) { function validateMaxBuffer(maxBuffer) {
if (maxBuffer != null && !(typeof maxBuffer === 'number' && maxBuffer >= 0)) { if (maxBuffer != null && !(typeof maxBuffer === 'number' && maxBuffer >= 0)) {
throw new TypeError('"maxBuffer" must be a positive number'); throw new errors.RangeError('ERR_VALUE_OUT_OF_RANGE',
'options.maxBuffer',
'a positive number',
maxBuffer);
} }
} }
@ -636,6 +672,9 @@ function sanitizeKillSignal(killSignal) {
if (typeof killSignal === 'string' || typeof killSignal === 'number') { if (typeof killSignal === 'string' || typeof killSignal === 'number') {
return convertToValidSignal(killSignal); return convertToValidSignal(killSignal);
} else if (killSignal != null) { } else if (killSignal != null) {
throw new TypeError('"killSignal" must be a string or number'); throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'options.killSignal',
['string', 'number'],
killSignal);
} }
} }

View File

@ -272,6 +272,9 @@ E('ERR_BUFFER_TOO_LARGE',
`Cannot create a Buffer larger than 0x${kMaxLength.toString(16)} bytes`); `Cannot create a Buffer larger than 0x${kMaxLength.toString(16)} bytes`);
E('ERR_CANNOT_WATCH_SIGINT', 'Cannot watch for SIGINT signals'); E('ERR_CANNOT_WATCH_SIGINT', 'Cannot watch for SIGINT signals');
E('ERR_CHILD_CLOSED_BEFORE_REPLY', 'Child closed before reply received'); E('ERR_CHILD_CLOSED_BEFORE_REPLY', 'Child closed before reply received');
E('ERR_CHILD_PROCESS_IPC_REQUIRED',
"Forked processes must have an IPC channel, missing value 'ipc' in %s");
E('ERR_CHILD_PROCESS_STDIO_MAXBUFFER', '%s maxBuffer length exceeded');
E('ERR_CONSOLE_WRITABLE_STREAM', E('ERR_CONSOLE_WRITABLE_STREAM',
'Console expects a writable stream instance for %s'); 'Console expects a writable stream instance for %s');
E('ERR_CPU_USAGE', 'Unable to obtain cpu usage %s'); E('ERR_CPU_USAGE', 'Unable to obtain cpu usage %s');

View File

@ -5,8 +5,9 @@ const cp = require('child_process');
function checkFactory(streamName) { function checkFactory(streamName) {
return common.mustCall((err) => { return common.mustCall((err) => {
const message = `${streamName} maxBuffer exceeded`; assert.strictEqual(err.message, `${streamName} maxBuffer length exceeded`);
assert.strictEqual(err.message, message); assert(err instanceof RangeError);
assert.strictEqual(err.code, 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER');
}); });
} }

View File

@ -10,11 +10,12 @@ const fork = require('child_process').fork;
const fixtures = require('../common/fixtures'); const fixtures = require('../common/fixtures');
const childScript = fixtures.path('child-process-spawn-node'); const childScript = fixtures.path('child-process-spawn-node');
const errorRegexp = /^TypeError: Incorrect value of stdio option:/;
const malFormedOpts = { stdio: '33' }; const malFormedOpts = { stdio: '33' };
const payload = { hello: 'world' }; const payload = { hello: 'world' };
assert.throws(() => fork(childScript, malFormedOpts), errorRegexp); common.expectsError(
() => fork(childScript, malFormedOpts),
{ code: 'ERR_INVALID_OPT_VALUE', type: TypeError });
function test(stringVariant) { function test(stringVariant) {
const child = fork(childScript, { stdio: stringVariant }); const child = fork(childScript, { stdio: stringVariant });

View File

@ -19,9 +19,9 @@ if (process.argv[2] === 'child') {
process.send(data); process.send(data);
}); });
} else { } else {
assert.throws(() => { common.expectsError(
cp.fork(__filename, { stdio: ['pipe', 'pipe', 'pipe', 'pipe'] }); () => cp.fork(__filename, { stdio: ['pipe', 'pipe', 'pipe', 'pipe'] }),
}, /Forked processes must have an IPC channel/); { code: 'ERR_CHILD_PROCESS_IPC_REQUIRED', type: Error });
let ipc = ''; let ipc = '';
let stderr = ''; let stderr = '';

View File

@ -26,13 +26,15 @@ const { spawn, fork, execFile } = require('child_process');
const fixtures = require('../common/fixtures'); const fixtures = require('../common/fixtures');
const cmd = common.isWindows ? 'rundll32' : 'ls'; const cmd = common.isWindows ? 'rundll32' : 'ls';
const invalidcmd = 'hopefully_you_dont_have_this_on_your_machine'; const invalidcmd = 'hopefully_you_dont_have_this_on_your_machine';
const invalidArgsMsg = /Incorrect value of args option/;
const invalidOptionsMsg = /"options" argument must be an object/;
const invalidFileMsg =
/^TypeError: "file" argument must be a non-empty string$/;
const empty = fixtures.path('empty.js'); const empty = fixtures.path('empty.js');
const invalidArgValueError =
common.expectsError({ code: 'ERR_INVALID_ARG_VALUE', type: TypeError }, 13);
const invalidArgTypeError =
common.expectsError({ code: 'ERR_INVALID_ARG_TYPE', type: TypeError }, 11);
assert.throws(function() { assert.throws(function() {
const child = spawn(invalidcmd, 'this is not an array'); const child = spawn(invalidcmd, 'this is not an array');
child.on('error', common.mustNotCall()); child.on('error', common.mustNotCall());
@ -58,32 +60,32 @@ assert.doesNotThrow(function() {
// verify that invalid argument combinations throw // verify that invalid argument combinations throw
assert.throws(function() { assert.throws(function() {
spawn(); spawn();
}, invalidFileMsg); }, invalidArgTypeError);
assert.throws(function() { assert.throws(function() {
spawn(''); spawn('');
}, invalidFileMsg); }, invalidArgTypeError);
assert.throws(function() { assert.throws(function() {
const file = { toString() { throw new Error('foo'); } }; const file = { toString() { return null; } };
spawn(file); spawn(file);
}, invalidFileMsg); }, invalidArgTypeError);
assert.throws(function() { assert.throws(function() {
spawn(cmd, null); spawn(cmd, null);
}, invalidArgsMsg); }, invalidArgTypeError);
assert.throws(function() { assert.throws(function() {
spawn(cmd, true); spawn(cmd, true);
}, invalidArgsMsg); }, invalidArgTypeError);
assert.throws(function() { assert.throws(function() {
spawn(cmd, [], null); spawn(cmd, [], null);
}, invalidOptionsMsg); }, invalidArgTypeError);
assert.throws(function() { assert.throws(function() {
spawn(cmd, [], 1); spawn(cmd, [], 1);
}, invalidOptionsMsg); }, invalidArgTypeError);
// Argument types for combinatorics // Argument types for combinatorics
const a = []; const a = [];
@ -107,11 +109,11 @@ assert.doesNotThrow(function() { spawn(cmd, o); });
assert.doesNotThrow(function() { spawn(cmd, u, o); }); assert.doesNotThrow(function() { spawn(cmd, u, o); });
assert.doesNotThrow(function() { spawn(cmd, a, u); }); assert.doesNotThrow(function() { spawn(cmd, a, u); });
assert.throws(function() { spawn(cmd, n, o); }, TypeError); assert.throws(function() { spawn(cmd, n, o); }, invalidArgTypeError);
assert.throws(function() { spawn(cmd, a, n); }, TypeError); assert.throws(function() { spawn(cmd, a, n); }, invalidArgTypeError);
assert.throws(function() { spawn(cmd, s); }, TypeError); assert.throws(function() { spawn(cmd, s); }, invalidArgTypeError);
assert.throws(function() { spawn(cmd, a, s); }, TypeError); assert.throws(function() { spawn(cmd, a, s); }, invalidArgTypeError);
// verify that execFile has same argument parsing behaviour as spawn // verify that execFile has same argument parsing behaviour as spawn
@ -160,17 +162,17 @@ assert.doesNotThrow(function() { execFile(cmd, c, n); });
// string is invalid in arg position (this may seem strange, but is // string is invalid in arg position (this may seem strange, but is
// consistent across node API, cf. `net.createServer('not options', 'not // consistent across node API, cf. `net.createServer('not options', 'not
// callback')` // callback')`
assert.throws(function() { execFile(cmd, s, o, c); }, TypeError); assert.throws(function() { execFile(cmd, s, o, c); }, invalidArgValueError);
assert.throws(function() { execFile(cmd, a, s, c); }, TypeError); assert.throws(function() { execFile(cmd, a, s, c); }, invalidArgValueError);
assert.throws(function() { execFile(cmd, a, o, s); }, TypeError); assert.throws(function() { execFile(cmd, a, o, s); }, invalidArgValueError);
assert.throws(function() { execFile(cmd, a, s); }, TypeError); assert.throws(function() { execFile(cmd, a, s); }, invalidArgValueError);
assert.throws(function() { execFile(cmd, o, s); }, TypeError); assert.throws(function() { execFile(cmd, o, s); }, invalidArgValueError);
assert.throws(function() { execFile(cmd, u, u, s); }, TypeError); assert.throws(function() { execFile(cmd, u, u, s); }, invalidArgValueError);
assert.throws(function() { execFile(cmd, n, n, s); }, TypeError); assert.throws(function() { execFile(cmd, n, n, s); }, invalidArgValueError);
assert.throws(function() { execFile(cmd, a, u, s); }, TypeError); assert.throws(function() { execFile(cmd, a, u, s); }, invalidArgValueError);
assert.throws(function() { execFile(cmd, a, n, s); }, TypeError); assert.throws(function() { execFile(cmd, a, n, s); }, invalidArgValueError);
assert.throws(function() { execFile(cmd, u, o, s); }, TypeError); assert.throws(function() { execFile(cmd, u, o, s); }, invalidArgValueError);
assert.throws(function() { execFile(cmd, n, o, s); }, TypeError); assert.throws(function() { execFile(cmd, n, o, s); }, invalidArgValueError);
assert.doesNotThrow(function() { execFile(cmd, c, s); }); assert.doesNotThrow(function() { execFile(cmd, c, s); });
@ -192,5 +194,5 @@ assert.doesNotThrow(function() { fork(empty, n, n); });
assert.doesNotThrow(function() { fork(empty, n, o); }); assert.doesNotThrow(function() { fork(empty, n, o); });
assert.doesNotThrow(function() { fork(empty, a, n); }); assert.doesNotThrow(function() { fork(empty, a, n); });
assert.throws(function() { fork(empty, s); }, TypeError); assert.throws(function() { fork(empty, s); }, invalidArgValueError);
assert.throws(function() { fork(empty, a, s); }, TypeError); assert.throws(function() { fork(empty, a, s); }, invalidArgValueError);

View File

@ -20,7 +20,7 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE. // USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict'; 'use strict';
require('../common'); const common = require('../common');
const assert = require('assert'); const assert = require('assert');
@ -76,10 +76,9 @@ let options = {
input: 1234 input: 1234
}; };
assert.throws(function() { common.expectsError(
spawnSync('cat', [], options); () => spawnSync('cat', [], options),
}, /TypeError:.*should be Buffer, Uint8Array or string not number/); { code: 'ERR_INVALID_ARG_TYPE', type: TypeError });
options = { options = {
input: 'hello world' input: 'hello world'

View File

@ -4,6 +4,19 @@ const assert = require('assert');
const spawnSync = require('child_process').spawnSync; const spawnSync = require('child_process').spawnSync;
const signals = process.binding('constants').os.signals; const signals = process.binding('constants').os.signals;
let invalidArgTypeError;
if (common.isWindows) {
invalidArgTypeError =
common.expectsError({ code: 'ERR_INVALID_ARG_TYPE', type: TypeError }, 36);
} else {
invalidArgTypeError =
common.expectsError({ code: 'ERR_INVALID_ARG_TYPE', type: TypeError }, 56);
}
const invalidRangeError =
common.expectsError({ code: 'ERR_VALUE_OUT_OF_RANGE', type: RangeError }, 20);
function pass(option, value) { function pass(option, value) {
// Run the command with the specified option. Since it's not a real command, // Run the command with the specified option. Since it's not a real command,
// spawnSync() should run successfully but return an ENOENT error. // spawnSync() should run successfully but return an ENOENT error.
@ -20,108 +33,96 @@ function fail(option, value, message) {
{ {
// Validate the cwd option // Validate the cwd option
const err = /^TypeError: "cwd" must be a string$/;
pass('cwd', undefined); pass('cwd', undefined);
pass('cwd', null); pass('cwd', null);
pass('cwd', __dirname); pass('cwd', __dirname);
fail('cwd', 0, err); fail('cwd', 0, invalidArgTypeError);
fail('cwd', 1, err); fail('cwd', 1, invalidArgTypeError);
fail('cwd', true, err); fail('cwd', true, invalidArgTypeError);
fail('cwd', false, err); fail('cwd', false, invalidArgTypeError);
fail('cwd', [], err); fail('cwd', [], invalidArgTypeError);
fail('cwd', {}, err); fail('cwd', {}, invalidArgTypeError);
fail('cwd', common.mustNotCall(), err); fail('cwd', common.mustNotCall(), invalidArgTypeError);
} }
{ {
// Validate the detached option // Validate the detached option
const err = /^TypeError: "detached" must be a boolean$/;
pass('detached', undefined); pass('detached', undefined);
pass('detached', null); pass('detached', null);
pass('detached', true); pass('detached', true);
pass('detached', false); pass('detached', false);
fail('detached', 0, err); fail('detached', 0, invalidArgTypeError);
fail('detached', 1, err); fail('detached', 1, invalidArgTypeError);
fail('detached', __dirname, err); fail('detached', __dirname, invalidArgTypeError);
fail('detached', [], err); fail('detached', [], invalidArgTypeError);
fail('detached', {}, err); fail('detached', {}, invalidArgTypeError);
fail('detached', common.mustNotCall(), err); fail('detached', common.mustNotCall(), invalidArgTypeError);
} }
if (!common.isWindows) { if (!common.isWindows) {
{ {
// Validate the uid option // Validate the uid option
if (process.getuid() !== 0) { if (process.getuid() !== 0) {
const err = /^TypeError: "uid" must be an integer$/;
pass('uid', undefined); pass('uid', undefined);
pass('uid', null); pass('uid', null);
pass('uid', process.getuid()); pass('uid', process.getuid());
fail('uid', __dirname, err); fail('uid', __dirname, invalidArgTypeError);
fail('uid', true, err); fail('uid', true, invalidArgTypeError);
fail('uid', false, err); fail('uid', false, invalidArgTypeError);
fail('uid', [], err); fail('uid', [], invalidArgTypeError);
fail('uid', {}, err); fail('uid', {}, invalidArgTypeError);
fail('uid', common.mustNotCall(), err); fail('uid', common.mustNotCall(), invalidArgTypeError);
fail('uid', NaN, err); fail('uid', NaN, invalidArgTypeError);
fail('uid', Infinity, err); fail('uid', Infinity, invalidArgTypeError);
fail('uid', 3.1, err); fail('uid', 3.1, invalidArgTypeError);
fail('uid', -3.1, err); fail('uid', -3.1, invalidArgTypeError);
} }
} }
{ {
// Validate the gid option // Validate the gid option
if (process.getgid() !== 0) { if (process.getgid() !== 0) {
const err = /^TypeError: "gid" must be an integer$/;
pass('gid', undefined); pass('gid', undefined);
pass('gid', null); pass('gid', null);
pass('gid', process.getgid()); pass('gid', process.getgid());
fail('gid', __dirname, err); fail('gid', __dirname, invalidArgTypeError);
fail('gid', true, err); fail('gid', true, invalidArgTypeError);
fail('gid', false, err); fail('gid', false, invalidArgTypeError);
fail('gid', [], err); fail('gid', [], invalidArgTypeError);
fail('gid', {}, err); fail('gid', {}, invalidArgTypeError);
fail('gid', common.mustNotCall(), err); fail('gid', common.mustNotCall(), invalidArgTypeError);
fail('gid', NaN, err); fail('gid', NaN, invalidArgTypeError);
fail('gid', Infinity, err); fail('gid', Infinity, invalidArgTypeError);
fail('gid', 3.1, err); fail('gid', 3.1, invalidArgTypeError);
fail('gid', -3.1, err); fail('gid', -3.1, invalidArgTypeError);
} }
} }
} }
{ {
// Validate the shell option // Validate the shell option
const err = /^TypeError: "shell" must be a boolean or string$/;
pass('shell', undefined); pass('shell', undefined);
pass('shell', null); pass('shell', null);
pass('shell', false); pass('shell', false);
fail('shell', 0, err); fail('shell', 0, invalidArgTypeError);
fail('shell', 1, err); fail('shell', 1, invalidArgTypeError);
fail('shell', [], err); fail('shell', [], invalidArgTypeError);
fail('shell', {}, err); fail('shell', {}, invalidArgTypeError);
fail('shell', common.mustNotCall(), err); fail('shell', common.mustNotCall(), invalidArgTypeError);
} }
{ {
// Validate the argv0 option // Validate the argv0 option
const err = /^TypeError: "argv0" must be a string$/;
pass('argv0', undefined); pass('argv0', undefined);
pass('argv0', null); pass('argv0', null);
pass('argv0', 'myArgv0'); pass('argv0', 'myArgv0');
fail('argv0', 0, err); fail('argv0', 0, invalidArgTypeError);
fail('argv0', 1, err); fail('argv0', 1, invalidArgTypeError);
fail('argv0', true, err); fail('argv0', true, invalidArgTypeError);
fail('argv0', false, err); fail('argv0', false, invalidArgTypeError);
fail('argv0', [], err); fail('argv0', [], invalidArgTypeError);
fail('argv0', {}, err); fail('argv0', {}, invalidArgTypeError);
fail('argv0', common.mustNotCall(), err); fail('argv0', common.mustNotCall(), invalidArgTypeError);
} }
{ {
@ -142,65 +143,58 @@ if (!common.isWindows) {
{ {
// Validate the windowsVerbatimArguments option // Validate the windowsVerbatimArguments option
const err = /^TypeError: "windowsVerbatimArguments" must be a boolean$/;
pass('windowsVerbatimArguments', undefined); pass('windowsVerbatimArguments', undefined);
pass('windowsVerbatimArguments', null); pass('windowsVerbatimArguments', null);
pass('windowsVerbatimArguments', true); pass('windowsVerbatimArguments', true);
pass('windowsVerbatimArguments', false); pass('windowsVerbatimArguments', false);
fail('windowsVerbatimArguments', 0, err); fail('windowsVerbatimArguments', 0, invalidArgTypeError);
fail('windowsVerbatimArguments', 1, err); fail('windowsVerbatimArguments', 1, invalidArgTypeError);
fail('windowsVerbatimArguments', __dirname, err); fail('windowsVerbatimArguments', __dirname, invalidArgTypeError);
fail('windowsVerbatimArguments', [], err); fail('windowsVerbatimArguments', [], invalidArgTypeError);
fail('windowsVerbatimArguments', {}, err); fail('windowsVerbatimArguments', {}, invalidArgTypeError);
fail('windowsVerbatimArguments', common.mustNotCall(), err); fail('windowsVerbatimArguments', common.mustNotCall(), invalidArgTypeError);
} }
{ {
// Validate the timeout option // Validate the timeout option
const err = /^TypeError: "timeout" must be an unsigned integer$/;
pass('timeout', undefined); pass('timeout', undefined);
pass('timeout', null); pass('timeout', null);
pass('timeout', 1); pass('timeout', 1);
pass('timeout', 0); pass('timeout', 0);
fail('timeout', -1, err); fail('timeout', -1, invalidRangeError);
fail('timeout', true, err); fail('timeout', true, invalidRangeError);
fail('timeout', false, err); fail('timeout', false, invalidRangeError);
fail('timeout', __dirname, err); fail('timeout', __dirname, invalidRangeError);
fail('timeout', [], err); fail('timeout', [], invalidRangeError);
fail('timeout', {}, err); fail('timeout', {}, invalidRangeError);
fail('timeout', common.mustNotCall(), err); fail('timeout', common.mustNotCall(), invalidRangeError);
fail('timeout', NaN, err); fail('timeout', NaN, invalidRangeError);
fail('timeout', Infinity, err); fail('timeout', Infinity, invalidRangeError);
fail('timeout', 3.1, err); fail('timeout', 3.1, invalidRangeError);
fail('timeout', -3.1, err); fail('timeout', -3.1, invalidRangeError);
} }
{ {
// Validate the maxBuffer option // Validate the maxBuffer option
const err = /^TypeError: "maxBuffer" must be a positive number$/;
pass('maxBuffer', undefined); pass('maxBuffer', undefined);
pass('maxBuffer', null); pass('maxBuffer', null);
pass('maxBuffer', 1); pass('maxBuffer', 1);
pass('maxBuffer', 0); pass('maxBuffer', 0);
pass('maxBuffer', Infinity); pass('maxBuffer', Infinity);
pass('maxBuffer', 3.14); pass('maxBuffer', 3.14);
fail('maxBuffer', -1, err); fail('maxBuffer', -1, invalidRangeError);
fail('maxBuffer', NaN, err); fail('maxBuffer', NaN, invalidRangeError);
fail('maxBuffer', -Infinity, err); fail('maxBuffer', -Infinity, invalidRangeError);
fail('maxBuffer', true, err); fail('maxBuffer', true, invalidRangeError);
fail('maxBuffer', false, err); fail('maxBuffer', false, invalidRangeError);
fail('maxBuffer', __dirname, err); fail('maxBuffer', __dirname, invalidRangeError);
fail('maxBuffer', [], err); fail('maxBuffer', [], invalidRangeError);
fail('maxBuffer', {}, err); fail('maxBuffer', {}, invalidRangeError);
fail('maxBuffer', common.mustNotCall(), err); fail('maxBuffer', common.mustNotCall(), invalidRangeError);
} }
{ {
// Validate the killSignal option // Validate the killSignal option
const typeErr = /^TypeError: "killSignal" must be a string or number$/;
const unknownSignalErr = const unknownSignalErr =
common.expectsError({ code: 'ERR_UNKNOWN_SIGNAL', type: TypeError }, 17); common.expectsError({ code: 'ERR_UNKNOWN_SIGNAL', type: TypeError }, 17);
@ -208,11 +202,11 @@ if (!common.isWindows) {
pass('killSignal', null); pass('killSignal', null);
pass('killSignal', 'SIGKILL'); pass('killSignal', 'SIGKILL');
fail('killSignal', 'SIGNOTAVALIDSIGNALNAME', unknownSignalErr); fail('killSignal', 'SIGNOTAVALIDSIGNALNAME', unknownSignalErr);
fail('killSignal', true, typeErr); fail('killSignal', true, invalidArgTypeError);
fail('killSignal', false, typeErr); fail('killSignal', false, invalidArgTypeError);
fail('killSignal', [], typeErr); fail('killSignal', [], invalidArgTypeError);
fail('killSignal', {}, typeErr); fail('killSignal', {}, invalidArgTypeError);
fail('killSignal', common.mustNotCall(), typeErr); fail('killSignal', common.mustNotCall(), invalidArgTypeError);
// Invalid signal names and numbers should fail // Invalid signal names and numbers should fail
fail('killSignal', 500, unknownSignalErr); fail('killSignal', 500, unknownSignalErr);