2009-11-30 02:20:37 +00:00
|
|
|
// Originally from narwhal.js (http://narwhaljs.org)
|
|
|
|
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
2010-03-15 15:00:19 +00:00
|
|
|
// of this software and associated documentation files (the 'Software'), to
|
2009-11-30 02:20:37 +00:00
|
|
|
// deal in the Software without restriction, including without limitation the
|
|
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
2010-12-02 00:36:23 +00:00
|
|
|
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
2009-11-30 02:20:37 +00:00
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
|
|
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
2014-11-22 15:59:48 +00:00
|
|
|
'use strict';
|
|
|
|
|
2017-12-09 22:20:07 +00:00
|
|
|
const { Buffer } = require('buffer');
|
|
|
|
const {
|
|
|
|
isDeepEqual,
|
|
|
|
isDeepStrictEqual
|
|
|
|
} = require('internal/util/comparisons');
|
2018-01-23 15:45:28 +00:00
|
|
|
const { AssertionError, TypeError, errorCache } = require('internal/errors');
|
2017-12-09 22:20:07 +00:00
|
|
|
const { openSync, closeSync, readSync } = require('fs');
|
|
|
|
const { parseExpressionAt } = require('internal/deps/acorn/dist/acorn');
|
2017-12-10 00:54:44 +00:00
|
|
|
const { inspect } = require('util');
|
2017-12-09 22:20:07 +00:00
|
|
|
const { EOL } = require('os');
|
2018-01-23 15:45:28 +00:00
|
|
|
const nativeModule = require('native_module');
|
2017-12-09 22:20:07 +00:00
|
|
|
|
|
|
|
// Escape control characters but not \n and \t to keep the line breaks and
|
|
|
|
// indentation intact.
|
|
|
|
// eslint-disable-next-line no-control-regex
|
|
|
|
const escapeSequencesRegExp = /[\x00-\x08\x0b\x0c\x0e-\x1f]/g;
|
|
|
|
const meta = [
|
|
|
|
'\\u0000', '\\u0001', '\\u0002', '\\u0003', '\\u0004',
|
|
|
|
'\\u0005', '\\u0006', '\\u0007', '\\b', '',
|
|
|
|
'', '\\u000b', '\\f', '', '\\u000e',
|
|
|
|
'\\u000f', '\\u0010', '\\u0011', '\\u0012', '\\u0013',
|
|
|
|
'\\u0014', '\\u0015', '\\u0016', '\\u0017', '\\u0018',
|
|
|
|
'\\u0019', '\\u001a', '\\u001b', '\\u001c', '\\u001d',
|
|
|
|
'\\u001e', '\\u001f'
|
|
|
|
];
|
|
|
|
|
|
|
|
const escapeFn = (str) => meta[str.charCodeAt(0)];
|
2017-04-25 20:18:25 +00:00
|
|
|
|
2017-12-09 21:38:20 +00:00
|
|
|
const ERR_DIFF_DEACTIVATED = 0;
|
|
|
|
const ERR_DIFF_NOT_EQUAL = 1;
|
|
|
|
const ERR_DIFF_EQUAL = 2;
|
|
|
|
|
2018-01-28 11:07:18 +00:00
|
|
|
let warned = false;
|
|
|
|
|
2017-01-02 21:50:04 +00:00
|
|
|
// The assert module provides functions that throw
|
2009-11-30 02:20:37 +00:00
|
|
|
// AssertionError's when particular conditions are not met. The
|
|
|
|
// assert module must conform to the following interface.
|
|
|
|
|
2015-01-21 16:36:59 +00:00
|
|
|
const assert = module.exports = ok;
|
2009-11-28 17:26:59 +00:00
|
|
|
|
2018-01-07 22:17:29 +00:00
|
|
|
const NO_EXCEPTION_SENTINEL = {};
|
|
|
|
|
2017-01-02 21:50:04 +00:00
|
|
|
// All of the following functions must throw an AssertionError
|
2009-11-28 17:26:59 +00:00
|
|
|
// when a corresponding condition is not met, with a message that
|
2017-06-27 04:00:35 +00:00
|
|
|
// may be undefined if not provided. All assertion methods provide
|
2009-11-28 17:26:59 +00:00
|
|
|
// both the actual and expected values to the assertion error for
|
|
|
|
// display purposes.
|
|
|
|
|
2017-12-09 19:15:19 +00:00
|
|
|
function innerFail(obj) {
|
|
|
|
if (obj.message instanceof Error) throw obj.message;
|
2017-09-10 01:36:47 +00:00
|
|
|
|
2018-01-22 23:11:22 +00:00
|
|
|
throw new AssertionError(obj);
|
2017-06-27 04:00:35 +00:00
|
|
|
}
|
|
|
|
|
2017-12-09 19:15:19 +00:00
|
|
|
function fail(actual, expected, message, operator, stackStartFn) {
|
2017-07-02 20:48:47 +00:00
|
|
|
const argsLen = arguments.length;
|
|
|
|
|
|
|
|
if (argsLen === 0) {
|
2017-06-28 23:57:02 +00:00
|
|
|
message = 'Failed';
|
2017-07-02 20:48:47 +00:00
|
|
|
} else if (argsLen === 1) {
|
2017-04-09 17:36:14 +00:00
|
|
|
message = actual;
|
2017-06-28 23:57:02 +00:00
|
|
|
actual = undefined;
|
2018-01-28 11:07:18 +00:00
|
|
|
} else {
|
|
|
|
if (warned === false) {
|
|
|
|
warned = true;
|
|
|
|
process.emitWarning(
|
|
|
|
'assert.fail() with more than one argument is deprecated. ' +
|
|
|
|
'Please use assert.strictEqual() instead or only pass a message.',
|
|
|
|
'DeprecationWarning',
|
|
|
|
'DEP00XXX'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (argsLen === 2)
|
|
|
|
operator = '!=';
|
2017-06-27 04:00:35 +00:00
|
|
|
}
|
2017-07-02 20:48:47 +00:00
|
|
|
|
2017-12-09 19:15:19 +00:00
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected,
|
|
|
|
message,
|
|
|
|
operator,
|
|
|
|
stackStartFn: stackStartFn || fail
|
|
|
|
});
|
2009-11-28 17:26:59 +00:00
|
|
|
}
|
2017-07-02 20:48:47 +00:00
|
|
|
|
2009-11-30 02:20:37 +00:00
|
|
|
assert.fail = fail;
|
|
|
|
|
2017-05-08 20:10:51 +00:00
|
|
|
// The AssertionError is defined in internal/error.
|
|
|
|
// new assert.AssertionError({ message: message,
|
|
|
|
// actual: actual,
|
|
|
|
// expected: expected });
|
2018-01-22 23:11:22 +00:00
|
|
|
assert.AssertionError = AssertionError;
|
2017-05-08 20:10:51 +00:00
|
|
|
|
2017-12-09 22:20:07 +00:00
|
|
|
function getBuffer(fd, assertLine) {
|
|
|
|
var lines = 0;
|
|
|
|
// Prevent blocking the event loop by limiting the maximum amount of
|
|
|
|
// data that may be read.
|
|
|
|
var maxReads = 64; // bytesPerRead * maxReads = 512 kb
|
|
|
|
var bytesRead = 0;
|
|
|
|
var startBuffer = 0; // Start reading from that char on
|
|
|
|
const bytesPerRead = 8192;
|
|
|
|
const buffers = [];
|
|
|
|
do {
|
|
|
|
const buffer = Buffer.allocUnsafe(bytesPerRead);
|
|
|
|
bytesRead = readSync(fd, buffer, 0, bytesPerRead);
|
|
|
|
for (var i = 0; i < bytesRead; i++) {
|
|
|
|
if (buffer[i] === 10) {
|
|
|
|
lines++;
|
|
|
|
if (lines === assertLine) {
|
|
|
|
startBuffer = i + 1;
|
|
|
|
// Read up to 15 more lines to make sure all code gets matched
|
|
|
|
} else if (lines === assertLine + 16) {
|
|
|
|
buffers.push(buffer.slice(startBuffer, i));
|
|
|
|
return buffers;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lines >= assertLine) {
|
|
|
|
buffers.push(buffer.slice(startBuffer, bytesRead));
|
|
|
|
// Reset the startBuffer in case we need more than one chunk
|
|
|
|
startBuffer = 0;
|
|
|
|
}
|
|
|
|
} while (--maxReads !== 0 && bytesRead !== 0);
|
|
|
|
return buffers;
|
|
|
|
}
|
|
|
|
|
2018-01-23 15:45:28 +00:00
|
|
|
function getErrMessage(call) {
|
|
|
|
const filename = call.getFileName();
|
|
|
|
const line = call.getLineNumber() - 1;
|
|
|
|
const column = call.getColumnNumber() - 1;
|
|
|
|
const identifier = `${filename}${line}${column}`;
|
|
|
|
|
|
|
|
if (errorCache.has(identifier)) {
|
|
|
|
return errorCache.get(identifier);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip Node.js modules!
|
|
|
|
if (filename.endsWith('.js') && nativeModule.exists(filename.slice(0, -3))) {
|
|
|
|
errorCache.set(identifier, undefined);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var fd;
|
|
|
|
try {
|
|
|
|
fd = openSync(filename, 'r', 0o666);
|
|
|
|
const buffers = getBuffer(fd, line);
|
|
|
|
const code = Buffer.concat(buffers).toString('utf8');
|
|
|
|
const nodes = parseExpressionAt(code, column);
|
|
|
|
// Node type should be "CallExpression" and some times
|
|
|
|
// "SequenceExpression".
|
|
|
|
const node = nodes.type === 'CallExpression' ? nodes : nodes.expressions[0];
|
|
|
|
const name = node.callee.name;
|
|
|
|
// Calling `ok` with .apply or .call is uncommon but we use a simple
|
|
|
|
// safeguard nevertheless.
|
|
|
|
if (name !== 'apply' && name !== 'call') {
|
|
|
|
// Only use `assert` and `assert.ok` to reference the "real API" and
|
|
|
|
// not user defined function names.
|
|
|
|
const ok = name === 'ok' ? '.ok' : '';
|
|
|
|
const args = node.arguments;
|
|
|
|
var message = code
|
|
|
|
.slice(args[0].start, args[args.length - 1].end)
|
|
|
|
.replace(escapeSequencesRegExp, escapeFn);
|
|
|
|
message = 'The expression evaluated to a falsy value:' +
|
|
|
|
`${EOL}${EOL} assert${ok}(${message})${EOL}`;
|
|
|
|
}
|
|
|
|
// Make sure to always set the cache! No matter if the message is
|
|
|
|
// undefined or not
|
|
|
|
errorCache.set(identifier, message);
|
|
|
|
|
|
|
|
return message;
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
// Invalidate cache to prevent trying to read this part again.
|
|
|
|
errorCache.set(identifier, undefined);
|
|
|
|
} finally {
|
|
|
|
if (fd !== undefined)
|
|
|
|
closeSync(fd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-09 22:20:07 +00:00
|
|
|
function innerOk(args, fn) {
|
|
|
|
var [value, message] = args;
|
2017-05-08 20:10:51 +00:00
|
|
|
|
2017-12-09 19:15:19 +00:00
|
|
|
if (!value) {
|
2018-01-31 14:43:09 +00:00
|
|
|
let generatedMessage = false;
|
|
|
|
|
2018-01-23 13:38:34 +00:00
|
|
|
if (args.length === 0) {
|
2018-01-31 14:43:09 +00:00
|
|
|
generatedMessage = true;
|
2018-01-23 13:38:34 +00:00
|
|
|
message = 'No value argument passed to `assert.ok()`';
|
|
|
|
} else if (message == null) {
|
2017-12-09 22:20:07 +00:00
|
|
|
// Use the call as error message if possible.
|
|
|
|
// This does not work with e.g. the repl.
|
|
|
|
const err = new Error();
|
|
|
|
// Make sure the limit is set to 1. Otherwise it could fail (<= 0) or it
|
|
|
|
// does to much work.
|
|
|
|
const tmpLimit = Error.stackTraceLimit;
|
|
|
|
Error.stackTraceLimit = 1;
|
|
|
|
Error.captureStackTrace(err, fn);
|
|
|
|
Error.stackTraceLimit = tmpLimit;
|
|
|
|
|
|
|
|
const tmpPrepare = Error.prepareStackTrace;
|
|
|
|
Error.prepareStackTrace = (_, stack) => stack;
|
|
|
|
const call = err.stack[0];
|
|
|
|
Error.prepareStackTrace = tmpPrepare;
|
|
|
|
|
2018-01-23 15:45:28 +00:00
|
|
|
// Make sure it would be "null" in case that is used.
|
|
|
|
message = getErrMessage(call) || message;
|
2018-01-31 14:43:09 +00:00
|
|
|
generatedMessage = true;
|
|
|
|
} else if (message instanceof Error) {
|
|
|
|
throw message;
|
2017-12-09 22:20:07 +00:00
|
|
|
}
|
2018-01-31 14:43:09 +00:00
|
|
|
|
|
|
|
const err = new AssertionError({
|
2017-12-09 19:15:19 +00:00
|
|
|
actual: value,
|
|
|
|
expected: true,
|
|
|
|
message,
|
|
|
|
operator: '==',
|
2017-12-09 22:20:07 +00:00
|
|
|
stackStartFn: fn
|
2017-12-09 19:15:19 +00:00
|
|
|
});
|
2018-01-31 14:43:09 +00:00
|
|
|
err.generatedMessage = generatedMessage;
|
|
|
|
throw err;
|
2017-12-09 19:15:19 +00:00
|
|
|
}
|
2011-10-04 22:08:18 +00:00
|
|
|
}
|
2017-12-09 22:20:07 +00:00
|
|
|
|
|
|
|
// Pure assertion tests whether a value is truthy, as determined
|
|
|
|
// by !!value.
|
|
|
|
function ok(...args) {
|
|
|
|
innerOk(args, ok);
|
|
|
|
}
|
2011-10-01 11:42:42 +00:00
|
|
|
assert.ok = ok;
|
2009-11-28 17:26:59 +00:00
|
|
|
|
2017-06-27 04:00:35 +00:00
|
|
|
// The equality assertion tests shallow, coercive equality with ==.
|
2017-01-08 23:23:34 +00:00
|
|
|
/* eslint-disable no-restricted-properties */
|
2009-11-30 02:20:37 +00:00
|
|
|
assert.equal = function equal(actual, expected, message) {
|
2017-04-16 18:29:35 +00:00
|
|
|
// eslint-disable-next-line eqeqeq
|
2017-12-09 19:15:19 +00:00
|
|
|
if (actual != expected) {
|
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected,
|
|
|
|
message,
|
|
|
|
operator: '==',
|
|
|
|
stackStartFn: equal
|
|
|
|
});
|
|
|
|
}
|
2009-11-28 17:26:59 +00:00
|
|
|
};
|
|
|
|
|
2017-01-02 21:50:04 +00:00
|
|
|
// The non-equality assertion tests for whether two objects are not
|
|
|
|
// equal with !=.
|
2009-11-30 02:20:37 +00:00
|
|
|
assert.notEqual = function notEqual(actual, expected, message) {
|
2017-04-16 18:29:35 +00:00
|
|
|
// eslint-disable-next-line eqeqeq
|
2010-04-11 20:46:24 +00:00
|
|
|
if (actual == expected) {
|
2017-12-09 19:15:19 +00:00
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected,
|
|
|
|
message,
|
|
|
|
operator: '!=',
|
|
|
|
stackStartFn: notEqual
|
|
|
|
});
|
2009-12-29 19:14:58 +00:00
|
|
|
}
|
2009-11-28 17:26:59 +00:00
|
|
|
};
|
|
|
|
|
2017-01-02 21:50:04 +00:00
|
|
|
// The equivalence assertion tests a deep equality relation.
|
2009-12-29 19:14:58 +00:00
|
|
|
assert.deepEqual = function deepEqual(actual, expected, message) {
|
2017-10-06 04:27:46 +00:00
|
|
|
if (!isDeepEqual(actual, expected)) {
|
2017-12-09 19:15:19 +00:00
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected,
|
|
|
|
message,
|
|
|
|
operator: 'deepEqual',
|
|
|
|
stackStartFn: deepEqual
|
|
|
|
});
|
2009-12-29 18:37:40 +00:00
|
|
|
}
|
2009-11-28 17:26:59 +00:00
|
|
|
};
|
2015-01-28 16:48:56 +00:00
|
|
|
|
2017-01-02 21:50:04 +00:00
|
|
|
// The non-equivalence assertion tests for any deep inequality.
|
2009-12-29 19:14:58 +00:00
|
|
|
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
2017-10-06 04:27:46 +00:00
|
|
|
if (isDeepEqual(actual, expected)) {
|
2017-12-09 19:15:19 +00:00
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected,
|
|
|
|
message,
|
|
|
|
operator: 'notDeepEqual',
|
|
|
|
stackStartFn: notDeepEqual
|
|
|
|
});
|
2009-12-29 18:37:40 +00:00
|
|
|
}
|
2009-11-28 17:26:59 +00:00
|
|
|
};
|
2017-10-19 19:39:29 +00:00
|
|
|
/* eslint-enable */
|
|
|
|
|
|
|
|
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
|
|
|
|
if (!isDeepStrictEqual(actual, expected)) {
|
2017-12-09 19:15:19 +00:00
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected,
|
|
|
|
message,
|
|
|
|
operator: 'deepStrictEqual',
|
2017-12-09 21:38:20 +00:00
|
|
|
stackStartFn: deepStrictEqual,
|
|
|
|
errorDiff: this === strict ? ERR_DIFF_EQUAL : ERR_DIFF_DEACTIVATED
|
2017-12-09 19:15:19 +00:00
|
|
|
});
|
2017-10-19 19:39:29 +00:00
|
|
|
}
|
|
|
|
};
|
2009-11-28 17:26:59 +00:00
|
|
|
|
2015-01-28 16:48:56 +00:00
|
|
|
assert.notDeepStrictEqual = notDeepStrictEqual;
|
|
|
|
function notDeepStrictEqual(actual, expected, message) {
|
2017-10-06 04:27:46 +00:00
|
|
|
if (isDeepStrictEqual(actual, expected)) {
|
2017-12-09 19:15:19 +00:00
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected,
|
|
|
|
message,
|
|
|
|
operator: 'notDeepStrictEqual',
|
2017-12-09 21:38:20 +00:00
|
|
|
stackStartFn: notDeepStrictEqual,
|
|
|
|
errorDiff: this === strict ? ERR_DIFF_NOT_EQUAL : ERR_DIFF_DEACTIVATED
|
2017-12-09 19:15:19 +00:00
|
|
|
});
|
2015-01-28 16:48:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-30 02:20:37 +00:00
|
|
|
assert.strictEqual = function strictEqual(actual, expected, message) {
|
2017-11-13 22:34:16 +00:00
|
|
|
if (!Object.is(actual, expected)) {
|
2017-12-09 19:15:19 +00:00
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected,
|
|
|
|
message,
|
|
|
|
operator: 'strictEqual',
|
2017-12-09 21:38:20 +00:00
|
|
|
stackStartFn: strictEqual,
|
|
|
|
errorDiff: this === strict ? ERR_DIFF_EQUAL : ERR_DIFF_DEACTIVATED
|
2017-12-09 19:15:19 +00:00
|
|
|
});
|
2009-12-29 19:14:58 +00:00
|
|
|
}
|
2009-11-28 17:26:59 +00:00
|
|
|
};
|
|
|
|
|
2009-11-30 02:20:37 +00:00
|
|
|
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
2017-11-13 22:34:16 +00:00
|
|
|
if (Object.is(actual, expected)) {
|
2017-12-09 19:15:19 +00:00
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected,
|
|
|
|
message,
|
|
|
|
operator: 'notStrictEqual',
|
2017-12-09 21:38:20 +00:00
|
|
|
stackStartFn: notStrictEqual,
|
|
|
|
errorDiff: this === strict ? ERR_DIFF_NOT_EQUAL : ERR_DIFF_DEACTIVATED
|
2017-12-09 19:15:19 +00:00
|
|
|
});
|
2009-12-29 19:14:58 +00:00
|
|
|
}
|
2009-11-28 17:26:59 +00:00
|
|
|
};
|
|
|
|
|
2017-12-10 00:54:44 +00:00
|
|
|
function createMsg(msg, key, actual, expected) {
|
|
|
|
if (msg)
|
|
|
|
return msg;
|
|
|
|
return `${key}: expected ${inspect(expected[key])}, ` +
|
|
|
|
`not ${inspect(actual[key])}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
function expectedException(actual, expected, msg) {
|
2017-06-28 18:35:16 +00:00
|
|
|
if (typeof expected !== 'function') {
|
2017-12-10 00:54:44 +00:00
|
|
|
if (expected instanceof RegExp)
|
|
|
|
return expected.test(actual);
|
|
|
|
// assert.doesNotThrow does not accept objects.
|
|
|
|
if (arguments.length === 2) {
|
2018-01-22 23:11:22 +00:00
|
|
|
throw new TypeError('ERR_INVALID_ARG_TYPE', 'expected',
|
|
|
|
['Function', 'RegExp'], expected);
|
2017-12-10 00:54:44 +00:00
|
|
|
}
|
|
|
|
// The name and message could be non enumerable. Therefore test them
|
|
|
|
// explicitly.
|
|
|
|
if ('name' in expected) {
|
|
|
|
assert.strictEqual(
|
|
|
|
actual.name,
|
|
|
|
expected.name,
|
|
|
|
createMsg(msg, 'name', actual, expected));
|
|
|
|
}
|
|
|
|
if ('message' in expected) {
|
|
|
|
assert.strictEqual(
|
|
|
|
actual.message,
|
|
|
|
expected.message,
|
|
|
|
createMsg(msg, 'message', actual, expected));
|
|
|
|
}
|
|
|
|
const keys = Object.keys(expected);
|
|
|
|
for (const key of keys) {
|
|
|
|
assert.deepStrictEqual(
|
|
|
|
actual[key],
|
|
|
|
expected[key],
|
|
|
|
createMsg(msg, key, actual, expected));
|
|
|
|
}
|
|
|
|
return true;
|
2010-11-26 23:03:31 +00:00
|
|
|
}
|
2017-06-28 18:35:16 +00:00
|
|
|
// Guard instanceof against arrow functions as they don't have a prototype.
|
|
|
|
if (expected.prototype !== undefined && actual instanceof expected) {
|
|
|
|
return true;
|
2015-10-08 10:25:03 +00:00
|
|
|
}
|
2015-12-06 01:29:28 +00:00
|
|
|
if (Error.isPrototypeOf(expected)) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-10-08 10:25:03 +00:00
|
|
|
return expected.call({}, actual) === true;
|
2010-11-26 23:03:31 +00:00
|
|
|
}
|
|
|
|
|
2017-12-09 23:47:49 +00:00
|
|
|
function getActual(block) {
|
|
|
|
if (typeof block !== 'function') {
|
2018-01-22 23:11:22 +00:00
|
|
|
throw new TypeError('ERR_INVALID_ARG_TYPE', 'block', 'Function',
|
|
|
|
block);
|
2017-12-09 23:47:49 +00:00
|
|
|
}
|
2015-12-20 07:01:34 +00:00
|
|
|
try {
|
|
|
|
block();
|
|
|
|
} catch (e) {
|
2017-06-28 18:35:16 +00:00
|
|
|
return e;
|
2015-12-20 07:01:34 +00:00
|
|
|
}
|
2018-01-07 22:17:29 +00:00
|
|
|
return NO_EXCEPTION_SENTINEL;
|
2015-12-20 07:01:34 +00:00
|
|
|
}
|
|
|
|
|
2017-12-09 23:47:49 +00:00
|
|
|
// Expected to throw an error.
|
|
|
|
assert.throws = function throws(block, error, message) {
|
|
|
|
const actual = getActual(block);
|
2010-11-26 23:03:31 +00:00
|
|
|
|
2017-12-09 23:47:49 +00:00
|
|
|
if (typeof error === 'string') {
|
|
|
|
if (arguments.length === 3)
|
2018-01-22 23:11:22 +00:00
|
|
|
throw new TypeError('ERR_INVALID_ARG_TYPE',
|
|
|
|
'error',
|
|
|
|
['Function', 'RegExp'],
|
|
|
|
error);
|
2015-01-12 16:13:18 +00:00
|
|
|
|
2017-12-09 23:47:49 +00:00
|
|
|
message = error;
|
|
|
|
error = null;
|
2009-12-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
2018-01-07 22:17:29 +00:00
|
|
|
if (actual === NO_EXCEPTION_SENTINEL) {
|
2017-12-09 23:47:49 +00:00
|
|
|
let details = '';
|
|
|
|
if (error && error.name) {
|
|
|
|
details += ` (${error.name})`;
|
2017-06-28 18:35:16 +00:00
|
|
|
}
|
2017-12-09 23:47:49 +00:00
|
|
|
details += message ? `: ${message}` : '.';
|
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected: error,
|
|
|
|
operator: 'throws',
|
|
|
|
message: `Missing expected exception${details}`,
|
|
|
|
stackStartFn: throws
|
|
|
|
});
|
|
|
|
}
|
2017-12-10 00:54:44 +00:00
|
|
|
if (error && expectedException(actual, error, message) === false) {
|
2010-11-26 23:03:31 +00:00
|
|
|
throw actual;
|
2009-12-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
};
|
2009-11-30 02:20:37 +00:00
|
|
|
|
2017-06-27 04:00:35 +00:00
|
|
|
assert.doesNotThrow = function doesNotThrow(block, error, message) {
|
2017-12-09 23:47:49 +00:00
|
|
|
const actual = getActual(block);
|
2018-01-07 22:17:29 +00:00
|
|
|
if (actual === NO_EXCEPTION_SENTINEL)
|
2017-12-09 23:47:49 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (typeof error === 'string') {
|
|
|
|
message = error;
|
|
|
|
error = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!error || expectedException(actual, error)) {
|
|
|
|
const details = message ? `: ${message}` : '.';
|
|
|
|
innerFail({
|
|
|
|
actual,
|
|
|
|
expected: error,
|
|
|
|
operator: 'doesNotThrow',
|
2018-01-07 22:17:29 +00:00
|
|
|
message: `Got unwanted exception${details}\n${actual && actual.message}`,
|
2017-12-09 23:47:49 +00:00
|
|
|
stackStartFn: doesNotThrow
|
|
|
|
});
|
|
|
|
}
|
|
|
|
throw actual;
|
2017-06-27 04:00:35 +00:00
|
|
|
};
|
2009-12-29 19:14:58 +00:00
|
|
|
|
2018-01-19 09:35:39 +00:00
|
|
|
assert.ifError = function ifError(err) {
|
2018-01-23 13:07:18 +00:00
|
|
|
if (err !== null && err !== undefined) {
|
2018-01-19 09:35:39 +00:00
|
|
|
let message = 'ifError got unwanted exception: ';
|
|
|
|
if (typeof err === 'object' && typeof err.message === 'string') {
|
|
|
|
if (err.message.length === 0 && err.constructor) {
|
|
|
|
message += err.constructor.name;
|
|
|
|
} else {
|
|
|
|
message += err.message;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
message += inspect(err);
|
|
|
|
}
|
|
|
|
|
2018-01-22 23:11:22 +00:00
|
|
|
const newErr = new AssertionError({
|
2018-01-19 09:35:39 +00:00
|
|
|
actual: err,
|
|
|
|
expected: null,
|
|
|
|
operator: 'ifError',
|
|
|
|
message,
|
|
|
|
stackStartFn: ifError
|
|
|
|
});
|
|
|
|
|
|
|
|
// Make sure we actually have a stack trace!
|
|
|
|
const origStack = err.stack;
|
|
|
|
|
|
|
|
if (typeof origStack === 'string') {
|
|
|
|
// This will remove any duplicated frames from the error frames taken
|
|
|
|
// from within `ifError` and add the original error frames to the newly
|
|
|
|
// created ones.
|
|
|
|
const tmp2 = origStack.split('\n');
|
|
|
|
tmp2.shift();
|
|
|
|
// Filter all frames existing in err.stack.
|
|
|
|
let tmp1 = newErr.stack.split('\n');
|
|
|
|
for (var i = 0; i < tmp2.length; i++) {
|
|
|
|
// Find the first occurrence of the frame.
|
|
|
|
const pos = tmp1.indexOf(tmp2[i]);
|
|
|
|
if (pos !== -1) {
|
|
|
|
// Only keep new frames.
|
|
|
|
tmp1 = tmp1.slice(0, pos);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
newErr.stack = `${tmp1.join('\n')}\n${tmp2.join('\n')}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw newErr;
|
|
|
|
}
|
|
|
|
};
|
2017-11-13 20:15:24 +00:00
|
|
|
|
|
|
|
// Expose a strict only variant of assert
|
2017-12-09 22:20:07 +00:00
|
|
|
function strict(...args) {
|
|
|
|
innerOk(args, strict);
|
2017-11-13 20:15:24 +00:00
|
|
|
}
|
|
|
|
assert.strict = Object.assign(strict, assert, {
|
|
|
|
equal: assert.strictEqual,
|
|
|
|
deepEqual: assert.deepStrictEqual,
|
|
|
|
notEqual: assert.notStrictEqual,
|
|
|
|
notDeepEqual: assert.notDeepStrictEqual
|
|
|
|
});
|
|
|
|
assert.strict.strict = assert.strict;
|