mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-12 22:28:59 +02:00
313 lines
9.4 KiB
JavaScript
313 lines
9.4 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
"use strict";
|
|
|
|
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
|
|
|
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
|
|
|
// Enable logging for all the tests. Both the debugger server and frontend will
|
|
// be affected by this pref.
|
|
let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
|
Services.prefs.setBoolPref("devtools.debugger.log", false);
|
|
|
|
let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
|
let { Promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
|
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
|
let { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
|
|
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
|
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
|
let { getPerformanceActorsConnection, PerformanceFront } = devtools.require("devtools/performance/front");
|
|
let nsIProfilerModule = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
|
|
let TargetFactory = devtools.TargetFactory;
|
|
let mm = null;
|
|
|
|
const FRAME_SCRIPT_UTILS_URL = "chrome://browser/content/devtools/frame-script-utils.js"
|
|
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/performance/test/";
|
|
const SIMPLE_URL = EXAMPLE_URL + "doc_simple-test.html";
|
|
|
|
// All tests are asynchronous.
|
|
waitForExplicitFinish();
|
|
|
|
let gToolEnabled = Services.prefs.getBoolPref("devtools.performance_dev.enabled");
|
|
let gShowTimelineMemory = Services.prefs.getBoolPref("devtools.performance.ui.show-timeline-memory");
|
|
|
|
gDevTools.testing = true;
|
|
|
|
/**
|
|
* Call manually in tests that use frame script utils after initializing
|
|
* the tool. Must be called after initializing so we can detect
|
|
* whether or not `content` is a CPOW or not. Call after init but before navigating
|
|
* to different pages.
|
|
*/
|
|
function loadFrameScripts () {
|
|
mm = gBrowser.selectedBrowser.messageManager;
|
|
mm.loadFrameScript(FRAME_SCRIPT_UTILS_URL, false);
|
|
}
|
|
|
|
registerCleanupFunction(() => {
|
|
gDevTools.testing = false;
|
|
info("finish() was called, cleaning up...");
|
|
|
|
Services.prefs.setBoolPref("devtools.performance.ui.show-timeline-memory", gShowTimelineMemory);
|
|
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
|
|
Services.prefs.setBoolPref("devtools.performance_dev.enabled", gToolEnabled);
|
|
// Make sure the profiler module is stopped when the test finishes.
|
|
nsIProfilerModule.StopProfiler();
|
|
|
|
Cu.forceGC();
|
|
});
|
|
|
|
function addTab(aUrl, aWindow) {
|
|
info("Adding tab: " + aUrl);
|
|
|
|
let deferred = Promise.defer();
|
|
let targetWindow = aWindow || window;
|
|
let targetBrowser = targetWindow.gBrowser;
|
|
|
|
targetWindow.focus();
|
|
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
|
|
let linkedBrowser = tab.linkedBrowser;
|
|
|
|
linkedBrowser.addEventListener("load", function onLoad() {
|
|
linkedBrowser.removeEventListener("load", onLoad, true);
|
|
info("Tab added and finished loading: " + aUrl);
|
|
deferred.resolve(tab);
|
|
}, true);
|
|
|
|
return deferred.promise;
|
|
}
|
|
|
|
function removeTab(aTab, aWindow) {
|
|
info("Removing tab.");
|
|
|
|
let deferred = Promise.defer();
|
|
let targetWindow = aWindow || window;
|
|
let targetBrowser = targetWindow.gBrowser;
|
|
let tabContainer = targetBrowser.tabContainer;
|
|
|
|
tabContainer.addEventListener("TabClose", function onClose(aEvent) {
|
|
tabContainer.removeEventListener("TabClose", onClose, false);
|
|
info("Tab removed and finished closing.");
|
|
deferred.resolve();
|
|
}, false);
|
|
|
|
targetBrowser.removeTab(aTab);
|
|
return deferred.promise;
|
|
}
|
|
|
|
function handleError(aError) {
|
|
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
|
finish();
|
|
}
|
|
|
|
function once(aTarget, aEventName, aUseCapture = false, spread = false) {
|
|
info("Waiting for event: '" + aEventName + "' on " + aTarget + ".");
|
|
|
|
let deferred = Promise.defer();
|
|
|
|
for (let [add, remove] of [
|
|
["on", "off"], // Use event emitter before DOM events for consistency
|
|
["addEventListener", "removeEventListener"],
|
|
["addListener", "removeListener"]
|
|
]) {
|
|
if ((add in aTarget) && (remove in aTarget)) {
|
|
aTarget[add](aEventName, function onEvent(...aArgs) {
|
|
aTarget[remove](aEventName, onEvent, aUseCapture);
|
|
deferred.resolve(spread ? aArgs : aArgs[0]);
|
|
}, aUseCapture);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return deferred.promise;
|
|
}
|
|
|
|
/**
|
|
* Like `once`, except returns an array so we can
|
|
* access all arguments fired by the event.
|
|
*/
|
|
function onceSpread(aTarget, aEventName, aUseCapture) {
|
|
return once(aTarget, aEventName, aUseCapture, true);
|
|
}
|
|
|
|
function test () {
|
|
Task.spawn(spawnTest).then(finish, handleError);
|
|
}
|
|
|
|
function initBackend(aUrl) {
|
|
info("Initializing a performance front.");
|
|
|
|
if (!DebuggerServer.initialized) {
|
|
DebuggerServer.init(() => true);
|
|
DebuggerServer.addBrowserActors();
|
|
}
|
|
|
|
return Task.spawn(function*() {
|
|
let tab = yield addTab(aUrl);
|
|
let target = TargetFactory.forTab(tab);
|
|
|
|
yield target.makeRemote();
|
|
|
|
yield gDevTools.showToolbox(target, "performance");
|
|
|
|
let connection = getPerformanceActorsConnection(target);
|
|
yield connection.open();
|
|
let front = new PerformanceFront(connection);
|
|
return { target, front };
|
|
});
|
|
}
|
|
|
|
function initPerformance(aUrl) {
|
|
info("Initializing a performance pane.");
|
|
|
|
return Task.spawn(function*() {
|
|
let tab = yield addTab(aUrl);
|
|
let target = TargetFactory.forTab(tab);
|
|
|
|
yield target.makeRemote();
|
|
|
|
Services.prefs.setBoolPref("devtools.performance_dev.enabled", true);
|
|
let toolbox = yield gDevTools.showToolbox(target, "performance");
|
|
let panel = toolbox.getCurrentPanel();
|
|
return { target, panel, toolbox };
|
|
});
|
|
}
|
|
|
|
function* teardown(panel) {
|
|
info("Destroying the performance tool.");
|
|
|
|
let tab = panel.target.tab;
|
|
yield panel._toolbox.destroy();
|
|
yield removeTab(tab);
|
|
}
|
|
|
|
function idleWait(time) {
|
|
return DevToolsUtils.waitForTime(time);
|
|
}
|
|
|
|
function consoleMethod (...args) {
|
|
if (!mm) {
|
|
throw new Error("`loadFrameScripts()` must be called before using frame scripts.");
|
|
}
|
|
mm.sendAsyncMessage("devtools:test:console", args);
|
|
}
|
|
|
|
function* consoleProfile(connection, label) {
|
|
let notified = connection.once("profile");
|
|
consoleMethod("profile", label);
|
|
yield notified;
|
|
}
|
|
|
|
function* consoleProfileEnd(connection) {
|
|
let notified = connection.once("profileEnd");
|
|
consoleMethod("profileEnd");
|
|
yield notified;
|
|
}
|
|
|
|
function busyWait(time) {
|
|
let start = Date.now();
|
|
let stack;
|
|
while (Date.now() - start < time) { stack = Components.stack; }
|
|
}
|
|
|
|
function idleWait(time) {
|
|
return DevToolsUtils.waitForTime(time);
|
|
}
|
|
|
|
function* startRecording(panel) {
|
|
let win = panel.panelWin;
|
|
let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_START_RECORDING);
|
|
let started = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_STARTED);
|
|
let button = win.$("#record-button");
|
|
|
|
ok(!button.hasAttribute("checked"),
|
|
"The record button should not be checked yet.");
|
|
|
|
ok(!button.hasAttribute("locked"),
|
|
"The record button should not be locked yet.");
|
|
|
|
EventUtils.sendMouseEvent({ type: "click" }, button, win);
|
|
|
|
yield clicked;
|
|
|
|
ok(button.hasAttribute("checked"),
|
|
"The record button should now be checked.");
|
|
ok(button.hasAttribute("locked"),
|
|
"The record button should be locked.");
|
|
|
|
yield started;
|
|
|
|
ok(button.hasAttribute("checked"),
|
|
"The record button should still be checked.");
|
|
ok(!button.hasAttribute("locked"),
|
|
"The record button should not be locked.");
|
|
}
|
|
|
|
function* stopRecording(panel) {
|
|
let win = panel.panelWin;
|
|
let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_STOP_RECORDING);
|
|
let ended = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_STOPPED);
|
|
let button = win.$("#record-button");
|
|
|
|
ok(button.hasAttribute("checked"),
|
|
"The record button should already be checked.");
|
|
ok(!button.hasAttribute("locked"),
|
|
"The record button should not be locked yet.");
|
|
|
|
EventUtils.sendMouseEvent({ type: "click" }, button, win);
|
|
|
|
yield clicked;
|
|
|
|
ok(!button.hasAttribute("checked"),
|
|
"The record button should not be checked.");
|
|
ok(button.hasAttribute("locked"),
|
|
"The record button should be locked.");
|
|
|
|
yield ended;
|
|
|
|
ok(!button.hasAttribute("checked"),
|
|
"The record button should not be checked.");
|
|
ok(!button.hasAttribute("locked"),
|
|
"The record button should not be locked.");
|
|
}
|
|
|
|
/**
|
|
* Waits until a predicate returns true.
|
|
*
|
|
* @param function predicate
|
|
* Invoked once in a while until it returns true.
|
|
* @param number interval [optional]
|
|
* How often the predicate is invoked, in milliseconds.
|
|
*/
|
|
function waitUntil(predicate, interval = 10) {
|
|
if (predicate()) {
|
|
return Promise.resolve(true);
|
|
}
|
|
let deferred = Promise.defer();
|
|
setTimeout(function() {
|
|
waitUntil(predicate).then(() => deferred.resolve(true));
|
|
}, interval);
|
|
return deferred.promise;
|
|
}
|
|
|
|
// EventUtils just doesn't work!
|
|
|
|
function dragStart(graph, x, y = 1) {
|
|
x /= window.devicePixelRatio;
|
|
y /= window.devicePixelRatio;
|
|
graph._onMouseMove({ clientX: x, clientY: y });
|
|
graph._onMouseDown({ clientX: x, clientY: y });
|
|
}
|
|
|
|
function dragStop(graph, x, y = 1) {
|
|
x /= window.devicePixelRatio;
|
|
y /= window.devicePixelRatio;
|
|
graph._onMouseMove({ clientX: x, clientY: y });
|
|
graph._onMouseUp({ clientX: x, clientY: y });
|
|
}
|
|
|
|
function dropSelection(graph) {
|
|
graph.dropSelection();
|
|
graph.emit("mouseup");
|
|
}
|