124 lines
3.4 KiB
JavaScript
124 lines
3.4 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
const { AsyncShutdown } = ChromeUtils.importESModule(
|
|
"resource://gre/modules/AsyncShutdown.sys.mjs"
|
|
);
|
|
|
|
function getConnection(dbName, extraOptions = {}) {
|
|
let path = dbName + ".sqlite";
|
|
let options = { path };
|
|
for (let [k, v] of Object.entries(extraOptions)) {
|
|
options[k] = v;
|
|
}
|
|
|
|
return Sqlite.openConnection(options);
|
|
}
|
|
|
|
async function getDummyDatabase(name, extraOptions = {}) {
|
|
const TABLES = {
|
|
dirs: "id INTEGER PRIMARY KEY AUTOINCREMENT, path TEXT",
|
|
files: "id INTEGER PRIMARY KEY AUTOINCREMENT, dir_id INTEGER, path TEXT",
|
|
};
|
|
|
|
let c = await getConnection(name, extraOptions);
|
|
c._initialStatementCount = 0;
|
|
|
|
for (let [k, v] of Object.entries(TABLES)) {
|
|
await c.execute("CREATE TABLE " + k + "(" + v + ")");
|
|
c._initialStatementCount++;
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
function sleep(ms) {
|
|
return new Promise(resolve => {
|
|
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
|
|
|
timer.initWithCallback(
|
|
{
|
|
notify() {
|
|
resolve();
|
|
},
|
|
},
|
|
ms,
|
|
timer.TYPE_ONE_SHOT
|
|
);
|
|
});
|
|
}
|
|
|
|
//
|
|
// ----------- Don't add a test after this one, as it shuts down Sqlite.sys.mjs
|
|
//
|
|
add_task(async function test_shutdown_clients() {
|
|
info("Ensuring that Sqlite.sys.mjs doesn't shutdown before its clients");
|
|
|
|
let assertions = [];
|
|
|
|
let sleepStarted = false;
|
|
let sleepComplete = false;
|
|
Sqlite.shutdown.addBlocker(
|
|
"test_sqlite.js shutdown blocker (sleep)",
|
|
async function () {
|
|
sleepStarted = true;
|
|
await sleep(100);
|
|
sleepComplete = true;
|
|
}
|
|
);
|
|
assertions.push({ name: "sleepStarted", value: () => sleepStarted });
|
|
assertions.push({ name: "sleepComplete", value: () => sleepComplete });
|
|
|
|
Sqlite.shutdown.addBlocker(
|
|
"test_sqlite.js shutdown blocker (immediate)",
|
|
true
|
|
);
|
|
|
|
let dbOpened = false;
|
|
let dbClosed = false;
|
|
|
|
Sqlite.shutdown.addBlocker(
|
|
"test_sqlite.js shutdown blocker (open a connection during shutdown)",
|
|
async function () {
|
|
let db = await getDummyDatabase("opened during shutdown");
|
|
dbOpened = true;
|
|
db.close().then(() => (dbClosed = true)); // Don't wait for this task to complete, Sqlite.sys.mjs must wait automatically
|
|
}
|
|
);
|
|
|
|
assertions.push({ name: "dbOpened", value: () => dbOpened });
|
|
assertions.push({ name: "dbClosed", value: () => dbClosed });
|
|
|
|
info("Now shutdown Sqlite.sys.mjs synchronously");
|
|
Services.prefs.setBoolPref("toolkit.asyncshutdown.testing", true);
|
|
// Check opening a connection during shutdown fails.
|
|
let deferred = Promise.withResolvers();
|
|
let conn = Sqlite.openConnection({
|
|
path: PathUtils.join(PathUtils.profileDir, "test_shutdown.sqlite"),
|
|
testDelayedOpenPromise: deferred.promise,
|
|
});
|
|
await AsyncShutdown.profileBeforeChange._trigger();
|
|
deferred.resolve();
|
|
await Assert.rejects(
|
|
conn,
|
|
/has been shutdown/,
|
|
"Should close the connection and not block"
|
|
);
|
|
Services.prefs.clearUserPref("toolkit.asyncshutdown.testing");
|
|
|
|
for (let { name, value } of assertions) {
|
|
Assert.ok(value(), "Checking: " + name);
|
|
}
|
|
|
|
info("Ensure that we cannot open databases anymore");
|
|
let exn;
|
|
try {
|
|
await getDummyDatabase("opened after shutdown");
|
|
} catch (ex) {
|
|
exn = ex;
|
|
}
|
|
Assert.ok(!!exn, `exception: ${exn.message}`);
|
|
Assert.ok(exn.message.includes("Sqlite.sys.mjs has been shutdown"));
|
|
});
|