• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --expose-internals
2// Copyright Joyent, Inc. and other Node contributors.
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the
6// "Software"), to deal in the Software without restriction, including
7// without limitation the rights to use, copy, modify, merge, publish,
8// distribute, sublicense, and/or sell copies of the Software, and to permit
9// persons to whom the Software is furnished to do so, subject to the
10// following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
18// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
19// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21// USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23'use strict';
24
25const common = require('../common');
26const assert = require('assert');
27const { inspect } = require('util');
28const vm = require('vm');
29const { internalBinding } = require('internal/test/binding');
30const a = assert;
31
32// Disable colored output to prevent color codes from breaking assertion
33// message comparisons. This should only be an issue when process.stdout
34// is a TTY.
35if (process.stdout.isTTY)
36  process.env.NODE_DISABLE_COLORS = '1';
37
38const strictEqualMessageStart = 'Expected values to be strictly equal:\n';
39const start = 'Expected values to be strictly deep-equal:';
40const actExp = '+ actual - expected';
41
42assert.ok(a.AssertionError.prototype instanceof Error,
43          'a.AssertionError instanceof Error');
44
45assert.throws(() => a(false), a.AssertionError, 'ok(false)');
46assert.throws(() => a.ok(false), a.AssertionError, 'ok(false)');
47
48// Throw message if the message is instanceof Error.
49{
50  let threw = false;
51  try {
52    assert.ok(false, new Error('ok(false)'));
53  } catch (e) {
54    threw = true;
55    assert.ok(e instanceof Error);
56  }
57  assert.ok(threw, 'Error: ok(false)');
58}
59
60
61a(true);
62a('test', 'ok(\'test\')');
63a.ok(true);
64a.ok('test');
65
66assert.throws(() => a.equal(true, false),
67              a.AssertionError, 'equal(true, false)');
68
69a.equal(null, null);
70a.equal(undefined, undefined);
71a.equal(null, undefined);
72a.equal(true, true);
73a.equal(2, '2');
74a.notEqual(true, false);
75
76assert.throws(() => a.notEqual(true, true),
77              a.AssertionError, 'notEqual(true, true)');
78
79assert.throws(() => a.strictEqual(2, '2'),
80              a.AssertionError, 'strictEqual(2, \'2\')');
81
82/* eslint-disable no-restricted-syntax */
83assert.throws(() => a.strictEqual(null, undefined),
84              a.AssertionError, 'strictEqual(null, undefined)');
85
86assert.throws(
87  () => a.notStrictEqual(2, 2),
88  {
89    message: 'Expected "actual" to be strictly unequal to: 2',
90    name: 'AssertionError'
91  }
92);
93
94assert.throws(
95  () => a.notStrictEqual('a '.repeat(30), 'a '.repeat(30)),
96  {
97    message: 'Expected "actual" to be strictly unequal to:\n\n' +
98             `'${'a '.repeat(30)}'`,
99    name: 'AssertionError'
100  }
101);
102
103assert.throws(
104  () => a.notEqual(1, 1),
105  {
106    message: '1 != 1',
107    operator: '!='
108  }
109);
110
111a.notStrictEqual(2, '2');
112
113// Testing the throwing.
114function thrower(errorConstructor) {
115  throw new errorConstructor({});
116}
117
118// The basic calls work.
119assert.throws(() => thrower(a.AssertionError), a.AssertionError, 'message');
120assert.throws(() => thrower(a.AssertionError), a.AssertionError);
121assert.throws(() => thrower(a.AssertionError));
122
123// If not passing an error, catch all.
124assert.throws(() => thrower(TypeError));
125
126// When passing a type, only catch errors of the appropriate type.
127assert.throws(
128  () => a.throws(() => thrower(TypeError), a.AssertionError),
129  {
130    generatedMessage: true,
131    actual: new TypeError({}),
132    expected: a.AssertionError,
133    code: 'ERR_ASSERTION',
134    name: 'AssertionError',
135    operator: 'throws',
136    message: 'The error is expected to be an instance of "AssertionError". ' +
137             'Received "TypeError"\n\nError message:\n\n[object Object]'
138  }
139);
140
141// doesNotThrow should pass through all errors.
142{
143  let threw = false;
144  try {
145    a.doesNotThrow(() => thrower(TypeError), a.AssertionError);
146  } catch (e) {
147    threw = true;
148    assert.ok(e instanceof TypeError);
149  }
150  assert(threw, 'a.doesNotThrow with an explicit error is eating extra errors');
151}
152
153// Key difference is that throwing our correct error makes an assertion error.
154{
155  let threw = false;
156  try {
157    a.doesNotThrow(() => thrower(TypeError), TypeError);
158  } catch (e) {
159    threw = true;
160    assert.ok(e instanceof a.AssertionError);
161    assert.ok(!e.stack.includes('at Function.doesNotThrow'));
162  }
163  assert.ok(threw, 'a.doesNotThrow is not catching type matching errors');
164}
165
166assert.throws(
167  () => a.doesNotThrow(() => thrower(Error), 'user message'),
168  {
169    name: 'AssertionError',
170    code: 'ERR_ASSERTION',
171    operator: 'doesNotThrow',
172    message: 'Got unwanted exception: user message\n' +
173             'Actual message: "[object Object]"'
174  }
175);
176
177assert.throws(
178  () => a.doesNotThrow(() => thrower(Error)),
179  {
180    code: 'ERR_ASSERTION',
181    message: 'Got unwanted exception.\nActual message: "[object Object]"'
182  }
183);
184
185assert.throws(
186  () => a.doesNotThrow(() => thrower(Error), /\[[a-z]{6}\s[A-z]{6}\]/g, 'user message'),
187  {
188    name: 'AssertionError',
189    code: 'ERR_ASSERTION',
190    operator: 'doesNotThrow',
191    message: 'Got unwanted exception: user message\n' +
192             'Actual message: "[object Object]"'
193  }
194);
195
196// Make sure that validating using constructor really works.
197{
198  let threw = false;
199  try {
200    assert.throws(
201      () => {
202        throw ({}); // eslint-disable-line no-throw-literal
203      },
204      Array
205    );
206  } catch {
207    threw = true;
208  }
209  assert.ok(threw, 'wrong constructor validation');
210}
211
212// Use a RegExp to validate the error message.
213{
214  a.throws(() => thrower(TypeError), /\[object Object\]/);
215
216  const symbol = Symbol('foo');
217  a.throws(() => {
218    throw symbol;
219  }, /foo/);
220
221  a.throws(() => {
222    a.throws(() => {
223      throw symbol;
224    }, /abc/);
225  }, {
226    message: 'The input did not match the regular expression /abc/. ' +
227             "Input:\n\n'Symbol(foo)'\n",
228    code: 'ERR_ASSERTION',
229    operator: 'throws',
230    actual: symbol,
231    expected: /abc/
232  });
233}
234
235// Use a fn to validate the error object.
236a.throws(() => thrower(TypeError), (err) => {
237  if ((err instanceof TypeError) && /\[object Object\]/.test(err)) {
238    return true;
239  }
240});
241
242// https://github.com/nodejs/node/issues/3188
243{
244  let actual;
245  assert.throws(
246    () => {
247      const ES6Error = class extends Error {};
248      const AnotherErrorType = class extends Error {};
249
250      assert.throws(() => {
251        actual = new AnotherErrorType('foo');
252        throw actual;
253      }, ES6Error);
254    },
255    (err) => {
256      assert.strictEqual(
257        err.message,
258        'The error is expected to be an instance of "ES6Error". ' +
259          'Received "AnotherErrorType"\n\nError message:\n\nfoo'
260      );
261      assert.strictEqual(err.actual, actual);
262      return true;
263    }
264  );
265}
266
267// Check messages from assert.throws().
268{
269  const noop = () => {};
270  assert.throws(
271    () => { a.throws((noop)); },
272    {
273      code: 'ERR_ASSERTION',
274      message: 'Missing expected exception.',
275      operator: 'throws',
276      actual: undefined,
277      expected: undefined
278    });
279
280  assert.throws(
281    () => { a.throws(noop, TypeError); },
282    {
283      code: 'ERR_ASSERTION',
284      message: 'Missing expected exception (TypeError).',
285      actual: undefined,
286      expected: TypeError
287    });
288
289  assert.throws(
290    () => { a.throws(noop, 'fhqwhgads'); },
291    {
292      code: 'ERR_ASSERTION',
293      message: 'Missing expected exception: fhqwhgads',
294      actual: undefined,
295      expected: undefined
296    });
297
298  assert.throws(
299    () => { a.throws(noop, TypeError, 'fhqwhgads'); },
300    {
301      code: 'ERR_ASSERTION',
302      message: 'Missing expected exception (TypeError): fhqwhgads',
303      actual: undefined,
304      expected: TypeError
305    });
306
307  let threw = false;
308  try {
309    a.throws(noop);
310  } catch (e) {
311    threw = true;
312    assert.ok(e instanceof a.AssertionError);
313    assert.ok(!e.stack.includes('at Function.throws'));
314  }
315  assert.ok(threw);
316}
317
318const circular = { y: 1 };
319circular.x = circular;
320
321function testAssertionMessage(actual, expected, msg) {
322  assert.throws(
323    () => assert.strictEqual(actual, ''),
324    {
325      generatedMessage: true,
326      message: msg || strictEqualMessageStart +
327               `+ actual - expected\n\n+ ${expected}\n- ''`
328    }
329  );
330}
331
332function testShortAssertionMessage(actual, expected) {
333  testAssertionMessage(actual, expected, strictEqualMessageStart +
334                                         `\n${inspect(actual)} !== ''\n`);
335}
336
337testShortAssertionMessage(null, 'null');
338testShortAssertionMessage(true, 'true');
339testShortAssertionMessage(false, 'false');
340testShortAssertionMessage(100, '100');
341testShortAssertionMessage(NaN, 'NaN');
342testShortAssertionMessage(Infinity, 'Infinity');
343testShortAssertionMessage('a', '"a"');
344testShortAssertionMessage('foo', '\'foo\'');
345testShortAssertionMessage(0, '0');
346testShortAssertionMessage(Symbol(), 'Symbol()');
347testShortAssertionMessage(undefined, 'undefined');
348testShortAssertionMessage(-Infinity, '-Infinity');
349testAssertionMessage([], '[]');
350testAssertionMessage(/a/, '/a/');
351testAssertionMessage(/abc/gim, '/abc/gim');
352testAssertionMessage({}, '{}');
353testAssertionMessage([1, 2, 3], '[\n+   1,\n+   2,\n+   3\n+ ]');
354testAssertionMessage(function f() {}, '[Function: f]');
355testAssertionMessage(function() {}, '[Function (anonymous)]');
356testAssertionMessage(circular,
357                     '<ref *1> {\n+   x: [Circular *1],\n+   y: 1\n+ }');
358testAssertionMessage({ a: undefined, b: null },
359                     '{\n+   a: undefined,\n+   b: null\n+ }');
360testAssertionMessage({ a: NaN, b: Infinity, c: -Infinity },
361                     '{\n+   a: NaN,\n+   b: Infinity,\n+   c: -Infinity\n+ }');
362
363// https://github.com/nodejs/node-v0.x-archive/issues/5292
364assert.throws(
365  () => assert.strictEqual(1, 2),
366  {
367    message: `${strictEqualMessageStart}\n1 !== 2\n`,
368    generatedMessage: true
369  }
370);
371
372assert.throws(
373  () => assert.strictEqual(1, 2, 'oh no'),
374  {
375    message: 'oh no',
376    generatedMessage: false
377  }
378);
379
380{
381  let threw = false;
382  const rangeError = new RangeError('my range');
383
384  // Verify custom errors.
385  try {
386    assert.strictEqual(1, 2, rangeError);
387  } catch (e) {
388    assert.strictEqual(e, rangeError);
389    threw = true;
390    assert.ok(e instanceof RangeError, 'Incorrect error type thrown');
391  }
392  assert.ok(threw);
393  threw = false;
394
395  // Verify AssertionError is the result from doesNotThrow with custom Error.
396  try {
397    a.doesNotThrow(() => {
398      throw new TypeError('wrong type');
399    }, TypeError, rangeError);
400  } catch (e) {
401    threw = true;
402    assert.ok(e.message.includes(rangeError.message));
403    assert.ok(e instanceof assert.AssertionError);
404    assert.ok(!e.stack.includes('doesNotThrow'), e);
405  }
406  assert.ok(threw);
407}
408
409{
410  // Verify that throws() and doesNotThrow() throw on non-functions.
411  const testBlockTypeError = (method, fn) => {
412    assert.throws(
413      () => method(fn),
414      {
415        code: 'ERR_INVALID_ARG_TYPE',
416        name: 'TypeError',
417        message: 'The "fn" argument must be of type function.' +
418                 common.invalidArgTypeHelper(fn)
419      }
420    );
421  };
422
423  testBlockTypeError(assert.throws, 'string');
424  testBlockTypeError(assert.doesNotThrow, 'string');
425  testBlockTypeError(assert.throws, 1);
426  testBlockTypeError(assert.doesNotThrow, 1);
427  testBlockTypeError(assert.throws, true);
428  testBlockTypeError(assert.doesNotThrow, true);
429  testBlockTypeError(assert.throws, false);
430  testBlockTypeError(assert.doesNotThrow, false);
431  testBlockTypeError(assert.throws, []);
432  testBlockTypeError(assert.doesNotThrow, []);
433  testBlockTypeError(assert.throws, {});
434  testBlockTypeError(assert.doesNotThrow, {});
435  testBlockTypeError(assert.throws, /foo/);
436  testBlockTypeError(assert.doesNotThrow, /foo/);
437  testBlockTypeError(assert.throws, null);
438  testBlockTypeError(assert.doesNotThrow, null);
439  testBlockTypeError(assert.throws, undefined);
440  testBlockTypeError(assert.doesNotThrow, undefined);
441}
442
443// https://github.com/nodejs/node/issues/3275
444// eslint-disable-next-line no-throw-literal
445assert.throws(() => { throw 'error'; }, (err) => err === 'error');
446assert.throws(() => { throw new Error(); }, (err) => err instanceof Error);
447
448// Long values should be truncated for display.
449assert.throws(() => {
450  assert.strictEqual('A'.repeat(1000), '');
451}, (err) => {
452  assert.strictEqual(err.code, 'ERR_ASSERTION');
453  assert.strictEqual(err.message,
454                     `${strictEqualMessageStart}+ actual - expected\n\n` +
455                     `+ '${'A'.repeat(1000)}'\n- ''`);
456  assert.strictEqual(err.actual.length, 1000);
457  assert.ok(inspect(err).includes(`actual: '${'A'.repeat(488)}...'`));
458  return true;
459});
460
461// Output that extends beyond 10 lines should also be truncated for display.
462{
463  const multilineString = 'fhqwhgads\n'.repeat(15);
464  assert.throws(() => {
465    assert.strictEqual(multilineString, '');
466  }, (err) => {
467    assert.strictEqual(err.code, 'ERR_ASSERTION');
468    assert.strictEqual(err.message.split('\n').length, 19);
469    assert.strictEqual(err.actual.split('\n').length, 16);
470    assert.ok(inspect(err).includes(
471      "actual: 'fhqwhgads\\n' +\n" +
472      "    'fhqwhgads\\n' +\n".repeat(9) +
473      "    '...'"));
474    return true;
475  });
476}
477
478{
479  // Bad args to AssertionError constructor should throw TypeError.
480  const args = [1, true, false, '', null, Infinity, Symbol('test'), undefined];
481  args.forEach((input) => {
482    assert.throws(
483      () => new assert.AssertionError(input),
484      {
485        code: 'ERR_INVALID_ARG_TYPE',
486        name: 'TypeError',
487        message: 'The "options" argument must be of type object.' +
488                 common.invalidArgTypeHelper(input)
489      });
490  });
491}
492
493assert.throws(
494  () => assert.strictEqual(new Error('foo'), new Error('foobar')),
495  {
496    code: 'ERR_ASSERTION',
497    name: 'AssertionError',
498    message: 'Expected "actual" to be reference-equal to "expected":\n' +
499             '+ actual - expected\n\n' +
500             '+ [Error: foo]\n- [Error: foobar]'
501  }
502);
503
504a.equal(NaN, NaN);
505a.throws(
506  () => a.notEqual(NaN, NaN),
507  a.AssertionError
508);
509
510// Test strict assert.
511{
512  const a = require('assert');
513  const assert = require('assert').strict;
514  /* eslint-disable no-restricted-properties */
515  assert.throws(() => assert.equal(1, true), assert.AssertionError);
516  assert.notEqual(0, false);
517  assert.throws(() => assert.deepEqual(1, true), assert.AssertionError);
518  assert.notDeepEqual(0, false);
519  assert.equal(assert.strict, assert.strict.strict);
520  assert.equal(assert.equal, assert.strictEqual);
521  assert.equal(assert.deepEqual, assert.deepStrictEqual);
522  assert.equal(assert.notEqual, assert.notStrictEqual);
523  assert.equal(assert.notDeepEqual, assert.notDeepStrictEqual);
524  assert.equal(Object.keys(assert).length, Object.keys(a).length);
525  assert(7);
526  assert.throws(
527    () => assert(...[]),
528    {
529      message: 'No value argument passed to `assert.ok()`',
530      name: 'AssertionError',
531      generatedMessage: true
532    }
533  );
534  assert.throws(
535    () => a(),
536    {
537      message: 'No value argument passed to `assert.ok()`',
538      name: 'AssertionError'
539    }
540  );
541
542  // Test setting the limit to zero and that assert.strict works properly.
543  const tmpLimit = Error.stackTraceLimit;
544  Error.stackTraceLimit = 0;
545  assert.throws(
546    () => {
547      assert.ok(
548        typeof 123 === 'string'
549      );
550    },
551    {
552      code: 'ERR_ASSERTION',
553      constructor: assert.AssertionError,
554      message: 'The expression evaluated to a falsy value:\n\n  ' +
555               "assert.ok(\n    typeof 123 === 'string'\n  )\n"
556    }
557  );
558  Error.stackTraceLimit = tmpLimit;
559
560  // Test error diffs.
561  let message = [
562    start,
563    `${actExp} ... Lines skipped`,
564    '',
565    '  [',
566    '    [',
567    '      [',
568    '        1,',
569    '        2,',
570    '+       3',
571    "-       '3'",
572    '      ]',
573    '...',
574    '    4,',
575    '    5',
576    '  ]'].join('\n');
577  assert.throws(
578    () => assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]),
579    { message });
580
581  message = [
582    start,
583    `${actExp} ... Lines skipped`,
584    '',
585    '  [',
586    '    1,',
587    '...',
588    '    1,',
589    '    0,',
590    '-   1,',
591    '    1,',
592    '...',
593    '    1,',
594    '    1',
595    '  ]',
596  ].join('\n');
597  assert.throws(
598    () => assert.deepEqual(
599      [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1],
600      [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]),
601    { message });
602
603  message = [
604    start,
605    `${actExp} ... Lines skipped`,
606    '',
607    '  [',
608    '    1,',
609    '...',
610    '    1,',
611    '    0,',
612    '+   1,',
613    '    1,',
614    '    1,',
615    '    1',
616    '  ]',
617  ].join('\n');
618  assert.throws(
619    () => assert.deepEqual(
620      [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1],
621      [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1]),
622    { message });
623
624  message = [
625    start,
626    actExp,
627    '',
628    '  [',
629    '    1,',
630    '+   2,',
631    '-   1,',
632    '    1,',
633    '    1,',
634    '    0,',
635    '+   1,',
636    '    1',
637    '  ]',
638  ].join('\n');
639  assert.throws(
640    () => assert.deepEqual(
641      [1, 2, 1, 1, 0, 1, 1],
642      [1, 1, 1, 1, 0, 1]),
643    { message });
644
645  message = [
646    start,
647    actExp,
648    '',
649    '+ [',
650    '+   1,',
651    '+   2,',
652    '+   1',
653    '+ ]',
654    '- undefined',
655  ].join('\n');
656  assert.throws(
657    () => assert.deepEqual([1, 2, 1], undefined),
658    { message });
659
660  message = [
661    start,
662    actExp,
663    '',
664    '  [',
665    '+   1,',
666    '    2,',
667    '    1',
668    '  ]',
669  ].join('\n');
670  assert.throws(
671    () => assert.deepEqual([1, 2, 1], [2, 1]),
672    { message });
673
674  message = `${start}\n` +
675    `${actExp} ... Lines skipped\n` +
676    '\n' +
677    '  [\n' +
678    '+   1,\n'.repeat(25) +
679    '...\n' +
680    '-   2,\n'.repeat(25) +
681    '...';
682  assert.throws(
683    () => assert.deepEqual(Array(28).fill(1), Array(28).fill(2)),
684    { message });
685
686  const obj1 = {};
687  const obj2 = { loop: 'forever' };
688  obj2[inspect.custom] = () => '{}';
689  // No infinite loop and no custom inspect.
690  assert.throws(() => assert.deepEqual(obj1, obj2), {
691    message: `${start}\n` +
692    `${actExp}\n` +
693    '\n' +
694    '+ {}\n' +
695    '- {\n' +
696    '-   [Symbol(nodejs.util.inspect.custom)]: [Function (anonymous)],\n' +
697    "-   loop: 'forever'\n" +
698    '- }'
699  });
700
701  // notDeepEqual tests
702  assert.throws(
703    () => assert.notDeepEqual([1], [1]),
704    {
705      message: 'Expected "actual" not to be strictly deep-equal to:\n\n' +
706               '[\n  1\n]\n'
707    }
708  );
709
710  message = 'Expected "actual" not to be strictly deep-equal to:' +
711            `\n\n[${'\n  1,'.repeat(45)}\n...\n`;
712  const data = Array(51).fill(1);
713  assert.throws(
714    () => assert.notDeepEqual(data, data),
715    { message });
716  /* eslint-enable no-restricted-properties */
717}
718
719assert.throws(
720  () => assert.ok(null),
721  {
722    code: 'ERR_ASSERTION',
723    constructor: assert.AssertionError,
724    generatedMessage: true,
725    message: 'The expression evaluated to a falsy value:\n\n  ' +
726             'assert.ok(null)\n'
727  }
728);
729assert.throws(
730  () => {
731    // This test case checks if `try` left brace without a line break
732    // before the assertion causes any wrong assertion message.
733    // Therefore, don't reformat the following code.
734    // Refs: https://github.com/nodejs/node/issues/30872
735    try { assert.ok(0);   // eslint-disable-line no-useless-catch, brace-style
736    } catch (err) {
737      throw err;
738    }
739  },
740  {
741    code: 'ERR_ASSERTION',
742    constructor: assert.AssertionError,
743    generatedMessage: true,
744    message: 'The expression evaluated to a falsy value:\n\n  ' +
745             'assert.ok(0)\n'
746  }
747);
748assert.throws(
749  () => {
750    try {
751      throw new Error();
752    // This test case checks if `catch` left brace without a line break
753    // before the assertion causes any wrong assertion message.
754    // Therefore, don't reformat the following code.
755    // Refs: https://github.com/nodejs/node/issues/30872
756    } catch (err) { assert.ok(0); }     // eslint-disable-line no-unused-vars
757  },
758  {
759    code: 'ERR_ASSERTION',
760    constructor: assert.AssertionError,
761    generatedMessage: true,
762    message: 'The expression evaluated to a falsy value:\n\n  ' +
763             'assert.ok(0)\n'
764  }
765);
766assert.throws(
767  () => {
768    // This test case checks if `function` left brace without a line break
769    // before the assertion causes any wrong assertion message.
770    // Therefore, don't reformat the following code.
771    // Refs: https://github.com/nodejs/node/issues/30872
772    function test() { assert.ok(0);     // eslint-disable-line brace-style
773    }
774    test();
775  },
776  {
777    code: 'ERR_ASSERTION',
778    constructor: assert.AssertionError,
779    generatedMessage: true,
780    message: 'The expression evaluated to a falsy value:\n\n  ' +
781             'assert.ok(0)\n'
782  }
783);
784assert.throws(
785  () => assert(typeof 123n === 'string'),
786  {
787    code: 'ERR_ASSERTION',
788    constructor: assert.AssertionError,
789    generatedMessage: true,
790    message: 'The expression evaluated to a falsy value:\n\n  ' +
791             "assert(typeof 123n === 'string')\n"
792  }
793);
794
795assert.throws(
796  () => assert(false, Symbol('foo')),
797  {
798    code: 'ERR_ASSERTION',
799    constructor: assert.AssertionError,
800    generatedMessage: false,
801    message: 'Symbol(foo)'
802  }
803);
804
805{
806  // Test caching.
807  const fs = internalBinding('fs');
808  const tmp = fs.close;
809  fs.close = common.mustCall(tmp, 1);
810  function throwErr() {
811    assert(
812      (Buffer.from('test') instanceof Error)
813    );
814  }
815  assert.throws(
816    () => throwErr(),
817    {
818      code: 'ERR_ASSERTION',
819      constructor: assert.AssertionError,
820      message: 'The expression evaluated to a falsy value:\n\n  ' +
821               "assert(\n    (Buffer.from('test') instanceof Error)\n  )\n"
822    }
823  );
824  assert.throws(
825    () => throwErr(),
826    {
827      code: 'ERR_ASSERTION',
828      constructor: assert.AssertionError,
829      message: 'The expression evaluated to a falsy value:\n\n  ' +
830               "assert(\n    (Buffer.from('test') instanceof Error)\n  )\n"
831    }
832  );
833  fs.close = tmp;
834}
835
836assert.throws(
837  () => {
838    a(
839      (() => 'string')()
840      // eslint-disable-next-line operator-linebreak
841      ===
842      123 instanceof
843          Buffer
844    );
845  },
846  {
847    code: 'ERR_ASSERTION',
848    constructor: assert.AssertionError,
849    message: 'The expression evaluated to a falsy value:\n\n' +
850             '  a(\n' +
851             '    (() => \'string\')()\n' +
852             '    // eslint-disable-next-line operator-linebreak\n' +
853             '    ===\n' +
854             '    123 instanceof\n' +
855             '        Buffer\n' +
856             '  )\n'
857  }
858);
859
860assert.throws(
861  () => {
862    a(
863      (() => 'string')()
864      // eslint-disable-next-line operator-linebreak
865      ===
866  123 instanceof
867          Buffer
868    );
869  },
870  {
871    code: 'ERR_ASSERTION',
872    constructor: assert.AssertionError,
873    message: 'The expression evaluated to a falsy value:\n\n' +
874             '  a(\n' +
875             '    (() => \'string\')()\n' +
876             '    // eslint-disable-next-line operator-linebreak\n' +
877             '    ===\n' +
878             '  123 instanceof\n' +
879             '        Buffer\n' +
880             '  )\n'
881  }
882);
883
884/* eslint-disable indent */
885assert.throws(() => {
886a((
887  () => 'string')() ===
888123 instanceof
889Buffer
890);
891}, {
892  code: 'ERR_ASSERTION',
893  constructor: assert.AssertionError,
894  message: 'The expression evaluated to a falsy value:\n\n' +
895           '  a((\n' +
896           '    () => \'string\')() ===\n' +
897           '  123 instanceof\n' +
898           '  Buffer\n' +
899           '  )\n'
900  }
901);
902/* eslint-enable indent */
903
904assert.throws(
905  () => {
906    assert(true); assert(null, undefined);
907  },
908  {
909    code: 'ERR_ASSERTION',
910    constructor: assert.AssertionError,
911    message: 'The expression evaluated to a falsy value:\n\n  ' +
912             'assert(null, undefined)\n'
913  }
914);
915
916assert.throws(
917  () => {
918    assert
919     .ok(null, undefined);
920  },
921  {
922    code: 'ERR_ASSERTION',
923    constructor: assert.AssertionError,
924    message: 'The expression evaluated to a falsy value:\n\n  ' +
925             'ok(null, undefined)\n'
926  }
927);
928
929assert.throws(
930  // eslint-disable-next-line dot-notation, quotes
931  () => assert['ok']["apply"](null, [0]),
932  {
933    code: 'ERR_ASSERTION',
934    constructor: assert.AssertionError,
935    message: 'The expression evaluated to a falsy value:\n\n  ' +
936             'assert[\'ok\']["apply"](null, [0])\n'
937  }
938);
939
940assert.throws(
941  () => {
942    const wrapper = (fn, value) => fn(value);
943    wrapper(assert, false);
944  },
945  {
946    code: 'ERR_ASSERTION',
947    constructor: assert.AssertionError,
948    message: 'The expression evaluated to a falsy value:\n\n  fn(value)\n'
949  }
950);
951
952assert.throws(
953  () => assert.ok.call(null, 0),
954  {
955    code: 'ERR_ASSERTION',
956    constructor: assert.AssertionError,
957    message: 'The expression evaluated to a falsy value:\n\n  ' +
958             'assert.ok.call(null, 0)\n',
959    generatedMessage: true
960  }
961);
962
963assert.throws(
964  () => assert.ok.call(null, 0, 'test'),
965  {
966    code: 'ERR_ASSERTION',
967    constructor: assert.AssertionError,
968    message: 'test',
969    generatedMessage: false
970  }
971);
972
973// Works in eval.
974assert.throws(
975  () => new Function('assert', 'assert(1 === 2);')(assert),
976  {
977    code: 'ERR_ASSERTION',
978    constructor: assert.AssertionError,
979    message: 'false == true'
980  }
981);
982assert.throws(
983  () => eval('console.log("FOO");\nassert.ok(1 === 2);'),
984  {
985    code: 'ERR_ASSERTION',
986    message: 'false == true'
987  }
988);
989
990assert.throws(
991  () => assert.throws(() => {}, 'Error message', 'message'),
992  {
993    code: 'ERR_INVALID_ARG_TYPE',
994    name: 'TypeError',
995    message: 'The "error" argument must be of type function or ' +
996             'an instance of Error, RegExp, or Object. Received type string ' +
997             "('Error message')"
998  }
999);
1000
1001[
1002  1,
1003  false,
1004  Symbol(),
1005].forEach((input) => {
1006  assert.throws(
1007    () => assert.throws(() => {}, input),
1008    {
1009      code: 'ERR_INVALID_ARG_TYPE',
1010      message: 'The "error" argument must be of type function or ' +
1011               'an instance of Error, RegExp, or Object.' +
1012               common.invalidArgTypeHelper(input)
1013    }
1014  );
1015});
1016
1017{
1018
1019  assert.throws(() => {
1020    assert.ok((() => Boolean('' === false))());
1021  }, {
1022    message: 'The expression evaluated to a falsy value:\n\n' +
1023             "  assert.ok((() => Boolean('\\u0001' === false))())\n"
1024  });
1025
1026  const errFn = () => {
1027    const err = new TypeError('Wrong value');
1028    err.code = 404;
1029    throw err;
1030  };
1031  const errObj = {
1032    name: 'TypeError',
1033    message: 'Wrong value'
1034  };
1035  assert.throws(errFn, errObj);
1036
1037  errObj.code = 404;
1038  assert.throws(errFn, errObj);
1039
1040  // Fail in case a expected property is undefined and not existent on the
1041  // error.
1042  errObj.foo = undefined;
1043  assert.throws(
1044    () => assert.throws(errFn, errObj),
1045    {
1046      code: 'ERR_ASSERTION',
1047      name: 'AssertionError',
1048      message: `${start}\n${actExp}\n\n` +
1049               '  Comparison {\n' +
1050               '    code: 404,\n' +
1051               '-   foo: undefined,\n' +
1052               "    message: 'Wrong value',\n" +
1053               "    name: 'TypeError'\n" +
1054               '  }'
1055    }
1056  );
1057
1058  // Show multiple wrong properties at the same time.
1059  errObj.code = '404';
1060  assert.throws(
1061    () => assert.throws(errFn, errObj),
1062    {
1063      code: 'ERR_ASSERTION',
1064      name: 'AssertionError',
1065      message: `${start}\n${actExp}\n\n` +
1066               '  Comparison {\n' +
1067               '+   code: 404,\n' +
1068               "-   code: '404',\n" +
1069               '-   foo: undefined,\n' +
1070               "    message: 'Wrong value',\n" +
1071               "    name: 'TypeError'\n" +
1072               '  }'
1073    }
1074  );
1075
1076  assert.throws(
1077    () => assert.throws(() => { throw new Error(); }, { foo: 'bar' }, 'foobar'),
1078    {
1079      constructor: assert.AssertionError,
1080      code: 'ERR_ASSERTION',
1081      message: 'foobar'
1082    }
1083  );
1084
1085  assert.throws(
1086    () => a.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }),
1087    {
1088      name: 'TypeError',
1089      code: 'ERR_INVALID_ARG_TYPE',
1090      message: 'The "expected" argument must be of type function or an ' +
1091               'instance of RegExp. Received an instance of Object'
1092    }
1093  );
1094
1095  assert.throws(() => { throw new Error('e'); }, new Error('e'));
1096  assert.throws(
1097    () => assert.throws(() => { throw new TypeError('e'); }, new Error('e')),
1098    {
1099      name: 'AssertionError',
1100      code: 'ERR_ASSERTION',
1101      message: `${start}\n${actExp}\n\n` +
1102               '  Comparison {\n' +
1103               "    message: 'e',\n" +
1104               "+   name: 'TypeError'\n" +
1105               "-   name: 'Error'\n" +
1106               '  }'
1107    }
1108  );
1109  assert.throws(
1110    () => assert.throws(() => { throw new Error('foo'); }, new Error('')),
1111    {
1112      name: 'AssertionError',
1113      code: 'ERR_ASSERTION',
1114      generatedMessage: true,
1115      message: `${start}\n${actExp}\n\n` +
1116               '  Comparison {\n' +
1117               "+   message: 'foo',\n" +
1118               "-   message: '',\n" +
1119               "    name: 'Error'\n" +
1120               '  }'
1121    }
1122  );
1123
1124  // eslint-disable-next-line no-throw-literal
1125  assert.throws(() => { throw undefined; }, /undefined/);
1126  assert.throws(
1127    // eslint-disable-next-line no-throw-literal
1128    () => a.doesNotThrow(() => { throw undefined; }),
1129    {
1130      name: 'AssertionError',
1131      code: 'ERR_ASSERTION',
1132      message: 'Got unwanted exception.\nActual message: "undefined"'
1133    }
1134  );
1135}
1136
1137assert.throws(
1138  () => assert.throws(() => { throw new Error(); }, {}),
1139  {
1140    message: "The argument 'error' may not be an empty object. Received {}",
1141    code: 'ERR_INVALID_ARG_VALUE'
1142  }
1143);
1144
1145assert.throws(
1146  () => a.throws(
1147    // eslint-disable-next-line no-throw-literal
1148    () => { throw 'foo'; },
1149    'foo'
1150  ),
1151  {
1152    code: 'ERR_AMBIGUOUS_ARGUMENT',
1153    message: 'The "error/message" argument is ambiguous. ' +
1154             'The error "foo" is identical to the message.'
1155  }
1156);
1157
1158assert.throws(
1159  () => a.throws(
1160    () => { throw new TypeError('foo'); },
1161    'foo'
1162  ),
1163  {
1164    code: 'ERR_AMBIGUOUS_ARGUMENT',
1165    message: 'The "error/message" argument is ambiguous. ' +
1166             'The error message "foo" is identical to the message.'
1167  }
1168);
1169/* eslint-enable no-restricted-syntax */
1170
1171// Should not throw.
1172// eslint-disable-next-line no-restricted-syntax, no-throw-literal
1173assert.throws(() => { throw null; }, 'foo');
1174
1175assert.throws(
1176  () => assert.strictEqual([], []),
1177  {
1178    message: 'Values have same structure but are not reference-equal:\n\n[]\n'
1179  }
1180);
1181
1182{
1183  const args = (function() { return arguments; })('a');
1184  assert.throws(
1185    () => assert.strictEqual(args, { 0: 'a' }),
1186    {
1187      message: 'Expected "actual" to be reference-equal to "expected":\n' +
1188               '+ actual - expected\n\n' +
1189               "+ [Arguments] {\n- {\n    '0': 'a'\n  }"
1190    }
1191  );
1192}
1193
1194assert.throws(
1195  () => { throw new TypeError('foobar'); },
1196  {
1197    message: /foo/,
1198    name: /^TypeError$/
1199  }
1200);
1201
1202assert.throws(
1203  () => assert.throws(
1204    () => { throw new TypeError('foobar'); },
1205    {
1206      message: /fooa/,
1207      name: /^TypeError$/
1208    }
1209  ),
1210  {
1211    message: `${start}\n${actExp}\n\n` +
1212             '  Comparison {\n' +
1213             "+   message: 'foobar',\n" +
1214             '-   message: /fooa/,\n' +
1215             "    name: 'TypeError'\n" +
1216             '  }'
1217  }
1218);
1219
1220{
1221  let actual = null;
1222  const expected = { message: 'foo' };
1223  assert.throws(
1224    () => assert.throws(
1225      () => { throw actual; },
1226      expected
1227    ),
1228    {
1229      operator: 'throws',
1230      actual,
1231      expected,
1232      generatedMessage: true,
1233      message: `${start}\n${actExp}\n\n` +
1234              '+ null\n' +
1235              '- {\n' +
1236              "-   message: 'foo'\n" +
1237              '- }'
1238    }
1239  );
1240
1241  actual = 'foobar';
1242  const message = 'message';
1243  assert.throws(
1244    () => assert.throws(
1245      () => { throw actual; },
1246      { message: 'foobar' },
1247      message
1248    ),
1249    {
1250      actual,
1251      message,
1252      operator: 'throws',
1253      generatedMessage: false
1254    }
1255  );
1256}
1257
1258// Indicate where the strings diverge.
1259assert.throws(
1260  () => assert.strictEqual('test test', 'test foobar'),
1261  {
1262    code: 'ERR_ASSERTION',
1263    name: 'AssertionError',
1264    message: strictEqualMessageStart +
1265             '+ actual - expected\n\n' +
1266             "+ 'test test'\n" +
1267             "- 'test foobar'\n" +
1268             '        ^'
1269  }
1270);
1271
1272// Check for reference-equal objects in `notStrictEqual()`
1273assert.throws(
1274  () => {
1275    const obj = {};
1276    assert.notStrictEqual(obj, obj);
1277  },
1278  {
1279    code: 'ERR_ASSERTION',
1280    name: 'AssertionError',
1281    message: 'Expected "actual" not to be reference-equal to "expected": {}'
1282  }
1283);
1284
1285assert.throws(
1286  () => {
1287    const obj = { a: true };
1288    assert.notStrictEqual(obj, obj);
1289  },
1290  {
1291    code: 'ERR_ASSERTION',
1292    name: 'AssertionError',
1293    message: 'Expected "actual" not to be reference-equal to "expected":\n\n' +
1294             '{\n  a: true\n}\n'
1295  }
1296);
1297
1298{
1299  let threw = false;
1300  try {
1301    // eslint-disable-next-line no-restricted-syntax
1302    assert.deepStrictEqual(Array(100).fill(1), 'foobar');
1303  } catch (err) {
1304    threw = true;
1305    assert.match(inspect(err), /actual: \[Array],\n {2}expected: 'foobar',/);
1306  }
1307  assert(threw);
1308}
1309
1310assert.throws(
1311  () => a.equal(1),
1312  { code: 'ERR_MISSING_ARGS' }
1313);
1314
1315assert.throws(
1316  () => a.deepEqual(/a/),
1317  { code: 'ERR_MISSING_ARGS' }
1318);
1319
1320assert.throws(
1321  () => a.notEqual(null),
1322  { code: 'ERR_MISSING_ARGS' }
1323);
1324
1325assert.throws(
1326  () => a.notDeepEqual('test'),
1327  { code: 'ERR_MISSING_ARGS' }
1328);
1329
1330assert.throws(
1331  () => a.strictEqual({}),
1332  { code: 'ERR_MISSING_ARGS' }
1333);
1334
1335assert.throws(
1336  () => a.deepStrictEqual(Symbol()),
1337  { code: 'ERR_MISSING_ARGS' }
1338);
1339
1340assert.throws(
1341  () => a.notStrictEqual(5n), // eslint-disable-line no-restricted-syntax
1342  { code: 'ERR_MISSING_ARGS' }
1343);
1344
1345assert.throws(
1346  () => a.notDeepStrictEqual(undefined),
1347  { code: 'ERR_MISSING_ARGS' }
1348);
1349
1350assert.throws(
1351  () => a.strictEqual(),
1352  { code: 'ERR_MISSING_ARGS' }
1353);
1354
1355assert.throws(
1356  () => a.deepStrictEqual(),
1357  { code: 'ERR_MISSING_ARGS' }
1358);
1359
1360// Verify that `stackStartFunction` works as alternative to `stackStartFn`.
1361{
1362  (function hidden() {
1363    const err = new assert.AssertionError({
1364      actual: 'foo',
1365      operator: 'strictEqual',
1366      stackStartFunction: hidden
1367    });
1368    const err2 = new assert.AssertionError({
1369      actual: 'foo',
1370      operator: 'strictEqual',
1371      stackStartFn: hidden
1372    });
1373    assert(!err.stack.includes('hidden'));
1374    assert(!err2.stack.includes('hidden'));
1375  })();
1376}
1377
1378assert.throws(
1379  () => assert.throws(() => { throw Symbol('foo'); }, RangeError),
1380  {
1381    message: 'The error is expected to be an instance of "RangeError". ' +
1382             'Received "Symbol(foo)"'
1383  }
1384);
1385
1386assert.throws(
1387  // eslint-disable-next-line no-throw-literal
1388  () => assert.throws(() => { throw [1, 2]; }, RangeError),
1389  {
1390    message: 'The error is expected to be an instance of "RangeError". ' +
1391             'Received "[Array]"'
1392  }
1393);
1394
1395{
1396  const err = new TypeError('foo');
1397  const validate = (() => () => ({ a: true, b: [ 1, 2, 3 ] }))();
1398  assert.throws(
1399    () => assert.throws(() => { throw err; }, validate),
1400    {
1401      message: 'The validation function is expected to ' +
1402              `return "true". Received ${inspect(validate())}\n\nCaught ` +
1403              `error:\n\n${err}`,
1404      code: 'ERR_ASSERTION',
1405      actual: err,
1406      expected: validate,
1407      name: 'AssertionError',
1408      operator: 'throws',
1409    }
1410  );
1411}
1412
1413assert.throws(
1414  () => {
1415    const script = new vm.Script('new RangeError("foobar");');
1416    const context = vm.createContext();
1417    const err = script.runInContext(context);
1418    assert.throws(() => { throw err; }, RangeError);
1419  },
1420  {
1421    message: 'The error is expected to be an instance of "RangeError". ' +
1422             'Received an error with identical name but a different ' +
1423             'prototype.\n\nError message:\n\nfoobar'
1424  }
1425);
1426
1427// Multiple assert.match() tests.
1428{
1429  assert.throws(
1430    () => assert.match(/abc/, 'string'),
1431    {
1432      code: 'ERR_INVALID_ARG_TYPE',
1433      message: 'The "regexp" argument must be an instance of RegExp. ' +
1434               "Received type string ('string')"
1435    }
1436  );
1437  assert.throws(
1438    () => assert.match('string', /abc/),
1439    {
1440      actual: 'string',
1441      expected: /abc/,
1442      operator: 'match',
1443      message: 'The input did not match the regular expression /abc/. ' +
1444               "Input:\n\n'string'\n",
1445      generatedMessage: true
1446    }
1447  );
1448  assert.throws(
1449    () => assert.match('string', /abc/, 'foobar'),
1450    {
1451      actual: 'string',
1452      expected: /abc/,
1453      operator: 'match',
1454      message: 'foobar',
1455      generatedMessage: false
1456    }
1457  );
1458  const errorMessage = new RangeError('foobar');
1459  assert.throws(
1460    () => assert.match('string', /abc/, errorMessage),
1461    errorMessage
1462  );
1463  assert.throws(
1464    () => assert.match({ abc: 123 }, /abc/),
1465    {
1466      actual: { abc: 123 },
1467      expected: /abc/,
1468      operator: 'match',
1469      message: 'The "string" argument must be of type string. ' +
1470               'Received type object ({ abc: 123 })',
1471      generatedMessage: true
1472    }
1473  );
1474  assert.match('I will pass', /pass$/);
1475}
1476
1477// Multiple assert.doesNotMatch() tests.
1478{
1479  assert.throws(
1480    () => assert.doesNotMatch(/abc/, 'string'),
1481    {
1482      code: 'ERR_INVALID_ARG_TYPE',
1483      message: 'The "regexp" argument must be an instance of RegExp. ' +
1484               "Received type string ('string')"
1485    }
1486  );
1487  assert.throws(
1488    () => assert.doesNotMatch('string', /string/),
1489    {
1490      actual: 'string',
1491      expected: /string/,
1492      operator: 'doesNotMatch',
1493      message: 'The input was expected to not match the regular expression ' +
1494               "/string/. Input:\n\n'string'\n",
1495      generatedMessage: true
1496    }
1497  );
1498  assert.throws(
1499    () => assert.doesNotMatch('string', /string/, 'foobar'),
1500    {
1501      actual: 'string',
1502      expected: /string/,
1503      operator: 'doesNotMatch',
1504      message: 'foobar',
1505      generatedMessage: false
1506    }
1507  );
1508  const errorMessage = new RangeError('foobar');
1509  assert.throws(
1510    () => assert.doesNotMatch('string', /string/, errorMessage),
1511    errorMessage
1512  );
1513  assert.throws(
1514    () => assert.doesNotMatch({ abc: 123 }, /abc/),
1515    {
1516      actual: { abc: 123 },
1517      expected: /abc/,
1518      operator: 'doesNotMatch',
1519      message: 'The "string" argument must be of type string. ' +
1520               'Received type object ({ abc: 123 })',
1521      generatedMessage: true
1522    }
1523  );
1524  assert.doesNotMatch('I will pass', /different$/);
1525}
1526
1527{
1528  const tempColor = inspect.defaultOptions.colors;
1529  assert.throws(() => {
1530    inspect.defaultOptions.colors = true;
1531    // Guarantee the position indicator is placed correctly.
1532    assert.strictEqual(111554n, 11111115);
1533  }, (err) => {
1534    assert.strictEqual(inspect(err).split('\n')[5], '     ^');
1535    inspect.defaultOptions.colors = tempColor;
1536    return true;
1537  });
1538}
1539