diff options
Diffstat (limited to 'browser/components/sessionstore/test/browser_upgrade_backup.js')
-rw-r--r-- | browser/components/sessionstore/test/browser_upgrade_backup.js | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/browser/components/sessionstore/test/browser_upgrade_backup.js b/browser/components/sessionstore/test/browser_upgrade_backup.js new file mode 100644 index 0000000000..bbd680ed09 --- /dev/null +++ b/browser/components/sessionstore/test/browser_upgrade_backup.js @@ -0,0 +1,197 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +ChromeUtils.import("resource://gre/modules/Services.jsm", this); +ChromeUtils.import("resource://gre/modules/osfile.jsm", this); +ChromeUtils.import("resource://gre/modules/Preferences.jsm", this); + +const Paths = SessionFile.Paths; +const PREF_UPGRADE = "browser.sessionstore.upgradeBackup.latestBuildID"; +const PREF_MAX_UPGRADE_BACKUPS = + "browser.sessionstore.upgradeBackup.maxUpgradeBackups"; + +/** + * Prepares tests by retrieving the current platform's build ID, clearing the + * build where the last backup was created and creating arbitrary JSON data + * for a new backup. + */ +function prepareTest() { + let result = {}; + + result.buildID = Services.appinfo.platformBuildID; + Services.prefs.setCharPref(PREF_UPGRADE, ""); + result.contents = JSON.stringify({ + "browser_upgrade_backup.js": Math.random(), + }); + + return result; +} + +/** + * Retrieves all upgrade backups and returns them in an array. + */ +async function getUpgradeBackups() { + let iterator; + let backups = []; + + try { + iterator = new OS.File.DirectoryIterator(Paths.backups); + + // iterate over all files in the backup directory + await iterator.forEach(function(file) { + // check the upgradeBackupPrefix + if (file.path.startsWith(Paths.upgradeBackupPrefix)) { + // the file is a backup + backups.push(file.path); + } + }, this); + } finally { + if (iterator) { + iterator.close(); + } + } + + // return results + return backups; +} + +add_task(async function init() { + // Wait until initialization is complete + await SessionStore.promiseInitialized; +}); + +add_task(async function test_upgrade_backup() { + let test = prepareTest(); + info("Let's check if we create an upgrade backup"); + await SessionFile.wipe(); + await OS.File.writeAtomic(Paths.clean, test.contents, { + encoding: "utf-8", + compression: "lz4", + }); + await SessionFile.read(); // First call to read() initializes the SessionWorker + await SessionFile.write(""); // First call to write() triggers the backup + + is( + Services.prefs.getCharPref(PREF_UPGRADE), + test.buildID, + "upgrade backup should be set" + ); + + is( + await OS.File.exists(Paths.upgradeBackup), + true, + "upgrade backup file has been created" + ); + + let data = await OS.File.read(Paths.upgradeBackup, { compression: "lz4" }); + is( + test.contents, + new TextDecoder().decode(data), + "upgrade backup contains the expected contents" + ); + + info("Let's check that we don't overwrite this upgrade backup"); + let newContents = JSON.stringify({ + "something else entirely": Math.random(), + }); + await OS.File.writeAtomic(Paths.clean, newContents, { + encoding: "utf-8", + compression: "lz4", + }); + await SessionFile.read(); // Reinitialize the SessionWorker + await SessionFile.write(""); // Next call to write() shouldn't trigger the backup + data = await OS.File.read(Paths.upgradeBackup, { compression: "lz4" }); + is( + test.contents, + new TextDecoder().decode(data), + "upgrade backup hasn't changed" + ); +}); + +add_task(async function test_upgrade_backup_removal() { + let test = prepareTest(); + let maxUpgradeBackups = Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3); + info("Let's see if we remove backups if there are too many"); + await SessionFile.wipe(); + await OS.File.makeDir(Paths.backups); + await OS.File.writeAtomic(Paths.clean, test.contents, { + encoding: "utf-8", + compression: "lz4", + }); + + // if the nextUpgradeBackup already exists (from another test), remove it + if (OS.File.exists(Paths.nextUpgradeBackup)) { + await OS.File.remove(Paths.nextUpgradeBackup); + } + + // create dummy backups + await OS.File.writeAtomic(Paths.upgradeBackupPrefix + "20080101010101", "", { + encoding: "utf-8", + compression: "lz4", + }); + await OS.File.writeAtomic(Paths.upgradeBackupPrefix + "20090101010101", "", { + encoding: "utf-8", + compression: "lz4", + }); + await OS.File.writeAtomic(Paths.upgradeBackupPrefix + "20100101010101", "", { + encoding: "utf-8", + compression: "lz4", + }); + await OS.File.writeAtomic(Paths.upgradeBackupPrefix + "20110101010101", "", { + encoding: "utf-8", + compression: "lz4", + }); + await OS.File.writeAtomic(Paths.upgradeBackupPrefix + "20120101010101", "", { + encoding: "utf-8", + compression: "lz4", + }); + await OS.File.writeAtomic(Paths.upgradeBackupPrefix + "20130101010101", "", { + encoding: "utf-8", + compression: "lz4", + }); + + // get currently existing backups + let backups = await getUpgradeBackups(); + + // trigger new backup + await SessionFile.read(); // First call to read() initializes the SessionWorker + await SessionFile.write(""); // First call to write() triggers the backup and the cleanup + + // a new backup should have been created (and still exist) + is( + Services.prefs.getCharPref(PREF_UPGRADE), + test.buildID, + "upgrade backup should be set" + ); + is( + await OS.File.exists(Paths.upgradeBackup), + true, + "upgrade backup file has been created" + ); + + // get currently existing backups and check their count + let newBackups = await getUpgradeBackups(); + is( + newBackups.length, + maxUpgradeBackups, + "expected number of backups are present after removing old backups" + ); + + // find all backups that were created during the last call to `SessionFile.write("");` + // ie, filter out all the backups that have already been present before the call + newBackups = newBackups.filter(function(backup) { + return !backups.includes(backup); + }); + + // check that exactly one new backup was created + is(newBackups.length, 1, "one new backup was created that was not removed"); + + await SessionFile.write(""); // Second call to write() should not trigger anything + + backups = await getUpgradeBackups(); + is( + backups.length, + maxUpgradeBackups, + "second call to SessionFile.write() didn't create or remove more backups" + ); +}); |