240 lines
7.3 KiB
JavaScript
240 lines
7.3 KiB
JavaScript
/* Delete created databases
|
|
*
|
|
* Go through each finished test, see if it has an associated database. Close
|
|
* that and delete the database. */
|
|
add_completion_callback(function(tests)
|
|
{
|
|
for (var i in tests)
|
|
{
|
|
if(tests[i].db)
|
|
{
|
|
tests[i].db.close();
|
|
self.indexedDB.deleteDatabase(tests[i].db.name);
|
|
}
|
|
}
|
|
});
|
|
|
|
function fail(test, desc) {
|
|
return test.step_func(function(e) {
|
|
if (e && e.message && e.target.error)
|
|
assert_unreached(desc + " (" + e.target.error.name + ": " + e.message + ")");
|
|
else if (e && e.message)
|
|
assert_unreached(desc + " (" + e.message + ")");
|
|
else if (e && e.target.readyState === 'done' && e.target.error)
|
|
assert_unreached(desc + " (" + e.target.error.name + ")");
|
|
else
|
|
assert_unreached(desc);
|
|
});
|
|
}
|
|
|
|
function createdb(test, dbname, version)
|
|
{
|
|
var rq_open = createdb_for_multiple_tests(dbname, version);
|
|
return rq_open.setTest(test);
|
|
}
|
|
|
|
function createdb_for_multiple_tests(dbname, version) {
|
|
var rq_open,
|
|
fake_open = {},
|
|
test = null,
|
|
dbname = (dbname ? dbname : "testdb-" + new Date().getTime() + Math.random() );
|
|
|
|
if (version)
|
|
rq_open = self.indexedDB.open(dbname, version);
|
|
else
|
|
rq_open = self.indexedDB.open(dbname);
|
|
|
|
function auto_fail(evt, current_test) {
|
|
/* Fail handlers, if we haven't set on/whatever/, don't
|
|
* expect to get event whatever. */
|
|
rq_open.manually_handled = {};
|
|
|
|
rq_open.addEventListener(evt, function(e) {
|
|
if (current_test !== test) {
|
|
return;
|
|
}
|
|
|
|
test.step(function() {
|
|
if (!rq_open.manually_handled[evt]) {
|
|
assert_unreached("unexpected open." + evt + " event");
|
|
}
|
|
|
|
if (e.target.result + '' == '[object IDBDatabase]' &&
|
|
!this.db) {
|
|
this.db = e.target.result;
|
|
|
|
this.db.onerror = fail(test, 'unexpected db.error');
|
|
this.db.onabort = fail(test, 'unexpected db.abort');
|
|
this.db.onversionchange =
|
|
fail(test, 'unexpected db.versionchange');
|
|
}
|
|
});
|
|
});
|
|
rq_open.__defineSetter__("on" + evt, function(h) {
|
|
rq_open.manually_handled[evt] = true;
|
|
if (!h)
|
|
rq_open.addEventListener(evt, function() {});
|
|
else
|
|
rq_open.addEventListener(evt, test.step_func(h));
|
|
});
|
|
}
|
|
|
|
// add a .setTest method to the IDBOpenDBRequest object
|
|
Object.defineProperty(rq_open, 'setTest', {
|
|
enumerable: false,
|
|
value: function(t) {
|
|
test = t;
|
|
|
|
auto_fail("upgradeneeded", test);
|
|
auto_fail("success", test);
|
|
auto_fail("blocked", test);
|
|
auto_fail("error", test);
|
|
|
|
return this;
|
|
}
|
|
});
|
|
|
|
return rq_open;
|
|
}
|
|
|
|
function assert_key_equals(actual, expected, description) {
|
|
assert_equals(indexedDB.cmp(actual, expected), 0, description);
|
|
}
|
|
|
|
// Usage:
|
|
// indexeddb_test(
|
|
// (test_object, db_connection, upgrade_tx, open_request) => {
|
|
// // Database creation logic.
|
|
// },
|
|
// (test_object, db_connection, open_request) => {
|
|
// // Test logic.
|
|
// test_object.done();
|
|
// },
|
|
// 'Test case description');
|
|
function indexeddb_test(upgrade_func, open_func, description, options) {
|
|
async_test(function(t) {
|
|
options = Object.assign({upgrade_will_abort: false}, options);
|
|
var dbname = location + '-' + t.name;
|
|
var del = indexedDB.deleteDatabase(dbname);
|
|
del.onerror = t.unreached_func('deleteDatabase should succeed');
|
|
var open = indexedDB.open(dbname, 1);
|
|
open.onupgradeneeded = t.step_func(function() {
|
|
var db = open.result;
|
|
t.add_cleanup(function() {
|
|
// If open didn't succeed already, ignore the error.
|
|
open.onerror = function(e) {
|
|
e.preventDefault();
|
|
};
|
|
db.close();
|
|
indexedDB.deleteDatabase(db.name);
|
|
});
|
|
var tx = open.transaction;
|
|
upgrade_func(t, db, tx, open);
|
|
});
|
|
if (options.upgrade_will_abort) {
|
|
open.onsuccess = t.unreached_func('open should not succeed');
|
|
} else {
|
|
open.onerror = t.unreached_func('open should succeed');
|
|
open.onsuccess = t.step_func(function() {
|
|
var db = open.result;
|
|
if (open_func)
|
|
open_func(t, db, open);
|
|
});
|
|
}
|
|
}, description);
|
|
}
|
|
|
|
// Call with a Test and an array of expected results in order. Returns
|
|
// a function; call the function when a result arrives and when the
|
|
// expected number appear the order will be asserted and test
|
|
// completed.
|
|
function expect(t, expected) {
|
|
var results = [];
|
|
return result => {
|
|
results.push(result);
|
|
if (results.length === expected.length) {
|
|
assert_array_equals(results, expected);
|
|
t.done();
|
|
}
|
|
};
|
|
}
|
|
|
|
// Checks to see if the passed transaction is active (by making
|
|
// requests against the named store).
|
|
function is_transaction_active(tx, store_name) {
|
|
try {
|
|
const request = tx.objectStore(store_name).get(0);
|
|
request.onerror = e => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
};
|
|
return true;
|
|
} catch (ex) {
|
|
assert_equals(ex.name, 'TransactionInactiveError',
|
|
'Active check should either not throw anything, or throw ' +
|
|
'TransactionInactiveError');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Keeps the passed transaction alive indefinitely (by making requests
|
|
// against the named store). Returns a function that asserts that the
|
|
// transaction has not already completed and then ends the request loop so that
|
|
// the transaction may autocommit and complete.
|
|
function keep_alive(tx, store_name) {
|
|
let completed = false;
|
|
tx.addEventListener('complete', () => { completed = true; });
|
|
|
|
let keepSpinning = true;
|
|
|
|
function spin() {
|
|
if (!keepSpinning)
|
|
return;
|
|
tx.objectStore(store_name).get(0).onsuccess = spin;
|
|
}
|
|
spin();
|
|
|
|
return () => {
|
|
assert_false(completed, 'Transaction completed while kept alive');
|
|
keepSpinning = false;
|
|
};
|
|
}
|
|
|
|
// Returns a new function. After it is called |count| times, |func|
|
|
// will be called.
|
|
function barrier_func(count, func) {
|
|
let n = 0;
|
|
return () => {
|
|
if (++n === count)
|
|
func();
|
|
};
|
|
}
|
|
|
|
// Create an IndexedDB by executing script on the given remote context
|
|
// with |dbName| and |version|.
|
|
async function createIndexedDBForTesting(rc, dbName, version) {
|
|
await rc.executeScript((dbName, version) => {
|
|
let request = indexedDB.open(dbName, version);
|
|
request.onupgradeneeded = () => {
|
|
if (version == 1) {
|
|
// Only create the object store once.
|
|
request.result.createObjectStore('store');
|
|
}
|
|
}
|
|
request.onversionchange = () => {
|
|
fail(t, 'unexpectedly received versionchange event.');
|
|
}
|
|
}, [dbName, version]);
|
|
}
|
|
|
|
// Create an IndexedDB by executing script on the given remote context
|
|
// with |dbName| and |version|, and wait for the reuslt.
|
|
async function waitUntilIndexedDBOpenForTesting(rc, dbName, version) {
|
|
await rc.executeScript(async (dbName, version) => {
|
|
await new Promise((resolve, reject) => {
|
|
let request = indexedDB.open(dbName, version);
|
|
request.onsuccess = resolve;
|
|
request.onerror = reject;
|
|
});
|
|
}, [dbName, version]);
|
|
}
|