browser_upgrade_backup.js (5057B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 const { Preferences } = ChromeUtils.importESModule( 5 "resource://gre/modules/Preferences.sys.mjs" 6 ); 7 8 const Paths = SessionFile.Paths; 9 const PREF_UPGRADE = "browser.sessionstore.upgradeBackup.latestBuildID"; 10 const PREF_MAX_UPGRADE_BACKUPS = 11 "browser.sessionstore.upgradeBackup.maxUpgradeBackups"; 12 13 /** 14 * Prepares tests by retrieving the current platform's build ID, clearing the 15 * build where the last backup was created and creating arbitrary JSON data 16 * for a new backup. 17 */ 18 function prepareTest() { 19 let result = {}; 20 21 result.buildID = Services.appinfo.platformBuildID; 22 Services.prefs.setCharPref(PREF_UPGRADE, ""); 23 result.contents = { 24 "browser_upgrade_backup.js": Math.random(), 25 }; 26 27 return result; 28 } 29 30 /** 31 * Retrieves all upgrade backups and returns them in an array. 32 */ 33 async function getUpgradeBackups() { 34 let children = await IOUtils.getChildren(Paths.backups); 35 36 return children.filter(path => path.startsWith(Paths.upgradeBackupPrefix)); 37 } 38 39 add_setup(async function () { 40 await SpecialPowers.pushPrefEnv({ 41 set: [["test.wait300msAfterTabSwitch", true]], 42 }); 43 44 // Wait until initialization is complete 45 await SessionStore.promiseInitialized; 46 }); 47 48 add_task(async function test_upgrade_backup() { 49 let test = prepareTest(); 50 info("Let's check if we create an upgrade backup"); 51 await SessionFile.wipe(); 52 await IOUtils.writeJSON(Paths.clean, test.contents, { 53 compress: true, 54 }); 55 info("Call `SessionFile.read()` to set state to 'clean'"); 56 await SessionFile.read(); 57 await SessionFile.write(""); // First call to write() triggers the backup 58 59 Assert.equal( 60 Services.prefs.getCharPref(PREF_UPGRADE), 61 test.buildID, 62 "upgrade backup should be set" 63 ); 64 65 Assert.ok( 66 await IOUtils.exists(Paths.upgradeBackup), 67 "upgrade backup file has been created" 68 ); 69 70 let data = await IOUtils.readJSON(Paths.upgradeBackup, { decompress: true }); 71 Assert.deepEqual( 72 test.contents, 73 data, 74 "upgrade backup contains the expected contents" 75 ); 76 77 info("Let's check that we don't overwrite this upgrade backup"); 78 let newContents = { 79 "something else entirely": Math.random(), 80 }; 81 await IOUtils.writeJSON(Paths.clean, newContents, { 82 compress: true, 83 }); 84 await SessionFile.write(""); // Next call to write() shouldn't trigger the backup 85 data = await IOUtils.readJSON(Paths.upgradeBackup, { decompress: true }); 86 Assert.deepEqual(test.contents, data, "upgrade backup hasn't changed"); 87 }); 88 89 add_task(async function test_upgrade_backup_removal() { 90 let test = prepareTest(); 91 let maxUpgradeBackups = Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3); 92 info("Let's see if we remove backups if there are too many"); 93 await SessionFile.wipe(); 94 await IOUtils.writeJSON(Paths.clean, test.contents, { 95 compress: true, 96 }); 97 info("Call `SessionFile.read()` to set state to 'clean'"); 98 await SessionFile.read(); 99 100 // create dummy backups 101 await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20080101010101", "", { 102 compress: true, 103 }); 104 await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20090101010101", "", { 105 compress: true, 106 }); 107 await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20100101010101", "", { 108 compress: true, 109 }); 110 await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20110101010101", "", { 111 compress: true, 112 }); 113 await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20120101010101", "", { 114 compress: true, 115 }); 116 await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20130101010101", "", { 117 compress: true, 118 }); 119 120 // get currently existing backups 121 let backups = await getUpgradeBackups(); 122 123 info("Write the session to disk and perform a backup"); 124 await SessionFile.write(""); // First call to write() triggers the backup and the cleanup 125 126 // a new backup should have been created (and still exist) 127 is( 128 Services.prefs.getCharPref(PREF_UPGRADE), 129 test.buildID, 130 "upgrade backup should be set" 131 ); 132 Assert.ok( 133 await IOUtils.exists(Paths.upgradeBackup), 134 "upgrade backup file has been created" 135 ); 136 137 // get currently existing backups and check their count 138 let newBackups = await getUpgradeBackups(); 139 is( 140 newBackups.length, 141 maxUpgradeBackups, 142 "expected number of backups are present after removing old backups" 143 ); 144 145 // find all backups that were created during the last call to `SessionFile.write("");` 146 // ie, filter out all the backups that have already been present before the call 147 newBackups = newBackups.filter(function (backup) { 148 return !backups.includes(backup); 149 }); 150 151 // check that exactly one new backup was created 152 is(newBackups.length, 1, "one new backup was created that was not removed"); 153 154 await SessionFile.write(""); // Second call to write() should not trigger anything 155 156 backups = await getUpgradeBackups(); 157 is( 158 backups.length, 159 maxUpgradeBackups, 160 "second call to SessionFile.write() didn't create or remove more backups" 161 ); 162 });