mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
LibWeb: Implement IDBFactory::cmp
This commit is contained in:
parent
c43b93e6fa
commit
331f26a88b
Notes:
github-actions[bot]
2024-11-25 10:54:47 +00:00
Author: https://github.com/stelar7 Commit: https://github.com/LadybirdBrowser/ladybird/commit/331f26a88bb Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2279 Reviewed-by: https://github.com/gmta Reviewed-by: https://github.com/tcl3
14 changed files with 655 additions and 1 deletions
|
@ -13,6 +13,7 @@
|
|||
#include <LibWeb/IndexedDB/IDBDatabase.h>
|
||||
#include <LibWeb/IndexedDB/IDBFactory.h>
|
||||
#include <LibWeb/IndexedDB/Internal/Algorithms.h>
|
||||
#include <LibWeb/IndexedDB/Internal/Key.h>
|
||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||
#include <LibWeb/StorageAPI/StorageKey.h>
|
||||
|
||||
|
@ -93,4 +94,25 @@ WebIDL::ExceptionOr<GC::Ref<IDBOpenDBRequest>> IDBFactory::open(String const& na
|
|||
return request;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/IndexedDB/#dom-idbfactory-cmp
|
||||
WebIDL::ExceptionOr<i8> IDBFactory::cmp(JS::Value first, JS::Value second)
|
||||
{
|
||||
// 1. Let a be the result of converting a value to a key with first. Rethrow any exceptions.
|
||||
auto a = convert_a_value_to_a_key(realm(), first);
|
||||
|
||||
// 2. If a is invalid, throw a "DataError" DOMException.
|
||||
if (a.is_error())
|
||||
return WebIDL::DataError::create(realm(), "Failed to convert a value to a key"_string);
|
||||
|
||||
// 3. Let b be the result of converting a value to a key with second. Rethrow any exceptions.
|
||||
auto b = convert_a_value_to_a_key(realm(), second);
|
||||
|
||||
// 4. If b is invalid, throw a "DataError" DOMException.
|
||||
if (b.is_error())
|
||||
return WebIDL::DataError::create(realm(), "Failed to convert a value to a key"_string);
|
||||
|
||||
// 5. Return the results of comparing two keys with a and b.
|
||||
return Key::compare_two_keys(a.release_value(), b.release_value());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
virtual ~IDBFactory() override;
|
||||
|
||||
WebIDL::ExceptionOr<GC::Ref<IDBOpenDBRequest>> open(String const& name, Optional<u64> version);
|
||||
WebIDL::ExceptionOr<i8> cmp(JS::Value first, JS::Value second);
|
||||
|
||||
protected:
|
||||
explicit IDBFactory(JS::Realm&);
|
||||
|
|
|
@ -6,7 +6,7 @@ interface IDBFactory {
|
|||
|
||||
[FIXME] Promise<sequence<IDBDatabaseInfo>> databases();
|
||||
|
||||
[FIXME] short cmp(any first, any second);
|
||||
short cmp(any first, any second);
|
||||
};
|
||||
|
||||
dictionary IDBDatabaseInfo {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
Summary
|
||||
|
||||
Harness status: OK
|
||||
|
||||
Rerun
|
||||
|
||||
Found 1 tests
|
||||
|
||||
1 Pass
|
||||
Details
|
||||
Result Test Name MessagePass IDBFactory.cmp()
|
|
@ -0,0 +1,13 @@
|
|||
Summary
|
||||
|
||||
Harness status: OK
|
||||
|
||||
Rerun
|
||||
|
||||
Found 3 tests
|
||||
|
||||
3 Pass
|
||||
Details
|
||||
Result Test Name MessagePass IDBFactory.cmp() - no argument
|
||||
Pass IDBFactory.cmp() - null
|
||||
Pass IDBFactory.cmp() - NaN
|
|
@ -0,0 +1,14 @@
|
|||
Summary
|
||||
|
||||
Harness status: OK
|
||||
|
||||
Rerun
|
||||
|
||||
Found 4 tests
|
||||
|
||||
4 Pass
|
||||
Details
|
||||
Result Test Name MessagePass Array v.s. Binary
|
||||
Pass Binary v.s. String
|
||||
Pass String v.s. Date
|
||||
Pass Date v.s. Number
|
|
@ -0,0 +1,14 @@
|
|||
Summary
|
||||
|
||||
Harness status: OK
|
||||
|
||||
Rerun
|
||||
|
||||
Found 4 tests
|
||||
|
||||
4 Pass
|
||||
Details
|
||||
Result Test Name MessagePass Compare in unsigned octet values (in the range [0, 255])
|
||||
Pass Compare values in then same length
|
||||
Pass Compare values in different lengths
|
||||
Pass Compare when the values in the range of their minimal length are the same
|
35
Tests/LibWeb/Text/expected/wpt-import/IndexedDB/keyorder.txt
Normal file
35
Tests/LibWeb/Text/expected/wpt-import/IndexedDB/keyorder.txt
Normal file
|
@ -0,0 +1,35 @@
|
|||
Summary
|
||||
|
||||
Harness status: OK
|
||||
|
||||
Rerun
|
||||
|
||||
Found 24 tests
|
||||
|
||||
12 Pass
|
||||
12 Fail
|
||||
Details
|
||||
Result Test Name MessageFail Database readback sort - String < Array Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - String < Array
|
||||
Fail Database readback sort - float < String Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - float < String
|
||||
Fail Database readback sort - float < Date Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - float < Date
|
||||
Fail Database readback sort - float < Date < String < Array Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - float < Date < String < Array
|
||||
Fail Database readback sort - Date(1 sec ago) < Date(now) < Date(1 minute in future) Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - Date(1 sec ago) < Date(now) < Date(1 minute in future)
|
||||
Fail Database readback sort - -1.1 < 1 < 1.01337 < 1.013373 < 2 Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - -1.1 < 1 < 1.01337 < 1.013373 < 2
|
||||
Fail Database readback sort - -Infinity < -0.01 < 0 < Infinity Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - -Infinity < -0.01 < 0 < Infinity
|
||||
Fail Database readback sort - "" < "a" < "ab" < "b" < "ba" Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - "" < "a" < "ab" < "b" < "ba"
|
||||
Fail Database readback sort - Arrays Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - Arrays
|
||||
Fail Database readback sort - Array.length: 10,000 < Array.length: 10,001 Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - Array.length: 10,000 < Array.length: 10,001
|
||||
Fail Database readback sort - Infinity inside arrays Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - Infinity inside arrays
|
||||
Fail Database readback sort - Test different stuff at once Cannot access property "transaction" on undefined object "db"
|
||||
Pass IDBKey.cmp sorted - Test different stuff at once
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>IDBFactory.cmp() - compared keys return correct value</title>
|
||||
<link rel="author" title="Microsoft" href="http://www.microsoft.com">
|
||||
<script src=../resources/testharness.js></script>
|
||||
<script src=../resources/testharnessreport.js></script>
|
||||
<script src=resources/support.js></script>
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
var greater = window.indexedDB.cmp(2, 1);
|
||||
var equal = window.indexedDB.cmp(2, 2);
|
||||
var less = window.indexedDB.cmp(1, 2);
|
||||
|
||||
assert_equals(greater, 1, "greater");
|
||||
assert_equals(equal, 0, "equal");
|
||||
assert_equals(less, -1, "less");
|
||||
}, "IDBFactory.cmp()");
|
||||
</script>
|
||||
|
||||
<div id=log></div>
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>IDBFactory.cmp() - invalid key</title>
|
||||
<link rel="author" title="Intel" href="http://www.intel.com">
|
||||
<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBFactory-cmp-short-any-first-any-second">
|
||||
<script src=../resources/testharness.js></script>
|
||||
<script src=../resources/testharnessreport.js></script>
|
||||
<script src=resources/support.js></script>
|
||||
<div id=log></div>
|
||||
<script>
|
||||
test( function() {
|
||||
assert_throws_js(TypeError, function() {
|
||||
indexedDB.cmp();
|
||||
});
|
||||
}, "IDBFactory.cmp() - no argument");
|
||||
|
||||
test( function() {
|
||||
assert_throws_dom("DataError", function() {
|
||||
indexedDB.cmp(null, null);
|
||||
});
|
||||
assert_throws_dom("DataError", function() {
|
||||
indexedDB.cmp(1, null);
|
||||
});
|
||||
assert_throws_dom("DataError", function() {
|
||||
indexedDB.cmp(null, 1);
|
||||
});
|
||||
}, "IDBFactory.cmp() - null");
|
||||
|
||||
test( function() {
|
||||
assert_throws_dom("DataError", function() {
|
||||
indexedDB.cmp(NaN, NaN);
|
||||
});
|
||||
assert_throws_dom("DataError", function() {
|
||||
indexedDB.cmp(1, NaN);
|
||||
});
|
||||
assert_throws_dom("DataError", function() {
|
||||
indexedDB.cmp(NaN, 1);
|
||||
});
|
||||
}, "IDBFactory.cmp() - NaN");
|
||||
</script>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>IDBFactory.cmp() - compared keys in different types</title>
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||
<link rel="help" href="http://w3c.github.io/IndexedDB/#key-construct">
|
||||
<script src=../resources/testharness.js></script>
|
||||
<script src=../resources/testharnessreport.js></script>
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
assert_equals(indexedDB.cmp([0], new Uint8Array([0])), 1, "Array > Binary");
|
||||
}, "Array v.s. Binary");
|
||||
|
||||
test(function() {
|
||||
assert_equals(indexedDB.cmp(new Uint8Array([0]), "0"), 1, "Binary > String");
|
||||
}, "Binary v.s. String");
|
||||
|
||||
test(function() {
|
||||
assert_equals(indexedDB.cmp("", new Date(0)), 1, "String > Date");
|
||||
}, "String v.s. Date");
|
||||
|
||||
test(function() {
|
||||
assert_equals(indexedDB.cmp(new Date(0), 0), 1, "Date > Number");
|
||||
}, "Date v.s. Number");
|
||||
</script>
|
||||
|
||||
<div id=log></div>
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>IDBFactory.cmp() - comparison of binary keys</title>
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||
<link rel="help" href="http://w3c.github.io/IndexedDB/#key-construct">
|
||||
<script src=../resources/testharness.js></script>
|
||||
<script src=../resources/testharnessreport.js></script>
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
assert_equals(indexedDB.cmp(new Int8Array([-1]), new Uint8Array([0])), 1,
|
||||
"255(-1) shall be larger than 0");
|
||||
}, "Compare in unsigned octet values (in the range [0, 255])");
|
||||
|
||||
test(function() {
|
||||
assert_equals(indexedDB.cmp(
|
||||
new Uint8Array([255, 254, 253]),
|
||||
new Uint8Array([255, 253, 254])),
|
||||
1,
|
||||
"[255, 254, 253] shall be larger than [255, 253, 254]");
|
||||
}, "Compare values in then same length");
|
||||
|
||||
test(function() {
|
||||
assert_equals(indexedDB.cmp(
|
||||
new Uint8Array([255, 254]),
|
||||
new Uint8Array([255, 253, 254])),
|
||||
1,
|
||||
"[255, 254] shall be larger than [255, 253, 254]");
|
||||
}, "Compare values in different lengths");
|
||||
|
||||
test(function() {
|
||||
assert_equals(indexedDB.cmp(
|
||||
new Uint8Array([255, 253, 254]),
|
||||
new Uint8Array([255, 253])),
|
||||
1,
|
||||
"[255, 253, 254] shall be larger than [255, 253]");
|
||||
}, "Compare when the values in the range of their minimal length are the same");
|
||||
</script>
|
||||
|
||||
<div id=log></div>
|
175
Tests/LibWeb/Text/input/wpt-import/IndexedDB/keyorder.htm
Normal file
175
Tests/LibWeb/Text/input/wpt-import/IndexedDB/keyorder.htm
Normal file
|
@ -0,0 +1,175 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Submitted from TestTWF Paris -->
|
||||
<meta charset="utf-8">
|
||||
<title>Key sort order</title>
|
||||
<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
|
||||
<link rel=assert title="For purposes of comparison, all Arrays are greater than all DOMString, Date and float values; all DOMString values are greater than all Date and float values; and all Date values are greater than all float values. Values of type float are compared to other float values numerically. Values of type Date are compared to other Date values chronologically. Values of type DOMString are compared to other values of type DOMString by using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm, of the ECMAScript Language Specification [ECMA-262]. Values of type Array are compared to other values of type Array as follows:
|
||||
|
||||
1. Let A be the first Array value and B be the second Array value.
|
||||
2. Let length be the lesser of A's length and B's length.
|
||||
3. Let i be 0.
|
||||
4. If the ith value of A is less than the ith value of B, then A is less than B. Skip the remaining steps.
|
||||
5. If the ith value of A is greater than the ith value of B, then A is greater than B. Skip the remaining steps.
|
||||
6. Increase i by 1.
|
||||
7. If i is not equal to length, go back to step 4. Otherwise continue to next step.
|
||||
8. If A's length is less than B's length, then A is less than B. If A's length is greater than B's length, then A is greater than B. Otherwise A and B are equal.">
|
||||
<script src="../resources/testharness.js"></script>
|
||||
<script src="../resources/testharnessreport.js"></script>
|
||||
<script src="resources/support.js"></script>
|
||||
|
||||
<script>
|
||||
var global_db = createdb_for_multiple_tests();
|
||||
|
||||
function keysort(desc, unsorted, expected) {
|
||||
var db,
|
||||
t = async_test("Database readback sort - " + desc),
|
||||
store_name = 'store-' + Date.now() + Math.random();
|
||||
|
||||
// The database test
|
||||
var open_rq = global_db.setTest(t);
|
||||
open_rq.onupgradeneeded = function(e) {
|
||||
db = e.target.result;
|
||||
var objStore = db.createObjectStore(store_name);
|
||||
|
||||
for (var i = 0; i < unsorted.length; i++)
|
||||
objStore.add("value", unsorted[i]);
|
||||
};
|
||||
|
||||
open_rq.onsuccess = function(e) {
|
||||
var actual_keys = [],
|
||||
rq = db.transaction(store_name)
|
||||
.objectStore(store_name)
|
||||
.openCursor();
|
||||
|
||||
rq.onsuccess = t.step_func(function(e) {
|
||||
var cursor = e.target.result;
|
||||
|
||||
if (cursor) {
|
||||
actual_keys.push(cursor.key);
|
||||
cursor.continue();
|
||||
}
|
||||
else {
|
||||
assert_key_equals(actual_keys, expected, "keyorder array");
|
||||
assert_equals(actual_keys.length, expected.length, "array length");
|
||||
|
||||
t.done();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// The IDBKey.cmp test
|
||||
test(function () {
|
||||
var sorted = unsorted.slice(0).sort(function(a, b) { return indexedDB.cmp(a, b)});
|
||||
assert_key_equals(sorted, expected, "sorted array");
|
||||
|
||||
}, "IDBKey.cmp sorted - " + desc);
|
||||
}
|
||||
|
||||
var now = new Date(),
|
||||
one_sec_ago = new Date(now - 1000),
|
||||
one_min_future = new Date(now.getTime() + (1000*60));
|
||||
|
||||
keysort('String < Array',
|
||||
[ [0], "yo", "", [] ],
|
||||
[ "", "yo", [], [0] ]);
|
||||
|
||||
keysort('float < String',
|
||||
[ Infinity, "yo", 0, "", 100 ],
|
||||
[ 0, 100, Infinity, "", "yo" ]);
|
||||
|
||||
keysort('float < Date',
|
||||
[ now, 0, 9999999999999, -0.22 ],
|
||||
[ -0.22, 0, 9999999999999, now ]);
|
||||
|
||||
keysort('float < Date < String < Array',
|
||||
[ [], "", now, [0], "-1", 0, 9999999999999, ],
|
||||
[ 0, 9999999999999, now, "", "-1", [], [0] ]);
|
||||
|
||||
|
||||
keysort('Date(1 sec ago) < Date(now) < Date(1 minute in future)',
|
||||
[ now, one_sec_ago, one_min_future ],
|
||||
[ one_sec_ago, now, one_min_future ]);
|
||||
|
||||
keysort('-1.1 < 1 < 1.01337 < 1.013373 < 2',
|
||||
[ 1.013373, 2, 1.01337, -1.1, 1 ],
|
||||
[ -1.1, 1, 1.01337, 1.013373, 2 ]);
|
||||
|
||||
keysort('-Infinity < -0.01 < 0 < Infinity',
|
||||
[ 0, -0.01, -Infinity, Infinity ],
|
||||
[ -Infinity, -0.01, 0, Infinity ]);
|
||||
|
||||
keysort('"" < "a" < "ab" < "b" < "ba"',
|
||||
[ "a", "ba", "", "b", "ab" ],
|
||||
[ "", "a", "ab", "b", "ba" ]);
|
||||
|
||||
keysort('Arrays',
|
||||
[ [[0]], [0], [], [0, 0], [0, [0]] ],
|
||||
[ [], [0], [0, 0], [0, [0]], [[0]] ]);
|
||||
|
||||
var big_array = [], bigger_array = [];
|
||||
for (var i=0; i < 10000; i++) {
|
||||
big_array.push(i);
|
||||
bigger_array.push(i);
|
||||
}
|
||||
bigger_array.push(0);
|
||||
|
||||
keysort('Array.length: 10,000 < Array.length: 10,001',
|
||||
[ bigger_array, [0, 2, 3], [0], [9], big_array ],
|
||||
[ [0], big_array, bigger_array, [0, 2, 3], [9] ]);
|
||||
|
||||
keysort('Infinity inside arrays',
|
||||
[ [Infinity, 1], [Infinity, Infinity], [1, 1],
|
||||
[1, Infinity], [1, -Infinity], [-Infinity, Infinity] ],
|
||||
[ [-Infinity, Infinity], [1, -Infinity], [1, 1],
|
||||
[1, Infinity], [Infinity, 1], [Infinity, Infinity] ]);
|
||||
|
||||
|
||||
keysort('Test different stuff at once',
|
||||
[
|
||||
now,
|
||||
[0, []],
|
||||
"test",
|
||||
1,
|
||||
["a", [1, [-1]]],
|
||||
["b", "a"],
|
||||
[ 0, 2, "c"],
|
||||
["a", [1, 2]],
|
||||
[],
|
||||
[0, [], 3],
|
||||
["a", "b"],
|
||||
[ 1, 2 ],
|
||||
["a", "b", "c"],
|
||||
one_sec_ago,
|
||||
[ 0, "b", "c"],
|
||||
Infinity,
|
||||
-Infinity,
|
||||
2.55,
|
||||
[ 0, now ],
|
||||
[1]
|
||||
],
|
||||
[
|
||||
-Infinity,
|
||||
1,
|
||||
2.55,
|
||||
Infinity,
|
||||
one_sec_ago,
|
||||
now,
|
||||
"test",
|
||||
[],
|
||||
[0 ,2, "c"],
|
||||
[0, now],
|
||||
[0, "b", "c"],
|
||||
[0, []],
|
||||
[0, [], 3],
|
||||
[1],
|
||||
[1, 2],
|
||||
["a", "b"],
|
||||
["a", "b", "c"],
|
||||
["a", [1, 2]],
|
||||
["a", [1, [-1]]],
|
||||
["b", "a"]
|
||||
]);
|
||||
|
||||
</script>
|
||||
|
||||
<div id="log"></div>
|
|
@ -0,0 +1,240 @@
|
|||
/* 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]);
|
||||
}
|
Loading…
Add table
Reference in a new issue