toolkit/modules/tests/xpcshell/test_DeferredTask.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* Any copyright is dedicated to the Public Domain.
michael@0 2 http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 3
michael@0 4 /**
michael@0 5 * This file tests the DeferredTask.jsm module.
michael@0 6 */
michael@0 7
michael@0 8 ////////////////////////////////////////////////////////////////////////////////
michael@0 9 /// Globals
michael@0 10
michael@0 11 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
michael@0 12
michael@0 13 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 14
michael@0 15 XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
michael@0 16 "resource://gre/modules/DeferredTask.jsm");
michael@0 17 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
michael@0 18 "resource://gre/modules/Promise.jsm");
michael@0 19
michael@0 20 /**
michael@0 21 * Due to the nature of this module, most of the tests are time-dependent. All
michael@0 22 * the timeouts are designed to occur at multiples of this granularity value,
michael@0 23 * in milliseconds, that should be high enough to prevent intermittent failures,
michael@0 24 * but low enough to prevent an excessive overall test execution time.
michael@0 25 */
michael@0 26 const T = 100;
michael@0 27
michael@0 28 /**
michael@0 29 * Waits for the specified timeout before resolving the returned promise.
michael@0 30 */
michael@0 31 function promiseTimeout(aTimeoutMs)
michael@0 32 {
michael@0 33 let deferred = Promise.defer();
michael@0 34 do_timeout(aTimeoutMs, deferred.resolve);
michael@0 35 return deferred.promise;
michael@0 36 }
michael@0 37
michael@0 38 function run_test()
michael@0 39 {
michael@0 40 run_next_test();
michael@0 41 }
michael@0 42
michael@0 43 ////////////////////////////////////////////////////////////////////////////////
michael@0 44 //// Tests
michael@0 45
michael@0 46 /**
michael@0 47 * Creates a simple DeferredTask and executes it once.
michael@0 48 */
michael@0 49 add_test(function test_arm_simple()
michael@0 50 {
michael@0 51 new DeferredTask(run_next_test, 10).arm();
michael@0 52 });
michael@0 53
michael@0 54 /**
michael@0 55 * Checks that the delay set for the task is respected.
michael@0 56 */
michael@0 57 add_test(function test_arm_delay_respected()
michael@0 58 {
michael@0 59 let executed1 = false;
michael@0 60 let executed2 = false;
michael@0 61
michael@0 62 new DeferredTask(function () {
michael@0 63 executed1 = true;
michael@0 64 do_check_false(executed2);
michael@0 65 }, 1*T).arm();
michael@0 66
michael@0 67 new DeferredTask(function () {
michael@0 68 executed2 = true;
michael@0 69 do_check_true(executed1);
michael@0 70 run_next_test();
michael@0 71 }, 2*T).arm();
michael@0 72 });
michael@0 73
michael@0 74 /**
michael@0 75 * Checks that calling "arm" again does not introduce further delay.
michael@0 76 */
michael@0 77 add_test(function test_arm_delay_notrestarted()
michael@0 78 {
michael@0 79 let executed = false;
michael@0 80
michael@0 81 // Create a task that will run later.
michael@0 82 let deferredTask = new DeferredTask(() => { executed = true; }, 4*T);
michael@0 83 deferredTask.arm();
michael@0 84
michael@0 85 // Before the task starts, call "arm" again.
michael@0 86 do_timeout(2*T, () => deferredTask.arm());
michael@0 87
michael@0 88 // The "arm" call should not have introduced further delays.
michael@0 89 do_timeout(5*T, function () {
michael@0 90 do_check_true(executed);
michael@0 91 run_next_test();
michael@0 92 });
michael@0 93 });
michael@0 94
michael@0 95 /**
michael@0 96 * Checks that a task runs only once when armed multiple times synchronously.
michael@0 97 */
michael@0 98 add_test(function test_arm_coalesced()
michael@0 99 {
michael@0 100 let executed = false;
michael@0 101
michael@0 102 let deferredTask = new DeferredTask(function () {
michael@0 103 do_check_false(executed);
michael@0 104 executed = true;
michael@0 105 run_next_test();
michael@0 106 }, 50);
michael@0 107
michael@0 108 deferredTask.arm();
michael@0 109 deferredTask.arm();
michael@0 110 });
michael@0 111
michael@0 112 /**
michael@0 113 * Checks that a task runs only once when armed multiple times synchronously,
michael@0 114 * even when it has been created with a delay of zero milliseconds.
michael@0 115 */
michael@0 116 add_test(function test_arm_coalesced_nodelay()
michael@0 117 {
michael@0 118 let executed = false;
michael@0 119
michael@0 120 let deferredTask = new DeferredTask(function () {
michael@0 121 do_check_false(executed);
michael@0 122 executed = true;
michael@0 123 run_next_test();
michael@0 124 }, 0);
michael@0 125
michael@0 126 deferredTask.arm();
michael@0 127 deferredTask.arm();
michael@0 128 });
michael@0 129
michael@0 130 /**
michael@0 131 * Checks that a task can be armed again while running.
michael@0 132 */
michael@0 133 add_test(function test_arm_recursive()
michael@0 134 {
michael@0 135 let executed = false;
michael@0 136
michael@0 137 let deferredTask = new DeferredTask(function () {
michael@0 138 if (!executed) {
michael@0 139 executed = true;
michael@0 140 deferredTask.arm();
michael@0 141 } else {
michael@0 142 run_next_test();
michael@0 143 }
michael@0 144 }, 50);
michael@0 145
michael@0 146 deferredTask.arm();
michael@0 147 });
michael@0 148
michael@0 149 /**
michael@0 150 * Checks that calling "arm" while an asynchronous task is running waits until
michael@0 151 * the task is finished before restarting the delay.
michael@0 152 */
michael@0 153 add_test(function test_arm_async()
michael@0 154 {
michael@0 155 let finishedExecution = false;
michael@0 156 let finishedExecutionAgain = false;
michael@0 157
michael@0 158 // Create a task that will run later.
michael@0 159 let deferredTask = new DeferredTask(function () {
michael@0 160 yield promiseTimeout(4*T);
michael@0 161 if (!finishedExecution) {
michael@0 162 finishedExecution = true;
michael@0 163 } else if (!finishedExecutionAgain) {
michael@0 164 finishedExecutionAgain = true;
michael@0 165 }
michael@0 166 }, 2*T);
michael@0 167 deferredTask.arm();
michael@0 168
michael@0 169 // While the task is running, call "arm" again. This will result in a wait
michael@0 170 // of 2*T until the task finishes, then another 2*T for the normal task delay
michael@0 171 // specified on construction.
michael@0 172 do_timeout(4*T, function () {
michael@0 173 do_check_true(deferredTask.isRunning);
michael@0 174 do_check_false(finishedExecution);
michael@0 175 deferredTask.arm();
michael@0 176 });
michael@0 177
michael@0 178 // This will fail in case the task was started without waiting 2*T after it
michael@0 179 // has finished.
michael@0 180 do_timeout(7*T, function () {
michael@0 181 do_check_false(deferredTask.isRunning);
michael@0 182 do_check_true(finishedExecution);
michael@0 183 });
michael@0 184
michael@0 185 // This is in the middle of the second execution.
michael@0 186 do_timeout(10*T, function () {
michael@0 187 do_check_true(deferredTask.isRunning);
michael@0 188 do_check_false(finishedExecutionAgain);
michael@0 189 });
michael@0 190
michael@0 191 // Wait enough time to verify that the task was executed as expected.
michael@0 192 do_timeout(13*T, function () {
michael@0 193 do_check_false(deferredTask.isRunning);
michael@0 194 do_check_true(finishedExecutionAgain);
michael@0 195 run_next_test();
michael@0 196 });
michael@0 197 });
michael@0 198
michael@0 199 /**
michael@0 200 * Checks that an armed task can be disarmed.
michael@0 201 */
michael@0 202 add_test(function test_disarm()
michael@0 203 {
michael@0 204 // Create a task that will run later.
michael@0 205 let deferredTask = new DeferredTask(function () {
michael@0 206 do_throw("This task should not run.");
michael@0 207 }, 2*T);
michael@0 208 deferredTask.arm();
michael@0 209
michael@0 210 // Disable execution later, but before the task starts.
michael@0 211 do_timeout(1*T, () => deferredTask.disarm());
michael@0 212
michael@0 213 // Wait enough time to verify that the task did not run.
michael@0 214 do_timeout(3*T, run_next_test);
michael@0 215 });
michael@0 216
michael@0 217 /**
michael@0 218 * Checks that calling "disarm" allows the delay to be restarted.
michael@0 219 */
michael@0 220 add_test(function test_disarm_delay_restarted()
michael@0 221 {
michael@0 222 let executed = false;
michael@0 223
michael@0 224 let deferredTask = new DeferredTask(() => { executed = true; }, 4*T);
michael@0 225 deferredTask.arm();
michael@0 226
michael@0 227 do_timeout(2*T, function () {
michael@0 228 deferredTask.disarm();
michael@0 229 deferredTask.arm();
michael@0 230 });
michael@0 231
michael@0 232 do_timeout(5*T, function () {
michael@0 233 do_check_false(executed);
michael@0 234 });
michael@0 235
michael@0 236 do_timeout(7*T, function () {
michael@0 237 do_check_true(executed);
michael@0 238 run_next_test();
michael@0 239 });
michael@0 240 });
michael@0 241
michael@0 242 /**
michael@0 243 * Checks that calling "disarm" while an asynchronous task is running does not
michael@0 244 * prevent the task to finish.
michael@0 245 */
michael@0 246 add_test(function test_disarm_async()
michael@0 247 {
michael@0 248 let finishedExecution = false;
michael@0 249
michael@0 250 let deferredTask = new DeferredTask(function () {
michael@0 251 deferredTask.arm();
michael@0 252 yield promiseTimeout(2*T);
michael@0 253 finishedExecution = true;
michael@0 254 }, 1*T);
michael@0 255 deferredTask.arm();
michael@0 256
michael@0 257 do_timeout(2*T, function () {
michael@0 258 do_check_true(deferredTask.isRunning);
michael@0 259 do_check_true(deferredTask.isArmed);
michael@0 260 do_check_false(finishedExecution);
michael@0 261 deferredTask.disarm();
michael@0 262 });
michael@0 263
michael@0 264 do_timeout(4*T, function () {
michael@0 265 do_check_false(deferredTask.isRunning);
michael@0 266 do_check_false(deferredTask.isArmed);
michael@0 267 do_check_true(finishedExecution);
michael@0 268 run_next_test();
michael@0 269 });
michael@0 270 });
michael@0 271
michael@0 272 /**
michael@0 273 * Checks that calling "arm" immediately followed by "disarm" while an
michael@0 274 * asynchronous task is running does not cause it to run again.
michael@0 275 */
michael@0 276 add_test(function test_disarm_immediate_async()
michael@0 277 {
michael@0 278 let executed = false;
michael@0 279
michael@0 280 let deferredTask = new DeferredTask(function () {
michael@0 281 do_check_false(executed);
michael@0 282 executed = true;
michael@0 283 yield promiseTimeout(2*T);
michael@0 284 }, 1*T);
michael@0 285 deferredTask.arm();
michael@0 286
michael@0 287 do_timeout(2*T, function () {
michael@0 288 do_check_true(deferredTask.isRunning);
michael@0 289 do_check_false(deferredTask.isArmed);
michael@0 290 deferredTask.arm();
michael@0 291 deferredTask.disarm();
michael@0 292 });
michael@0 293
michael@0 294 do_timeout(4*T, function () {
michael@0 295 do_check_true(executed);
michael@0 296 do_check_false(deferredTask.isRunning);
michael@0 297 do_check_false(deferredTask.isArmed);
michael@0 298 run_next_test();
michael@0 299 });
michael@0 300 });
michael@0 301
michael@0 302 /**
michael@0 303 * Checks the isArmed and isRunning properties with a synchronous task.
michael@0 304 */
michael@0 305 add_test(function test_isArmed_isRunning()
michael@0 306 {
michael@0 307 let deferredTask = new DeferredTask(function () {
michael@0 308 do_check_true(deferredTask.isRunning);
michael@0 309 do_check_false(deferredTask.isArmed);
michael@0 310 deferredTask.arm();
michael@0 311 do_check_true(deferredTask.isArmed);
michael@0 312 deferredTask.disarm();
michael@0 313 do_check_false(deferredTask.isArmed);
michael@0 314 run_next_test();
michael@0 315 }, 50);
michael@0 316
michael@0 317 do_check_false(deferredTask.isArmed);
michael@0 318 deferredTask.arm();
michael@0 319 do_check_true(deferredTask.isArmed);
michael@0 320 do_check_false(deferredTask.isRunning);
michael@0 321 });
michael@0 322
michael@0 323 /**
michael@0 324 * Checks that the "finalize" method executes a synchronous task.
michael@0 325 */
michael@0 326 add_test(function test_finalize()
michael@0 327 {
michael@0 328 let executed = false;
michael@0 329 let timePassed = false;
michael@0 330
michael@0 331 let deferredTask = new DeferredTask(function () {
michael@0 332 do_check_false(timePassed);
michael@0 333 executed = true;
michael@0 334 }, 2*T);
michael@0 335 deferredTask.arm();
michael@0 336
michael@0 337 do_timeout(1*T, () => { timePassed = true; });
michael@0 338
michael@0 339 // This should trigger the immediate execution of the task.
michael@0 340 deferredTask.finalize().then(function () {
michael@0 341 do_check_true(executed);
michael@0 342 run_next_test();
michael@0 343 });
michael@0 344 });
michael@0 345
michael@0 346 /**
michael@0 347 * Checks that the "finalize" method executes the task again from start to
michael@0 348 * finish in case it is already running.
michael@0 349 */
michael@0 350 add_test(function test_finalize_executes_entirely()
michael@0 351 {
michael@0 352 let executed = false;
michael@0 353 let executedAgain = false;
michael@0 354 let timePassed = false;
michael@0 355
michael@0 356 let deferredTask = new DeferredTask(function () {
michael@0 357 // The first time, we arm the timer again and set up the finalization.
michael@0 358 if (!executed) {
michael@0 359 deferredTask.arm();
michael@0 360 do_check_true(deferredTask.isArmed);
michael@0 361 do_check_true(deferredTask.isRunning);
michael@0 362
michael@0 363 deferredTask.finalize().then(function () {
michael@0 364 // When we reach this point, the task must be finished.
michael@0 365 do_check_true(executedAgain);
michael@0 366 do_check_false(timePassed);
michael@0 367 do_check_false(deferredTask.isArmed);
michael@0 368 do_check_false(deferredTask.isRunning);
michael@0 369 run_next_test();
michael@0 370 });
michael@0 371
michael@0 372 // The second execution triggered by the finalization waits 1*T for the
michael@0 373 // current task to finish (see the timeout below), but then it must not
michael@0 374 // wait for the 2*T specified on construction as normal task delay. The
michael@0 375 // second execution will finish after the timeout below has passed again,
michael@0 376 // for a total of 2*T of wait time.
michael@0 377 do_timeout(3*T, () => { timePassed = true; });
michael@0 378 }
michael@0 379
michael@0 380 yield promiseTimeout(1*T);
michael@0 381
michael@0 382 // Just before finishing, indicate if we completed the second execution.
michael@0 383 if (executed) {
michael@0 384 do_check_true(deferredTask.isRunning);
michael@0 385 executedAgain = true;
michael@0 386 } else {
michael@0 387 executed = true;
michael@0 388 }
michael@0 389 }, 2*T);
michael@0 390
michael@0 391 deferredTask.arm();
michael@0 392 });

mercurial