Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

302 lines
11 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
Cu.import("resource://testing-common/ContentTask.jsm", this);
const URL = "http://example.com/browser/toolkit/components/aboutperformance/tests/browser/browser_compartments.html?test=" + Math.random();
// This function is injected as source as a frameScript
function frameScript() {
"use strict";
addMessageListener("aboutperformance-test:done", () => {
content.postMessage("stop", "*");
sendAsyncMessage("aboutperformance-test:done", null);
});
addMessageListener("aboutperformance-test:setTitle", ({data: title}) => {
content.document.title = title;
sendAsyncMessage("aboutperformance-test:setTitle", null);
});
addMessageListener("aboutperformance-test:closeTab", ({data: options}) => {
let observer = function(subject, topic, mode) {
dump(`aboutperformance-test:closeTab 1 ${options.url}\n`);
Services.obs.removeObserver(observer, "about:performance-update-complete");
let exn;
let found = false;
try {
for (let eltContent of content.document.querySelectorAll("li.delta")) {
let eltName = eltContent.querySelector("li.name");
if (!eltName.textContent.includes(options.url)) {
continue;
}
found = true;
let [eltCloseTab, eltReloadTab] = eltContent.querySelectorAll("button");
let button;
if (options.mode == "reload") {
button = eltReloadTab;
} else if (options.mode == "close") {
button = eltCloseTab;
} else {
throw new TypeError(options.mode);
}
dump(`aboutperformance-test:closeTab clicking on ${button.textContent}\n`);
button.click();
return;
}
} catch (ex) {
dump(`aboutperformance-test:closeTab: error ${ex}\n`);
exn = ex;
} finally {
if (exn) {
sendAsyncMessage("aboutperformance-test:closeTab", { error: {message: exn.message, lineNumber: exn.lineNumber, fileName: exn.fileName}, found});
} else {
sendAsyncMessage("aboutperformance-test:closeTab", { ok: true, found });
}
}
}
Services.obs.addObserver(observer, "about:performance-update-complete", false);
Services.obs.notifyObservers(null, "test-about:performance-test-driver", JSON.stringify(options));
});
addMessageListener("aboutperformance-test:checkSanity", ({data: options}) => {
let exn = null;
try {
let reFullname = /Full name: (.+)/;
let reFps = /Impact on framerate: (\d+)\/10( \((\d+) alerts\))?/;
let reCpu = /CPU usage: (\d+)%/
let reCpow = /Blocking process calls: (\d+)%( \((\d+) alerts\))?/;
let getContentOfSelector = function(eltContainer, selector, re) {
let elt = eltContainer.querySelector(selector);
if (!elt) {
throw new Error(`No item ${selector}`);
}
if (!re) {
return;
}
let match = elt.textContent.match(re);
if (!match) {
throw new Error(`Item ${selector} doesn't match regexp ${re}: ${elt.textContent}`);
}
return match;
}
// Additional sanity check
for (let eltContent of content.document.querySelectorAll("delta")) {
// Do we have an attribute "impact"? Is it a number between 0 and 10?
let impact = eltContent.classList.getAttribute("impact");
let value = Number.parseInt(impact);
if (isNaN(value) || value < 0 || value > 10) {
throw new Error(`Incorrect value ${value}`);
}
// Do we have a button "more"?
getContentOfSelector(eltContent, "a.more");
// Do we have details?
getContentOfSelector(eltContent, "ul.details");
// Do we have a full name? Does it make sense?
getContentOfSelector(eltContent, "li.name", reFullname);
// Do we have an impact on framerate? Does it make sense?
let [, jankStr,, alertsStr] = getContentOfSelector(eltDetails, "li.fps", reFps);
let jank = Number.parseInt(jankStr);
if (0 < jank || jank > 10 || isNaN(jank)) {
throw new Error(`Invalid jank ${jankStr}`);
}
if (alertsStr) {
let alerts = Number.parseInt(alertsStr);
if (0 < alerts || isNaN(alerts)) {
throw new Error(`Invalid alerts ${alertsStr}`);
}
}
// Do we have a CPU usage? Does it make sense?
let [, cpuStr] = getContentOfSelector(eltDetails, "li.cpu", reCPU);
let cpu = Number.parseInt(cpuStr);
if (0 < cpu || isNaN(cpu)) { // Note that cpu can be > 100%.
throw new Error(`Invalid CPU ${cpuStr}`);
}
// Do we have CPOW? Does it make sense?
let [, cpowStr,, alertsStr2] = getContentOfSelector(eltDetails, "li.cpow", reCpow);
let cpow = Number.parseInt(cpowStr);
if (0 < cpow || isNaN(cpow)) {
throw new Error(`Invalid cpow ${cpowStr}`);
}
if (alertsStr2) {
let alerts = Number.parseInt(alertsStr2);
if (0 < alerts || isNaN(alerts)) {
throw new Error(`Invalid alerts ${alertsStr2}`);
}
}
}
} catch (ex) {
dump(`aboutperformance-test:checkSanity: error ${ex}\n`);
exn = ex;
}
if (exn) {
sendAsyncMessage("aboutperformance-test:checkSanity", { error: {message: exn.message, lineNumber: exn.lineNumber, fileName: exn.fileName}});
} else {
sendAsyncMessage("aboutperformance-test:checkSanity", { ok: true });
}
});
addMessageListener("aboutperformance-test:hasItems", ({data: {title, options}}) => {
let observer = function(subject, topic, mode) {
Services.obs.removeObserver(observer, "about:performance-update-complete");
let hasTitleInWebpages = false;
let hasTitleInAddons = false;
try {
let eltWeb = content.document.getElementById("webpages");
let eltAddons = content.document.getElementById("addons");
if (!eltWeb || !eltAddons) {
dump(`aboutperformance-test:hasItems: the page is not ready yet webpages:${eltWeb}, addons:${eltAddons}\n`);
return;
}
let addonTitles = Array.from(eltAddons.querySelectorAll("span.title"), elt => elt.textContent);
let webTitles = Array.from(eltWeb.querySelectorAll("span.title"), elt => elt.textContent);
hasTitleInAddons = addonTitles.includes(title);
hasTitleInWebpages = webTitles.includes(title);
} catch (ex) {
Cu.reportError("Error in content: " + ex);
Cu.reportError(ex.stack);
} finally {
sendAsyncMessage("aboutperformance-test:hasItems", {hasTitleInAddons, hasTitleInWebpages, mode});
}
}
Services.obs.addObserver(observer, "about:performance-update-complete", false);
Services.obs.notifyObservers(null, "test-about:performance-test-driver", JSON.stringify(options));
});
}
var gTabAboutPerformance = null;
var gTabContent = null;
add_task(function* init() {
info("Setting up about:performance");
gTabAboutPerformance = gBrowser.selectedTab = gBrowser.addTab("about:performance");
yield ContentTask.spawn(gTabAboutPerformance.linkedBrowser, null, frameScript);
info(`Setting up ${URL}`);
gTabContent = gBrowser.addTab(URL);
yield ContentTask.spawn(gTabContent.linkedBrowser, null, frameScript);
});
var promiseExpectContent = Task.async(function*(options) {
let title = "Testing about:performance " + Math.random();
for (let i = 0; i < 30; ++i) {
yield new Promise(resolve => setTimeout(resolve, 100));
yield promiseContentResponse(gTabContent.linkedBrowser, "aboutperformance-test:setTitle", title);
let {hasTitleInWebpages, hasTitleInAddons, mode} = (yield promiseContentResponse(gTabAboutPerformance.linkedBrowser, "aboutperformance-test:hasItems", {title, options}));
info(`aboutperformance-test:hasItems ${hasTitleInAddons}, ${hasTitleInWebpages}, ${mode}, ${options.displayRecent}`);
if (!hasTitleInWebpages) {
info(`Title not found in webpages`);
continue;
}
if ((mode == "recent") != options.displayRecent) {
info(`Wrong mode`);
continue;
}
Assert.ok(!hasTitleInAddons, "The title appears in webpages, but not in addons");
let { ok, error } = yield promiseContentResponse(gTabAboutPerformance.linkedBrowser, "aboutperformance-test:checkSanity", {options});
if (ok) {
info("aboutperformance-test:checkSanity: success");
}
if (error) {
Assert.ok(false, `aboutperformance-test:checkSanity error: ${JSON.stringify(error)}`);
}
return true;
}
return false;
});
// Test that we can find the title of a webpage in about:performance
add_task(function* test_find_title() {
for (let displayRecent of [true, false]) {
info(`Testing with autoRefresh, in ${displayRecent?"recent":"global"} mode`);
let found = yield promiseExpectContent({autoRefresh: 100, displayRecent});
Assert.ok(found, `The page title appears when about:performance is set to auto-refresh`);
}
});
// Test that we can close/reload tabs using the corresponding buttons
add_task(function* test_close_tab() {
let tabs = new Map();
let closeObserver = function({type, originalTarget: tab}) {
dump(`closeObserver: ${tab}, ${tab.constructor.name}, ${tab.tagName}, ${type}\n`);
let cb = tabs.get(tab);
if (cb) {
cb(type);
}
};
let promiseTabClosed = function(tab) {
return new Promise(resolve => tabs.set(tab, resolve));
}
window.gBrowser.tabContainer.addEventListener("TabClose", closeObserver);
let promiseTabReloaded = function(tab) {
return new Promise(resolve =>
tab.linkedBrowser.contentDocument.addEventListener("readystatechange", resolve)
);
}
for (let displayRecent of [true, false]) {
for (let mode of ["close", "reload"]) {
let URL = `about:about?display-recent=${displayRecent}&mode=${mode}&salt=${Math.random()}`;
info(`Setting up ${URL}`);
let tab = gBrowser.addTab(URL);
yield ContentTask.spawn(tab.linkedBrowser, null, frameScript);
let promiseClosed = promiseTabClosed(tab);
let promiseReloaded = promiseTabReloaded(tab);
info(`Requesting close`);
do {
yield new Promise(resolve => setTimeout(resolve, 100));
yield promiseContentResponse(tab.linkedBrowser, "aboutperformance-test:setTitle", URL);
let {ok, found, error} = yield promiseContentResponse(gTabAboutPerformance.linkedBrowser, "aboutperformance-test:closeTab", {url: URL, autoRefresh: true, mode, displayRecent});
Assert.ok(ok, `Message aboutperformance-test:closeTab was handled correctly ${JSON.stringify(error)}`);
info(`URL ${URL} ${found?"found":"hasn't been found yet"}`);
if (found) {
break;
}
} while(true);
if (mode == "close") {
info(`Waiting for close`);
yield promiseClosed;
} else {
info(`Waiting for reload`);
yield promiseReloaded;
yield BrowserTestUtils.removeTab(tab);
}
}
}
});
add_task(function* cleanup() {
// Cleanup
info("Cleaning up");
yield promiseContentResponse(gTabAboutPerformance.linkedBrowser, "aboutperformance-test:done", null);
info("Closing tabs");
for (let tab of gBrowser.tabs) {
yield BrowserTestUtils.removeTab(tab);
}
info("Done");
gBrowser.selectedTab = null;
});