errors: validate input arguments

This makes sure the input arguments get validated so implementation
errors will be caught early. It also improves a couple of error
messages by providing more detailed information and fixes errors
detected by the new functionality. Besides that a error type got
simplified and tests got refactored.

PR-URL: https://github.com/nodejs/node/pull/19924
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Ruben Bridgewater 2018-04-11 03:10:22 +02:00
parent d5495e859c
commit dca7fb2225
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
18 changed files with 215 additions and 178 deletions

View File

@ -920,7 +920,7 @@ Buffer.prototype.write = function write(string, offset, length, encoding) {
length = remaining;
if (string.length > 0 && (length < 0 || offset < 0))
throw new ERR_BUFFER_OUT_OF_BOUNDS('length', true);
throw new ERR_BUFFER_OUT_OF_BOUNDS();
} else {
// if someone is still calling the obsolete form of write(), tell them.
// we don't want eg buf.write("foo", "utf8", 10) to silently turn into

View File

@ -1019,7 +1019,7 @@ fs.fchmod = function(fd, mode, callback) {
validateUint32(mode, 'mode');
// Values for mode < 0 are already checked via the validateUint32 function
if (mode > 0o777)
throw new ERR_OUT_OF_RANGE('mode');
throw new ERR_OUT_OF_RANGE('mode', undefined, mode);
const req = new FSReqWrap();
req.oncomplete = makeCallback(callback);
@ -1032,7 +1032,7 @@ fs.fchmodSync = function(fd, mode) {
validateUint32(mode, 'mode');
// Values for mode < 0 are already checked via the validateUint32 function
if (mode > 0o777)
throw new ERR_OUT_OF_RANGE('mode');
throw new ERR_OUT_OF_RANGE('mode', undefined, mode);
const ctx = {};
binding.fchmod(fd, mode, undefined, ctx);
handleErrorFromBinding(ctx);

View File

@ -373,7 +373,7 @@ async function fchmod(handle, mode) {
validateFileHandle(handle);
validateUint32(mode, 'mode');
if (mode > 0o777)
throw new ERR_OUT_OF_RANGE('mode');
throw new ERR_OUT_OF_RANGE('mode', undefined, mode);
return binding.fchmod(handle.fd, mode, kUsePromises);
}

View File

@ -50,7 +50,7 @@ function boundsError(value, length, type) {
}
if (length < 0)
throw new ERR_BUFFER_OUT_OF_BOUNDS(null, true);
throw new ERR_BUFFER_OUT_OF_BOUNDS();
throw new ERR_OUT_OF_RANGE(type || 'offset',
`>= ${type ? 1 : 0} and <= ${length}`,

View File

@ -64,11 +64,8 @@ function _pbkdf2(password, salt, iterations, keylen, digest, callback) {
if (typeof keylen !== 'number')
throw new ERR_INVALID_ARG_TYPE('keylen', 'number', keylen);
if (keylen < 0 ||
!Number.isFinite(keylen) ||
keylen > INT_MAX) {
throw new ERR_OUT_OF_RANGE('keylen');
}
if (keylen < 0 || !Number.isInteger(keylen) || keylen > INT_MAX)
throw new ERR_OUT_OF_RANGE('keylen', `>= 0 && <= ${INT_MAX}`, keylen);
const encoding = getDefaultEncoding();

View File

@ -416,20 +416,30 @@ function internalAssert(condition, message) {
}
}
function message(key, args) {
function message(key, args = []) {
const msg = messages.get(key);
internalAssert(msg, `An invalid error message key was used: ${key}.`);
let fmt;
if (util === undefined) util = require('util');
if (typeof msg === 'function') {
fmt = msg;
} else {
fmt = util.format;
if (args === undefined || args.length === 0)
return msg;
args.unshift(msg);
internalAssert(
msg.length <= args.length, // Default options do not count.
`Code: ${key}; The provided arguments length (${args.length}) does not ` +
`match the required ones (${msg.length}).`
);
return msg.apply(null, args);
}
return String(fmt.apply(null, args));
const expectedLength = (msg.match(/%[dfijoOs]/g) || []).length;
internalAssert(
expectedLength === args.length,
`Code: ${key}; The provided arguments length (${args.length}) does not ` +
`match the required ones (${expectedLength}).`
);
if (args.length === 0)
return msg;
args.unshift(msg);
return util.format.apply(null, args);
}
/**
@ -740,7 +750,7 @@ E('ERR_HTTP2_INVALID_SETTING_VALUE',
'Invalid value for setting "%s": %s', TypeError, RangeError);
E('ERR_HTTP2_INVALID_STREAM', 'The stream has been destroyed', Error);
E('ERR_HTTP2_MAX_PENDING_SETTINGS_ACK',
'Maximum number of pending settings acknowledgements (%s)', Error);
'Maximum number of pending settings acknowledgements', Error);
E('ERR_HTTP2_NO_SOCKET_MANIPULATION',
'HTTP/2 sockets should not be directly manipulated (e.g. read and written)',
Error);
@ -793,7 +803,7 @@ E('ERR_INVALID_ARG_VALUE', (name, value, reason = 'is invalid') => {
}, TypeError, RangeError);
E('ERR_INVALID_ARRAY_LENGTH',
(name, len, actual) => {
internalAssert(typeof actual === 'number', 'actual must be a number');
internalAssert(typeof actual === 'number', 'actual must be of type number');
return `The array "${name}" (length ${actual}) must be of length ${len}.`;
}, TypeError);
E('ERR_INVALID_ASYNC_ID', 'Invalid %s value: %s', RangeError);
@ -925,7 +935,9 @@ E('ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET',
Error);
E('ERR_UNESCAPED_CHARACTERS', '%s contains unescaped characters', TypeError);
E('ERR_UNHANDLED_ERROR',
(err) => {
// Using a default argument here is important so the argument is not counted
// towards `Function#length`.
(err = undefined) => {
const msg = 'Unhandled error.';
if (err === undefined) return msg;
return `${msg} (${err})`;
@ -960,7 +972,6 @@ E('ERR_VM_MODULE_STATUS', 'Module status %s', Error);
E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed', Error);
function invalidArgType(name, expected, actual) {
internalAssert(arguments.length === 3, 'Exactly 3 arguments are required');
internalAssert(typeof name === 'string', 'name must be a string');
// determiner: 'must be' or 'must not be'
@ -1007,8 +1018,7 @@ function missingArgs(...args) {
}
function oneOf(expected, thing) {
internalAssert(expected, 'expected is required');
internalAssert(typeof thing === 'string', 'thing is required');
internalAssert(typeof thing === 'string', '`thing` has to be of type string');
if (Array.isArray(expected)) {
const len = expected.length;
internalAssert(len > 0,
@ -1027,17 +1037,20 @@ function oneOf(expected, thing) {
}
}
function bufferOutOfBounds(name, isWriting) {
if (isWriting) {
return 'Attempt to write outside buffer bounds';
} else {
// Using a default argument here is important so the argument is not counted
// towards `Function#length`.
function bufferOutOfBounds(name = undefined) {
if (name) {
return `"${name}" is outside of buffer bounds`;
}
return 'Attempt to write outside buffer bounds';
}
function invalidChar(name, field) {
// Using a default argument here is important so the argument is not counted
// towards `Function#length`.
function invalidChar(name, field = undefined) {
let msg = `Invalid character in ${name}`;
if (field) {
if (field !== undefined) {
msg += ` ["${field}"]`;
}
return msg;
@ -1045,7 +1058,7 @@ function invalidChar(name, field) {
function outOfRange(name, range, value) {
let msg = `The value of "${name}" is out of range.`;
if (range) msg += ` It must be ${range}.`;
if (value !== undefined) msg += ` Received ${value}`;
if (range !== undefined) msg += ` It must be ${range}.`;
msg += ` Received ${value}`;
return msg;
}

View File

@ -368,9 +368,10 @@ function validateOffsetLengthRead(offset, length, bufferLength) {
let err;
if (offset < 0 || offset >= bufferLength) {
err = new ERR_OUT_OF_RANGE('offset');
err = new ERR_OUT_OF_RANGE('offset', `>= 0 && <= ${bufferLength}`, offset);
} else if (length < 0 || offset + length > bufferLength) {
err = new ERR_OUT_OF_RANGE('length');
err = new ERR_OUT_OF_RANGE('length',
`>= 0 && <= ${bufferLength - offset}`, length);
}
if (err !== undefined) {
@ -383,9 +384,12 @@ function validateOffsetLengthWrite(offset, length, byteLength) {
let err;
if (offset > byteLength) {
err = new ERR_OUT_OF_RANGE('offset');
} else if (offset + length > byteLength || offset + length > kMaxLength) {
err = new ERR_OUT_OF_RANGE('length');
err = new ERR_OUT_OF_RANGE('offset', `<= ${byteLength}`, offset);
} else {
const max = byteLength > kMaxLength ? kMaxLength : byteLength;
if (length > max - offset) {
err = new ERR_OUT_OF_RANGE('length', `<= ${max - offset}`, length);
}
}
if (err !== undefined) {

View File

@ -1312,8 +1312,10 @@ class ServerHttp2Session extends Http2Session {
if (origin === 'null')
throw new ERR_HTTP2_ALTSVC_INVALID_ORIGIN();
} else if (typeof originOrStream === 'number') {
if (originOrStream >>> 0 !== originOrStream || originOrStream === 0)
throw new ERR_OUT_OF_RANGE('originOrStream');
if (originOrStream >>> 0 !== originOrStream || originOrStream === 0) {
throw new ERR_OUT_OF_RANGE('originOrStream',
`> 0 && < ${2 ** 32}`, originOrStream);
}
stream = originOrStream;
} else if (originOrStream !== undefined) {
// Allow origin to be passed a URL or object with origin property
@ -1764,7 +1766,7 @@ class Http2Stream extends Duplex {
if (typeof code !== 'number')
throw new ERR_INVALID_ARG_TYPE('code', 'number', code);
if (code < 0 || code > kMaxInt)
throw new ERR_OUT_OF_RANGE('code');
throw new ERR_OUT_OF_RANGE('code', `>= 0 && <= ${kMaxInt}`, code);
if (callback !== undefined && typeof callback !== 'function')
throw new ERR_INVALID_CALLBACK();

View File

@ -1,6 +1,6 @@
'use strict';
const common = require('../common');
require('../common');
const assert = require('assert');
const LENGTH = 16;
@ -58,14 +58,14 @@ assert.throws(function() {
buf[0] = 9;
assert.strictEqual(ab[1], 9);
common.expectsError(() => Buffer.from(ab.buffer, 6), {
assert.throws(() => Buffer.from(ab.buffer, 6), {
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
type: RangeError,
name: 'RangeError [ERR_BUFFER_OUT_OF_BOUNDS]',
message: '"offset" is outside of buffer bounds'
});
common.expectsError(() => Buffer.from(ab.buffer, 3, 6), {
assert.throws(() => Buffer.from(ab.buffer, 3, 6), {
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
type: RangeError,
name: 'RangeError [ERR_BUFFER_OUT_OF_BOUNDS]',
message: '"length" is outside of buffer bounds'
});
}
@ -86,14 +86,14 @@ assert.throws(function() {
buf[0] = 9;
assert.strictEqual(ab[1], 9);
common.expectsError(() => Buffer(ab.buffer, 6), {
assert.throws(() => Buffer(ab.buffer, 6), {
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
type: RangeError,
name: 'RangeError [ERR_BUFFER_OUT_OF_BOUNDS]',
message: '"offset" is outside of buffer bounds'
});
common.expectsError(() => Buffer(ab.buffer, 3, 6), {
assert.throws(() => Buffer(ab.buffer, 3, 6), {
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
type: RangeError,
name: 'RangeError [ERR_BUFFER_OUT_OF_BOUNDS]',
message: '"length" is outside of buffer bounds'
});
}
@ -111,11 +111,11 @@ assert.throws(function() {
assert.deepStrictEqual(Buffer.from(ab, [1]), Buffer.from(ab, 1));
// If byteOffset is Infinity, throw.
common.expectsError(() => {
assert.throws(() => {
Buffer.from(ab, Infinity);
}, {
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
type: RangeError,
name: 'RangeError [ERR_BUFFER_OUT_OF_BOUNDS]',
message: '"offset" is outside of buffer bounds'
});
}
@ -133,11 +133,11 @@ assert.throws(function() {
assert.deepStrictEqual(Buffer.from(ab, 0, [1]), Buffer.from(ab, 0, 1));
// If length is Infinity, throw.
common.expectsError(() => {
assert.throws(() => {
Buffer.from(ab, 0, Infinity);
}, {
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
type: RangeError,
name: 'RangeError [ERR_BUFFER_OUT_OF_BOUNDS]',
message: '"length" is outside of buffer bounds'
});
}

View File

@ -31,18 +31,26 @@ const n = fork(fixtures.path('child-process-spawn-node.js'), args);
assert.strictEqual(n.channel, n._channel);
assert.deepStrictEqual(args, ['foo', 'bar']);
n.on('message', function(m) {
n.on('message', (m) => {
console.log('PARENT got message:', m);
assert.ok(m.foo);
});
// https://github.com/joyent/node/issues/2355 - JSON.stringify(undefined)
// returns "undefined" but JSON.parse() cannot parse that...
assert.throws(function() { n.send(undefined); }, TypeError);
assert.throws(function() { n.send(); }, TypeError);
assert.throws(() => n.send(undefined), {
name: 'TypeError [ERR_MISSING_ARGS]',
message: 'The "message" argument must be specified',
code: 'ERR_MISSING_ARGS'
});
assert.throws(() => n.send(), {
name: 'TypeError [ERR_MISSING_ARGS]',
message: 'The "message" argument must be specified',
code: 'ERR_MISSING_ARGS'
});
n.send({ hello: 'world' });
n.on('exit', common.mustCall(function(c) {
n.on('exit', common.mustCall((c) => {
assert.strictEqual(c, 0);
}));

View File

@ -57,45 +57,46 @@ function ondone(err, key) {
}
// Error path should not leak memory (check with valgrind).
common.expectsError(
assert.throws(
() => crypto.pbkdf2('password', 'salt', 1, 20, null),
{
code: 'ERR_INVALID_CALLBACK',
type: TypeError
name: 'TypeError [ERR_INVALID_CALLBACK]'
}
);
common.expectsError(
assert.throws(
() => crypto.pbkdf2Sync('password', 'salt', -1, 20, null),
{
code: 'ERR_OUT_OF_RANGE',
type: RangeError,
name: 'RangeError [ERR_OUT_OF_RANGE]',
message: 'The value of "iterations" is out of range. ' +
'It must be a non-negative number. Received -1'
}
);
['str', null, undefined, [], {}].forEach((notNumber) => {
common.expectsError(
assert.throws(
() => {
crypto.pbkdf2Sync('password', 'salt', 1, notNumber, 'sha256');
}, {
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: 'The "keylen" argument must be of type number. ' +
`Received type ${typeof notNumber}`
});
});
[Infinity, -Infinity, NaN, -1, 4073741824, INT_MAX + 1].forEach((i) => {
common.expectsError(
[Infinity, -Infinity, NaN, -1, 4073741824, INT_MAX + 1].forEach((input) => {
assert.throws(
() => {
crypto.pbkdf2('password', 'salt', 1, i, 'sha256',
crypto.pbkdf2('password', 'salt', 1, input, 'sha256',
common.mustNotCall());
}, {
code: 'ERR_OUT_OF_RANGE',
type: RangeError,
message: 'The value of "keylen" is out of range.'
name: 'RangeError [ERR_OUT_OF_RANGE]',
message: 'The value of "keylen" is out of range. It ' +
`must be >= 0 && <= 2147483647. Received ${input}`
});
});
@ -103,58 +104,58 @@ common.expectsError(
// https://github.com/nodejs/node/issues/8571
crypto.pbkdf2('', '', 1, 32, 'sha256', common.mustCall(assert.ifError));
common.expectsError(
assert.throws(
() => crypto.pbkdf2('password', 'salt', 8, 8, common.mustNotCall()),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: 'The "digest" argument must be one of type string or null. ' +
'Received type undefined'
});
common.expectsError(
assert.throws(
() => crypto.pbkdf2Sync('password', 'salt', 8, 8),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: 'The "digest" argument must be one of type string or null. ' +
'Received type undefined'
});
[1, {}, [], true, undefined, null].forEach((input) => {
const msgPart2 = `Buffer, or TypedArray. Received type ${typeof input}`;
common.expectsError(
assert.throws(
() => crypto.pbkdf2(input, 'salt', 8, 8, 'sha256', common.mustNotCall()),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: `The "password" argument must be one of type string, ${msgPart2}`
}
);
common.expectsError(
assert.throws(
() => crypto.pbkdf2('pass', input, 8, 8, 'sha256', common.mustNotCall()),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: `The "salt" argument must be one of type string, ${msgPart2}`
}
);
common.expectsError(
assert.throws(
() => crypto.pbkdf2Sync(input, 'salt', 8, 8, 'sha256'),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: `The "password" argument must be one of type string, ${msgPart2}`
}
);
common.expectsError(
assert.throws(
() => crypto.pbkdf2Sync('pass', input, 8, 8, 'sha256'),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: `The "salt" argument must be one of type string, ${msgPart2}`
}
);
@ -162,20 +163,20 @@ common.expectsError(
['test', {}, [], true, undefined, null].forEach((i) => {
const received = `Received type ${typeof i}`;
common.expectsError(
assert.throws(
() => crypto.pbkdf2('pass', 'salt', i, 8, 'sha256', common.mustNotCall()),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: `The "iterations" argument must be of type number. ${received}`
}
);
common.expectsError(
assert.throws(
() => crypto.pbkdf2Sync('pass', 'salt', i, 8, 'sha256'),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: `The "iterations" argument must be of type number. ${received}`
}
);
@ -204,20 +205,20 @@ crypto.pbkdf2Sync('pass', new Float32Array(10), 8, 8, 'sha256');
crypto.pbkdf2Sync(new Float64Array(10), 'salt', 8, 8, 'sha256');
crypto.pbkdf2Sync('pass', new Float64Array(10), 8, 8, 'sha256');
common.expectsError(
assert.throws(
() => crypto.pbkdf2('pass', 'salt', 8, 8, 'md55', common.mustNotCall()),
{
code: 'ERR_CRYPTO_INVALID_DIGEST',
type: TypeError,
name: 'TypeError [ERR_CRYPTO_INVALID_DIGEST]',
message: 'Invalid digest: md55'
}
);
common.expectsError(
assert.throws(
() => crypto.pbkdf2Sync('pass', 'salt', 8, 8, 'md55'),
{
code: 'ERR_CRYPTO_INVALID_DIGEST',
type: TypeError,
name: 'TypeError [ERR_CRYPTO_INVALID_DIGEST]',
message: 'Invalid digest: md55'
}
);

View File

@ -1,19 +1,17 @@
// Flags: --expose-internals
'use strict';
const common = require('../common');
require('../common');
const assert = require('assert');
const errors = require('internal/errors');
const { AssertionError } = require('assert');
const { E, SystemError } = errors;
common.expectsError(
assert.throws(
() => { throw new errors.SystemError(); },
{
code: 'ERR_ASSERTION',
type: AssertionError,
message: 'An invalid error message key was used: undefined.'
name: 'TypeError',
message: 'Cannot read property \'match\' of undefined'
}
);
@ -29,11 +27,11 @@ const { ERR_TEST } = errors.codes;
dest: '/str2'
};
common.expectsError(
assert.throws(
() => { throw new ERR_TEST(ctx); },
{
code: 'ERR_TEST',
type: SystemError,
name: 'SystemError [ERR_TEST]',
message: 'custom message: syscall_test returned ETEST (code message)' +
' /str => /str2',
info: ctx
@ -49,11 +47,11 @@ const { ERR_TEST } = errors.codes;
path: Buffer.from('/buf'),
dest: '/str2'
};
common.expectsError(
assert.throws(
() => { throw new ERR_TEST(ctx); },
{
code: 'ERR_TEST',
type: SystemError,
name: 'SystemError [ERR_TEST]',
message: 'custom message: syscall_test returned ETEST (code message)' +
' /buf => /str2',
info: ctx
@ -69,11 +67,11 @@ const { ERR_TEST } = errors.codes;
path: Buffer.from('/buf'),
dest: Buffer.from('/buf2')
};
common.expectsError(
assert.throws(
() => { throw new ERR_TEST(ctx); },
{
code: 'ERR_TEST',
type: SystemError,
name: 'SystemError [ERR_TEST]',
message: 'custom message: syscall_test returned ETEST (code message)' +
' /buf => /buf2',
info: ctx

View File

@ -70,19 +70,19 @@ fs.fchmodSync(1, modeUpperBoundaryValue);
// umask of 0o777 is equal to 775
const modeOutsideUpperBoundValue = 776;
common.expectsError(
assert.throws(
() => fs.fchmod(1, modeOutsideUpperBoundValue),
{
code: 'ERR_OUT_OF_RANGE',
type: RangeError,
message: 'The value of "mode" is out of range.'
name: 'RangeError [ERR_OUT_OF_RANGE]',
message: 'The value of "mode" is out of range. Received 776'
}
);
common.expectsError(
assert.throws(
() => fs.fchmodSync(1, modeOutsideUpperBoundValue),
{
code: 'ERR_OUT_OF_RANGE',
type: RangeError,
message: 'The value of "mode" is out of range.'
name: 'RangeError [ERR_OUT_OF_RANGE]',
message: 'The value of "mode" is out of range. Received 776'
}
);

View File

@ -1,6 +1,7 @@
'use strict';
const common = require('../common');
const fs = require('fs');
const assert = require('assert');
const fixtures = require('../common/fixtures');
const filepath = fixtures.path('x.txt');
@ -9,18 +10,18 @@ const expected = 'xyz\n';
// Error must be thrown with string
common.expectsError(
assert.throws(
() => fs.read(fd, expected.length, 0, 'utf-8', common.mustNotCall()),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: 'The "buffer" argument must be one of type Buffer or Uint8Array.' +
' Received type number'
}
);
[true, null, undefined, () => {}, {}].forEach((value) => {
common.expectsError(() => {
assert.throws(() => {
fs.read(value,
Buffer.allocUnsafe(expected.length),
0,
@ -29,45 +30,53 @@ common.expectsError(
common.mustNotCall());
}, {
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: 'The "fd" argument must be of type number. ' +
`Received type ${typeof value}`
});
});
common.expectsError(() => {
assert.throws(() => {
fs.read(fd,
Buffer.allocUnsafe(expected.length),
-1,
expected.length,
0,
common.mustNotCall());
}, { code: 'ERR_OUT_OF_RANGE', type: RangeError,
message: 'The value of "offset" is out of range.' });
}, {
code: 'ERR_OUT_OF_RANGE',
name: 'RangeError [ERR_OUT_OF_RANGE]',
message: 'The value of "offset" is out of range. It must be >= 0 && <= 4. ' +
'Received -1'
});
common.expectsError(() => {
assert.throws(() => {
fs.read(fd,
Buffer.allocUnsafe(expected.length),
0,
-1,
0,
common.mustNotCall());
}, { code: 'ERR_OUT_OF_RANGE', type: RangeError,
message: 'The value of "length" is out of range.' });
}, {
code: 'ERR_OUT_OF_RANGE',
name: 'RangeError [ERR_OUT_OF_RANGE]',
message: 'The value of "length" is out of range. ' +
'It must be >= 0 && <= 4. Received -1'
});
common.expectsError(
assert.throws(
() => fs.readSync(fd, expected.length, 0, 'utf-8'),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: 'The "buffer" argument must be one of type Buffer or Uint8Array.' +
' Received type number'
}
);
[true, null, undefined, () => {}, {}].forEach((value) => {
common.expectsError(() => {
assert.throws(() => {
fs.readSync(value,
Buffer.allocUnsafe(expected.length),
0,
@ -75,26 +84,34 @@ common.expectsError(
0);
}, {
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
message: 'The "fd" argument must be of type number. ' +
`Received type ${typeof value}`
});
});
common.expectsError(() => {
assert.throws(() => {
fs.readSync(fd,
Buffer.allocUnsafe(expected.length),
-1,
expected.length,
0);
}, { code: 'ERR_OUT_OF_RANGE', type: RangeError,
message: 'The value of "offset" is out of range.' });
}, {
code: 'ERR_OUT_OF_RANGE',
name: 'RangeError [ERR_OUT_OF_RANGE]',
message: 'The value of "offset" is out of range. ' +
'It must be >= 0 && <= 4. Received -1'
});
common.expectsError(() => {
assert.throws(() => {
fs.readSync(fd,
Buffer.allocUnsafe(expected.length),
0,
-1,
0);
}, { code: 'ERR_OUT_OF_RANGE', type: RangeError,
message: 'The value of "length" is out of range.' });
}, {
code: 'ERR_OUT_OF_RANGE',
name: 'RangeError [ERR_OUT_OF_RANGE]',
message: 'The value of "length" is out of range. ' +
'It must be >= 0 && <= 4. Received -1'
});

View File

@ -28,43 +28,46 @@ server.on('session', common.mustCall((session) => {
session.altsvc('h2=":8000"', 3);
// Will error because the numeric stream id is out of valid range
[0, -1, 1.1, 0xFFFFFFFF + 1, Infinity, -Infinity].forEach((i) => {
common.expectsError(
() => session.altsvc('h2=":8000"', i),
[0, -1, 1.1, 0xFFFFFFFF + 1, Infinity, -Infinity].forEach((input) => {
assert.throws(
() => session.altsvc('h2=":8000"', input),
{
code: 'ERR_OUT_OF_RANGE',
type: RangeError
name: 'RangeError [ERR_OUT_OF_RANGE]',
message: 'The value of "originOrStream" is out of ' +
`range. It must be > 0 && < 4294967296. Received ${input}`
}
);
});
// First argument must be a string
[0, {}, [], null, Infinity].forEach((i) => {
common.expectsError(
() => session.altsvc(i),
[0, {}, [], null, Infinity].forEach((input) => {
assert.throws(
() => session.altsvc(input),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError
name: 'TypeError [ERR_INVALID_ARG_TYPE]'
}
);
});
['\u0001', 'h2="\uff20"', '👀'].forEach((i) => {
common.expectsError(
() => session.altsvc(i),
['\u0001', 'h2="\uff20"', '👀'].forEach((input) => {
assert.throws(
() => session.altsvc(input),
{
code: 'ERR_INVALID_CHAR',
type: TypeError
name: 'TypeError [ERR_INVALID_CHAR]',
message: 'Invalid character in alt'
}
);
});
[{}, [], true].forEach((i) => {
common.expectsError(
() => session.altsvc('clear', i),
[{}, [], true].forEach((input) => {
assert.throws(
() => session.altsvc('clear', input),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError
name: 'TypeError [ERR_INVALID_ARG_TYPE]'
}
);
});
@ -74,25 +77,27 @@ server.on('session', common.mustCall((session) => {
new URL('abc:'),
{ origin: 'null' },
{ origin: '' }
].forEach((i) => {
common.expectsError(
() => session.altsvc('h2=":8000', i),
].forEach((input) => {
assert.throws(
() => session.altsvc('h2=":8000', input),
{
code: 'ERR_HTTP2_ALTSVC_INVALID_ORIGIN',
type: TypeError
name: 'TypeError [ERR_HTTP2_ALTSVC_INVALID_ORIGIN]',
message: 'HTTP/2 ALTSVC frames require a valid origin'
}
);
});
// arguments + origin are too long for an ALTSVC frame
common.expectsError(
assert.throws(
() => {
session.altsvc('h2=":8000"',
`http://example.${'a'.repeat(17000)}.org:8000`);
},
{
code: 'ERR_HTTP2_ALTSVC_LENGTH',
type: TypeError
name: 'TypeError [ERR_HTTP2_ALTSVC_LENGTH]',
message: 'HTTP/2 ALTSVC frames are limited to 16382 bytes'
}
);
}));

View File

@ -18,12 +18,13 @@ server.listen(0, common.mustCall(() => {
const req = client.request();
const closeCode = 1;
common.expectsError(
assert.throws(
() => req.close(2 ** 32),
{
type: RangeError,
name: 'RangeError [ERR_OUT_OF_RANGE]',
code: 'ERR_OUT_OF_RANGE',
message: 'The value of "code" is out of range.'
message: 'The value of "code" is out of range. It must be ' +
'>= 0 && <= 4294967295. Received 4294967296'
}
);
assert.strictEqual(req.closed, false);

View File

@ -42,11 +42,13 @@ errors.E('TEST_ERROR_2', (a, b) => `${a} ${b}`, Error);
}
{
const err = new errors.codes.TEST_ERROR_1();
assert(err instanceof Error);
assert.strictEqual(err.name, 'Error [TEST_ERROR_1]');
assert.strictEqual(err.message, 'Error for testing purposes: %s');
assert.strictEqual(err.code, 'TEST_ERROR_1');
assert.throws(
() => new errors.codes.TEST_ERROR_1(),
{
message: 'Code: TEST_ERROR_1; The provided arguments ' +
'length (0) does not match the required ones (1).'
}
);
}
// Tests for common.expectsError
@ -156,16 +158,6 @@ assert.strictEqual(
'Method must be a valid HTTP token ["foo"]'
);
assert.strictEqual(
errors.message('ERR_OUT_OF_RANGE', ['A']),
'The value of "A" is out of range.'
);
assert.strictEqual(
errors.message('ERR_OUT_OF_RANGE', ['A', 'some values']),
'The value of "A" is out of range. It must be some values.'
);
assert.strictEqual(
errors.message('ERR_OUT_OF_RANGE', ['A', 'some values', 'B']),
'The value of "A" is out of range. It must be some values. Received B'

View File

@ -1,16 +1,15 @@
'use strict';
// Flags: --expose-internals
const common = require('../common');
const tty = require('tty');
const { SystemError } = require('internal/errors');
const uv = process.binding('uv');
const assert = require('assert');
common.expectsError(
assert.throws(
() => new tty.WriteStream(-1),
{
code: 'ERR_INVALID_FD',
type: RangeError,
name: 'RangeError [ERR_INVALID_FD]',
message: '"fd" must be a positive integer: -1'
}
);
@ -27,37 +26,37 @@ common.expectsError(
'EBADF (bad file descriptor)' : 'EINVAL (invalid argument)';
const message = `TTY initialization failed: uv_tty_init returned ${suffix}`;
common.expectsError(
assert.throws(
() => {
common.runWithInvalidFD((fd) => {
new tty.WriteStream(fd);
});
}, {
code: 'ERR_TTY_INIT_FAILED',
type: SystemError,
name: 'SystemError [ERR_TTY_INIT_FAILED]',
message,
info
}
);
common.expectsError(
assert.throws(
() => {
common.runWithInvalidFD((fd) => {
new tty.ReadStream(fd);
});
}, {
code: 'ERR_TTY_INIT_FAILED',
type: SystemError,
name: 'SystemError [ERR_TTY_INIT_FAILED]',
message,
info
});
}
common.expectsError(
assert.throws(
() => new tty.ReadStream(-1),
{
code: 'ERR_INVALID_FD',
type: RangeError,
name: 'RangeError [ERR_INVALID_FD]',
message: '"fd" must be a positive integer: -1'
}
);