Bug 1574296: Support assertions in nested SpecialPowers.span calls. r=mccr8

Prior to this patch, assertions in SpecialPowers.spawn callbacks only work
when the caller was in a window with a SimpleTest harness.

This patch fixes that by registering a default assertion handler at the start
of a test, and sending assertions from any task without its own harness to
said default handler.

MANUAL PUSH: Contains complex rename operations that I don't trust Lando to
handle correctly.

Differential Revision: https://phabricator.services.mozilla.com/D42210

--HG--
extra : rebase_source : b0b72ce166647621a50aad0af8f130c0d89e3829
extra : source : 41b6d03a870caa7c4be2146ce8c8d84efdb20e79
This commit is contained in:
Kris Maglione 2019-08-15 14:21:37 -07:00
Родитель 62614ed9ba
Коммит a7bea0cda2
5 изменённых файлов: 64 добавлений и 8 удалений

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

@ -477,6 +477,9 @@ function Tester(aTests, structuredLogger, aCallback) {
);
this.SimpleTest = simpleTestScope.SimpleTest;
window.SpecialPowers.SimpleTest = this.SimpleTest;
window.SpecialPowers.setAsDefaultAssertHandler();
var extensionUtilsScope = {
registerCleanupFunction: fn => {
this.currentTest.scope.registerCleanupFunction(fn);

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

@ -37,8 +37,11 @@ async function interceptDiagnostics(func) {
}
add_task(async function() {
const frameSrc = "https://example.com/tests/testing/mochitest/tests/Harness_sanity/file_spawn.html";
const subframeSrc = "https://example.org/tests/testing/mochitest/tests/Harness_sanity/file_spawn.html";
let frame = document.getElementById("iframe");
frame.src = "https://example.com/tests/testing/mochitest/tests/Harness_sanity/file_spawn.html";
frame.src = frameSrc;
await new Promise(resolve => {
frame.addEventListener("load", resolve, {once: true});
@ -59,13 +62,31 @@ add_task(async function() {
// just need to make sure that the general functionality works as expected.
let tests = {
"SpecialPowers.spawn": () => {
return SpecialPowers.spawn(frame, [], () => {
return SpecialPowers.spawn(frame, [], 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(frame, [subframeSrc], async src => {
let frame = this.content.document.createElement("iframe");
frame.src = src;
this.content.document.body.appendChild(frame);
await new Promise(resolve => {
frame.addEventListener("load", resolve, { once: true });
});
await SpecialPowers.spawn(frame, [], () => {
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(() => {
this.addMessageListener("ping", () => "pong");

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

@ -228,6 +228,8 @@ SimpleTest._inChaosMode = false;
SimpleTest.expected = 'pass';
SimpleTest.num_failed = 0;
SpecialPowers.setAsDefaultAssertHandler();
function usesFailurePatterns() {
return Array.isArray(SimpleTest.expected);
}

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

@ -285,9 +285,7 @@ class SpecialPowersChild extends JSWindowActorChild {
// An assertion has been done in a mochitest chrome script
let { name, passed, stack, diag } = message.data;
let SimpleTest =
this.contentWindow && this.contentWindow.wrappedJSObject.SimpleTest;
let { SimpleTest } = this;
if (SimpleTest) {
SimpleTest.record(
passed,
@ -1661,6 +1659,7 @@ class SpecialPowersChild extends JSWindowActorChild {
args,
task: String(task),
caller: SpecialPowersSandbox.getCallerInfo(Components.stack.caller),
hasHarness: typeof this.SimpleTest === "object",
});
}
@ -1692,6 +1691,21 @@ class SpecialPowersChild extends JSWindowActorChild {
return sb.execute(task, args, caller);
}
get SimpleTest() {
return this._SimpleTest || this.contentWindow.wrappedJSObject.SimpleTest;
}
set SimpleTest(val) {
this._SimpleTest = val;
}
/**
* Sets this actor as the default assertion result handler for tasks
* which originate in a window without a test harness.
*/
setAsDefaultAssertHandler() {
this.sendAsyncMessage("SetAsDefaultAssertHandler");
}
getFocusedElementForWindow(targetWindow, aDeep) {
var outParam = {};
Services.focus.getFocusedElementForWindow(targetWindow, aDeep, outParam);

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

@ -119,6 +119,10 @@ function doPrefEnvOp(fn) {
// used to bounce assertion messages back down to the correct child.
let nextTaskID = 1;
// The default actor to send assertions to if a task originated in a
// window without a test harness.
let defaultAssertHandler;
class SpecialPowersParent extends JSWindowActorParent {
constructor() {
super();
@ -200,6 +204,10 @@ class SpecialPowersParent extends JSWindowActorParent {
}
uninit() {
if (defaultAssertHandler === this) {
defaultAssertHandler = null;
}
var obs = Services.obs;
obs.removeObserver(this._observer, "http-on-modify-request");
this._registerObservers._topics.splice(0).forEach(element => {
@ -1042,15 +1050,22 @@ class SpecialPowersParent extends JSWindowActorParent {
});
}
case "SetAsDefaultAssertHandler": {
defaultAssertHandler = this;
return undefined;
}
case "Spawn": {
let { browsingContext, task, args, caller } = aMessage.data;
let { browsingContext, task, args, caller, hasHarness } = aMessage.data;
let spParent = browsingContext.currentWindowGlobal.getActor(
"SpecialPowers"
);
let taskId = nextTaskID++;
if (hasHarness) {
spParent._taskActors.set(taskId, this);
}
return spParent
.sendQuery("Spawn", { task, args, caller, taskId })
@ -1083,9 +1098,10 @@ class SpecialPowersParent extends JSWindowActorParent {
case "ProxiedAssert": {
let { taskId, data } = aMessage.data;
let actor = this._taskActors.get(taskId);
let actor = this._taskActors.get(taskId) || defaultAssertHandler;
actor.sendAsyncMessage("Assert", data);
return undefined;
}