| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 })(); |
| OLD | NEW |