Wed, 31 Dec 2014 07:53:36 +0100
Correct small whitespace inconsistency, lost while renaming variables.
1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 Cu.import("resource://services-sync/constants.js");
5 Cu.import("resource://services-sync/engines.js");
6 Cu.import("resource://services-sync/engines/clients.js");
7 Cu.import("resource://services-sync/util.js");
8 Cu.import("resource://testing-common/services/sync/utils.js");
10 Svc.DefaultPrefs.set("registerEngines", "");
11 Cu.import("resource://services-sync/service.js");
13 let scheduler = Service.scheduler;
14 let clientsEngine = Service.clientsEngine;
16 function promiseStopServer(server) {
17 let deferred = Promise.defer();
18 server.stop(deferred.resolve);
19 return deferred.promise;
20 }
22 function sync_httpd_setup() {
23 let global = new ServerWBO("global", {
24 syncID: Service.syncID,
25 storageVersion: STORAGE_VERSION,
26 engines: {clients: {version: clientsEngine.version,
27 syncID: clientsEngine.syncID}}
28 });
29 let clientsColl = new ServerCollection({}, true);
31 // Tracking info/collections.
32 let collectionsHelper = track_collections_helper();
33 let upd = collectionsHelper.with_updated_collection;
35 return httpd_setup({
36 "/1.1/johndoe/storage/meta/global": upd("meta", global.handler()),
37 "/1.1/johndoe/info/collections": collectionsHelper.handler,
38 "/1.1/johndoe/storage/crypto/keys":
39 upd("crypto", (new ServerWBO("keys")).handler()),
40 "/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler())
41 });
42 }
44 function setUp(server) {
45 yield configureIdentity({username: "johndoe"});
46 Service.serverURL = server.baseURI + "/";
47 Service.clusterURL = server.baseURI + "/";
48 generateNewKeys(Service.collectionKeys);
49 let serverKeys = Service.collectionKeys.asWBO("crypto", "keys");
50 serverKeys.encrypt(Service.identity.syncKeyBundle);
51 serverKeys.upload(Service.resource(Service.cryptoKeysURL));
52 }
54 function run_test() {
55 initTestLogging("Trace");
57 Log.repository.getLogger("Sync.Service").level = Log.Level.Trace;
58 Log.repository.getLogger("Sync.SyncScheduler").level = Log.Level.Trace;
60 run_next_test();
61 }
63 add_identity_test(this, function test_successful_sync_adjustSyncInterval() {
64 _("Test successful sync calling adjustSyncInterval");
65 let syncSuccesses = 0;
66 function onSyncFinish() {
67 _("Sync success.");
68 syncSuccesses++;
69 };
70 Svc.Obs.add("weave:service:sync:finish", onSyncFinish);
72 let server = sync_httpd_setup();
73 yield setUp(server);
75 // Confirm defaults
76 do_check_false(scheduler.idle);
77 do_check_false(scheduler.numClients > 1);
78 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
79 do_check_false(scheduler.hasIncomingItems);
81 _("Test as long as numClients <= 1 our sync interval is SINGLE_USER.");
82 // idle == true && numClients <= 1 && hasIncomingItems == false
83 scheduler.idle = true;
84 Service.sync();
85 do_check_eq(syncSuccesses, 1);
86 do_check_true(scheduler.idle);
87 do_check_false(scheduler.numClients > 1);
88 do_check_false(scheduler.hasIncomingItems);
89 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
91 // idle == false && numClients <= 1 && hasIncomingItems == false
92 scheduler.idle = false;
93 Service.sync();
94 do_check_eq(syncSuccesses, 2);
95 do_check_false(scheduler.idle);
96 do_check_false(scheduler.numClients > 1);
97 do_check_false(scheduler.hasIncomingItems);
98 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
100 // idle == false && numClients <= 1 && hasIncomingItems == true
101 scheduler.hasIncomingItems = true;
102 Service.sync();
103 do_check_eq(syncSuccesses, 3);
104 do_check_false(scheduler.idle);
105 do_check_false(scheduler.numClients > 1);
106 do_check_true(scheduler.hasIncomingItems);
107 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
109 // idle == true && numClients <= 1 && hasIncomingItems == true
110 scheduler.idle = true;
111 Service.sync();
112 do_check_eq(syncSuccesses, 4);
113 do_check_true(scheduler.idle);
114 do_check_false(scheduler.numClients > 1);
115 do_check_true(scheduler.hasIncomingItems);
116 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
118 _("Test as long as idle && numClients > 1 our sync interval is idleInterval.");
119 // idle == true && numClients > 1 && hasIncomingItems == true
120 Service.clientsEngine._store.create({id: "foo", cleartext: "bar"});
121 Service.sync();
122 do_check_eq(syncSuccesses, 5);
123 do_check_true(scheduler.idle);
124 do_check_true(scheduler.numClients > 1);
125 do_check_true(scheduler.hasIncomingItems);
126 do_check_eq(scheduler.syncInterval, scheduler.idleInterval);
128 // idle == true && numClients > 1 && hasIncomingItems == false
129 scheduler.hasIncomingItems = false;
130 Service.sync();
131 do_check_eq(syncSuccesses, 6);
132 do_check_true(scheduler.idle);
133 do_check_true(scheduler.numClients > 1);
134 do_check_false(scheduler.hasIncomingItems);
135 do_check_eq(scheduler.syncInterval, scheduler.idleInterval);
137 _("Test non-idle, numClients > 1, no incoming items => activeInterval.");
138 // idle == false && numClients > 1 && hasIncomingItems == false
139 scheduler.idle = false;
140 Service.sync();
141 do_check_eq(syncSuccesses, 7);
142 do_check_false(scheduler.idle);
143 do_check_true(scheduler.numClients > 1);
144 do_check_false(scheduler.hasIncomingItems);
145 do_check_eq(scheduler.syncInterval, scheduler.activeInterval);
147 _("Test non-idle, numClients > 1, incoming items => immediateInterval.");
148 // idle == false && numClients > 1 && hasIncomingItems == true
149 scheduler.hasIncomingItems = true;
150 Service.sync();
151 do_check_eq(syncSuccesses, 8);
152 do_check_false(scheduler.idle);
153 do_check_true(scheduler.numClients > 1);
154 do_check_false(scheduler.hasIncomingItems); //gets reset to false
155 do_check_eq(scheduler.syncInterval, scheduler.immediateInterval);
157 Svc.Obs.remove("weave:service:sync:finish", onSyncFinish);
158 Service.startOver();
159 yield promiseStopServer(server);
160 });
162 add_identity_test(this, function test_unsuccessful_sync_adjustSyncInterval() {
163 _("Test unsuccessful sync calling adjustSyncInterval");
165 let syncFailures = 0;
166 function onSyncError() {
167 _("Sync error.");
168 syncFailures++;
169 }
170 Svc.Obs.add("weave:service:sync:error", onSyncError);
172 _("Test unsuccessful sync calls adjustSyncInterval");
173 // Force sync to fail.
174 Svc.Prefs.set("firstSync", "notReady");
176 let server = sync_httpd_setup();
177 yield setUp(server);
179 // Confirm defaults
180 do_check_false(scheduler.idle);
181 do_check_false(scheduler.numClients > 1);
182 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
183 do_check_false(scheduler.hasIncomingItems);
185 _("Test as long as numClients <= 1 our sync interval is SINGLE_USER.");
186 // idle == true && numClients <= 1 && hasIncomingItems == false
187 scheduler.idle = true;
188 Service.sync();
189 do_check_eq(syncFailures, 1);
190 do_check_true(scheduler.idle);
191 do_check_false(scheduler.numClients > 1);
192 do_check_false(scheduler.hasIncomingItems);
193 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
195 // idle == false && numClients <= 1 && hasIncomingItems == false
196 scheduler.idle = false;
197 Service.sync();
198 do_check_eq(syncFailures, 2);
199 do_check_false(scheduler.idle);
200 do_check_false(scheduler.numClients > 1);
201 do_check_false(scheduler.hasIncomingItems);
202 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
204 // idle == false && numClients <= 1 && hasIncomingItems == true
205 scheduler.hasIncomingItems = true;
206 Service.sync();
207 do_check_eq(syncFailures, 3);
208 do_check_false(scheduler.idle);
209 do_check_false(scheduler.numClients > 1);
210 do_check_true(scheduler.hasIncomingItems);
211 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
213 // idle == true && numClients <= 1 && hasIncomingItems == true
214 scheduler.idle = true;
215 Service.sync();
216 do_check_eq(syncFailures, 4);
217 do_check_true(scheduler.idle);
218 do_check_false(scheduler.numClients > 1);
219 do_check_true(scheduler.hasIncomingItems);
220 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
222 _("Test as long as idle && numClients > 1 our sync interval is idleInterval.");
223 // idle == true && numClients > 1 && hasIncomingItems == true
224 Service.clientsEngine._store.create({id: "foo", cleartext: "bar"});
226 Service.sync();
227 do_check_eq(syncFailures, 5);
228 do_check_true(scheduler.idle);
229 do_check_true(scheduler.numClients > 1);
230 do_check_true(scheduler.hasIncomingItems);
231 do_check_eq(scheduler.syncInterval, scheduler.idleInterval);
233 // idle == true && numClients > 1 && hasIncomingItems == false
234 scheduler.hasIncomingItems = false;
235 Service.sync();
236 do_check_eq(syncFailures, 6);
237 do_check_true(scheduler.idle);
238 do_check_true(scheduler.numClients > 1);
239 do_check_false(scheduler.hasIncomingItems);
240 do_check_eq(scheduler.syncInterval, scheduler.idleInterval);
242 _("Test non-idle, numClients > 1, no incoming items => activeInterval.");
243 // idle == false && numClients > 1 && hasIncomingItems == false
244 scheduler.idle = false;
245 Service.sync();
246 do_check_eq(syncFailures, 7);
247 do_check_false(scheduler.idle);
248 do_check_true(scheduler.numClients > 1);
249 do_check_false(scheduler.hasIncomingItems);
250 do_check_eq(scheduler.syncInterval, scheduler.activeInterval);
252 _("Test non-idle, numClients > 1, incoming items => immediateInterval.");
253 // idle == false && numClients > 1 && hasIncomingItems == true
254 scheduler.hasIncomingItems = true;
255 Service.sync();
256 do_check_eq(syncFailures, 8);
257 do_check_false(scheduler.idle);
258 do_check_true(scheduler.numClients > 1);
259 do_check_false(scheduler.hasIncomingItems); //gets reset to false
260 do_check_eq(scheduler.syncInterval, scheduler.immediateInterval);
262 Service.startOver();
263 Svc.Obs.remove("weave:service:sync:error", onSyncError);
264 yield promiseStopServer(server);
265 });
267 add_identity_test(this, function test_back_triggers_sync() {
268 let server = sync_httpd_setup();
269 yield setUp(server);
271 // Single device: no sync triggered.
272 scheduler.idle = true;
273 scheduler.observe(null, "active", Svc.Prefs.get("scheduler.idleTime"));
274 do_check_false(scheduler.idle);
276 // Multiple devices: sync is triggered.
277 clientsEngine._store.create({id: "foo", cleartext: "bar"});
278 scheduler.updateClientMode();
280 let deferred = Promise.defer();
281 Svc.Obs.add("weave:service:sync:finish", function onSyncFinish() {
282 Svc.Obs.remove("weave:service:sync:finish", onSyncFinish);
284 Service.recordManager.clearCache();
285 Svc.Prefs.resetBranch("");
286 scheduler.setDefaults();
287 clientsEngine.resetClient();
289 Service.startOver();
290 server.stop(deferred.resolve);
291 });
293 scheduler.idle = true;
294 scheduler.observe(null, "active", Svc.Prefs.get("scheduler.idleTime"));
295 do_check_false(scheduler.idle);
296 yield deferred.promise;
297 });
299 add_identity_test(this, function test_adjust_interval_on_sync_error() {
300 let server = sync_httpd_setup();
301 yield setUp(server);
303 let syncFailures = 0;
304 function onSyncError() {
305 _("Sync error.");
306 syncFailures++;
307 }
308 Svc.Obs.add("weave:service:sync:error", onSyncError);
310 _("Test unsuccessful sync updates client mode & sync intervals");
311 // Force a sync fail.
312 Svc.Prefs.set("firstSync", "notReady");
314 do_check_eq(syncFailures, 0);
315 do_check_false(scheduler.numClients > 1);
316 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
318 clientsEngine._store.create({id: "foo", cleartext: "bar"});
319 Service.sync();
321 do_check_eq(syncFailures, 1);
322 do_check_true(scheduler.numClients > 1);
323 do_check_eq(scheduler.syncInterval, scheduler.activeInterval);
325 Svc.Obs.remove("weave:service:sync:error", onSyncError);
326 Service.startOver();
327 yield promiseStopServer(server);
328 });
330 add_identity_test(this, function test_bug671378_scenario() {
331 // Test scenario similar to bug 671378. This bug appeared when a score
332 // update occurred that wasn't large enough to trigger a sync so
333 // scheduleNextSync() was called without a time interval parameter,
334 // setting nextSync to a non-zero value and preventing the timer from
335 // being adjusted in the next call to scheduleNextSync().
336 let server = sync_httpd_setup();
337 yield setUp(server);
339 let syncSuccesses = 0;
340 function onSyncFinish() {
341 _("Sync success.");
342 syncSuccesses++;
343 };
344 Svc.Obs.add("weave:service:sync:finish", onSyncFinish);
346 // After first sync call, syncInterval & syncTimer are singleDeviceInterval.
347 Service.sync();
348 do_check_eq(syncSuccesses, 1);
349 do_check_false(scheduler.numClients > 1);
350 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
351 do_check_eq(scheduler.syncTimer.delay, scheduler.singleDeviceInterval);
353 let deferred = Promise.defer();
354 // Wrap scheduleNextSync so we are notified when it is finished.
355 scheduler._scheduleNextSync = scheduler.scheduleNextSync;
356 scheduler.scheduleNextSync = function() {
357 scheduler._scheduleNextSync();
359 // Check on sync:finish scheduleNextSync sets the appropriate
360 // syncInterval and syncTimer values.
361 if (syncSuccesses == 2) {
362 do_check_neq(scheduler.nextSync, 0);
363 do_check_eq(scheduler.syncInterval, scheduler.activeInterval);
364 do_check_true(scheduler.syncTimer.delay <= scheduler.activeInterval);
366 scheduler.scheduleNextSync = scheduler._scheduleNextSync;
367 Svc.Obs.remove("weave:service:sync:finish", onSyncFinish);
368 Service.startOver();
369 server.stop(deferred.resolve);
370 }
371 };
373 // Set nextSync != 0
374 // syncInterval still hasn't been set by call to updateClientMode.
375 // Explicitly trying to invoke scheduleNextSync during a sync
376 // (to immitate a score update that isn't big enough to trigger a sync).
377 Svc.Obs.add("weave:service:sync:start", function onSyncStart() {
378 // Wait for other sync:start observers to be called so that
379 // nextSync is set to 0.
380 Utils.nextTick(function() {
381 Svc.Obs.remove("weave:service:sync:start", onSyncStart);
383 scheduler.scheduleNextSync();
384 do_check_neq(scheduler.nextSync, 0);
385 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
386 do_check_eq(scheduler.syncTimer.delay, scheduler.singleDeviceInterval);
387 });
388 });
390 clientsEngine._store.create({id: "foo", cleartext: "bar"});
391 Service.sync();
392 yield deferred.promise;
393 });
395 add_test(function test_adjust_timer_larger_syncInterval() {
396 _("Test syncInterval > current timout period && nextSync != 0, syncInterval is NOT used.");
397 clientsEngine._store.create({id: "foo", cleartext: "bar"});
398 scheduler.updateClientMode();
399 do_check_eq(scheduler.syncInterval, scheduler.activeInterval);
401 scheduler.scheduleNextSync();
403 // Ensure we have a small interval.
404 do_check_neq(scheduler.nextSync, 0);
405 do_check_eq(scheduler.syncTimer.delay, scheduler.activeInterval);
407 // Make interval large again
408 clientsEngine._wipeClient();
409 scheduler.updateClientMode();
410 do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
412 scheduler.scheduleNextSync();
414 // Ensure timer delay remains as the small interval.
415 do_check_neq(scheduler.nextSync, 0);
416 do_check_true(scheduler.syncTimer.delay <= scheduler.activeInterval);
418 //SyncSchedule.
419 Service.startOver();
420 run_next_test();
421 });
423 add_test(function test_adjust_timer_smaller_syncInterval() {
424 _("Test current timout > syncInterval period && nextSync != 0, syncInterval is used.");
425 scheduler.scheduleNextSync();
427 // Ensure we have a large interval.
428 do_check_neq(scheduler.nextSync, 0);
429 do_check_eq(scheduler.syncTimer.delay, scheduler.singleDeviceInterval);
431 // Make interval smaller
432 clientsEngine._store.create({id: "foo", cleartext: "bar"});
433 scheduler.updateClientMode();
434 do_check_eq(scheduler.syncInterval, scheduler.activeInterval);
436 scheduler.scheduleNextSync();
438 // Ensure smaller timer delay is used.
439 do_check_neq(scheduler.nextSync, 0);
440 do_check_true(scheduler.syncTimer.delay <= scheduler.activeInterval);
442 //SyncSchedule.
443 Service.startOver();
444 run_next_test();
445 });