tor-browser

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

test_keys.js (8439B)


      1 /**
      2 * Any copyright is dedicated to the Public Domain.
      3 * http://creativecommons.org/publicdomain/zero/1.0/
      4 */
      5 
      6 /* exported testGenerator */
      7 var testGenerator = testSteps();
      8 
      9 // helper function that ensures that ArrayBuffer instances are meaningfully
     10 // displayed (not just as 'object ArrayBuffer')
     11 // TODO better move to helpers.js?
     12 function showKey(key) {
     13  if (key instanceof Array) {
     14    return key.map(x => showKey(x)).toString();
     15  }
     16  if (key instanceof ArrayBuffer) {
     17    return "ArrayBuffer([" + new Uint8Array(key).toString() + "])";
     18  }
     19  return key.toString();
     20 }
     21 
     22 function* testSteps() {
     23  const dbname = this.window ? window.location.pathname : "Splendid Test";
     24 
     25  let openRequest = indexedDB.open(dbname, 1);
     26  openRequest.onerror = errorHandler;
     27  openRequest.onupgradeneeded = grabEventAndContinueHandler;
     28  openRequest.onsuccess = unexpectedSuccessHandler;
     29  let event = yield undefined;
     30  let db = event.target.result;
     31 
     32  // Create test stores
     33  let store = db.createObjectStore("store");
     34  let enc = new TextEncoder();
     35 
     36  // Test simple inserts
     37  // Note: the keys must be in order
     38  var keys = [
     39    -1 / 0,
     40    -1.7e308,
     41    -10000,
     42    -2,
     43    -1.5,
     44    -1,
     45    -1.00001e-200,
     46    -1e-200,
     47    0,
     48    1e-200,
     49    1.00001e-200,
     50    1,
     51    2,
     52    10000,
     53    1.7e308,
     54    1 / 0,
     55    new Date("1750-01-02"),
     56    new Date("1800-12-31T12:34:56.001"),
     57    new Date(-1000),
     58    new Date(-10),
     59    new Date(-1),
     60    new Date(0),
     61    new Date(1),
     62    new Date(2),
     63    new Date(1000),
     64    new Date("1971-01-01"),
     65    new Date("1971-01-01T01:01:01Z"),
     66    new Date("1971-01-01T01:01:01.001Z"),
     67    new Date("1971-01-01T01:01:01.01Z"),
     68    new Date("1971-01-01T01:01:01.1Z"),
     69    new Date("1980-02-02"),
     70    new Date("3333-03-19T03:33:33.333"),
     71    "",
     72    "\x00",
     73    "\x00\x00",
     74    "\x00\x01",
     75    "\x01",
     76    "\x02",
     77    "\x03",
     78    "\x04",
     79    "\x07",
     80    "\x08",
     81    "\x0F",
     82    "\x10",
     83    "\x1F",
     84    "\x20",
     85    "01234",
     86    "\x3F",
     87    "\x40",
     88    "A",
     89    "A\x00",
     90    "A1",
     91    "ZZZZ",
     92    "a",
     93    "a\x00",
     94    "aa",
     95    "azz",
     96    "}",
     97    "\x7E",
     98    "\x7F",
     99    "\x80",
    100    "\xFF",
    101    "\u0100",
    102    "\u01FF",
    103    "\u0200",
    104    "\u03FF",
    105    "\u0400",
    106    "\u07FF",
    107    "\u0800",
    108    "\u0FFF",
    109    "\u1000",
    110    "\u1FFF",
    111    "\u2000",
    112    "\u3FFF",
    113    "\u4000",
    114    "\u7FFF",
    115    "\u8000",
    116    "\uD800",
    117    "\uD800a",
    118    "\uD800\uDC01",
    119    "\uDBFF",
    120    "\uDC00",
    121    "\uDFFF\uD800",
    122    "\uFFFE",
    123    "\uFFFF",
    124    "\uFFFF\x00",
    125    "\uFFFFZZZ",
    126    // Note: enc.encode returns an Uint8Array, which is a valid key, but when
    127    // converting it back and forth, the result will be a plain ArrayBuffer,
    128    // which is expected in comparisons below
    129    // TODO is it ok that the information that the original key was an
    130    // Uint8Array is lost?
    131    new ArrayBuffer(0),
    132    Uint8Array.from([0]).buffer,
    133    Uint8Array.from([0, 0]).buffer,
    134    Uint8Array.from([0, 1]).buffer,
    135    Uint8Array.from([0, 1, 0]).buffer,
    136    enc.encode("abc").buffer,
    137    enc.encode("abcd").buffer,
    138    enc.encode("xyz").buffer,
    139    Uint8Array.from([0x80]).buffer,
    140    [],
    141    [-1 / 0],
    142    [-1],
    143    [0],
    144    [1],
    145    [1, "a"],
    146    [1, []],
    147    [1, [""]],
    148    [2, 3],
    149    [2, 3.0000000000001],
    150    [12, [[]]],
    151    [12, [[[]]]],
    152    [12, [[[""]]]],
    153    [12, [[["foo"]]]],
    154    [12, [[[[[3]]]]]],
    155    [12, [[[[[[3]]]]]]],
    156    [new Date(-1)],
    157    [new Date(1)],
    158    [""],
    159    ["", [[]]],
    160    ["", [[[]]]],
    161    ["abc"],
    162    ["abc", "def"],
    163    ["abc\x00"],
    164    ["abc\x00", "\x00\x01"],
    165    ["abc\x00", "\x00def"],
    166    ["abc\x00\x00def"],
    167    ["x", [[]]],
    168    ["x", [[[]]]],
    169    // see comment on scalar ArrayBuffers above
    170    [new ArrayBuffer(0)],
    171    [new ArrayBuffer(0), "abc"],
    172    [new ArrayBuffer(0), new ArrayBuffer(0)],
    173    [new ArrayBuffer(0), enc.encode("abc").buffer],
    174    [enc.encode("abc").buffer],
    175    [enc.encode("abc").buffer, new ArrayBuffer(0)],
    176    [enc.encode("abc").buffer, enc.encode("xyz").buffer],
    177    [enc.encode("xyz").buffer],
    178    [[]],
    179    [[], "foo"],
    180    [[], []],
    181    [[[]]],
    182    [[[]], []],
    183    [[[]], [[]]],
    184    [[[]], [[1]]],
    185    [[[]], [[[]]]],
    186    [[[1]]],
    187    [[[[]], []]],
    188  ];
    189 
    190  for (var i = 0; i < keys.length; ++i) {
    191    let keyI = keys[i];
    192    is(indexedDB.cmp(keyI, keyI), 0, i + " compared to self");
    193 
    194    function doCompare(keyI) {
    195      for (var j = i - 1; j >= i - 10 && j >= 0; --j) {
    196        is(indexedDB.cmp(keyI, keys[j]), 1, i + " compared to " + j);
    197        is(indexedDB.cmp(keys[j], keyI), -1, j + " compared to " + i);
    198      }
    199    }
    200 
    201    doCompare(keyI);
    202    store.add(i, keyI).onsuccess = function (e) {
    203      is(
    204        indexedDB.cmp(e.target.result, keyI),
    205        0,
    206        "Returned key should cmp as equal; index = " +
    207          i +
    208          ", input = " +
    209          showKey(keyI) +
    210          ", returned = " +
    211          showKey(e.target.result)
    212      );
    213      ok(
    214        compareKeys(e.target.result, keyI),
    215        "Returned key should actually be equal; index = " +
    216          i +
    217          ", input = " +
    218          showKey(keyI) +
    219          ", returned = " +
    220          showKey(e.target.result)
    221      );
    222    };
    223 
    224    // Test that -0 compares the same as 0
    225    if (keyI === 0) {
    226      doCompare(-0);
    227      let req = store.add(i, -0);
    228      req.addEventListener("error", new ExpectError("ConstraintError", true));
    229      req.onsuccess = unexpectedSuccessHandler;
    230      yield undefined;
    231    } else if (Array.isArray(keyI) && keyI.length === 1 && keyI[0] === 0) {
    232      doCompare([-0]);
    233      let req = store.add(i, [-0]);
    234      req.addEventListener("error", new ExpectError("ConstraintError", true));
    235      req.onsuccess = unexpectedSuccessHandler;
    236      yield undefined;
    237    }
    238  }
    239 
    240  store.openCursor().onsuccess = grabEventAndContinueHandler;
    241  for (i = 0; i < keys.length; ++i) {
    242    event = yield undefined;
    243    let cursor = event.target.result;
    244    is(
    245      indexedDB.cmp(cursor.key, keys[i]),
    246      0,
    247      "Read back key should cmp as equal; index = " +
    248        i +
    249        ", input = " +
    250        showKey(keys[i]) +
    251        ", readBack = " +
    252        showKey(cursor.key)
    253    );
    254    ok(
    255      compareKeys(cursor.key, keys[i]),
    256      "Read back key should actually be equal; index = " +
    257        i +
    258        ", input = " +
    259        showKey(keys[i]) +
    260        ", readBack = " +
    261        showKey(cursor.key)
    262    );
    263    is(cursor.value, i, "Stored with right value");
    264 
    265    cursor.continue();
    266  }
    267  event = yield undefined;
    268  is(event.target.result, null, "no more results expected");
    269 
    270  let nan = 0 / 0;
    271  let invalidKeys = [
    272    nan,
    273    undefined,
    274    null,
    275    /x/,
    276    {},
    277    new Date(NaN),
    278    new Date("foopy"),
    279    [nan],
    280    [undefined],
    281    [null],
    282    [/x/],
    283    [{}],
    284    [new Date(NaN)],
    285    [1, nan],
    286    [1, undefined],
    287    [1, null],
    288    [1, /x/],
    289    [1, {}],
    290    [1, [nan]],
    291    [1, [undefined]],
    292    [1, [null]],
    293    [1, [/x/]],
    294    [1, [{}]],
    295  ];
    296 
    297  try {
    298    // ATTENTION, the following key allocates 2GB of memory and might cause
    299    // subtle failures in some environments, see bug 1796753. We might
    300    // want to have some common way between IndexeDB mochitests and
    301    // xpcshell tests how to access AppConstants in order to dynamically
    302    // exclude this key from some environments, rather than disabling the
    303    // entire xpcshell variant of this test for ASAN/TSAN.
    304    invalidKeys.push(new Uint8Array(2147483647));
    305  } catch {
    306    info("Key instantiation failed, skipping");
    307  }
    308 
    309  function checkInvalidKeyException(ex, i, callText) {
    310    let suffix = ` during ${callText} with invalid key ${i}: ${invalidKeys[i]}`;
    311    // isInstance() is not available in mochitest, and we use this JS also as mochitest.
    312    // eslint-disable-next-line mozilla/use-isInstance
    313    ok(ex instanceof DOMException, "Threw DOMException" + suffix);
    314    is(ex.name, "DataError", "Threw right DOMException" + suffix);
    315    is(ex.code, 0, "Threw with right code" + suffix);
    316  }
    317 
    318  for (let key of invalidKeys) {
    319    try {
    320      indexedDB.cmp(key, 1);
    321      ok(false, "didn't throw");
    322    } catch (ex) {
    323      checkInvalidKeyException(ex, i, "cmp(key, 1)");
    324    }
    325    try {
    326      indexedDB.cmp(1, key);
    327      ok(false, "didn't throw2");
    328    } catch (ex) {
    329      checkInvalidKeyException(ex, i, "cmp(1, key)");
    330    }
    331    try {
    332      store.put(1, key);
    333      ok(false, "didn't throw3");
    334    } catch (ex) {
    335      checkInvalidKeyException(ex, i, "store.put(1, key)");
    336    }
    337  }
    338 
    339  openRequest.onsuccess = grabEventAndContinueHandler;
    340  yield undefined;
    341 
    342  finishTest();
    343 }