services/sync/tests/unit/test_interval_triggers.js

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial