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