services/sync/tests/unit/test_addons_engine.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* Any copyright is dedicated to the Public Domain.
michael@0 2 http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 3
michael@0 4 "use strict";
michael@0 5
michael@0 6 Cu.import("resource://gre/modules/AddonManager.jsm");
michael@0 7 Cu.import("resource://gre/modules/Preferences.jsm");
michael@0 8 Cu.import("resource://gre/modules/Services.jsm");
michael@0 9 Cu.import("resource://services-common/async.js");
michael@0 10 Cu.import("resource://services-sync/addonsreconciler.js");
michael@0 11 Cu.import("resource://services-sync/engines/addons.js");
michael@0 12 Cu.import("resource://services-sync/service.js");
michael@0 13 Cu.import("resource://services-sync/util.js");
michael@0 14 Cu.import("resource://testing-common/services/sync/utils.js");
michael@0 15
michael@0 16 let prefs = new Preferences();
michael@0 17 prefs.set("extensions.getAddons.get.url",
michael@0 18 "http://localhost:8888/search/guid:%IDS%");
michael@0 19
michael@0 20 loadAddonTestFunctions();
michael@0 21 startupManager();
michael@0 22
michael@0 23 let engineManager = Service.engineManager;
michael@0 24
michael@0 25 engineManager.register(AddonsEngine);
michael@0 26 let engine = engineManager.get("addons");
michael@0 27 let reconciler = engine._reconciler;
michael@0 28 let tracker = engine._tracker;
michael@0 29
michael@0 30 function advance_test() {
michael@0 31 reconciler._addons = {};
michael@0 32 reconciler._changes = [];
michael@0 33
michael@0 34 let cb = Async.makeSpinningCallback();
michael@0 35 reconciler.saveState(null, cb);
michael@0 36 cb.wait();
michael@0 37
michael@0 38 Svc.Prefs.reset("addons.ignoreRepositoryChecking");
michael@0 39
michael@0 40 run_next_test();
michael@0 41 }
michael@0 42
michael@0 43 // This is a basic sanity test for the unit test itself. If this breaks, the
michael@0 44 // add-ons API likely changed upstream.
michael@0 45 add_test(function test_addon_install() {
michael@0 46 _("Ensure basic add-on APIs work as expected.");
michael@0 47
michael@0 48 let install = getAddonInstall("test_bootstrap1_1");
michael@0 49 do_check_neq(install, null);
michael@0 50 do_check_eq(install.type, "extension");
michael@0 51 do_check_eq(install.name, "Test Bootstrap 1");
michael@0 52
michael@0 53 advance_test();
michael@0 54 });
michael@0 55
michael@0 56 add_test(function test_find_dupe() {
michael@0 57 _("Ensure the _findDupe() implementation is sane.");
michael@0 58
michael@0 59 // This gets invoked at the top of sync, which is bypassed by this
michael@0 60 // test, so we do it manually.
michael@0 61 engine._refreshReconcilerState();
michael@0 62
michael@0 63 let addon = installAddon("test_bootstrap1_1");
michael@0 64
michael@0 65 let record = {
michael@0 66 id: Utils.makeGUID(),
michael@0 67 addonID: addon.id,
michael@0 68 enabled: true,
michael@0 69 applicationID: Services.appinfo.ID,
michael@0 70 source: "amo"
michael@0 71 };
michael@0 72
michael@0 73 let dupe = engine._findDupe(record);
michael@0 74 do_check_eq(addon.syncGUID, dupe);
michael@0 75
michael@0 76 record.id = addon.syncGUID;
michael@0 77 dupe = engine._findDupe(record);
michael@0 78 do_check_eq(null, dupe);
michael@0 79
michael@0 80 uninstallAddon(addon);
michael@0 81 advance_test();
michael@0 82 });
michael@0 83
michael@0 84 add_test(function test_get_changed_ids() {
michael@0 85 _("Ensure getChangedIDs() has the appropriate behavior.");
michael@0 86
michael@0 87 _("Ensure getChangedIDs() returns an empty object by default.");
michael@0 88 let changes = engine.getChangedIDs();
michael@0 89 do_check_eq("object", typeof(changes));
michael@0 90 do_check_eq(0, Object.keys(changes).length);
michael@0 91
michael@0 92 _("Ensure tracker changes are populated.");
michael@0 93 let now = new Date();
michael@0 94 let changeTime = now.getTime() / 1000;
michael@0 95 let guid1 = Utils.makeGUID();
michael@0 96 tracker.addChangedID(guid1, changeTime);
michael@0 97
michael@0 98 changes = engine.getChangedIDs();
michael@0 99 do_check_eq("object", typeof(changes));
michael@0 100 do_check_eq(1, Object.keys(changes).length);
michael@0 101 do_check_true(guid1 in changes);
michael@0 102 do_check_eq(changeTime, changes[guid1]);
michael@0 103
michael@0 104 tracker.clearChangedIDs();
michael@0 105
michael@0 106 _("Ensure reconciler changes are populated.");
michael@0 107 Svc.Prefs.set("addons.ignoreRepositoryChecking", true);
michael@0 108 let addon = installAddon("test_bootstrap1_1");
michael@0 109 tracker.clearChangedIDs(); // Just in case.
michael@0 110 changes = engine.getChangedIDs();
michael@0 111 do_check_eq("object", typeof(changes));
michael@0 112 do_check_eq(1, Object.keys(changes).length);
michael@0 113 do_check_true(addon.syncGUID in changes);
michael@0 114 _("Change time: " + changeTime + ", addon change: " + changes[addon.syncGUID]);
michael@0 115 do_check_true(changes[addon.syncGUID] >= changeTime);
michael@0 116
michael@0 117 let oldTime = changes[addon.syncGUID];
michael@0 118 let guid2 = addon.syncGUID;
michael@0 119 uninstallAddon(addon);
michael@0 120 changes = engine.getChangedIDs();
michael@0 121 do_check_eq(1, Object.keys(changes).length);
michael@0 122 do_check_true(guid2 in changes);
michael@0 123 do_check_true(changes[guid2] > oldTime);
michael@0 124
michael@0 125 _("Ensure non-syncable add-ons aren't picked up by reconciler changes.");
michael@0 126 reconciler._addons = {};
michael@0 127 reconciler._changes = [];
michael@0 128 let record = {
michael@0 129 id: "DUMMY",
michael@0 130 guid: Utils.makeGUID(),
michael@0 131 enabled: true,
michael@0 132 installed: true,
michael@0 133 modified: new Date(),
michael@0 134 type: "UNSUPPORTED",
michael@0 135 scope: 0,
michael@0 136 foreignInstall: false
michael@0 137 };
michael@0 138 reconciler.addons["DUMMY"] = record;
michael@0 139 reconciler._addChange(record.modified, CHANGE_INSTALLED, record);
michael@0 140
michael@0 141 changes = engine.getChangedIDs();
michael@0 142 _(JSON.stringify(changes));
michael@0 143 do_check_eq(0, Object.keys(changes).length);
michael@0 144
michael@0 145 advance_test();
michael@0 146 });
michael@0 147
michael@0 148 add_test(function test_disabled_install_semantics() {
michael@0 149 _("Ensure that syncing a disabled add-on preserves proper state.");
michael@0 150
michael@0 151 // This is essentially a test for bug 712542, which snuck into the original
michael@0 152 // add-on sync drop. It ensures that when an add-on is installed that the
michael@0 153 // disabled state and incoming syncGUID is preserved, even on the next sync.
michael@0 154
michael@0 155 Svc.Prefs.set("addons.ignoreRepositoryChecking", true);
michael@0 156
michael@0 157 const USER = "foo";
michael@0 158 const PASSWORD = "password";
michael@0 159 const PASSPHRASE = "abcdeabcdeabcdeabcdeabcdea";
michael@0 160 const ADDON_ID = "addon1@tests.mozilla.org";
michael@0 161
michael@0 162 let server = new SyncServer();
michael@0 163 server.start();
michael@0 164 new SyncTestingInfrastructure(server.server, USER, PASSWORD, PASSPHRASE);
michael@0 165
michael@0 166 generateNewKeys(Service.collectionKeys);
michael@0 167
michael@0 168 let contents = {
michael@0 169 meta: {global: {engines: {addons: {version: engine.version,
michael@0 170 syncID: engine.syncID}}}},
michael@0 171 crypto: {},
michael@0 172 addons: {}
michael@0 173 };
michael@0 174
michael@0 175 server.registerUser(USER, "password");
michael@0 176 server.createContents(USER, contents);
michael@0 177
michael@0 178 let amoServer = new HttpServer();
michael@0 179 amoServer.registerFile("/search/guid:addon1%40tests.mozilla.org",
michael@0 180 do_get_file("addon1-search.xml"));
michael@0 181
michael@0 182 let installXPI = ExtensionsTestPath("/addons/test_install1.xpi");
michael@0 183 amoServer.registerFile("/addon1.xpi", do_get_file(installXPI));
michael@0 184 amoServer.start(8888);
michael@0 185
michael@0 186 // Insert an existing record into the server.
michael@0 187 let id = Utils.makeGUID();
michael@0 188 let now = Date.now() / 1000;
michael@0 189
michael@0 190 let record = encryptPayload({
michael@0 191 id: id,
michael@0 192 applicationID: Services.appinfo.ID,
michael@0 193 addonID: ADDON_ID,
michael@0 194 enabled: false,
michael@0 195 deleted: false,
michael@0 196 source: "amo",
michael@0 197 });
michael@0 198 let wbo = new ServerWBO(id, record, now - 2);
michael@0 199 server.insertWBO(USER, "addons", wbo);
michael@0 200
michael@0 201 _("Performing sync of add-ons engine.");
michael@0 202 engine._sync();
michael@0 203
michael@0 204 // At this point the non-restartless extension should be staged for install.
michael@0 205
michael@0 206 // Don't need this server any more.
michael@0 207 let cb = Async.makeSpinningCallback();
michael@0 208 amoServer.stop(cb);
michael@0 209 cb.wait();
michael@0 210
michael@0 211 // We ensure the reconciler has recorded the proper ID and enabled state.
michael@0 212 let addon = reconciler.getAddonStateFromSyncGUID(id);
michael@0 213 do_check_neq(null, addon);
michael@0 214 do_check_eq(false, addon.enabled);
michael@0 215
michael@0 216 // We fake an app restart and perform another sync, just to make sure things
michael@0 217 // are sane.
michael@0 218 restartManager();
michael@0 219
michael@0 220 engine._sync();
michael@0 221
michael@0 222 // The client should not upload a new record. The old record should be
michael@0 223 // retained and unmodified.
michael@0 224 let collection = server.getCollection(USER, "addons");
michael@0 225 do_check_eq(1, collection.count());
michael@0 226
michael@0 227 let payload = collection.payloads()[0];
michael@0 228 do_check_neq(null, collection.wbo(id));
michael@0 229 do_check_eq(ADDON_ID, payload.addonID);
michael@0 230 do_check_false(payload.enabled);
michael@0 231
michael@0 232 server.stop(advance_test);
michael@0 233 });
michael@0 234
michael@0 235 add_test(function cleanup() {
michael@0 236 // There's an xpcom-shutdown hook for this, but let's give this a shot.
michael@0 237 reconciler.stopListening();
michael@0 238 run_next_test();
michael@0 239 });
michael@0 240
michael@0 241 function run_test() {
michael@0 242 initTestLogging("Trace");
michael@0 243 Log.repository.getLogger("Sync.Engine.Addons").level =
michael@0 244 Log.Level.Trace;
michael@0 245 Log.repository.getLogger("Sync.Store.Addons").level = Log.Level.Trace;
michael@0 246 Log.repository.getLogger("Sync.Tracker.Addons").level =
michael@0 247 Log.Level.Trace;
michael@0 248 Log.repository.getLogger("Sync.AddonsRepository").level =
michael@0 249 Log.Level.Trace;
michael@0 250
michael@0 251 reconciler.startListening();
michael@0 252
michael@0 253 // Don't flush to disk in the middle of an event listener!
michael@0 254 // This causes test hangs on WinXP.
michael@0 255 reconciler._shouldPersist = false;
michael@0 256
michael@0 257 advance_test();
michael@0 258 }

mercurial