summaryrefslogtreecommitdiffstats
path: root/addon-sdk/source/lib/sdk/test
diff options
context:
space:
mode:
Diffstat (limited to 'addon-sdk/source/lib/sdk/test')
-rw-r--r--addon-sdk/source/lib/sdk/test/assert.js366
-rw-r--r--addon-sdk/source/lib/sdk/test/harness.js645
-rw-r--r--addon-sdk/source/lib/sdk/test/httpd.js6
-rw-r--r--addon-sdk/source/lib/sdk/test/loader.js123
-rw-r--r--addon-sdk/source/lib/sdk/test/memory.js11
-rw-r--r--addon-sdk/source/lib/sdk/test/options.js23
-rw-r--r--addon-sdk/source/lib/sdk/test/runner.js131
-rw-r--r--addon-sdk/source/lib/sdk/test/utils.js199
8 files changed, 0 insertions, 1504 deletions
diff --git a/addon-sdk/source/lib/sdk/test/assert.js b/addon-sdk/source/lib/sdk/test/assert.js
deleted file mode 100644
index 8478c8414..000000000
--- a/addon-sdk/source/lib/sdk/test/assert.js
+++ /dev/null
@@ -1,366 +0,0 @@
-/* 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": "unstable"
-};
-
-const { isFunction, isNull, isObject, isString,
- isRegExp, isArray, isDate, isPrimitive,
- isUndefined, instanceOf, source } = require("../lang/type");
-
-/**
- * The `AssertionError` is defined in assert.
- * @extends Error
- * @example
- * new assert.AssertionError({
- * message: message,
- * actual: actual,
- * expected: expected
- * })
- */
-function AssertionError(options) {
- let assertionError = Object.create(AssertionError.prototype);
-
- if (isString(options))
- options = { message: options };
- if ("actual" in options)
- assertionError.actual = options.actual;
- if ("expected" in options)
- assertionError.expected = options.expected;
- if ("operator" in options)
- assertionError.operator = options.operator;
-
- assertionError.message = options.message;
- assertionError.stack = new Error().stack;
- return assertionError;
-}
-AssertionError.prototype = Object.create(Error.prototype, {
- constructor: { value: AssertionError },
- name: { value: "AssertionError", enumerable: true },
- toString: { value: function toString() {
- let value;
- if (this.message) {
- value = this.name + " : " + this.message;
- }
- else {
- value = [
- this.name + " : ",
- source(this.expected),
- this.operator,
- source(this.actual)
- ].join(" ");
- }
- return value;
- }}
-});
-exports.AssertionError = AssertionError;
-
-function Assert(logger) {
- let assert = Object.create(Assert.prototype, { _log: { value: logger }});
-
- assert.fail = assert.fail.bind(assert);
- assert.pass = assert.pass.bind(assert);
-
- return assert;
-}
-
-Assert.prototype = {
- fail: function fail(e) {
- if (!e || typeof(e) !== 'object') {
- this._log.fail(e);
- return;
- }
- let message = e.message;
- try {
- if ('operator' in e) {
- message += [
- " -",
- source(e.actual),
- e.operator,
- source(e.expected)
- ].join(" ");
- }
- }
- catch(e) {}
- this._log.fail(message);
- },
- pass: function pass(message) {
- this._log.pass(message);
- return true;
- },
- error: function error(e) {
- this._log.exception(e);
- },
- ok: function ok(value, message) {
- if (!!!value) {
- this.fail({
- actual: value,
- expected: true,
- message: message,
- operator: "=="
- });
- return false;
- }
-
- this.pass(message);
- return true;
- },
-
- /**
- * The equality assertion tests shallow, coercive equality with `==`.
- * @example
- * assert.equal(1, 1, "one is one");
- */
- equal: function equal(actual, expected, message) {
- if (actual == expected) {
- this.pass(message);
- return true;
- }
-
- this.fail({
- actual: actual,
- expected: expected,
- message: message,
- operator: "=="
- });
- return false;
- },
-
- /**
- * The non-equality assertion tests for whether two objects are not equal
- * with `!=`.
- * @example
- * assert.notEqual(1, 2, "one is not two");
- */
- notEqual: function notEqual(actual, expected, message) {
- if (actual != expected) {
- this.pass(message);
- return true;
- }
-
- this.fail({
- actual: actual,
- expected: expected,
- message: message,
- operator: "!=",
- });
- return false;
- },
-
- /**
- * The equivalence assertion tests a deep (with `===`) equality relation.
- * @example
- * assert.deepEqual({ a: "foo" }, { a: "foo" }, "equivalent objects")
- */
- deepEqual: function deepEqual(actual, expected, message) {
- if (isDeepEqual(actual, expected)) {
- this.pass(message);
- return true;
- }
-
- this.fail({
- actual: actual,
- expected: expected,
- message: message,
- operator: "deepEqual"
- });
- return false;
- },
-
- /**
- * The non-equivalence assertion tests for any deep (with `===`) inequality.
- * @example
- * assert.notDeepEqual({ a: "foo" }, Object.create({ a: "foo" }),
- * "object's inherit from different prototypes");
- */
- notDeepEqual: function notDeepEqual(actual, expected, message) {
- if (!isDeepEqual(actual, expected)) {
- this.pass(message);
- return true;
- }
-
- this.fail({
- actual: actual,
- expected: expected,
- message: message,
- operator: "notDeepEqual"
- });
- return false;
- },
-
- /**
- * The strict equality assertion tests strict equality, as determined by
- * `===`.
- * @example
- * assert.strictEqual(null, null, "`null` is `null`")
- */
- strictEqual: function strictEqual(actual, expected, message) {
- if (actual === expected) {
- this.pass(message);
- return true;
- }
-
- this.fail({
- actual: actual,
- expected: expected,
- message: message,
- operator: "==="
- });
- return false;
- },
-
- /**
- * The strict non-equality assertion tests for strict inequality, as
- * determined by `!==`.
- * @example
- * assert.notStrictEqual(null, undefined, "`null` is not `undefined`");
- */
- notStrictEqual: function notStrictEqual(actual, expected, message) {
- if (actual !== expected) {
- this.pass(message);
- return true;
- }
-
- this.fail({
- actual: actual,
- expected: expected,
- message: message,
- operator: "!=="
- });
- return false;
- },
-
- /**
- * The assertion whether or not given `block` throws an exception. If optional
- * `Error` argument is provided and it's type of function thrown error is
- * asserted to be an instance of it, if type of `Error` is string then message
- * of throw exception is asserted to contain it.
- * @param {Function} block
- * Function that is expected to throw.
- * @param {Error|RegExp} [Error]
- * Error constructor that is expected to be thrown or a string that
- * must be contained by a message of the thrown exception, or a RegExp
- * matching a message of the thrown exception.
- * @param {String} message
- * Description message
- *
- * @examples
- *
- * assert.throws(function block() {
- * doSomething(4)
- * }, "Object is expected", "Incorrect argument is passed");
- *
- * assert.throws(function block() {
- * Object.create(5)
- * }, TypeError, "TypeError is thrown");
- */
- throws: function throws(block, Error, message) {
- let threw = false;
- let exception = null;
-
- // If third argument is not provided and second argument is a string it
- // means that optional `Error` argument was not passed, so we shift
- // arguments.
- if (isString(Error) && isUndefined(message)) {
- message = Error;
- Error = undefined;
- }
-
- // Executing given `block`.
- try {
- block();
- }
- catch (e) {
- threw = true;
- exception = e;
- }
-
- // If exception was thrown and `Error` argument was not passed assert is
- // passed.
- if (threw && (isUndefined(Error) ||
- // If passed `Error` is RegExp using it's test method to
- // assert thrown exception message.
- (isRegExp(Error) && (Error.test(exception.message) || Error.test(exception.toString()))) ||
- // If passed `Error` is a constructor function testing if
- // thrown exception is an instance of it.
- (isFunction(Error) && instanceOf(exception, Error))))
- {
- this.pass(message);
- return true;
- }
-
- // Otherwise we report assertion failure.
- let failure = {
- message: message,
- operator: "matches"
- };
-
- if (exception) {
- failure.actual = exception.message || exception.toString();
- }
-
- if (Error) {
- failure.expected = Error.toString();
- }
-
- this.fail(failure);
- return false;
- }
-};
-exports.Assert = Assert;
-
-function isDeepEqual(actual, expected) {
- // 7.1. All identical values are equivalent, as determined by ===.
- if (actual === expected) {
- return true;
- }
-
- // 7.2. If the expected value is a Date object, the actual value is
- // equivalent if it is also a Date object that refers to the same time.
- else if (isDate(actual) && isDate(expected)) {
- return actual.getTime() === expected.getTime();
- }
-
- // XXX specification bug: this should be specified
- else if (isPrimitive(actual) || isPrimitive(expected)) {
- return expected === actual;
- }
-
- // 7.3. Other pairs that do not both pass typeof value == "object",
- // equivalence is determined by ==.
- else if (!isObject(actual) && !isObject(expected)) {
- return actual == expected;
- }
-
- // 7.4. For all other Object pairs, including Array objects, equivalence is
- // determined by having the same number of owned properties (as verified
- // with Object.prototype.hasOwnProperty.call), the same set of keys
- // (although not necessarily the same order), equivalent values for every
- // corresponding key, and an identical "prototype" property. Note: this
- // accounts for both named and indexed properties on Arrays.
- else {
- return actual.prototype === expected.prototype &&
- isEquivalent(actual, expected);
- }
-}
-
-function isEquivalent(a, b, stack) {
- let aKeys = Object.keys(a);
- let bKeys = Object.keys(b);
-
- return aKeys.length === bKeys.length &&
- isArrayEquivalent(aKeys.sort(), bKeys.sort()) &&
- aKeys.every(function(key) {
- return isDeepEqual(a[key], b[key], stack)
- });
-}
-
-function isArrayEquivalent(a, b, stack) {
- return isArray(a) && isArray(b) &&
- a.every(function(value, index) {
- return isDeepEqual(value, b[index]);
- });
-}
diff --git a/addon-sdk/source/lib/sdk/test/harness.js b/addon-sdk/source/lib/sdk/test/harness.js
deleted file mode 100644
index 1b31a1c79..000000000
--- a/addon-sdk/source/lib/sdk/test/harness.js
+++ /dev/null
@@ -1,645 +0,0 @@
-/* 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": "experimental"
-};
-
-const { Cc, Ci, Cu } = require("chrome");
-const { Loader } = require('./loader');
-const { serializeStack, parseStack } = require("toolkit/loader");
-const { setTimeout } = require('../timers');
-const { PlainTextConsole } = require("../console/plain-text");
-const { when: unload } = require("../system/unload");
-const { format, fromException } = require("../console/traceback");
-const system = require("../system");
-const { gc: gcPromise } = require('./memory');
-const { defer } = require('../core/promise');
-const { extend } = require('../core/heritage');
-
-// Trick manifest builder to make it think we need these modules ?
-const unit = require("../deprecated/unit-test");
-const test = require("../../test");
-const url = require("../url");
-
-function emptyPromise() {
- let { promise, resolve } = defer();
- resolve();
- return promise;
-}
-
-var cService = Cc['@mozilla.org/consoleservice;1'].getService(Ci.nsIConsoleService);
-
-// The console used to log messages
-var testConsole;
-
-// Cuddlefish loader in which we load and execute tests.
-var loader;
-
-// Function to call when we're done running tests.
-var onDone;
-
-// Function to print text to a console, w/o CR at the end.
-var print;
-
-// How many more times to run all tests.
-var iterationsLeft;
-
-// Whether to report memory profiling information.
-var profileMemory;
-
-// Whether we should stop as soon as a test reports a failure.
-var stopOnError;
-
-// Function to call to retrieve a list of tests to execute
-var findAndRunTests;
-
-// Combined information from all test runs.
-var results;
-
-// A list of the compartments and windows loaded after startup
-var startLeaks;
-
-// JSON serialization of last memory usage stats; we keep it stringified
-// so we don't actually change the memory usage stats (in terms of objects)
-// of the JSRuntime we're profiling.
-var lastMemoryUsage;
-
-function analyzeRawProfilingData(data) {
- var graph = data.graph;
- var shapes = {};
-
- // Convert keys in the graph from strings to ints.
- // TODO: Can we get rid of this ridiculousness?
- var newGraph = {};
- for (id in graph) {
- newGraph[parseInt(id)] = graph[id];
- }
- graph = newGraph;
-
- var modules = 0;
- var moduleIds = [];
- var moduleObjs = {UNKNOWN: 0};
- for (let name in data.namedObjects) {
- moduleObjs[name] = 0;
- moduleIds[data.namedObjects[name]] = name;
- modules++;
- }
-
- var count = 0;
- for (id in graph) {
- var parent = graph[id].parent;
- while (parent) {
- if (parent in moduleIds) {
- var name = moduleIds[parent];
- moduleObjs[name]++;
- break;
- }
- if (!(parent in graph)) {
- moduleObjs.UNKNOWN++;
- break;
- }
- parent = graph[parent].parent;
- }
- count++;
- }
-
- print("\nobject count is " + count + " in " + modules + " modules" +
- " (" + data.totalObjectCount + " across entire JS runtime)\n");
- if (lastMemoryUsage) {
- var last = JSON.parse(lastMemoryUsage);
- var diff = {
- moduleObjs: dictDiff(last.moduleObjs, moduleObjs),
- totalObjectClasses: dictDiff(last.totalObjectClasses,
- data.totalObjectClasses)
- };
-
- for (let name in diff.moduleObjs)
- print(" " + diff.moduleObjs[name] + " in " + name + "\n");
- for (let name in diff.totalObjectClasses)
- print(" " + diff.totalObjectClasses[name] + " instances of " +
- name + "\n");
- }
- lastMemoryUsage = JSON.stringify(
- {moduleObjs: moduleObjs,
- totalObjectClasses: data.totalObjectClasses}
- );
-}
-
-function dictDiff(last, curr) {
- var diff = {};
-
- for (let name in last) {
- var result = (curr[name] || 0) - last[name];
- if (result)
- diff[name] = (result > 0 ? "+" : "") + result;
- }
- for (let name in curr) {
- var result = curr[name] - (last[name] || 0);
- if (result)
- diff[name] = (result > 0 ? "+" : "") + result;
- }
- return diff;
-}
-
-function reportMemoryUsage() {
- if (!profileMemory) {
- return emptyPromise();
- }
-
- return gcPromise().then((() => {
- var mgr = Cc["@mozilla.org/memory-reporter-manager;1"]
- .getService(Ci.nsIMemoryReporterManager);
- let count = 0;
- function logReporter(process, path, kind, units, amount, description) {
- print(((++count == 1) ? "\n" : "") + description + ": " + amount + "\n");
- }
- mgr.getReportsForThisProcess(logReporter, null, /* anonymize = */ false);
- }));
-}
-
-var gWeakrefInfo;
-
-function checkMemory() {
- return gcPromise().then(_ => {
- let leaks = getPotentialLeaks();
-
- let compartmentURLs = Object.keys(leaks.compartments).filter(function(url) {
- return !(url in startLeaks.compartments);
- });
-
- let windowURLs = Object.keys(leaks.windows).filter(function(url) {
- return !(url in startLeaks.windows);
- });
-
- for (let url of compartmentURLs)
- console.warn("LEAKED", leaks.compartments[url]);
-
- for (let url of windowURLs)
- console.warn("LEAKED", leaks.windows[url]);
- }).then(showResults);
-}
-
-function showResults() {
- let { promise, resolve } = defer();
-
- if (gWeakrefInfo) {
- gWeakrefInfo.forEach(
- function(info) {
- var ref = info.weakref.get();
- if (ref !== null) {
- var data = ref.__url__ ? ref.__url__ : ref;
- var warning = data == "[object Object]"
- ? "[object " + data.constructor.name + "(" +
- Object.keys(data).join(", ") + ")]"
- : data;
- console.warn("LEAK", warning, info.bin);
- }
- }
- );
- }
-
- onDone(results);
-
- resolve();
- return promise;
-}
-
-function cleanup() {
- let coverObject = {};
- try {
- loader.unload();
-
- if (loader.globals.console.errorsLogged && !results.failed) {
- results.failed++;
- console.error("warnings and/or errors were logged.");
- }
-
- if (consoleListener.errorsLogged && !results.failed) {
- console.warn(consoleListener.errorsLogged + " " +
- "warnings or errors were logged to the " +
- "platform's nsIConsoleService, which could " +
- "be of no consequence; however, they could also " +
- "be indicative of aberrant behavior.");
- }
-
- // read the code coverage object, if it exists, from CoverJS-moz
- if (typeof loader.globals.global == "object") {
- coverObject = loader.globals.global['__$coverObject'] || {};
- }
-
- consoleListener.errorsLogged = 0;
- loader = null;
-
- consoleListener.unregister();
-
- Cu.forceGC();
- }
- catch (e) {
- results.failed++;
- console.error("unload.send() threw an exception.");
- console.exception(e);
- };
-
- setTimeout(require("./options").checkMemory ? checkMemory : showResults, 1);
-
- // dump the coverobject
- if (Object.keys(coverObject).length){
- const self = require('sdk/self');
- const {pathFor} = require("sdk/system");
- let file = require('sdk/io/file');
- const {env} = require('sdk/system/environment');
- console.log("CWD:", env.PWD);
- let out = file.join(env.PWD,'coverstats-'+self.id+'.json');
- console.log('coverstats:', out);
- let outfh = file.open(out,'w');
- outfh.write(JSON.stringify(coverObject,null,2));
- outfh.flush();
- outfh.close();
- }
-}
-
-function getPotentialLeaks() {
- Cu.forceGC();
-
- // Things we can assume are part of the platform and so aren't leaks
- let GOOD_BASE_URLS = [
- "chrome://",
- "resource:///",
- "resource://app/",
- "resource://gre/",
- "resource://gre-resources/",
- "resource://pdf.js/",
- "resource://pdf.js.components/",
- "resource://services-common/",
- "resource://services-crypto/",
- "resource://services-sync/"
- ];
-
- let ioService = Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService);
- let uri = ioService.newURI("chrome://global/content/", "UTF-8", null);
- let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
- getService(Ci.nsIChromeRegistry);
- uri = chromeReg.convertChromeURL(uri);
- let spec = uri.spec;
- let pos = spec.indexOf("!/");
- GOOD_BASE_URLS.push(spec.substring(0, pos + 2));
-
- let zoneRegExp = new RegExp("^explicit/js-non-window/zones/zone[^/]+/compartment\\((.+)\\)");
- let compartmentRegexp = new RegExp("^explicit/js-non-window/compartments/non-window-global/compartment\\((.+)\\)/");
- let compartmentDetails = new RegExp("^([^,]+)(?:, (.+?))?(?: \\(from: (.*)\\))?$");
- let windowRegexp = new RegExp("^explicit/window-objects/top\\((.*)\\)/active");
- let windowDetails = new RegExp("^(.*), id=.*$");
-
- function isPossibleLeak(item) {
- if (!item.location)
- return false;
-
- for (let url of GOOD_BASE_URLS) {
- if (item.location.substring(0, url.length) == url) {
- return false;
- }
- }
-
- return true;
- }
-
- let compartments = {};
- let windows = {};
- function logReporter(process, path, kind, units, amount, description) {
- let matches;
-
- if ((matches = compartmentRegexp.exec(path)) || (matches = zoneRegExp.exec(path))) {
- if (matches[1] in compartments)
- return;
-
- let details = compartmentDetails.exec(matches[1]);
- if (!details) {
- console.error("Unable to parse compartment detail " + matches[1]);
- return;
- }
-
- let item = {
- path: matches[1],
- principal: details[1],
- location: details[2] ? details[2].replace(/\\/g, "/") : undefined,
- source: details[3] ? details[3].split(" -> ").reverse() : undefined,
- toString: function() {
- return this.location;
- }
- };
-
- if (!isPossibleLeak(item))
- return;
-
- compartments[matches[1]] = item;
- return;
- }
-
- if ((matches = windowRegexp.exec(path))) {
- if (matches[1] in windows)
- return;
-
- let details = windowDetails.exec(matches[1]);
- if (!details) {
- console.error("Unable to parse window detail " + matches[1]);
- return;
- }
-
- let item = {
- path: matches[1],
- location: details[1].replace(/\\/g, "/"),
- source: [details[1].replace(/\\/g, "/")],
- toString: function() {
- return this.location;
- }
- };
-
- if (!isPossibleLeak(item))
- return;
-
- windows[matches[1]] = item;
- }
- }
-
- Cc["@mozilla.org/memory-reporter-manager;1"]
- .getService(Ci.nsIMemoryReporterManager)
- .getReportsForThisProcess(logReporter, null, /* anonymize = */ false);
-
- return { compartments: compartments, windows: windows };
-}
-
-function nextIteration(tests) {
- if (tests) {
- results.passed += tests.passed;
- results.failed += tests.failed;
-
- reportMemoryUsage().then(_ => {
- let testRun = [];
- for (let test of tests.testRunSummary) {
- let testCopy = {};
- for (let info in test) {
- testCopy[info] = test[info];
- }
- testRun.push(testCopy);
- }
-
- results.testRuns.push(testRun);
- iterationsLeft--;
-
- checkForEnd();
- })
- }
- else {
- checkForEnd();
- }
-}
-
-function checkForEnd() {
- if (iterationsLeft && (!stopOnError || results.failed == 0)) {
- // Pass the loader which has a hooked console that doesn't dispatch
- // errors to the JS console and avoid firing false alarm in our
- // console listener
- findAndRunTests(loader, nextIteration);
- }
- else {
- setTimeout(cleanup, 0);
- }
-}
-
-var POINTLESS_ERRORS = [
- 'Invalid chrome URI:',
- 'OpenGL LayerManager Initialized Succesfully.',
- '[JavaScript Error: "TelemetryStopwatch:',
- 'reference to undefined property',
- '[JavaScript Error: "The character encoding of the HTML document was ' +
- 'not declared.',
- '[Javascript Warning: "Error: Failed to preserve wrapper of wrapped ' +
- 'native weak map key',
- '[JavaScript Warning: "Duplicate resource declaration for',
- 'file: "chrome://browser/content/',
- 'file: "chrome://global/content/',
- '[JavaScript Warning: "The character encoding of a framed document was ' +
- 'not declared.',
- 'file: "chrome://browser/skin/'
-];
-
-// These are messages that will cause a test to fail if logged through the
-// console service
-var IMPORTANT_ERRORS = [
- 'Sending message that cannot be cloned. Are you trying to send an XPCOM object?',
-];
-
-var consoleListener = {
- registered: false,
-
- register: function() {
- if (this.registered)
- return;
- cService.registerListener(this);
- this.registered = true;
- },
-
- unregister: function() {
- if (!this.registered)
- return;
- cService.unregisterListener(this);
- this.registered = false;
- },
-
- errorsLogged: 0,
-
- observe: function(object) {
- if (!(object instanceof Ci.nsIScriptError))
- return;
- this.errorsLogged++;
- var message = object.QueryInterface(Ci.nsIConsoleMessage).message;
- if (IMPORTANT_ERRORS.find(msg => message.indexOf(msg) >= 0)) {
- testConsole.error(message);
- return;
- }
- var pointless = POINTLESS_ERRORS.filter(err => message.indexOf(err) >= 0);
- if (pointless.length == 0 && message)
- testConsole.log(message);
- }
-};
-
-function TestRunnerConsole(base, options) {
- let proto = extend(base, {
- errorsLogged: 0,
- warn: function warn() {
- this.errorsLogged++;
- base.warn.apply(base, arguments);
- },
- error: function error() {
- this.errorsLogged++;
- base.error.apply(base, arguments);
- },
- info: function info(first) {
- if (options.verbose)
- base.info.apply(base, arguments);
- else
- if (first == "pass:")
- print(".");
- },
- });
- return Object.create(proto);
-}
-
-function stringify(arg) {
- try {
- return String(arg);
- }
- catch(ex) {
- return "<toString() error>";
- }
-}
-
-function stringifyArgs(args) {
- return Array.map(args, stringify).join(" ");
-}
-
-function TestRunnerTinderboxConsole(base, options) {
- this.base = base;
- this.print = options.print;
- this.verbose = options.verbose;
- this.errorsLogged = 0;
-
- // Binding all the public methods to an instance so that they can be used
- // as callback / listener functions straightaway.
- this.log = this.log.bind(this);
- this.info = this.info.bind(this);
- this.warn = this.warn.bind(this);
- this.error = this.error.bind(this);
- this.debug = this.debug.bind(this);
- this.exception = this.exception.bind(this);
- this.trace = this.trace.bind(this);
-};
-
-TestRunnerTinderboxConsole.prototype = {
- testMessage: function testMessage(pass, expected, test, message) {
- let type = "TEST-";
- if (expected) {
- if (pass)
- type += "PASS";
- else
- type += "KNOWN-FAIL";
- }
- else {
- this.errorsLogged++;
- if (pass)
- type += "UNEXPECTED-PASS";
- else
- type += "UNEXPECTED-FAIL";
- }
-
- this.print(type + " | " + test + " | " + message + "\n");
- if (!expected)
- this.trace();
- },
-
- log: function log() {
- this.print("TEST-INFO | " + stringifyArgs(arguments) + "\n");
- },
-
- info: function info(first) {
- this.print("TEST-INFO | " + stringifyArgs(arguments) + "\n");
- },
-
- warn: function warn() {
- this.errorsLogged++;
- this.print("TEST-UNEXPECTED-FAIL | " + stringifyArgs(arguments) + "\n");
- },
-
- error: function error() {
- this.errorsLogged++;
- this.print("TEST-UNEXPECTED-FAIL | " + stringifyArgs(arguments) + "\n");
- this.base.error.apply(this.base, arguments);
- },
-
- debug: function debug() {
- this.print("TEST-INFO | " + stringifyArgs(arguments) + "\n");
- },
-
- exception: function exception(e) {
- this.print("An exception occurred.\n" +
- require("../console/traceback").format(e) + "\n" + e + "\n");
- },
-
- trace: function trace() {
- var traceback = require("../console/traceback");
- var stack = traceback.get();
- stack.splice(-1, 1);
- this.print("TEST-INFO | " + stringify(traceback.format(stack)) + "\n");
- }
-};
-
-var runTests = exports.runTests = function runTests(options) {
- iterationsLeft = options.iterations;
- profileMemory = options.profileMemory;
- stopOnError = options.stopOnError;
- onDone = options.onDone;
- print = options.print;
- findAndRunTests = options.findAndRunTests;
-
- results = {
- passed: 0,
- failed: 0,
- testRuns: []
- };
-
- try {
- consoleListener.register();
- print("Running tests on " + system.name + " " + system.version +
- "/Gecko " + system.platformVersion + " (Build " +
- system.build + ") (" + system.id + ") under " +
- system.platform + "/" + system.architecture + ".\n");
-
- if (options.parseable)
- testConsole = new TestRunnerTinderboxConsole(new PlainTextConsole(), options);
- else
- testConsole = new TestRunnerConsole(new PlainTextConsole(), options);
-
- loader = Loader(module, {
- console: testConsole,
- global: {} // useful for storing things like coverage testing.
- });
-
- // Load these before getting initial leak stats as they will still be in
- // memory when we check later
- require("../deprecated/unit-test");
- require("../deprecated/unit-test-finder");
- if (profileMemory)
- startLeaks = getPotentialLeaks();
-
- nextIteration();
- } catch (e) {
- let frames = fromException(e).reverse().reduce(function(frames, frame) {
- if (frame.fileName.split("/").pop() === "unit-test-finder.js")
- frames.done = true
- if (!frames.done) frames.push(frame)
-
- return frames
- }, [])
-
- let prototype = typeof(e) === "object" ? e.constructor.prototype :
- Error.prototype;
- let stack = serializeStack(frames.reverse());
-
- let error = Object.create(prototype, {
- message: { value: e.message, writable: true, configurable: true },
- fileName: { value: e.fileName, writable: true, configurable: true },
- lineNumber: { value: e.lineNumber, writable: true, configurable: true },
- stack: { value: stack, writable: true, configurable: true },
- toString: { value: () => String(e), writable: true, configurable: true },
- });
-
- print("Error: " + error + " \n " + format(error));
- onDone({passed: 0, failed: 1});
- }
-};
-
-unload(_ => consoleListener.unregister());
diff --git a/addon-sdk/source/lib/sdk/test/httpd.js b/addon-sdk/source/lib/sdk/test/httpd.js
deleted file mode 100644
index 218493924..000000000
--- a/addon-sdk/source/lib/sdk/test/httpd.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* 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/. */
-
-throw new Error(`This file was removed. A copy can be obtained from:
- https://github.com/mozilla/addon-sdk/blob/master/test/lib/httpd.js`);
diff --git a/addon-sdk/source/lib/sdk/test/loader.js b/addon-sdk/source/lib/sdk/test/loader.js
deleted file mode 100644
index 33ba2ca5a..000000000
--- a/addon-sdk/source/lib/sdk/test/loader.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/* 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";
-
-const { resolveURI, Require,
- unload, override, descriptor } = require('../../toolkit/loader');
-const { ensure } = require('../system/unload');
-const addonWindow = require('../addon/window');
-const { PlainTextConsole } = require('sdk/console/plain-text');
-
-var defaultGlobals = override(require('../system/globals'), {
- console: console
-});
-
-function CustomLoader(module, globals, packaging, overrides={}) {
- let options = packaging || require("@loader/options");
- options = override(options, {
- id: overrides.id || options.id,
- globals: override(defaultGlobals, globals || {}),
- modules: override(override(options.modules || {}, overrides.modules || {}), {
- 'sdk/addon/window': addonWindow
- })
- });
-
- let loaderModule = options.isNative ? '../../toolkit/loader' : '../loader/cuddlefish';
- let { Loader } = require(loaderModule);
- let loader = Loader(options);
- let wrapper = Object.create(loader, descriptor({
- require: Require(loader, module),
- sandbox: function(id) {
- let requirement = loader.resolve(id, module.id);
- if (!requirement)
- requirement = id;
- let uri = resolveURI(requirement, loader.mapping);
- return loader.sandboxes[uri];
- },
- unload: function(reason) {
- unload(loader, reason);
- }
- }));
- ensure(wrapper);
- return wrapper;
-};
-exports.Loader = CustomLoader;
-
-function HookedPlainTextConsole(hook, print, innerID) {
- this.log = hook.bind(null, "log", innerID);
- this.info = hook.bind(null, "info", innerID);
- this.warn = hook.bind(null, "warn", innerID);
- this.error = hook.bind(null, "error", innerID);
- this.debug = hook.bind(null, "debug", innerID);
- this.exception = hook.bind(null, "exception", innerID);
- this.time = hook.bind(null, "time", innerID);
- this.timeEnd = hook.bind(null, "timeEnd", innerID);
-
- this.__exposedProps__ = {
- log: "rw", info: "rw", warn: "rw", error: "rw", debug: "rw",
- exception: "rw", time: "rw", timeEnd: "rw"
- };
-}
-
-// Creates a custom loader instance whose console module is hooked in order
-// to avoid printing messages to the console, and instead, expose them in the
-// returned `messages` array attribute
-exports.LoaderWithHookedConsole = function (module, callback) {
- let messages = [];
- function hook(type, innerID, msg) {
- messages.push({ type: type, msg: msg, innerID: innerID });
- if (callback)
- callback(type, msg, innerID);
- }
-
- return {
- loader: CustomLoader(module, {
- console: new HookedPlainTextConsole(hook, null, null)
- }, null, {
- modules: {
- 'sdk/console/plain-text': {
- PlainTextConsole: HookedPlainTextConsole.bind(null, hook)
- }
- }
- }),
- messages: messages
- };
-}
-
-// Same than LoaderWithHookedConsole with lower level, instead we get what is
-// actually printed to the command line console
-exports.LoaderWithHookedConsole2 = function (module, callback) {
- let messages = [];
- return {
- loader: CustomLoader(module, {
- console: new PlainTextConsole(function (msg) {
- messages.push(msg);
- if (callback)
- callback(msg);
- })
- }),
- messages: messages
- };
-}
-
-// Creates a custom loader with a filtered console. The callback is passed every
-// console message type and message and if it returns false the message will
-// not be logged normally
-exports.LoaderWithFilteredConsole = function (module, callback) {
- function hook(type, innerID, msg) {
- if (callback && callback(type, msg, innerID) == false)
- return;
- console[type](msg);
- }
-
- return CustomLoader(module, {
- console: new HookedPlainTextConsole(hook, null, null)
- }, null, {
- modules: {
- 'sdk/console/plain-text': {
- PlainTextConsole: HookedPlainTextConsole.bind(null, hook)
- }
- }
- });
-}
diff --git a/addon-sdk/source/lib/sdk/test/memory.js b/addon-sdk/source/lib/sdk/test/memory.js
deleted file mode 100644
index bd1198bfe..000000000
--- a/addon-sdk/source/lib/sdk/test/memory.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/* 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';
-
-const { Cu } = require("chrome");
-
-function gc() {
- return new Promise(resolve => Cu.schedulePreciseGC(resolve));
-}
-exports.gc = gc;
diff --git a/addon-sdk/source/lib/sdk/test/options.js b/addon-sdk/source/lib/sdk/test/options.js
deleted file mode 100644
index 9bc611ca5..000000000
--- a/addon-sdk/source/lib/sdk/test/options.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* 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": "unstable"
-};
-
-const options = require("@test/options");
-const { id } = require("../self");
-const { get } = require("../preferences/service");
-
-const readPref = (key) => get("extensions." + id + ".sdk." + key);
-
-exports.iterations = readPref("test.iterations") || options.iterations;
-exports.filter = readPref("test.filter") || options.filter;
-exports.profileMemory = readPref("profile.memory") || options.profileMemory;
-exports.stopOnError = readPref("test.stop") || options.stopOnError;
-exports.keepOpen = readPref("test.keepOpen") || false;
-exports.verbose = (readPref("output.logLevel") == "verbose") || options.verbose;
-exports.parseable = (readPref("output.format") == "tbpl") || options.parseable;
-exports.checkMemory = readPref("profile.leaks") || options.check_memory;
diff --git a/addon-sdk/source/lib/sdk/test/runner.js b/addon-sdk/source/lib/sdk/test/runner.js
deleted file mode 100644
index ea37ac84f..000000000
--- a/addon-sdk/source/lib/sdk/test/runner.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/* 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": "experimental"
-};
-
-var { exit, stdout } = require("../system");
-var cfxArgs = require("../test/options");
-var events = require("../system/events");
-const { resolve } = require("../core/promise");
-
-function runTests(findAndRunTests) {
- var harness = require("./harness");
-
- function onDone(tests) {
- stdout.write("\n");
- var total = tests.passed + tests.failed;
- stdout.write(tests.passed + " of " + total + " tests passed.\n");
-
- events.emit("sdk:test:results", { data: JSON.stringify(tests) });
-
- if (tests.failed == 0) {
- if (tests.passed === 0)
- stdout.write("No tests were run\n");
- if (!cfxArgs.keepOpen)
- exit(0);
- } else {
- if (cfxArgs.verbose || cfxArgs.parseable)
- printFailedTests(tests, stdout.write);
- if (!cfxArgs.keepOpen)
- exit(1);
- }
- };
-
- // We may have to run test on next cycle, otherwise XPCOM components
- // are not correctly updated.
- // For ex: nsIFocusManager.getFocusedElementForWindow may throw
- // NS_ERROR_ILLEGAL_VALUE exception.
- require("../timers").setTimeout(_ => harness.runTests({
- findAndRunTests: findAndRunTests,
- iterations: cfxArgs.iterations || 1,
- filter: cfxArgs.filter,
- profileMemory: cfxArgs.profileMemory,
- stopOnError: cfxArgs.stopOnError,
- verbose: cfxArgs.verbose,
- parseable: cfxArgs.parseable,
- print: stdout.write,
- onDone: onDone
- }));
-}
-
-function printFailedTests(tests, print) {
- let iterationNumber = 0;
- let singleIteration = (tests.testRuns || []).length == 1;
- let padding = singleIteration ? "" : " ";
-
- print("\nThe following tests failed:\n");
-
- for (let testRun of tests.testRuns) {
- iterationNumber++;
-
- if (!singleIteration)
- print(" Iteration " + iterationNumber + ":\n");
-
- for (let test of testRun) {
- if (test.failed > 0) {
- print(padding + " " + test.name + ": " + test.errors +"\n");
- }
- }
- print("\n");
- }
-}
-
-function main() {
- var testsStarted = false;
-
- if (!testsStarted) {
- testsStarted = true;
- runTests(function findAndRunTests(loader, nextIteration) {
- loader.require("../deprecated/unit-test").findAndRunTests({
- testOutOfProcess: false,
- testInProcess: true,
- stopOnError: cfxArgs.stopOnError,
- filter: cfxArgs.filter,
- onDone: nextIteration
- });
- });
- }
-};
-
-if (require.main === module)
- main();
-
-exports.runTestsFromModule = function runTestsFromModule(module) {
- let id = module.id;
- // Make a copy of exports as it may already be frozen by module loader
- let exports = {};
- Object.keys(module.exports).forEach(key => {
- exports[key] = module.exports[key];
- });
-
- runTests(function findAndRunTests(loader, nextIteration) {
- // Consider that all these tests are CommonJS ones
- loader.require('../../test').run(exports);
-
- // Reproduce what is done in sdk/deprecated/unit-test-finder.findTests()
- let tests = [];
- for (let name of Object.keys(exports).sort()) {
- tests.push({
- setup: exports.setup,
- teardown: exports.teardown,
- testFunction: exports[name],
- name: id + "." + name
- });
- }
-
- // Reproduce what is done by unit-test.findAndRunTests()
- var { TestRunner } = loader.require("../deprecated/unit-test");
- var runner = new TestRunner();
- runner.startMany({
- tests: {
- getNext: () => resolve(tests.shift())
- },
- stopOnError: cfxArgs.stopOnError,
- onDone: nextIteration
- });
- });
-}
diff --git a/addon-sdk/source/lib/sdk/test/utils.js b/addon-sdk/source/lib/sdk/test/utils.js
deleted file mode 100644
index b01df67d4..000000000
--- a/addon-sdk/source/lib/sdk/test/utils.js
+++ /dev/null
@@ -1,199 +0,0 @@
-/* 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': 'unstable'
-};
-
-const { defer } = require('../core/promise');
-const { setInterval, clearInterval } = require('../timers');
-const { getTabs, closeTab } = require("../tabs/utils");
-const { windows: getWindows } = require("../window/utils");
-const { close: closeWindow } = require("../window/helpers");
-const { isGenerator } = require("../lang/type");
-const { env } = require("../system/environment");
-const { Task } = require("resource://gre/modules/Task.jsm");
-
-const getTestNames = (exports) =>
- Object.keys(exports).filter(name => /^test/.test(name));
-
-const isTestAsync = ({length}) => length > 1;
-const isHelperAsync = ({length}) => length > 2;
-
-/*
- * Takes an `exports` object of a test file and a function `beforeFn`
- * to be run before each test. `beforeFn` is called with a `name` string
- * as the first argument of the test name, and may specify a second
- * argument function `done` to indicate that this function should
- * resolve asynchronously
- */
-function before (exports, beforeFn) {
- getTestNames(exports).map(name => {
- let testFn = exports[name];
-
- // GENERATOR TESTS
- if (isGenerator(testFn) && isGenerator(beforeFn)) {
- exports[name] = function*(assert) {
- yield Task.spawn(beforeFn.bind(null, name, assert));
- yield Task.spawn(testFn.bind(null, assert));
- }
- }
- else if (isGenerator(testFn) && !isHelperAsync(beforeFn)) {
- exports[name] = function*(assert) {
- beforeFn(name, assert);
- yield Task.spawn(testFn.bind(null, assert));
- }
- }
- else if (isGenerator(testFn) && isHelperAsync(beforeFn)) {
- exports[name] = function*(assert) {
- yield new Promise(resolve => beforeFn(name, assert, resolve));
- yield Task.spawn(testFn.bind(null, assert));
- }
- }
- // SYNC TESTS
- else if (!isTestAsync(testFn) && isGenerator(beforeFn)) {
- exports[name] = function*(assert) {
- yield Task.spawn(beforeFn.bind(null, name, assert));
- testFn(assert);
- };
- }
- else if (!isTestAsync(testFn) && !isHelperAsync(beforeFn)) {
- exports[name] = function (assert) {
- beforeFn(name, assert);
- testFn(assert);
- };
- }
- else if (!isTestAsync(testFn) && isHelperAsync(beforeFn)) {
- exports[name] = function (assert, done) {
- beforeFn(name, assert, () => {
- testFn(assert);
- done();
- });
- };
- }
- // ASYNC TESTS
- else if (isTestAsync(testFn) && isGenerator(beforeFn)) {
- exports[name] = function*(assert) {
- yield Task.spawn(beforeFn.bind(null, name, assert));
- yield new Promise(resolve => testFn(assert, resolve));
- };
- }
- else if (isTestAsync(testFn) && !isHelperAsync(beforeFn)) {
- exports[name] = function (assert, done) {
- beforeFn(name, assert);
- testFn(assert, done);
- };
- }
- else if (isTestAsync(testFn) && isHelperAsync(beforeFn)) {
- exports[name] = function (assert, done) {
- beforeFn(name, assert, () => {
- testFn(assert, done);
- });
- };
- }
- });
-}
-exports.before = before;
-
-/*
- * Takes an `exports` object of a test file and a function `afterFn`
- * to be run after each test. `afterFn` is called with a `name` string
- * as the first argument of the test name, and may specify a second
- * argument function `done` to indicate that this function should
- * resolve asynchronously
- */
-function after (exports, afterFn) {
- getTestNames(exports).map(name => {
- let testFn = exports[name];
-
- // GENERATOR TESTS
- if (isGenerator(testFn) && isGenerator(afterFn)) {
- exports[name] = function*(assert) {
- yield Task.spawn(testFn.bind(null, assert));
- yield Task.spawn(afterFn.bind(null, name, assert));
- }
- }
- else if (isGenerator(testFn) && !isHelperAsync(afterFn)) {
- exports[name] = function*(assert) {
- yield Task.spawn(testFn.bind(null, assert));
- afterFn(name, assert);
- }
- }
- else if (isGenerator(testFn) && isHelperAsync(afterFn)) {
- exports[name] = function*(assert) {
- yield Task.spawn(testFn.bind(null, assert));
- yield new Promise(resolve => afterFn(name, assert, resolve));
- }
- }
- // SYNC TESTS
- else if (!isTestAsync(testFn) && isGenerator(afterFn)) {
- exports[name] = function*(assert) {
- testFn(assert);
- yield Task.spawn(afterFn.bind(null, name, assert));
- };
- }
- else if (!isTestAsync(testFn) && !isHelperAsync(afterFn)) {
- exports[name] = function (assert) {
- testFn(assert);
- afterFn(name, assert);
- };
- }
- else if (!isTestAsync(testFn) && isHelperAsync(afterFn)) {
- exports[name] = function (assert, done) {
- testFn(assert);
- afterFn(name, assert, done);
- };
- }
- // ASYNC TESTS
- else if (isTestAsync(testFn) && isGenerator(afterFn)) {
- exports[name] = function*(assert) {
- yield new Promise(resolve => testFn(assert, resolve));
- yield Task.spawn(afterFn.bind(null, name, assert));
- };
- }
- else if (isTestAsync(testFn) && !isHelperAsync(afterFn)) {
- exports[name] = function*(assert) {
- yield new Promise(resolve => testFn(assert, resolve));
- afterFn(name, assert);
- };
- }
- else if (isTestAsync(testFn) && isHelperAsync(afterFn)) {
- exports[name] = function*(assert) {
- yield new Promise(resolve => testFn(assert, resolve));
- yield new Promise(resolve => afterFn(name, assert, resolve));
- };
- }
- });
-}
-exports.after = after;
-
-function waitUntil (predicate, delay) {
- let { promise, resolve } = defer();
- let interval = setInterval(() => {
- if (!predicate()) return;
- clearInterval(interval);
- resolve();
- }, delay || 10);
- return promise;
-}
-exports.waitUntil = waitUntil;
-
-var cleanUI = function cleanUI() {
- let { promise, resolve } = defer();
-
- let windows = getWindows(null, { includePrivate: true });
- if (windows.length > 1) {
- return closeWindow(windows[1]).then(cleanUI);
- }
-
- getTabs(windows[0]).slice(1).forEach(closeTab);
-
- resolve();
-
- return promise;
-}
-exports.cleanUI = cleanUI;
-
-exports.isTravisCI = ("TRAVIS" in env && "CI" in env);