Bug 1648545: Part 3 - Support Assert in SpecialPowers.spawn for xpcshell tests. r=ahal

Differential Revision: https://phabricator.services.mozilla.com/D119450
This commit is contained in:
Kris Maglione 2023-05-25 22:04:31 +00:00
Родитель 1abe5de918
Коммит 05d13811b2
10 изменённых файлов: 247 добавлений и 10 удалений

Просмотреть файл

@ -88,7 +88,7 @@ async function ensureDataCleanup() {
// resulting install invocation. The installation's call to importScripts when evaluated
// will load the script directly out of the Cache API.
function testSWUpdate(contentPage) {
return contentPage.spawn([], async () => {
return contentPage.legacySpawn([], async () => {
const oldReg = await this.content.navigator.serviceWorker.ready;
const reg = await oldReg.update();
const sw = reg.installing || reg.waiting || reg.active;
@ -178,7 +178,7 @@ add_task(async function test_extension_invalid_sw_scripts_redirect_ignored() {
// Register the worker while the test extension isn't loaded and cannot
// intercept and redirect the importedScripts requests.
info("Register service worker from a content webpage");
let workerMessage = await contentPage.spawn([], async () => {
let workerMessage = await contentPage.legacySpawn([], async () => {
const reg = await this.content.navigator.serviceWorker.register("/sw.js");
return new Promise(resolve => {
const { port1, port2 } = new MessageChannel();
@ -281,7 +281,7 @@ add_task(async function test_filter_sw_script() {
"http://localhost/page.html"
);
let workerMessage = await contentPage.spawn([], async () => {
let workerMessage = await contentPage.legacySpawn([], async () => {
const reg = await this.content.navigator.serviceWorker.register("/sw.js");
return new Promise(resolve => {
const { port1, port2 } = new MessageChannel();
@ -349,7 +349,7 @@ add_task(async function test_extension_redirect_sw_imported_script() {
// Register the worker while the test extension isn't loaded and cannot
// intercept and redirect the importedScripts requests.
let workerMessage = await contentPage.spawn([], async () => {
let workerMessage = await contentPage.legacySpawn([], async () => {
const reg = await this.content.navigator.serviceWorker.register("/sw.js");
return new Promise(resolve => {
const { port1, port2 } = new MessageChannel();

Просмотреть файл

@ -0,0 +1,12 @@
"use strict";
module.exports = {
extends: ["plugin:mozilla/xpcshell-test"],
overrides: [
{
files: "*.html",
env: { browser: true },
},
],
};

Просмотреть файл

@ -0,0 +1,139 @@
"use strict";
/* eslint-disable @microsoft/sdl/no-insecure-url */
const { XPCShellContentUtils } = ChromeUtils.import(
"resource://testing-common/XPCShellContentUtils.jsm"
);
XPCShellContentUtils.init(this);
const HTML = String.raw`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<span id="span">Hello there.</span>
</body>
</html>`;
const server = XPCShellContentUtils.createHttpServer({
hosts: ["example.com", "example.org"],
});
server.registerPathHandler("/", (request, response) => {
response.setHeader("Content-Type", "text/html");
response.write(HTML);
});
/**
* Tests that the shared sandbox functionality for cross-process script
* execution works as expected. In particular, ensures that Assert methods
* report the correct diagnostics in the caller scope.
*/
let scope = this;
async function interceptDiagnostics(func) {
let originalRecord = scope.do_report_result;
try {
let diags = [];
scope.do_report_result = (passed, msg, stack) => {
diags.push({ passed, msg, stack });
};
await func();
return diags;
} finally {
scope.do_report_result = originalRecord;
}
}
add_task(async function () {
const frameSrc = "http://example.com/";
const subframeSrc = "http://example.org/";
let page = await XPCShellContentUtils.loadContentPage(frameSrc, {
remote: true,
remoteSubframes: true,
});
let { SpecialPowers, browsingContext } = page;
let expected = [
[false, "Thing - 1 == 2"],
[true, "Hmm - 1 == 1"],
[true, "Yay. - true == true"],
[false, "Boo!. - false == true"],
];
// Test that a representative variety of assertions work as expected, and
// trigger the expected calls to the harness's reporting function.
//
// Note: Assert.sys.mjs has its own tests, and defers all of its reporting to a
// single reporting function, so we don't need to test it comprehensively. We
// just need to make sure that the general functionality works as expected.
let tests = {
"SpecialPowers.spawn": () => {
return SpecialPowers.spawn(browsingContext, [], async () => {
Assert.equal(1, 2, "Thing");
Assert.equal(1, 1, "Hmm");
Assert.ok(true, "Yay.");
Assert.ok(false, "Boo!.");
});
},
"SpecialPowers.spawn-subframe": () => {
return SpecialPowers.spawn(browsingContext, [subframeSrc], async src => {
let subFrame = this.content.document.createElement("iframe");
subFrame.src = src;
this.content.document.body.appendChild(subFrame);
await new Promise(resolve => {
subFrame.addEventListener("load", resolve, { once: true });
});
await SpecialPowers.spawn(subFrame, [], () => {
Assert.equal(1, 2, "Thing");
Assert.equal(1, 1, "Hmm");
Assert.ok(true, "Yay.");
Assert.ok(false, "Boo!.");
});
});
},
"SpecialPowers.spawnChrome": () => {
return SpecialPowers.spawnChrome([], async () => {
Assert.equal(1, 2, "Thing");
Assert.equal(1, 1, "Hmm");
Assert.ok(true, "Yay.");
Assert.ok(false, "Boo!.");
});
},
"SpecialPowers.loadChromeScript": async () => {
let script = SpecialPowers.loadChromeScript(() => {
/* eslint-env mozilla/chrome-script */
this.addMessageListener("ping", () => "pong");
Assert.equal(1, 2, "Thing");
Assert.equal(1, 1, "Hmm");
Assert.ok(true, "Yay.");
Assert.ok(false, "Boo!.");
});
await script.sendQuery("ping");
script.destroy();
},
};
for (let [name, func] of Object.entries(tests)) {
info(`Starting task: ${name}`);
let diags = await interceptDiagnostics(func);
let results = diags.map(diag => [diag.passed, diag.msg]);
deepEqual(results, expected, "Got expected assertions");
}
});

Просмотреть файл

@ -0,0 +1,68 @@
"use strict";
const { XPCShellContentUtils } = ChromeUtils.import(
"resource://testing-common/XPCShellContentUtils.jsm"
);
XPCShellContentUtils.init(this);
const HTML = String.raw`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<span id="span">Hello there.</span>
</body>
</html>`;
const server = XPCShellContentUtils.createHttpServer({
hosts: ["example.com"],
});
server.registerPathHandler("/", (request, response) => {
response.setHeader("Content-Type", "text/html");
response.write(HTML);
});
add_task(async function () {
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
let page = await XPCShellContentUtils.loadContentPage("http://example.com/", {
remote: true,
remoteSubframes: true,
});
let { SpecialPowers, browsingContext } = page;
let result = await SpecialPowers.spawn(
browsingContext,
["#span"],
selector => {
let elem = content.document.querySelector(selector);
return elem.textContent;
}
);
equal(result, "Hello there.", "Got correct element text from frame");
let line = Components.stack.lineNumber + 1;
let callback = () => {
let e = new Error("Hello.");
return { filename: e.fileName, lineNumber: e.lineNumber };
};
let loc = await SpecialPowers.spawn(browsingContext, [], callback);
equal(
loc.filename,
Components.stack.filename,
"Error should have correct script filename"
);
equal(
loc.lineNumber,
line + 2,
"Error should have correct script line number"
);
await page.close();
});

Просмотреть файл

@ -0,0 +1,2 @@
[test_SpecialPowersSandbox.js]
[test_SpecialPowersSpawn.js]

Просмотреть файл

@ -11,4 +11,5 @@ TESTING_JS_MODULES += [
]
MOCHITEST_MANIFESTS += ["Harness_sanity/mochitest.ini"]
XPCSHELL_TESTS_MANIFESTS += ["Harness_sanity/xpcshell.ini"]
BROWSER_CHROME_MANIFESTS += ["browser/browser.ini"]

Просмотреть файл

@ -177,6 +177,10 @@ class ContentPage {
let chromeDoc = await promiseDocumentLoaded(chromeShell.document);
let { SpecialPowers } = chromeDoc.ownerGlobal;
SpecialPowers.xpcshellScope = XPCShellContentUtils.currentScope;
SpecialPowers.setAsDefaultAssertHandler();
let browser = chromeDoc.createXULElement("browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");

Просмотреть файл

@ -311,7 +311,7 @@ export class SpecialPowersChild extends JSWindowActorChild {
case "Assert":
{
if ("info" in message.data) {
this.SimpleTest.info(message.data.info);
(this.xpcshellScope || this.SimpleTest).info(message.data.info);
break;
}
@ -322,6 +322,8 @@ export class SpecialPowersChild extends JSWindowActorChild {
if (SimpleTest) {
let expected = expectFail ? "fail" : "pass";
SimpleTest.record(passed, name, diag, stack, expected);
} else if (this.xpcshellScope) {
this.xpcshellScope.do_report_result(passed, name, stack);
} else {
// Well, this is unexpected.
dump(name + "\n");
@ -1585,7 +1587,9 @@ export class SpecialPowersChild extends JSWindowActorChild {
args,
task: String(task),
caller: Cu.getFunctionSourceLocation(task),
hasHarness: typeof this.SimpleTest === "object",
hasHarness:
typeof this.SimpleTest === "object" ||
typeof this.xpcshellScope === "object",
imports: this._spawnTaskImports,
});
}
@ -1667,6 +1671,13 @@ export class SpecialPowersChild extends JSWindowActorChild {
this._SimpleTest = val;
}
get xpcshellScope() {
return this._xpcshellScope;
}
set xpcshellScope(val) {
this._xpcshellScope = val;
}
async evictAllContentViewers() {
if (Services.appinfo.sessionHistoryInParent) {
await this.sendQuery("EvictAllContentViewers");

Просмотреть файл

@ -179,7 +179,7 @@ add_task(async function test_blob_url() {
"http://example.org/empty"
);
let blobUrl = await contentPage.spawn(null, async () => {
let blobUrl = await contentPage.spawn([], async () => {
// Create a third-party iframe and create a blob url in there.
let f = this.content.document.createElement("iframe");
f.src = "http://foo.com/iframe";

Просмотреть файл

@ -177,7 +177,7 @@ add_task(async function page_content_process() {
"privilegedabout"
);
await contentPage.spawn(PAGE_ICON_TEST_URLS, async URLS => {
await contentPage.spawn([PAGE_ICON_TEST_URLS], async URLS => {
// We expect each of these URLs to produce an error event when
// we attempt to load them in this process type.
/* global content */
@ -218,7 +218,7 @@ add_task(async function page_privileged_about_content_process() {
"privilegedabout"
);
await contentPage.spawn(PAGE_ICON_TEST_URLS, async URLS => {
await contentPage.spawn([PAGE_ICON_TEST_URLS], async URLS => {
// We expect each of these URLs to load correctly in this process
// type.
for (let url of URLS) {