Issue #439 - Remove tests from toolkit/

This commit is contained in:
Matt A. Tobin 2020-02-25 15:07:00 -05:00 • committed by Roy Tam
commit e5bacc6f6e
2362 changed files with 95 additions and 246993 deletions

View file

@ -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')

View file

@ -1,7 +0,0 @@
"use strict";
module.exports = {
"extends": [
"../../../../../testing/xpcshell/xpcshell.eslintrc.js"
]
};

View file

@ -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);
}

View file

@ -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");
});

View file

@ -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");
});

View file

@ -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);
}
}
}

View file

@ -1,8 +0,0 @@
[DEFAULT]
head=head.js
tail=
skip-if = toolkit == 'android'
[test_AsyncShutdown.js]
[test_AsyncShutdown_leave_uncaught.js]
[test_converters.js]