Bug 1361330 - Part 5: Automatic tests for simpledb; r=asuth

This commit is contained in:
Jan Varga 2018-08-20 14:33:10 +02:00
Родитель 5733cbbbd3
Коммит e7d1daf164
11 изменённых файлов: 308 добавлений и 19 удалений

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

@ -15,6 +15,10 @@ XPCSHELL_TESTS_MANIFESTS += [
'test/unit/xpcshell.ini'
]
TEST_HARNESS_FILES.xpcshell.dom.quota.test += [
'test/head-shared.js',
]
XPIDL_SOURCES += [
'nsIQuotaCallbacks.idl',
'nsIQuotaManagerService.idl',

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

@ -1,10 +1,12 @@
[DEFAULT]
skip-if = (buildapp != "browser")
support-files =
head.js
browserHelpers.js
browser_permissionsPrompt.html
head-shared.js
head.js
[browser_permissionsPromptAllow.js]
[browser_permissionsPromptDeny.js]
[browser_permissionsPromptUnknown.js]
[browser_simpledb.js]

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

@ -0,0 +1,48 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
add_task(async function testSimpleDB() {
const name = "data";
const bufferSize = 100;
let database = getSimpleDatabase();
let request = database.open("data");
await requestFinished(request);
let buffer1 = getRandomBuffer(bufferSize);
request = database.write(buffer1);
await requestFinished(request);
request = database.seek(0);
await requestFinished(request);
request = database.read(bufferSize);
let result = await requestFinished(request);
let buffer2 = result.getAsArrayBuffer();
ok(compareBuffers(buffer1, buffer2), "Buffers equal.");
let database2 = getSimpleDatabase();
try {
request = database2.open(name);
await requestFinished(request);
ok(false, "Should have thrown!");
} catch(ex) {
ok(request.resultCode == NS_ERROR_STORAGE_BUSY, "Good result code.");
}
request = database.close();
await requestFinished(request);
request = database2.open(name);
await requestFinished(request);
request = database2.close();
await requestFinished(request);
});

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

@ -0,0 +1,37 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
function getBuffer(size)
{
let buffer = new ArrayBuffer(size);
is(buffer.byteLength, size, "Correct byte length");
return buffer;
}
function getRandomBuffer(size)
{
let buffer = getBuffer(size);
let view = new Uint8Array(buffer);
for (let i = 0; i < size; i++) {
view[i] = parseInt(Math.random() * 255)
}
return buffer;
}
function compareBuffers(buffer1, buffer2)
{
if (buffer1.byteLength != buffer2.byteLength) {
return false;
}
let view1 = buffer1 instanceof Uint8Array ? buffer1 : new Uint8Array(buffer1);
let view2 = buffer2 instanceof Uint8Array ? buffer2 : new Uint8Array(buffer2);
for (let i = 0; i < buffer1.byteLength; i++) {
if (view1[i] != view2[i]) {
return false;
}
}
return true;
}

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

@ -3,6 +3,8 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const NS_ERROR_STORAGE_BUSY = Cr.NS_ERROR_STORAGE_BUSY;
var gActiveListeners = {};
// These event (un)registration handlers only work for one window, DONOT use
@ -136,3 +138,37 @@ function getPermission(url, permission)
.getService(Ci.nsIPermissionManager)
.testPermissionFromPrincipal(principal, permission);
}
function getCurrentPrincipal()
{
return Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
}
function getSimpleDatabase(principal)
{
let connection = Cc["@mozilla.org/dom/sdb-connection;1"]
.createInstance(Ci.nsISDBConnection);
if (!principal) {
principal = getCurrentPrincipal();
}
connection.init(principal);
return connection;
}
function requestFinished(request) {
return new Promise(function(resolve, reject) {
request.callback = function(request) {
if (request.resultCode == Cr.NS_OK) {
resolve(request.result);
} else {
reject(request.resultCode);
}
}
});
}
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/dom/quota/test/head-shared.js", this);

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

@ -3,6 +3,8 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const NS_ERROR_STORAGE_BUSY = SpecialPowers.Cr.NS_ERROR_STORAGE_BUSY;
var testGenerator = testSteps();
function clearAllDatabases(callback)
@ -138,6 +140,12 @@ function* testHarnessSteps()
info("Running test in main thread");
let script = document.createElement("script");
script.src = "head-shared.js";
script.onload = nextTestHarnessStep;
document.head.appendChild(script);
yield undefined;
// Now run the test script in the main thread.
testGenerator.next();
@ -304,3 +312,54 @@ function workerScript()
self.postMessage({ op: "ready" });
}
// SimpleDB connections and SpecialPowers wrapping:
//
// SpecialPowers provides a SpecialPowersHandler Proxy mechanism that lets our
// content-privileged code borrow its chrome-privileged principal to access
// things we shouldn't be able to access. The proxies wrap their returned
// values, so once we have something wrapped we can rely on returned objects
// being wrapped as well. The proxy will also automatically unwrap wrapped
// arguments we pass in. However, we need to invoke wrapCallback on callback
// functions so that the arguments they receive will be wrapped because the
// proxy does not automatically wrap content-privileged functions.
//
// Our use of (wrapped) SpecialPowers.Cc results in getSimpleDatabase()
// producing a wrapped nsISDBConnection instance. The nsISDBResult instances
// exposed on the (wrapped) nsISDBRequest are also wrapped, so our
// requestFinished helper wraps the results in helper objects that behave the
// same as the result, automatically unwrapping the wrapped array/arraybuffer
// results.
function getSimpleDatabase()
{
let connection = SpecialPowers.Cc["@mozilla.org/dom/sdb-connection;1"]
.createInstance(SpecialPowers.Ci.nsISDBConnection);
let principal = SpecialPowers.wrap(document).nodePrincipal;
connection.init(principal);
return connection;
}
function* requestFinished(request) {
request.callback = SpecialPowers.wrapCallback(continueToNextStepSync);
yield undefined;
if (request.resultCode == SpecialPowers.Cr.NS_OK) {
let result = request.result;
if (SpecialPowers.call_Instanceof(result, SpecialPowers.Ci.nsISDBResult)) {
let wrapper = {};
for (let i in result) {
if (typeof result[i] == "function") {
wrapper[i] = SpecialPowers.unwrap(result[i]);
} else {
wrapper[i] = result[i];
}
}
return wrapper;
}
return result;
}
throw request.resultCode;
}

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

