services/sync/tests/unit/test_addons_engine.js

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

mercurial