Bug 1140658 - Part 1: Create a mini-framework for running tests in the worker, service worker and window contexts; r=bkelly

This commit is contained in:
Ehsan Akhgari 2015-03-06 20:24:46 -05:00
Родитель 69363dcf7f
Коммит 8ceef26b0c
7 изменённых файлов: 229 добавлений и 62 удалений

86
dom/cache/test/mochitest/driver.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,86 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
//
// This helper script exposes a runTests function that takes the name of a
// test script as its input argument and runs the test in three different
// contexts:
// 1. Regular Worker context
// 2. Service Worker context
// 3. Window context
// The function returns a promise which will get resolved once all tests
// finish. The caller of this function is responsible to call SimpleTest.finish
// when the returned promise is resolved.
function runTests(testFile) {
function setupPrefs() {
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({
"set": [["dom.caches.enabled", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true]]
}, function() {
resolve();
});
});
}
function loadScript(script) {
return new Promise(function(resolve, reject) {
var s = document.createElement("script");
s.src = script;
s.onerror = reject;
s.onload = resolve;
document.body.appendChild(s);
});
}
function importDrivers() {
return Promise.all([loadScript("worker_driver.js"),
loadScript("serviceworker_driver.js")]);
}
function runWorkerTest() {
return workerTestExec(testFile);
}
function runServiceWorkerTest() {
return serviceWorkerTestExec(testFile);
}
function runFrameTest() {
return new Promise(function(resolve, reject) {
var iframe = document.createElement("iframe");
iframe.src = "frame.html";
iframe.onload = function() {
var doc = iframe.contentDocument;
var s = doc.createElement("script");
s.src = testFile;
window.onmessage = function(event) {
if (event.data.type == 'finish') {
window.onmessage = null;
resolve();
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
}
};
doc.body.appendChild(s);
};
document.body.appendChild(iframe);
});
}
SimpleTest.waitForExplicitFinish();
return setupPrefs()
.then(importDrivers)
// TODO: Investigate interleaving these tests by making the driver able
// to differentiate where the incoming messages are coming from and use
// Promise.all([runWorkerTest, runServiceWorkerTest, runFrameTest]t) below.
.then(runWorkerTest)
.then(runServiceWorkerTest)
.then(runFrameTest)
.catch(function(e) {
ok(false, "A promise was rejected during test execution: " + e);
});
}

16
dom/cache/test/mochitest/frame.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE html>
<script>
function ok(a, msg) {
dump("OK: " + !!a + " => " + a + ": " + msg + "\n");
parent.postMessage({type: 'status', status: !!a, msg: a + ": " + msg }, "*");
}
function is(a, b, msg) {
dump("IS: " + (a===b) + " => " + a + " | " + b + ": " + msg + "\n");
parent.postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg }, "*");
}
function testDone() {
parent.postMessage({type: 'finish'}, "*");
}
</script>

6
dom/cache/test/mochitest/message_receiver.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
<!DOCTYPE html>
<script>
navigator.serviceWorker.onmessage = function(e) {
window.parent.postMessage(e.data, "*");
};
</script>

4
dom/cache/test/mochitest/mochitest.ini поставляемый
Просмотреть файл

@ -6,6 +6,10 @@ support-files =
test_cache_quick_close.js
worker_driver.js
worker_wrapper.js
frame.html
message_receiver.html
driver.js
serviceworker_driver.js
[test_cache.html]
[test_cache_add.html]

43
dom/cache/test/mochitest/serviceworker_driver.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,43 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
function serviceWorkerTestExec(testFile) {
return new Promise(function(resolve, reject) {
function setupSW(registration) {
var worker = registration.waiting ||
registration.active;
window.onmessage = function(event) {
if (event.data.type == 'finish') {
window.onmessage = null;
registration.unregister()
.then(resolve)
.catch(reject);
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
}
};
worker.onerror = reject;
var iframe = document.createElement("iframe");
iframe.src = "message_receiver.html";
iframe.onload = function() {
worker.postMessage({ script: testFile });
};
document.body.appendChild(iframe);
}
navigator.serviceWorker.register("worker_wrapper.js", {scope: "."})
.then(function(registration) {
if (registration.installing) {
registration.installing.onstatechange = function(e) {
e.target.onstatechange = null;
setupSW(registration);
};
} else {
setupSW(registration);
}
});
});
}

90
dom/cache/test/mochitest/worker_driver.js поставляемый
Просмотреть файл