@ -4,11 +4,14 @@
[DEFAULT]
support-files =
head-shared.js
helpers.js
unit/test_simpledb.js
unit/test_storage_manager_persist_allow.js
unit/test_storage_manager_persist_deny.js
unit/test_storage_manager_persisted.js
[test_simpledb.html]
[test_storage_manager_persist_allow.html]
scheme=https
[test_storage_manager_persist_deny.html]

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

@ -0,0 +1,19 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>SimpleDB Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="unit/test_simpledb.js"></script>
<script type="text/javascript" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

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

@ -6,15 +6,16 @@
const NS_OK = Cr.NS_OK;
const NS_ERROR_FAILURE = Cr.NS_ERROR_FAILURE;
const NS_ERROR_UNEXPECTED = Cr.NS_ERROR_UNEXPECTED;
const NS_ERROR_STORAGE_BUSY = Cr.NS_ERROR_STORAGE_BUSY;
function is(a, b, msg)
{
Assert.equal(a, b, Components.stack.caller);
Assert.equal(a, b, msg);
}
function ok(cond, msg)
{
Assert.ok(!!cond, Components.stack.caller);
Assert.ok(!!cond, msg);
}
function run_test()
@ -229,22 +230,6 @@ function getRelativeFile(relativePath)
return file;
}
function compareBuffers(buffer1, buffer2)
{
if (buffer1.byteLength != buffer2.byteLength) {
return false;
}
let view1 = buffer1 instanceof Uint8Array ? buffer1 : new Uint8Array(buffer1);
let view2 = buffer2 instanceof Uint8Array ? buffer2 : new Uint8Array(buffer2);
for (let i = 0; i < buffer1.byteLength; i++) {
if (view1[i] != view2[i]) {
return false;
}
}
return true;
}
function getPersistedFromMetadata(readBuffer)
{
const persistedPosition = 8; // Persisted state is stored in the 9th byte
@ -292,6 +277,34 @@ function getPrincipal(url)
return ssm.createCodebasePrincipal(uri, {});
}
function getCurrentPrincipal()
{
return Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
}
function getSimpleDatabase(principal)
{
let connection = Cc["@mozilla.org/dom/sdb-connection;1"]
.createInstance(Ci.nsISDBConnection);
if (!principal) {
principal = getCurrentPrincipal();
}
connection.init(principal);
return connection;
}
function* requestFinished(request) {
request.callback = continueToNextStepSync;
yield undefined;
if (request.resultCode == NS_OK) {
return request.result;
}
throw request.resultCode;
}
var SpecialPowers = {
getBoolPref: function(prefName) {
return this._getPrefs().getBoolPref(prefName);
@ -316,3 +329,15 @@ var SpecialPowers = {
.getService(Ci.nsIQuotaManagerService);
},
};
function loadSubscript(path)
{
let file = do_get_file(path, false);
let uri = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService).newFileURI(file);
let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
scriptLoader.loadSubScript(uri.spec);
}
loadSubscript("../head-shared.js");

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

@ -0,0 +1,55 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var disableWorkerTest = "SimpleDB doesn't work in workers yet";
var testGenerator = testSteps();
function* testSteps()
{
const name = "data";
const bufferSize = 100;
let database = getSimpleDatabase();
let request = database.open(name);
yield* requestFinished(request);
let buffer1 = getRandomBuffer(bufferSize);
request = database.write(buffer1);
yield* requestFinished(request);
request = database.seek(0);
yield* requestFinished(request);
request = database.read(bufferSize);
let result = yield* requestFinished(request);
let buffer2 = result.getAsArrayBuffer();
ok(compareBuffers(buffer1, buffer2), "Buffers equal.");
let database2 = getSimpleDatabase();
try {
request = database2.open(name);
yield* requestFinished(request);
ok(false, "Should have thrown!");
} catch(ex) {
ok(request.resultCode == NS_ERROR_STORAGE_BUSY, "Good result code.");
}
request = database.close();
yield* requestFinished(request);
request = database2.open(name);
yield* requestFinished(request);
request = database2.close();
yield* requestFinished(request);
finishTest();
}

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

@ -32,6 +32,7 @@ skip-if = release_or_beta
[test_persist.js]
[test_removeAppsUpgrade.js]
[test_removeLocalStorage.js]
[test_simpledb.js]
[test_storagePersistentUpgrade.js]
[test_tempMetadataCleanup.js]
[test_unknownFiles.js]