tools: prohibit assert.doesNotReject() in Node.js core

This makes sure we do not use `assert.doesNotReject()` anywhere in
our code base. This is just a simple wrapper that catches the
rejection and then rejects it again in case of an error. Thus, it is
not useful to do that.

The error message for `assert.doesNotThrow()` is also improved.

PR-URL: https://github.com/nodejs/node/pull/27402
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Beth Griggs <Bethany.Griggs@uk.ibm.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Ruben Bridgewater 2019-04-25 00:46:40 +02:00
parent 38f3526f27
commit 31b3dd2842
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
4 changed files with 43 additions and 38 deletions

View File

@ -184,7 +184,11 @@ module.exports = {
}, },
{ {
selector: "CallExpression[callee.property.name='doesNotThrow']", selector: "CallExpression[callee.property.name='doesNotThrow']",
message: 'Please replace `assert.doesNotThrow()` and add a comment next to the code instead.', message: 'Do not use `assert.doesNotThrow()`. Write the code without the wrapper and add a comment instead.',
},
{
selector: "CallExpression[callee.property.name='doesNotReject']",
message: 'Do not use `assert.doesNotReject()`. Write the code without the wrapper and add a comment instead.',
}, },
{ {
selector: "CallExpression[callee.property.name='rejects'][arguments.length<2]", selector: "CallExpression[callee.property.name='rejects'][arguments.length<2]",

View File

@ -454,6 +454,7 @@ function. See [`assert.throws()`][] for more details.
Besides the async nature to await the completion behaves identically to Besides the async nature to await the completion behaves identically to
[`assert.doesNotThrow()`][]. [`assert.doesNotThrow()`][].
<!-- eslint-disable no-restricted-syntax -->
```js ```js
(async () => { (async () => {
await assert.doesNotReject( await assert.doesNotReject(
@ -465,6 +466,7 @@ Besides the async nature to await the completion behaves identically to
})(); })();
``` ```
<!-- eslint-disable no-restricted-syntax -->
```js ```js
assert.doesNotReject(Promise.reject(new TypeError('Wrong value'))) assert.doesNotReject(Promise.reject(new TypeError('Wrong value')))
.then(() => { .then(() => {

View File

@ -114,11 +114,36 @@ promises.push(assert.rejects(
} }
)); ));
{
const handler = (generated, actual, err) => {
assert.strictEqual(err.generatedMessage, generated);
assert.strictEqual(err.code, 'ERR_ASSERTION');
assert.strictEqual(err.actual, actual);
assert.strictEqual(err.operator, 'rejects');
assert(/rejects/.test(err.stack));
return true;
};
const err = new Error();
promises.push(assert.rejects(
assert.rejects(Promise.reject(null), { code: 'FOO' }),
handler.bind(null, true, null)
));
promises.push(assert.rejects(
assert.rejects(Promise.reject(5), { code: 'FOO' }, 'AAAAA'),
handler.bind(null, false, 5)
));
promises.push(assert.rejects(
assert.rejects(Promise.reject(err), { code: 'FOO' }, 'AAAAA'),
handler.bind(null, false, err)
));
}
// Check `assert.doesNotReject`. // Check `assert.doesNotReject`.
{ {
// `assert.doesNotReject` accepts a function or a promise // `assert.doesNotReject` accepts a function or a promise
// or a thenable as first argument. // or a thenable as first argument.
const promise = assert.doesNotReject(() => new Map(), common.mustNotCall()); /* eslint-disable no-restricted-syntax */
let promise = assert.doesNotReject(() => new Map(), common.mustNotCall());
promises.push(assert.rejects(promise, { promises.push(assert.rejects(promise, {
message: 'Expected instance of Promise to be returned ' + message: 'Expected instance of Promise to be returned ' +
'from the "promiseFn" function but got instance of Map.', 'from the "promiseFn" function but got instance of Map.',
@ -149,9 +174,7 @@ promises.push(assert.rejects(
code: 'ERR_INVALID_RETURN_VALUE' code: 'ERR_INVALID_RETURN_VALUE'
}) })
); );
}
{
const handler1 = (err) => { const handler1 = (err) => {
assert(err instanceof assert.AssertionError, assert(err instanceof assert.AssertionError,
`${err.name} is not instance of AssertionError`); `${err.name} is not instance of AssertionError`);
@ -173,7 +196,7 @@ promises.push(assert.rejects(
const rejectingFn = async () => assert.fail(); const rejectingFn = async () => assert.fail();
let promise = assert.doesNotReject(rejectingFn, common.mustCall(handler1)); promise = assert.doesNotReject(rejectingFn, common.mustCall(handler1));
promises.push(assert.rejects(promise, common.mustCall(handler2))); promises.push(assert.rejects(promise, common.mustCall(handler2)));
promise = assert.doesNotReject(rejectingFn(), common.mustCall(handler1)); promise = assert.doesNotReject(rejectingFn(), common.mustCall(handler1));
@ -181,39 +204,16 @@ promises.push(assert.rejects(
promise = assert.doesNotReject(() => assert.fail(), common.mustNotCall()); promise = assert.doesNotReject(() => assert.fail(), common.mustNotCall());
promises.push(assert.rejects(promise, common.mustCall(handler1))); promises.push(assert.rejects(promise, common.mustCall(handler1)));
}
promises.push(assert.rejects(
assert.doesNotReject(123),
{
code: 'ERR_INVALID_ARG_TYPE',
message: 'The "promiseFn" argument must be one of type ' +
'Function or Promise. Received type number'
}
));
{
const handler = (generated, actual, err) => {
assert.strictEqual(err.generatedMessage, generated);
assert.strictEqual(err.code, 'ERR_ASSERTION');
assert.strictEqual(err.actual, actual);
assert.strictEqual(err.operator, 'rejects');
assert(/rejects/.test(err.stack));
return true;
};
const err = new Error();
promises.push(assert.rejects( promises.push(assert.rejects(
assert.rejects(Promise.reject(null), { code: 'FOO' }), assert.doesNotReject(123),
handler.bind(null, true, null) {
)); code: 'ERR_INVALID_ARG_TYPE',
promises.push(assert.rejects( message: 'The "promiseFn" argument must be one of type ' +
assert.rejects(Promise.reject(5), { code: 'FOO' }, 'AAAAA'), 'Function or Promise. Received type number'
handler.bind(null, false, 5) }
));
promises.push(assert.rejects(
assert.rejects(Promise.reject(err), { code: 'FOO' }, 'AAAAA'),
handler.bind(null, false, err)
)); ));
/* eslint-enable no-restricted-syntax */
} }
// Make sure all async code gets properly executed. // Make sure all async code gets properly executed.

View File

@ -72,13 +72,12 @@ fs.readdir(readdirDir, {
assertDirents(dirents); assertDirents(dirents);
})); }));
// Check the promisified version (async () => {
assert.doesNotReject(async () => {
const dirents = await fs.promises.readdir(readdirDir, { const dirents = await fs.promises.readdir(readdirDir, {
withFileTypes: true withFileTypes: true
}); });
assertDirents(dirents); assertDirents(dirents);
}); })();
// Check for correct types when the binding returns unknowns // Check for correct types when the binding returns unknowns
const UNKNOWN = constants.UV_DIRENT_UNKNOWN; const UNKNOWN = constants.UV_DIRENT_UNKNOWN;