Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
"use strict";
const { AddonsReconciler, CHANGE_INSTALLED, CHANGE_UNINSTALLED } =
ChromeUtils.importESModule(
);
const { AddonsEngine } = ChromeUtils.importESModule(
);
const { Service } = ChromeUtils.importESModule(
);
AddonTestUtils.init(this);
AddonTestUtils.createAppInfo(
"xpcshell@tests.mozilla.org",
"XPCShell",
"1",
"1.9.2"
);
AddonTestUtils.overrideCertDB();
const ADDON_ID = "addon1@tests.mozilla.org";
const XPI = AddonTestUtils.createTempWebExtensionFile({
manifest: {
name: "Test 1",
description: "Test Description",
browser_specific_settings: { gecko: { id: ADDON_ID } },
},
});
function makeAddonsReconciler() {
const log = Service.engineManager.get("addons")._log;
const queueCaller = Async.asyncQueueCaller(log);
return new AddonsReconciler(queueCaller);
}
add_task(async function setup() {
await AddonTestUtils.promiseStartupManager();
Svc.PrefBranch.setBoolPref("engine.addons", true);
await Service.engineManager.register(AddonsEngine);
});
add_task(async function test_defaults() {
_("Ensure new objects have reasonable defaults.");
let reconciler = makeAddonsReconciler();
await reconciler.ensureStateLoaded();
Assert.ok(!reconciler._listening);
Assert.equal("object", typeof reconciler.addons);
Assert.equal(0, Object.keys(reconciler.addons).length);
Assert.equal(0, reconciler._changes.length);
Assert.equal(0, reconciler._listeners.length);
});
add_task(async function test_load_state_empty_file() {
_("Ensure loading from a missing file results in defaults being set.");
let reconciler = makeAddonsReconciler();
await reconciler.ensureStateLoaded();
let loaded = await reconciler.loadState();
Assert.ok(!loaded);
Assert.equal("object", typeof reconciler.addons);
Assert.equal(0, Object.keys(reconciler.addons).length);
Assert.equal(0, reconciler._changes.length);
});
add_task(async function test_install_detection() {
_("Ensure that add-on installation results in appropriate side-effects.");
let reconciler = makeAddonsReconciler();
await reconciler.ensureStateLoaded();
reconciler.startListening();
let before = new Date();
let addon = await installAddon(XPI);
let after = new Date();
Assert.equal(1, Object.keys(reconciler.addons).length);
Assert.ok(addon.id in reconciler.addons);
let record = reconciler.addons[ADDON_ID];
const KEYS = [
"id",
"guid",
"enabled",
"installed",
"modified",
"type",
"scope",
"foreignInstall",
];
for (let key of KEYS) {
Assert.ok(key in record);
Assert.notEqual(null, record[key]);
}
Assert.equal(addon.id, record.id);
Assert.equal(addon.syncGUID, record.guid);
Assert.ok(record.enabled);
Assert.ok(record.installed);
Assert.ok(record.modified >= before && record.modified <= after);
Assert.equal("extension", record.type);
Assert.ok(!record.foreignInstall);
Assert.equal(1, reconciler._changes.length);
let change = reconciler._changes[0];
Assert.ok(change[0] >= before && change[1] <= after);
Assert.equal(CHANGE_INSTALLED, change[1]);
Assert.equal(addon.id, change[2]);
await uninstallAddon(addon);
});
add_task(async function test_uninstall_detection() {
_("Ensure that add-on uninstallation results in appropriate side-effects.");
let reconciler = makeAddonsReconciler();
await reconciler.ensureStateLoaded();
reconciler.startListening();
reconciler._addons = {};
reconciler._changes = [];
let addon = await installAddon(XPI);
let id = addon.id;
reconciler._changes = [];
await uninstallAddon(addon, reconciler);
Assert.equal(1, Object.keys(reconciler.addons).length);
Assert.ok(id in reconciler.addons);
let record = reconciler.addons[id];
Assert.ok(!record.installed);
Assert.equal(1, reconciler._changes.length);
let change = reconciler._changes[0];
Assert.equal(CHANGE_UNINSTALLED, change[1]);
Assert.equal(id, change[2]);
});
add_task(async function test_load_state_future_version() {
_("Ensure loading a file from a future version results in no data loaded.");
const FILENAME = "TEST_LOAD_STATE_FUTURE_VERSION";
let reconciler = makeAddonsReconciler();
await reconciler.ensureStateLoaded();
// First we populate our new file.
let state = { version: 100, addons: { foo: {} }, changes: [[1, 1, "foo"]] };
// jsonSave() expects an object with ._log, so we give it a reconciler
// instance.
await Utils.jsonSave(FILENAME, reconciler, state);
let loaded = await reconciler.loadState(FILENAME);
Assert.ok(!loaded);
Assert.equal("object", typeof reconciler.addons);
Assert.equal(0, Object.keys(reconciler.addons).length);
Assert.equal(0, reconciler._changes.length);
});
add_task(async function test_prune_changes_before_date() {
_("Ensure that old changes are pruned properly.");
let reconciler = makeAddonsReconciler();
await reconciler.ensureStateLoaded();
reconciler._changes = [];
let now = new Date();
const HOUR_MS = 1000 * 60 * 60;
_("Ensure pruning an empty changes array works.");
reconciler.pruneChangesBeforeDate(now);
Assert.equal(0, reconciler._changes.length);
let old = new Date(now.getTime() - HOUR_MS);
let young = new Date(now.getTime() - 1000);
reconciler._changes.push([old, CHANGE_INSTALLED, "foo"]);
reconciler._changes.push([young, CHANGE_INSTALLED, "bar"]);
Assert.equal(2, reconciler._changes.length);
_("Ensure pruning with an old time won't delete anything.");
let threshold = new Date(old.getTime() - 1);
reconciler.pruneChangesBeforeDate(threshold);
Assert.equal(2, reconciler._changes.length);
_("Ensure pruning a single item works.");
threshold = new Date(young.getTime() - 1000);
reconciler.pruneChangesBeforeDate(threshold);
Assert.equal(1, reconciler._changes.length);
Assert.notEqual(undefined, reconciler._changes[0]);
Assert.equal(young, reconciler._changes[0][0]);
Assert.equal("bar", reconciler._changes[0][2]);
_("Ensure pruning all changes works.");
reconciler._changes.push([old, CHANGE_INSTALLED, "foo"]);
reconciler.pruneChangesBeforeDate(now);
Assert.equal(0, reconciler._changes.length);
});