Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(862)

Side by Side Diff: third_party/WebKit/LayoutTests/storage/indexeddb/rename-index.html

Issue 2276593002: Support renaming of IndexedDB indexes and object stores. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed review and buildbot feedback. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <!DOCTYPE html>
2 <title>IndexedDB: index renaming support</title>
3 <script src='../../resources/testharness.js'></script>
4 <link rel="help"
5 href="https://w3c.github.io/IndexedDB/#dom-idbindex-name">
6 <link rel="author" href="pwnall@chromium.org" title="Victor Costan">
7 <script src='../../resources/testharnessreport.js'></script>
8 <script src='resources/rename-common.js'></script>
9 <script>
10
11 promise_test(testCase => {
12 let authorIndex = null, authorIndex2 = null;
13 let renamedAuthorIndex = null, renamedAuthorIndex2 = null;
14 return createDatabase(testCase, (database, transaction) => {
15 const store = createBooksStore(testCase, database);
16 authorIndex = store.index('by_author');
17 }).then(database => {
18 const transaction = database.transaction('books', 'readonly');
19 const store = transaction.objectStore('books');
20 assert_array_equals(
21 store.indexNames, ['by_author', 'by_title'],
22 'Test setup should have created two indexes');
23 authorIndex2 = store.index('by_author');
24 return checkAuthorIndexContents(
25 testCase, authorIndex2,
26 'The index should have the expected contents before any renaming').
27 then(() => database.close());
28 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
29 const store = transaction.objectStore('books');
30 renamedAuthorIndex = store.index('by_author');
31 renamedAuthorIndex.name = 'renamed_by_author';
32
33 assert_equals(
34 renamedAuthorIndex.name, 'renamed_by_author',
35 'IDBIndex name should change immediately after a rename');
36 assert_array_equals(
37 store.indexNames, ['by_title', 'renamed_by_author'],
38 'IDBObjectStore.indexNames should immediately reflect the rename');
39 assert_equals(
40 store.index('renamed_by_author'), renamedAuthorIndex,
41 'IDBObjectStore.index should return the renamed index store when ' +
42 'queried using the new name immediately after the rename');
43 assert_throws(
44 'NotFoundError', () => store.index('by_author'),
45 'IDBObjectStore.index should throw when queried using the renamed' +
46 "index's old name immediately after the rename");
47 })).then(database => {
48 const transaction = database.transaction('books', 'readonly');
49 const store = transaction.objectStore('books');
50 assert_array_equals(
51 store.indexNames, ['by_title', 'renamed_by_author'],
52 'IDBObjectStore.indexNames should still reflect the rename after ' +
53 'the versionchange transaction commits');
54 renamedAuthorIndex2 = store.index('renamed_by_author');
55 return checkAuthorIndexContents(
56 testCase, renamedAuthorIndex2,
57 'Renaming an index should not change its contents').then(
58 () => database.close());
59 }).then(() => {
60 assert_equals(
61 authorIndex.name, 'by_author',
62 'IDBIndex obtained before the rename transaction should not ' +
63 'reflect the rename');
64 assert_equals(
65 authorIndex2.name, 'by_author',
66 'IDBIndex obtained before the rename transaction should not ' +
67 'reflect the rename');
68 assert_equals(
69 renamedAuthorIndex.name, 'renamed_by_author',
70 'IDBIndex used in the rename transaction should keep reflecting ' +
71 'the new name after the transaction is committed');
72 assert_equals(
73 renamedAuthorIndex2.name, 'renamed_by_author',
74 'IDBIndex obtained after the rename transaction should reflect ' +
75 'the new name');
76 });
77 }, 'IndexedDB index rename in new transaction');
78
79 promise_test(testCase => {
80 let renamedAuthorIndex = null, renamedAuthorIndex2 = null;
81 return createDatabase(testCase, (database, transaction) => {
82 const store = createBooksStore(testCase, database);
83 renamedAuthorIndex = store.index('by_author');
84 renamedAuthorIndex.name = 'renamed_by_author';
85
86 assert_equals(
87 renamedAuthorIndex.name, 'renamed_by_author',
88 'IDBIndex name should change immediately after a rename');
89 assert_array_equals(
90 store.indexNames, ['by_title', 'renamed_by_author'],
91 'IDBObjectStore.indexNames should immediately reflect the rename');
92 assert_equals(
93 store.index('renamed_by_author'), renamedAuthorIndex,
94 'IDBObjectStore.index should return the renamed index store when ' +
95 'queried using the new name immediately after the rename');
96 assert_throws(
97 'NotFoundError', () => store.index('by_author'),
98 'IDBObjectStore.index should throw when queried using the renamed' +
99 "index's old name immediately after the rename");
100 }).then(database => {
101 const transaction = database.transaction('books', 'readonly');
102 const store = transaction.objectStore('books');
103 assert_array_equals(
104 store.indexNames, ['by_title', 'renamed_by_author'],
105 'IDBObjectStore.indexNames should still reflect the rename after ' +
106 'the versionchange transaction commits');
107 renamedAuthorIndex2 = store.index('renamed_by_author');
108 return checkAuthorIndexContents(
109 testCase, renamedAuthorIndex2,
110 'Renaming an index should not change its contents').then(
111 () => database.close());
112 }).then(() => {
113 assert_equals(
114 renamedAuthorIndex.name, 'renamed_by_author',
115 'IDBIndex used in the rename transaction should keep reflecting ' +
116 'the new name after the transaction is committed');
117 assert_equals(
118 renamedAuthorIndex2.name, 'renamed_by_author',
119 'IDBIndex obtained after the rename transaction should reflect ' +
120 'the new name');
121 });
122 }, 'IndexedDB index rename in the transaction where it is created');
123
124 promise_test(testCase => {
125 return createDatabase(testCase, (database, transaction) => {
126 createBooksStore(testCase, database);
127 }).then(database => {
128 database.close();
129 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
130 const store = transaction.objectStore('books');
131 const index = store.index('by_author');
132 store.deleteIndex('by_author');
133 assert_throws(
134 'InvalidStateError', () => index.name = 'renamed_by_author');
135 })).then(database => database.close());
136 }, 'IndexedDB deleted index rename throws');
137
138 promise_test(testCase => {
139 return createDatabase(testCase, (database, transaction) => {
140 createBooksStore(testCase, database);
141 }).then(database => {
142 const transaction = database.transaction('books', 'readonly');
143 const store = transaction.objectStore('books');
144 const index = store.index('by_author');
145
146 assert_throws(
147 'InvalidStateError', () => index.name = 'renamed_by_author');
148 database.close();
149 });
150 }, 'IndexedDB index rename throws in a readonly transaction');
151
152 promise_test(testCase => {
153 return createDatabase(testCase, (database, transaction) => {
154 createBooksStore(testCase, database);
155 }).then(database => {
156 const transaction = database.transaction('books', 'readwrite');
157 const store = transaction.objectStore('books');
158 const index = store.index('by_author');
159
160 assert_throws(
161 'InvalidStateError', () => index.name = 'renamed_by_author');
162 database.close();
163 });
164 }, 'IndexedDB index rename throws in a readwrite transaction');
165
166 promise_test(testCase => {
167 let authorIndex = null;
168 return createDatabase(testCase, (database, transaction) => {
169 const store = createBooksStore(testCase, database);
170 authorIndex = store.index('by_author');
171 }).then(database => {
172 assert_throws(
173 'TransactionInactiveError',
174 () => authorIndex.name = 'renamed_by_author');
175 database.close();
176 });
177 }, 'IndexedDB index rename throws in an inactive transaction');
178
179 promise_test(testCase => {
180 return createDatabase(testCase, (database, transaction) => {
181 createBooksStore(testCase, database);
182 }).then(database => {
183 database.close();
184 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
185 const store = transaction.objectStore('books');
186 const index = store.index('by_author');
187 index.name = 'by_author';
188 assert_array_equals(
189 store.indexNames, ['by_author', 'by_title'],
190 'Renaming an index to the same name should not change the ' +
191 "index's IDBObjectStore.indexNames");
192 })).then(database => {
193 const transaction = database.transaction('books', 'readonly');
194 const store = transaction.objectStore('books');
195 assert_array_equals(
196 store.indexNames, ['by_author', 'by_title'],
197 'Committing a transaction that renames a store to the same name ' +
198 "should not change the index's IDBObjectStore.indexNames");
199 const index = store.index('by_author');
200 return checkAuthorIndexContents(
201 testCase, index,
202 'Committing a transaction that renames an index to the same name ' +
203 "should not change the index's contents").then(
204 () => database.close());
205 });
206 }, 'IndexedDB index rename to the same name succeeds');
207
208 promise_test(testCase => {
209 return createDatabase(testCase, (database, transaction) => {
210 createBooksStore(testCase, database);
211 }).then(database => {
212 database.close();
213 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
214 const store = transaction.objectStore('books');
215 const index = store.index('by_author');
216
217 assert_throws('ConstraintError', () => index.name = 'by_title');
218 assert_array_equals(
219 store.indexNames, ['by_author', 'by_title'],
220 'An index rename that throws an exception should not change the ' +
221 "index's IDBObjectStore.indexNames");
222 })).then(database => {
223 const transaction = database.transaction('books', 'readonly');
224 const store = transaction.objectStore('books');
225 assert_array_equals(
226 store.indexNames, ['by_author', 'by_title'],
227 'Committing a transaction with a failed store rename attempt ' +
228 "should not change the index's IDBObjectStore.indexNames");
229 const index = store.index('by_author');
230 return checkAuthorIndexContents(
231 testCase, index,
232 'Committing a transaction with a failed rename attempt should not' +
233 "change the index's contents").then(() => database.close());
234 });
235 }, 'IndexedDB index rename to the name of another index throws');
236
237 promise_test(testCase => {
238 return createDatabase(testCase, (database, transaction) => {
239 createBooksStore(testCase, database);
240 }).then(database => {
241 database.close();
242 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
243 const store = transaction.objectStore('books');
244 const index = store.index('by_author');
245 store.deleteIndex('by_title');
246 index.name = 'by_title';
247 assert_array_equals(
248 store.indexNames, ['by_title'],
249 'IDBObjectStore.indexNames should immediately reflect the rename');
250 })).then(database => {
251 const transaction = database.transaction('books', 'readonly');
252 const store = transaction.objectStore('books');
253 assert_array_equals(
254 store.indexNames, ['by_title'],
255 'IDBObjectStore.indexNames should still reflect the rename after ' +
256 'the versionchange transaction commits');
257 const index = store.index('by_title');
258 return checkAuthorIndexContents(
259 testCase, index,
260 'Renaming an index should not change its contents').then(
261 () => database.close());
262 });
263 }, 'IndexedDB index rename to the name of a deleted index succeeds');
264
265 promise_test(testCase => {
266 return createDatabase(testCase, (database, transaction) => {
267 createBooksStore(testCase, database);
268 }).then(database => {
269 database.close();
270 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
271 const store = transaction.objectStore('books');
272 store.index('by_author').name = 'tmp';
273 store.index('by_title').name = 'by_author';
274 store.index('tmp').name = 'by_title';
275 assert_array_equals(
276 store.indexNames, ['by_author', 'by_title'],
277 'IDBObjectStore.indexNames should reflect the swap immediately ' +
278 'after the renames');
279 return checkTitleIndexContents(
280 testCase, store.index('by_author'),
281 'Renaming an index should not change its contents');
282 })).then(database => {
283 const transaction = database.transaction('books', 'readonly');
284 const store = transaction.objectStore('books');
285 assert_array_equals(
286 store.indexNames, ['by_author', 'by_title'],
287 'IDBObjectStore.indexNames should still reflect the swap after ' +
288 'the versionchange transaction commits');
289 const index = store.index('by_title');
290 return checkAuthorIndexContents(
291 testCase, index,
292 'Renaming an index should not change its contents').then(
293 () => database.close());
294 });
295 }, 'IndexedDB index swapping via renames succeeds');
296
297 promise_test(testCase => {
298 return createDatabase(testCase, (database, transaction) => {
299 createBooksStore(testCase, database);
300 }).then(database => {
301 database.close();
302 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
303 const store = transaction.objectStore('books');
304 const index = store.index('by_author');
305
306 index.name = 42;
307 assert_equals(index.name, '42',
308 'IDBIndex name should change immediately after a rename to a ' +
309 'number');
310 assert_array_equals(
311 store.indexNames, ['42', 'by_title'],
312 'IDBObjectStore.indexNames should immediately reflect the ' +
313 'stringifying rename');
314
315 index.name = true;
316 assert_equals(index.name, 'true',
317 'IDBIndex name should change immediately after a rename to a ' +
318 'boolean');
319
320 index.name = {};
321 assert_equals(index.name, '[object Object]',
322 'IDBIndex name should change immediately after a rename to an ' +
323 'object');
324
325 index.name = () => null;
326 assert_equals(index.name, '() => null',
327 'IDBIndex name should change immediately after a rename to a ' +
328 'function');
329
330 index.name = undefined;
331 assert_equals(index.name, 'undefined',
332 'IDBIndex name should change immediately after a rename to ' +
333 'undefined');
334 })).then(database => {
335 const transaction = database.transaction('books', 'readonly');
336 const store = transaction.objectStore('books');
337 assert_array_equals(
338 store.indexNames, ['by_title', 'undefined'],
339 'IDBObjectStore.indexNames should reflect the last rename ' +
340 'after the versionchange transaction commits');
341 const index = store.index('undefined');
342 return checkAuthorIndexContents(
343 testCase, index,
344 'Renaming an index should not change its contents').then(
345 () => database.close());
346 });
347 }, 'IndexedDB object store rename stringifies non-string names');
348
349 promise_test(testCase => {
350 return createDatabase(testCase, (database, transaction) => {
351 createBooksStore(testCase, database);
352 }).then(database => {
353 database.close();
354 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
355 const store = transaction.objectStore('books');
356 const index = store.index('by_author');
357
358 assert_throws(
359 { name: 'Custom stringifying error'},
360 () => {
361 index.name = {
362 toString: () => { throw { name: 'Custom stringifying error'}; }
363 };
364 }, 'IDBObjectStore rename should re-raise toString() exception');
365 assert_array_equals(
366 store.indexNames, ['by_author', 'by_title'],
367 'An index rename that throws an exception should not change the ' +
368 "index's IDBObjectStore.indexNames");
369 })).then(database => {
370 const transaction = database.transaction('books', 'readonly');
371 const store = transaction.objectStore('books');
372 assert_array_equals(
373 store.indexNames, ['by_author', 'by_title'],
374 'Committing a transaction with a failed store rename attempt ' +
375 "should not change the index's IDBObjectStore.indexNames");
376 const index = store.index('by_author');
377 return checkAuthorIndexContents(
378 testCase, index,
379 'Committing a transaction with a failed rename attempt should not' +
380 "change the index's contents").then(() => database.close());
381 });
382 }, 'IndexedDB object store rename handles exceptions when stringifying names');
383
384 for (let escapedName of ['', '\\u0000', '\\uDC00\\uD800']) ((escapedName) => {
385 const name = JSON.parse('"' + escapedName + '"');
386 promise_test(testCase => {
387 return createDatabase(testCase, (database, transaction) => {
388 createBooksStore(testCase, database);
389 }).then(database => {
390 database.close();
391 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
392 const store = transaction.objectStore('books');
393 const index = store.index('by_author');
394
395 index.name = name;
396 assert_equals(index.name, name,
397 'IDBIndex name should change immediately after the rename');
398 assert_array_equals(
399 store.indexNames, [name, 'by_title'].sort(),
400 'IDBObjectStore.indexNames should immediately reflect the rename');
401 })).then(database => {
402 const transaction = database.transaction('books', 'readonly');
403 const store = transaction.objectStore('books');
404 assert_array_equals(
405 store.indexNames, [name, 'by_title'].sort(),
406 'IDBObjectStore.indexNames should reflect the rename ' +
407 'after the versionchange transaction commits');
408 const index = store.index(name);
409 return checkAuthorIndexContents(
410 testCase, index,
411 'Renaming an index should not change its contents').then(
412 () => database.close());
413 });
414 }, 'IndexedDB object store can be renamed to "' + escapedName + '"');
415 })(escapedName);
416
417 promise_test(testCase => {
418 const dbName = databaseName(testCase);
419 let authorIndex = null, authorIndex2 = null;
420 return createDatabase(testCase, (database, transaction) => {
421 const store = createBooksStore(testCase, database);
422 }).then(database => {
423 database.close();
424 }).then(() => new Promise((resolve, reject) => {
425 const request = indexedDB.open(dbName, 2);
426 request.onupgradeneeded = event => {
427 const database = event.target.result;
428 const transaction = event.target.transaction;
429 const store = transaction.objectStore('books');
430 authorIndex = store.index('by_author');
431 authorIndex.name = 'renamed_by_author';
432 request.onerror = event => {
433 event.preventDefault();
434 resolve(event);
435 }
436 transaction.abort();
437
438 assert_equals(
439 authorIndex.name, 'by_author',
440 'IDBIndex.name should not reflect the rename anymore ' +
441 'immediately after transaction.abort() returns');
442 assert_array_equals(
443 store.indexNames, ['by_author', 'by_title'],
444 'IDBObjectStore.indexNames should not reflect the rename ' +
445 'anymore immediately after transaction.abort() returns');
446 };
447 request.onerror = event => reject(event.target.error);
448 request.onsuccess = () => reject(new Error(
449 'indexedDB.open was not supposed to succeed'));
450 })).then(event => {
451 assert_equals(authorIndex.name, 'by_author',
452 'IDBIndex.name should not reflect the rename anymore ' +
453 'after the versionchange transaction is aborted');
454
455 const request = indexedDB.open(dbName, 1);
456 return requestWatcher(testCase, request).wait_for('success');
457 }).then(event => {
458 const database = event.target.result;
459 const transaction = database.transaction('books', 'readonly');
460 const store = transaction.objectStore('books');
461 assert_array_equals(
462 store.indexNames, ['by_author', 'by_title'],
463 'IDBDatabase.objectStoreNames should not reflect the rename ' +
464 'after the versionchange transaction is aborted');
465
466 authorIndex2 = store.index('by_author');
467 return checkAuthorIndexContents(
468 testCase, authorIndex2,
469 'Aborting an index rename transaction should not change the ' +
470 "index's records").then(() => database.close());
471 }).then(() => {
472 assert_equals(
473 authorIndex.name, 'by_author',
474 'IDBIndex used in aborted rename transaction should not reflect ' +
475 'the rename after the transaction is aborted');
476 assert_equals(authorIndex2.name, 'by_author',
477 'IDBIndex obtained after an aborted rename transaction should ' +
478 'not reflect the rename');
479 });
480 }, 'IndexedDB object store rename in aborted transaction');
481 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698