Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
test: rework common.expectWarning()
The current API is somewhat confusing at times and simpler usage is
possible. This overloads the arguments further to accept objects
with deprecation codes as property keys. It also adds documentation
for the different possible styles.

Besides that it is now going to validate for the code being present
in case of deprecations but not for other cases. The former validation
was not consistent as it only validated some cases and accepted
undefined instead of `common.NoWarnCode`. This check is removed due to
the lack of consistency.

This also verifies that the warning order is identical to the order
in which they are triggered.
  • Loading branch information
BridgeAR committed Dec 28, 2018
commit 3d579f6bf7769f77969f66f6ff621ed82d468f9e
44 changes: 42 additions & 2 deletions test/common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,55 @@ Indicates if there is more than 1gb of total memory.
returned function has not been called exactly `exact` number of times when the
test is complete, then the test will fail.

### expectWarning(name, expected, code)
### expectWarning(name, expected[, code])
* `name` [<string>]
* `expected` [<string>] | [<Array>]
* `expected` [<string>] | [<Array>] | [<Object>]
* `code` [<string>]

Tests whether `name`, `expected`, and `code` are part of a raised warning. If
an expected warning does not have a code then `common.noWarnCode` can be used
to indicate this.

The code is required in case the name is set to `'DeprecationWarning'`.

Examples:

```js
const { expectWarning } = require('../common');

expectWarning('Warning', 'Foobar is really bad');

expectWarning('DeprecationWarning', 'Foobar is deprecated', 'DEP0XXX');

expectWarning('DeprecationWarning', [
'Foobar is deprecated', 'DEP0XXX'
]);

expectWarning('DeprecationWarning', [
['Foobar is deprecated', 'DEP0XXX'],
['Baz is also deprecated', noWarnCode]
]);

expectWarning('DeprecationWarning', {
DEP0XXX: 'Foobar is deprecated',
DEP0XX2: 'Baz is also deprecated'
});

expectWarning({
Comment thread
BridgeAR marked this conversation as resolved.
DeprecationWarning: {
DEP0XXX: 'Foobar is deprecated',
DEP0XX1: 'Baz is also deprecated'
},
Warning: [
['Foobar', noWarnCode],
['Multiple array entries are fine', 'DEP0XXX'],
['No code is also fine']
],
SingleEntry: ['This will also work', 'DEP0XXX'],
SingleString: 'Single string entries without code will also work'
});
```

### getArrayBufferViews(buf)
* `buf` [<Buffer>]
* return [<ArrayBufferView[]>]
Expand Down
65 changes: 27 additions & 38 deletions test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -498,54 +498,43 @@ function isAlive(pid) {
}
}

function _expectWarning(name, expected) {
const map = new Map(expected);
function _expectWarning(name, expected, code) {
if (typeof expected === 'string') {
expected = [[expected, code]];
} else if (!Array.isArray(expected)) {
expected = Object.entries(expected).map(([a, b]) => [b, a]);
} else if (!(Array.isArray(expected[0]))) {
expected = [[expected[0], expected[1]]];
}
// Deprecation codes are mandatory, everything else is not.
if (name === 'DeprecationWarning') {
expected.forEach(([_, code]) => assert(code, expected));
}
return mustCall((warning) => {
const [ message, code ] = expected.shift();
assert.strictEqual(warning.name, name);
assert.ok(map.has(warning.message),
`unexpected error message: "${warning.message}"`);
const code = map.get(warning.message);
assert.strictEqual(warning.message, message);
assert.strictEqual(warning.code, code);
// Remove a warning message after it is seen so that we guarantee that we
// get each message only once.
map.delete(expected);
}, expected.length);
}

function expectWarningByName(name, expected, code) {
if (typeof expected === 'string') {
expected = [[expected, code]];
}
process.on('warning', _expectWarning(name, expected));
}
let catchWarning;

function expectWarningByMap(warningMap) {
const catchWarning = {};
Object.keys(warningMap).forEach((name) => {
let expected = warningMap[name];
if (!Array.isArray(expected)) {
throw new Error('warningMap entries must be arrays consisting of two ' +
'entries: [message, warningCode]');
}
if (!(Array.isArray(expected[0]))) {
if (expected.length === 0) {
return;
}
expected = [[expected[0], expected[1]]];
}
catchWarning[name] = _expectWarning(name, expected);
});
process.on('warning', (warning) => catchWarning[warning.name](warning));
}

// Accepts a warning name and description or array of descriptions or a map
// of warning names to description(s)
// ensures a warning is generated for each name/description pair
// Accepts a warning name and description or array of descriptions or a map of
// warning names to description(s) ensures a warning is generated for each
// name/description pair.
// The expected messages have to be unique per `expectWarning()` call.
function expectWarning(nameOrMap, expected, code) {
if (catchWarning === undefined) {
catchWarning = {};
process.on('warning', (warning) => catchWarning[warning.name](warning));
}
if (typeof nameOrMap === 'string') {
expectWarningByName(nameOrMap, expected, code);
catchWarning[nameOrMap] = _expectWarning(nameOrMap, expected, code);
} else {
expectWarningByMap(nameOrMap);
Object.keys(nameOrMap).forEach((name) => {
catchWarning[name] = _expectWarning(name, nameOrMap[name]);
});
}
}

Expand Down
14 changes: 6 additions & 8 deletions test/parallel/test-dns-lookup.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,19 @@ cares.getaddrinfo = () => internalBinding('uv').UV_ENOENT;
common.expectsError(() => dnsPromises.lookup(1, {}), err);
}

// This also verifies different expectWarning notations.
common.expectWarning({
// For 'internal/test/binding' module.
'internal/test/binding': [
'These APIs are for internal testing only. Do not use them.'
],
// For dns.promises.
'ExperimentalWarning': [
'The dns.promises API is experimental'
],
'ExperimentalWarning': 'The dns.promises API is experimental',
// For calling `dns.lookup` with falsy `hostname`.
'DeprecationWarning': [
'The provided hostname "false" is not a valid ' +
'hostname, and is supported in the dns module solely for compatibility.',
'DEP0118',
],
'DeprecationWarning': {
DEP0118: 'The provided hostname "false" is not a valid ' +
'hostname, and is supported in the dns module solely for compatibility.'
}
});

common.expectsError(() => {
Expand Down
4 changes: 2 additions & 2 deletions test/parallel/test-promises-unhandled-symbol-rejections.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ const expectedPromiseWarning = ['Unhandled promise rejection. ' +
common.expectWarning({
DeprecationWarning: expectedDeprecationWarning,
UnhandledPromiseRejectionWarning: [
expectedPromiseWarning,
expectedValueWarning
expectedValueWarning,
expectedPromiseWarning
],
});

Expand Down