@ -27,57 +27,57 @@
// For an example see test_worker_interfaces.html and test_worker_interfaces.js.
function workerTestExec(script) {
SimpleTest.waitForExplicitFinish();
var worker = new Worker('worker_wrapper.js');
worker.onmessage = function(event) {
if (event.data.type == 'finish') {
SpecialPowers.forceGC();
SimpleTest.finish();
return new Promise(function(resolve, reject) {
var worker = new Worker('worker_wrapper.js');
worker.onmessage = function(event) {
if (event.data.type == 'finish') {
SpecialPowers.forceGC();
resolve();
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
} else if (event.data.type == 'getPrefs') {
var result = {};
event.data.prefs.forEach(function(pref) {
result[pref] = SpecialPowers.Services.prefs.getBoolPref(pref);
});
worker.postMessage({
type: 'returnPrefs',
prefs: event.data.prefs,
result: result
});
} else if (event.data.type == 'getPrefs') {
var result = {};
event.data.prefs.forEach(function(pref) {
result[pref] = SpecialPowers.Services.prefs.getBoolPref(pref);
});
worker.postMessage({
type: 'returnPrefs',
prefs: event.data.prefs,
result: result
});
} else if (event.data.type == 'getPermissions') {
var result = {};
event.data.permissions.forEach(function(permission) {
result[permission] = SpecialPowers.hasPermission(permission, window.document);
});
worker.postMessage({
type: 'returnPermissions',
permissions: event.data.permissions,
result: result
});
} else if (event.data.type == 'getPermissions') {
var result = {};
event.data.permissions.forEach(function(permission) {
result[permission] = SpecialPowers.hasPermission(permission, window.document);
});
worker.postMessage({
type: 'returnPermissions',
permissions: event.data.permissions,
result: result
});
} else if (event.data.type == 'getVersion') {
var result = SpecialPowers.Cc['@mozilla.org/xre/app-info;1'].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
worker.postMessage({
type: 'returnVersion',
result: result
});
} else if (event.data.type == 'getVersion') {
var result = SpecialPowers.Cc['@mozilla.org/xre/app-info;1'].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
worker.postMessage({
type: 'returnVersion',
result: result
});
} else if (event.data.type == 'getUserAgent') {
worker.postMessage({
type: 'returnUserAgent',
result: navigator.userAgent
});
} else if (event.data.type == 'getUserAgent') {
worker.postMessage({
type: 'returnUserAgent',
result: navigator.userAgent
});
}
}
}
worker.onerror = function(event) {
ok(false, 'Worker had an error: ' + event.data);
SimpleTest.finish();
};
worker.onerror = function(event) {
reject('Worker had an error: ' + event.data);
};
worker.postMessage({ script: script });
worker.postMessage({ script: script });
});
}

46
dom/cache/test/mochitest/worker_wrapper.js поставляемый
Просмотреть файл

@ -1,17 +1,18 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
//
// Worker-side wrapper script for the worker_driver.js helper code. See
// the comments at the top of worker_driver.js for more information.
// ServiceWorker equivalent of worker_wrapper.js.
var client;
function ok(a, msg) {
dump("OK: " + !!a + " => " + a + ": " + msg + "\n");
postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
client.postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
}
function is(a, b, msg) {
dump("IS: " + (a===b) + " => " + a + " | " + b + ": " + msg + "\n");
postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
client.postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
}
function workerTestArrayEquals(a, b) {
@ -26,8 +27,8 @@ function workerTestArrayEquals(a, b) {
return true;
}
function workerTestDone() {
postMessage({ type: 'finish' });
function testDone() {
client.postMessage({ type: 'finish' });
}
function workerTestGetPrefs(prefs, cb) {
@ -39,7 +40,7 @@ function workerTestGetPrefs(prefs, cb) {
removeEventListener('message', workerTestGetPrefsCB);
cb(e.data.result);
});
postMessage({
client.postMessage({
type: 'getPrefs',
prefs: prefs
});
@ -54,7 +55,7 @@ function workerTestGetPermissions(permissions, cb) {
removeEventListener('message', workerTestGetPermissionsCB);
cb(e.data.result);
});
postMessage({
client.postMessage({
type: 'getPermissions',
permissions: permissions
});
@ -68,7 +69,7 @@ function workerTestGetVersion(cb) {
removeEventListener('message', workerTestGetVersionCB);
cb(e.data.result);
});
postMessage({
client.postMessage({
type: 'getVersion'
});
}
@ -81,7 +82,7 @@ function workerTestGetUserAgent(cb) {
removeEventListener('message', workerTestGetUserAgentCB);
cb(e.data.result);
});
postMessage({
client.postMessage({
type: 'getUserAgent'
});
}
@ -89,13 +90,24 @@ function workerTestGetUserAgent(cb) {
addEventListener('message', function workerWrapperOnMessage(e) {
removeEventListener('message', workerWrapperOnMessage);
var data = e.data;
try {
importScripts(data.script);
} catch(e) {
postMessage({
type: 'status',
status: false,
msg: 'worker failed to import ' + data.script + "; error: " + e.message
function runScript() {
try {
importScripts(data.script);
} catch(e) {
client.postMessage({
type: 'status',
status: false,
msg: 'worker failed to import ' + data.script + "; error: " + e.message
});
}
}
if ("ServiceWorker" in self) {
self.clients.matchAll().then(function(clients) {
client = clients[0];
runScript();
});
} else {
client = self;
runScript();
}
});