From d28211ec3da0eb6047c846d5cc7cdaa3993e16b8 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 11 Apr 2018 03:10:22 +0200 Subject: [PATCH] errors: validate input arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- lib/buffer.js | 2 +- lib/fs.js | 4 +- lib/fs/promises.js | 2 +- lib/internal/buffer.js | 2 +- lib/internal/crypto/pbkdf2.js | 7 +-- lib/internal/errors.js | 61 +++++++++++------- lib/internal/fs.js | 14 +++-- lib/internal/http2/core.js | 8 ++- test/parallel/test-buffer-arraybuffer.js | 26 ++++---- test/parallel/test-child-process-fork.js | 16 +++-- test/parallel/test-crypto-pbkdf2.js | 63 ++++++++++--------- test/parallel/test-errors-systemerror.js | 22 +++---- test/parallel/test-fs-fchmod.js | 12 ++-- test/parallel/test-fs-read-type.js | 57 +++++++++++------ test/parallel/test-http2-altsvc.js | 49 ++++++++------- ...t-http2-client-rststream-before-connect.js | 7 ++- test/parallel/test-internal-errors.js | 22 +++---- test/parallel/test-ttywrap-invalid-fd.js | 19 +++--- 18 files changed, 215 insertions(+), 178 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index 1fbfb756f03171..061ff7ebe440da 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -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 diff --git a/lib/fs.js b/lib/fs.js index ebf70948192844..6b80af3b63443e 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -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); diff --git a/lib/fs/promises.js b/lib/fs/promises.js index 7a0389978fdab1..a1d805803ae789 100644 --- a/lib/fs/promises.js +++ b/lib/fs/promises.js @@ -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); } diff --git a/lib/internal/buffer.js b/lib/internal/buffer.js index 59ee776250c904..085a82265a95de 100644 --- a/lib/internal/buffer.js +++ b/lib/internal/buffer.js @@ -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}`, diff --git a/lib/internal/crypto/pbkdf2.js b/lib/internal/crypto/pbkdf2.js index de41be42281c07..4a7f26b509b521 100644 --- a/lib/internal/crypto/pbkdf2.js +++ b/lib/internal/crypto/pbkdf2.js @@ -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(); diff --git a/lib/internal/errors.js b/lib/internal/errors.js index c8be91796ec249..f09bf973efc02a 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -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; } diff --git a/lib/internal/fs.js b/lib/internal/fs.js index 6ff4152aa46814..02ba4bbf72baf9 100644 --- a/lib/internal/fs.js +++ b/lib/internal/fs.js @@ -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) { diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index c9f4f36748628c..8d0ceffc67253b 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -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(); diff --git a/test/parallel/test-buffer-arraybuffer.js b/test/parallel/test-buffer-arraybuffer.js index 24fb5969baec4e..8d26f983f2b4dd 100644 --- a/test/parallel/test-buffer-arraybuffer.js +++ b/test/parallel/test-buffer-arraybuffer.js @@ -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' }); } diff --git a/test/parallel/test-child-process-fork.js b/test/parallel/test-child-process-fork.js index 04318207a3ea94..6cfeeefb51952d 100644 --- a/test/parallel/test-child-process-fork.js +++ b/test/parallel/test-child-process-fork.js @@ -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); })); diff --git a/test/parallel/test-crypto-pbkdf2.js b/test/parallel/test-crypto-pbkdf2.js index d3f02cf8bd1d87..b4ecd3c6061158 100644 --- a/test/parallel/test-crypto-pbkdf2.js +++ b/test/parallel/test-crypto-pbkdf2.js @@ -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' } ); diff --git a/test/parallel/test-errors-systemerror.js b/test/parallel/test-errors-systemerror.js index 285c89b5d25c2a..a74d7b3846f59d 100644 --- a/test/parallel/test-errors-systemerror.js +++ b/test/parallel/test-errors-systemerror.js @@ -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 diff --git a/test/parallel/test-fs-fchmod.js b/test/parallel/test-fs-fchmod.js index edf5cc32ea8dca..63d780a57dfc66 100644 --- a/test/parallel/test-fs-fchmod.js +++ b/test/parallel/test-fs-fchmod.js @@ -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' } ); diff --git a/test/parallel/test-fs-read-type.js b/test/parallel/test-fs-read-type.js index 55049ed79f84eb..2980bca7d2038e 100644 --- a/test/parallel/test-fs-read-type.js +++ b/test/parallel/test-fs-read-type.js @@ -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' +}); diff --git a/test/parallel/test-http2-altsvc.js b/test/parallel/test-http2-altsvc.js index 9fd9a9fc278552..d4216e973df3ca 100644 --- a/test/parallel/test-http2-altsvc.js +++ b/test/parallel/test-http2-altsvc.js @@ -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' } ); })); diff --git a/test/parallel/test-http2-client-rststream-before-connect.js b/test/parallel/test-http2-client-rststream-before-connect.js index 3120a80b11ddf4..7bace941d1a0af 100644 --- a/test/parallel/test-http2-client-rststream-before-connect.js +++ b/test/parallel/test-http2-client-rststream-before-connect.js @@ -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); diff --git a/test/parallel/test-internal-errors.js b/test/parallel/test-internal-errors.js index 7521633c6265ad..a161a1db69e66d 100644 --- a/test/parallel/test-internal-errors.js +++ b/test/parallel/test-internal-errors.js @@ -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' diff --git a/test/parallel/test-ttywrap-invalid-fd.js b/test/parallel/test-ttywrap-invalid-fd.js index c360489cb33529..0a0f8c5c4e1a3a 100644 --- a/test/parallel/test-ttywrap-invalid-fd.js +++ b/test/parallel/test-ttywrap-invalid-fd.js @@ -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' } );