summaryrefslogtreecommitdiff
path: root/toolkit/components/asyncshutdown
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/asyncshutdown')
-rw-r--r--toolkit/components/asyncshutdown/moz.build14
-rw-r--r--toolkit/components/asyncshutdown/tests/xpcshell/.eslintrc.js7
-rw-r--r--toolkit/components/asyncshutdown/tests/xpcshell/head.js174
-rw-r--r--toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown.js194
-rw-r--r--toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown_leave_uncaught.js96
-rw-r--r--toolkit/components/asyncshutdown/tests/xpcshell/test_converters.js88
-rw-r--r--toolkit/components/asyncshutdown/tests/xpcshell/xpcshell.ini8
7 files changed, 2 insertions, 579 deletions
diff --git a/toolkit/components/asyncshutdown/moz.build b/toolkit/components/asyncshutdown/moz.build
index 79a4c44c70..0051c97a01 100644
--- a/toolkit/components/asyncshutdown/moz.build
+++ b/toolkit/components/asyncshutdown/moz.build
@@ -4,22 +4,12 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
-
XPIDL_MODULE = 'toolkit_asyncshutdown'
+XPIDL_SOURCES += ['nsIAsyncShutdown.idl']
-XPIDL_SOURCES += [
- 'nsIAsyncShutdown.idl',
-]
-
-EXTRA_JS_MODULES += [
- 'AsyncShutdown.jsm',
-]
+EXTRA_JS_MODULES += ['AsyncShutdown.jsm']
EXTRA_COMPONENTS += [
'nsAsyncShutdown.js',
'nsAsyncShutdown.manifest',
]
-
-with Files('**'):
- BUG_COMPONENT = ('Toolkit', 'Async Tooling')
diff --git a/toolkit/components/asyncshutdown/tests/xpcshell/.eslintrc.js b/toolkit/components/asyncshutdown/tests/xpcshell/.eslintrc.js
deleted file mode 100644
index d35787cd2c..0000000000
--- a/toolkit/components/asyncshutdown/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
- "extends": [
- "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
- ]
-};
diff --git a/toolkit/components/asyncshutdown/tests/xpcshell/head.js b/toolkit/components/asyncshutdown/tests/xpcshell/head.js
deleted file mode 100644
index 9de489808d..0000000000
--- a/toolkit/components/asyncshutdown/tests/xpcshell/head.js
+++ /dev/null
@@ -1,174 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-"use strict";
-
-var Cu = Components.utils;
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cr = Components.results;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/AsyncShutdown.jsm");
-
-var asyncShutdownService = Cc["@mozilla.org/async-shutdown-service;1"].
- getService(Ci.nsIAsyncShutdownService);
-
-
-Services.prefs.setBoolPref("toolkit.asyncshutdown.testing", true);
-
-/**
- * Utility function used to provide the same API for various sources
- * of async shutdown barriers.
- *
- * @param {string} kind One of
- * - "phase" to test an AsyncShutdown phase;
- * - "barrier" to test an instance of AsyncShutdown.Barrier;
- * - "xpcom-barrier" to test an instance of nsIAsyncShutdownBarrier;
- * - "xpcom-barrier-unwrapped" to test the field `jsclient` of a nsIAsyncShutdownClient.
- *
- * @return An object with the following methods:
- * - addBlocker() - the same method as AsyncShutdown phases and barrier clients
- * - wait() - trigger the resolution of the lock
- */
-function makeLock(kind) {
- if (kind == "phase") {
- let topic = "test-Phase-" + ++makeLock.counter;
- let phase = AsyncShutdown._getPhase(topic);
- return {
- addBlocker: function(...args) {
- return phase.addBlocker(...args);
- },
- removeBlocker: function(blocker) {
- return phase.removeBlocker(blocker);
- },
- wait: function() {
- Services.obs.notifyObservers(null, topic, null);
- return Promise.resolve();
- }
- };
- } else if (kind == "barrier") {
- let name = "test-Barrier-" + ++makeLock.counter;
- let barrier = new AsyncShutdown.Barrier(name);
- return {
- addBlocker: barrier.client.addBlocker,
- removeBlocker: barrier.client.removeBlocker,
- wait: function() {
- return barrier.wait();
- }
- };
- } else if (kind == "xpcom-barrier") {
- let name = "test-xpcom-Barrier-" + ++makeLock.counter;
- let barrier = asyncShutdownService.makeBarrier(name);
- return {
- addBlocker: function(blockerName, condition, state) {
- if (condition == null) {
- // Slight trick as `null` or `undefined` cannot be used as keys
- // for `xpcomMap`. Note that this has no incidence on the result
- // of the test as the XPCOM interface imposes that the condition
- // is a method, so it cannot be `null`/`undefined`.
- condition = "<this case can't happen with the xpcom interface>";
- }
- let blocker = makeLock.xpcomMap.get(condition);
- if (!blocker) {
- blocker = {
- name: blockerName,
- state: state,
- blockShutdown: function(aBarrierClient) {
- return Task.spawn(function*() {
- try {
- if (typeof condition == "function") {
- yield Promise.resolve(condition());
- } else {
- yield Promise.resolve(condition);
- }
- } finally {
- aBarrierClient.removeBlocker(blocker);
- }
- });
- },
- };
- makeLock.xpcomMap.set(condition, blocker);
- }
- let {fileName, lineNumber, stack} = (new Error());
- return barrier.client.addBlocker(blocker, fileName, lineNumber, stack);
- },
- removeBlocker: function(condition) {
- let blocker = makeLock.xpcomMap.get(condition);
- if (!blocker) {
- return;
- }
- barrier.client.removeBlocker(blocker);
- },
- wait: function() {
- return new Promise(resolve => {
- barrier.wait(resolve);
- });
- }
- };
- } else if ("unwrapped-xpcom-barrier") {
- let name = "unwrapped-xpcom-barrier-" + ++makeLock.counter;
- let barrier = asyncShutdownService.makeBarrier(name);
- let client = barrier.client.jsclient;
- return {
- addBlocker: client.addBlocker,
- removeBlocker: client.removeBlocker,
- wait: function() {
- return new Promise(resolve => {
- barrier.wait(resolve);
- });
- }
- };
- }
- throw new TypeError("Unknown kind " + kind);
-}
-makeLock.counter = 0;
-makeLock.xpcomMap = new Map(); // Note: Not a WeakMap as we wish to handle non-gc-able keys (e.g. strings)
-
-/**
- * An asynchronous task that takes several ticks to complete.
- *
- * @param {*=} resolution The value with which the resulting promise will be
- * resolved once the task is complete. This may be a rejected promise,
- * in which case the resulting promise will itself be rejected.
- * @param {object=} outResult An object modified by side-effect during the task.
- * Initially, its field |isFinished| is set to |false|. Once the task is
- * complete, its field |isFinished| is set to |true|.
- *
- * @return {promise} A promise fulfilled once the task is complete
- */
-function longRunningAsyncTask(resolution = undefined, outResult = {}) {
- outResult.isFinished = false;
- if (!("countFinished" in outResult)) {
- outResult.countFinished = 0;
- }
- let deferred = Promise.defer();
- do_timeout(100, function() {
- ++outResult.countFinished;
- outResult.isFinished = true;
- deferred.resolve(resolution);
- });
- return deferred.promise;
-}
-
-function get_exn(f) {
- try {
- f();
- return null;
- } catch (ex) {
- return ex;
- }
-}
-
-function do_check_exn(exn, constructor) {
- do_check_neq(exn, null);
- if (exn.name == constructor) {
- do_check_eq(exn.constructor.name, constructor);
- return;
- }
- do_print("Wrong error constructor");
- do_print(exn.constructor.name);
- do_print(exn.stack);
- do_check_true(false);
-}
diff --git a/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown.js b/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown.js
deleted file mode 100644
index f1aebc3ad2..0000000000
--- a/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown.js
+++ /dev/null
@@ -1,194 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-"use strict";
-
-Cu.import("resource://gre/modules/PromiseUtils.jsm", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_task(function* test_no_condition() {
- for (let kind of ["phase", "barrier", "xpcom-barrier", "xpcom-barrier-unwrapped"]) {
- do_print("Testing a barrier with no condition (" + kind + ")");
- let lock = makeLock(kind);
- yield lock.wait();
- do_print("Barrier with no condition didn't lock");
- }
-});
-
-add_task(function* test_phase_various_failures() {
- for (let kind of ["phase", "barrier", "xpcom-barrier", "xpcom-barrier-unwrapped"]) {
- do_print("Kind: " + kind);
- // Testing with wrong arguments
- let lock = makeLock(kind);
-
- Assert.throws(() => lock.addBlocker(), /TypeError|NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS/);
- Assert.throws(() => lock.addBlocker(null, true), /TypeError|NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS/);
-
- if (kind != "xpcom-barrier") {
- // xpcom-barrier actually expects a string in that position
- Assert.throws(() => lock.addBlocker("Test 2", () => true, "not a function"), /TypeError/);
- }
-
- // Attempting to add a blocker after we are done waiting
- yield lock.wait();
- Assert.throws(() => lock.addBlocker("Test 3", () => true), /is finished/);
- }
-});
-
-add_task(function* test_reentrant() {
- do_print("Ensure that we can call addBlocker from within a blocker");
-
- for (let kind of ["phase", "barrier", "xpcom-barrier", "xpcom-barrier-unwrapped"]) {
- do_print("Kind: " + kind);
- let lock = makeLock(kind);
-
- let deferredOuter = PromiseUtils.defer();
- let deferredInner = PromiseUtils.defer();
- let deferredBlockInner = PromiseUtils.defer();
-
- lock.addBlocker("Outer blocker", () => {
- do_print("Entering outer blocker");
- deferredOuter.resolve();
- lock.addBlocker("Inner blocker", () => {
- do_print("Entering inner blocker");
- deferredInner.resolve();
- return deferredBlockInner.promise;
- });
- });
-
- // Note that phase-style locks spin the event loop and do not return from
- // `lock.wait()` until after all blockers have been resolved. Therefore,
- // to be able to test them, we need to dispatch the following steps to the
- // event loop before calling `lock.wait()`, which we do by forcing
- // a Promise.resolve().
- //
- let promiseSteps = Task.spawn(function* () {
- yield Promise.resolve();
-
- do_print("Waiting until we have entered the outer blocker");
- yield deferredOuter.promise;
-
- do_print("Waiting until we have entered the inner blocker");
- yield deferredInner.promise;
-
- do_print("Allowing the lock to resolve")
- deferredBlockInner.resolve();
- });
-
- do_print("Starting wait");
- yield lock.wait();
-
- do_print("Waiting until all steps have been walked");
- yield promiseSteps;
- }
-});
-
-
-add_task(function* test_phase_removeBlocker() {
- do_print("Testing that we can call removeBlocker before, during and after the call to wait()");
-
- for (let kind of ["phase", "barrier", "xpcom-barrier", "xpcom-barrier-unwrapped"]) {
-
- do_print("Switching to kind " + kind);
- do_print("Attempt to add then remove a blocker before wait()");
- let lock = makeLock(kind);
- let blocker = () => {
- do_print("This promise will never be resolved");
- return Promise.defer().promise;
- };
-
- lock.addBlocker("Wait forever", blocker);
- let do_remove_blocker = function(aLock, aBlocker, aShouldRemove) {
- do_print("Attempting to remove blocker " + aBlocker + ", expecting result " + aShouldRemove);
- if (kind == "xpcom-barrier") {
- // The xpcom variant always returns `undefined`, so we can't
- // check its result.
- aLock.removeBlocker(aBlocker);
- return;
- }
- do_check_eq(aLock.removeBlocker(aBlocker), aShouldRemove);
- };
- do_remove_blocker(lock, blocker, true);
- do_remove_blocker(lock, blocker, false);
- do_print("Attempt to remove non-registered blockers before wait()");
- do_remove_blocker(lock, "foo", false);
- do_remove_blocker(lock, null, false);
- do_print("Waiting (should lift immediately)");
- yield lock.wait();
-
- do_print("Attempt to add a blocker then remove it during wait()");
- lock = makeLock(kind);
- let blockers = [
- () => {
- do_print("This blocker will self-destruct");
- do_remove_blocker(lock, blockers[0], true);
- return Promise.defer().promise;
- },
- () => {
- do_print("This blocker will self-destruct twice");
- do_remove_blocker(lock, blockers[1], true);
- do_remove_blocker(lock, blockers[1], false);
- return Promise.defer().promise;
- },
- () => {
- do_print("Attempt to remove non-registered blockers during wait()");
- do_remove_blocker(lock, "foo", false);
- do_remove_blocker(lock, null, false);
- }
- ];
- for (let i in blockers) {
- lock.addBlocker("Wait forever again: " + i, blockers[i]);
- }
- do_print("Waiting (should lift very quickly)");
- yield lock.wait();
- do_remove_blocker(lock, blockers[0], false);
-
-
- do_print("Attempt to remove a blocker after wait");
- lock = makeLock(kind);
- blocker = Promise.resolve.bind(Promise);
- yield lock.wait();
- do_remove_blocker(lock, blocker, false);
-
- do_print("Attempt to remove non-registered blocker after wait()");
- do_remove_blocker(lock, "foo", false);
- do_remove_blocker(lock, null, false);
- }
-
-});
-
-add_task(function* test_state() {
- do_print("Testing information contained in `state`");
-
- let BLOCKER_NAME = "test_state blocker " + Math.random();
-
- // Set up the barrier. Note that we cannot test `barrier.state`
- // immediately, as it initially contains "Not started"
- let barrier = new AsyncShutdown.Barrier("test_filename");
- let deferred = Promise.defer();
- let {filename, lineNumber} = Components.stack;
- barrier.client.addBlocker(BLOCKER_NAME,
- function() {
- return deferred.promise;
- });
-
- let promiseDone = barrier.wait();
-
- // Now that we have called `wait()`, the state contains interesting things
- let state = barrier.state[0];
- do_print("State: " + JSON.stringify(barrier.state, null, "\t"));
- Assert.equal(state.filename, filename);
- Assert.equal(state.lineNumber, lineNumber + 1);
- Assert.equal(state.name, BLOCKER_NAME);
- Assert.ok(state.stack.some(x => x.includes("test_state")), "The stack contains the caller function's name");
- Assert.ok(state.stack.some(x => x.includes(filename)), "The stack contains the calling file's name");
-
- deferred.resolve();
- yield promiseDone;
-});
-
-add_task(function*() {
- Services.prefs.clearUserPref("toolkit.asyncshutdown.testing");
-});
diff --git a/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown_leave_uncaught.js b/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown_leave_uncaught.js
deleted file mode 100644
index 33da1f53fb..0000000000
--- a/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown_leave_uncaught.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-"use strict";
-
-//
-// This file contains tests that need to leave uncaught asynchronous
-// errors. If your test catches all its asynchronous errors, please
-// put it in another file.
-//
-
-Promise.Debugging.clearUncaughtErrorObservers();
-
-function run_test() {
- run_next_test();
-}
-
-add_task(function* test_phase_simple_async() {
- do_print("Testing various combinations of a phase with a single condition");
- for (let kind of ["phase", "barrier", "xpcom-barrier", "xpcom-barrier-unwrapped"]) {
- for (let arg of [undefined, null, "foo", 100, new Error("BOOM")]) {
- for (let resolution of [arg, Promise.reject(arg)]) {
- for (let success of [false, true]) {
- for (let state of [[null],
- [],
- [() => "some state"],
- [function() {
- throw new Error("State BOOM"); }],
- [function() {
- return {
- toJSON: function() {
- throw new Error("State.toJSON BOOM");
- }
- };
- }]]) {
- // Asynchronous phase
- do_print("Asynchronous test with " + arg + ", " + resolution + ", " + kind);
- let lock = makeLock(kind);
- let outParam = { isFinished: false };
- lock.addBlocker(
- "Async test",
- function() {
- if (success) {
- return longRunningAsyncTask(resolution, outParam);
- }
- throw resolution;
- },
- ...state
- );
- do_check_false(outParam.isFinished);
- yield lock.wait();
- do_check_eq(outParam.isFinished, success);
- }
- }
-
- // Synchronous phase - just test that we don't throw/freeze
- do_print("Synchronous test with " + arg + ", " + resolution + ", " + kind);
- let lock = makeLock(kind);
- lock.addBlocker(
- "Sync test",
- resolution
- );
- yield lock.wait();
- }
- }
- }
-});
-
-add_task(function* test_phase_many() {
- do_print("Testing various combinations of a phase with many conditions");
- for (let kind of ["phase", "barrier", "xpcom-barrier", "xpcom-barrier-unwrapped"]) {
- let lock = makeLock(kind);
- let outParams = [];
- for (let arg of [undefined, null, "foo", 100, new Error("BOOM")]) {
- for (let resolve of [true, false]) {
- do_print("Testing with " + kind + ", " + arg + ", " + resolve);
- let resolution = resolve ? arg : Promise.reject(arg);
- let outParam = { isFinished: false };
- lock.addBlocker(
- "Test " + Math.random(),
- () => longRunningAsyncTask(resolution, outParam)
- );
- }
- }
- do_check_true(outParams.every((x) => !x.isFinished));
- yield lock.wait();
- do_check_true(outParams.every((x) => x.isFinished));
- }
-});
-
-
-
-
-add_task(function*() {
- Services.prefs.clearUserPref("toolkit.asyncshutdown.testing");
-});
-
diff --git a/toolkit/components/asyncshutdown/tests/xpcshell/test_converters.js b/toolkit/components/asyncshutdown/tests/xpcshell/test_converters.js
deleted file mode 100644
index c6c9231871..0000000000
--- a/toolkit/components/asyncshutdown/tests/xpcshell/test_converters.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-"use strict";
-
-/**
- * Test conversion between nsIPropertyBag and JS values.
- */
-
-var PropertyBagConverter = asyncShutdownService.wrappedJSObject._propertyBagConverter;
-
-function run_test() {
- test_conversions();
-}
-
-function normalize(obj) {
- if (obj == null || typeof obj != "object") {
- return obj;
- }
- if (Array.isArray(obj)) {
- return obj.map(normalize);
- }
- let result = {};
- for (let k of Object.keys(obj).sort()) {
- result[k] = normalize(obj[k]);
- }
- return result;
-}
-
-function test_conversions() {
- const SAMPLES = [
- // Simple values
- 1,
- true,
- "string",
- null,
-
- // Objects
- {
- a: 1,
- b: true,
- c: "string",
- d:.5,
- e: [2, false, "another string", .3],
- f: [],
- g: {
- a2: 1,
- b2: true,
- c2: "string",
- d2:.5,
- e2: [2, false, "another string", .3],
- f2: [],
- g2: [{
- a3: 1,
- b3: true,
- c3: "string",
- d3:.5,
- e3: [2, false, "another string", .3],
- f3: [],
- g3: {}
- }]
- }
- }];
-
- for (let sample of SAMPLES) {
- let stringified = JSON.stringify(normalize(sample), null, "\t");
- do_print("Testing conversions of " + stringified);
- let rewrites = [sample];
- for (let i = 1; i < 3; ++i) {
- let source = rewrites[i - 1];
- let bag = PropertyBagConverter.fromValue(source);
- do_print(" => " + bag);
- if (source == null) {
- Assert.ok(bag == null, "The bag is null");
- } else if (typeof source == "object") {
- Assert.ok(bag instanceof Ci.nsIPropertyBag, "The bag is a property bag");
- } else {
- Assert.ok(typeof bag != "object", "The bag is not an object");
- }
- let dest = PropertyBagConverter.toValue(bag);
- let restringified = JSON.stringify(normalize(dest), null, "\t");
- do_print("Comparing");
- do_print(stringified);
- do_print(restringified);
- Assert.deepEqual(sample, dest, "Testing after " + i + " conversions");
- rewrites.push(dest);
- }
- }
-}
diff --git a/toolkit/components/asyncshutdown/tests/xpcshell/xpcshell.ini b/toolkit/components/asyncshutdown/tests/xpcshell/xpcshell.ini
deleted file mode 100644
index f573955bc9..0000000000
--- a/toolkit/components/asyncshutdown/tests/xpcshell/xpcshell.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[DEFAULT]
-head=head.js
-tail=
-skip-if = toolkit == 'android'
-
-[test_AsyncShutdown.js]
-[test_AsyncShutdown_leave_uncaught.js]
-[test_converters.js]