diff options
Diffstat (limited to 'tests/node_compat/test/parallel/test-assert.js')
-rw-r--r-- | tests/node_compat/test/parallel/test-assert.js | 1615 |
1 files changed, 1615 insertions, 0 deletions
diff --git a/tests/node_compat/test/parallel/test-assert.js b/tests/node_compat/test/parallel/test-assert.js new file mode 100644 index 000000000..58b95068c --- /dev/null +++ b/tests/node_compat/test/parallel/test-assert.js @@ -0,0 +1,1615 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file + +// Copyright Joyent and Node contributors. All rights reserved. MIT license. +// Taken from Node 15.5.1 +// This file is automatically generated by "node/_tools/setup.ts". Do not modify this file manually + +// Flags: --expose-internals +// 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'; + +const common = require('../common'); +const assert = require('assert'); +const { inspect } = require('util'); +// TODO(kt3k): Enable these when "vm" is ready. +// const vm = require('vm'); +// TODO(kt3k): Enable these when "internal/test/binding" is ready. +// const { internalBinding } = require('internal/test/binding'); +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 strictEqualMessageStart = 'Expected values to be strictly equal:\n'; +const start = 'Expected values to be strictly deep-equal:'; +const actExp = '+ actual - expected'; + +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)'); + +// Throw message if the message is instanceof Error. +{ + let threw = false; + try { + assert.ok(false, new Error('ok(false)')); + } catch (e) { + threw = true; + assert.ok(e instanceof Error); + } + assert.ok(threw, 'Error: 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: 'Expected "actual" to be strictly unequal to: 2\n', + name: 'AssertionError' + } +); + +assert.throws( + () => a.notStrictEqual('a '.repeat(30), 'a '.repeat(30)), + { + message: 'Expected "actual" to be strictly unequal to: ' + + `"${'a '.repeat(30)}"\n`, + name: 'AssertionError' + } +); + +assert.throws( + () => a.notEqual(1, 1), + { + message: '1 != 1', + operator: '!=' + } +); + +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); +assert.throws(() => thrower(a.AssertionError)); + +// If not passing an error, catch all. +assert.throws(() => thrower(TypeError)); + +// When passing a type, only catch errors of the appropriate type. +assert.throws( + () => a.throws(() => thrower(TypeError), a.AssertionError), + { + // generatedMessage: true, + // actual: new TypeError({}), + expected: a.AssertionError, + code: 'ERR_ASSERTION', + name: 'AssertionError', + operator: 'throws', + message: 'The error is expected to be an instance of "AssertionError". ' + + 'Received "TypeError"\n\nError message:\n\n[object Object]' + } +); + +// 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); + // Commented out the following assertion + // 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', + 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]"' + } +); + +assert.throws( + () => a.doesNotThrow(() => thrower(Error), /\[[a-z]{6}\s[A-z]{6}\]/g, 'user message'), + { + name: 'AssertionError', + code: 'ERR_ASSERTION', + operator: 'doesNotThrow', + message: 'Got unwanted exception: user message\n' + + 'Actual message: "[object Object]"' + } +); + +// Make sure that validating using constructor really works. +{ + let threw = false; + try { + assert.throws( + () => { + throw ({}); + }, + Array + ); + } catch { + threw = true; + } + assert.ok(threw, 'wrong constructor validation'); +} + +// Use a RegExp to validate the error message. +{ + a.throws(() => thrower(TypeError), /\[object Object\]/); + + const symbol = Symbol('foo'); + a.throws(() => { + throw symbol; + }, /foo/); + + a.throws(() => { + a.throws(() => { + throw symbol; + }, /abc/); + }, { + message: 'The input did not match the regular expression /abc/. ' + + "Input:\n\n'Symbol(foo)'\n", + code: 'ERR_ASSERTION', + operator: 'throws', + actual: symbol, + expected: /abc/ + }); +} + +// 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 actual; + assert.throws( + () => { + const ES6Error = class extends Error {}; + const AnotherErrorType = class extends Error {}; + + assert.throws(() => { + actual = new AnotherErrorType('foo'); + throw actual; + }, ES6Error); + }, + (err) => { + assert.strictEqual( + err.message, + 'The error is expected to be an instance of "ES6Error". ' + + 'Received "AnotherErrorType"\n\nError message:\n\nfoo' + ); + assert.strictEqual(err.actual, actual); + return true; + } + ); +} + +// 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); + // TODO(kt3k): enable this assertion + // assert.ok(!e.stack.includes('at Function.throws')); + } + assert.ok(threw); +} + +const circular = { y: 1 }; +circular.x = circular; + +function testAssertionMessage(actual, expected, msg) { + assert.throws( + () => assert.strictEqual(actual, ''), + { + generatedMessage: true, + message: msg || strictEqualMessageStart + + `+ actual - expected\n\n+ ${expected}\n- ''` + } + ); +} + +function testShortAssertionMessage(actual, expected) { + testAssertionMessage(actual, expected, strictEqualMessageStart + + `\n${inspect(actual)} !== ''\n`); +} + +// TODO(kt3k): Do we need completely simulate +// Node.js assertion error messages? +/* +testShortAssertionMessage(null, 'null'); +testShortAssertionMessage(true, 'true'); +testShortAssertionMessage(false, 'false'); +testShortAssertionMessage(100, '100'); +testShortAssertionMessage(NaN, 'NaN'); +testShortAssertionMessage(Infinity, 'Infinity'); +testShortAssertionMessage('a', '"a"'); +testShortAssertionMessage('foo', '\'foo\''); +testShortAssertionMessage(0, '0'); +testShortAssertionMessage(Symbol(), 'Symbol()'); +testShortAssertionMessage(undefined, 'undefined'); +testShortAssertionMessage(-Infinity, '-Infinity'); +testAssertionMessage([], '[]'); +testAssertionMessage(/a/, '/a/'); +testAssertionMessage(/abc/gim, '/abc/gim'); +testAssertionMessage({}, '{}'); +testAssertionMessage([1, 2, 3], '[\n+ 1,\n+ 2,\n+ 3\n+ ]'); +testAssertionMessage(function f() {}, '[Function: f]'); +testAssertionMessage(function() {}, '[Function (anonymous)]'); +testAssertionMessage(circular, + '<ref *1> {\n+ x: [Circular *1],\n+ y: 1\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 +assert.throws( + () => assert.strictEqual(1, 2), +/* Memo: Disabled this object assertion + { + message: `${strictEqualMessageStart}\n1 !== 2\n`, + generatedMessage: true + } +*/ +); + +assert.throws( + () => assert.strictEqual(1, 2, 'oh no'), + { + message: 'oh no', + generatedMessage: false + } +); + +{ + 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); + // TODO(kt3k): Enable this assertion + // assert.ok(!e.stack.includes('doesNotThrow'), e); + } + assert.ok(threw); +} + +{ + // Verify that throws() and doesNotThrow() throw on non-functions. + const testBlockTypeError = (method, fn) => { + assert.throws( + () => method(fn), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + message: 'The "fn" argument must be of type function.' + + common.invalidArgTypeHelper(fn) + } + ); + }; + + 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 +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), ''); +}, (err) => { + assert.strictEqual(err.code, 'ERR_ASSERTION'); + /* TODO(kt3k): Enable this assertion + assert.strictEqual(err.message, + `${strictEqualMessageStart}+ actual - expected\n\n` + + `+ '${'A'.repeat(1000)}'\n- ''`); + */ + assert.strictEqual(err.actual.length, 1000); + // TODO(kt3k): Enable this after fixing 'inspect' + // assert.ok(inspect(err).includes(`actual: '${'A'.repeat(488)}...'`)); + return true; +}); + +// Output that extends beyond 10 lines should also be truncated for display. +{ + const multilineString = 'fhqwhgads\n'.repeat(15); + assert.throws(() => { + assert.strictEqual(multilineString, ''); + }, (err) => { + assert.strictEqual(err.code, 'ERR_ASSERTION'); + // TODO(kt3k): Enable these assertion when the strictEqual message is aligned + // to Node.js API. + // assert.strictEqual(err.message.split('\n').length, 19); + assert.strictEqual(err.actual.split('\n').length, 16); + // TODO(kt3k): inspect(err) causes Maximum call stack error. + /* + assert.ok(inspect(err).includes( + "actual: 'fhqwhgads\\n' +\n" + + " 'fhqwhgads\\n' +\n".repeat(9) + + " '...'")); + */ + return true; + }); +} + +{ + // 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', + message: 'The "options" argument must be of type object.' + + common.invalidArgTypeHelper(input) + }); + }); +} + +assert.throws( + () => assert.strictEqual(new Error('foo'), new Error('foobar')), + { + code: 'ERR_ASSERTION', + name: 'AssertionError', + /* TODO(kt3k): Enable this assertion when the assertion error message is fixed. + message: 'Expected "actual" to be reference-equal to "expected":\n' + + '+ actual - expected\n\n' + + '+ [Error: foo]\n- [Error: foobar]' + */ + } +); + +a.equal(NaN, NaN); +a.throws( + () => a.notEqual(NaN, NaN), + a.AssertionError +); + +// Test strict assert. +{ + const a = require('assert'); + const assert = require('assert').strict; + 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', + // TODO(kt3k): Enable this + // generatedMessage: true + } + ); + assert.throws( + () => a(), + { + message: 'No value argument passed to `assert.ok()`', + name: 'AssertionError' + } + ); + + // Test setting the limit to zero and that assert.strict works properly. + const tmpLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; + assert.throws( + () => { + assert.ok( + typeof 123 === 'string' + ); + }, + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + 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`, + '', + ' [', + ' [', + ' [', + ' 1,', + ' 2,', + '+ 3', + "- '3'", + ' ]', + '...', + ' 4,', + ' 5', + ' ]'].join('\n'); + assert.throws( + () => assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]), + /* TODO(kt3k): Enable this assertion + { message } + */ + ); + + message = [ + start, + `${actExp} ... Lines skipped`, + '', + ' [', + ' 1,', + '...', + ' 1,', + ' 0,', + '- 1,', + ' 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]), + /* TODO(kt3k): Enable this assertion + { message } + */ + ); + + message = [ + start, + `${actExp} ... Lines skipped`, + '', + ' [', + ' 1,', + '...', + ' 1,', + ' 0,', + '+ 1,', + ' 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]), + /* TODO(kt3k): Enable this assertion + { 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]), + /* TODO(kt3k): Enable this assertion + { message } + */ + ); + + message = [ + start, + actExp, + '', + '+ [', + '+ 1,', + '+ 2,', + '+ 1', + '+ ]', + '- undefined', + ].join('\n'); + assert.throws( + () => assert.deepEqual([1, 2, 1], undefined), + /* TODO(kt3k): Enable this assertion + { message } + */ + ); + + message = [ + start, + actExp, + '', + ' [', + '+ 1,', + ' 2,', + ' 1', + ' ]' + ].join('\n'); + assert.throws( + () => assert.deepEqual([1, 2, 1], [2, 1]), + /* TODO(kt3k): Enable this assertion + { message } + */ + ); + + message = `${start}\n` + + `${actExp} ... Lines skipped\n` + + '\n' + + ' [\n' + + '+ 1,\n'.repeat(25) + + '...\n' + + '- 2,\n'.repeat(25) + + '...'; + assert.throws( + () => assert.deepEqual(Array(28).fill(1), Array(28).fill(2)), + /* TODO(kt3k): Enable this assertion + { message } + */ + ); + + const obj1 = {}; + const obj2 = { loop: 'forever' }; + obj2[inspect.custom] = () => '{}'; + // No infinite loop and no custom inspect. + assert.throws(() => assert.deepEqual(obj1, obj2), { + code: "ERR_ASSERTION", + /* TODO(kt3k): Enable this assertion + message: `${start}\n` + + `${actExp}\n` + + '\n' + + '+ {}\n' + + '- {\n' + + '- [Symbol(nodejs.util.inspect.custom)]: [Function (anonymous)],\n' + + "- loop: 'forever'\n" + + '- }' + */ + }); + + // notDeepEqual tests + assert.throws( + () => assert.notDeepEqual([1], [1]), + { + code: "ERR_ASSERTION", + /* TODO(kt3k): Enable this assertion + message: 'Expected "actual" not to be strictly deep-equal to:\n\n' + + '[\n 1\n]\n' + */ + } + ); + + message = 'Expected "actual" not to be strictly deep-equal to:' + + `\n\n[${'\n 1,'.repeat(45)}\n...\n`; + const data = Array(51).fill(1); + assert.throws( + () => assert.notDeepEqual(data, data), + /* TODO(kt3k): Enable this assertion + { message } + */ + ); +} + +assert.throws( + () => assert.ok(null), + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + generatedMessage: true, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n ' + + 'assert.ok(null)\n' + */ + } +); +assert.throws( + () => assert(typeof 123n === 'string'), + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + generatedMessage: true, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n ' + + "assert(typeof 123n === 'string')\n" + */ + } +); + +assert.throws( + () => assert(false, Symbol('foo')), + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + generatedMessage: false, + message: 'Symbol(foo)' + */ + } +); + +// TODO(kt3k): Enable these when "internal/test/binding" is ready. +/* +{ + // Test caching. + const fs = internalBinding('fs'); + const tmp = fs.close; + fs.close = common.mustCall(tmp, 1); + function throwErr() { + assert( + (Buffer.from('test') instanceof Error) + ); + } + assert.throws( + () => throwErr(), + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + message: 'The expression evaluated to a falsy value:\n\n ' + + "assert(\n (Buffer.from('test') instanceof Error)\n )\n" + } + ); + assert.throws( + () => throwErr(), + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + message: 'The expression evaluated to a falsy value:\n\n ' + + "assert(\n (Buffer.from('test') instanceof Error)\n )\n" + } + ); + fs.close = tmp; +} +*/ + +assert.throws( + () => { + a( + (() => 'string')() + === + 123 instanceof + Buffer + ); + }, + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n' + + ' a(\n' + + ' (() => \'string\')()\n' + + ' ===\n' + + ' 123 instanceof\n' + + ' Buffer\n' + + ' )\n' + */ + } +); + +assert.throws( + () => { + a( + (() => 'string')() + === + 123 instanceof + Buffer + ); + }, + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n' + + ' a(\n' + + ' (() => \'string\')()\n' + + ' ===\n' + + ' 123 instanceof\n' + + ' Buffer\n' + + ' )\n' + */ + } +); + +assert.throws(() => { +a(( + () => 'string')() === +123 instanceof +Buffer +); +}, { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n' + + ' a((\n' + + ' () => \'string\')() ===\n' + + ' 123 instanceof\n' + + ' Buffer\n' + + ' )\n' + */ + } +); + +assert.throws( + () => { + assert(true); assert(null, undefined); + }, + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n ' + + 'assert(null, undefined)\n' + */ + } +); + +assert.throws( + () => { + assert + .ok(null, undefined); + }, + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n ' + + 'ok(null, undefined)\n' + */ + } +); + +assert.throws( + () => assert['ok']["apply"](null, [0]), + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n ' + + 'assert[\'ok\']["apply"](null, [0])\n' + */ + } +); + +assert.throws( + () => { + const wrapper = (fn, value) => fn(value); + wrapper(assert, false); + }, + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n fn(value)\n' + */ + } +); + +assert.throws( + () => assert.ok.call(null, 0), + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n ' + + 'assert.ok.call(null, 0)\n', + generatedMessage: true + */ + } +); + +assert.throws( + () => assert.ok.call(null, 0, 'test'), + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + message: 'test', + generatedMessage: false + } +); + +// Works in eval. +assert.throws( + () => new Function('assert', 'assert(1 === 2);')(assert), + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n assert(1 === 2)\n' + */ + } +); + +assert.throws( + () => eval('console.log("FOO");\nassert.ok(1 === 2);'), + { + code: 'ERR_ASSERTION', + /* TODO(kt3k): Enable this assertion + message: 'false == true' + */ + } +); + +assert.throws( + () => assert.throws(() => {}, 'Error message', 'message'), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + /* TODO(kt3k): Enable this assertion + message: 'The "error" argument must be of type function or ' + + 'an instance of Error, RegExp, or Object. Received type string ' + + "('Error message')" + */ + } +); + +[ + 1, + false, + Symbol() +].forEach((input) => { + assert.throws( + () => assert.throws(() => {}, input), + { + code: 'ERR_INVALID_ARG_TYPE', + /* TODO(kt3k): Enable this assertion + message: 'The "error" argument must be of type function or ' + + 'an instance of Error, RegExp, or Object.' + + common.invalidArgTypeHelper(input) + */ + } + ); +}); + +{ + + assert.throws(() => { + assert.ok((() => Boolean('' === false))()); + }, { + code: "ERR_ASSERTION", + /* TODO(kt3k): Enable this assertion + message: 'The expression evaluated to a falsy value:\n\n' + + " assert.ok((() => Boolean('\\u0001' === false))())\n" + */ + }); + + 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', + /* TODO(kt3k): Enable this assertion + message: `${start}\n${actExp}\n\n` + + ' Comparison {\n' + + ' code: 404,\n' + + '- foo: undefined,\n' + + " message: 'Wrong value',\n" + + " name: 'TypeError'\n" + + ' }' + */ + } + ); + + // Show multiple wrong properties at the same time. + errObj.code = '404'; + assert.throws( + () => assert.throws(errFn, errObj), + { + code: 'ERR_ASSERTION', + name: 'AssertionError', + /* TODO(kt3k): Enable this assertion + message: `${start}\n${actExp}\n\n` + + ' Comparison {\n' + + '+ code: 404,\n' + + "- code: '404',\n" + + '- foo: undefined,\n' + + " message: 'Wrong value',\n" + + " name: 'TypeError'\n" + + ' }' + */ + } + ); + + assert.throws( + () => assert.throws(() => { throw new Error(); }, { foo: 'bar' }, 'foobar'), + { + constructor: assert.AssertionError, + code: 'ERR_ASSERTION', + message: 'foobar' + } + ); + + assert.throws( + () => a.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }), + { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE', + /* TODO(kt3k): Enable this assertion + message: 'The "expected" argument must be of type function or an ' + + 'instance of RegExp. Received an instance of Object' + */ + } + ); + + assert.throws(() => { throw new Error('e'); }, new Error('e')); + assert.throws( + () => assert.throws(() => { throw new TypeError('e'); }, new Error('e')), + { + name: 'AssertionError', + code: 'ERR_ASSERTION', + /* TODO(kt3k): Enable this assertion + message: `${start}\n${actExp}\n\n` + + ' Comparison {\n' + + " message: 'e',\n" + + "+ name: 'TypeError'\n" + + "- name: 'Error'\n" + + ' }' + */ + } + ); + assert.throws( + () => assert.throws(() => { throw new Error('foo'); }, new Error('')), + { + name: 'AssertionError', + code: 'ERR_ASSERTION', + /* TODO(kt3k): Enable this assertion + generatedMessage: true, + message: `${start}\n${actExp}\n\n` + + ' Comparison {\n' + + "+ message: 'foo',\n" + + "- message: '',\n" + + " name: 'Error'\n" + + ' }' + */ + } + ); + + assert.throws(() => { throw undefined; }, /undefined/); + assert.throws( + () => a.doesNotThrow(() => { throw undefined; }), + { + name: 'AssertionError', + 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( + () => { 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. +assert.throws(() => { throw null; }, 'foo'); + +assert.throws( + () => assert.strictEqual([], []), + { + code: 'ERR_ASSERTION', + /* TODO(kt3k): Enable this assertion + message: 'Values have same structure but are not reference-equal:\n\n[]\n' + */ + } +); + +{ + const args = (function() { return arguments; })('a'); + assert.throws( + () => assert.strictEqual(args, { 0: 'a' }), + { + code: 'ERR_ASSERTION', + /* TODO(kt3k): Enable this assertion + message: 'Expected "actual" to be reference-equal to "expected":\n' + + '+ actual - expected\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$/ + } + ), + { + code: 'ERR_ASSERTION', + /* TODO(kt3k): Enable this assertion + 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, + code: 'ERR_ASSERTION', + /* TODO(kt3k): Enable this assertion + 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 + } + ); +} + +// Indicate where the strings diverge. +assert.throws( + () => assert.strictEqual('test test', 'test foobar'), + { + code: 'ERR_ASSERTION', + name: 'AssertionError', + /* TODO(kt3k): Enable this assertion + message: strictEqualMessageStart + + '+ actual - expected\n\n' + + "+ 'test test'\n" + + "- 'test foobar'\n" + + ' ^' + */ + } +); + +// Check for reference-equal objects in `notStrictEqual()` +assert.throws( + () => { + const obj = {}; + assert.notStrictEqual(obj, obj); + }, + { + code: 'ERR_ASSERTION', + name: 'AssertionError', + /* TODO(kt3k): Enable this assertion + message: 'Expected "actual" not to be reference-equal to "expected": {}' + */ + } +); + +assert.throws( + () => { + const obj = { a: true }; + assert.notStrictEqual(obj, obj); + }, + { + code: 'ERR_ASSERTION', + name: 'AssertionError', + /* TODO(kt3k): Enable this assertion + message: 'Expected "actual" not to be reference-equal to "expected":\n\n' + + '{\n a: true\n}\n' + */ + } +); + +{ + let threw = false; + try { + assert.deepStrictEqual(Array(100).fill(1), 'foobar'); + } catch (err) { + threw = true; + /* TODO(kt3k): Enable this assertion + assert(/actual: \[Array],\n expected: 'foobar',/.test(inspect(err))); + */ + } + assert(threw); +} + +assert.throws( + () => a.equal(1), + { code: 'ERR_MISSING_ARGS' } +); + +assert.throws( + () => a.deepEqual(/a/), + { code: 'ERR_MISSING_ARGS' } +); + +assert.throws( + () => a.notEqual(null), + { code: 'ERR_MISSING_ARGS' } +); + +assert.throws( + () => a.notDeepEqual('test'), + { code: 'ERR_MISSING_ARGS' } +); + +assert.throws( + () => a.strictEqual({}), + { code: 'ERR_MISSING_ARGS' } +); + +assert.throws( + () => a.deepStrictEqual(Symbol()), + { code: 'ERR_MISSING_ARGS' } +); + +assert.throws( + () => a.notStrictEqual(5n), + { code: 'ERR_MISSING_ARGS' } +); + +assert.throws( + () => a.notDeepStrictEqual(undefined), + { code: 'ERR_MISSING_ARGS' } +); + +assert.throws( + () => a.strictEqual(), + { code: 'ERR_MISSING_ARGS' } +); + +assert.throws( + () => a.deepStrictEqual(), + { code: 'ERR_MISSING_ARGS' } +); + +// Verify that `stackStartFunction` works as alternative to `stackStartFn`. +{ + (function hidden() { + const err = new assert.AssertionError({ + actual: 'foo', + operator: 'strictEqual', + stackStartFunction: hidden + }); + const err2 = new assert.AssertionError({ + actual: 'foo', + operator: 'strictEqual', + stackStartFn: hidden + }); + assert(!err.stack.includes('hidden')); + assert(!err2.stack.includes('hidden')); + })(); +} + +assert.throws( + () => assert.throws(() => { throw Symbol('foo'); }, RangeError), + { + code: 'ERR_ASSERTION', + /* TODO(kt3k): Enable this assertion + message: 'The error is expected to be an instance of "RangeError". ' + + 'Received "Symbol(foo)"' + */ + } +); + +assert.throws( + () => assert.throws(() => { throw [1, 2]; }, RangeError), + { + code: 'ERR_ASSERTION', + /* TODO(kt3k): Enable this assertion + message: 'The error is expected to be an instance of "RangeError". ' + + 'Received "[Array]"' + */ + } +); + +{ + const err = new TypeError('foo'); + const validate = (() => () => ({ a: true, b: [ 1, 2, 3 ] }))(); + assert.throws( + () => assert.throws(() => { throw err; }, validate), + { + message: 'The validation function is expected to ' + + `return "true". Received ${inspect(validate())}\n\nCaught ` + + `error:\n\n${err}`, + code: 'ERR_ASSERTION', + actual: err, + expected: validate, + name: 'AssertionError', + operator: 'throws', + } + ); +} + +// TODO(kt3k): Enable these when "vm" is ready. +/* +assert.throws( + () => { + const script = new vm.Script('new RangeError("foobar");'); + const context = vm.createContext(); + const err = script.runInContext(context); + assert.throws(() => { throw err; }, RangeError); + }, + { + message: 'The error is expected to be an instance of "RangeError". ' + + 'Received an error with identical name but a different ' + + 'prototype.\n\nError message:\n\nfoobar' + } +); +*/ + +// Multiple assert.match() tests. +{ + assert.throws( + () => assert.match(/abc/, 'string'), + { + code: 'ERR_INVALID_ARG_TYPE', + /* TODO(kt3k): Enable this assertion + message: 'The "regexp" argument must be an instance of RegExp. ' + + "Received type string ('string')" + */ + } + ); + assert.throws( + () => assert.match('string', /abc/), + { + actual: 'string', + expected: /abc/, + operator: 'match', + /* TODO(kt3k): Enable this assertion + message: 'The input did not match the regular expression /abc/. ' + + "Input:\n\n'string'\n", + generatedMessage: true + */ + } + ); + assert.throws( + () => assert.match('string', /abc/, 'foobar'), + { + actual: 'string', + expected: /abc/, + operator: 'match', + message: 'foobar', + generatedMessage: false + } + ); + const errorMessage = new RangeError('foobar'); + assert.throws( + () => assert.match('string', /abc/, errorMessage), + errorMessage + ); + assert.throws( + () => assert.match({ abc: 123 }, /abc/), + { + actual: { abc: 123 }, + expected: /abc/, + operator: 'match', + /* TODO(kt3k): Enable this assertion + message: 'The "string" argument must be of type string. ' + + 'Received type object ({ abc: 123 })', + generatedMessage: true + */ + } + ); + assert.match('I will pass', /pass$/); +} + +// Multiple assert.doesNotMatch() tests. +{ + assert.throws( + () => assert.doesNotMatch(/abc/, 'string'), + { + code: 'ERR_INVALID_ARG_TYPE', + /* TODO(kt3k): Enable this assertion + message: 'The "regexp" argument must be an instance of RegExp. ' + + "Received type string ('string')" + */ + } + ); + assert.throws( + () => assert.doesNotMatch('string', /string/), + { + actual: 'string', + expected: /string/, + operator: 'doesNotMatch', + /* TODO(kt3k): Enable this assertion + message: 'The input was expected to not match the regular expression ' + + "/string/. Input:\n\n'string'\n", + generatedMessage: true + */ + } + ); + assert.throws( + () => assert.doesNotMatch('string', /string/, 'foobar'), + { + actual: 'string', + expected: /string/, + operator: 'doesNotMatch', + message: 'foobar', + generatedMessage: false + } + ); + const errorMessage = new RangeError('foobar'); + assert.throws( + () => assert.doesNotMatch('string', /string/, errorMessage), + errorMessage + ); + assert.throws( + () => assert.doesNotMatch({ abc: 123 }, /abc/), + { + actual: { abc: 123 }, + expected: /abc/, + operator: 'doesNotMatch', + message: 'The "string" argument must be of type string. ' + + 'Received type object ({ abc: 123 })', + /* TODO(kt3k): Enable this assertion + generatedMessage: true + */ + } + ); + assert.doesNotMatch('I will pass', /different$/); +} + +{ + const tempColor = inspect.defaultOptions.colors; + assert.throws(() => { + inspect.defaultOptions.colors = true; + // Guarantee the position indicator is placed correctly. + assert.strictEqual(111554n, 11111115); + }, (err) => { + // TODO(kt3k): Enable this assertion + // assert.strictEqual(inspect(err).split('\n')[5], ' ^'); + inspect.defaultOptions.colors = tempColor; + return true; + }); +} |