From baa4b9b4255922f63ea2b0e3ac92005ae273e3dc Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Fri, 28 Dec 2018 14:33:33 +0100 Subject: [PATCH] test: refactor `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. `common.noWarnCode` is completely removed due to just being sugar for `undefined`. This also verifies that the warning order is identical to the order in which they are triggered. PR-URL: https://github.com/nodejs/node/pull/25251 Reviewed-By: Daniel Bevenius Reviewed-By: James M Snell --- test/common/README.md | 52 ++++++++++++--- test/common/index.js | 66 ++++++++----------- test/common/index.mjs | 2 - test/parallel/test-atomics-notify.js | 4 +- test/parallel/test-console.js | 16 ++--- test/parallel/test-crypto-authenticated.js | 38 +++++------ test/parallel/test-crypto-cipher-decipher.js | 2 +- test/parallel/test-dns-lookup.js | 14 ++-- test/parallel/test-fs-filehandle.js | 6 +- test/parallel/test-https-strict.js | 3 +- .../test-process-emit-warning-from-native.js | 2 +- ...est-promises-unhandled-proxy-rejections.js | 2 +- ...st-promises-unhandled-symbol-rejections.js | 8 +-- test/parallel/test-tls-dhe.js | 3 +- test/parallel/test-trace-events-api.js | 3 +- test/parallel/test-warn-sigprof.js | 3 +- ...est-worker-message-port-transfer-target.js | 3 +- 17 files changed, 119 insertions(+), 108 deletions(-) diff --git a/test/common/README.md b/test/common/README.md index 121bb20bb19710..0542c38bbcb419 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -109,14 +109,51 @@ 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) -* `name` [<string>] -* `expected` [<string>] | [<Array>] +### expectWarning(name[, expected[, code]]) +* `name` [<string>] | [<Object>] +* `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. +Tests whether `name`, `expected`, and `code` are part of a raised warning. + +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', 'DEP0XX2'] +]); + +expectWarning('DeprecationWarning', { + DEP0XXX: 'Foobar is deprecated', + DEP0XX2: 'Baz is also deprecated' +}); + +expectWarning({ + DeprecationWarning: { + DEP0XXX: 'Foobar is deprecated', + DEP0XX1: 'Baz is also deprecated' + }, + Warning: [ + ['Multiple array entries are fine', 'SpecialWarningCode'], + ['No code is also fine'] + ], + SingleEntry: ['This will also work', 'WarningCode'], + SingleString: 'Single string entries without code will also work' +}); +``` ### getArrayBufferViews(buf) * `buf` [<Buffer>] @@ -262,9 +299,6 @@ Returns `true` if the exit code `exitCode` and/or signal name `signal` represent the exit code and/or signal name of a node process that aborted, `false` otherwise. -### noWarnCode -See `common.expectWarning()` for usage. - ### opensslCli * [<boolean>] diff --git a/test/common/index.js b/test/common/index.js index 5d9a4b31e36534..ea59009ba565b2 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -497,54 +497,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]); + }); } } @@ -758,7 +747,6 @@ module.exports = { mustCallAtLeast, mustNotCall, nodeProcessAborted, - noWarnCode: undefined, PIPE, platformTimeout, printSkipMessage, diff --git a/test/common/index.mjs b/test/common/index.mjs index 068dd35049c301..de9119f37e2f3d 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -37,7 +37,6 @@ const { nodeProcessAborted, busyLoop, isAlive, - noWarnCode, expectWarning, expectsError, skipIfInspectorDisabled, @@ -84,7 +83,6 @@ export { nodeProcessAborted, busyLoop, isAlive, - noWarnCode, expectWarning, expectsError, skipIfInspectorDisabled, diff --git a/test/parallel/test-atomics-notify.js b/test/parallel/test-atomics-notify.js index fc59d5aa331084..16dd1bb0c7dac1 100644 --- a/test/parallel/test-atomics-notify.js +++ b/test/parallel/test-atomics-notify.js @@ -1,6 +1,6 @@ 'use strict'; -const { expectWarning, noWarnCode } = require('../common'); +const { expectWarning } = require('../common'); const assert = require('assert'); const { runInNewContext } = require('vm'); @@ -14,6 +14,6 @@ assert.strictEqual(runInNewContext('typeof Atomics.notify'), 'function'); expectWarning( 'Atomics', 'Atomics.wake will be removed in a future version, ' + - 'use Atomics.notify instead.', noWarnCode); + 'use Atomics.notify instead.'); Atomics.wake(new Int32Array(new SharedArrayBuffer(4)), 0, 0); diff --git a/test/parallel/test-console.js b/test/parallel/test-console.js index 7448d62208e65f..e94b6020652463 100644 --- a/test/parallel/test-console.js +++ b/test/parallel/test-console.js @@ -42,14 +42,14 @@ if (common.isMainThread) { common.expectWarning( 'Warning', [ - ['Count for \'noLabel\' does not exist', common.noWarnCode], - ['No such label \'noLabel\' for console.timeLog()', common.noWarnCode], - ['No such label \'noLabel\' for console.timeEnd()', common.noWarnCode], - ['Count for \'default\' does not exist', common.noWarnCode], - ['No such label \'default\' for console.timeLog()', common.noWarnCode], - ['No such label \'default\' for console.timeEnd()', common.noWarnCode], - ['Label \'default\' already exists for console.time()', common.noWarnCode], - ['Label \'test\' already exists for console.time()', common.noWarnCode] + ['Count for \'noLabel\' does not exist'], + ['No such label \'noLabel\' for console.timeLog()'], + ['No such label \'noLabel\' for console.timeEnd()'], + ['Count for \'default\' does not exist'], + ['No such label \'default\' for console.timeLog()'], + ['No such label \'default\' for console.timeEnd()'], + ['Label \'default\' already exists for console.time()'], + ['Label \'test\' already exists for console.time()'] ] ); diff --git a/test/parallel/test-crypto-authenticated.js b/test/parallel/test-crypto-authenticated.js index 4f382eae6e849e..414404511f9064 100644 --- a/test/parallel/test-crypto-authenticated.js +++ b/test/parallel/test-crypto-authenticated.js @@ -50,25 +50,25 @@ const ciphers = crypto.getCiphers(); const expectedWarnings = common.hasFipsCrypto ? [] : [ - ['Use Cipheriv for counter mode of aes-192-gcm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-192-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-192-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-128-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-128-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-128-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode], - ['Use Cipheriv for counter mode of aes-256-ccm', common.noWarnCode] + ['Use Cipheriv for counter mode of aes-192-gcm'], + ['Use Cipheriv for counter mode of aes-192-ccm'], + ['Use Cipheriv for counter mode of aes-192-ccm'], + ['Use Cipheriv for counter mode of aes-128-ccm'], + ['Use Cipheriv for counter mode of aes-128-ccm'], + ['Use Cipheriv for counter mode of aes-128-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'], + ['Use Cipheriv for counter mode of aes-256-ccm'] ]; const expectedDeprecationWarnings = [ diff --git a/test/parallel/test-crypto-cipher-decipher.js b/test/parallel/test-crypto-cipher-decipher.js index 12fa98f3b27228..dfa01e2422c23b 100644 --- a/test/parallel/test-crypto-cipher-decipher.js +++ b/test/parallel/test-crypto-cipher-decipher.js @@ -12,7 +12,7 @@ const assert = require('assert'); common.expectWarning({ Warning: [ - ['Use Cipheriv for counter mode of aes-256-gcm', common.noWarnCode] + ['Use Cipheriv for counter mode of aes-256-gcm'] ], DeprecationWarning: [ ['crypto.createCipher is deprecated.', 'DEP0106'] diff --git a/test/parallel/test-dns-lookup.js b/test/parallel/test-dns-lookup.js index 3da4e9f58db95c..951e7e17a98b82 100644 --- a/test/parallel/test-dns-lookup.js +++ b/test/parallel/test-dns-lookup.js @@ -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(() => { diff --git a/test/parallel/test-fs-filehandle.js b/test/parallel/test-fs-filehandle.js index a56b39f7c92526..30f42a60f044b3 100644 --- a/test/parallel/test-fs-filehandle.js +++ b/test/parallel/test-fs-filehandle.js @@ -21,12 +21,10 @@ let fdnum; common.expectWarning({ 'internal/test/binding': [ - 'These APIs are for internal testing only. Do not use them.', - common.noWarnCode + 'These APIs are for internal testing only. Do not use them.' ], 'Warning': [ - `Closing file descriptor ${fdnum} on garbage collection`, - common.noWarnCode + `Closing file descriptor ${fdnum} on garbage collection` ] }); diff --git a/test/parallel/test-https-strict.js b/test/parallel/test-https-strict.js index 6c1d6325eac176..a7f4b80716c917 100644 --- a/test/parallel/test-https-strict.js +++ b/test/parallel/test-https-strict.js @@ -32,8 +32,7 @@ common.expectWarning( 'Warning', 'Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to \'0\' ' + 'makes TLS connections and HTTPS requests insecure by disabling ' + - 'certificate verification.', - common.noWarnCode + 'certificate verification.' ); const assert = require('assert'); diff --git a/test/parallel/test-process-emit-warning-from-native.js b/test/parallel/test-process-emit-warning-from-native.js index 530b7a24047b92..ee7e731935dc9d 100644 --- a/test/parallel/test-process-emit-warning-from-native.js +++ b/test/parallel/test-process-emit-warning-from-native.js @@ -16,7 +16,7 @@ const key = '0123456789'; ['crypto.createCipher is deprecated.', 'DEP0106'] ], Warning: [ - ['Use Cipheriv for counter mode of aes-256-gcm', common.noWarnCode] + ['Use Cipheriv for counter mode of aes-256-gcm'] ] }); diff --git a/test/parallel/test-promises-unhandled-proxy-rejections.js b/test/parallel/test-promises-unhandled-proxy-rejections.js index 83062e9520165b..b3cf5719cb9ab0 100644 --- a/test/parallel/test-promises-unhandled-proxy-rejections.js +++ b/test/parallel/test-promises-unhandled-proxy-rejections.js @@ -12,7 +12,7 @@ const expectedPromiseWarning = ['Unhandled promise rejection. ' + 'This error originated either by throwing ' + 'inside of an async function without a catch ' + 'block, or by rejecting a promise which was ' + - 'not handled with .catch(). (rejection id: 1)', common.noWarnCode]; + 'not handled with .catch(). (rejection id: 1)']; function throwErr() { throw new Error('Error from proxy'); diff --git a/test/parallel/test-promises-unhandled-symbol-rejections.js b/test/parallel/test-promises-unhandled-symbol-rejections.js index 2102de81918bd7..d777a13e62e984 100644 --- a/test/parallel/test-promises-unhandled-symbol-rejections.js +++ b/test/parallel/test-promises-unhandled-symbol-rejections.js @@ -3,7 +3,7 @@ const common = require('../common'); common.disableCrashOnUnhandledRejection(); -const expectedValueWarning = ['Symbol()', common.noWarnCode]; +const expectedValueWarning = ['Symbol()']; const expectedDeprecationWarning = ['Unhandled promise rejections are ' + 'deprecated. In the future, promise ' + 'rejections that are not handled will ' + @@ -13,13 +13,13 @@ const expectedPromiseWarning = ['Unhandled promise rejection. ' + 'This error originated either by throwing ' + 'inside of an async function without a catch ' + 'block, or by rejecting a promise which was ' + - 'not handled with .catch(). (rejection id: 1)', common.noWarnCode]; + 'not handled with .catch(). (rejection id: 1)']; common.expectWarning({ DeprecationWarning: expectedDeprecationWarning, UnhandledPromiseRejectionWarning: [ - expectedPromiseWarning, - expectedValueWarning + expectedValueWarning, + expectedPromiseWarning ], }); diff --git a/test/parallel/test-tls-dhe.js b/test/parallel/test-tls-dhe.js index 86130aff262ab5..868686335077a5 100644 --- a/test/parallel/test-tls-dhe.js +++ b/test/parallel/test-tls-dhe.js @@ -41,8 +41,7 @@ const ciphers = 'DHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; // Test will emit a warning because the DH parameter size is < 2048 bits common.expectWarning('SecurityWarning', - 'DH parameter is less than 2048 bits', - common.noWarnCode); + 'DH parameter is less than 2048 bits'); function loadDHParam(n) { const params = [`dh${n}.pem`]; diff --git a/test/parallel/test-trace-events-api.js b/test/parallel/test-trace-events-api.js index 2810ac0dd0f6d7..346f943b9c36c5 100644 --- a/test/parallel/test-trace-events-api.js +++ b/test/parallel/test-trace-events-api.js @@ -99,8 +99,7 @@ if (isChild) { common.expectWarning( 'Warning', 'Possible trace_events memory leak detected. There are more than ' + - '10 enabled Tracing objects.', - common.noWarnCode); + '10 enabled Tracing objects.'); for (let n = 0; n < 10; n++) { const tracing = createTracing({ categories: [ `a${n}` ] }); tracing.enable(); diff --git a/test/parallel/test-warn-sigprof.js b/test/parallel/test-warn-sigprof.js index c3986a27be1703..36b0db78d82687 100644 --- a/test/parallel/test-warn-sigprof.js +++ b/test/parallel/test-warn-sigprof.js @@ -13,7 +13,6 @@ if (common.isWindows) common.skipIfWorker(); // Worker inspector never has a server running common.expectWarning('Warning', - 'process.on(SIGPROF) is reserved while debugging', - common.noWarnCode); + 'process.on(SIGPROF) is reserved while debugging'); process.on('SIGPROF', () => {}); diff --git a/test/parallel/test-worker-message-port-transfer-target.js b/test/parallel/test-worker-message-port-transfer-target.js index 0b1d537bd38c58..638591023fb3b1 100644 --- a/test/parallel/test-worker-message-port-transfer-target.js +++ b/test/parallel/test-worker-message-port-transfer-target.js @@ -10,8 +10,7 @@ const arrayBuf = new ArrayBuffer(10); common.expectWarning('Warning', 'The target port was posted to itself, and the ' + - 'communication channel was lost', - common.noWarnCode); + 'communication channel was lost'); port2.onmessage = common.mustNotCall(); port2.postMessage(null, [port1, arrayBuf]);