tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_interval_triggers.js (16183B)


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