tor-browser

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

test_headers_common.js (7554B)


      1 //
      2 // Utility functions
      3 //
      4 
      5 function shouldThrow(func, expected, msg) {
      6  var err;
      7  try {
      8    func();
      9  } catch (e) {
     10    err = e;
     11  } finally {
     12    ok(err instanceof expected, msg);
     13  }
     14 }
     15 
     16 function recursiveArrayCompare(actual, expected) {
     17  is(
     18    Array.isArray(actual),
     19    Array.isArray(expected),
     20    "Both should either be arrays, or not"
     21  );
     22  if (Array.isArray(actual) && Array.isArray(expected)) {
     23    var diff = actual.length !== expected.length;
     24 
     25    for (var i = 0, n = actual.length; !diff && i < n; ++i) {
     26      diff = recursiveArrayCompare(actual[i], expected[i]);
     27    }
     28 
     29    return diff;
     30  } else {
     31    return actual !== expected;
     32  }
     33 }
     34 
     35 function arrayEquals(actual, expected, msg) {
     36  if (actual === expected) {
     37    return;
     38  }
     39 
     40  var diff = recursiveArrayCompare(actual, expected);
     41 
     42  ok(!diff, msg);
     43  if (diff) {
     44    is(actual, expected, msg);
     45  }
     46 }
     47 
     48 function checkHas(headers, name, msg) {
     49  function doCheckHas(n) {
     50    return headers.has(n);
     51  }
     52  return _checkHas(doCheckHas, headers, name, msg);
     53 }
     54 
     55 function checkNotHas(headers, name, msg) {
     56  function doCheckNotHas(n) {
     57    return !headers.has(n);
     58  }
     59  return _checkHas(doCheckNotHas, headers, name, msg);
     60 }
     61 
     62 function _checkHas(func, headers, name, msg) {
     63  ok(func(name), msg);
     64  ok(func(name.toLowerCase()), msg);
     65  ok(func(name.toUpperCase()), msg);
     66 }
     67 
     68 function checkGet(headers, name, expected, msg) {
     69  is(headers.get(name), expected, msg);
     70  is(headers.get(name.toLowerCase()), expected, msg);
     71  is(headers.get(name.toUpperCase()), expected, msg);
     72 }
     73 
     74 //
     75 // Test Cases
     76 //
     77 
     78 function TestCoreBehavior(headers, name) {
     79  var start = headers.get(name);
     80 
     81  headers.append(name, "bar");
     82 
     83  checkHas(headers, name, "Has the header");
     84  var expected = start ? start.concat(", bar") : "bar";
     85  checkGet(headers, name, expected, "Retrieve all headers for name");
     86 
     87  headers.append(name, "baz");
     88  checkHas(headers, name, "Has the header");
     89  expected = start ? start.concat(", bar, baz") : "bar, baz";
     90  checkGet(headers, name, expected, "Retrieve all headers for name");
     91 
     92  headers.set(name, "snafu");
     93  checkHas(headers, name, "Has the header after set");
     94  checkGet(headers, name, "snafu", "Retrieve all headers after set");
     95 
     96  const value_bam = "boom";
     97  let testHTTPWhitespace = ["\t", "\n", "\r", " "];
     98  while (testHTTPWhitespace.length) {
     99    headers.delete(name);
    100 
    101    let char = testHTTPWhitespace.shift();
    102    headers.set(name, char);
    103    checkGet(
    104      headers,
    105      name,
    106      "",
    107      "Header value " +
    108        char +
    109        " should be normalized before checking and throwing"
    110    );
    111    headers.delete(name);
    112 
    113    let valueFront = char + value_bam;
    114    headers.set(name, valueFront);
    115    checkGet(
    116      headers,
    117      name,
    118      value_bam,
    119      "Header value " +
    120        valueFront +
    121        " should be normalized before checking and throwing"
    122    );
    123 
    124    headers.delete(name);
    125 
    126    let valueBack = value_bam + char;
    127    headers.set(name, valueBack);
    128    checkGet(
    129      headers,
    130      name,
    131      value_bam,
    132      "Header value " +
    133        valueBack +
    134        " should be normalized before checking and throwing"
    135    );
    136  }
    137 
    138  headers.delete(name.toUpperCase());
    139  checkNotHas(headers, name, "Does not have the header after delete");
    140  checkGet(headers, name, null, "Retrieve all headers after delete");
    141 
    142  // should be ok to delete non-existent name
    143  headers.delete(name);
    144 
    145  shouldThrow(
    146    function () {
    147      headers.append("foo,", "bam");
    148    },
    149    TypeError,
    150    "Append invalid header name should throw TypeError."
    151  );
    152 
    153  shouldThrow(
    154    function () {
    155      headers.append(name, "ba\nm");
    156    },
    157    TypeError,
    158    "Append invalid header value should throw TypeError."
    159  );
    160 
    161  shouldThrow(
    162    function () {
    163      headers.append(name, "ba\rm");
    164    },
    165    TypeError,
    166    "Append invalid header value should throw TypeError."
    167  );
    168 
    169  ok(!headers.guard, "guard should be undefined in content");
    170 }
    171 
    172 function TestEmptyHeaders() {
    173  is(typeof Headers, "function", "Headers global constructor exists.");
    174  var headers = new Headers();
    175  ok(headers, "Constructed empty Headers object");
    176  TestCoreBehavior(headers, "foo");
    177 }
    178 
    179 function TestFilledHeaders() {
    180  var source = new Headers();
    181  var filled = new Headers(source);
    182  ok(filled, "Fill header from empty header");
    183  TestCoreBehavior(filled, "foo");
    184 
    185  source = new Headers();
    186  source.append("abc", "123");
    187  source.append("def", "456");
    188  source.append("def", "789");
    189 
    190  filled = new Headers(source);
    191  checkGet(
    192    filled,
    193    "abc",
    194    source.get("abc"),
    195    "Single value header list matches"
    196  );
    197  checkGet(
    198    filled,
    199    "def",
    200    source.get("def"),
    201    "Multiple value header list matches"
    202  );
    203  TestCoreBehavior(filled, "def");
    204 
    205  filled = new Headers({
    206    zxy: "987",
    207    xwv: "654",
    208    uts: "321",
    209  });
    210  checkGet(filled, "zxy", "987", "Has first object filled key");
    211  checkGet(filled, "xwv", "654", "Has second object filled key");
    212  checkGet(filled, "uts", "321", "Has third object filled key");
    213  TestCoreBehavior(filled, "xwv");
    214 
    215  filled = new Headers([
    216    ["zxy", "987"],
    217    ["xwv", "654"],
    218    ["xwv", "abc"],
    219    ["uts", "321"],
    220  ]);
    221  checkGet(filled, "zxy", "987", "Has first sequence filled key");
    222  checkGet(filled, "xwv", "654, abc", "Has second sequence filled key");
    223  checkGet(filled, "uts", "321", "Has third sequence filled key");
    224  TestCoreBehavior(filled, "xwv");
    225 
    226  shouldThrow(
    227    function () {
    228      filled = new Headers([
    229        ["zxy", "987", "654"],
    230        ["uts", "321"],
    231      ]);
    232    },
    233    TypeError,
    234    "Fill with non-tuple sequence should throw TypeError."
    235  );
    236 
    237  shouldThrow(
    238    function () {
    239      filled = new Headers([["zxy"], ["uts", "321"]]);
    240    },
    241    TypeError,
    242    "Fill with non-tuple sequence should throw TypeError."
    243  );
    244 }
    245 
    246 function iterate(iter) {
    247  var result = [];
    248  for (var val = iter.next(); !val.done; ) {
    249    result.push(val.value);
    250    val = iter.next();
    251  }
    252  return result;
    253 }
    254 
    255 function iterateForOf(iter) {
    256  var result = [];
    257  for (var value of iter) {
    258    result.push(value);
    259  }
    260  return result;
    261 }
    262 
    263 function byteInflate(str) {
    264  var encoder = new TextEncoder();
    265  var encoded = encoder.encode(str);
    266  var result = "";
    267  for (var i = 0; i < encoded.length; ++i) {
    268    result += String.fromCharCode(encoded[i]);
    269  }
    270  return result;
    271 }
    272 
    273 function TestHeadersIterator() {
    274  var ehsanInflated = byteInflate("احسان");
    275  var headers = new Headers();
    276  headers.set("foo0", "bar0");
    277  headers.append("foo", "bar");
    278  headers.append("foo", ehsanInflated);
    279  headers.append("Foo2", "bar2");
    280  headers.set("Foo2", "baz2");
    281  headers.set("foo3", "bar3");
    282  headers.delete("foo0");
    283  headers.delete("foo3");
    284 
    285  var key_iter = headers.keys();
    286  var value_iter = headers.values();
    287  var entries_iter = headers.entries();
    288 
    289  arrayEquals(iterate(key_iter), ["foo", "foo2"], "Correct key iterator");
    290  arrayEquals(
    291    iterate(value_iter),
    292    ["bar, " + ehsanInflated, "baz2"],
    293    "Correct value iterator"
    294  );
    295  arrayEquals(
    296    iterate(entries_iter),
    297    [
    298      ["foo", "bar, " + ehsanInflated],
    299      ["foo2", "baz2"],
    300    ],
    301    "Correct entries iterator"
    302  );
    303 
    304  arrayEquals(
    305    iterateForOf(headers),
    306    [
    307      ["foo", "bar, " + ehsanInflated],
    308      ["foo2", "baz2"],
    309    ],
    310    "Correct entries iterator"
    311  );
    312  arrayEquals(
    313    iterateForOf(new Headers(headers)),
    314    [
    315      ["foo", "bar, " + ehsanInflated],
    316      ["foo2", "baz2"],
    317    ],
    318    "Correct entries iterator"
    319  );
    320 }
    321 
    322 function runTest() {
    323  TestEmptyHeaders();
    324  TestFilledHeaders();
    325  TestHeadersIterator();
    326  return Promise.resolve();
    327 }