From 75139375b76cb277546da2429d8e983ca6758f61 Mon Sep 17 00:00:00 2001 From: Rogan Creswick Date: Wed, 2 Jan 2013 14:56:40 -0800 Subject: added addon-sdk-1.7, without any changes --- .../packages/test-harness/lib/harness.js | 324 +++++++++++++++++++++ .../packages/test-harness/lib/run-tests.js | 101 +++++++ 2 files changed, 425 insertions(+) create mode 100644 tools/addon-sdk-1.7/packages/test-harness/lib/harness.js create mode 100644 tools/addon-sdk-1.7/packages/test-harness/lib/run-tests.js (limited to 'tools/addon-sdk-1.7/packages/test-harness/lib') diff --git a/tools/addon-sdk-1.7/packages/test-harness/lib/harness.js b/tools/addon-sdk-1.7/packages/test-harness/lib/harness.js new file mode 100644 index 0000000..e1b1105 --- /dev/null +++ b/tools/addon-sdk-1.7/packages/test-harness/lib/harness.js @@ -0,0 +1,324 @@ +/* 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 { Cc,Ci } = require("chrome"); +const { Loader } = require("@loader") +const memory = require('api-utils/memory'); + +var cService = Cc['@mozilla.org/consoleservice;1'].getService() + .QueryInterface(Ci.nsIConsoleService); + +// Cuddlefish loader for the sandbox in which we load and +// execute tests. +var sandbox; + +// 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; + +// Only tests in files whose names match this regexp filter will be run. +var filter; + +// Whether to report memory profiling information. +var profileMemory; + +// Whether we should stop as soon as a test reports a failure. +var stopOnError; + +// Combined information from all test runs. +var results = { + passed: 0, + failed: 0, + testRuns: [] +}; + +// 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() { + memory.gc(); + + var mgr = Cc["@mozilla.org/memory-reporter-manager;1"] + .getService(Ci.nsIMemoryReporterManager); + var reporters = mgr.enumerateReporters(); + if (reporters.hasMoreElements()) + print("\n"); + while (reporters.hasMoreElements()) { + var reporter = reporters.getNext(); + reporter.QueryInterface(Ci.nsIMemoryReporter); + print(reporter.description + ": " + reporter.memoryUsed + "\n"); + } + + var weakrefs = [info.weakref.get() + for each (info in memory.getObjects())]; + weakrefs = [weakref for each (weakref in weakrefs) if (weakref)]; + print("Tracked memory objects in testing sandbox: " + + weakrefs.length + "\n"); +} + +var gWeakrefInfo; + +function showResults() { + memory.gc(); + + 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 + "(" + + [p for (p in data)].join(", ") + ")]" + : data; + console.warn("LEAK", warning, info.bin); + } + } + ); + } + + print("\n"); + var total = results.passed + results.failed; + print(results.passed + " of " + total + " tests passed.\n"); + onDone(results); +} + +function cleanup() { + try { + for (let name in sandbox.modules) + memory.track(sandbox.modules[name], + "module global scope: " + name); + memory.track(sandbox, "Cuddlefish Loader"); + + if (profileMemory) { + gWeakrefInfo = [{ weakref: info.weakref, bin: info.bin } + for each (info in memory.getObjects())]; + } + + sandbox.unload(); + + if (sandbox.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."); + } + + consoleListener.errorsLogged = 0; + sandbox = null; + + memory.gc(); + } catch (e) { + results.failed++; + console.error("unload.send() threw an exception."); + console.exception(e); + }; + + require("api-utils/timer").setTimeout(showResults, 1); +} + +function nextIteration(tests) { + if (tests) { + results.passed += tests.passed; + results.failed += tests.failed; + + if (profileMemory) + reportMemoryUsage(); + + let testRun = []; + for each (let test in tests.testRunSummary) { + let testCopy = {}; + for (let info in test) { + testCopy[info] = test[info]; + } + testRun.push(testCopy); + } + + results.testRuns.push(testRun); + iterationsLeft--; + } + + if (iterationsLeft && (!stopOnError || results.failed == 0)) { + let require = Loader.require.bind(sandbox, module.path); + require("api-utils/unit-test").findAndRunTests({ + testOutOfProcess: require('@packaging').enableE10s, + testInProcess: true, + stopOnError: stopOnError, + filter: filter, + onDone: nextIteration + }); + } + else { + require("api-utils/timer").setTimeout(cleanup, 0); + } +} + +var POINTLESS_ERRORS = [ + "Invalid chrome URI:", + "OpenGL LayerManager Initialized Succesfully." +]; + +var consoleListener = { + errorsLogged: 0, + observe: function(object) { + if (!(object instanceof Ci.nsIScriptError)) + return; + this.errorsLogged++; + var message = object.QueryInterface(Ci.nsIConsoleMessage).message; + var pointless = [err for each (err in POINTLESS_ERRORS) + if (message.indexOf(err) == 0)]; + if (pointless.length == 0 && message) + print("console: " + message + "\n"); + } +}; + +function TestRunnerConsole(base, options) { + this.__proto__ = { + 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("."); + }, + __proto__: base + }; +} + +var runTests = exports.runTests = function runTests(options) { + iterationsLeft = options.iterations; + filter = options.filter; + profileMemory = options.profileMemory; + stopOnError = options.stopOnError; + onDone = options.onDone; + print = options.print; + + try { + cService.registerListener(consoleListener); + + var ptc = require("api-utils/plain-text-console"); + var url = require("api-utils/url"); + var system = require("api-utils/system"); + + print("Running tests on " + system.name + " " + system.version + + "/Gecko " + system.platformVersion + " (" + + system.id + ") under " + + system.platform + "/" + system.architecture + ".\n"); + + sandbox = Loader.new(require("@packaging")); + Object.defineProperty(sandbox.globals, 'console', { + value: new TestRunnerConsole(new ptc.PlainTextConsole(print), options) + }); + + nextIteration(); + } catch (e) { + print(require("api-utils/traceback").format(e) + "\n" + e + "\n"); + onDone({passed: 0, failed: 1}); + } +}; + +require("api-utils/unload").when(function() { + cService.unregisterListener(consoleListener); +}); diff --git a/tools/addon-sdk-1.7/packages/test-harness/lib/run-tests.js b/tools/addon-sdk-1.7/packages/test-harness/lib/run-tests.js new file mode 100644 index 0000000..4eb8570 --- /dev/null +++ b/tools/addon-sdk-1.7/packages/test-harness/lib/run-tests.js @@ -0,0 +1,101 @@ +/* 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"; + +var obsvc = require("api-utils/observer-service"); +var system = require("api-utils/system"); +var options = require('@packaging'); +var {Cc,Ci} = require("chrome"); + +function runTests(iterations, filter, profileMemory, stopOnError, verbose, exit, print) { + var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"] + .getService(Ci.nsIWindowWatcher); + + let ns = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; + let msg = 'Running tests...'; + let markup = ''; + let url = "data:application/vnd.mozilla.xul+xml," + escape(markup); + + + var window = ww.openWindow(null, url, "harness", "centerscreen", null); + + var harness = require("./harness"); + + function onDone(tests) { + window.close(); + if (tests.failed == 0) { + if (tests.passed === 0) + print("No tests were run\n"); + exit(0); + } else { + printFailedTests(tests, verbose, print); + exit(1); + } + }; + + // We have to wait for this window to be fully loaded *and* focused + // in order to avoid it to mess with our various window/focus tests. + // We are first waiting for our window to be fully loaded before ensuring + // that it will take the focus, and then we wait for it to be focused. + window.addEventListener("load", function onload() { + window.removeEventListener("load", onload, true); + + window.addEventListener("focus", function onfocus() { + window.removeEventListener("focus", onfocus, true); + // Finally, we 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("timer").setTimeout(function () { + harness.runTests({iterations: iterations, + filter: filter, + profileMemory: profileMemory, + stopOnError: stopOnError, + verbose: verbose, + print: print, + onDone: onDone}); + }, 0); + }, true); + window.focus(); + }, true); +} + +function printFailedTests(tests, verbose, print) { + if (!verbose) + return; + + let iterationNumber = 0; + let singleIteration = tests.testRuns.length == 1; + let padding = singleIteration ? "" : " "; + + print("\nThe following tests failed:\n"); + + for each (let testRun in tests.testRuns) { + iterationNumber++; + + if (!singleIteration) + print(" Iteration " + iterationNumber + ":\n"); + + for each (let test in testRun) { + if (test.failed > 0) { + print(padding + " " + test.name + ": " + test.errors +"\n"); + } + } + print("\n"); + } +} + +exports.main = function main() { + var testsStarted = false; + + if (!testsStarted) { + testsStarted = true; + runTests(options.iterations, options.filter, + options.profileMemory, options.stopOnError, options.verbose, + system.exit, + dump); + } +}; -- cgit v1.2.3