From 11d44c63d0391b157b520cc7a2d19ca08beb894b Mon Sep 17 00:00:00 2001 From: Lance Ball Date: Wed, 22 Nov 2017 13:49:50 -0500 Subject: [PATCH] test: make common.mustNotCall show file:linenumber MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a test fails via `common.mustNotCall` it is sometimes hard to determine exactly what was called. This modification stores the caller's file and line number by using the V8 Error API to capture a stack at the time `common.mustNotCall()` is called. In the event of failure, this information is printed. This change also exposes a new function in test/common, `getCallSite()` which accepts a `function` and returns a `String` with the file name and line number for the function. PR-URL: https://github.com/nodejs/node/pull/17257 Reviewed-By: James M Snell Reviewed-By: Michaël Zasso Reviewed-By: Gibson Fahnestock Reviewed-By: Tobias Nießen Reviewed-By: Joyee Cheung Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Khaidi Chu --- test/common/README.md | 6 +++++ test/common/index.js | 16 ++++++++++++- test/parallel/test-common-must-not-call.js | 26 ++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-common-must-not-call.js diff --git a/test/common/README.md b/test/common/README.md index b6cc52b6651924..5e69db69a4673c 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -135,6 +135,12 @@ Path to the 'fixtures' directory. Returns an instance of all possible `ArrayBufferView`s of the provided Buffer. +### getCallSite(func) +* `func` [<Function>] +* return [<String>] + +Returns the file name and line number for the provided Function. + ### globalCheck * return [<Boolean>] diff --git a/test/common/index.js b/test/common/index.js index 9798b0fdab8dad..899f5e0acdee21 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -579,9 +579,23 @@ exports.canCreateSymLink = function() { return true; }; +exports.getCallSite = function getCallSite(top) { + const originalStackFormatter = Error.prepareStackTrace; + Error.prepareStackTrace = (err, stack) => + `${stack[0].getFileName()}:${stack[0].getLineNumber()}`; + const err = new Error(); + Error.captureStackTrace(err, top); + // with the V8 Error API, the stack is not formatted until it is accessed + err.stack; + Error.prepareStackTrace = originalStackFormatter; + return err.stack; +}; + exports.mustNotCall = function(msg) { + const callSite = exports.getCallSite(exports.mustNotCall); return function mustNotCall() { - assert.fail(msg || 'function should not have been called'); + assert.fail( + `${msg || 'function should not have been called'} at ${callSite}`); }; }; diff --git a/test/parallel/test-common-must-not-call.js b/test/parallel/test-common-must-not-call.js new file mode 100644 index 00000000000000..d70daabf0a4bd0 --- /dev/null +++ b/test/parallel/test-common-must-not-call.js @@ -0,0 +1,26 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); + +const message = 'message'; +const testFunction = common.mustNotCall(message); + +const validateError = common.mustCall((e) => { + const prefix = `${message} at `; + assert.ok(e.message.startsWith(prefix)); + if (process.platform === 'win32') { + e.message = e.message.substring(2); // remove 'C:' + } + const [ fileName, lineNumber ] = e.message + .substring(prefix.length).split(':'); + assert.strictEqual(path.basename(fileName), 'test-common-must-not-call.js'); + assert.strictEqual(lineNumber, '8'); +}); + +try { + testFunction(); +} catch (e) { + validateError(e); +}