summaryrefslogtreecommitdiffstats
path: root/addon-sdk/source/lib/sdk/deprecated/unit-test-finder.js
diff options
context:
space:
mode:
Diffstat (limited to 'addon-sdk/source/lib/sdk/deprecated/unit-test-finder.js')
-rw-r--r--addon-sdk/source/lib/sdk/deprecated/unit-test-finder.js199
1 files changed, 199 insertions, 0 deletions
diff --git a/addon-sdk/source/lib/sdk/deprecated/unit-test-finder.js b/addon-sdk/source/lib/sdk/deprecated/unit-test-finder.js
new file mode 100644
index 000000000..e38629f45
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/deprecated/unit-test-finder.js
@@ -0,0 +1,199 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+"use strict";
+
+module.metadata = {
+ "stability": "deprecated"
+};
+
+const file = require("../io/file");
+const { Loader } = require("../test/loader");
+
+const { isNative } = require('@loader/options');
+
+const cuddlefish = isNative ? require("toolkit/loader") : require("../loader/cuddlefish");
+
+const { defer, resolve } = require("../core/promise");
+const { getAddon } = require("../addon/installer");
+const { id } = require("sdk/self");
+const { newURI } = require('sdk/url/utils');
+const { getZipReader } = require("../zip/utils");
+
+const { Cc, Ci, Cu } = require("chrome");
+const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
+var ios = Cc['@mozilla.org/network/io-service;1']
+ .getService(Ci.nsIIOService);
+
+const CFX_TEST_REGEX = /(([^\/]+\/)(?:lib\/)?)?(tests?\/test-[^\.\/]+)\.js$/;
+const JPM_TEST_REGEX = /^()(tests?\/test-[^\.\/]+)\.js$/;
+
+const { mapcat, map, filter, fromEnumerator } = require("sdk/util/sequence");
+
+const toFile = x => x.QueryInterface(Ci.nsIFile);
+const isTestFile = ({leafName}) => leafName.substr(0, 5) == "test-" && leafName.substr(-3, 3) == ".js";
+const getFileURI = x => ios.newFileURI(x).spec;
+
+const getDirectoryEntries = file => map(toFile, fromEnumerator(_ => file.directoryEntries));
+const getTestFiles = directory => filter(isTestFile, getDirectoryEntries(directory));
+const getTestURIs = directory => map(getFileURI, getTestFiles(directory));
+
+const isDirectory = x => x.isDirectory();
+const getTestEntries = directory => mapcat(entry =>
+ /^tests?$/.test(entry.leafName) ? getTestURIs(entry) : getTestEntries(entry),
+ filter(isDirectory, getDirectoryEntries(directory)));
+
+const removeDups = (array) => array.reduce((result, value) => {
+ if (value != result[result.length - 1]) {
+ result.push(value);
+ }
+ return result;
+}, []);
+
+const getSuites = function getSuites({ id, filter }) {
+ const TEST_REGEX = isNative ? JPM_TEST_REGEX : CFX_TEST_REGEX;
+
+ return getAddon(id).then(addon => {
+ let fileURI = addon.getResourceURI("tests/");
+ let isPacked = fileURI.scheme == "jar";
+ let xpiURI = addon.getResourceURI();
+ let file = xpiURI.QueryInterface(Ci.nsIFileURL).file;
+ let suites = [];
+ let addEntry = (entry) => {
+ if (filter(entry) && TEST_REGEX.test(entry)) {
+ let suite = (isNative ? "./" : "") + (RegExp.$2 || "") + RegExp.$3;
+ suites.push(suite);
+ }
+ }
+
+ if (isPacked) {
+ return getZipReader(file).then(zip => {
+ let entries = zip.findEntries(null);
+ while (entries.hasMore()) {
+ let entry = entries.getNext();
+ addEntry(entry);
+ }
+ zip.close();
+
+ // sort and remove dups
+ suites = removeDups(suites.sort());
+ return suites;
+ })
+ }
+ else {
+ let tests = [...getTestEntries(file)];
+ let rootURI = addon.getResourceURI("/");
+ tests.forEach((entry) => {
+ addEntry(entry.replace(rootURI.spec, ""));
+ });
+ }
+
+ // sort and remove dups
+ suites = removeDups(suites.sort());
+ return suites;
+ });
+}
+exports.getSuites = getSuites;
+
+const makeFilters = function makeFilters(options) {
+ options = options || {};
+
+ // A filter string is {fileNameRegex}[:{testNameRegex}] - ie, a colon
+ // optionally separates a regex for the test fileName from a regex for the
+ // testName.
+ if (options.filter) {
+ let colonPos = options.filter.indexOf(':');
+ let filterFileRegex, filterNameRegex;
+
+ if (colonPos === -1) {
+ filterFileRegex = new RegExp(options.filter);
+ filterNameRegex = { test: () => true }
+ }
+ else {
+ filterFileRegex = new RegExp(options.filter.substr(0, colonPos));
+ filterNameRegex = new RegExp(options.filter.substr(colonPos + 1));
+ }
+
+ return {
+ fileFilter: (name) => filterFileRegex.test(name),
+ testFilter: (name) => filterNameRegex.test(name)
+ }
+ }
+
+ return {
+ fileFilter: () => true,
+ testFilter: () => true
+ };
+}
+exports.makeFilters = makeFilters;
+
+var loader = Loader(module);
+const NOT_TESTS = ['setup', 'teardown'];
+
+var TestFinder = exports.TestFinder = function TestFinder(options) {
+ this.filter = options.filter;
+ this.testInProcess = options.testInProcess === false ? false : true;
+ this.testOutOfProcess = options.testOutOfProcess === true ? true : false;
+};
+
+TestFinder.prototype = {
+ findTests: function findTests() {
+ let { fileFilter, testFilter } = makeFilters({ filter: this.filter });
+
+ return getSuites({ id: id, filter: fileFilter }).then(suites => {
+ let testsRemaining = [];
+
+ let getNextTest = () => {
+ if (testsRemaining.length) {
+ return testsRemaining.shift();
+ }
+
+ if (!suites.length) {
+ return null;
+ }
+
+ let suite = suites.shift();
+
+ // Load each test file as a main module in its own loader instance
+ // `suite` is defined by cuddlefish/manifest.py:ManifestBuilder.build
+ let suiteModule;
+
+ try {
+ suiteModule = cuddlefish.main(loader, suite);
+ }
+ catch (e) {
+ if (/Unsupported Application/i.test(e.message)) {
+ // If `Unsupported Application` error thrown during test,
+ // skip the test suite
+ suiteModule = {
+ 'test suite skipped': assert => assert.pass(e.message)
+ };
+ }
+ else {
+ console.exception(e);
+ throw e;
+ }
+ }
+
+ if (this.testInProcess) {
+ for (let name of Object.keys(suiteModule).sort()) {
+ if (NOT_TESTS.indexOf(name) === -1 && testFilter(name)) {
+ testsRemaining.push({
+ setup: suiteModule.setup,
+ teardown: suiteModule.teardown,
+ testFunction: suiteModule[name],
+ name: suite + "." + name
+ });
+ }
+ }
+ }
+
+ return getNextTest();
+ };
+
+ return {
+ getNext: () => resolve(getNextTest())
+ };
+ });
+ }
+};