diff options
Diffstat (limited to 'toolkit/mozapps/webextensions/test/xpcshell/test_system_update.js')
-rw-r--r-- | toolkit/mozapps/webextensions/test/xpcshell/test_system_update.js | 788 |
1 files changed, 788 insertions, 0 deletions
diff --git a/toolkit/mozapps/webextensions/test/xpcshell/test_system_update.js b/toolkit/mozapps/webextensions/test/xpcshell/test_system_update.js new file mode 100644 index 000000000..c8e314427 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpcshell/test_system_update.js @@ -0,0 +1,788 @@ +// Tests that we reset to the default system add-ons correctly when switching +// application versions +const PREF_SYSTEM_ADDON_SET = "extensions.systemAddonSet"; +const PREF_SYSTEM_ADDON_UPDATE_URL = "extensions.systemAddon.update.url"; +const PREF_XPI_STATE = "extensions.xpiState"; +const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; + +Components.utils.import("resource://testing-common/httpd.js"); +const { computeHash } = Components.utils.import("resource://gre/modules/addons/ProductAddonChecker.jsm"); + +BootstrapMonitor.init(); + +const updatesDir = FileUtils.getDir("ProfD", ["features"], false); + +function getCurrentUpdatesDir() { + let dir = updatesDir.clone(); + let set = JSON.parse(Services.prefs.getCharPref(PREF_SYSTEM_ADDON_SET)); + dir.append(set.directory); + return dir; +} + +function clearUpdatesDir() { + // Delete any existing directories + if (updatesDir.exists()) + updatesDir.remove(true); + + Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET); +} + +function buildPrefilledUpdatesDir() { + clearUpdatesDir(); + + // Build the test set + let dir = FileUtils.getDir("ProfD", ["features", "prefilled"], true); + + do_get_file("data/system_addons/system2_2.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi"); + do_get_file("data/system_addons/system3_2.xpi").copyTo(dir, "system3@tests.mozilla.org.xpi"); + + // Mark these in the past so the startup file scan notices when files have changed properly + FileUtils.getFile("ProfD", ["features", "prefilled", "system2@tests.mozilla.org.xpi"]).lastModifiedTime -= 10000; + FileUtils.getFile("ProfD", ["features", "prefilled", "system3@tests.mozilla.org.xpi"]).lastModifiedTime -= 10000; + + Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify({ + schema: 1, + directory: dir.leafName, + addons: { + "system2@tests.mozilla.org": { + version: "2.0" + }, + "system3@tests.mozilla.org": { + version: "2.0" + }, + } + })); +} + +let dir = FileUtils.getDir("ProfD", ["sysfeatures", "hidden"], true); +do_get_file("data/system_addons/system1_1.xpi").copyTo(dir, "system1@tests.mozilla.org.xpi"); +do_get_file("data/system_addons/system2_1.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi"); + +dir = FileUtils.getDir("ProfD", ["sysfeatures", "prefilled"], true); +do_get_file("data/system_addons/system2_2.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi"); +do_get_file("data/system_addons/system3_2.xpi").copyTo(dir, "system3@tests.mozilla.org.xpi"); + +const distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "empty"], true); +registerDirectory("XREAppFeat", distroDir); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2"); + +var testserver = new HttpServer(); +testserver.registerDirectory("/data/", do_get_file("data/system_addons")); +testserver.start(); +var root = testserver.identity.primaryScheme + "://" + + testserver.identity.primaryHost + ":" + + testserver.identity.primaryPort + "/data/" +Services.prefs.setCharPref(PREF_SYSTEM_ADDON_UPDATE_URL, root + "update.xml"); + +function makeUUID() { + let uuidGen = AM_Cc["@mozilla.org/uuid-generator;1"]. + getService(AM_Ci.nsIUUIDGenerator); + return uuidGen.generateUUID().toString(); +} + +function* check_installed(conditions) { + for (let i = 0; i < conditions.length; i++) { + let condition = conditions[i]; + let id = "system" + (i + 1) + "@tests.mozilla.org"; + let addon = yield promiseAddonByID(id); + + if (!("isUpgrade" in condition) || !("version" in condition)) { + throw Error("condition must contain isUpgrade and version"); + } + let isUpgrade = conditions[i].isUpgrade; + let version = conditions[i].version; + + let expectedDir = isUpgrade ? getCurrentUpdatesDir() : distroDir; + + if (version) { + do_print(`Checking state of add-on ${id}, expecting version ${version}`); + + // Add-on should be installed + do_check_neq(addon, null); + do_check_eq(addon.version, version); + do_check_true(addon.isActive); + do_check_false(addon.foreignInstall); + do_check_true(addon.hidden); + do_check_true(addon.isSystem); + + // Verify the add-ons file is in the right place + let file = expectedDir.clone(); + file.append(id + ".xpi"); + do_check_true(file.exists()); + do_check_true(file.isFile()); + + let uri = addon.getResourceURI(null); + do_check_true(uri instanceof AM_Ci.nsIFileURL); + do_check_eq(uri.file.path, file.path); + + if (isUpgrade) { + do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_SYSTEM); + } + + // Verify the add-on actually started + BootstrapMonitor.checkAddonStarted(id, version); + } + else { + do_print(`Checking state of add-on ${id}, expecting it to be missing`); + + if (isUpgrade) { + // Add-on should not be installed + do_check_eq(addon, null); + } + + BootstrapMonitor.checkAddonNotStarted(id); + + if (addon) + BootstrapMonitor.checkAddonInstalled(id); + else + BootstrapMonitor.checkAddonNotInstalled(id); + } + } +} + + +/** + * Defines the set of initial conditions to run each test against. Each should + * define the following properties: + * + * setup: A task to setup the profile into the initial state. + * initialState: The initial expected system add-on state after setup has run. + */ +const TEST_CONDITIONS = { + // Runs tests with no updated or default system add-ons initially installed + blank: { + setup: function*() { + clearUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + }, + // Runs tests with default system add-ons installed + withAppSet: { + setup: function*() { + clearUpdatesDir(); + distroDir.leafName = "prefilled"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with updated system add-ons installed + withProfileSet: { + setup: function*() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with both default and updated system add-ons installed + withBothSets: { + setup: function*() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "hidden"; + }, + initialState: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, +}; + + +/** + * The tests to run. Each test must define an updateList or test. The following + * properties are used: + * + * updateList: The set of add-ons the server should respond with. + * test: A function to run to perform the update check (replaces + * updateList) + * fails: An optional property, if true the update check is expected to + * fail. + * finalState: An optional property, the expected final state of system add-ons, + * if missing the test condition's initialState is used. + */ +const TESTS = { + // Test that a blank response does nothing + blank: { + updateList: null, + }, + + // Test that an empty list removes existing updates, leaving defaults. + empty: { + updateList: [], + finalState: { + blank: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withAppSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withProfileSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withBothSets: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: false, version: "1.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + // Set this to `true` to so `verify_state()` expects a blank profile dir + { isUpgrade: true, version: null} + ] + }, + }, + // Tests that a new set of system add-ons gets installed + newset: { + updateList: [ + { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" }, + { id: "system5@tests.mozilla.org", version: "1.0", path: "system5_1.xpi" } + ], + finalState: { + blank: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: true, version: "1.0"} + ], + withAppSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: true, version: "1.0"} + ], + withProfileSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: true, version: "1.0"} + ], + withBothSets: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: false, version: "1.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: true, version: "1.0"} + ] + } + }, + + // Tests that an upgraded set of system add-ons gets installed + upgrades: { + updateList: [ + { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi" }, + { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" } + ], + finalState: { + blank: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withAppSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withProfileSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withBothSets: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + } + }, + + // Tests that a set of system add-ons, some new, some existing gets installed + overlapping: { + updateList: [ + { id: "system1@tests.mozilla.org", version: "2.0", path: "system1_2.xpi" }, + { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, + { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" }, + { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" } + ], + finalState: { + blank: [ + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: false, version: null} + ], + withAppSet: [ + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: false, version: null} + ], + withProfileSet: [ + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: false, version: null} + ], + withBothSets: [ + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: false, version: null} + ] + } + }, + + // Specifying an incorrect version should stop us updating anything + badVersion: { + fails: true, + updateList: [ + { id: "system2@tests.mozilla.org", version: "4.0", path: "system2_3.xpi" }, + { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" } + ], + }, + + // Specifying an invalid size should stop us updating anything + badSize: { + fails: true, + updateList: [ + { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi", size: 2 }, + { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" } + ], + }, + + // Specifying an incorrect hash should stop us updating anything + badHash: { + fails: true, + updateList: [ + { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi" }, + { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi", hashFunction: "sha1", hashValue: "205a4c49bd513ebd30594e380c19e86bba1f83e2" } + ], + }, + + // Correct sizes and hashes should work + checkSizeHash: { + updateList: [ + { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi", size: 4697 }, + { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi", hashFunction: "sha1", hashValue: "a4c7198d56deb315511c02937fd96c696de6cb84" }, + { id: "system5@tests.mozilla.org", version: "1.0", path: "system5_1.xpi", size: 4691, hashFunction: "sha1", hashValue: "6887b916a1a9a5338b0df4181f6187f5396861eb" } + ], + finalState: { + blank: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"} + ], + withAppSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"} + ], + withProfileSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"} + ], + withBothSets: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"} + ] + } + }, + + // A bad certificate should stop updates + badCert: { + fails: true, + updateList: [ + { id: "system1@tests.mozilla.org", version: "1.0", path: "system1_1_badcert.xpi" }, + { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } + ], + }, + + // An unpacked add-on should stop updates. + notPacked: { + fails: true, + updateList: [ + { id: "system6@tests.mozilla.org", version: "1.0", path: "system6_1_unpack.xpi" }, + { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } + ], + }, + + // A non-bootstrap add-on should stop updates. + notBootstrap: { + fails: true, + updateList: [ + { id: "system6@tests.mozilla.org", version: "1.0", path: "system6_2_notBootstrap.xpi" }, + { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } + ], + }, + + // A non-multiprocess add-on should stop updates. + notMultiprocess: { + fails: true, + updateList: [ + { id: "system6@tests.mozilla.org", version: "1.0", path: "system6_3_notMultiprocess.xpi" }, + { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } + ], + } +} + +add_task(function* setup() { + // Initialise the profile + startupManager(); + yield promiseShutdownManager(); +}) + +function* get_directories() { + let subdirs = []; + + if (yield OS.File.exists(updatesDir.path)) { + let iterator = new OS.File.DirectoryIterator(updatesDir.path); + yield iterator.forEach(entry => { + if (entry.isDir) { + subdirs.push(entry); + } + }); + iterator.close(); + } + + return subdirs; +} + +function* setup_conditions(setup) { + do_print("Clearing existing database."); + Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET); + distroDir.leafName = "empty"; + startupManager(false); + yield promiseShutdownManager(); + + do_print("Setting up conditions."); + yield setup.setup(); + + startupManager(false); + + // Make sure the initial state is correct + do_print("Checking initial state."); + yield check_installed(setup.initialState); +} + +function* verify_state(initialState, finalState = undefined, alreadyUpgraded = false) { + let expectedDirs = 0; + + // If the initial state was using the profile set then that directory will + // still exist. + + if (initialState.some(a => a.isUpgrade)) { + expectedDirs++; + } + + if (finalState == undefined) { + finalState = initialState; + } + else if (finalState.some(a => a.isUpgrade)) { + // If the new state is using the profile then that directory will exist. + expectedDirs++; + } + + // Since upgrades are restartless now, the previous update dir hasn't been removed. + if (alreadyUpgraded) { + expectedDirs++; + } + + do_print("Checking final state."); + + let dirs = yield get_directories(); + do_check_eq(dirs.length, expectedDirs); + + yield check_installed(...finalState); + + // Check that the new state is active after a restart + yield promiseRestartManager(); + yield check_installed(finalState); +} + +function* exec_test(setupName, testName) { + let setup = TEST_CONDITIONS[setupName]; + let test = TESTS[testName]; + + yield setup_conditions(setup); + + try { + if ("test" in test) { + yield test.test(); + } + else { + yield installSystemAddons(yield buildSystemAddonUpdates(test.updateList, root), testserver); + } + + if (test.fails) { + do_throw("Expected this test to fail"); + } + } + catch (e) { + if (!test.fails) { + do_throw(e); + } + } + + // some tests have a different expected combination of default + // and updated add-ons. + if (test.finalState && setupName in test.finalState) { + yield verify_state(setup.initialState, test.finalState[setupName]); + } + else { + yield verify_state(setup.initialState, test.finalState); + } + + yield promiseShutdownManager(); +} + +add_task(function*() { + for (let setup of Object.keys(TEST_CONDITIONS)) { + for (let test of Object.keys(TESTS)) { + do_print("Running test " + setup + " " + test); + + yield exec_test(setup, test); + } + } +}); + +// Some custom tests +// Test that the update check is performed as part of the regular add-on update +// check +add_task(function* test_addon_update() { + yield setup_conditions(TEST_CONDITIONS.blank); + + yield updateAllSystemAddons(yield buildSystemAddonUpdates([ + { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, + { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" } + ], root), testserver); + + yield verify_state(TEST_CONDITIONS.blank.initialState, [ + {isUpgrade: false, version: null}, + {isUpgrade: true, version: "2.0"}, + {isUpgrade: true, version: "2.0"}, + {isUpgrade: false, version: null}, + {isUpgrade: false, version: null} + ]); + + yield promiseShutdownManager(); +}); + +// Disabling app updates should block system add-on updates +add_task(function* test_app_update_disabled() { + yield setup_conditions(TEST_CONDITIONS.blank); + + Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, false); + yield updateAllSystemAddons(yield buildSystemAddonUpdates([ + { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, + { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" } + ], root), testserver); + Services.prefs.clearUserPref(PREF_APP_UPDATE_ENABLED); + + yield verify_state(TEST_CONDITIONS.blank.initialState); + + yield promiseShutdownManager(); +}); + +// Safe mode should block system add-on updates +add_task(function* test_safe_mode() { + gAppInfo.inSafeMode = true; + + yield setup_conditions(TEST_CONDITIONS.blank); + + Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, false); + yield updateAllSystemAddons(yield buildSystemAddonUpdates([ + { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, + { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" } + ], root), testserver); + Services.prefs.clearUserPref(PREF_APP_UPDATE_ENABLED); + + yield verify_state(TEST_CONDITIONS.blank.initialState); + + yield promiseShutdownManager(); + + gAppInfo.inSafeMode = false; +}); + +// Tests that a set that matches the default set does nothing +add_task(function* test_match_default() { + yield setup_conditions(TEST_CONDITIONS.withAppSet); + + yield installSystemAddons(yield buildSystemAddonUpdates([ + { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, + { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" } + ], root), testserver); + + // Shouldn't have installed an updated set + yield verify_state(TEST_CONDITIONS.withAppSet.initialState); + + yield promiseShutdownManager(); +}); + +// Tests that a set that matches the hidden default set works +add_task(function* test_match_default_revert() { + yield setup_conditions(TEST_CONDITIONS.withBothSets); + + yield installSystemAddons(yield buildSystemAddonUpdates([ + { id: "system1@tests.mozilla.org", version: "1.0", path: "system1_1.xpi" }, + { id: "system2@tests.mozilla.org", version: "1.0", path: "system2_1.xpi" } + ], root), testserver); + + // This should revert to the default set instead of installing new versions + // into an updated set. + yield verify_state(TEST_CONDITIONS.withBothSets.initialState, [ + {isUpgrade: false, version: "1.0"}, + {isUpgrade: false, version: "1.0"}, + {isUpgrade: false, version: null}, + {isUpgrade: false, version: null}, + {isUpgrade: false, version: null} + ]); + + yield promiseShutdownManager(); +}); + +// Tests that a set that matches the current set works +add_task(function* test_match_current() { + yield setup_conditions(TEST_CONDITIONS.withBothSets); + + yield installSystemAddons(yield buildSystemAddonUpdates([ + { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, + { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" } + ], root), testserver); + + // This should remain with the current set instead of creating a new copy + let set = JSON.parse(Services.prefs.getCharPref(PREF_SYSTEM_ADDON_SET)); + do_check_eq(set.directory, "prefilled"); + + yield verify_state(TEST_CONDITIONS.withBothSets.initialState); + + yield promiseShutdownManager(); +}); + +// Tests that a set with a minor change doesn't re-download existing files +add_task(function* test_no_download() { + yield setup_conditions(TEST_CONDITIONS.withBothSets); + + // The missing file here is unneeded since there is a local version already + yield installSystemAddons(yield buildSystemAddonUpdates([ + { id: "system2@tests.mozilla.org", version: "2.0", path: "missing.xpi" }, + { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" } + ], root), testserver); + + yield verify_state(TEST_CONDITIONS.withBothSets.initialState, [ + {isUpgrade: false, version: "1.0"}, + {isUpgrade: true, version: "2.0"}, + {isUpgrade: false, version: null}, + {isUpgrade: true, version: "1.0"}, + {isUpgrade: false, version: null} + ]); + + yield promiseShutdownManager(); +}); + +// Tests that a second update before a restart works +add_task(function* test_double_update() { + yield setup_conditions(TEST_CONDITIONS.withAppSet); + + yield installSystemAddons(yield buildSystemAddonUpdates([ + { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, + { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } + ], root), testserver); + + yield installSystemAddons(yield buildSystemAddonUpdates([ + { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" }, + { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" } + ], root), testserver); + + yield verify_state(TEST_CONDITIONS.withAppSet.initialState, [ + {isUpgrade: false, version: null}, + {isUpgrade: false, version: "2.0"}, + {isUpgrade: true, version: "2.0"}, + {isUpgrade: true, version: "1.0"}, + {isUpgrade: false, version: null} + ], true); + + yield promiseShutdownManager(); +}); + +// A second update after a restart will delete the original unused set +add_task(function* test_update_purges() { + yield setup_conditions(TEST_CONDITIONS.withBothSets); + + yield installSystemAddons(yield buildSystemAddonUpdates([ + { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, + { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } + ], root), testserver); + + yield verify_state(TEST_CONDITIONS.withBothSets.initialState, [ + {isUpgrade: false, version: "1.0"}, + {isUpgrade: true, version: "2.0"}, + {isUpgrade: true, version: "1.0"}, + {isUpgrade: false, version: null}, + {isUpgrade: false, version: null} + ]); + + yield installSystemAddons(yield buildSystemAddonUpdates(null), testserver); + + let dirs = yield get_directories(); + do_check_eq(dirs.length, 1); + + yield promiseShutdownManager(); +}); |