tor-browser

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

test_clear_object_store_with_indexes.js (5820B)


      1 /**
      2 * Any copyright is dedicated to the Public Domain.
      3 * http://creativecommons.org/publicdomain/zero/1.0/
      4 */
      5 
      6 // Reduce the amount of data on slow platforms.
      7 const getDataBlockSize = () => {
      8  if (mozinfo.os == "android") {
      9    // Android is much slower than desktop.
     10    if (mozinfo.verify) {
     11      return 54; // Chaos mode on android
     12    }
     13 
     14    return 3333;
     15  }
     16 
     17  if (isInChaosMode()) {
     18    return 333;
     19  }
     20 
     21  return 33333;
     22 };
     23 
     24 /* exported testSteps */
     25 async function testSteps() {
     26  const name = this.window ? window.location.pathname : "Splendid Test";
     27  const request = indexedDB.open(name, 1);
     28 
     29  (ev => {
     30    const os = ev.target.result.createObjectStore("testObjectStore", {
     31      keyPath: "id",
     32      autoIncrement: false,
     33    });
     34 
     35    os.createIndex("testObjectStoreIndexA", "indexA", { unique: true });
     36    os.createIndex("testObjectStoreIndexB", "indexB", { unique: false });
     37    os.createIndex("testObjectStoreIndexC", "indexC", { unique: false });
     38  })(await expectingUpgrade(request));
     39 
     40  const db = (await expectingSuccess(request)).target.result;
     41 
     42  const objectStore = db
     43    .transaction(["testObjectStore"], "readwrite")
     44    .objectStore("testObjectStore");
     45 
     46  const dataBlock = getDataBlockSize();
     47  const lastIndex = 3 * dataBlock;
     48 
     49  info("We will now add " + lastIndex + " blobs to our object store");
     50 
     51  const addSegment = async (from, dataValue) => {
     52    for (let i = from; i <= from + dataBlock - 1; ++i) {
     53      await objectStore.add({
     54        id: i,
     55        indexA: i,
     56        indexB: lastIndex + 1 - i,
     57        indexC: i % 3,
     58        value: dataValue,
     59      });
     60    }
     61  };
     62 
     63  const expectedBegin = getRandomView(512);
     64  const expectedMiddle = getRandomView(512);
     65  const expectedEnd = getRandomView(512);
     66  ok(
     67    !compareBuffers(expectedBegin, expectedMiddle),
     68    "Are all buffers different?"
     69  );
     70  ok(!compareBuffers(expectedBegin, expectedEnd), "Are all buffers different?");
     71  ok(
     72    !compareBuffers(expectedMiddle, expectedEnd),
     73    "Are all buffers different?"
     74  );
     75 
     76  const dataValueBegin = getBlob(expectedBegin);
     77  await addSegment(1, dataValueBegin);
     78 
     79  const dataValueMiddle = getBlob(expectedMiddle);
     80  await addSegment(dataBlock + 1, dataValueMiddle);
     81 
     82  const dataValueEnd = getBlob(expectedEnd);
     83  await addSegment(2 * dataBlock + 1, dataValueEnd);
     84 
     85  // Performance issue of 1860486 occurs here
     86  await new Promise((res, rej) => {
     87    let isDone = false;
     88    const deleteReq = objectStore.delete(
     89      IDBKeyRange.bound(6, lastIndex - 5, false, false)
     90    );
     91    deleteReq.onsuccess = () => {
     92      isDone = true;
     93      res();
     94    };
     95    deleteReq.onerror = err => {
     96      isDone = true;
     97      rej(err);
     98    };
     99 
    100    /**
    101     * The deletion should be over in 20 seconds or less on desktop. With the
    102     * regression, the operation can take more than 30 minutes. We use one
    103     * minute to reduce intermittent failures due to the CI environment.
    104     *
    105     * Note that this is not a magical timeout for the completion of an
    106     * asynchronous request: we are testing a hang and using an explicit timeout
    107     * will avoid the much longer default timeout which is way too long to be
    108     * acceptable in real use cases.
    109     *
    110     * Maintenance plan: If disk contention and slow hardware lead to too many
    111     * intermittent failures, the regression cutoff could be increased to 2-3
    112     * minutes or the test could be turned into a raptor performance test.
    113     */
    114    const minutes = 60 * 1000;
    115    const performance_regression_cutoff = 1 * minutes;
    116    do_timeout(performance_regression_cutoff, () => {
    117      if (!isDone) {
    118        rej(Error("Performance regression detected"));
    119      }
    120    });
    121  });
    122 
    123  const getIndexedItems = async indexName => {
    124    let actuals = [];
    125    return new Promise(res => {
    126      db
    127        .transaction(["testObjectStore"], "readonly")
    128        .objectStore("testObjectStore")
    129        .index(indexName)
    130        .openCursor().onsuccess = ev => {
    131        const cursor = ev.target.result;
    132        if (!cursor) {
    133          res(actuals);
    134        } else {
    135          actuals.push(cursor.value.value);
    136          cursor.continue();
    137        }
    138      };
    139    });
    140  };
    141 
    142  const checkValuesEqualTo = async (actuals, from, to, expected) => {
    143    for (let i = from; i < to; ++i) {
    144      const actual = new Uint8Array(await actuals[i].arrayBuffer());
    145      if (!compareBuffers(actual, expected)) {
    146        return i;
    147      }
    148    }
    149    return undefined;
    150  };
    151 
    152  const itemsA = await getIndexedItems("testObjectStoreIndexA");
    153  equal(itemsA.length, 10);
    154 
    155  const mismatchABegin = await checkValuesEqualTo(itemsA, 0, 5, expectedBegin);
    156  equal(
    157    mismatchABegin,
    158    undefined,
    159    "First index with value mismatch is " + mismatchABegin
    160  );
    161  const mismatchAEnd = await checkValuesEqualTo(itemsA, 5, 10, expectedEnd);
    162  equal(
    163    mismatchAEnd,
    164    undefined,
    165    "First index with value mismatch is " + mismatchAEnd
    166  );
    167 
    168  const itemsB = await getIndexedItems("testObjectStoreIndexB");
    169 
    170  equal(itemsB.length, 10);
    171  const mismatchBEnd = await checkValuesEqualTo(itemsB, 0, 5, expectedEnd);
    172  equal(
    173    mismatchBEnd,
    174    undefined,
    175    "First index with value mismatch is " + mismatchBEnd
    176  );
    177  const mismatchBBegin = await checkValuesEqualTo(itemsB, 5, 10, expectedBegin);
    178  equal(
    179    mismatchBBegin,
    180    undefined,
    181    "First index with value mismatch is " + mismatchBBegin
    182  );
    183 
    184  const actualsC = await getIndexedItems("testObjectStoreIndexC");
    185 
    186  equal(actualsC.length, 10);
    187  let countBegin = 0;
    188  let countEnd = 0;
    189  for (let i = 0; i < 10; ++i) {
    190    const actual = new Uint8Array(await actualsC[i].arrayBuffer());
    191    if (compareBuffers(actual, expectedBegin)) {
    192      ++countBegin;
    193    } else if (compareBuffers(actual, expectedEnd)) {
    194      ++countEnd;
    195    }
    196  }
    197 
    198  equal(countBegin, 5);
    199  equal(countEnd, 5);
    200 
    201  await db.close();
    202 }