Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Side by Side Diff: chrome/test/data/webui/test_api.js

Issue 7250009: Added guts to pull call signatures when assertions & expectations fail. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: clang Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/test/data/webui/assertions-inl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview Library providing basic test framework functionality. 6 * @fileoverview Library providing basic test framework functionality.
7 **/ 7 **/
8 8
9 /** 9 /**
10 * Namespace for |Test|. 10 * Namespace for |Test|.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 67
68 /** 68 /**
69 * When set to a function, will be called in the context of the test 69 * When set to a function, will be called in the context of the test
70 * generation inside the function, and before any generated C++. 70 * generation inside the function, and before any generated C++.
71 * @type {function(string,string)} 71 * @type {function(string,string)}
72 **/ 72 **/
73 testGenPreamble: null, 73 testGenPreamble: null,
74 74
75 /** 75 /**
76 * When set to a function, will be called in the context of the test 76 * When set to a function, will be called in the context of the test
77 * generation inside the function, and before any generated C++. 77 * generation inside the function, and after any generated C++.
78 * @type {function(string,string)} 78 * @type {function(string,string)}
79 **/ 79 **/
80 testGenPostamble: null, 80 testGenPostamble: null,
81 81
82 /** 82 /**
83 * When set to a non-null String, auto-generate typedef before generating 83 * When set to a non-null String, auto-generate typedef before generating
84 * TEST*: {@code typedef typedefCppFixture testFixture}. 84 * TEST*: {@code typedef typedefCppFixture testFixture}.
85 * @type {String} 85 * @type {String}
86 **/ 86 **/
87 typedefCppFixture: 'WebUIBrowserTest', 87 typedefCppFixture: 'WebUIBrowserTest',
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 /** 139 /**
140 * Called at preload time, proxies to the fixture. 140 * Called at preload time, proxies to the fixture.
141 * @type {Function} 141 * @type {Function}
142 **/ 142 **/
143 PreLoad: function(name) { 143 PreLoad: function(name) {
144 if (this.fixture) 144 if (this.fixture)
145 this.fixture.PreLoad(); 145 this.fixture.PreLoad();
146 }, 146 },
147 147
148 /** 148 /**
149 * Runs this test case. 149 * Runs this test case with |this| set to the |fixture|.
150 *
151 * Note: Tests created with TEST_F may depend upon |this| being set to an
152 * instance of this.fixture. The current implementation of TEST creates a
153 * dummy constructor, but tests created with TEST should not rely on |this|
154 * being set.
150 * @type {Function} 155 * @type {Function}
151 **/ 156 **/
152 Run: function() { 157 Run: function() {
153 if (this.fixture) 158 if (this.fixture)
154 this.fixture.SetUp(); 159 this.fixture.SetUp();
155 if (this.body) 160 if (this.body)
156 this.body.call(this.fixture); 161 this.body.call(this.fixture);
157 if (this.fixture) 162 if (this.fixture)
158 this.fixture.TearDown(); 163 this.fixture.TearDown();
159 }, 164 },
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 **/ 215 **/
211 function send(messageName) { 216 function send(messageName) {
212 var callback = sendCallbacks[messageName]; 217 var callback = sendCallbacks[messageName];
213 var args = Array.prototype.slice.call(arguments, 1); 218 var args = Array.prototype.slice.call(arguments, 1);
214 if (callback != undefined) 219 if (callback != undefined)
215 callback[1].apply(callback[0], args); 220 callback[1].apply(callback[0], args);
216 else 221 else
217 oldChrome.send.apply(oldChrome, args); 222 oldChrome.send.apply(oldChrome, args);
218 } 223 }
219 224
225 /**
226 * Provides a mechanism for assert* and expect* methods to fetch the signature
227 * of their caller. Assert* methods should |registerCall| and expect* methods
228 * should set |isExpect| and |expectName| properties to indicate that the
229 * interesting caller is one more level up the stack.
230 **/
231 function CallHelper() {
232 this.__proto__ = CallHelper.prototype;
233 }
234
235 CallHelper.prototype = {
236 /**
237 * Holds the mapping of (callerCallerString, callerName) -> count of times
238 * called.
239 * @type {Object.<string, Object.<string, number>>}
240 **/
241 counts_: {},
242
243 /**
244 * This information about the caller is needed from most of the following
245 * routines.
246 * @param {Function} caller the caller of the assert* routine.
247 * @return {{callerName: string, callercallerString: string}} stackInfo
248 * @private
249 **/
250 getCallerInfo_: function(caller) {
251 var callerName = caller.name;
252 var callerCaller = caller.caller;
253 if (callerCaller['isExpect']) {
254 callerName = callerCaller.expectName;
255 callerCaller = callerCaller.caller;
256 }
257 var callerCallerString = callerCaller.toString();
258 return {
259 callerName: callerName,
260 callerCallerString: callerCallerString,
261 };
262 },
263
264 /**
265 * Register a call to an assertion class.
266 **/
267 registerCall: function() {
268 var stackInfo = this.getCallerInfo_(arguments.callee.caller);
269 if (!(stackInfo.callerCallerString in this.counts_))
270 this.counts_[stackInfo.callerCallerString] = {};
271 if (!(stackInfo.callerName in this.counts_[stackInfo.callerCallerString]))
272 this.counts_[stackInfo.callerCallerString][stackInfo.callerName] = 0;
273 ++this.counts_[stackInfo.callerCallerString][stackInfo.callerName];
274 },
275
276 /**
277 * Get the call signature of this instance of the caller's call to this
278 * function.
279 * @param {Function} caller The caller of the assert* routine.
280 * @return {String} Call signature.
281 * @private
282 **/
283 getCall_: function(caller) {
284 var stackInfo = this.getCallerInfo_(caller);
285 var count =
286 this.counts_[stackInfo.callerCallerString][stackInfo.callerName];
287
288 // Allow pattern to match multiple lines for text wrapping.
289 var callerRegExp =
290 new RegExp(stackInfo.callerName + '\\((.|\\n)*?\\);', 'g');
291
292 // Find all matches allowing wrap around such as when a helper function
293 // calls assert/expect calls and that helper function is called multiple
294 // times.
295 var matches = stackInfo.callerCallerString.match(callerRegExp);
296 var match = matches[(count - 1) % matches.length];
297
298 // Chop off the trailing ';'.
299 return match.substring(0, match.length-1);
300 },
301
302 /**
303 * Returns the text of the call signature and any |message|.
304 * @param {string=} message Addtional message text from caller.
305 **/
306 getCallMessage: function(message) {
307 var callMessage = this.getCall_(arguments.callee.caller);
308 if (message)
309 callMessage += ': ' + message;
310 return callMessage;
311 },
312 };
313
314 /**
315 * Help register calls for better error reporting.
316 * @type {CallHelper}
317 **/
318 var helper = new CallHelper();
319
220 // Asserts. 320 // Asserts.
221 // Use the following assertions to verify a condition within a test. 321 // Use the following assertions to verify a condition within a test.
222 // If assertion fails, the C++ backend will be immediately notified. 322 // If assertion fails, the C++ backend will be immediately notified.
223 // If assertion passes, no notification will be sent to the C++ backend. 323 // If assertion passes, no notification will be sent to the C++ backend.
224 324
225 /** 325 /**
226 * When |test| !== |expected|, aborts the current test. 326 * When |test| !== |expected|, aborts the current test.
227 * @param {Boolean} test The predicate to check against |expected|. 327 * @param {Boolean} test The predicate to check against |expected|.
228 * @param {Boolean} expected The expected value of |test|. 328 * @param {Boolean} expected The expected value of |test|.
229 * @param {String=} message The message to include in the Error thrown. 329 * @param {String=} message The message to include in the Error thrown.
230 * @throws {Error} upon failure. 330 * @throws {Error} upon failure.
231 **/ 331 **/
232 function assertBool(test, expected, message) { 332 function assertBool(test, expected, message) {
233 if (test !== expected) { 333 helper.registerCall();
234 if (message) 334 if (test !== expected)
235 message = test + '\n' + message; 335 throw new Error('Test Error ' + helper.getCallMessage(message) +
236 else 336 ': ' + test);
237 message = test;
238 throw new Error(message);
239 }
240 } 337 }
241 338
242 /** 339 /**
243 * When |test| !== true, aborts the current test. 340 * When |test| !== true, aborts the current test.
244 * @param {Boolean} test The predicate to check against |expected|. 341 * @param {Boolean} test The predicate to check against |expected|.
245 * @param {String=} message The message to include in the Error thrown. 342 * @param {String=} message The message to include in the Error thrown.
246 * @throws {Error} upon failure. 343 * @throws {Error} upon failure.
247 **/ 344 **/
248 function assertTrue(test, message) { 345 function assertTrue(test, message) {
249 assertBool(test, true, message); 346 helper.registerCall();
347 if (test !== true)
348 throw new Error('Test Error ' + helper.getCallMessage(message) +
349 ': ' + test);
250 } 350 }
251 351
252 /** 352 /**
253 * When |test| !== false, aborts the current test. 353 * When |test| !== false, aborts the current test.
254 * @param {Boolean} test The predicate to check against |expected|. 354 * @param {Boolean} test The predicate to check against |expected|.
255 * @param {String=} message The message to include in the Error thrown. 355 * @param {String=} message The message to include in the Error thrown.
256 * @throws {Error} upon failure. 356 * @throws {Error} upon failure.
257 **/ 357 **/
258 function assertFalse(test, message) { 358 function assertFalse(test, message) {
259 assertBool(test, false, message); 359 helper.registerCall();
360 if (test !== false)
361 throw new Error('Test Error ' + helper.getCallMessage(message) +
362 ': ' + test);
260 } 363 }
261 364
262 /** 365 /**
263 * When |expected| !== |actual|, aborts the current test. 366 * When |expected| !== |actual|, aborts the current test.
264 * @param {*} expected The predicate to check against |expected|. 367 * @param {*} expected The predicate to check against |expected|.
265 * @param {*} actual The expected value of |test|. 368 * @param {*} actual The expected value of |test|.
266 * @param {String=} message The message to include in the Error thrown. 369 * @param {String=} message The message to include in the Error thrown.
267 * @throws {Error} upon failure. 370 * @throws {Error} upon failure.
268 **/ 371 **/
269 function assertEquals(expected, actual, message) { 372 function assertEquals(expected, actual, message) {
373 helper.registerCall();
270 if (expected != actual) { 374 if (expected != actual) {
271 throw new Error('Test Error. Actual: ' + actual + '\nExpected: ' + 375 throw new Error('Test Error ' + helper.getCallMessage(message) +
272 expected + '\n' + message); 376 '\nActual: ' + actual + '\nExpected: ' + expected);
273 } 377 }
274 if (typeof expected != typeof actual) { 378 if (typeof expected != typeof actual) {
275 throw new Error('Test Error' + 379 throw new Error('Test Error (type mismatch) ' +
276 ' (type mismatch)\nActual Type: ' + typeof actual + 380 helper.getCallMessage(message) +
277 '\nExpected Type:' + typeof expected + '\n' + message); 381 '\nActual Type: ' + typeof actual +
382 '\nExpected Type:' + typeof expected);
278 } 383 }
279 } 384 }
280 385
281 /** 386 /**
282 * Always aborts the current test. 387 * Always aborts the current test.
283 * @param {String=} message The message to include in the Error thrown. 388 * @param {String=} message The message to include in the Error thrown.
284 * @throws {Error} always. 389 * @throws {Error} always.
285 **/ 390 **/
286 function assertNotReached(message) { 391 function assertNotReached(message) {
287 throw new Error(message); 392 helper.registerCall();
393 throw new Error(helper.getCallMessage(message));
288 } 394 }
289 395
290 /** 396 /**
291 * Holds the errors, if any, caught by expects so that the test case can fail. 397 * Holds the errors, if any, caught by expects so that the test case can fail.
292 * @type {Array.<Error>} 398 * @type {Array.<Error>}
293 **/ 399 **/
294 var errors = []; 400 var errors = [];
295 401
296 /** 402 /**
297 * Creates a function based upon a function that thows an exception on 403 * Creates a function based upon a function that thows an exception on
298 * failure. The new function stuffs any errors into the |errors| array for 404 * failure. The new function stuffs any errors into the |errors| array for
299 * checking by runTest. This allows tests to continue running other checks, 405 * checking by runTest. This allows tests to continue running other checks,
300 * while failing the overal test if any errors occurrred. 406 * while failing the overal test if any errors occurrred.
301 * @param {Function} assertFunc The function which may throw an Error. 407 * @param {Function} assertFunc The function which may throw an Error.
302 * @return {Function} A function that applies its arguments to |assertFunc|. 408 * @return {Function} A function that applies its arguments to |assertFunc|.
303 * @see errors 409 * @see errors
304 * @see runTest 410 * @see runTest
305 **/ 411 **/
306 function createExpect(assertFunc) { 412 function createExpect(assertFunc) {
307 return function() { 413 var expectFunc = function() {
308 try { 414 try {
309 assertFunc.apply(null, arguments); 415 assertFunc.apply(null, arguments);
310 } catch (e) { 416 } catch (e) {
311 errors.push(e); 417 errors.push(e);
312 } 418 }
313 }; 419 };
420 expectFunc.isExpect = true;
421 expectFunc.expectName = assertFunc.name.replace(/^assert/, 'expect');
422 return expectFunc;
314 } 423 }
315 424
316 /** 425 /**
317 * This is the starting point for tests run by WebUIBrowserTest. It clears 426 * This is the starting point for tests run by WebUIBrowserTest. It clears
318 * |errors|, runs the test surrounded by an expect to catch Errors. If 427 * |errors|, runs the test surrounded by an expect to catch Errors. If
319 * |errors| is non-empty, it reports a failure and a message by joining 428 * |errors| is non-empty, it reports a failure and a message by joining
320 * |errors|. 429 * |errors|.
321 * @param {String} testFunction The function name to call. 430 * @param {String} testFunction The function name to call.
322 * @param {Array} testArguments The arguments to call |testFunction| with. 431 * @param {Array} testArguments The arguments to call |testFunction| with.
323 * @return {Array.<Boolean, String>} [test-succeeded, message-if-failed] 432 * @return {Array.<Boolean, String>} [test-succeeded, message-if-failed]
324 * @see errors 433 * @see errors
325 * @see createExpect 434 * @see createExpect
326 **/ 435 **/
327 function runTest(testFunction, testArguments) { 436 function runTest(testFunction, testArguments) {
328 errors = []; 437 errors.splice(0, errors.length);
329 // Avoid eval() if at all possible, since it will not work on pages 438 // Avoid eval() if at all possible, since it will not work on pages
330 // that have enabled content-security-policy. 439 // that have enabled content-security-policy.
331 var testBody = this[testFunction]; // global object -- not a method. 440 var testBody = this[testFunction]; // global object -- not a method.
332 if (typeof testBody === "undefined") 441 if (typeof testBody === "undefined")
333 testBody = eval(testFunction); 442 testBody = eval(testFunction);
334 if (testBody != RUN_TEST_F) 443 if (testBody != RUN_TEST_F) {
335 console.log('Running test ' + testBody.name); 444 var testName =
445 testFunction.name ? testFunction.name : testBody.toString();
446 console.log('Running test ' + testName);
447 }
336 createExpect(testBody).apply(null, testArguments); 448 createExpect(testBody).apply(null, testArguments);
337 449
450 var result = [true];
338 if (errors.length) { 451 if (errors.length) {
452 var message = '';
339 for (var i = 0; i < errors.length; ++i) { 453 for (var i = 0; i < errors.length; ++i) {
340 console.log('Failed: ' + testFunction + '(' + 454 message += 'Failed: ' + testFunction + '(' +
341 testArguments.toString() + ')\n' + errors[i].stack); 455 testArguments.map(JSON.stringify) +
456 ')\n' + errors[i].stack;
342 } 457 }
343 return [false, errors.join('\n')]; 458 errors.splice(0, errors.length);
344 } else { 459 result = [false, message];
345 return [true];
346 } 460 }
461 return result;
347 } 462 }
348 463
349 /** 464 /**
350 * Creates a new test case for the given |testFixture| and |testName|. Assumes 465 * Creates a new test case for the given |testFixture| and |testName|. Assumes
351 * |testFixture| describes a globally available subclass of type Test. 466 * |testFixture| describes a globally available subclass of type Test.
352 * @param {String} testFixture The fixture for this test case. 467 * @param {String} testFixture The fixture for this test case.
353 * @param {String} testName The name for this test case. 468 * @param {String} testName The name for this test case.
354 * @return {TestCase} A newly created TestCase. 469 * @return {TestCase} A newly created TestCase.
355 **/ 470 **/
356 function createTestCase(testFixture, testName) { 471 function createTestCase(testFixture, testName) {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 window.registerMockMessageCallbacks = registerMockMessageCallbacks; 606 window.registerMockMessageCallbacks = registerMockMessageCallbacks;
492 window.runTest = runTest; 607 window.runTest = runTest;
493 window.preloadJavascriptLibraries = preloadJavascriptLibraries; 608 window.preloadJavascriptLibraries = preloadJavascriptLibraries;
494 window.TEST = TEST; 609 window.TEST = TEST;
495 window.TEST_F = TEST_F; 610 window.TEST_F = TEST_F;
496 window.GEN = GEN; 611 window.GEN = GEN;
497 612
498 // Import the Mock4JS helpers. 613 // Import the Mock4JS helpers.
499 Mock4JS.addMockSupport(window); 614 Mock4JS.addMockSupport(window);
500 })(); 615 })();
OLDNEW
« no previous file with comments | « chrome/test/data/webui/assertions-inl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698