mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
ecab1de927
jetpack-addon-harness.js runs in a browser window scope so it already has the setTimeout functions available to it. Loading Timer.jsm overrides the DOM timer functions with those from Timer.jsm. Any other code that used setTimeout previously will have timer IDs from the DOM functions which don't match those in Timer.jsm. If this other code attempts to clear a timer it can then end up clearing an unrelated timer. In the intermittent failure here the browser-thumbnails code manages to clear the timer that is waiting to resolve the promise that makes tests continue. I've also added an additional timer that throws an exception and so ends tests if the add-on uninstall doesn't actually complete in a reasonable time as well as removing the add-on listener.
246 lines
7.7 KiB
JavaScript
246 lines
7.7 KiB
JavaScript
/* -*- js-indent-level: 2; tab-width: 2; indent-tabs-mode: nil -*- */
|
|
var gConfig;
|
|
|
|
if (Cc === undefined) {
|
|
var Cc = Components.classes;
|
|
var Ci = Components.interfaces;
|
|
var Cu = Components.utils;
|
|
}
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
Cu.import("resource://gre/modules/Task.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
|
"resource://gre/modules/Services.jsm");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
|
|
"resource://gre/modules/AddonManager.jsm");
|
|
|
|
// How long to wait for an add-on to uninstall before aborting
|
|
const MAX_UNINSTALL_TIME = 10000;
|
|
setTimeout(testInit, 0);
|
|
|
|
var sdkpath = null;
|
|
|
|
// Strip off the chrome prefix to get the actual path of the test directory
|
|
function realPath(chrome) {
|
|
return chrome.substring("chrome://mochitests/content/jetpack-addon/".length)
|
|
.replace(".xpi", "");
|
|
}
|
|
|
|
// Installs a single add-on returning a promise for when install is completed
|
|
function installAddon(url) {
|
|
return new Promise(function(resolve, reject) {
|
|
AddonManager.getInstallForURL(url, function(install) {
|
|
install.addListener({
|
|
onDownloadEnded: function(install) {
|
|
// Set add-on's test options
|
|
const options = {
|
|
test: {
|
|
iterations: 1,
|
|
stop: false,
|
|
keepOpen: true,
|
|
},
|
|
profile: {
|
|
memory: false,
|
|
leaks: false,
|
|
},
|
|
output: {
|
|
logLevel: "verbose",
|
|
format: "tbpl",
|
|
},
|
|
console: {
|
|
logLevel: "info",
|
|
},
|
|
}
|
|
setPrefs("extensions." + install.addon.id + ".sdk", options);
|
|
|
|
// If necessary override the add-ons module paths to point somewhere
|
|
// else
|
|
if (sdkpath) {
|
|
let paths = {}
|
|
for (let path of ["dev", "diffpatcher", "framescript", "method", "node", "sdk", "toolkit"]) {
|
|
paths[path] = sdkpath + path;
|
|
}
|
|
setPrefs("extensions.modules." + install.addon.id + ".path", paths);
|
|
}
|
|
},
|
|
|
|
onInstallEnded: function(install, addon) {
|
|
resolve(addon);
|
|
},
|
|
|
|
onDownloadCancelled: function(install) {
|
|
reject("Download cancelled: " + install.error);
|
|
},
|
|
|
|
onDownloadFailed: function(install) {
|
|
reject("Download failed: " + install.error);
|
|
},
|
|
|
|
onInstallCancelled: function(install) {
|
|
reject("Install cancelled: " + install.error);
|
|
},
|
|
|
|
onInstallFailed: function(install) {
|
|
reject("Install failed: " + install.error);
|
|
}
|
|
});
|
|
|
|
install.install();
|
|
}, "application/x-xpinstall");
|
|
});
|
|
}
|
|
|
|
// Uninstalls an add-on returning a promise for when it is gone
|
|
function uninstallAddon(oldAddon) {
|
|
return new Promise(function(resolve, reject) {
|
|
AddonManager.addAddonListener({
|
|
onUninstalled: function(addon) {
|
|
if (addon.id != oldAddon.id)
|
|
return;
|
|
|
|
AddonManager.removeAddonListener(this);
|
|
|
|
dump("TEST-INFO | jetpack-addon-harness.js | Uninstalled test add-on " + addon.id + "\n");
|
|
|
|
// Some add-ons do async work on uninstall, we must wait for that to
|
|
// complete
|
|
setTimeout(resolve, 500);
|
|
}
|
|
});
|
|
|
|
oldAddon.uninstall();
|
|
|
|
// The uninstall should happen quickly, if not throw an exception
|
|
setTimeout(() => {
|
|
reject(new Error(`Addon ${oldAddon.id} failed to uninstall in a timely fashion.`));
|
|
}, MAX_UNINSTALL_TIME);
|
|
});
|
|
}
|
|
|
|
// Waits for a test add-on to signal it has completed its tests
|
|
function waitForResults() {
|
|
return new Promise(function(resolve, reject) {
|
|
Services.obs.addObserver(function(subject, topic, data) {
|
|
Services.obs.removeObserver(arguments.callee, "sdk:test:results");
|
|
|
|
resolve(JSON.parse(data));
|
|
}, "sdk:test:results", false);
|
|
});
|
|
}
|
|
|
|
// Runs tests for the add-on available at URL.
|
|
var testAddon = Task.async(function*({ url }) {
|
|
dump("TEST-INFO | jetpack-addon-harness.js | Installing test add-on " + realPath(url) + "\n");
|
|
let addon = yield installAddon(url);
|
|
|
|
let results = yield waitForResults();
|
|
|
|
dump("TEST-INFO | jetpack-addon-harness.js | Uninstalling test add-on " + addon.id + "\n");
|
|
yield uninstallAddon(addon);
|
|
|
|
dump("TEST-INFO | jetpack-addon-harness.js | Testing add-on " + realPath(url) + " is complete\n");
|
|
return results;
|
|
});
|
|
|
|
// Sets a set of prefs for test add-ons
|
|
function setPrefs(root, options) {
|
|
Object.keys(options).forEach(id => {
|
|
const key = root + "." + id;
|
|
const value = options[id]
|
|
const type = typeof(value);
|
|
|
|
value === null ? void(0) :
|
|
value === undefined ? void(0) :
|
|
type === "boolean" ? Services.prefs.setBoolPref(key, value) :
|
|
type === "string" ? Services.prefs.setCharPref(key, value) :
|
|
type === "number" ? Services.prefs.setIntPref(key, parseInt(value)) :
|
|
type === "object" ? setPrefs(key, value) :
|
|
void(0);
|
|
});
|
|
}
|
|
|
|
function testInit() {
|
|
// Make sure to run the test harness for the first opened window only
|
|
if (Services.prefs.prefHasUserValue("testing.jetpackTestHarness.running"))
|
|
return;
|
|
|
|
Services.prefs.setBoolPref("testing.jetpackTestHarness.running", true);
|
|
|
|
// Get the list of tests to run
|
|
let config = readConfig();
|
|
getTestList(config, function(links) {
|
|
try {
|
|
let fileNames = [];
|
|
let fileNameRegexp = /.+\.xpi$/;
|
|
arrayOfTestFiles(links, fileNames, fileNameRegexp);
|
|
|
|
if (config.startAt || config.endAt) {
|
|
fileNames = skipTests(fileNames, config.startAt, config.endAt);
|
|
}
|
|
|
|
// Override the SDK modules if necessary
|
|
try {
|
|
let sdklibs = Services.prefs.getCharPref("extensions.sdk.path");
|
|
// sdkpath is a file path, make it a URI
|
|
let sdkfile = Cc["@mozilla.org/file/local;1"].
|
|
createInstance(Ci.nsIFile);
|
|
sdkfile.initWithPath(sdklibs);
|
|
sdkpath = Services.io.newFileURI(sdkfile).spec;
|
|
}
|
|
catch (e) {
|
|
// Stick with the built-in modules
|
|
}
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
|
|
function finish() {
|
|
if (passed + failed == 0) {
|
|
dump("TEST-UNEXPECTED-FAIL | jetpack-addon-harness.js | " +
|
|
"No tests to run. Did you pass invalid test_paths?\n");
|
|
}
|
|
else {
|
|
dump("Jetpack Addon Test Summary\n");
|
|
dump("\tPassed: " + passed + "\n" +
|
|
"\tFailed: " + failed + "\n" +
|
|
"\tTodo: 0\n");
|
|
}
|
|
|
|
if (config.closeWhenDone) {
|
|
dump("TEST-INFO | jetpack-addon-harness.js | Shutting down.\n");
|
|
|
|
const appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].
|
|
getService(Ci.nsIAppStartup);
|
|
appStartup.quit(appStartup.eAttemptQuit);
|
|
}
|
|
}
|
|
|
|
function testNextAddon() {
|
|
if (fileNames.length == 0)
|
|
return finish();
|
|
|
|
let filename = fileNames.shift();
|
|
dump("TEST-INFO | jetpack-addon-harness.js | Starting test add-on " + realPath(filename.url) + "\n");
|
|
testAddon(filename).then(results => {
|
|
passed += results.passed;
|
|
failed += results.failed;
|
|
}).then(testNextAddon, error => {
|
|
// If something went wrong during the test then a previous test add-on
|
|
// may still be installed, this leaves us in an unexpected state so
|
|
// probably best to just abandon testing at this point
|
|
failed++;
|
|
dump("TEST-UNEXPECTED-FAIL | jetpack-addon-harness.js | Error testing " + realPath(filename.url) + ": " + error + "\n");
|
|
finish();
|
|
});
|
|
}
|
|
|
|
testNextAddon();
|
|
}
|
|
catch (e) {
|
|
dump("TEST-UNEXPECTED-FAIL | jetpack-addon-harness.js | error starting test harness (" + e + ")\n");
|
|
dump(e.stack);
|
|
}
|
|
});
|
|
}
|