Source code
Revision control
Copy as Markdown
Other Tools
/**
* Any copyright is dedicated to the Public Domain.
*/
// The path to the top level directory.
const depth = "../../../../";
var testGenerator;
var testHarnessGenerator;
var workerScriptPaths = [];
loadScript("dom/quota/test/common/mochitest.js");
function loadScript(path) {
const url = new URL(depth + path, window.location.href);
SpecialPowers.Services.scriptloader.loadSubScript(url.href, this);
}
function loadWorkerScript(path) {
const url = new URL(depth + path, window.location.href);
workerScriptPaths.push(url.href);
}
function* testHarnessSteps() {
function nextTestHarnessStep(val) {
testHarnessGenerator.next(val);
}
info("Enabling storage testing");
enableStorageTesting().then(nextTestHarnessStep);
yield undefined;
info("Pushing preferences");
SpecialPowers.pushPrefEnv(
{
set: [["dom.storageManager.prompt.testing", true]],
},
nextTestHarnessStep
);
yield undefined;
info("Clearing old databases");
clearAllDatabases(nextTestHarnessStep);
yield undefined;
info("Running test in given scopes");
if (workerScriptPaths.length) {
info("Running test in a worker");
let workerScriptBlob = new Blob(["(" + workerScript.toString() + ")();"], {
type: "text/javascript",
});
let workerScriptURL = URL.createObjectURL(workerScriptBlob);
let worker = new Worker(workerScriptURL);
worker.onerror = function (event) {
ok(false, "Worker had an error: " + event.message);
worker.terminate();
nextTestHarnessStep();
};
worker.onmessage = function (event) {
let message = event.data;
switch (message.op) {
case "ok":
ok(message.condition, message.name + " - " + message.diag);
break;
case "todo":
todo(message.condition, message.name, message.diag);
break;
case "info":
info(message.msg);
break;
case "ready":
worker.postMessage({ op: "load", files: workerScriptPaths });
break;
case "loaded":
worker.postMessage({ op: "start" });
break;
case "done":
ok(true, "Worker finished");
nextTestHarnessStep();
break;
case "clearAllDatabases":
clearAllDatabases(function () {
worker.postMessage({ op: "clearAllDatabasesDone" });
});
break;
default:
ok(
false,
"Received a bad message from worker: " + JSON.stringify(message)
);
nextTestHarnessStep();
}
};
URL.revokeObjectURL(workerScriptURL);
yield undefined;
worker.terminate();
worker = null;
clearAllDatabases(nextTestHarnessStep);
yield undefined;
}
info("Running test in main thread");
// Now run the test script in the main thread.
if (testSteps.constructor.name === "AsyncFunction") {
SimpleTest.registerCleanupFunction(async function () {
await requestFinished(clearAllDatabases());
});
add_task(testSteps);
} else {
testGenerator = testSteps();
testGenerator.next();
yield undefined;
}
}
if (!window.runTest) {
window.runTest = function () {
SimpleTest.waitForExplicitFinish();
testHarnessGenerator = testHarnessSteps();
testHarnessGenerator.next();
};
}
function finishTest() {
SimpleTest.executeSoon(function () {
clearAllDatabases(function () {
SimpleTest.finish();
});
});
}
function grabArgAndContinueHandler(arg) {
testGenerator.next(arg);
}
function continueToNextStep() {
SimpleTest.executeSoon(function () {
testGenerator.next();
});
}
function continueToNextStepSync() {
testGenerator.next();
}
function workerScript() {
"use strict";
self.testGenerator = null;
self.repr = function (_thing_) {
if (typeof _thing_ == "undefined") {
return "undefined";
}
let str;
try {
str = _thing_ + "";
} catch (e) {
return "[" + typeof _thing_ + "]";
}
if (typeof _thing_ == "function") {
str = str.replace(/^\s+/, "");
let idx = str.indexOf("{");
if (idx != -1) {
str = str.substr(0, idx) + "{...}";
}
}
return str;
};
self.ok = function (_condition_, _name_, _diag_) {
self.postMessage({
op: "ok",
condition: !!_condition_,
name: _name_,
diag: _diag_,
});
};
self.is = function (_a_, _b_, _name_) {
let pass = _a_ == _b_;
let diag = pass ? "" : "got " + repr(_a_) + ", expected " + repr(_b_);
ok(pass, _name_, diag);
};
self.isnot = function (_a_, _b_, _name_) {
let pass = _a_ != _b_;
let diag = pass ? "" : "didn't expect " + repr(_a_) + ", but got it";
ok(pass, _name_, diag);
};
self.todo = function (_condition_, _name_, _diag_) {
self.postMessage({
op: "todo",
condition: !!_condition_,
name: _name_,
diag: _diag_,
});
};
self.info = function (_msg_) {
self.postMessage({ op: "info", msg: _msg_ });
};
self.executeSoon = function (_fun_) {
var channel = new MessageChannel();
channel.port1.postMessage("");
channel.port2.onmessage = function (event) {
_fun_();
};
};
self.finishTest = function () {
self.postMessage({ op: "done" });
};
self.grabArgAndContinueHandler = function (_arg_) {
testGenerator.next(_arg_);
};
self.continueToNextStep = function () {
executeSoon(function () {
testGenerator.next();
});
};
self.continueToNextStepSync = function () {
testGenerator.next();
};
self._clearAllDatabasesCallback = undefined;
self.clearAllDatabases = function (_callback_) {
self._clearAllDatabasesCallback = _callback_;
self.postMessage({ op: "clearAllDatabases" });
};
self.onerror = function (_message_, _file_, _line_) {
ok(
false,
"Worker: uncaught exception [" +
_file_ +
":" +
_line_ +
"]: '" +
_message_ +
"'"
);
self.finishTest();
self.close();
return true;
};
self.onmessage = function (_event_) {
let message = _event_.data;
switch (message.op) {
case "load":
info("Worker: loading " + JSON.stringify(message.files));
self.importScripts(message.files);
self.postMessage({ op: "loaded" });
break;
case "start":
executeSoon(function () {
info("Worker: starting tests");
testGenerator = testSteps();
testGenerator.next();
});
break;
case "clearAllDatabasesDone":
info("Worker: all databases are cleared");
if (self._clearAllDatabasesCallback) {
self._clearAllDatabasesCallback();
}
break;
default:
throw new Error(
"Received a bad message from parent: " + JSON.stringify(message)
);
}
};
self.postMessage({ op: "ready" });
}