2014-09-22 22:08:06 +04:00
|
|
|
/* -*- js-indent-level: 2; tab-width: 2; indent-tabs-mode: nil -*- */
|
|
|
|
const TEST_PACKAGE = "chrome://mochitests/content/";
|
2014-11-06 23:16:15 +03:00
|
|
|
|
|
|
|
// Make sure to use the real add-on ID to get the e10s shims activated
|
|
|
|
const TEST_ID = "mochikit@mozilla.org";
|
2014-09-22 22:08:06 +04:00
|
|
|
|
|
|
|
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");
|
|
|
|
|
|
|
|
// Start the tests after the window has been displayed
|
|
|
|
window.addEventListener("load", function testOnLoad() {
|
|
|
|
window.removeEventListener("load", testOnLoad);
|
|
|
|
window.addEventListener("MozAfterPaint", function testOnMozAfterPaint() {
|
|
|
|
window.removeEventListener("MozAfterPaint", testOnMozAfterPaint);
|
|
|
|
setTimeout(testInit, 0);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// Tests a single module
|
2014-11-06 23:16:15 +03:00
|
|
|
function testModule(require, { url, expected }) {
|
2014-09-22 22:08:06 +04:00
|
|
|
return new Promise(resolve => {
|
|
|
|
let path = url.substring(TEST_PACKAGE.length);
|
|
|
|
|
|
|
|
const { stdout } = require("sdk/system");
|
|
|
|
|
|
|
|
const { runTests } = require("sdk/test/harness");
|
|
|
|
const loaderModule = require("toolkit/loader");
|
|
|
|
const options = require("sdk/test/options");
|
|
|
|
|
|
|
|
function findAndRunTests(loader, nextIteration) {
|
|
|
|
const { TestRunner } = loaderModule.main(loader, "sdk/deprecated/unit-test");
|
|
|
|
|
|
|
|
const NOT_TESTS = ['setup', 'teardown'];
|
|
|
|
var runner = new TestRunner();
|
|
|
|
|
|
|
|
let tests = [];
|
|
|
|
|
|
|
|
let suiteModule;
|
|
|
|
try {
|
|
|
|
dump("TEST-INFO: " + path + " | Loading test module\n");
|
|
|
|
suiteModule = loaderModule.main(loader, "tests/" + path.substring(0, path.length - 3));
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
// If `Unsupported Application` error thrown during test,
|
|
|
|
// skip the test suite
|
|
|
|
suiteModule = {
|
|
|
|
'test suite skipped': assert => assert.pass(e.message)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let name of Object.keys(suiteModule).sort()) {
|
|
|
|
if (NOT_TESTS.indexOf(name) != -1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
tests.push({
|
|
|
|
setup: suiteModule.setup,
|
|
|
|
teardown: suiteModule.teardown,
|
|
|
|
testFunction: suiteModule[name],
|
|
|
|
name: path + "." + name
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
runner.startMany({
|
|
|
|
tests: {
|
|
|
|
getNext: () => Promise.resolve(tests.shift())
|
|
|
|
},
|
|
|
|
stopOnError: options.stopOnError,
|
|
|
|
onDone: nextIteration
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
runTests({
|
|
|
|
findAndRunTests: findAndRunTests,
|
|
|
|
iterations: options.iterations,
|
|
|
|
filter: options.filter,
|
|
|
|
profileMemory: options.profileMemory,
|
|
|
|
stopOnError: options.stopOnError,
|
|
|
|
verbose: options.verbose,
|
|
|
|
parseable: options.parseable,
|
|
|
|
print: stdout.write,
|
|
|
|
onDone: resolve
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sets the test prefs
|
|
|
|
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);
|
|
|
|
|
2014-11-28 11:44:12 +03:00
|
|
|
// Need to set this very early, otherwise the false value gets cached in
|
|
|
|
// DOM bindings code.
|
|
|
|
Services.prefs.setBoolPref("dom.indexedDB.experimental", true);
|
|
|
|
|
2014-09-22 22:08:06 +04:00
|
|
|
// Get the list of tests to run
|
|
|
|
let config = readConfig();
|
|
|
|
getTestList(config, function(links) {
|
|
|
|
try {
|
|
|
|
let fileNames = [];
|
|
|
|
let fileNameRegexp = /test-.+\.js$/;
|
|
|
|
arrayOfTestFiles(links, fileNames, fileNameRegexp);
|
|
|
|
|
|
|
|
if (config.startAt || config.endAt) {
|
|
|
|
fileNames = skipTests(fileNames, config.startAt, config.endAt);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The SDK assumes it is being run from resource URIs
|
|
|
|
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
|
|
|
|
let realPath = chromeReg.convertChromeURL(Services.io.newURI(TEST_PACKAGE, null, null));
|
|
|
|
let resProtocol = Cc["@mozilla.org/network/protocol;1?name=resource"].getService(Ci.nsIResProtocolHandler);
|
|
|
|
resProtocol.setSubstitution("jetpack-package-tests", realPath);
|
|
|
|
|
|
|
|
// Set the test options
|
|
|
|
const options = {
|
|
|
|
test: {
|
|
|
|
iterations: config.runUntilFailure ? config.repeat : 1,
|
|
|
|
stop: false,
|
|
|
|
keepOpen: true,
|
|
|
|
},
|
|
|
|
profile: {
|
|
|
|
memory: false,
|
|
|
|
leaks: false,
|
|
|
|
},
|
|
|
|
output: {
|
|
|
|
logLevel: "verbose",
|
|
|
|
format: "tbpl",
|
|
|
|
},
|
2014-11-17 20:58:08 +03:00
|
|
|
console: {
|
|
|
|
logLevel: "info",
|
|
|
|
},
|
2014-09-22 22:08:06 +04:00
|
|
|
}
|
|
|
|
setPrefs("extensions." + TEST_ID + ".sdk", options);
|
|
|
|
|
|
|
|
// Override the SDK modules if necessary
|
|
|
|
let sdkpath = "resource://gre/modules/commonjs/";
|
|
|
|
try {
|
|
|
|
let sdklibs = Services.prefs.getCharPref("extensions.sdk.path");
|
|
|
|
// sdkpath is a file path, make it a URI and map a resource URI to it
|
|
|
|
let sdkfile = Cc["@mozilla.org/file/local;1"].
|
|
|
|
createInstance(Ci.nsIFile);
|
|
|
|
sdkfile.initWithPath(sdklibs);
|
|
|
|
let sdkuri = Services.io.newFileURI(sdkfile);
|
|
|
|
resProtocol.setSubstitution("jetpack-modules", sdkuri);
|
|
|
|
sdkpath = "resource://jetpack-modules/";
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
// Stick with the built-in modules
|
|
|
|
}
|
|
|
|
|
|
|
|
const paths = {
|
|
|
|
"": sdkpath,
|
|
|
|
"tests/": "resource://jetpack-package-tests/",
|
|
|
|
};
|
|
|
|
|
|
|
|
// Create the base module loader to load the test harness
|
|
|
|
const loaderID = "toolkit/loader";
|
|
|
|
const loaderURI = paths[""] + loaderID + ".js";
|
|
|
|
const loaderModule = Cu.import(loaderURI, {}).Loader;
|
|
|
|
|
|
|
|
const modules = {};
|
|
|
|
|
|
|
|
// Manually set the loader's module cache to include itself;
|
|
|
|
// which otherwise fails due to lack of `Components`.
|
|
|
|
modules[loaderID] = loaderModule;
|
|
|
|
modules["@test/options"] = {};
|
|
|
|
|
|
|
|
let loader = loaderModule.Loader({
|
|
|
|
id: TEST_ID,
|
|
|
|
name: "addon-sdk",
|
|
|
|
version: "1.0",
|
|
|
|
loadReason: "install",
|
|
|
|
paths: paths,
|
|
|
|
modules: modules,
|
|
|
|
isNative: true,
|
|
|
|
rootURI: paths["tests/"],
|
|
|
|
prefixURI: paths["tests/"],
|
|
|
|
metadata: {},
|
|
|
|
});
|
|
|
|
|
|
|
|
const module = loaderModule.Module(loaderID, loaderURI);
|
|
|
|
const require = loaderModule.Require(loader, module);
|
|
|
|
|
|
|
|
// Wait until the add-on window is ready
|
|
|
|
require("sdk/addon/window").ready.then(() => {
|
|
|
|
let passed = 0;
|
|
|
|
let failed = 0;
|
|
|
|
|
|
|
|
function finish() {
|
|
|
|
if (passed + failed == 0) {
|
|
|
|
dump("TEST-UNEXPECTED-FAIL | jetpack-package-harness.js | " +
|
2015-06-05 20:28:29 +03:00
|
|
|
"No tests to run. Did you pass invalid test_paths?\n");
|
2014-09-22 22:08:06 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
dump("Jetpack Package Test Summary\n");
|
|
|
|
dump("\tPassed: " + passed + "\n" +
|
|
|
|
"\tFailed: " + failed + "\n" +
|
|
|
|
"\tTodo: 0\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config.closeWhenDone) {
|
|
|
|
require("sdk/system").exit(failed == 0 ? 0 : 1);
|
|
|
|
}
|
2015-03-26 21:51:57 +03:00
|
|
|
else {
|
|
|
|
loaderModule.unload(loader, "shutdown");
|
|
|
|
}
|
2014-09-22 22:08:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
function testNextModule() {
|
|
|
|
if (fileNames.length == 0)
|
|
|
|
return finish();
|
|
|
|
|
|
|
|
let filename = fileNames.shift();
|
|
|
|
testModule(require, filename).then(tests => {
|
|
|
|
passed += tests.passed;
|
|
|
|
failed += tests.failed;
|
|
|
|
}).then(testNextModule);
|
|
|
|
}
|
|
|
|
|
|
|
|
testNextModule();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
dump("TEST-UNEXPECTED-FAIL: jetpack-package-harness.js | error starting test harness (" + e + ")\n");
|
|
|
|
dump(e.stack);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|