tor-browser

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

test_eviction.js (6835B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 var test_generator = do_run_test();
      7 
      8 function run_test() {
      9  do_test_pending();
     10  do_run_generator(test_generator);
     11 }
     12 
     13 function continue_test() {
     14  do_run_generator(test_generator);
     15 }
     16 
     17 function repeat_test() {
     18  // The test is probably going to fail because setting a batch of cookies took
     19  // a significant fraction of 'gPurgeAge'. Compensate by rerunning the
     20  // test with a larger purge age.
     21  Assert.less(gPurgeAge, 64);
     22  gPurgeAge *= 2;
     23  gShortExpiry *= 2;
     24 
     25  executeSoon(function () {
     26    test_generator.return();
     27    test_generator = do_run_test();
     28    do_run_generator(test_generator);
     29  });
     30 }
     31 
     32 // Purge threshold, in seconds.
     33 var gPurgeAge = 1;
     34 
     35 // Short expiry age, in seconds.
     36 var gShortExpiry = 2;
     37 
     38 // Required delay to ensure a purge occurs, in milliseconds. This must be at
     39 // least gPurgeAge + 10%, and includes a little fuzz to account for timer
     40 // resolution and possible differences between PR_Now() and Date.now().
     41 function get_purge_delay() {
     42  return gPurgeAge * 1100 + 100;
     43 }
     44 
     45 // Required delay to ensure a cookie set with an expiry time 'gShortExpiry' into
     46 // the future will have expired.
     47 function get_expiry_delay() {
     48  return gShortExpiry * 1000 + 100;
     49 }
     50 
     51 function* do_run_test() {
     52  // Set up a profile.
     53  do_get_profile();
     54 
     55  // twiddle prefs to convenient values for this test
     56  Services.prefs.setIntPref("network.cookie.purgeAge", gPurgeAge);
     57  Services.prefs.setIntPref("network.cookie.maxNumber", 100);
     58 
     59  let expiry = Date.now() + 1000 * 1000;
     60 
     61  // eviction is performed based on two limits: when the total number of cookies
     62  // exceeds maxNumber + 10% (110), and when cookies are older than purgeAge
     63  // (1 second). purging is done when both conditions are satisfied, and only
     64  // those cookies are purged.
     65 
     66  // we test the following cases of eviction:
     67  // 1) excess and age are satisfied, but only some of the excess are old enough
     68  // to be purged.
     69  Services.cookies.removeAll();
     70  if (!set_cookies(0, 5, expiry)) {
     71    repeat_test();
     72    return;
     73  }
     74  // Sleep a while, to make sure the first batch of cookies is older than
     75  // the second (timer resolution varies on different platforms).
     76  do_timeout(get_purge_delay(), continue_test);
     77  yield;
     78  if (!set_cookies(5, 111, expiry)) {
     79    repeat_test();
     80    return;
     81  }
     82 
     83  // Fake a profile change, to ensure eviction affects the database correctly.
     84  do_close_profile(test_generator);
     85  yield;
     86  do_load_profile();
     87  Assert.ok(check_remaining_cookies(111, 5, 106));
     88 
     89  // 2) excess and age are satisfied, and all of the excess are old enough
     90  // to be purged.
     91  Services.cookies.removeAll();
     92  if (!set_cookies(0, 10, expiry)) {
     93    repeat_test();
     94    return;
     95  }
     96  do_timeout(get_purge_delay(), continue_test);
     97  yield;
     98  if (!set_cookies(10, 111, expiry)) {
     99    repeat_test();
    100    return;
    101  }
    102 
    103  do_close_profile(test_generator);
    104  yield;
    105  do_load_profile();
    106  Assert.ok(check_remaining_cookies(111, 10, 101));
    107 
    108  // 3) excess and age are satisfied, and more than the excess are old enough
    109  // to be purged.
    110  Services.cookies.removeAll();
    111  if (!set_cookies(0, 50, expiry)) {
    112    repeat_test();
    113    return;
    114  }
    115  do_timeout(get_purge_delay(), continue_test);
    116  yield;
    117  if (!set_cookies(50, 111, expiry)) {
    118    repeat_test();
    119    return;
    120  }
    121 
    122  do_close_profile(test_generator);
    123  yield;
    124  do_load_profile();
    125  Assert.ok(check_remaining_cookies(111, 50, 101));
    126 
    127  // 4) excess but not age are satisfied.
    128  Services.cookies.removeAll();
    129  if (!set_cookies(0, 120, expiry)) {
    130    repeat_test();
    131    return;
    132  }
    133 
    134  do_close_profile(test_generator);
    135  yield;
    136  do_load_profile();
    137  Assert.ok(check_remaining_cookies(120, 0, 120));
    138 
    139  // 5) age but not excess are satisfied.
    140  Services.cookies.removeAll();
    141  if (!set_cookies(0, 20, expiry)) {
    142    repeat_test();
    143    return;
    144  }
    145  do_timeout(get_purge_delay(), continue_test);
    146  yield;
    147  if (!set_cookies(20, 110, expiry)) {
    148    repeat_test();
    149    return;
    150  }
    151 
    152  do_close_profile(test_generator);
    153  yield;
    154  do_load_profile();
    155  Assert.ok(check_remaining_cookies(110, 20, 110));
    156 
    157  // 6) Excess and age are satisfied, but the cookie limit can be satisfied by
    158  // purging expired cookies.
    159  Services.cookies.removeAll();
    160  let shortExpiry = Date.now() + 1000 * gShortExpiry;
    161  if (!set_cookies(0, 20, shortExpiry)) {
    162    repeat_test();
    163    return;
    164  }
    165  do_timeout(get_expiry_delay(), continue_test);
    166  yield;
    167  if (!set_cookies(20, 110, expiry)) {
    168    repeat_test();
    169    return;
    170  }
    171  do_timeout(get_purge_delay(), continue_test);
    172  yield;
    173  if (!set_cookies(110, 111, expiry)) {
    174    repeat_test();
    175    return;
    176  }
    177 
    178  do_close_profile(test_generator);
    179  yield;
    180  do_load_profile();
    181  Assert.ok(check_remaining_cookies(111, 20, 91));
    182 
    183  do_finish_generator_test(test_generator);
    184 }
    185 
    186 // Set 'end - begin' total cookies, with consecutively increasing hosts numbered
    187 // 'begin' to 'end'.
    188 function set_cookies(begin, end, expiry) {
    189  Assert.notEqual(begin, end);
    190 
    191  let beginTime;
    192  for (let i = begin; i < end; ++i) {
    193    let host = "eviction." + i + ".tests";
    194    const cv = Services.cookies.add(
    195      host,
    196      "",
    197      "test",
    198      "eviction",
    199      false,
    200      false,
    201      false,
    202      expiry,
    203      {},
    204      Ci.nsICookie.SAMESITE_UNSET,
    205      Ci.nsICookie.SCHEME_HTTPS
    206    );
    207    Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
    208 
    209    if (i == begin) {
    210      beginTime = get_creationTime(i);
    211    }
    212  }
    213 
    214  let endTime = get_creationTime(end - 1);
    215  Assert.ok(begin == end - 1 || endTime > beginTime);
    216  if (endTime - beginTime > gPurgeAge * 1000000) {
    217    // Setting cookies took an amount of time very close to the purge threshold.
    218    // Retry the test with a larger threshold.
    219    return false;
    220  }
    221 
    222  return true;
    223 }
    224 
    225 function get_creationTime(i) {
    226  let host = "eviction." + i + ".tests";
    227  let cookies = Services.cookies.getCookiesFromHost(host, {});
    228  Assert.ok(cookies.length);
    229  let cookie = cookies[0];
    230  return cookie.creationTime;
    231 }
    232 
    233 // Test that 'aNumberToExpect' cookies remain after purging is complete, and
    234 // that the cookies that remain consist of the set expected given the number of
    235 // of older and newer cookies -- eviction should occur by order of lastAccessed
    236 // time, if both the limit on total cookies (maxNumber + 10%) and the purge age
    237 // + 10% are exceeded.
    238 function check_remaining_cookies(aNumberTotal, aNumberOld, aNumberToExpect) {
    239  let i = 0;
    240  for (let cookie of Services.cookies.cookies) {
    241    ++i;
    242 
    243    if (aNumberTotal != aNumberToExpect) {
    244      // make sure the cookie is one of the batch we expect was purged.
    245      var hostNumber = Number(cookie.rawHost.split(".")[1]);
    246      if (hostNumber < aNumberOld - aNumberToExpect) {
    247        break;
    248      }
    249    }
    250  }
    251 
    252  return i == aNumberToExpect;
    253 }