--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -1336,45 +1336,56 @@ function* buildSystemAddonUpdates(addons
}
xml += ` </addons>\n`;
}
xml += `</updates>\n`;
return xml;
}
-// system add-on test functions
+let hiddenSystemAddonDir = FileUtils.getDir("ProfD", ["sysfeatures", "hidden"], true);
+do_get_file("data/system_addons/system1_1.xpi").copyTo(hiddenSystemAddonDir, "system1@tests.mozilla.org.xpi");
+do_get_file("data/system_addons/system2_1.xpi").copyTo(hiddenSystemAddonDir, "system2@tests.mozilla.org.xpi");
-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");
+let prefilledSystemAddonDir = FileUtils.getDir("ProfD", ["sysfeatures", "prefilled"], true);
+do_get_file("data/system_addons/system2_2.xpi").copyTo(prefilledSystemAddonDir, "system2@tests.mozilla.org.xpi");
+do_get_file("data/system_addons/system3_2.xpi").copyTo(prefilledSystemAddonDir, "system3@tests.mozilla.org.xpi");
const distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "empty"], true);
+registerDirectory("XREAppFeat", distroDir);
-function getCurrentUpdatesDir() {
+const updatesDir = FileUtils.getDir("ProfD", ["features"], false);
+
+
+/**
+ * Returns current system add-on update directory (stored in pref).
+ */
+function getCurrentSystemAddonUpdatesDir() {
let dir = updatesDir.clone();
let set = JSON.parse(Services.prefs.getCharPref(PREF_SYSTEM_ADDON_SET));
dir.append(set.directory);
return dir;
}
-function clearUpdatesDir() {
+/**
+ * Removes all files from system add-on update directory.
+ */
+function clearSystemAddonUpdatesDir() {
// Delete any existing directories
if (updatesDir.exists())
updatesDir.remove(true);
Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET);
}
+/**
+ * Installs a known set of add-ons into the system add-on update directory.
+ */
function buildPrefilledUpdatesDir() {
- clearUpdatesDir();
+ clearSystemAddonUpdatesDir();
// 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
@@ -1390,29 +1401,34 @@ function buildPrefilledUpdatesDir() {
},
"system3@tests.mozilla.org": {
version: "2.0"
},
}
}));
}
-function* check_installed(conditions) {
+/**
+ * Check currently installed ssystem add-ons against a set of conditions.
+ *
+ * @param {Array<Object>} conditions - an array of objects of the form { isUpgrade: false, version: null}
+ */
+function* checkInstalledSystemAddons(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;
+ let expectedDir = isUpgrade ? getCurrentSystemAddonUpdatesDir() : 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);
@@ -1449,50 +1465,66 @@ function* check_installed(conditions) {
if (addon)
BootstrapMonitor.checkAddonInstalled(id);
else
BootstrapMonitor.checkAddonNotInstalled(id);
}
}
}
-function* get_directories() {
+/**
+ * Returns all system add-on updates directories.
+ */
+function* getSystemAddonDirectories() {
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) {
+/**
+ * Sets up initial system add-on update conditions.
+ *
+ * @param {Object<function, Array<Object>} setup - an object containing a setup function and an array of objects
+ * of the form {isUpgrade: false, version: null}
+ */
+function* setupSystemAddonConditions(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);
+ yield checkInstalledSystemAddons(setup.initialState);
}
-function* verify_state(initialState, finalState = undefined, alreadyUpgraded = false) {
+/**
+ * Verify state of system add-ons after installation.
+ *
+ * @param {Array<Object>} initialState - an array of objects of the form {isUpgrade: false, version: null}
+ * @param {Array<Object>} finalState - an array of objects of the form {isUpgrade: false, version: null}
+ * @param {Boolean} alreadyUpgraded - whether a restartless upgrade has already been performed.
+ */
+function* verifySystemAddonState(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++;
}
@@ -1506,31 +1538,47 @@ function* verify_state(initialState, fin
// 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();
+ let dirs = yield getSystemAddonDirectories();
do_check_eq(dirs.length, expectedDirs);
- yield check_installed(...finalState);
+ yield checkInstalledSystemAddons(...finalState);
// Check that the new state is active after a restart
yield promiseRestartManager();
- yield check_installed(finalState);
+ yield checkInstalledSystemAddons(finalState);
}
-function* exec_test(setupName, testName) {
- let setup = TEST_CONDITIONS[setupName];
- let test = TESTS[testName];
+/**
+ * Run system add-on tests and compare the results against a set of expected conditions.
+ *
+ * @param {String} setupName - name of the current setup conditions.
+ * @param {Object<function, Array<Object>} setup - 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.
+ * @param {Array<Object>} test - The test 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.
+ */
- yield setup_conditions(setup);
+function* execSystemAddonTest(setupName, setup, test) {
+ yield setupSystemAddonConditions(setup);
try {
if ("test" in test) {
yield test.test();
} else {
yield installSystemAddons(yield buildSystemAddonUpdates(test.updateList, root), testserver);
}
@@ -1541,15 +1589,15 @@ function* exec_test(setupName, testName)
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]);
+ yield verifySystemAddonState(setup.initialState, test.finalState[setupName]);
} else {
- yield verify_state(setup.initialState, test.finalState);
+ yield verifySystemAddonState(setup.initialState, test.finalState);
}
yield promiseShutdownManager();
}
\ No newline at end of file
--- a/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js
@@ -3,20 +3,16 @@
const PREF_SYSTEM_ADDON_SET = "extensions.systemAddonSet";
const PREF_SYSTEM_ADDON_UPDATE_URL = "extensions.systemAddon.update.url";
const PREF_APP_UPDATE_ENABLED = "app.update.enabled";
Components.utils.import("resource://testing-common/httpd.js");
BootstrapMonitor.init();
-const updatesDir = FileUtils.getDir("ProfD", ["features"], false);
-
-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/"
@@ -28,31 +24,31 @@ Services.prefs.setCharPref(PREF_SYSTEM_A
*
* 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() {
- clearUpdatesDir();
+ clearSystemAddonUpdatesDir();
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() {
- clearUpdatesDir();
+ clearSystemAddonUpdatesDir();
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}
@@ -134,17 +130,17 @@ const TESTS = {
{ 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
+ // Set this to `true` to so `verifySystemAddonState()` 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" },
@@ -365,200 +361,203 @@ const TESTS = {
add_task(function* setup() {
// Initialise the profile
startupManager();
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);
+ for (let setupName of Object.keys(TEST_CONDITIONS)) {
+ for (let testName of Object.keys(TESTS)) {
+ do_print("Running test " + setupName + " " + testName);
- yield exec_test(setup, test);
+ let setup = TEST_CONDITIONS[setupName];
+ let test = TESTS[testName];
+
+ yield execSystemAddonTest(setupName, 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 setupSystemAddonConditions(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, [
+ yield verifySystemAddonState(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);
+ yield setupSystemAddonConditions(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 verifySystemAddonState(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);
+ yield setupSystemAddonConditions(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 verifySystemAddonState(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 setupSystemAddonConditions(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 verifySystemAddonState(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 setupSystemAddonConditions(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, [
+ yield verifySystemAddonState(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 setupSystemAddonConditions(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 verifySystemAddonState(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);
+ yield setupSystemAddonConditions(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, [
+ yield verifySystemAddonState(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 setupSystemAddonConditions(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, [
+ yield verifySystemAddonState(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 setupSystemAddonConditions(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, [
+ yield verifySystemAddonState(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();
+ let dirs = yield getSystemAddonDirectories();
do_check_eq(dirs.length, 1);
yield promiseShutdownManager();
});