test_addons_reconciler.js (6396B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { AddonsReconciler, CHANGE_INSTALLED, CHANGE_UNINSTALLED } = 7 ChromeUtils.importESModule( 8 "resource://services-sync/addonsreconciler.sys.mjs" 9 ); 10 const { AddonsEngine } = ChromeUtils.importESModule( 11 "resource://services-sync/engines/addons.sys.mjs" 12 ); 13 const { Service } = ChromeUtils.importESModule( 14 "resource://services-sync/service.sys.mjs" 15 ); 16 17 AddonTestUtils.init(this); 18 AddonTestUtils.createAppInfo( 19 "xpcshell@tests.mozilla.org", 20 "XPCShell", 21 "1", 22 "1.9.2" 23 ); 24 AddonTestUtils.overrideCertDB(); 25 26 const ADDON_ID = "addon1@tests.mozilla.org"; 27 const XPI = AddonTestUtils.createTempWebExtensionFile({ 28 manifest: { 29 name: "Test 1", 30 description: "Test Description", 31 browser_specific_settings: { gecko: { id: ADDON_ID } }, 32 }, 33 }); 34 35 function makeAddonsReconciler() { 36 const log = Service.engineManager.get("addons")._log; 37 const queueCaller = Async.asyncQueueCaller(log); 38 return new AddonsReconciler(queueCaller); 39 } 40 41 add_task(async function setup() { 42 await AddonTestUtils.promiseStartupManager(); 43 Svc.PrefBranch.setBoolPref("engine.addons", true); 44 await Service.engineManager.register(AddonsEngine); 45 }); 46 47 add_task(async function test_defaults() { 48 _("Ensure new objects have reasonable defaults."); 49 50 let reconciler = makeAddonsReconciler(); 51 await reconciler.ensureStateLoaded(); 52 53 Assert.ok(!reconciler._listening); 54 Assert.equal("object", typeof reconciler.addons); 55 Assert.equal(0, Object.keys(reconciler.addons).length); 56 Assert.equal(0, reconciler._changes.length); 57 Assert.equal(0, reconciler._listeners.length); 58 }); 59 60 add_task(async function test_load_state_empty_file() { 61 _("Ensure loading from a missing file results in defaults being set."); 62 63 let reconciler = makeAddonsReconciler(); 64 await reconciler.ensureStateLoaded(); 65 66 let loaded = await reconciler.loadState(); 67 Assert.ok(!loaded); 68 69 Assert.equal("object", typeof reconciler.addons); 70 Assert.equal(0, Object.keys(reconciler.addons).length); 71 Assert.equal(0, reconciler._changes.length); 72 }); 73 74 add_task(async function test_install_detection() { 75 _("Ensure that add-on installation results in appropriate side-effects."); 76 77 let reconciler = makeAddonsReconciler(); 78 await reconciler.ensureStateLoaded(); 79 reconciler.startListening(); 80 81 let before = new Date(); 82 let addon = await installAddon(XPI); 83 let after = new Date(); 84 85 Assert.equal(1, Object.keys(reconciler.addons).length); 86 Assert.ok(addon.id in reconciler.addons); 87 let record = reconciler.addons[ADDON_ID]; 88 89 const KEYS = [ 90 "id", 91 "guid", 92 "enabled", 93 "installed", 94 "modified", 95 "type", 96 "scope", 97 "foreignInstall", 98 ]; 99 for (let key of KEYS) { 100 Assert.ok(key in record); 101 Assert.notEqual(null, record[key]); 102 } 103 104 Assert.equal(addon.id, record.id); 105 Assert.equal(addon.syncGUID, record.guid); 106 Assert.ok(record.enabled); 107 Assert.ok(record.installed); 108 Assert.ok(record.modified >= before && record.modified <= after); 109 Assert.equal("extension", record.type); 110 Assert.ok(!record.foreignInstall); 111 112 Assert.equal(1, reconciler._changes.length); 113 let change = reconciler._changes[0]; 114 Assert.ok(change[0] >= before && change[1] <= after); 115 Assert.equal(CHANGE_INSTALLED, change[1]); 116 Assert.equal(addon.id, change[2]); 117 118 await uninstallAddon(addon); 119 }); 120 121 add_task(async function test_uninstall_detection() { 122 _("Ensure that add-on uninstallation results in appropriate side-effects."); 123 124 let reconciler = makeAddonsReconciler(); 125 await reconciler.ensureStateLoaded(); 126 reconciler.startListening(); 127 128 reconciler._addons = {}; 129 reconciler._changes = []; 130 131 let addon = await installAddon(XPI); 132 let id = addon.id; 133 134 reconciler._changes = []; 135 await uninstallAddon(addon, reconciler); 136 137 Assert.equal(1, Object.keys(reconciler.addons).length); 138 Assert.ok(id in reconciler.addons); 139 140 let record = reconciler.addons[id]; 141 Assert.ok(!record.installed); 142 143 Assert.equal(1, reconciler._changes.length); 144 let change = reconciler._changes[0]; 145 Assert.equal(CHANGE_UNINSTALLED, change[1]); 146 Assert.equal(id, change[2]); 147 }); 148 149 add_task(async function test_load_state_future_version() { 150 _("Ensure loading a file from a future version results in no data loaded."); 151 152 const FILENAME = "TEST_LOAD_STATE_FUTURE_VERSION"; 153 154 let reconciler = makeAddonsReconciler(); 155 await reconciler.ensureStateLoaded(); 156 157 // First we populate our new file. 158 let state = { version: 100, addons: { foo: {} }, changes: [[1, 1, "foo"]] }; 159 160 // jsonSave() expects an object with ._log, so we give it a reconciler 161 // instance. 162 await Utils.jsonSave(FILENAME, reconciler, state); 163 164 let loaded = await reconciler.loadState(FILENAME); 165 Assert.ok(!loaded); 166 167 Assert.equal("object", typeof reconciler.addons); 168 Assert.equal(0, Object.keys(reconciler.addons).length); 169 Assert.equal(0, reconciler._changes.length); 170 }); 171 172 add_task(async function test_prune_changes_before_date() { 173 _("Ensure that old changes are pruned properly."); 174 175 let reconciler = makeAddonsReconciler(); 176 await reconciler.ensureStateLoaded(); 177 reconciler._changes = []; 178 179 let now = new Date(); 180 const HOUR_MS = 1000 * 60 * 60; 181 182 _("Ensure pruning an empty changes array works."); 183 reconciler.pruneChangesBeforeDate(now); 184 Assert.equal(0, reconciler._changes.length); 185 186 let old = new Date(now.getTime() - HOUR_MS); 187 let young = new Date(now.getTime() - 1000); 188 reconciler._changes.push([old, CHANGE_INSTALLED, "foo"]); 189 reconciler._changes.push([young, CHANGE_INSTALLED, "bar"]); 190 Assert.equal(2, reconciler._changes.length); 191 192 _("Ensure pruning with an old time won't delete anything."); 193 let threshold = new Date(old.getTime() - 1); 194 reconciler.pruneChangesBeforeDate(threshold); 195 Assert.equal(2, reconciler._changes.length); 196 197 _("Ensure pruning a single item works."); 198 threshold = new Date(young.getTime() - 1000); 199 reconciler.pruneChangesBeforeDate(threshold); 200 Assert.equal(1, reconciler._changes.length); 201 Assert.notEqual(undefined, reconciler._changes[0]); 202 Assert.equal(young, reconciler._changes[0][0]); 203 Assert.equal("bar", reconciler._changes[0][2]); 204 205 _("Ensure pruning all changes works."); 206 reconciler._changes.push([old, CHANGE_INSTALLED, "foo"]); 207 reconciler.pruneChangesBeforeDate(now); 208 Assert.equal(0, reconciler._changes.length); 209 });