diff options
Diffstat (limited to 'toolkit/components/places/tests/maintenance/head.js')
-rw-r--r-- | toolkit/components/places/tests/maintenance/head.js | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/maintenance/head.js b/toolkit/components/places/tests/maintenance/head.js new file mode 100644 index 0000000000..3d343e92e5 --- /dev/null +++ b/toolkit/components/places/tests/maintenance/head.js @@ -0,0 +1,109 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +// Import common head. +{ + /* import-globals-from ../head_common.js */ + let commonFile = do_get_file("../head_common.js", false); + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); +} + +// Put any other stuff relative to this test folder below. + +XPCOMUtils.defineLazyModuleGetters(this, { + PlacesDBUtils: "resource://gre/modules/PlacesDBUtils.jsm", +}); + +async function createCorruptDb(filename) { + let path = OS.Path.join(OS.Constants.Path.profileDir, filename); + await OS.File.remove(path, { ignoreAbsent: true }); + // Create a corrupt database. + let dir = await OS.File.getCurrentDirectory(); + let src = OS.Path.join(dir, "corruptDB.sqlite"); + await OS.File.copy(src, path); +} + +/** + * Used in _replaceOnStartup_ tests as common test code. It checks whether we + * are properly cloning or replacing a corrupt database. + * + * @param {string} src + * Path to a test database, relative to this test folder + * @param {string} filename + * Database file name + * @param {boolean} shouldClone + * Whether we expect the database to be cloned + * @param {boolean} dbStatus + * The expected final database status + */ +async function test_database_replacement(src, filename, shouldClone, dbStatus) { + registerCleanupFunction(() => { + Services.prefs.clearUserPref("places.database.cloneOnCorruption"); + }); + Services.prefs.setBoolPref("places.database.cloneOnCorruption", shouldClone); + + // Only the main database file (places.sqlite) will be cloned, because + // attached databased would break due to OS file lockings. + let willClone = shouldClone && filename == DB_FILENAME; + + // Ensure that our databases don't exist yet. + let dest = OS.Path.join(OS.Constants.Path.profileDir, filename); + Assert.ok( + !(await OS.File.exists(dest)), + `"${filename} should not exist initially` + ); + let corrupt = OS.Path.join( + OS.Constants.Path.profileDir, + `${filename}.corrupt` + ); + Assert.ok( + !(await OS.File.exists(corrupt)), + `${filename}.corrupt should not exist initially` + ); + + let dir = await OS.File.getCurrentDirectory(); + src = OS.Path.join(dir, src); + await OS.File.copy(src, dest); + + // Create some unique stuff to check later. + let db = await Sqlite.openConnection({ path: dest }); + await db.execute(`CREATE TABLE moz_cloned (id INTEGER PRIMARY KEY)`); + await db.execute(`CREATE TABLE not_cloned (id INTEGER PRIMARY KEY)`); + await db.execute(`DELETE FROM moz_cloned`); // Shouldn't throw. + await db.close(); + + // Open the database with Places. + Services.prefs.setCharPref( + "places.database.replaceDatabaseOnStartup", + filename + ); + Assert.equal(PlacesUtils.history.databaseStatus, dbStatus); + + Assert.ok(await OS.File.exists(dest), "The database should exist"); + + // Check the new database still contains our special data. + db = await Sqlite.openConnection({ path: dest }); + if (willClone) { + await db.execute(`DELETE FROM moz_cloned`); // Shouldn't throw. + } + + // Check the new database is really a new one. + await Assert.rejects( + db.execute(`DELETE FROM not_cloned`), + /no such table/, + "The database should have been replaced" + ); + await db.close(); + + if (willClone) { + Assert.ok( + !(await OS.File.exists(corrupt)), + "The corrupt db should not exist" + ); + } else { + Assert.ok(await OS.File.exists(corrupt), "The corrupt db should exist"); + } +} |