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