mirror of
https://github.com/nodejs/node.git
synced 2025-04-30 15:41:06 +00:00

1) If simple assert is called in the very first line of a file and it causes an error, it used to report the wrong code. The reason is that the column that is reported is faulty. This is fixed by subtracting the offset from now on in such cases. 2) The actual code read is now limited to the part that is actually required to visualize the call site. All other code in e.g. minified files will not cause a significant overhead anymore. 3) The number of allocations is now significantly lower than it used to be. The buffer is reused until the correct line in the code is found. In general the algorithm tries to safe operations where possible. 4) The indentation is now corrected depending on where the statement actually beginns. 5) It is now possible to handle `.call()` and `.apply()` properly. 6) The user defined function name will now always be used instead of only choosing either `assert.ok()` or `assert()`. PR-URL: https://github.com/nodejs/node/pull/21626 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ben Coe <bencoe@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1069 lines
27 KiB
JavaScript
1069 lines
27 KiB
JavaScript
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// 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.
|
|
|
|
'use strict';
|
|
|
|
/* eslint-disable node-core/prefer-common-expectserror */
|
|
|
|
const common = require('../common');
|
|
const assert = require('assert');
|
|
const { inspect } = require('util');
|
|
const a = assert;
|
|
|
|
// Disable colored output to prevent color codes from breaking assertion
|
|
// message comparisons. This should only be an issue when process.stdout
|
|
// is a TTY.
|
|
if (process.stdout.isTTY)
|
|
process.env.NODE_DISABLE_COLORS = '1';
|
|
|
|
const start = 'Input A expected to strictly deep-equal input B:';
|
|
const actExp = '+ expected - actual';
|
|
|
|
assert.ok(a.AssertionError.prototype instanceof Error,
|
|
'a.AssertionError instanceof Error');
|
|
|
|
assert.throws(() => a(false), a.AssertionError, 'ok(false)');
|
|
assert.throws(() => a.ok(false), a.AssertionError, 'ok(false)');
|
|
|
|
a(true);
|
|
a('test', 'ok(\'test\')');
|
|
a.ok(true);
|
|
a.ok('test');
|
|
|
|
assert.throws(() => a.equal(true, false),
|
|
a.AssertionError, 'equal(true, false)');
|
|
|
|
a.equal(null, null);
|
|
a.equal(undefined, undefined);
|
|
a.equal(null, undefined);
|
|
a.equal(true, true);
|
|
a.equal(2, '2');
|
|
a.notEqual(true, false);
|
|
|
|
assert.throws(() => a.notEqual(true, true),
|
|
a.AssertionError, 'notEqual(true, true)');
|
|
|
|
assert.throws(() => a.strictEqual(2, '2'),
|
|
a.AssertionError, 'strictEqual(2, \'2\')');
|
|
|
|
assert.throws(() => a.strictEqual(null, undefined),
|
|
a.AssertionError, 'strictEqual(null, undefined)');
|
|
|
|
assert.throws(
|
|
() => a.notStrictEqual(2, 2),
|
|
{
|
|
message: 'Identical input passed to notStrictEqual: 2',
|
|
name: 'AssertionError [ERR_ASSERTION]'
|
|
}
|
|
);
|
|
|
|
assert.throws(
|
|
() => a.notStrictEqual('a '.repeat(30), 'a '.repeat(30)),
|
|
{
|
|
message: `Identical input passed to notStrictEqual: '${'a '.repeat(30)}'`,
|
|
name: 'AssertionError [ERR_ASSERTION]'
|
|
}
|
|
);
|
|
|
|
a.notStrictEqual(2, '2');
|
|
|
|
// Testing the throwing.
|
|
function thrower(errorConstructor) {
|
|
throw new errorConstructor({});
|
|
}
|
|
|
|
// The basic calls work.
|
|
assert.throws(() => thrower(a.AssertionError), a.AssertionError, 'message');
|
|
assert.throws(() => thrower(a.AssertionError), a.AssertionError);
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
assert.throws(() => thrower(a.AssertionError));
|
|
|
|
// If not passing an error, catch all.
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
assert.throws(() => thrower(TypeError));
|
|
|
|
// When passing a type, only catch errors of the appropriate type.
|
|
{
|
|
let threw = false;
|
|
try {
|
|
a.throws(() => thrower(TypeError), a.AssertionError);
|
|
} catch (e) {
|
|
threw = true;
|
|
assert.ok(e instanceof TypeError, 'type');
|
|
}
|
|
assert.ok(threw, 'a.throws with an explicit error is eating extra errors');
|
|
}
|
|
|
|
// doesNotThrow should pass through all errors.
|
|
{
|
|
let threw = false;
|
|
try {
|
|
a.doesNotThrow(() => thrower(TypeError), a.AssertionError);
|
|
} catch (e) {
|
|
threw = true;
|
|
assert.ok(e instanceof TypeError);
|
|
}
|
|
assert(threw, 'a.doesNotThrow with an explicit error is eating extra errors');
|
|
}
|
|
|
|
// Key difference is that throwing our correct error makes an assertion error.
|
|
{
|
|
let threw = false;
|
|
try {
|
|
a.doesNotThrow(() => thrower(TypeError), TypeError);
|
|
} catch (e) {
|
|
threw = true;
|
|
assert.ok(e instanceof a.AssertionError);
|
|
assert.ok(!e.stack.includes('at Function.doesNotThrow'));
|
|
}
|
|
assert.ok(threw, 'a.doesNotThrow is not catching type matching errors');
|
|
}
|
|
|
|
assert.throws(
|
|
() => a.doesNotThrow(() => thrower(Error), 'user message'),
|
|
{
|
|
name: 'AssertionError [ERR_ASSERTION]',
|
|
code: 'ERR_ASSERTION',
|
|
operator: 'doesNotThrow',
|
|
message: 'Got unwanted exception: user message\n' +
|
|
'Actual message: "[object Object]"'
|
|
}
|
|
);
|
|
|
|
assert.throws(
|
|
() => a.doesNotThrow(() => thrower(Error)),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
message: 'Got unwanted exception.\nActual message: "[object Object]"'
|
|
}
|
|
);
|
|
|
|
// Make sure that validating using constructor really works.
|
|
{
|
|
let threw = false;
|
|
try {
|
|
assert.throws(
|
|
() => {
|
|
throw ({}); // eslint-disable-line no-throw-literal
|
|
},
|
|
Array
|
|
);
|
|
} catch (e) {
|
|
threw = true;
|
|
}
|
|
assert.ok(threw, 'wrong constructor validation');
|
|
}
|
|
|
|
// Use a RegExp to validate the error message.
|
|
a.throws(() => thrower(TypeError), /\[object Object\]/);
|
|
|
|
// Use a fn to validate the error object.
|
|
a.throws(() => thrower(TypeError), (err) => {
|
|
if ((err instanceof TypeError) && /\[object Object\]/.test(err)) {
|
|
return true;
|
|
}
|
|
});
|
|
|
|
// https://github.com/nodejs/node/issues/3188
|
|
{
|
|
let threw = false;
|
|
let AnotherErrorType;
|
|
try {
|
|
const ES6Error = class extends Error {};
|
|
AnotherErrorType = class extends Error {};
|
|
|
|
assert.throws(() => { throw new AnotherErrorType('foo'); }, ES6Error);
|
|
} catch (e) {
|
|
threw = true;
|
|
assert(e instanceof AnotherErrorType,
|
|
`expected AnotherErrorType, received ${e}`);
|
|
}
|
|
|
|
assert.ok(threw);
|
|
}
|
|
|
|
// Check messages from assert.throws().
|
|
{
|
|
const noop = () => {};
|
|
assert.throws(
|
|
() => { a.throws((noop)); },
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
message: 'Missing expected exception.',
|
|
operator: 'throws',
|
|
actual: undefined,
|
|
expected: undefined
|
|
});
|
|
|
|
assert.throws(
|
|
() => { a.throws(noop, TypeError); },
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
message: 'Missing expected exception (TypeError).',
|
|
actual: undefined,
|
|
expected: TypeError
|
|
});
|
|
|
|
assert.throws(
|
|
() => { a.throws(noop, 'fhqwhgads'); },
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
message: 'Missing expected exception: fhqwhgads',
|
|
actual: undefined,
|
|
expected: undefined
|
|
});
|
|
|
|
assert.throws(
|
|
() => { a.throws(noop, TypeError, 'fhqwhgads'); },
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
message: 'Missing expected exception (TypeError): fhqwhgads',
|
|
actual: undefined,
|
|
expected: TypeError
|
|
});
|
|
|
|
let threw = false;
|
|
try {
|
|
a.throws(noop);
|
|
} catch (e) {
|
|
threw = true;
|
|
assert.ok(e instanceof a.AssertionError);
|
|
assert.ok(!e.stack.includes('at Function.throws'));
|
|
}
|
|
assert.ok(threw);
|
|
}
|
|
|
|
const circular = { y: 1 };
|
|
circular.x = circular;
|
|
|
|
function testAssertionMessage(actual, expected) {
|
|
try {
|
|
assert.strictEqual(actual, '');
|
|
} catch (e) {
|
|
assert.strictEqual(
|
|
e.message,
|
|
'Input A expected to strictly equal input B:\n+ expected - actual\n\n' +
|
|
`- ${expected}\n+ ''`
|
|
);
|
|
assert.ok(e.generatedMessage, 'Message not marked as generated');
|
|
}
|
|
}
|
|
|
|
testAssertionMessage(undefined, 'undefined');
|
|
testAssertionMessage(null, 'null');
|
|
testAssertionMessage(true, 'true');
|
|
testAssertionMessage(false, 'false');
|
|
testAssertionMessage(0, '0');
|
|
testAssertionMessage(100, '100');
|
|
testAssertionMessage(NaN, 'NaN');
|
|
testAssertionMessage(Infinity, 'Infinity');
|
|
testAssertionMessage(-Infinity, '-Infinity');
|
|
testAssertionMessage('', '""');
|
|
testAssertionMessage('foo', '\'foo\'');
|
|
testAssertionMessage([], '[]');
|
|
testAssertionMessage([1, 2, 3], '[\n- 1,\n- 2,\n- 3\n- ]');
|
|
testAssertionMessage(/a/, '/a/');
|
|
testAssertionMessage(/abc/gim, '/abc/gim');
|
|
testAssertionMessage(function f() {}, '[Function: f]');
|
|
testAssertionMessage(function() {}, '[Function]');
|
|
testAssertionMessage({}, '{}');
|
|
testAssertionMessage(circular, '{\n- y: 1,\n- x: [Circular]\n- }');
|
|
testAssertionMessage({ a: undefined, b: null },
|
|
'{\n- a: undefined,\n- b: null\n- }');
|
|
testAssertionMessage({ a: NaN, b: Infinity, c: -Infinity },
|
|
'{\n- a: NaN,\n- b: Infinity,\n- c: -Infinity\n- }');
|
|
|
|
// https://github.com/nodejs/node-v0.x-archive/issues/5292
|
|
try {
|
|
assert.strictEqual(1, 2);
|
|
} catch (e) {
|
|
assert.strictEqual(
|
|
e.message,
|
|
'Input A expected to strictly equal input B:\n' +
|
|
'+ expected - actual\n\n- 1\n+ 2'
|
|
);
|
|
assert.ok(e.generatedMessage, 'Message not marked as generated');
|
|
}
|
|
|
|
try {
|
|
assert.strictEqual(1, 2, 'oh no');
|
|
} catch (e) {
|
|
assert.strictEqual(e.message, 'oh no');
|
|
assert.strictEqual(e.generatedMessage, false,
|
|
'Message incorrectly marked as generated');
|
|
}
|
|
|
|
{
|
|
let threw = false;
|
|
const rangeError = new RangeError('my range');
|
|
|
|
// Verify custom errors.
|
|
try {
|
|
assert.strictEqual(1, 2, rangeError);
|
|
} catch (e) {
|
|
assert.strictEqual(e, rangeError);
|
|
threw = true;
|
|
assert.ok(e instanceof RangeError, 'Incorrect error type thrown');
|
|
}
|
|
assert.ok(threw);
|
|
threw = false;
|
|
|
|
// Verify AssertionError is the result from doesNotThrow with custom Error.
|
|
try {
|
|
a.doesNotThrow(() => {
|
|
throw new TypeError('wrong type');
|
|
}, TypeError, rangeError);
|
|
} catch (e) {
|
|
threw = true;
|
|
assert.ok(e.message.includes(rangeError.message));
|
|
assert.ok(e instanceof assert.AssertionError);
|
|
assert.ok(!e.stack.includes('doesNotThrow'), e.stack);
|
|
}
|
|
assert.ok(threw);
|
|
}
|
|
|
|
{
|
|
// Verify that throws() and doesNotThrow() throw on non-function block.
|
|
const testBlockTypeError = (method, block) => {
|
|
common.expectsError(
|
|
() => method(block),
|
|
{
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
type: TypeError,
|
|
message: 'The "block" argument must be of type Function. Received ' +
|
|
`type ${typeof block}`
|
|
}
|
|
);
|
|
};
|
|
|
|
testBlockTypeError(assert.throws, 'string');
|
|
testBlockTypeError(assert.doesNotThrow, 'string');
|
|
testBlockTypeError(assert.throws, 1);
|
|
testBlockTypeError(assert.doesNotThrow, 1);
|
|
testBlockTypeError(assert.throws, true);
|
|
testBlockTypeError(assert.doesNotThrow, true);
|
|
testBlockTypeError(assert.throws, false);
|
|
testBlockTypeError(assert.doesNotThrow, false);
|
|
testBlockTypeError(assert.throws, []);
|
|
testBlockTypeError(assert.doesNotThrow, []);
|
|
testBlockTypeError(assert.throws, {});
|
|
testBlockTypeError(assert.doesNotThrow, {});
|
|
testBlockTypeError(assert.throws, /foo/);
|
|
testBlockTypeError(assert.doesNotThrow, /foo/);
|
|
testBlockTypeError(assert.throws, null);
|
|
testBlockTypeError(assert.doesNotThrow, null);
|
|
testBlockTypeError(assert.throws, undefined);
|
|
testBlockTypeError(assert.doesNotThrow, undefined);
|
|
}
|
|
|
|
// https://github.com/nodejs/node/issues/3275
|
|
// eslint-disable-next-line no-throw-literal
|
|
assert.throws(() => { throw 'error'; }, (err) => err === 'error');
|
|
assert.throws(() => { throw new Error(); }, (err) => err instanceof Error);
|
|
|
|
// Long values should be truncated for display.
|
|
assert.throws(() => {
|
|
assert.strictEqual('A'.repeat(1000), '');
|
|
}, {
|
|
code: 'ERR_ASSERTION',
|
|
message: 'Input A expected to strictly equal input B:\n' +
|
|
`+ expected - actual\n\n- '${'A'.repeat(1000)}'\n+ ''`
|
|
});
|
|
|
|
{
|
|
// Bad args to AssertionError constructor should throw TypeError.
|
|
const args = [1, true, false, '', null, Infinity, Symbol('test'), undefined];
|
|
args.forEach((input) => {
|
|
assert.throws(
|
|
() => new assert.AssertionError(input),
|
|
{
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
name: 'TypeError [ERR_INVALID_ARG_TYPE]',
|
|
message: 'The "options" argument must be of type Object. ' +
|
|
`Received type ${typeof input}`
|
|
});
|
|
});
|
|
}
|
|
|
|
assert.throws(
|
|
() => assert.strictEqual(new Error('foo'), new Error('foobar')),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
name: 'AssertionError [ERR_ASSERTION]',
|
|
message: 'Input A expected to strictly equal input B:\n' +
|
|
'+ expected - actual\n\n- [Error: foo]\n+ [Error: foobar]'
|
|
}
|
|
);
|
|
|
|
// Test strict assert.
|
|
{
|
|
const a = require('assert');
|
|
const assert = require('assert').strict;
|
|
/* eslint-disable no-restricted-properties */
|
|
assert.throws(() => assert.equal(1, true), assert.AssertionError);
|
|
assert.notEqual(0, false);
|
|
assert.throws(() => assert.deepEqual(1, true), assert.AssertionError);
|
|
assert.notDeepEqual(0, false);
|
|
assert.equal(assert.strict, assert.strict.strict);
|
|
assert.equal(assert.equal, assert.strictEqual);
|
|
assert.equal(assert.deepEqual, assert.deepStrictEqual);
|
|
assert.equal(assert.notEqual, assert.notStrictEqual);
|
|
assert.equal(assert.notDeepEqual, assert.notDeepStrictEqual);
|
|
assert.equal(Object.keys(assert).length, Object.keys(a).length);
|
|
assert(7);
|
|
assert.throws(
|
|
() => assert(...[]),
|
|
{
|
|
message: 'No value argument passed to `assert.ok()`',
|
|
name: 'AssertionError [ERR_ASSERTION]'
|
|
}
|
|
);
|
|
assert.throws(
|
|
() => a(),
|
|
{
|
|
message: 'No value argument passed to `assert.ok()`',
|
|
name: 'AssertionError [ERR_ASSERTION]'
|
|
}
|
|
);
|
|
|
|
// Test setting the limit to zero and that assert.strict works properly.
|
|
const tmpLimit = Error.stackTraceLimit;
|
|
Error.stackTraceLimit = 0;
|
|
common.expectsError(
|
|
() => {
|
|
assert.ok(
|
|
typeof 123 === 'string'
|
|
);
|
|
},
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n ' +
|
|
"assert.ok(\n typeof 123 === 'string'\n )\n"
|
|
}
|
|
);
|
|
Error.stackTraceLimit = tmpLimit;
|
|
|
|
// Test error diffs.
|
|
let message = [
|
|
start,
|
|
`${actExp} ... Lines skipped`,
|
|
'',
|
|
' [',
|
|
' [',
|
|
'...',
|
|
' 2,',
|
|
'- 3',
|
|
"+ '3'",
|
|
' ]',
|
|
'...',
|
|
' 5',
|
|
' ]'].join('\n');
|
|
assert.throws(
|
|
() => assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]),
|
|
{ message });
|
|
|
|
message = [
|
|
start,
|
|
`${actExp} ... Lines skipped`,
|
|
'',
|
|
' [',
|
|
' 1,',
|
|
'...',
|
|
' 0,',
|
|
'+ 1,',
|
|
' 1,',
|
|
'...',
|
|
' 1',
|
|
' ]'
|
|
].join('\n');
|
|
assert.throws(
|
|
() => assert.deepEqual(
|
|
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1],
|
|
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]),
|
|
{ message });
|
|
|
|
message = [
|
|
start,
|
|
`${actExp} ... Lines skipped`,
|
|
'',
|
|
' [',
|
|
' 1,',
|
|
'...',
|
|
' 0,',
|
|
'- 1,',
|
|
' 1,',
|
|
'...',
|
|
' 1',
|
|
' ]'
|
|
].join('\n');
|
|
assert.throws(
|
|
() => assert.deepEqual(
|
|
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1],
|
|
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1]),
|
|
{ message });
|
|
|
|
message = [
|
|
start,
|
|
actExp,
|
|
'',
|
|
' [',
|
|
' 1,',
|
|
'- 2,',
|
|
'+ 1,',
|
|
' 1,',
|
|
' 1,',
|
|
' 0,',
|
|
'- 1,',
|
|
' 1',
|
|
' ]'
|
|
].join('\n');
|
|
assert.throws(
|
|
() => assert.deepEqual(
|
|
[1, 2, 1, 1, 0, 1, 1],
|
|
[1, 1, 1, 1, 0, 1]),
|
|
{ message });
|
|
|
|
message = [
|
|
start,
|
|
actExp,
|
|
'',
|
|
'- [',
|
|
'- 1,',
|
|
'- 2,',
|
|
'- 1',
|
|
'- ]',
|
|
'+ undefined',
|
|
].join('\n');
|
|
assert.throws(
|
|
() => assert.deepEqual([1, 2, 1]),
|
|
{ message });
|
|
|
|
message = [
|
|
start,
|
|
actExp,
|
|
'',
|
|
' [',
|
|
'- 1,',
|
|
' 2,',
|
|
' 1',
|
|
' ]'
|
|
].join('\n');
|
|
assert.throws(
|
|
() => assert.deepEqual([1, 2, 1], [2, 1]),
|
|
{ message });
|
|
|
|
message = `${start}\n` +
|
|
`${actExp} ... Lines skipped\n` +
|
|
'\n' +
|
|
' [\n' +
|
|
'- 1,\n'.repeat(10) +
|
|
'...\n' +
|
|
'+ 2,\n'.repeat(10) +
|
|
'...';
|
|
assert.throws(
|
|
() => assert.deepEqual(Array(12).fill(1), Array(12).fill(2)),
|
|
{ message });
|
|
|
|
const obj1 = {};
|
|
const obj2 = { loop: 'forever' };
|
|
obj2[inspect.custom] = () => '{}';
|
|
// No infinite loop and no custom inspect.
|
|
assert.throws(() => assert.deepEqual(obj1, obj2), {
|
|
message: `${start}\n` +
|
|
`${actExp}\n` +
|
|
'\n' +
|
|
'- {}\n' +
|
|
'+ {\n' +
|
|
"+ loop: 'forever',\n" +
|
|
'+ [Symbol(util.inspect.custom)]: [Function]\n' +
|
|
'+ }'
|
|
});
|
|
|
|
// notDeepEqual tests
|
|
message = 'Identical input passed to notDeepStrictEqual:\n\n[\n 1\n]\n';
|
|
assert.throws(
|
|
() => assert.notDeepEqual([1], [1]),
|
|
{ message });
|
|
|
|
message = 'Identical input passed to notDeepStrictEqual:' +
|
|
`\n\n[${'\n 1,'.repeat(25)}\n...\n`;
|
|
const data = Array(31).fill(1);
|
|
assert.throws(
|
|
() => assert.notDeepEqual(data, data),
|
|
{ message });
|
|
/* eslint-enable no-restricted-properties */
|
|
}
|
|
|
|
common.expectsError(
|
|
() => assert.ok(null),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
generatedMessage: true,
|
|
message: 'The expression evaluated to a falsy value:\n\n ' +
|
|
'assert.ok(null)\n'
|
|
}
|
|
);
|
|
common.expectsError(
|
|
() => assert(typeof 123 === 'string'),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
generatedMessage: true,
|
|
message: 'The expression evaluated to a falsy value:\n\n ' +
|
|
"assert(typeof 123 === 'string')\n"
|
|
}
|
|
);
|
|
|
|
common.expectsError(
|
|
() => assert(false, Symbol('foo')),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
generatedMessage: false,
|
|
message: 'Symbol(foo)'
|
|
}
|
|
);
|
|
|
|
{
|
|
// Test caching.
|
|
const fs = process.binding('fs');
|
|
const tmp = fs.close;
|
|
fs.close = common.mustCall(tmp, 1);
|
|
function throwErr() {
|
|
// eslint-disable-next-line prefer-assert-methods
|
|
assert(
|
|
(Buffer.from('test') instanceof Error)
|
|
);
|
|
}
|
|
common.expectsError(
|
|
() => throwErr(),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n ' +
|
|
"assert(\n (Buffer.from('test') instanceof Error)\n )\n"
|
|
}
|
|
);
|
|
common.expectsError(
|
|
() => throwErr(),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n ' +
|
|
"assert(\n (Buffer.from('test') instanceof Error)\n )\n"
|
|
}
|
|
);
|
|
fs.close = tmp;
|
|
}
|
|
|
|
common.expectsError(
|
|
() => {
|
|
a(
|
|
(() => 'string')()
|
|
// eslint-disable-next-line
|
|
===
|
|
123 instanceof
|
|
Buffer
|
|
);
|
|
},
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n' +
|
|
' a(\n' +
|
|
' (() => \'string\')()\n' +
|
|
' // eslint-disable-next-line\n' +
|
|
' ===\n' +
|
|
' 123 instanceof\n' +
|
|
' Buffer\n' +
|
|
' )\n'
|
|
}
|
|
);
|
|
|
|
common.expectsError(
|
|
() => {
|
|
a(
|
|
(() => 'string')()
|
|
// eslint-disable-next-line
|
|
===
|
|
123 instanceof
|
|
Buffer
|
|
);
|
|
},
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n' +
|
|
' a(\n' +
|
|
' (() => \'string\')()\n' +
|
|
' // eslint-disable-next-line\n' +
|
|
' ===\n' +
|
|
' 123 instanceof\n' +
|
|
' Buffer\n' +
|
|
' )\n'
|
|
}
|
|
);
|
|
|
|
/* eslint-disable indent */
|
|
common.expectsError(() => {
|
|
a((
|
|
() => 'string')() ===
|
|
123 instanceof
|
|
Buffer
|
|
);
|
|
}, {
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n' +
|
|
' a((\n' +
|
|
' () => \'string\')() ===\n' +
|
|
' 123 instanceof\n' +
|
|
' Buffer\n' +
|
|
' )\n'
|
|
}
|
|
);
|
|
/* eslint-enable indent */
|
|
|
|
common.expectsError(
|
|
() => {
|
|
assert(true); assert(null, undefined);
|
|
},
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n ' +
|
|
'assert(null, undefined)\n'
|
|
}
|
|
);
|
|
|
|
common.expectsError(
|
|
() => {
|
|
assert
|
|
.ok(null, undefined);
|
|
},
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n ' +
|
|
'ok(null, undefined)\n'
|
|
}
|
|
);
|
|
|
|
common.expectsError(
|
|
// eslint-disable-next-line dot-notation, quotes
|
|
() => assert['ok']["apply"](null, [0]),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n ' +
|
|
'assert[\'ok\']["apply"](null, [0])\n'
|
|
}
|
|
);
|
|
|
|
common.expectsError(
|
|
() => {
|
|
const wrapper = (fn, value) => fn(value);
|
|
wrapper(assert, false);
|
|
},
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n fn(value)\n'
|
|
}
|
|
);
|
|
|
|
common.expectsError(
|
|
() => assert.ok.call(null, 0),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'The expression evaluated to a falsy value:\n\n ' +
|
|
'assert.ok.call(null, 0)\n',
|
|
generatedMessage: true
|
|
}
|
|
);
|
|
|
|
common.expectsError(
|
|
() => assert.ok.call(null, 0, 'test'),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'test',
|
|
generatedMessage: false
|
|
}
|
|
);
|
|
|
|
// Works in eval.
|
|
common.expectsError(
|
|
() => new Function('assert', 'assert(1 === 2);')(assert),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
type: assert.AssertionError,
|
|
message: 'false == true'
|
|
}
|
|
);
|
|
|
|
common.expectsError(
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
() => assert.throws(() => {}, 'Error message', 'message'),
|
|
{
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
type: TypeError,
|
|
message: 'The "error" argument must be one of type Object, Error, ' +
|
|
'Function, or RegExp. Received type string'
|
|
}
|
|
);
|
|
|
|
[
|
|
1,
|
|
false,
|
|
Symbol()
|
|
].forEach((input) => {
|
|
assert.throws(
|
|
() => assert.throws(() => {}, input),
|
|
{
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: 'The "error" argument must be one of type Object, Error, ' +
|
|
`Function, or RegExp. Received type ${typeof input}`
|
|
}
|
|
);
|
|
});
|
|
|
|
{
|
|
const errFn = () => {
|
|
const err = new TypeError('Wrong value');
|
|
err.code = 404;
|
|
throw err;
|
|
};
|
|
const errObj = {
|
|
name: 'TypeError',
|
|
message: 'Wrong value'
|
|
};
|
|
assert.throws(errFn, errObj);
|
|
|
|
errObj.code = 404;
|
|
assert.throws(errFn, errObj);
|
|
|
|
// Fail in case a expected property is undefined and not existent on the
|
|
// error.
|
|
errObj.foo = undefined;
|
|
assert.throws(
|
|
() => assert.throws(errFn, errObj),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
name: 'AssertionError [ERR_ASSERTION]',
|
|
message: `${start}\n${actExp}\n\n` +
|
|
" Comparison {\n name: 'TypeError',\n" +
|
|
" message: 'Wrong value',\n- code: 404\n" +
|
|
'+ code: 404,\n+ foo: undefined\n }'
|
|
}
|
|
);
|
|
|
|
// Show multiple wrong properties at the same time.
|
|
errObj.code = '404';
|
|
assert.throws(
|
|
() => assert.throws(errFn, errObj),
|
|
{
|
|
code: 'ERR_ASSERTION',
|
|
name: 'AssertionError [ERR_ASSERTION]',
|
|
message: `${start}\n${actExp}\n\n` +
|
|
" Comparison {\n name: 'TypeError',\n" +
|
|
" message: 'Wrong value',\n- code: 404\n" +
|
|
"+ code: '404',\n+ foo: undefined\n }"
|
|
}
|
|
);
|
|
|
|
common.expectsError(
|
|
() => assert.throws(() => { throw new Error(); }, { foo: 'bar' }, 'foobar'),
|
|
{
|
|
type: assert.AssertionError,
|
|
code: 'ERR_ASSERTION',
|
|
message: 'foobar'
|
|
}
|
|
);
|
|
|
|
common.expectsError(
|
|
() => a.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }),
|
|
{
|
|
type: TypeError,
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: 'The "expected" argument must be one of type Function or ' +
|
|
'RegExp. Received type object'
|
|
}
|
|
);
|
|
|
|
assert.throws(() => { throw new Error('e'); }, new Error('e'));
|
|
assert.throws(
|
|
() => assert.throws(() => { throw new TypeError('e'); }, new Error('e')),
|
|
{
|
|
name: 'AssertionError [ERR_ASSERTION]',
|
|
code: 'ERR_ASSERTION',
|
|
message: `${start}\n${actExp}\n\n` +
|
|
" Comparison {\n- name: 'TypeError',\n+ name: 'Error'," +
|
|
"\n message: 'e'\n }"
|
|
}
|
|
);
|
|
assert.throws(
|
|
() => assert.throws(() => { throw new Error('foo'); }, new Error('')),
|
|
{
|
|
name: 'AssertionError [ERR_ASSERTION]',
|
|
code: 'ERR_ASSERTION',
|
|
generatedMessage: true,
|
|
message: `${start}\n${actExp}\n\n` +
|
|
" Comparison {\n name: 'Error',\n- message: 'foo'" +
|
|
"\n+ message: ''\n }"
|
|
}
|
|
);
|
|
|
|
// eslint-disable-next-line no-throw-literal
|
|
assert.throws(() => { throw undefined; }, /undefined/);
|
|
assert.throws(
|
|
// eslint-disable-next-line no-throw-literal
|
|
() => a.doesNotThrow(() => { throw undefined; }),
|
|
{
|
|
name: 'AssertionError [ERR_ASSERTION]',
|
|
code: 'ERR_ASSERTION',
|
|
message: 'Got unwanted exception.\nActual message: "undefined"'
|
|
}
|
|
);
|
|
}
|
|
|
|
assert.throws(
|
|
() => assert.throws(() => { throw new Error(); }, {}),
|
|
{
|
|
message: "The argument 'error' may not be an empty object. Received {}",
|
|
code: 'ERR_INVALID_ARG_VALUE'
|
|
}
|
|
);
|
|
|
|
assert.throws(
|
|
() => a.throws(
|
|
// eslint-disable-next-line no-throw-literal
|
|
() => { throw 'foo'; },
|
|
'foo'
|
|
),
|
|
{
|
|
code: 'ERR_AMBIGUOUS_ARGUMENT',
|
|
message: 'The "error/message" argument is ambiguous. ' +
|
|
'The error "foo" is identical to the message.'
|
|
}
|
|
);
|
|
|
|
assert.throws(
|
|
() => a.throws(
|
|
() => { throw new TypeError('foo'); },
|
|
'foo'
|
|
),
|
|
{
|
|
code: 'ERR_AMBIGUOUS_ARGUMENT',
|
|
message: 'The "error/message" argument is ambiguous. ' +
|
|
'The error message "foo" is identical to the message.'
|
|
}
|
|
);
|
|
|
|
// Should not throw.
|
|
// eslint-disable-next-line no-restricted-syntax, no-throw-literal
|
|
assert.throws(() => { throw null; }, 'foo');
|
|
|
|
assert.throws(
|
|
() => assert.strictEqual([], []),
|
|
{
|
|
message: 'Input objects identical but not reference equal:\n\n[]\n'
|
|
}
|
|
);
|
|
|
|
{
|
|
const args = (function() { return arguments; })('a');
|
|
assert.throws(
|
|
() => assert.strictEqual(args, { 0: 'a' }),
|
|
{
|
|
message: 'Input A expected to strictly equal input B:\n+ expected' +
|
|
" - actual\n\n- [Arguments] {\n+ {\n '0': 'a'\n }"
|
|
}
|
|
);
|
|
}
|
|
|
|
assert.throws(
|
|
() => { throw new TypeError('foobar'); },
|
|
{
|
|
message: /foo/,
|
|
name: /^TypeError$/
|
|
}
|
|
);
|
|
|
|
assert.throws(
|
|
() => assert.throws(
|
|
() => { throw new TypeError('foobar'); },
|
|
{
|
|
message: /fooa/,
|
|
name: /^TypeError$/
|
|
}
|
|
),
|
|
{
|
|
message: `${start}\n${actExp}\n\n` +
|
|
' Comparison {\n' +
|
|
"- message: 'foobar',\n" +
|
|
'+ message: /fooa/,\n' +
|
|
" name: 'TypeError'\n" +
|
|
' }'
|
|
}
|
|
);
|
|
|
|
{
|
|
let actual = null;
|
|
const expected = { message: 'foo' };
|
|
assert.throws(
|
|
() => assert.throws(
|
|
() => { throw actual; },
|
|
expected
|
|
),
|
|
{
|
|
operator: 'throws',
|
|
actual,
|
|
expected,
|
|
generatedMessage: true,
|
|
message: `${start}\n${actExp}\n\n` +
|
|
'- null\n' +
|
|
'+ {\n' +
|
|
"+ message: 'foo'\n" +
|
|
'+ }'
|
|
}
|
|
);
|
|
|
|
actual = 'foobar';
|
|
const message = 'message';
|
|
assert.throws(
|
|
() => assert.throws(
|
|
() => { throw actual; },
|
|
{ message: 'foobar' },
|
|
message
|
|
),
|
|
{
|
|
actual,
|
|
message,
|
|
operator: 'throws',
|
|
generatedMessage: false
|
|
}
|
|
);
|
|
}
|