tor-browser

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

test_cache-control_request.js (11882B)


      1 "use strict";
      2 
      3 const { HttpServer } = ChromeUtils.importESModule(
      4  "resource://testing-common/httpd.sys.mjs"
      5 );
      6 
      7 var httpserver = new HttpServer();
      8 httpserver.start(-1);
      9 var cache = null;
     10 
     11 var base_url = "http://localhost:" + httpserver.identity.primaryPort;
     12 var resource_age_100 = "/resource_age_100";
     13 var resource_age_100_url = base_url + resource_age_100;
     14 var resource_stale_100 = "/resource_stale_100";
     15 var resource_stale_100_url = base_url + resource_stale_100;
     16 var resource_fresh_100 = "/resource_fresh_100";
     17 var resource_fresh_100_url = base_url + resource_fresh_100;
     18 
     19 // Test flags
     20 var hit_server = false;
     21 
     22 function make_channel(url, cache_control) {
     23  // Reset test global status
     24  hit_server = false;
     25 
     26  var req = NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
     27  req.QueryInterface(Ci.nsIHttpChannel);
     28  if (cache_control) {
     29    req.setRequestHeader("Cache-control", cache_control, false);
     30  }
     31 
     32  return req;
     33 }
     34 
     35 function make_uri(url) {
     36  return Services.io.newURI(url);
     37 }
     38 
     39 function resource_age_100_handler(metadata, response) {
     40  hit_server = true;
     41 
     42  response.setStatusLine(metadata.httpVersion, 200, "OK");
     43  response.setHeader("Content-Type", "text/plain", false);
     44  response.setHeader("Age", "100", false);
     45  response.setHeader("Last-Modified", date_string_from_now(-100), false);
     46  response.setHeader("Expires", date_string_from_now(+9999), false);
     47 
     48  const body = "data1";
     49  response.bodyOutputStream.write(body, body.length);
     50 }
     51 
     52 function resource_stale_100_handler(metadata, response) {
     53  hit_server = true;
     54 
     55  response.setStatusLine(metadata.httpVersion, 200, "OK");
     56  response.setHeader("Content-Type", "text/plain", false);
     57  response.setHeader("Date", date_string_from_now(-200), false);
     58  response.setHeader("Last-Modified", date_string_from_now(-200), false);
     59  response.setHeader("Cache-Control", "max-age=100", false);
     60  response.setHeader("Expires", date_string_from_now(-100), false);
     61 
     62  const body = "data2";
     63  response.bodyOutputStream.write(body, body.length);
     64 }
     65 
     66 function resource_fresh_100_handler(metadata, response) {
     67  hit_server = true;
     68 
     69  response.setStatusLine(metadata.httpVersion, 200, "OK");
     70  response.setHeader("Content-Type", "text/plain", false);
     71  response.setHeader("Last-Modified", date_string_from_now(0), false);
     72  response.setHeader("Cache-Control", "max-age=100", false);
     73  response.setHeader("Expires", date_string_from_now(+100), false);
     74 
     75  const body = "data3";
     76  response.bodyOutputStream.write(body, body.length);
     77 }
     78 
     79 function run_test() {
     80  do_get_profile();
     81 
     82  do_test_pending();
     83 
     84  Services.prefs.setBoolPref("network.http.rcwn.enabled", false);
     85 
     86  httpserver.registerPathHandler(resource_age_100, resource_age_100_handler);
     87  httpserver.registerPathHandler(
     88    resource_stale_100,
     89    resource_stale_100_handler
     90  );
     91  httpserver.registerPathHandler(
     92    resource_fresh_100,
     93    resource_fresh_100_handler
     94  );
     95  cache = getCacheStorage("disk");
     96 
     97  wait_for_cache_index(run_next_test);
     98 }
     99 
    100 // Here starts the list of tests
    101 
    102 // ============================================================================
    103 // Cache-Control: no-store
    104 
    105 add_test(() => {
    106  // Must not create a cache entry
    107  var ch = make_channel(resource_age_100_url, "no-store");
    108  ch.asyncOpen(
    109    new ChannelListener(function () {
    110      Assert.ok(hit_server);
    111      Assert.ok(!cache.exists(make_uri(resource_age_100_url), ""));
    112 
    113      run_next_test();
    114    }, null)
    115  );
    116 });
    117 
    118 add_test(() => {
    119  // Prepare state only, cache the entry
    120  var ch = make_channel(resource_age_100_url);
    121  ch.asyncOpen(
    122    new ChannelListener(function () {
    123      Assert.ok(hit_server);
    124      Assert.ok(cache.exists(make_uri(resource_age_100_url), ""));
    125 
    126      run_next_test();
    127    }, null)
    128  );
    129 });
    130 
    131 add_test(() => {
    132  // Check the prepared cache entry is used when no special directives are added
    133  var ch = make_channel(resource_age_100_url);
    134  ch.asyncOpen(
    135    new ChannelListener(function () {
    136      Assert.ok(!hit_server);
    137      Assert.ok(cache.exists(make_uri(resource_age_100_url), ""));
    138 
    139      run_next_test();
    140    }, null)
    141  );
    142 });
    143 
    144 add_test(() => {
    145  // Try again, while we already keep a cache entry,
    146  // the channel must not use it, entry should stay in the cache
    147  var ch = make_channel(resource_age_100_url, "no-store");
    148  ch.asyncOpen(
    149    new ChannelListener(function () {
    150      Assert.ok(hit_server);
    151      Assert.ok(cache.exists(make_uri(resource_age_100_url), ""));
    152 
    153      run_next_test();
    154    }, null)
    155  );
    156 });
    157 
    158 // ============================================================================
    159 // Cache-Control: no-cache
    160 
    161 add_test(() => {
    162  // Check the prepared cache entry is used when no special directives are added
    163  var ch = make_channel(resource_age_100_url);
    164  ch.asyncOpen(
    165    new ChannelListener(function () {
    166      Assert.ok(!hit_server);
    167      Assert.ok(cache.exists(make_uri(resource_age_100_url), ""));
    168 
    169      run_next_test();
    170    }, null)
    171  );
    172 });
    173 
    174 add_test(() => {
    175  // The existing entry should be revalidated (we expect a server hit)
    176  var ch = make_channel(resource_age_100_url, "no-cache");
    177  ch.asyncOpen(
    178    new ChannelListener(function () {
    179      Assert.ok(hit_server);
    180      Assert.ok(cache.exists(make_uri(resource_age_100_url), ""));
    181 
    182      run_next_test();
    183    }, null)
    184  );
    185 });
    186 
    187 // ============================================================================
    188 // Cache-Control: max-age
    189 
    190 add_test(() => {
    191  // Check the prepared cache entry is used when no special directives are added
    192  var ch = make_channel(resource_age_100_url);
    193  ch.asyncOpen(
    194    new ChannelListener(function () {
    195      Assert.ok(!hit_server);
    196      Assert.ok(cache.exists(make_uri(resource_age_100_url), ""));
    197 
    198      run_next_test();
    199    }, null)
    200  );
    201 });
    202 
    203 add_test(() => {
    204  // The existing entry's age is greater than the maximum requested,
    205  // should hit server
    206  var ch = make_channel(resource_age_100_url, "max-age=10");
    207  ch.asyncOpen(
    208    new ChannelListener(function () {
    209      Assert.ok(hit_server);
    210      Assert.ok(cache.exists(make_uri(resource_age_100_url), ""));
    211 
    212      run_next_test();
    213    }, null)
    214  );
    215 });
    216 
    217 add_test(() => {
    218  // The existing entry's age is greater than the maximum requested,
    219  // but the max-stale directive says to use it when it's fresh enough
    220  var ch = make_channel(resource_age_100_url, "max-age=10, max-stale=99999");
    221  ch.asyncOpen(
    222    new ChannelListener(function () {
    223      Assert.ok(!hit_server);
    224      Assert.ok(cache.exists(make_uri(resource_age_100_url), ""));
    225 
    226      run_next_test();
    227    }, null)
    228  );
    229 });
    230 
    231 add_test(() => {
    232  // The existing entry's age is lesser than the maximum requested,
    233  // should go from cache
    234  var ch = make_channel(resource_age_100_url, "max-age=1000");
    235  ch.asyncOpen(
    236    new ChannelListener(function () {
    237      Assert.ok(!hit_server);
    238      Assert.ok(cache.exists(make_uri(resource_age_100_url), ""));
    239 
    240      run_next_test();
    241    }, null)
    242  );
    243 });
    244 
    245 // ============================================================================
    246 // Cache-Control: max-stale
    247 
    248 add_test(() => {
    249  // Preprate the entry first
    250  var ch = make_channel(resource_stale_100_url);
    251  ch.asyncOpen(
    252    new ChannelListener(function () {
    253      Assert.ok(hit_server);
    254      Assert.ok(cache.exists(make_uri(resource_stale_100_url), ""));
    255 
    256      // Must shift the expiration time set on the entry to |now| be in the past
    257      do_timeout(1500, run_next_test);
    258    }, null)
    259  );
    260 });
    261 
    262 add_test(() => {
    263  // Check it's not reused (as it's stale) when no special directives
    264  // are provided
    265  var ch = make_channel(resource_stale_100_url);
    266  ch.asyncOpen(
    267    new ChannelListener(function () {
    268      Assert.ok(hit_server);
    269      Assert.ok(cache.exists(make_uri(resource_stale_100_url), ""));
    270 
    271      do_timeout(1500, run_next_test);
    272    }, null)
    273  );
    274 });
    275 
    276 add_test(() => {
    277  // Accept cached responses of any stale time
    278  var ch = make_channel(resource_stale_100_url, "max-stale");
    279  ch.asyncOpen(
    280    new ChannelListener(function () {
    281      Assert.ok(!hit_server);
    282      Assert.ok(cache.exists(make_uri(resource_stale_100_url), ""));
    283 
    284      do_timeout(1500, run_next_test);
    285    }, null)
    286  );
    287 });
    288 
    289 add_test(() => {
    290  // The entry is stale only by 100 seconds, accept it
    291  var ch = make_channel(resource_stale_100_url, "max-stale=1000");
    292  ch.asyncOpen(
    293    new ChannelListener(function () {
    294      Assert.ok(!hit_server);
    295      Assert.ok(cache.exists(make_uri(resource_stale_100_url), ""));
    296 
    297      do_timeout(1500, run_next_test);
    298    }, null)
    299  );
    300 });
    301 
    302 add_test(() => {
    303  // The entry is stale by 100 seconds but we only accept a 10 seconds stale
    304  // entry, go from server
    305  var ch = make_channel(resource_stale_100_url, "max-stale=10");
    306  ch.asyncOpen(
    307    new ChannelListener(function () {
    308      Assert.ok(hit_server);
    309      Assert.ok(cache.exists(make_uri(resource_stale_100_url), ""));
    310 
    311      run_next_test();
    312    }, null)
    313  );
    314 });
    315 
    316 // ============================================================================
    317 // Cache-Control: min-fresh
    318 
    319 add_test(() => {
    320  // Preprate the entry first
    321  var ch = make_channel(resource_fresh_100_url);
    322  ch.asyncOpen(
    323    new ChannelListener(function () {
    324      Assert.ok(hit_server);
    325      Assert.ok(cache.exists(make_uri(resource_fresh_100_url), ""));
    326 
    327      run_next_test();
    328    }, null)
    329  );
    330 });
    331 
    332 add_test(() => {
    333  // Check it's reused when no special directives are provided
    334  var ch = make_channel(resource_fresh_100_url);
    335  ch.asyncOpen(
    336    new ChannelListener(function () {
    337      Assert.ok(!hit_server);
    338      Assert.ok(cache.exists(make_uri(resource_fresh_100_url), ""));
    339 
    340      run_next_test();
    341    }, null)
    342  );
    343 });
    344 
    345 add_test(() => {
    346  // Entry fresh enough to be served from the cache
    347  var ch = make_channel(resource_fresh_100_url, "min-fresh=10");
    348  ch.asyncOpen(
    349    new ChannelListener(function () {
    350      Assert.ok(!hit_server);
    351      Assert.ok(cache.exists(make_uri(resource_fresh_100_url), ""));
    352 
    353      run_next_test();
    354    }, null)
    355  );
    356 });
    357 
    358 add_test(() => {
    359  // The entry is not fresh enough
    360  var ch = make_channel(resource_fresh_100_url, "min-fresh=1000");
    361  ch.asyncOpen(
    362    new ChannelListener(function () {
    363      Assert.ok(hit_server);
    364      Assert.ok(cache.exists(make_uri(resource_fresh_100_url), ""));
    365 
    366      run_next_test();
    367    }, null)
    368  );
    369 });
    370 
    371 // ============================================================================
    372 // Parser test, if the Cache-Control header would not parse correctly, the entry
    373 // doesn't load from the server.
    374 
    375 add_test(() => {
    376  var ch = make_channel(
    377    resource_fresh_100_url,
    378    'unknown1,unknown2 = "a,b",  min-fresh = 1000 '
    379  );
    380  ch.asyncOpen(
    381    new ChannelListener(function () {
    382      Assert.ok(hit_server);
    383      Assert.ok(cache.exists(make_uri(resource_fresh_100_url), ""));
    384 
    385      run_next_test();
    386    }, null)
    387  );
    388 });
    389 
    390 add_test(() => {
    391  var ch = make_channel(resource_fresh_100_url, "no-cache = , min-fresh = 10");
    392  ch.asyncOpen(
    393    new ChannelListener(function () {
    394      Assert.ok(hit_server);
    395      Assert.ok(cache.exists(make_uri(resource_fresh_100_url), ""));
    396 
    397      run_next_test();
    398    }, null)
    399  );
    400 });
    401 
    402 // ============================================================================
    403 // Done
    404 
    405 add_test(() => {
    406  run_next_test();
    407  httpserver.stop(do_test_finished);
    408 });
    409 
    410 // ============================================================================
    411 // Helpers
    412 
    413 function date_string_from_now(delta_secs) {
    414  var months = [
    415    "Jan",
    416    "Feb",
    417    "Mar",
    418    "Apr",
    419    "May",
    420    "Jun",
    421    "Jul",
    422    "Aug",
    423    "Sep",
    424    "Oct",
    425    "Nov",
    426    "Dec",
    427  ];
    428  var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
    429 
    430  var d = new Date();
    431  d.setTime(d.getTime() + delta_secs * 1000);
    432  return (
    433    days[d.getUTCDay()] +
    434    ", " +
    435    d.getUTCDate() +
    436    " " +
    437    months[d.getUTCMonth()] +
    438    " " +
    439    d.getUTCFullYear() +
    440    " " +
    441    d.getUTCHours() +
    442    ":" +
    443    d.getUTCMinutes() +
    444    ":" +
    445    d.getUTCSeconds() +
    446    " UTC"
    447  );
    448 }