summaryrefslogtreecommitdiffstats
path: root/dom/indexedDB/test/unit/test_keys.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/indexedDB/test/unit/test_keys.js')
-rw-r--r--dom/indexedDB/test/unit/test_keys.js350
1 files changed, 350 insertions, 0 deletions
diff --git a/dom/indexedDB/test/unit/test_keys.js b/dom/indexedDB/test/unit/test_keys.js
new file mode 100644
index 0000000000..e3f8d6abba
--- /dev/null
+++ b/dom/indexedDB/test/unit/test_keys.js
@@ -0,0 +1,350 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* exported testGenerator */
+var testGenerator = testSteps();
+
+// helper function that ensures that ArrayBuffer instances are meaningfully
+// displayed (not just as 'object ArrayBuffer')
+// TODO better move to helpers.js?
+function showKey(key) {
+ if (key instanceof Array) {
+ return key.map(x => showKey(x)).toString();
+ }
+ if (key instanceof ArrayBuffer) {
+ return "ArrayBuffer([" + new Uint8Array(key).toString() + "])";
+ }
+ return key.toString();
+}
+
+function* testSteps() {
+ const dbname = this.window ? window.location.pathname : "Splendid Test";
+
+ let openRequest = indexedDB.open(dbname, 1);
+ openRequest.onerror = errorHandler;
+ openRequest.onupgradeneeded = grabEventAndContinueHandler;
+ openRequest.onsuccess = unexpectedSuccessHandler;
+ let event = yield undefined;
+ let db = event.target.result;
+
+ // Create test stores
+ let store = db.createObjectStore("store");
+ let enc = new TextEncoder();
+
+ // Test simple inserts
+ // Note: the keys must be in order
+ var keys = [
+ -1 / 0,
+ -1.7e308,
+ -10000,
+ -2,
+ -1.5,
+ -1,
+ -1.00001e-200,
+ -1e-200,
+ 0,
+ 1e-200,
+ 1.00001e-200,
+ 1,
+ 2,
+ 10000,
+ 1.7e308,
+ 1 / 0,
+ new Date("1750-01-02"),
+ new Date("1800-12-31T12:34:56.001"),
+ new Date(-1000),
+ new Date(-10),
+ new Date(-1),
+ new Date(0),
+ new Date(1),
+ new Date(2),
+ new Date(1000),
+ new Date("1971-01-01"),
+ new Date("1971-01-01T01:01:01Z"),
+ new Date("1971-01-01T01:01:01.001Z"),
+ new Date("1971-01-01T01:01:01.01Z"),
+ new Date("1971-01-01T01:01:01.1Z"),
+ new Date("1980-02-02"),
+ new Date("3333-03-19T03:33:33.333"),
+ "",
+ "\x00",
+ "\x00\x00",
+ "\x00\x01",
+ "\x01",
+ "\x02",
+ "\x03",
+ "\x04",
+ "\x07",
+ "\x08",
+ "\x0F",
+ "\x10",
+ "\x1F",
+ "\x20",
+ "01234",
+ "\x3F",
+ "\x40",
+ "A",
+ "A\x00",
+ "A1",
+ "ZZZZ",
+ "a",
+ "a\x00",
+ "aa",
+ "azz",
+ "}",
+ "\x7E",
+ "\x7F",
+ "\x80",
+ "\xFF",
+ "\u0100",
+ "\u01FF",
+ "\u0200",
+ "\u03FF",
+ "\u0400",
+ "\u07FF",
+ "\u0800",
+ "\u0FFF",
+ "\u1000",
+ "\u1FFF",
+ "\u2000",
+ "\u3FFF",
+ "\u4000",
+ "\u7FFF",
+ "\u8000",
+ "\uD800",
+ "\uD800a",
+ "\uD800\uDC01",
+ "\uDBFF",
+ "\uDC00",
+ "\uDFFF\uD800",
+ "\uFFFE",
+ "\uFFFF",
+ "\uFFFF\x00",
+ "\uFFFFZZZ",
+ // Note: enc.encode returns an Uint8Array, which is a valid key, but when
+ // converting it back and forth, the result will be a plain ArrayBuffer,
+ // which is expected in comparisons below
+ // TODO is it ok that the information that the original key was an
+ // Uint8Array is lost?
+ new ArrayBuffer(0),
+ Uint8Array.from([0]).buffer,
+ Uint8Array.from([0, 0]).buffer,
+ Uint8Array.from([0, 1]).buffer,
+ Uint8Array.from([0, 1, 0]).buffer,
+ enc.encode("abc").buffer,
+ enc.encode("abcd").buffer,
+ enc.encode("xyz").buffer,
+ Uint8Array.from([0x80]).buffer,
+ [],
+ [-1 / 0],
+ [-1],
+ [0],
+ [1],
+ [1, "a"],
+ [1, []],
+ [1, [""]],
+ [2, 3],
+ [2, 3.0000000000001],
+ [12, [[]]],
+ [12, [[[]]]],
+ [12, [[[""]]]],
+ [12, [[["foo"]]]],
+ [12, [[[[[3]]]]]],
+ [12, [[[[[[3]]]]]]],
+ [new Date(-1)],
+ [new Date(1)],
+ [""],
+ ["", [[]]],
+ ["", [[[]]]],
+ ["abc"],
+ ["abc", "def"],
+ ["abc\x00"],
+ ["abc\x00", "\x00\x01"],
+ ["abc\x00", "\x00def"],
+ ["abc\x00\x00def"],
+ ["x", [[]]],
+ ["x", [[[]]]],
+ // see comment on scalar ArrayBuffers above
+ [new ArrayBuffer(0)],
+ [new ArrayBuffer(0), "abc"],
+ [new ArrayBuffer(0), new ArrayBuffer(0)],
+ [new ArrayBuffer(0), enc.encode("abc").buffer],
+ [enc.encode("abc").buffer],
+ [enc.encode("abc").buffer, new ArrayBuffer(0)],
+ [enc.encode("abc").buffer, enc.encode("xyz").buffer],
+ [enc.encode("xyz").buffer],
+ [[]],
+ [[], "foo"],
+ [[], []],
+ [[[]]],
+ [[[]], []],
+ [[[]], [[]]],
+ [[[]], [[1]]],
+ [[[]], [[[]]]],
+ [[[1]]],
+ [[[[]], []]],
+ ];
+
+ for (var i = 0; i < keys.length; ++i) {
+ let keyI = keys[i];
+ is(indexedDB.cmp(keyI, keyI), 0, i + " compared to self");
+
+ function doCompare(keyI) {
+ for (var j = i - 1; j >= i - 10 && j >= 0; --j) {
+ is(indexedDB.cmp(keyI, keys[j]), 1, i + " compared to " + j);
+ is(indexedDB.cmp(keys[j], keyI), -1, j + " compared to " + i);
+ }
+ }
+
+ doCompare(keyI);
+ store.add(i, keyI).onsuccess = function (e) {
+ is(
+ indexedDB.cmp(e.target.result, keyI),
+ 0,
+ "Returned key should cmp as equal; index = " +
+ i +
+ ", input = " +
+ showKey(keyI) +
+ ", returned = " +
+ showKey(e.target.result)
+ );
+ ok(
+ compareKeys(e.target.result, keyI),
+ "Returned key should actually be equal; index = " +
+ i +
+ ", input = " +
+ showKey(keyI) +
+ ", returned = " +
+ showKey(e.target.result)
+ );
+ };
+
+ // Test that -0 compares the same as 0
+ if (keyI === 0) {
+ doCompare(-0);
+ let req = store.add(i, -0);
+ req.addEventListener("error", new ExpectError("ConstraintError", true));
+ req.onsuccess = unexpectedSuccessHandler;
+ yield undefined;
+ } else if (Array.isArray(keyI) && keyI.length === 1 && keyI[0] === 0) {
+ doCompare([-0]);
+ let req = store.add(i, [-0]);
+ req.addEventListener("error", new ExpectError("ConstraintError", true));
+ req.onsuccess = unexpectedSuccessHandler;
+ yield undefined;
+ }
+ }
+
+ store.openCursor().onsuccess = grabEventAndContinueHandler;
+ for (i = 0; i < keys.length; ++i) {
+ event = yield undefined;
+ let cursor = event.target.result;
+ is(
+ indexedDB.cmp(cursor.key, keys[i]),
+ 0,
+ "Read back key should cmp as equal; index = " +
+ i +
+ ", input = " +
+ showKey(keys[i]) +
+ ", readBack = " +
+ showKey(cursor.key)
+ );
+ ok(
+ compareKeys(cursor.key, keys[i]),
+ "Read back key should actually be equal; index = " +
+ i +
+ ", input = " +
+ showKey(keys[i]) +
+ ", readBack = " +
+ showKey(cursor.key)
+ );
+ is(cursor.value, i, "Stored with right value");
+
+ cursor.continue();
+ }
+ event = yield undefined;
+ is(event.target.result, null, "no more results expected");
+
+ // Note that nan is defined below as '0 / 0'.
+ var invalidKeys = [
+ "nan",
+ "undefined",
+ "null",
+ "/x/",
+ "{}",
+ "new Date(NaN)",
+ 'new Date("foopy")',
+ "[nan]",
+ "[undefined]",
+ "[null]",
+ "[/x/]",
+ "[{}]",
+ "[new Date(NaN)]",
+ "[1, nan]",
+ "[1, undefined]",
+ "[1, null]",
+ "[1, /x/]",
+ "[1, {}]",
+ "[1, [nan]]",
+ "[1, [undefined]]",
+ "[1, [null]]",
+ "[1, [/x/]]",
+ "[1, [{}]]",
+ // ATTENTION, the following key allocates 2GB of memory and might cause
+ // subtle failures in some environments, see bug 1796753. We might
+ // want to have some common way between IndexeDB mochitests and
+ // xpcshell tests how to access AppConstants in order to dynamically
+ // exclude this key from some environments, rather than disabling the
+ // entire xpcshell variant of this test for ASAN/TSAN.
+ "new Uint8Array(2147483647)",
+ ];
+
+ function checkInvalidKeyException(ex, i, callText) {
+ let suffix = ` during ${callText} with invalid key ${i}: ${invalidKeys[i]}`;
+ // isInstance() is not available in mochitest, and we use this JS also as mochitest.
+ // eslint-disable-next-line mozilla/use-isInstance
+ ok(ex instanceof DOMException, "Threw DOMException" + suffix);
+ is(ex.name, "DataError", "Threw right DOMException" + suffix);
+ is(ex.code, 0, "Threw with right code" + suffix);
+ }
+
+ for (i = 0; i < invalidKeys.length; ++i) {
+ let key_fn = Function(
+ `"use strict"; var nan = 0 / 0; let k = (${invalidKeys[i]}); return k;`
+ );
+ let key;
+ try {
+ key = key_fn();
+ } catch (e) {
+ // If we cannot instantiate the key, we are most likely on a 32 Bit
+ // platform with insufficient memory. Just skip it.
+ info("Key instantiation failed, skipping");
+ continue;
+ }
+ try {
+ indexedDB.cmp(key, 1);
+ ok(false, "didn't throw");
+ } catch (ex) {
+ checkInvalidKeyException(ex, i, "cmp(key, 1)");
+ }
+ try {
+ indexedDB.cmp(1, key);
+ ok(false, "didn't throw2");
+ } catch (ex) {
+ checkInvalidKeyException(ex, i, "cmp(1, key)");
+ }
+ try {
+ store.put(1, key);
+ ok(false, "didn't throw3");
+ } catch (ex) {
+ checkInvalidKeyException(ex, i, "store.put(1, key)");
+ }
+ }
+
+ openRequest.onsuccess = grabEventAndContinueHandler;
+ yield undefined;
+
+ finishTest();
+}