tor-browser

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

test-helpers.js (9266B)


      1 (function() {
      2  var next_cache_index = 1;
      3 
      4  // Returns a promise that resolves to a newly created Cache object. The
      5  // returned Cache will be destroyed when |test| completes.
      6  function create_temporary_cache(test) {
      7    var uniquifier = String(++next_cache_index);
      8    var cache_name = self.location.pathname + '/' + uniquifier;
      9 
     10    test.add_cleanup(function() {
     11        self.caches.delete(cache_name);
     12      });
     13 
     14    return self.caches.delete(cache_name)
     15      .then(function() {
     16          return self.caches.open(cache_name);
     17        });
     18  }
     19 
     20  self.create_temporary_cache = create_temporary_cache;
     21 })();
     22 
     23 // Runs |test_function| with a temporary unique Cache passed in as the only
     24 // argument. The function is run as a part of Promise chain owned by
     25 // promise_test(). As such, it is expected to behave in a manner identical (with
     26 // the exception of the argument) to a function passed into promise_test().
     27 //
     28 // E.g.:
     29 //    cache_test(function(cache) {
     30 //      // Do something with |cache|, which is a Cache object.
     31 //    }, "Some Cache test");
     32 function cache_test(test_function, description) {
     33  promise_test(function(test) {
     34      return create_temporary_cache(test)
     35        .then(function(cache) { return test_function(cache, test); });
     36    }, description);
     37 }
     38 
     39 // A set of Request/Response pairs to be used with prepopulated_cache_test().
     40 var simple_entries = [
     41  {
     42    name: 'a',
     43    request: new Request('http://example.com/a'),
     44    response: new Response('')
     45  },
     46 
     47  {
     48    name: 'b',
     49    request: new Request('http://example.com/b'),
     50    response: new Response('')
     51  },
     52 
     53  {
     54    name: 'a_with_query',
     55    request: new Request('http://example.com/a?q=r'),
     56    response: new Response('')
     57  },
     58 
     59  {
     60    name: 'A',
     61    request: new Request('http://example.com/A'),
     62    response: new Response('')
     63  },
     64 
     65  {
     66    name: 'a_https',
     67    request: new Request('https://example.com/a'),
     68    response: new Response('')
     69  },
     70 
     71  {
     72    name: 'a_org',
     73    request: new Request('http://example.org/a'),
     74    response: new Response('')
     75  },
     76 
     77  {
     78    name: 'cat',
     79    request: new Request('http://example.com/cat'),
     80    response: new Response('')
     81  },
     82 
     83  {
     84    name: 'catmandu',
     85    request: new Request('http://example.com/catmandu'),
     86    response: new Response('')
     87  },
     88 
     89  {
     90    name: 'cat_num_lives',
     91    request: new Request('http://example.com/cat?lives=9'),
     92    response: new Response('')
     93  },
     94 
     95  {
     96    name: 'cat_in_the_hat',
     97    request: new Request('http://example.com/cat/in/the/hat'),
     98    response: new Response('')
     99  },
    100 
    101  {
    102    name: 'non_2xx_response',
    103    request: new Request('http://example.com/non2xx'),
    104    response: new Response('', {status: 404, statusText: 'nope'})
    105  },
    106 
    107  {
    108    name: 'error_response',
    109    request: new Request('http://example.com/error'),
    110    response: Response.error()
    111  },
    112 ];
    113 
    114 // A set of Request/Response pairs to be used with prepopulated_cache_test().
    115 // These contain a mix of test cases that use Vary headers.
    116 var vary_entries = [
    117  {
    118    name: 'vary_cookie_is_cookie',
    119    request: new Request('http://example.com/c',
    120                         {headers: {'Cookies': 'is-for-cookie'}}),
    121    response: new Response('',
    122                           {headers: {'Vary': 'Cookies'}})
    123  },
    124 
    125  {
    126    name: 'vary_cookie_is_good',
    127    request: new Request('http://example.com/c',
    128                         {headers: {'Cookies': 'is-good-enough-for-me'}}),
    129    response: new Response('',
    130                           {headers: {'Vary': 'Cookies'}})
    131  },
    132 
    133  {
    134    name: 'vary_cookie_absent',
    135    request: new Request('http://example.com/c'),
    136    response: new Response('',
    137                           {headers: {'Vary': 'Cookies'}})
    138  }
    139 ];
    140 
    141 // Run |test_function| with a Cache object and a map of entries. Prior to the
    142 // call, the Cache is populated by cache entries from |entries|. The latter is
    143 // expected to be an Object mapping arbitrary keys to objects of the form
    144 // {request: <Request object>, response: <Response object>}. Entries are
    145 // serially added to the cache in the order specified.
    146 //
    147 // |test_function| should return a Promise that can be used with promise_test.
    148 function prepopulated_cache_test(entries, test_function, description) {
    149  cache_test(function(cache) {
    150      var p = Promise.resolve();
    151      var hash = {};
    152      entries.forEach(function(entry) {
    153          hash[entry.name] = entry;
    154          p = p.then(function() {
    155              return cache.put(entry.request.clone(), entry.response.clone())
    156                  .catch(function(e) {
    157                      assert_unreached(
    158                          'Test setup failed for entry ' + entry.name + ': ' + e
    159                      );
    160                  });
    161          });
    162      });
    163      return p
    164        .then(function() {
    165            assert_equals(Object.keys(hash).length, entries.length);
    166        })
    167        .then(function() {
    168            return test_function(cache, hash);
    169        });
    170    }, description);
    171 }
    172 
    173 // Helper for testing with Headers objects. Compares Headers instances
    174 // by serializing |expected| and |actual| to arrays and comparing.
    175 function assert_header_equals(actual, expected, description) {
    176    assert_class_string(actual, "Headers", description);
    177    var header;
    178    var actual_headers = [];
    179    var expected_headers = [];
    180    for (header of actual)
    181        actual_headers.push(header[0] + ": " + header[1]);
    182    for (header of expected)
    183        expected_headers.push(header[0] + ": " + header[1]);
    184    assert_array_equals(actual_headers, expected_headers,
    185                        description + " Headers differ.");
    186 }
    187 
    188 // Helper for testing with Response objects. Compares simple
    189 // attributes defined on the interfaces, as well as the headers. It
    190 // does not compare the response bodies.
    191 function assert_response_equals(actual, expected, description) {
    192    assert_class_string(actual, "Response", description);
    193    ["type", "url", "status", "ok", "statusText"].forEach(function(attribute) {
    194        assert_equals(actual[attribute], expected[attribute],
    195                      description + " Attributes differ: " + attribute + ".");
    196    });
    197    assert_header_equals(actual.headers, expected.headers, description);
    198 }
    199 
    200 // Assert that the two arrays |actual| and |expected| contain the same
    201 // set of Responses as determined by assert_response_equals. The order
    202 // is not significant.
    203 //
    204 // |expected| is assumed to not contain any duplicates.
    205 function assert_response_array_equivalent(actual, expected, description) {
    206    assert_true(Array.isArray(actual), description);
    207    assert_equals(actual.length, expected.length, description);
    208    expected.forEach(function(expected_element) {
    209        // assert_response_in_array treats the first argument as being
    210        // 'actual', and the second as being 'expected array'. We are
    211        // switching them around because we want to be resilient
    212        // against the |actual| array containing duplicates.
    213        assert_response_in_array(expected_element, actual, description);
    214    });
    215 }
    216 
    217 // Asserts that two arrays |actual| and |expected| contain the same
    218 // set of Responses as determined by assert_response_equals(). The
    219 // corresponding elements must occupy corresponding indices in their
    220 // respective arrays.
    221 function assert_response_array_equals(actual, expected, description) {
    222    assert_true(Array.isArray(actual), description);
    223    assert_equals(actual.length, expected.length, description);
    224    actual.forEach(function(value, index) {
    225        assert_response_equals(value, expected[index],
    226                               description + " : object[" + index + "]");
    227    });
    228 }
    229 
    230 // Equivalent to assert_in_array, but uses assert_response_equals.
    231 function assert_response_in_array(actual, expected_array, description) {
    232    assert_true(expected_array.some(function(element) {
    233        try {
    234            assert_response_equals(actual, element);
    235            return true;
    236        } catch (e) {
    237            return false;
    238        }
    239    }), description);
    240 }
    241 
    242 // Helper for testing with Request objects. Compares simple
    243 // attributes defined on the interfaces, as well as the headers.
    244 function assert_request_equals(actual, expected, description) {
    245    assert_class_string(actual, "Request", description);
    246    ["url"].forEach(function(attribute) {
    247        assert_equals(actual[attribute], expected[attribute],
    248                      description + " Attributes differ: " + attribute + ".");
    249    });
    250    assert_header_equals(actual.headers, expected.headers, description);
    251 }
    252 
    253 // Asserts that two arrays |actual| and |expected| contain the same
    254 // set of Requests as determined by assert_request_equals(). The
    255 // corresponding elements must occupy corresponding indices in their
    256 // respective arrays.
    257 function assert_request_array_equals(actual, expected, description) {
    258    assert_true(Array.isArray(actual), description);
    259    assert_equals(actual.length, expected.length, description);
    260    actual.forEach(function(value, index) {
    261        assert_request_equals(value, expected[index],
    262                              description + " : object[" + index + "]");
    263    });
    264 }
    265 
    266 // Deletes all caches, returning a promise indicating success.
    267 function delete_all_caches() {
    268  return self.caches.keys()
    269    .then(function(keys) {
    270      return Promise.all(keys.map(self.caches.delete.bind(self.caches)));
    271    });
    272 }