1 if (this.importScripts) {
2 importScripts('../../../resources/js-test.js');
3 importScripts('shared.js');
6 description("Test IndexedDB's key generator behavior.");
14 function defineTest(description, verchange, optional) {
17 description: description,
28 testAcrossConnections();
32 var test = tests.shift();
34 debug(test.description);
36 indexedDBTest(prepareDatabase, onSuccess);
37 function prepareDatabase()
39 db = event.target.result;
40 trans = event.target.transaction;
41 trans.onabort = unexpectedAbortCallback;
42 test.verchange(db, trans);
44 function onSuccess() {
45 db = event.target.result;
47 function finishTest() {
48 evalAndLog("db.close()");
53 test.optional(db, finishTest);
63 function check(store, key, expected) {
65 request = evalAndLog("request = store.get(" + JSON.stringify(key) + ")");
66 request.onerror = unexpectedErrorCallback;
67 request.onsuccess = function (e) {
68 self.expected = expected;
69 if (JSON.stringify(event.target.result) === JSON.stringify(expected)) {
70 testPassed("Got " + JSON.stringify(event.target.result) + " for key: " + JSON.stringify(key));
72 testFailed("Got " + JSON.stringify(event.target.result) + " for key: " + JSON.stringify(key) +
73 " expected: " + JSON.stringify(expected));
79 'Verify that each object store has an independent key generator.',
80 function (db, trans) {
81 evalAndLog("store1 = db.createObjectStore('store1', { autoIncrement: true })");
82 evalAndLog("store1.put('a')");
83 check(store1, 1, 'a');
84 evalAndLog("store2 = db.createObjectStore('store2', { autoIncrement: true })");
85 evalAndLog("store2.put('a')");
86 check(store2, 1, 'a');
87 evalAndLog("store1.put('b')");
88 check(store1, 2, 'b');
89 evalAndLog("store2.put('b')");
90 check(store2, 2, 'b');
95 'Verify that the key generator is not updated if insertion fails',
96 function (db, trans) {
97 trans.onerror = function(e) { e.preventDefault() };
98 evalAndLog("store = db.createObjectStore('store1', { autoIncrement: true })");
99 evalAndLog("index = store.createIndex('index1', 'ix', { unique: true })");
100 evalAndLog("store.put({ ix: 'a'})");
101 check(store, 1, {ix: 'a'});
102 evalAndLog("store.put({ ix: 'a'})");
103 evalAndLog("store.put({ ix: 'b'})");
104 check(store, 2, {ix: 'b'});
109 'Verify that the key generator is not affected by item removal (delete or clear).',
110 function (db, trans) {
111 evalAndLog("store = db.createObjectStore('store1', { autoIncrement: true })");
112 evalAndLog("store.put('a')");
113 check(store, 1, 'a');
114 evalAndLog("store.delete(1)");
115 evalAndLog("store.put('b')");
116 check(store, 2, 'b');
117 evalAndLog("store.clear()");
118 evalAndLog("store.put('c')");
119 check(store, 3, 'c');
120 evalAndLog("store.delete(IDBKeyRange.lowerBound(0))");
121 evalAndLog("store.put('d')");
122 check(store, 4, 'd');
127 'Verify that the key generator is only set if and only if a numeric key greater than the last generated key is used.',
128 function (db, trans) {
129 evalAndLog("store = db.createObjectStore('store1', { autoIncrement: true })");
130 evalAndLog("store.put('a')");
131 check(store, 1, 'a');
132 evalAndLog("store.put('b', 3)");
133 check(store, 3, 'b');
134 evalAndLog("store.put('c')");
135 check(store, 4, 'c');
136 evalAndLog("store.put('d', -10)");
137 check(store, -10, 'd');
138 evalAndLog("store.put('e')");
139 check(store, 5, 'e');
140 evalAndLog("store.put('f', 6.00001)");
141 check(store, 6.00001, 'f');
142 evalAndLog("store.put('g')");
143 check(store, 7, 'g');
144 evalAndLog("store.put('f', 8.9999)");
145 check(store, 8.9999, 'f');
146 evalAndLog("store.put('g')");
147 check(store, 9, 'g');
148 evalAndLog("store.put('h', 'foo')");
149 check(store, 'foo', 'h');
150 evalAndLog("store.put('i')");
151 check(store, 10, 'i');
152 evalAndLog("store.put('j', [1000])");
153 check(store, [1000], 'j');
154 evalAndLog("store.put('k')");
155 check(store, 11, 'k');
157 // FIXME: Repeat this test, but with a keyPath and inline key.
162 'Verify that aborting a transaction resets the key generator state.',
163 function (db, trans) {
164 db.createObjectStore('store', { autoIncrement: true });
167 function (db, callback) {
168 evalAndLog("trans1 = db.transaction(['store'], 'readwrite')");
169 evalAndLog("store_t1 = trans1.objectStore('store')");
170 evalAndLog("store_t1.put('a')");
171 check(store_t1, 1, 'a');
172 evalAndLog("store_t1.put('b')");
173 check(store_t1, 2, 'b');
175 // Schedule the abort as a task (not run it synchronously)
176 store_t1.get(0).onsuccess = function () {
177 debug('aborting...');
178 evalAndLog("trans1.abort()");
179 trans1.onabort = function () {
182 evalAndLog("trans2 = db.transaction(['store'], 'readwrite')");
183 evalAndLog("store_t2 = trans2.objectStore('store')");
184 evalAndLog("store_t2.put('c')");
185 check(store_t2, 1, 'c');
186 evalAndLog("store_t2.put('d')");
187 check(store_t2, 2, 'd');
189 trans2.oncomplete = callback;
196 'Verify that keys above 2^53 result in errors.',
197 function (db, trans) {
198 db.createObjectStore('store', { autoIncrement: true });
201 function (db, callback) {
202 evalAndLog("trans1 = db.transaction(['store'], 'readwrite')");
203 evalAndLog("store_t1 = trans1.objectStore('store')");
204 evalAndLog("store_t1.put('a')");
205 check(store_t1, 1, 'a');
206 evalAndLog("store_t1.put('b', 9007199254740992)");
207 check(store_t1, 9007199254740992, 'b');
208 request = evalAndLog("store_t1.put('c')");
209 request.onsuccess = unexpectedSuccessCallback;
210 request.onerror = function () {
211 debug("Error event fired auto-incrementing past 2^53 (as expected)");
212 shouldBe("event.target.error.name", "'ConstraintError'");
213 evalAndLog("event.preventDefault()");
215 evalAndLog("store_t1.put('d', 2)");
216 check(store_t1, 2, 'd');
218 trans1.oncomplete = callback;
222 function testAcrossConnections()
225 debug("Ensure key generator state is maintained across connections:");
226 indexedDBTest(prepareDatabase, doFirstWrite);
227 function prepareDatabase()
229 db = event.target.result;
230 evalAndLog("db.createObjectStore('store', {autoIncrement: true})");
233 function doFirstWrite() {
235 evalAndLog("trans = db.transaction('store', 'readwrite')");
236 trans.onabort = unexpectedAbortCallback;
237 evalAndLog("request = trans.objectStore('store').put('value1')");
238 request.onerror = unexpectedErrorCallback;
239 request.onsuccess = function() {
240 shouldBe("request.result", "1");
241 evalAndLog("trans.objectStore('store').clear()");
243 trans.oncomplete = closeAndReopen;
246 function closeAndReopen() {
247 evalAndLog("db.close()");
249 evalAndLog("request = indexedDB.open(dbname)");
250 request.onsuccess = function () {
251 evalAndLog("db = request.result");
256 function doSecondWrite() {
257 evalAndLog("trans = db.transaction('store', 'readwrite')");
258 trans.onabort = unexpectedAbortCallback;
259 evalAndLog("request = trans.objectStore('store').put('value2')");
260 request.onerror = unexpectedErrorCallback;
261 request.onsuccess = function() {
262 shouldBe("request.result", "2");
264 trans.oncomplete = function() {