Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | "use strict"; |
michael@0 | 6 | |
michael@0 | 7 | module.metadata = { |
michael@0 | 8 | "stability": "deprecated" |
michael@0 | 9 | }; |
michael@0 | 10 | |
michael@0 | 11 | const memory = require('./memory'); |
michael@0 | 12 | var timer = require("../timers"); |
michael@0 | 13 | var cfxArgs = require("@test/options"); |
michael@0 | 14 | |
michael@0 | 15 | exports.findAndRunTests = function findAndRunTests(options) { |
michael@0 | 16 | var TestFinder = require("./unit-test-finder").TestFinder; |
michael@0 | 17 | var finder = new TestFinder({ |
michael@0 | 18 | filter: options.filter, |
michael@0 | 19 | testInProcess: options.testInProcess, |
michael@0 | 20 | testOutOfProcess: options.testOutOfProcess |
michael@0 | 21 | }); |
michael@0 | 22 | var runner = new TestRunner({fs: options.fs}); |
michael@0 | 23 | finder.findTests( |
michael@0 | 24 | function (tests) { |
michael@0 | 25 | runner.startMany({tests: tests, |
michael@0 | 26 | stopOnError: options.stopOnError, |
michael@0 | 27 | onDone: options.onDone}); |
michael@0 | 28 | }); |
michael@0 | 29 | }; |
michael@0 | 30 | |
michael@0 | 31 | var TestRunner = exports.TestRunner = function TestRunner(options) { |
michael@0 | 32 | if (options) { |
michael@0 | 33 | this.fs = options.fs; |
michael@0 | 34 | } |
michael@0 | 35 | this.console = (options && "console" in options) ? options.console : console; |
michael@0 | 36 | memory.track(this); |
michael@0 | 37 | this.passed = 0; |
michael@0 | 38 | this.failed = 0; |
michael@0 | 39 | this.testRunSummary = []; |
michael@0 | 40 | this.expectFailNesting = 0; |
michael@0 | 41 | }; |
michael@0 | 42 | |
michael@0 | 43 | TestRunner.prototype = { |
michael@0 | 44 | toString: function toString() "[object TestRunner]", |
michael@0 | 45 | |
michael@0 | 46 | DEFAULT_PAUSE_TIMEOUT: 5*60000, |
michael@0 | 47 | PAUSE_DELAY: 500, |
michael@0 | 48 | |
michael@0 | 49 | _logTestFailed: function _logTestFailed(why) { |
michael@0 | 50 | if (!(why in this.test.errors)) |
michael@0 | 51 | this.test.errors[why] = 0; |
michael@0 | 52 | this.test.errors[why]++; |
michael@0 | 53 | }, |
michael@0 | 54 | |
michael@0 | 55 | pass: function pass(message) { |
michael@0 | 56 | if(!this.expectFailure) { |
michael@0 | 57 | if ("testMessage" in this.console) |
michael@0 | 58 | this.console.testMessage(true, true, this.test.name, message); |
michael@0 | 59 | else |
michael@0 | 60 | this.console.info("pass:", message); |
michael@0 | 61 | this.passed++; |
michael@0 | 62 | this.test.passed++; |
michael@0 | 63 | } |
michael@0 | 64 | else { |
michael@0 | 65 | this.expectFailure = false; |
michael@0 | 66 | this._logTestFailed("failure"); |
michael@0 | 67 | if ("testMessage" in this.console) { |
michael@0 | 68 | this.console.testMessage(true, false, this.test.name, message); |
michael@0 | 69 | } |
michael@0 | 70 | else { |
michael@0 | 71 | this.console.error("fail:", 'Failure Expected: ' + message) |
michael@0 | 72 | this.console.trace(); |
michael@0 | 73 | } |
michael@0 | 74 | this.failed++; |
michael@0 | 75 | this.test.failed++; |
michael@0 | 76 | } |
michael@0 | 77 | }, |
michael@0 | 78 | |
michael@0 | 79 | fail: function fail(message) { |
michael@0 | 80 | if(!this.expectFailure) { |
michael@0 | 81 | this._logTestFailed("failure"); |
michael@0 | 82 | if ("testMessage" in this.console) { |
michael@0 | 83 | this.console.testMessage(false, false, this.test.name, message); |
michael@0 | 84 | } |
michael@0 | 85 | else { |
michael@0 | 86 | this.console.error("fail:", message) |
michael@0 | 87 | this.console.trace(); |
michael@0 | 88 | } |
michael@0 | 89 | this.failed++; |
michael@0 | 90 | this.test.failed++; |
michael@0 | 91 | } |
michael@0 | 92 | else { |
michael@0 | 93 | this.expectFailure = false; |
michael@0 | 94 | if ("testMessage" in this.console) |
michael@0 | 95 | this.console.testMessage(false, true, this.test.name, message); |
michael@0 | 96 | else |
michael@0 | 97 | this.console.info("pass:", message); |
michael@0 | 98 | this.passed++; |
michael@0 | 99 | this.test.passed++; |
michael@0 | 100 | } |
michael@0 | 101 | }, |
michael@0 | 102 | |
michael@0 | 103 | expectFail: function(callback) { |
michael@0 | 104 | this.expectFailure = true; |
michael@0 | 105 | callback(); |
michael@0 | 106 | this.expectFailure = false; |
michael@0 | 107 | }, |
michael@0 | 108 | |
michael@0 | 109 | exception: function exception(e) { |
michael@0 | 110 | this._logTestFailed("exception"); |
michael@0 | 111 | if (cfxArgs.parseable) |
michael@0 | 112 | this.console.print("TEST-UNEXPECTED-FAIL | " + this.test.name + " | " + e + "\n"); |
michael@0 | 113 | this.console.exception(e); |
michael@0 | 114 | this.failed++; |
michael@0 | 115 | this.test.failed++; |
michael@0 | 116 | }, |
michael@0 | 117 | |
michael@0 | 118 | assertMatches: function assertMatches(string, regexp, message) { |
michael@0 | 119 | if (regexp.test(string)) { |
michael@0 | 120 | if (!message) |
michael@0 | 121 | message = uneval(string) + " matches " + uneval(regexp); |
michael@0 | 122 | this.pass(message); |
michael@0 | 123 | } else { |
michael@0 | 124 | var no = uneval(string) + " doesn't match " + uneval(regexp); |
michael@0 | 125 | if (!message) |
michael@0 | 126 | message = no; |
michael@0 | 127 | else |
michael@0 | 128 | message = message + " (" + no + ")"; |
michael@0 | 129 | this.fail(message); |
michael@0 | 130 | } |
michael@0 | 131 | }, |
michael@0 | 132 | |
michael@0 | 133 | assertRaises: function assertRaises(func, predicate, message) { |
michael@0 | 134 | try { |
michael@0 | 135 | func(); |
michael@0 | 136 | if (message) |
michael@0 | 137 | this.fail(message + " (no exception thrown)"); |
michael@0 | 138 | else |
michael@0 | 139 | this.fail("function failed to throw exception"); |
michael@0 | 140 | } catch (e) { |
michael@0 | 141 | var errorMessage; |
michael@0 | 142 | if (typeof(e) == "string") |
michael@0 | 143 | errorMessage = e; |
michael@0 | 144 | else |
michael@0 | 145 | errorMessage = e.message; |
michael@0 | 146 | if (typeof(predicate) == "string") |
michael@0 | 147 | this.assertEqual(errorMessage, predicate, message); |
michael@0 | 148 | else |
michael@0 | 149 | this.assertMatches(errorMessage, predicate, message); |
michael@0 | 150 | } |
michael@0 | 151 | }, |
michael@0 | 152 | |
michael@0 | 153 | assert: function assert(a, message) { |
michael@0 | 154 | if (!a) { |
michael@0 | 155 | if (!message) |
michael@0 | 156 | message = "assertion failed, value is " + a; |
michael@0 | 157 | this.fail(message); |
michael@0 | 158 | } else |
michael@0 | 159 | this.pass(message || "assertion successful"); |
michael@0 | 160 | }, |
michael@0 | 161 | |
michael@0 | 162 | assertNotEqual: function assertNotEqual(a, b, message) { |
michael@0 | 163 | if (a != b) { |
michael@0 | 164 | if (!message) |
michael@0 | 165 | message = "a != b != " + uneval(a); |
michael@0 | 166 | this.pass(message); |
michael@0 | 167 | } else { |
michael@0 | 168 | var equality = uneval(a) + " == " + uneval(b); |
michael@0 | 169 | if (!message) |
michael@0 | 170 | message = equality; |
michael@0 | 171 | else |
michael@0 | 172 | message += " (" + equality + ")"; |
michael@0 | 173 | this.fail(message); |
michael@0 | 174 | } |
michael@0 | 175 | }, |
michael@0 | 176 | |
michael@0 | 177 | assertEqual: function assertEqual(a, b, message) { |
michael@0 | 178 | if (a == b) { |
michael@0 | 179 | if (!message) |
michael@0 | 180 | message = "a == b == " + uneval(a); |
michael@0 | 181 | this.pass(message); |
michael@0 | 182 | } else { |
michael@0 | 183 | var inequality = uneval(a) + " != " + uneval(b); |
michael@0 | 184 | if (!message) |
michael@0 | 185 | message = inequality; |
michael@0 | 186 | else |
michael@0 | 187 | message += " (" + inequality + ")"; |
michael@0 | 188 | this.fail(message); |
michael@0 | 189 | } |
michael@0 | 190 | }, |
michael@0 | 191 | |
michael@0 | 192 | assertNotStrictEqual: function assertNotStrictEqual(a, b, message) { |
michael@0 | 193 | if (a !== b) { |
michael@0 | 194 | if (!message) |
michael@0 | 195 | message = "a !== b !== " + uneval(a); |
michael@0 | 196 | this.pass(message); |
michael@0 | 197 | } else { |
michael@0 | 198 | var equality = uneval(a) + " === " + uneval(b); |
michael@0 | 199 | if (!message) |
michael@0 | 200 | message = equality; |
michael@0 | 201 | else |
michael@0 | 202 | message += " (" + equality + ")"; |
michael@0 | 203 | this.fail(message); |
michael@0 | 204 | } |
michael@0 | 205 | }, |
michael@0 | 206 | |
michael@0 | 207 | assertStrictEqual: function assertStrictEqual(a, b, message) { |
michael@0 | 208 | if (a === b) { |
michael@0 | 209 | if (!message) |
michael@0 | 210 | message = "a === b === " + uneval(a); |
michael@0 | 211 | this.pass(message); |
michael@0 | 212 | } else { |
michael@0 | 213 | var inequality = uneval(a) + " !== " + uneval(b); |
michael@0 | 214 | if (!message) |
michael@0 | 215 | message = inequality; |
michael@0 | 216 | else |
michael@0 | 217 | message += " (" + inequality + ")"; |
michael@0 | 218 | this.fail(message); |
michael@0 | 219 | } |
michael@0 | 220 | }, |
michael@0 | 221 | |
michael@0 | 222 | assertFunction: function assertFunction(a, message) { |
michael@0 | 223 | this.assertStrictEqual('function', typeof a, message); |
michael@0 | 224 | }, |
michael@0 | 225 | |
michael@0 | 226 | assertUndefined: function(a, message) { |
michael@0 | 227 | this.assertStrictEqual('undefined', typeof a, message); |
michael@0 | 228 | }, |
michael@0 | 229 | |
michael@0 | 230 | assertNotUndefined: function(a, message) { |
michael@0 | 231 | this.assertNotStrictEqual('undefined', typeof a, message); |
michael@0 | 232 | }, |
michael@0 | 233 | |
michael@0 | 234 | assertNull: function(a, message) { |
michael@0 | 235 | this.assertStrictEqual(null, a, message); |
michael@0 | 236 | }, |
michael@0 | 237 | |
michael@0 | 238 | assertNotNull: function(a, message) { |
michael@0 | 239 | this.assertNotStrictEqual(null, a, message); |
michael@0 | 240 | }, |
michael@0 | 241 | |
michael@0 | 242 | assertObject: function(a, message) { |
michael@0 | 243 | this.assertStrictEqual('[object Object]', Object.prototype.toString.apply(a), message); |
michael@0 | 244 | }, |
michael@0 | 245 | |
michael@0 | 246 | assertString: function(a, message) { |
michael@0 | 247 | this.assertStrictEqual('[object String]', Object.prototype.toString.apply(a), message); |
michael@0 | 248 | }, |
michael@0 | 249 | |
michael@0 | 250 | assertArray: function(a, message) { |
michael@0 | 251 | this.assertStrictEqual('[object Array]', Object.prototype.toString.apply(a), message); |
michael@0 | 252 | }, |
michael@0 | 253 | |
michael@0 | 254 | assertNumber: function(a, message) { |
michael@0 | 255 | this.assertStrictEqual('[object Number]', Object.prototype.toString.apply(a), message); |
michael@0 | 256 | }, |
michael@0 | 257 | |
michael@0 | 258 | done: function done() { |
michael@0 | 259 | if (!this.isDone) { |
michael@0 | 260 | this.isDone = true; |
michael@0 | 261 | if(this.test.teardown) { |
michael@0 | 262 | this.test.teardown(this); |
michael@0 | 263 | } |
michael@0 | 264 | if (this.waitTimeout !== null) { |
michael@0 | 265 | timer.clearTimeout(this.waitTimeout); |
michael@0 | 266 | this.waitTimeout = null; |
michael@0 | 267 | } |
michael@0 | 268 | // Do not leave any callback set when calling to `waitUntil` |
michael@0 | 269 | this.waitUntilCallback = null; |
michael@0 | 270 | if (this.test.passed == 0 && this.test.failed == 0) { |
michael@0 | 271 | this._logTestFailed("empty test"); |
michael@0 | 272 | if ("testMessage" in this.console) { |
michael@0 | 273 | this.console.testMessage(false, false, this.test.name, "Empty test"); |
michael@0 | 274 | } |
michael@0 | 275 | else { |
michael@0 | 276 | this.console.error("fail:", "Empty test") |
michael@0 | 277 | } |
michael@0 | 278 | this.failed++; |
michael@0 | 279 | this.test.failed++; |
michael@0 | 280 | } |
michael@0 | 281 | |
michael@0 | 282 | this.testRunSummary.push({ |
michael@0 | 283 | name: this.test.name, |
michael@0 | 284 | passed: this.test.passed, |
michael@0 | 285 | failed: this.test.failed, |
michael@0 | 286 | errors: [error for (error in this.test.errors)].join(", ") |
michael@0 | 287 | }); |
michael@0 | 288 | |
michael@0 | 289 | if (this.onDone !== null) { |
michael@0 | 290 | var onDone = this.onDone; |
michael@0 | 291 | var self = this; |
michael@0 | 292 | this.onDone = null; |
michael@0 | 293 | timer.setTimeout(function() { onDone(self); }, 0); |
michael@0 | 294 | } |
michael@0 | 295 | } |
michael@0 | 296 | }, |
michael@0 | 297 | |
michael@0 | 298 | // Set of assertion functions to wait for an assertion to become true |
michael@0 | 299 | // These functions take the same arguments as the TestRunner.assert* methods. |
michael@0 | 300 | waitUntil: function waitUntil() { |
michael@0 | 301 | return this._waitUntil(this.assert, arguments); |
michael@0 | 302 | }, |
michael@0 | 303 | |
michael@0 | 304 | waitUntilNotEqual: function waitUntilNotEqual() { |
michael@0 | 305 | return this._waitUntil(this.assertNotEqual, arguments); |
michael@0 | 306 | }, |
michael@0 | 307 | |
michael@0 | 308 | waitUntilEqual: function waitUntilEqual() { |
michael@0 | 309 | return this._waitUntil(this.assertEqual, arguments); |
michael@0 | 310 | }, |
michael@0 | 311 | |
michael@0 | 312 | waitUntilMatches: function waitUntilMatches() { |
michael@0 | 313 | return this._waitUntil(this.assertMatches, arguments); |
michael@0 | 314 | }, |
michael@0 | 315 | |
michael@0 | 316 | /** |
michael@0 | 317 | * Internal function that waits for an assertion to become true. |
michael@0 | 318 | * @param {Function} assertionMethod |
michael@0 | 319 | * Reference to a TestRunner assertion method like test.assert, |
michael@0 | 320 | * test.assertEqual, ... |
michael@0 | 321 | * @param {Array} args |
michael@0 | 322 | * List of arguments to give to the previous assertion method. |
michael@0 | 323 | * All functions in this list are going to be called to retrieve current |
michael@0 | 324 | * assertion values. |
michael@0 | 325 | */ |
michael@0 | 326 | _waitUntil: function waitUntil(assertionMethod, args) { |
michael@0 | 327 | let count = 0; |
michael@0 | 328 | let maxCount = this.DEFAULT_PAUSE_TIMEOUT / this.PAUSE_DELAY; |
michael@0 | 329 | |
michael@0 | 330 | // We need to ensure that test is asynchronous |
michael@0 | 331 | if (!this.waitTimeout) |
michael@0 | 332 | this.waitUntilDone(this.DEFAULT_PAUSE_TIMEOUT); |
michael@0 | 333 | |
michael@0 | 334 | let callback = null; |
michael@0 | 335 | let finished = false; |
michael@0 | 336 | |
michael@0 | 337 | let test = this; |
michael@0 | 338 | |
michael@0 | 339 | // capture a traceback before we go async. |
michael@0 | 340 | let traceback = require("../console/traceback"); |
michael@0 | 341 | let stack = traceback.get(); |
michael@0 | 342 | stack.splice(-2, 2); |
michael@0 | 343 | let currentWaitStack = traceback.format(stack); |
michael@0 | 344 | let timeout = null; |
michael@0 | 345 | |
michael@0 | 346 | function loop(stopIt) { |
michael@0 | 347 | timeout = null; |
michael@0 | 348 | |
michael@0 | 349 | // Build a mockup object to fake TestRunner API and intercept calls to |
michael@0 | 350 | // pass and fail methods, in order to retrieve nice error messages |
michael@0 | 351 | // and assertion result |
michael@0 | 352 | let mock = { |
michael@0 | 353 | pass: function (msg) { |
michael@0 | 354 | test.pass(msg); |
michael@0 | 355 | test.waitUntilCallback = null; |
michael@0 | 356 | if (callback && !stopIt) |
michael@0 | 357 | callback(); |
michael@0 | 358 | finished = true; |
michael@0 | 359 | }, |
michael@0 | 360 | fail: function (msg) { |
michael@0 | 361 | // If we are called on test timeout, we stop the loop |
michael@0 | 362 | // and print which test keeps failing: |
michael@0 | 363 | if (stopIt) { |
michael@0 | 364 | test.console.error("test assertion never became true:\n", |
michael@0 | 365 | msg + "\n", |
michael@0 | 366 | currentWaitStack); |
michael@0 | 367 | if (timeout) |
michael@0 | 368 | timer.clearTimeout(timeout); |
michael@0 | 369 | return; |
michael@0 | 370 | } |
michael@0 | 371 | timeout = timer.setTimeout(loop, test.PAUSE_DELAY); |
michael@0 | 372 | } |
michael@0 | 373 | }; |
michael@0 | 374 | |
michael@0 | 375 | // Automatically call args closures in order to build arguments for |
michael@0 | 376 | // assertion function |
michael@0 | 377 | let appliedArgs = []; |
michael@0 | 378 | for (let i = 0, l = args.length; i < l; i++) { |
michael@0 | 379 | let a = args[i]; |
michael@0 | 380 | if (typeof a == "function") { |
michael@0 | 381 | try { |
michael@0 | 382 | a = a(); |
michael@0 | 383 | } |
michael@0 | 384 | catch(e) { |
michael@0 | 385 | test.fail("Exception when calling asynchronous assertion: " + e + |
michael@0 | 386 | "\n" + e.stack); |
michael@0 | 387 | finished = true; |
michael@0 | 388 | return; |
michael@0 | 389 | } |
michael@0 | 390 | } |
michael@0 | 391 | appliedArgs.push(a); |
michael@0 | 392 | } |
michael@0 | 393 | |
michael@0 | 394 | // Finally call assertion function with current assertion values |
michael@0 | 395 | assertionMethod.apply(mock, appliedArgs); |
michael@0 | 396 | } |
michael@0 | 397 | loop(); |
michael@0 | 398 | this.waitUntilCallback = loop; |
michael@0 | 399 | |
michael@0 | 400 | // Return an object with `then` method, to offer a way to execute |
michael@0 | 401 | // some code when the assertion passed or failed |
michael@0 | 402 | return { |
michael@0 | 403 | then: function (c) { |
michael@0 | 404 | callback = c; |
michael@0 | 405 | |
michael@0 | 406 | // In case of immediate positive result, we need to execute callback |
michael@0 | 407 | // immediately here: |
michael@0 | 408 | if (finished) |
michael@0 | 409 | callback(); |
michael@0 | 410 | } |
michael@0 | 411 | }; |
michael@0 | 412 | }, |
michael@0 | 413 | |
michael@0 | 414 | waitUntilDone: function waitUntilDone(ms) { |
michael@0 | 415 | if (ms === undefined) |
michael@0 | 416 | ms = this.DEFAULT_PAUSE_TIMEOUT; |
michael@0 | 417 | |
michael@0 | 418 | var self = this; |
michael@0 | 419 | |
michael@0 | 420 | function tiredOfWaiting() { |
michael@0 | 421 | self._logTestFailed("timed out"); |
michael@0 | 422 | if ("testMessage" in self.console) { |
michael@0 | 423 | self.console.testMessage(false, false, self.test.name, "Timed out"); |
michael@0 | 424 | } |
michael@0 | 425 | else { |
michael@0 | 426 | self.console.error("fail:", "Timed out") |
michael@0 | 427 | } |
michael@0 | 428 | if (self.waitUntilCallback) { |
michael@0 | 429 | self.waitUntilCallback(true); |
michael@0 | 430 | self.waitUntilCallback = null; |
michael@0 | 431 | } |
michael@0 | 432 | self.failed++; |
michael@0 | 433 | self.test.failed++; |
michael@0 | 434 | self.done(); |
michael@0 | 435 | } |
michael@0 | 436 | |
michael@0 | 437 | // We may already have registered a timeout callback |
michael@0 | 438 | if (this.waitTimeout) |
michael@0 | 439 | timer.clearTimeout(this.waitTimeout); |
michael@0 | 440 | |
michael@0 | 441 | this.waitTimeout = timer.setTimeout(tiredOfWaiting, ms); |
michael@0 | 442 | }, |
michael@0 | 443 | |
michael@0 | 444 | startMany: function startMany(options) { |
michael@0 | 445 | function runNextTest(self) { |
michael@0 | 446 | var test = options.tests.shift(); |
michael@0 | 447 | if (options.stopOnError && self.test && self.test.failed) { |
michael@0 | 448 | self.console.error("aborted: test failed and --stop-on-error was specified"); |
michael@0 | 449 | options.onDone(self); |
michael@0 | 450 | } else if (test) { |
michael@0 | 451 | self.start({test: test, onDone: runNextTest}); |
michael@0 | 452 | } else { |
michael@0 | 453 | options.onDone(self); |
michael@0 | 454 | } |
michael@0 | 455 | } |
michael@0 | 456 | runNextTest(this); |
michael@0 | 457 | }, |
michael@0 | 458 | |
michael@0 | 459 | start: function start(options) { |
michael@0 | 460 | this.test = options.test; |
michael@0 | 461 | this.test.passed = 0; |
michael@0 | 462 | this.test.failed = 0; |
michael@0 | 463 | this.test.errors = {}; |
michael@0 | 464 | |
michael@0 | 465 | this.isDone = false; |
michael@0 | 466 | this.onDone = function(self) { |
michael@0 | 467 | if (cfxArgs.parseable) |
michael@0 | 468 | self.console.print("TEST-END | " + self.test.name + "\n"); |
michael@0 | 469 | options.onDone(self); |
michael@0 | 470 | } |
michael@0 | 471 | this.waitTimeout = null; |
michael@0 | 472 | |
michael@0 | 473 | try { |
michael@0 | 474 | if (cfxArgs.parseable) |
michael@0 | 475 | this.console.print("TEST-START | " + this.test.name + "\n"); |
michael@0 | 476 | else |
michael@0 | 477 | this.console.info("executing '" + this.test.name + "'"); |
michael@0 | 478 | |
michael@0 | 479 | if(this.test.setup) { |
michael@0 | 480 | this.test.setup(this); |
michael@0 | 481 | } |
michael@0 | 482 | this.test.testFunction(this); |
michael@0 | 483 | } catch (e) { |
michael@0 | 484 | this.exception(e); |
michael@0 | 485 | } |
michael@0 | 486 | if (this.waitTimeout === null) |
michael@0 | 487 | this.done(); |
michael@0 | 488 | } |
michael@0 | 489 | }; |