Bug 1816170 - Disable perftest-on-autoland cron. r=aglavic
[gecko.git] / dom / indexedDB / test / unit / test_keys.js
blob6f1c3de76be1f170d30ac1798f4c53cb7dc26356
1 /**
2  * Any copyright is dedicated to the Public Domain.
3  * http://creativecommons.org/publicdomain/zero/1.0/
4  */
6 /* exported testGenerator */
7 var testGenerator = testSteps();
9 // helper function that ensures that ArrayBuffer instances are meaningfully
10 // displayed (not just as 'object ArrayBuffer')
11 // TODO better move to helpers.js?
12 function showKey(key) {
13   if (key instanceof Array) {
14     return key.map(x => showKey(x)).toString();
15   }
16   if (key instanceof ArrayBuffer) {
17     return "ArrayBuffer([" + new Uint8Array(key).toString() + "])";
18   }
19   return key.toString();
22 function* testSteps() {
23   const dbname = this.window ? window.location.pathname : "Splendid Test";
25   let openRequest = indexedDB.open(dbname, 1);
26   openRequest.onerror = errorHandler;
27   openRequest.onupgradeneeded = grabEventAndContinueHandler;
28   openRequest.onsuccess = unexpectedSuccessHandler;
29   let event = yield undefined;
30   let db = event.target.result;
32   // Create test stores
33   let store = db.createObjectStore("store");
34   let enc = new TextEncoder();
36   // Test simple inserts
37   // Note: the keys must be in order
38   var keys = [
39     -1 / 0,
40     -1.7e308,
41     -10000,
42     -2,
43     -1.5,
44     -1,
45     -1.00001e-200,
46     -1e-200,
47     0,
48     1e-200,
49     1.00001e-200,
50     1,
51     2,
52     10000,
53     1.7e308,
54     1 / 0,
55     new Date("1750-01-02"),
56     new Date("1800-12-31T12:34:56.001"),
57     new Date(-1000),
58     new Date(-10),
59     new Date(-1),
60     new Date(0),
61     new Date(1),
62     new Date(2),
63     new Date(1000),
64     new Date("1971-01-01"),
65     new Date("1971-01-01T01:01:01Z"),
66     new Date("1971-01-01T01:01:01.001Z"),
67     new Date("1971-01-01T01:01:01.01Z"),
68     new Date("1971-01-01T01:01:01.1Z"),
69     new Date("1980-02-02"),
70     new Date("3333-03-19T03:33:33.333"),
71     "",
72     "\x00",
73     "\x00\x00",
74     "\x00\x01",
75     "\x01",
76     "\x02",
77     "\x03",
78     "\x04",
79     "\x07",
80     "\x08",
81     "\x0F",
82     "\x10",
83     "\x1F",
84     "\x20",
85     "01234",
86     "\x3F",
87     "\x40",
88     "A",
89     "A\x00",
90     "A1",
91     "ZZZZ",
92     "a",
93     "a\x00",
94     "aa",
95     "azz",
96     "}",
97     "\x7E",
98     "\x7F",
99     "\x80",
100     "\xFF",
101     "\u0100",
102     "\u01FF",
103     "\u0200",
104     "\u03FF",
105     "\u0400",
106     "\u07FF",
107     "\u0800",
108     "\u0FFF",
109     "\u1000",
110     "\u1FFF",
111     "\u2000",
112     "\u3FFF",
113     "\u4000",
114     "\u7FFF",
115     "\u8000",
116     "\uD800",
117     "\uD800a",
118     "\uD800\uDC01",
119     "\uDBFF",
120     "\uDC00",
121     "\uDFFF\uD800",
122     "\uFFFE",
123     "\uFFFF",
124     "\uFFFF\x00",
125     "\uFFFFZZZ",
126     // Note: enc.encode returns an Uint8Array, which is a valid key, but when
127     // converting it back and forth, the result will be a plain ArrayBuffer,
128     // which is expected in comparisons below
129     // TODO is it ok that the information that the original key was an
130     // Uint8Array is lost?
131     new ArrayBuffer(0),
132     Uint8Array.from([0]).buffer,
133     Uint8Array.from([0, 0]).buffer,
134     Uint8Array.from([0, 1]).buffer,
135     Uint8Array.from([0, 1, 0]).buffer,
136     enc.encode("abc").buffer,
137     enc.encode("abcd").buffer,
138     enc.encode("xyz").buffer,
139     Uint8Array.from([0x80]).buffer,
140     [],
141     [-1 / 0],
142     [-1],
143     [0],
144     [1],
145     [1, "a"],
146     [1, []],
147     [1, [""]],
148     [2, 3],
149     [2, 3.0000000000001],
150     [12, [[]]],
151     [12, [[[]]]],
152     [12, [[[""]]]],
153     [12, [[["foo"]]]],
154     [12, [[[[[3]]]]]],
155     [12, [[[[[[3]]]]]]],
156     [new Date(-1)],
157     [new Date(1)],
158     [""],
159     ["", [[]]],
160     ["", [[[]]]],
161     ["abc"],
162     ["abc", "def"],
163     ["abc\x00"],
164     ["abc\x00", "\x00\x01"],
165     ["abc\x00", "\x00def"],
166     ["abc\x00\x00def"],
167     ["x", [[]]],
168     ["x", [[[]]]],
169     // see comment on scalar ArrayBuffers above
170     [new ArrayBuffer(0)],
171     [new ArrayBuffer(0), "abc"],
172     [new ArrayBuffer(0), new ArrayBuffer(0)],
173     [new ArrayBuffer(0), enc.encode("abc").buffer],
174     [enc.encode("abc").buffer],
175     [enc.encode("abc").buffer, new ArrayBuffer(0)],
176     [enc.encode("abc").buffer, enc.encode("xyz").buffer],
177     [enc.encode("xyz").buffer],
178     [[]],
179     [[], "foo"],
180     [[], []],
181     [[[]]],
182     [[[]], []],
183     [[[]], [[]]],
184     [[[]], [[1]]],
185     [[[]], [[[]]]],
186     [[[1]]],
187     [[[[]], []]],
188   ];
190   for (var i = 0; i < keys.length; ++i) {
191     let keyI = keys[i];
192     is(indexedDB.cmp(keyI, keyI), 0, i + " compared to self");
194     function doCompare(keyI) {
195       for (var j = i - 1; j >= i - 10 && j >= 0; --j) {
196         is(indexedDB.cmp(keyI, keys[j]), 1, i + " compared to " + j);
197         is(indexedDB.cmp(keys[j], keyI), -1, j + " compared to " + i);
198       }
199     }
201     doCompare(keyI);
202     store.add(i, keyI).onsuccess = function(e) {
203       is(
204         indexedDB.cmp(e.target.result, keyI),
205         0,
206         "Returned key should cmp as equal; index = " +
207           i +
208           ", input = " +
209           showKey(keyI) +
210           ", returned = " +
211           showKey(e.target.result)
212       );
213       ok(
214         compareKeys(e.target.result, keyI),
215         "Returned key should actually be equal; index = " +
216           i +
217           ", input = " +
218           showKey(keyI) +
219           ", returned = " +
220           showKey(e.target.result)
221       );
222     };
224     // Test that -0 compares the same as 0
225     if (keyI === 0) {
226       doCompare(-0);
227       let req = store.add(i, -0);
228       req.addEventListener("error", new ExpectError("ConstraintError", true));
229       req.onsuccess = unexpectedSuccessHandler;
230       yield undefined;
231     } else if (Array.isArray(keyI) && keyI.length === 1 && keyI[0] === 0) {
232       doCompare([-0]);
233       let req = store.add(i, [-0]);
234       req.addEventListener("error", new ExpectError("ConstraintError", true));
235       req.onsuccess = unexpectedSuccessHandler;
236       yield undefined;
237     }
238   }
240   store.openCursor().onsuccess = grabEventAndContinueHandler;
241   for (i = 0; i < keys.length; ++i) {
242     event = yield undefined;
243     let cursor = event.target.result;
244     is(
245       indexedDB.cmp(cursor.key, keys[i]),
246       0,
247       "Read back key should cmp as equal; index = " +
248         i +
249         ", input = " +
250         showKey(keys[i]) +
251         ", readBack = " +
252         showKey(cursor.key)
253     );
254     ok(
255       compareKeys(cursor.key, keys[i]),
256       "Read back key should actually be equal; index = " +
257         i +
258         ", input = " +
259         showKey(keys[i]) +
260         ", readBack = " +
261         showKey(cursor.key)
262     );
263     is(cursor.value, i, "Stored with right value");
265     cursor.continue();
266   }
267   event = yield undefined;
268   is(event.target.result, null, "no more results expected");
270   // Note that nan is defined below as '0 / 0'.
271   var invalidKeys = [
272     "nan",
273     "undefined",
274     "null",
275     "/x/",
276     "{}",
277     "new Date(NaN)",
278     'new Date("foopy")',
279     "[nan]",
280     "[undefined]",
281     "[null]",
282     "[/x/]",
283     "[{}]",
284     "[new Date(NaN)]",
285     "[1, nan]",
286     "[1, undefined]",
287     "[1, null]",
288     "[1, /x/]",
289     "[1, {}]",
290     "[1, [nan]]",
291     "[1, [undefined]]",
292     "[1, [null]]",
293     "[1, [/x/]]",
294     "[1, [{}]]",
295     // ATTENTION, the following key allocates 2GB of memory and might cause
296     // subtle failures in some environments, see bug 1796753. We might
297     // want to have some common way between IndexeDB mochitests and
298     // xpcshell tests how to access AppConstants in order to dynamically
299     // exclude this key from some environments, rather than disabling the
300     // entire xpcshell variant of this test for ASAN/TSAN.
301     "new Uint8Array(2147483647)",
302   ];
304   function checkInvalidKeyException(ex, i, callText) {
305     let suffix = ` during ${callText} with invalid key ${i}: ${invalidKeys[i]}`;
306     // isInstance() is not available in mochitest, and we use this JS also as mochitest.
307     // eslint-disable-next-line mozilla/use-isInstance
308     ok(ex instanceof DOMException, "Threw DOMException" + suffix);
309     is(ex.name, "DataError", "Threw right DOMException" + suffix);
310     is(ex.code, 0, "Threw with right code" + suffix);
311   }
313   for (i = 0; i < invalidKeys.length; ++i) {
314     let key_fn = Function(
315       `"use strict"; var nan = 0 / 0; let k = (${invalidKeys[i]}); return k;`
316     );
317     let key;
318     try {
319       key = key_fn();
320     } catch (e) {
321       // If we cannot instantiate the key, we are most likely on a 32 Bit
322       // platform with insufficient memory. Just skip it.
323       info("Key instantiation failed, skipping");
324       continue;
325     }
326     try {
327       indexedDB.cmp(key, 1);
328       ok(false, "didn't throw");
329     } catch (ex) {
330       checkInvalidKeyException(ex, i, "cmp(key, 1)");
331     }
332     try {
333       indexedDB.cmp(1, key);
334       ok(false, "didn't throw2");
335     } catch (ex) {
336       checkInvalidKeyException(ex, i, "cmp(1, key)");
337     }
338     try {
339       store.put(1, key);
340       ok(false, "didn't throw3");
341     } catch (ex) {
342       checkInvalidKeyException(ex, i, "store.put(1, key)");
343     }
344   }
346   openRequest.onsuccess = grabEventAndContinueHandler;
347   yield undefined;
349   finishTest();