| Index: chrome/test/data/webui/test_api.js
|
| diff --git a/chrome/test/data/webui/test_api.js b/chrome/test/data/webui/test_api.js
|
| index dc3a8a0e3abc2652e6926f8682eac1da47fe3934..71d17242dcf3618b37d82f1823ac179fe7e01410 100644
|
| --- a/chrome/test/data/webui/test_api.js
|
| +++ b/chrome/test/data/webui/test_api.js
|
| @@ -74,7 +74,7 @@ var currentTestCase = null;
|
|
|
| /**
|
| * When set to a function, will be called in the context of the test
|
| - * generation inside the function, and before any generated C++.
|
| + * generation inside the function, and after any generated C++.
|
| * @type {function(string,string)}
|
| **/
|
| testGenPostamble: null,
|
| @@ -146,7 +146,12 @@ var currentTestCase = null;
|
| },
|
|
|
| /**
|
| - * Runs this test case.
|
| + * Runs this test case with |this| set to the |fixture|.
|
| + *
|
| + * Note: Tests created with TEST_F may depend upon |this| being set to an
|
| + * instance of this.fixture. The current implementation of TEST creates a
|
| + * dummy constructor, but tests created with TEST should not rely on |this|
|
| + * being set.
|
| * @type {Function}
|
| **/
|
| Run: function() {
|
| @@ -217,6 +222,136 @@ var currentTestCase = null;
|
| oldChrome.send.apply(oldChrome, args);
|
| }
|
|
|
| + /**
|
| + * Provides a mechanism for assert* and expect* methods to fetch the signature
|
| + * of their caller. Assert* methods should |registerCall| and expect* methods
|
| + * should set |isExpect| and |expectName| properties to indicate that the
|
| + * interesting caller is one more level up the stack.
|
| + **/
|
| + function CallHelper() {
|
| + this.__proto__ = CallHelper.prototype;
|
| + }
|
| +
|
| + CallHelper.prototype = {
|
| + /**
|
| + * Holds the mapping of (callerCallerString, callerName) -> count of times
|
| + * called.
|
| + * @type {Object.<string, Object.<string, number>>}
|
| + **/
|
| + 'counts_': {},
|
| +
|
| + /**
|
| + * This information about the caller is needed from most of the following
|
| + * routines.
|
| + * @param {Function} caller the caller of the assert* routine.
|
| + * @return {{callerName: string, callercallerString: string}} stackInfo
|
| + **/
|
| + 'getCallerInfo': function(caller) {
|
| + var callerName = caller.name;
|
| + var callerCaller = caller.caller;
|
| + if (callerCaller['isExpect']) {
|
| + callerName = callerCaller.expectName;
|
| + callerCaller = callerCaller.caller;
|
| + }
|
| + var callerCallerString = callerCaller.toString();
|
| + return {
|
| + callerName: callerName,
|
| + callerCallerString: callerCallerString,
|
| + };
|
| + },
|
| +
|
| + /**
|
| + * Register a call to an assertion class.
|
| + **/
|
| + 'registerCall': function() {
|
| + var stackInfo = this.getCallerInfo(arguments.callee.caller);
|
| + if (!(stackInfo.callerCallerString in this.counts_))
|
| + this.counts_[stackInfo.callerCallerString] = {};
|
| + if (!(stackInfo.callerName in this.counts_[stackInfo.callerCallerString]))
|
| + this.counts_[stackInfo.callerCallerString][stackInfo.callerName] = 0;
|
| + ++this.counts_[stackInfo.callerCallerString][stackInfo.callerName];
|
| + },
|
| +
|
| + /**
|
| + * @param {String} string the string to match parentheses.
|
| + * @param {number} index offset to the opening parenthesis.
|
| + * @return {[number, Array]} the index after matching paren and the args.
|
| + **/
|
| + 'matchedParamsIndex': function(string, index) {
|
| + var args = [];
|
| + var parenCount = 1;
|
| + var argStart = index + 1;
|
| + for(index = argStart;
|
| + parenCount && index < string.length;
|
| + ++index) {
|
| + if (string[index] == '(') {
|
| + ++parenCount;
|
| + } else if (string[index] == ')') {
|
| + if (--parenCount == 0)
|
| + args.push(string.substring(argStart, index));
|
| + } else if (string[index] == ',' && parenCount == 1) {
|
| + args.push(string.substring(argStart, index));
|
| + argStart = index + 1;
|
| + }
|
| + }
|
| + return [index, args];
|
| + },
|
| +
|
| + /**
|
| + * Get the parameters of this instance of caller's call to this function.
|
| + * @param {Function} caller_ a particular caller or |undefined|.
|
| + * @param {number} count_ the number of times this instance was called.
|
| + * @return {Array.<string>} parameters of caller's call to this function.
|
| + **/
|
| + 'getParams': function(caller_, count_) {
|
| + var caller = (caller_ == undefined) ?
|
| + arguments.callee.caller : caller_;
|
| + var stackInfo = this.getCallerInfo(caller);
|
| + var count = (count_ == undefined) ?
|
| + this.counts_[stackInfo.callerCallerString][stackInfo.callerName] :
|
| + count_;
|
| + var searchStart = 0;
|
| + var args;
|
| + for(var i = 0;
|
| + i < count && searchStart < stackInfo.callerCallerString.length;
|
| + ++i) {
|
| + searchStart = stackInfo.callerCallerString.indexOf(
|
| + stackInfo.callerName, searchStart);
|
| + if (searchStart == -1) {
|
| + if (i && count_ == undefined) {
|
| + return this.getParams(caller, ((count - 1) % i) + 1);
|
| + } else {
|
| + console.error('bad count ' + count);
|
| + return undefined;
|
| + }
|
| + }
|
| + searchStart += stackInfo.callerName.length;
|
| + var matched = this.matchedParamsIndex(stackInfo.callerCallerString,
|
| + searchStart);
|
| + args = matched[1];
|
| + searchStart = matched[0];
|
| + }
|
| + return args;
|
| + },
|
| +
|
| + /**
|
| + * Get the call signature of this instance of the caller's call to this
|
| + * function.
|
| + * @return {String} call signature.
|
| + **/
|
| + 'getCall': function() {
|
| + var caller = arguments.callee.caller;
|
| + var stackInfo = this.getCallerInfo(caller);
|
| + return stackInfo.callerName + '(' + this.getParams(caller) + ')';
|
| + },
|
| + };
|
| +
|
| + /**
|
| + * Help register calls for better error reporting.
|
| + * @type {CallHelper}
|
| + **/
|
| + var helper = new CallHelper();
|
| +
|
| // Asserts.
|
| // Use the following assertions to verify a condition within a test.
|
| // If assertion fails, the C++ backend will be immediately notified.
|
| @@ -230,13 +365,9 @@ var currentTestCase = null;
|
| * @throws {Error} upon failure.
|
| **/
|
| function assertBool(test, expected, message) {
|
| - if (test !== expected) {
|
| - if (message)
|
| - message = test + '\n' + message;
|
| - else
|
| - message = test;
|
| - throw new Error(message);
|
| - }
|
| + helper.registerCall();
|
| + if (test !== expected)
|
| + throw new Error('Test Error ' + helper.getCall() + ': ' + test);
|
| }
|
|
|
| /**
|
| @@ -246,7 +377,9 @@ var currentTestCase = null;
|
| * @throws {Error} upon failure.
|
| **/
|
| function assertTrue(test, message) {
|
| - assertBool(test, true, message);
|
| + helper.registerCall();
|
| + if (test !== true)
|
| + throw new Error('Test Error ' + helper.getCall() + ': ' + test);
|
| }
|
|
|
| /**
|
| @@ -256,7 +389,9 @@ var currentTestCase = null;
|
| * @throws {Error} upon failure.
|
| **/
|
| function assertFalse(test, message) {
|
| - assertBool(test, false, message);
|
| + helper.registerCall();
|
| + if (test !== false)
|
| + throw new Error('Test Error ' + helper.getCall() + ': ' + test);
|
| }
|
|
|
| /**
|
| @@ -267,14 +402,15 @@ var currentTestCase = null;
|
| * @throws {Error} upon failure.
|
| **/
|
| function assertEquals(expected, actual, message) {
|
| + helper.registerCall();
|
| if (expected != actual) {
|
| - throw new Error('Test Error. Actual: ' + actual + '\nExpected: ' +
|
| - expected + '\n' + message);
|
| + throw new Error('Test Error ' + helper.getCall() + '\nActual: ' + actual +
|
| + '\nExpected: ' + expected);
|
| }
|
| if (typeof expected != typeof actual) {
|
| - throw new Error('Test Error' +
|
| - ' (type mismatch)\nActual Type: ' + typeof actual +
|
| - '\nExpected Type:' + typeof expected + '\n' + message);
|
| + throw new Error('Test Error (type mismatch) ' + helper.getCall() +
|
| + '\nActual Type: ' + typeof actual +
|
| + '\nExpected Type:' + typeof expected);
|
| }
|
| }
|
|
|
| @@ -284,7 +420,8 @@ var currentTestCase = null;
|
| * @throws {Error} always.
|
| **/
|
| function assertNotReached(message) {
|
| - throw new Error(message);
|
| + helper.registerCall();
|
| + throw new Error(helper.getCall());
|
| }
|
|
|
| /**
|
| @@ -304,13 +441,16 @@ var currentTestCase = null;
|
| * @see runTest
|
| **/
|
| function createExpect(assertFunc) {
|
| - return function() {
|
| + var expectFunc = function() {
|
| try {
|
| assertFunc.apply(null, arguments);
|
| } catch (e) {
|
| errors.push(e);
|
| }
|
| };
|
| + expectFunc.isExpect = true;
|
| + expectFunc.expectName = assertFunc.name.replace(/^assert/, 'expect');
|
| + return expectFunc;
|
| }
|
|
|
| /**
|
| @@ -325,25 +465,31 @@ var currentTestCase = null;
|
| * @see createExpect
|
| **/
|
| function runTest(testFunction, testArguments) {
|
| - errors = [];
|
| + errors.splice(0, errors.length);
|
| // Avoid eval() if at all possible, since it will not work on pages
|
| // that have enabled content-security-policy.
|
| var testBody = this[testFunction]; // global object -- not a method.
|
| if (typeof testBody === "undefined")
|
| testBody = eval(testFunction);
|
| - if (testBody != RUN_TEST_F)
|
| - console.log('Running test ' + testBody.name);
|
| + if (testBody != RUN_TEST_F) {
|
| + var testName =
|
| + testFunction.name ? testFunction.name : testBody.toString();
|
| + console.log('Running test ' + testName);
|
| + }
|
| createExpect(testBody).apply(null, testArguments);
|
|
|
| + var result = [true];
|
| if (errors.length) {
|
| + var message = '';
|
| for (var i = 0; i < errors.length; ++i) {
|
| - console.log('Failed: ' + testFunction + '(' +
|
| - testArguments.toString() + ')\n' + errors[i].stack);
|
| + message += 'Failed: ' + testFunction + '(' +
|
| + testArguments.map(JSON.stringify) +
|
| + ')\n' + errors[i].stack;
|
| }
|
| - return [false, errors.join('\n')];
|
| - } else {
|
| - return [true];
|
| + errors.splice(0, errors.length);
|
| + result = [false, message];
|
| }
|
| + return result;
|
| }
|
|
|
| /**
|
|
|