/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ const { Preferences } = ChromeUtils.importESModule( "resource://gre/modules/Preferences.sys.mjs" ); 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 = { "browser_upgrade_backup.js": Math.random(), }; return result; } /** * Retrieves all upgrade backups and returns them in an array. */ async function getUpgradeBackups() { let children = await IOUtils.getChildren(Paths.backups); return children.filter(path => path.startsWith(Paths.upgradeBackupPrefix)); } add_setup(async function () { // 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 IOUtils.writeJSON(Paths.clean, test.contents, { compress: true, }); info("Call `SessionFile.read()` to set state to 'clean'"); await SessionFile.read(); await SessionFile.write(""); // First call to write() triggers the backup Assert.equal( Services.prefs.getCharPref(PREF_UPGRADE), test.buildID, "upgrade backup should be set" ); Assert.ok( await IOUtils.exists(Paths.upgradeBackup), "upgrade backup file has been created" ); let data = await IOUtils.readJSON(Paths.upgradeBackup, { decompress: true }); Assert.deepEqual( test.contents, data, "upgrade backup contains the expected contents" ); info("Let's check that we don't overwrite this upgrade backup"); let newContents = { "something else entirely": Math.random(), }; await IOUtils.writeJSON(Paths.clean, newContents, { compress: true, }); await SessionFile.write(""); // Next call to write() shouldn't trigger the backup data = await IOUtils.readJSON(Paths.upgradeBackup, { decompress: true }); Assert.deepEqual(test.contents, 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 IOUtils.writeJSON(Paths.clean, test.contents, { compress: true, }); info("Call `SessionFile.read()` to set state to 'clean'"); await SessionFile.read(); // create dummy backups await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20080101010101", "", { compress: true, }); await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20090101010101", "", { compress: true, }); await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20100101010101", "", { compress: true, }); await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20110101010101", "", { compress: true, }); await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20120101010101", "", { compress: true, }); await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20130101010101", "", { compress: true, }); // get currently existing backups let backups = await getUpgradeBackups(); info("Write the session to disk and perform a backup"); 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" ); Assert.ok( await IOUtils.exists(Paths.upgradeBackup), "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" ); });