tor-browser

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

support.js (7832B)


      1 'use strict';
      2 /* Delete created databases
      3 *
      4 * Go through each finished test, see if it has an associated database. Close
      5 * that and delete the database. */
      6 add_completion_callback(function(tests)
      7 {
      8    for (var i in tests)
      9    {
     10        if(tests[i].db)
     11        {
     12            tests[i].db.close();
     13            self.indexedDB.deleteDatabase(tests[i].db.name);
     14        }
     15    }
     16 });
     17 
     18 function fail(test, desc) {
     19    return test.step_func(function(e) {
     20        if (e && e.message && e.target.error)
     21            assert_unreached(desc + " (" + e.target.error.name + ": " + e.message + ")");
     22        else if (e && e.message)
     23            assert_unreached(desc + " (" + e.message + ")");
     24        else if (e && e.target.readyState === 'done' && e.target.error)
     25            assert_unreached(desc + " (" + e.target.error.name + ")");
     26        else
     27            assert_unreached(desc);
     28    });
     29 }
     30 
     31 function createdb(test, dbname, version)
     32 {
     33    var rq_open = createdb_for_multiple_tests(dbname, version);
     34    return rq_open.setTest(test);
     35 }
     36 
     37 function createdb_for_multiple_tests(dbname, version) {
     38    var rq_open,
     39        fake_open = {},
     40        test = null,
     41        dbname = (dbname ? dbname : "testdb-" + new Date().getTime() + Math.random() );
     42 
     43    if (version)
     44        rq_open = self.indexedDB.open(dbname, version);
     45    else
     46        rq_open = self.indexedDB.open(dbname);
     47 
     48    function auto_fail(evt, current_test) {
     49        /* Fail handlers, if we haven't set on/whatever/, don't
     50         * expect to get event whatever. */
     51        rq_open.manually_handled = {};
     52 
     53        rq_open.addEventListener(evt, function(e) {
     54            if (current_test !== test) {
     55                return;
     56            }
     57 
     58            test.step(function() {
     59                if (!rq_open.manually_handled[evt]) {
     60                    assert_unreached("unexpected open." + evt + " event");
     61                }
     62 
     63                if (e.target.result + '' == '[object IDBDatabase]' &&
     64                    !this.db) {
     65                  this.db = e.target.result;
     66 
     67                  this.db.onerror = fail(test, 'unexpected db.error');
     68                  this.db.onabort = fail(test, 'unexpected db.abort');
     69                  this.db.onversionchange =
     70                      fail(test, 'unexpected db.versionchange');
     71                }
     72            });
     73        });
     74        rq_open.__defineSetter__("on" + evt, function(h) {
     75            rq_open.manually_handled[evt] = true;
     76            if (!h)
     77                rq_open.addEventListener(evt, function() {});
     78            else
     79                rq_open.addEventListener(evt, test.step_func(h));
     80        });
     81    }
     82 
     83    // add a .setTest method to the IDBOpenDBRequest object
     84    Object.defineProperty(rq_open, 'setTest', {
     85        enumerable: false,
     86        value: function(t) {
     87            test = t;
     88 
     89            auto_fail("upgradeneeded", test);
     90            auto_fail("success", test);
     91            auto_fail("blocked", test);
     92            auto_fail("error", test);
     93 
     94            return this;
     95        }
     96    });
     97 
     98    return rq_open;
     99 }
    100 
    101 function assert_key_equals(actual, expected, description) {
    102  assert_equals(indexedDB.cmp(actual, expected), 0, description);
    103 }
    104 
    105 // Usage:
    106 //   indexeddb_test(
    107 //     (test_object, db_connection, upgrade_tx, open_request) => {
    108 //        // Database creation logic.
    109 //     },
    110 //     (test_object, db_connection, open_request) => {
    111 //        // Test logic.
    112 //        test_object.done();
    113 //     },
    114 //     'Test case description');
    115 function indexeddb_test(upgrade_func, open_func, description, options) {
    116  async_test(function(t) {
    117    options = Object.assign({upgrade_will_abort: false}, options);
    118    var dbname = location + '-' + t.name;
    119    var del = indexedDB.deleteDatabase(dbname);
    120    del.onerror = t.unreached_func('deleteDatabase should succeed');
    121    var open = indexedDB.open(dbname, 1);
    122    open.onupgradeneeded = t.step_func(function() {
    123      var db = open.result;
    124      t.add_cleanup(function() {
    125        // If open didn't succeed already, ignore the error.
    126        open.onerror = function(e) {
    127          e.preventDefault();
    128        };
    129        db.close();
    130        indexedDB.deleteDatabase(db.name);
    131      });
    132      var tx = open.transaction;
    133      upgrade_func(t, db, tx, open);
    134    });
    135    if (options.upgrade_will_abort) {
    136      open.onsuccess = t.unreached_func('open should not succeed');
    137    } else {
    138      open.onerror = t.unreached_func('open should succeed');
    139      open.onsuccess = t.step_func(function() {
    140        var db = open.result;
    141        if (open_func)
    142          open_func(t, db, open);
    143      });
    144    }
    145  }, description);
    146 }
    147 
    148 // Call with a Test and an array of expected results in order. Returns
    149 // a function; call the function when a result arrives and when the
    150 // expected number appear the order will be asserted and test
    151 // completed.
    152 function expect(t, expected) {
    153  var results = [];
    154  return result => {
    155    results.push(result);
    156    if (results.length === expected.length) {
    157      assert_array_equals(results, expected);
    158      t.done();
    159    }
    160  };
    161 }
    162 
    163 // Checks to see if the passed transaction is active (by making
    164 // requests against the named store).
    165 function is_transaction_active(tx, store_name) {
    166  try {
    167    const request = tx.objectStore(store_name).get(0);
    168    request.onerror = e => {
    169      e.preventDefault();
    170      e.stopPropagation();
    171    };
    172    return true;
    173  } catch (ex) {
    174    assert_equals(ex.name, 'TransactionInactiveError',
    175                  'Active check should either not throw anything, or throw ' +
    176                  'TransactionInactiveError');
    177    return false;
    178  }
    179 }
    180 
    181 // Keeps the passed transaction alive indefinitely (by making requests
    182 // against the named store). Returns a function that asserts that the
    183 // transaction has not already completed and then ends the request loop so that
    184 // the transaction may autocommit and complete.
    185 function keep_alive(tx, store_name) {
    186  let completed = false;
    187  tx.addEventListener('complete', () => { completed = true; });
    188 
    189  let keepSpinning = true;
    190 
    191  function spin() {
    192    if (!keepSpinning)
    193      return;
    194    tx.objectStore(store_name).get(0).onsuccess = spin;
    195  }
    196  spin();
    197 
    198  return () => {
    199    assert_false(completed, 'Transaction completed while kept alive');
    200    keepSpinning = false;
    201  };
    202 }
    203 
    204 // Returns a new function. After it is called |count| times, |func|
    205 // will be called.
    206 function barrier_func(count, func) {
    207  let n = 0;
    208  return () => {
    209    if (++n === count)
    210      func();
    211  };
    212 }
    213 
    214 // Create an IndexedDB by executing script on the given remote context
    215 // with |dbName| and |version|.
    216 async function createIndexedDBForTesting(rc, dbName, version) {
    217  await rc.executeScript((dbName, version) => {
    218    let request = indexedDB.open(dbName, version);
    219    request.onupgradeneeded = () => {
    220      if (version == 1) {
    221        // Only create the object store once.
    222        request.result.createObjectStore('store');
    223      }
    224    }
    225    request.onversionchange = () => {
    226      fail(t, 'unexpectedly received versionchange event.');
    227    }
    228  }, [dbName, version]);
    229 }
    230 
    231 // Create an IndexedDB by executing script on the given remote context
    232 // with |dbName| and |version|, and wait for the reuslt.
    233 async function waitUntilIndexedDBOpenForTesting(rc, dbName, version) {
    234  await rc.executeScript(async (dbName, version) => {
    235    await new Promise((resolve, reject) => {
    236        let request = indexedDB.open(dbName, version);
    237        request.onsuccess = resolve;
    238        request.onerror = reject;
    239    });
    240  }, [dbName, version]);
    241 }
    242 
    243 // Returns a detached ArrayBuffer by transferring it to a message port.
    244 function createDetachedArrayBuffer() {
    245  const array = new Uint8Array([1, 2, 3, 4]);
    246  const buffer = array.buffer;
    247  assert_equals(array.byteLength, 4);
    248 
    249  const channel = new MessageChannel();
    250  channel.port1.postMessage('', [buffer]);
    251  assert_equals(array.byteLength, 0);
    252  return array;
    253 }