tor-browser

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

name-scopes.any.js (5053B)


      1 // META: title=IndexedDB: scoping for database / object store / index names, and index keys
      2 // META: global=window,worker
      3 // META: script=resources/support-promises.js
      4 
      5 // Spec: https://w3c.github.io/IndexedDB/#constructs
      6 
      7 'use strict';
      8 
      9 // Creates the structure inside a test database.
     10 //
     11 // The structure includes two stores with identical indexes and nearly-similar
     12 // records. The records differ in the "path" attribute values, which are used to
     13 // verify that IndexedDB returns the correct records when queried.
     14 //
     15 // databaseName appears redundant, but we don't want to rely on database.name.
     16 const buildStores = (database, databaseName, useUniqueKeys) => {
     17  for (let storeName of ['x', 'y']) {
     18    const store = database.createObjectStore(
     19        storeName, {keyPath: 'pKey', autoIncrement: true});
     20    for (let indexName of ['x', 'y']) {
     21      store.createIndex(indexName, `${indexName}Key`, {unique: useUniqueKeys});
     22    }
     23 
     24    for (let xKeyRoot of ['x', 'y']) {
     25      for (let yKeyRoot of ['x', 'y']) {
     26        let xKey, yKey;
     27        if (useUniqueKeys) {
     28          xKey = `${xKeyRoot}${yKeyRoot}`;
     29          yKey = `${yKeyRoot}${xKeyRoot}`;
     30        } else {
     31          xKey = xKeyRoot;
     32          yKey = yKeyRoot;
     33        }
     34        const path = `${databaseName}-${storeName}-${xKeyRoot}-${yKeyRoot}`;
     35        store.put({xKey: xKey, yKey: yKey, path: path});
     36      }
     37    }
     38  }
     39 };
     40 
     41 // Creates two databases with identical structures.
     42 const buildDatabases = (testCase, useUniqueKeys) => {
     43  return createNamedDatabase(
     44             testCase, 'x',
     45             database => buildStores(database, 'x', useUniqueKeys))
     46      .then(database => database.close())
     47      .then(
     48          () => createNamedDatabase(
     49              testCase, 'y',
     50              database => buildStores(database, 'y', useUniqueKeys)))
     51      .then(database => database.close());
     52 };
     53 
     54 // Reads all the store's values using an index.
     55 //
     56 // Returns a Promise that resolves with an array of values.
     57 const readIndex =
     58    (testCase, index) => {
     59      return new Promise((resolve, reject) => {
     60        const results = [];
     61        const request = index.openCursor(IDBKeyRange.bound('a', 'z'), 'next');
     62        request.onsuccess = testCase.step_func(() => {
     63          const cursor = request.result;
     64          if (cursor) {
     65            results.push(cursor.value);
     66            cursor.continue();
     67          } else {
     68            resolve(results);
     69          }
     70        });
     71      });
     72    }
     73 
     74 // Verifies that a database contains the expected records.
     75 const checkDatabaseContent =
     76    (testCase, database, databaseName, usedUniqueKeys) => {
     77      const promises = [];
     78      const transaction = database.transaction(['x', 'y'], 'readonly');
     79      for (let storeName of ['x', 'y']) {
     80        const store = transaction.objectStore(storeName);
     81        for (let indexName of ['x', 'y']) {
     82          const index = store.index(indexName);
     83 
     84          const promise = readIndex(testCase, index).then((results) => {
     85            assert_array_equals(
     86                results.map(result => `${result.path}:${result.pKey}`).sort(),
     87                [
     88                  `${databaseName}-${storeName}-x-x:1`,
     89                  `${databaseName}-${storeName}-x-y:2`,
     90                  `${databaseName}-${storeName}-y-x:3`,
     91                  `${databaseName}-${storeName}-y-y:4`
     92                ],
     93                'The results should include all records put into the store');
     94 
     95            let expectedKeys = (usedUniqueKeys) ?
     96                ['xx:xx', 'xy:yx', 'yx:xy', 'yy:yy'] :
     97                ['x:x', 'x:y', 'y:x', 'y:y'];
     98            assert_array_equals(
     99                results.map(result => `${result.xKey}:${result.yKey}`).sort(),
    100                expectedKeys,
    101                'The results should include all the index keys put in the store');
    102 
    103            assert_array_equals(
    104                results.map(result => result[`${indexName}Key`]),
    105                results.map(result => result[`${indexName}Key`]).sort(),
    106                'The results should be sorted by the index key');
    107          });
    108          promises.push(promise);
    109        }
    110      }
    111 
    112      return Promise.all(promises).then(() => database);
    113    }
    114 
    115 promise_test(testCase => {
    116  return buildDatabases(testCase, false)
    117      .then(() => openNamedDatabase(testCase, 'x', 1))
    118      .then(database => checkDatabaseContent(testCase, database, 'x', false))
    119      .then(database => database.close())
    120      .then(() => openNamedDatabase(testCase, 'y', 1))
    121      .then(database => checkDatabaseContent(testCase, database, 'y', false))
    122      .then(database => database.close());
    123 }, 'Non-unique index keys');
    124 
    125 promise_test(testCase => {
    126  return buildDatabases(testCase, true)
    127      .then(() => openNamedDatabase(testCase, 'x', 1))
    128      .then(database => checkDatabaseContent(testCase, database, 'x', true))
    129      .then(database => database.close())
    130      .then(() => openNamedDatabase(testCase, 'y', 1))
    131      .then(database => checkDatabaseContent(testCase, database, 'y', true))
    132      .then(database => database.close());
    133 }, 'Unique index keys');