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

Side by Side Diff: third_party/WebKit/LayoutTests/storage/indexeddb/resources/rename-common.js

Issue 2314933005: Align IndexedDB metadata rollback on transaction abort to spec. (Closed)
Patch Set: Add failing tests. 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
2 // Returns an IndexedDB database name likely to be unique to the test case.
3 const databaseName = (testCase) => {
4 return 'db' + self.location.pathname + '-' + testCase.name;
5 };
6
7 // Creates an EventWatcher covering all the events that can be issued by
8 // IndexedDB requests and transactions.
9 const requestWatcher = (testCase, request) => {
10 return new EventWatcher(testCase, request,
11 ['error', 'success', 'upgradeneeded']);
12 };
13
14 // Migrates an IndexedDB database whose name is unique for the test case.
15 //
16 // migrationCallback will be called during a versionchange transaction and will
17 // be given the created database and the versionchange transaction
18 //
19 // Returns a promise. If the versionchange transaction goes through, the promise
20 // resolves to an IndexedDB database that must be closed by the caller. If the
21 // versionchange transaction is aborted, the promise resolves to an error.
22 const migrateDatabase = (testCase, newVersion, migrationCallback) => {
23 // We cannot use eventWatcher.wait_for('upgradeneeded') here, because
24 // the versionchange transaction auto-commits before the Promise's then
25 // callback gets called.
26 return new Promise((resolve, reject) => {
27 const request = indexedDB.open(databaseName(testCase), newVersion);
28 request.onupgradeneeded = testCase.step_func(event => {
29 const database = event.target.result;
30 const transaction = event.target.transaction;
31 let abortCalled = false;
32
33 // We wrap IDBTransaction.abort so we can set up the correct event
34 // listeners and expectations if the test chooses to abort the
35 // versionchange transaction.
36 const transactionAbort = transaction.abort.bind(transaction);
37 transaction.abort = () => {
38 request.onerror = event => {
39 event.preventDefault();
40 resolve(event);
41 };
42 request.onsuccess = () => reject(new Error(
43 'indexedDB.open should not succeed after the ' +
44 'versionchange transaction is aborted'));
45 transactionAbort();
46 abortCalled = true;
47 }
48
49 migrationCallback(database, transaction);
50 if (!abortCalled) {
51 request.onsuccess = null;
52 resolve(requestWatcher(testCase, request).wait_for('success'));
53 }
54 });
55 request.onerror = event => reject(event.target.error);
56 request.onsuccess = () => reject(new Error(
57 'indexedDB.open should not succeed without creating a ' +
58 'versionchange transaction'));
59 }).then(event => event.target.result || event.target.error);
60 };
61
62 // Creates an IndexedDB database whose name is unique for the test case.
63 //
64 // setupCallback will be called during a versionchange transaction, and will be
65 // given the created database and the versionchange transaction.
66 //
67 // Returns a promise that resolves to an IndexedDB database. The caller must
68 // close the database.
69 const createDatabase = (testCase, setupCallback) => {
70 const request = indexedDB.deleteDatabase(databaseName(testCase));
71 const eventWatcher = requestWatcher(testCase, request);
72
73 return eventWatcher.wait_for('success').then(event =>
74 migrateDatabase(testCase, 1, setupCallback));
75 };
76
77 // The data in the 'books' object store records in the first example of the
78 // IndexedDB specification.
79 const BOOKS_RECORD_DATA = [
80 { title: 'Quarry Memories', author: 'Fred', isbn: 123456 },
81 { title: 'Water Buffaloes', author: 'Fred', isbn: 234567 },
82 { title: 'Bedrock Nights', author: 'Barney', isbn: 345678 },
83 ];
84
85 // Creates a 'books' object store whose contents closely resembles the first
86 // example in the IndexedDB specification.
87 const createBooksStore = (testCase, database) => {
88 const store = database.createObjectStore('books',
89 { keyPath: 'isbn', autoIncrement: true });
90 store.createIndex('by_author', 'author');
91 store.createIndex('by_title', 'title', { unique: true });
92 for (let record of BOOKS_RECORD_DATA)
93 store.put(record);
94 return store;
95 };
96
97 // Creates a 'not_books' object store used to test renaming into existing or
98 // deleted store names.
99 const createNotBooksStore = (testCase, database) => {
100 const store = database.createObjectStore('not_books');
101 store.createIndex('not_by_author', 'author');
102 store.createIndex('not_by_title', 'title', { unique: true });
103 return store;
104 };
105
106 // Verifies that an object store's indexes match the indexes used to create the
107 // books store in the test database's version 1.
108 //
109 // The errorMessage is used if the assertions fail. It can state that the
110 // IndexedDB implementation being tested is incorrect, or that the testing code
111 // is using it incorrectly.
112 const checkStoreIndexes = (testCase, store, errorMessage) => {
113 assert_array_equals(
114 store.indexNames, ['by_author', 'by_title'], errorMessage);
115 const authorIndex = store.index('by_author');
116 const titleIndex = store.index('by_title');
117 return Promise.all([
118 checkAuthorIndexContents(testCase, authorIndex, errorMessage),
119 checkTitleIndexContents(testCase, titleIndex, errorMessage),
120 ]);
121 };
122
123 // Verifies that an object store's key generator is in the same state as the
124 // key generator created for the books store in the test database's version 1.
125 //
126 // The errorMessage is used if the assertions fail. It can state that the
127 // IndexedDB implementation being tested is incorrect, or that the testing code
128 // is using it incorrectly.
129 const checkStoreGenerator = (testCase, store, expectedKey, errorMessage) => {
130 const request = store.put(
131 { title: 'Bedrock Nights ' + expectedKey, author: 'Barney' });
132 const eventWatcher = requestWatcher(testCase, request);
133 return eventWatcher.wait_for('success').then(() => {
134 const result = request.result;
135 assert_equals(result, expectedKey, errorMessage);
136 });
137 };
138
139 // Verifies that an object store's contents matches the contents used to create
140 // the books store in the test database's version 1.
141 //
142 // The errorMessage is used if the assertions fail. It can state that the
143 // IndexedDB implementation being tested is incorrect, or that the testing code
144 // is using it incorrectly.
145 const checkStoreContents = (testCase, store, errorMessage) => {
146 const request = store.get(123456);
147 const eventWatcher = requestWatcher(testCase, request);
148 return eventWatcher.wait_for('success').then(() => {
149 const result = request.result;
150 assert_equals(result.isbn, BOOKS_RECORD_DATA[0].isbn, errorMessage);
151 assert_equals(result.author, BOOKS_RECORD_DATA[0].author, errorMessage);
152 assert_equals(result.title, BOOKS_RECORD_DATA[0].title, errorMessage);
153 });
154 };
155
156 // Verifies that index matches the 'by_author' index used to create the
157 // by_author books store in the test database's version 1.
158 //
159 // The errorMessage is used if the assertions fail. It can state that the
160 // IndexedDB implementation being tested is incorrect, or that the testing code
161 // is using it incorrectly.
162 const checkAuthorIndexContents = (testCase, index, errorMessage) => {
163 const request = index.get(BOOKS_RECORD_DATA[2].author);
164 const eventWatcher = requestWatcher(testCase, request);
165 return eventWatcher.wait_for('success').then(() => {
166 const result = request.result;
167 assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
168 assert_equals(result.title, BOOKS_RECORD_DATA[2].title, errorMessage);
169 });
170 };
171
172 // Verifies that an index matches the 'by_title' index used to create the books
173 // store in the test database's version 1.
174 //
175 // The errorMessage is used if the assertions fail. It can state that the
176 // IndexedDB implementation being tested is incorrect, or that the testing code
177 // is using it incorrectly.
178 const checkTitleIndexContents = (testCase, index, errorMessage) => {
179 const request = index.get(BOOKS_RECORD_DATA[2].title);
180 const eventWatcher = requestWatcher(testCase, request);
181 return eventWatcher.wait_for('success').then(() => {
182 const result = request.result;
183 assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
184 assert_equals(result.author, BOOKS_RECORD_DATA[2].author, errorMessage);
185 });
186 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698