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

Side by Side Diff: third_party/WebKit/LayoutTests/storage/indexeddb/resources/support-promises.js

Issue 2556373003: Tests for exceptions related to IndexedDB upgrade transaction lifecycle. (Closed)
Patch Set: Yanked hacky tests, added meta charset. Created 3 years, 12 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
« no previous file with comments | « no previous file | third_party/WebKit/LayoutTests/storage/indexeddb/upgrade-transaction-lifecycle-backend-aborted.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 'use strict';
2
3 // Returns an IndexedDB database name likely to be unique to the test case.
jsbell 2017/01/04 23:38:49 I'd drop 'likely to be'
pwnall 2017/01/05 06:52:12 Done.
4 const databaseName = testCase => {
jsbell 2017/01/04 23:38:49 Is there an advantage to `const f = a => { ... };`
pwnall 2017/01/05 06:52:12 Done. Replaced everywhere in the file.
5 return 'db' + self.location.pathname + '-' + testCase.name;
6 };
7
8 // Creates an EventWatcher covering all the events that can be issued by
9 // IndexedDB requests and transactions.
jsbell 2017/01/04 23:38:49 no longer true - transactions have 'complete' and
pwnall 2017/01/05 06:52:12 Done. I added the other events. Thank you for noti
10 const requestWatcher = (testCase, request) => {
11 return new EventWatcher(testCase, request,
12 ['blocked', 'error', 'success', 'upgradeneeded']);
13 };
14
15 // Migrates an IndexedDB database whose name is unique for the test case.
16 //
17 // newVersion must be greater than the database's current version.
18 //
19 // migrationCallback will be called during a versionchange transaction and will
20 // given the created database, the versionchange transaction, and the database
21 // open request.
22 //
23 // Returns a promise. If the versionchange transaction goes through, the promise
24 // resolves to an IndexedDB database that must be closed by the caller. If the
25 // versionchange transaction is aborted, the promise resolves to an error.
26 const migrateDatabase = (testCase, newVersion, migrationCallback) => {
27 return migrateNamedDatabase(
28 testCase, databaseName(testCase), newVersion, migrationCallback);
29 };
30
31 // Migrates an IndexedDB database.
32 //
33 // newVersion must be greater than the database's current version.
34 //
35 // migrationCallback will be called during a versionchange transaction and will
36 // given the created database, the versionchange transaction, and the database
37 // open request.
38 //
39 // Returns a promise. If the versionchange transaction goes through, the promise
40 // resolves to an IndexedDB database that must be closed by the caller. If the
41 // versionchange transaction is aborted, the promise resolves to an error.
42 const migrateNamedDatabase =
43 (testCase, databaseName, newVersion, migrationCallback) => {
44 // We cannot use eventWatcher.wait_for('upgradeneeded') here, because
45 // the versionchange transaction auto-commits before the Promise's then
46 // callback gets called.
47 return new Promise((resolve, reject) => {
48 const request = indexedDB.open(databaseName, newVersion);
49 request.onupgradeneeded = testCase.step_func(event => {
50 const database = event.target.result;
51 const transaction = event.target.transaction;
52 let shouldBeAborted = false;
53 let requestEventPromise = null;
54
55 // We wrap IDBTransaction.abort so we can set up the correct event
56 // listeners and expectations if the test chooses to abort the
57 // versionchange transaction.
58 const transactionAbort = transaction.abort.bind(transaction);
59 transaction.abort = () => {
60 transaction._willBeAborted();
61 transactionAbort();
62 }
63 transaction._willBeAborted = () => {
64 requestEventPromise = new Promise((resolve, reject) => {
65 request.onerror = event => {
66 event.preventDefault();
67 resolve(event);
68 };
69 request.onsuccess = () => reject(new Error(
70 'indexedDB.open should not succeed for an aborted ' +
71 'versionchange transaction'));
72 });
73 shouldBeAborted = true;
74 }
75
76 // If migration callback returns a promise, we'll wait for it to resolve.
77 // This simplifies some tests.
78 const callbackResult = migrationCallback(database, transaction, request);
79 if (!shouldBeAborted) {
80 request.onerror = null;
81 request.onsuccess = null;
82 requestEventPromise =
83 requestWatcher(testCase, request).wait_for('success');
84 }
85
86 // requestEventPromise needs to be the last promise in the chain, because
87 // we want the event that it resolves to.
88 resolve(Promise.resolve(callbackResult).then(() => requestEventPromise));
89 });
90 request.onerror = event => reject(event.target.error);
91 request.onsuccess = () => reject(new Error(
92 'indexedDB.open should not succeed without creating a ' +
93 'versionchange transaction'));
94 }).then(event => event.target.result || event.target.error);
95 };
96
97 // Creates an IndexedDB database whose name is unique for the test case.
98 //
99 // setupCallback will be called during a versionchange transaction, and will be
100 // given the created database, the versionchange transaction, and the database
101 // open request.
102 //
103 // Returns a promise that resolves to an IndexedDB database. The caller must
104 // close the database.
105 const createDatabase = (testCase, setupCallback) => {
106 return createNamedDatabase(testCase, databaseName(testCase), setupCallback);
107 };
108
109 // Creates an IndexedDB database.
110 //
111 // setupCallback will be called during a versionchange transaction, and will be
112 // given the created database, the versionchange transaction, and the database
113 // open request.
114 //
115 // Returns a promise that resolves to an IndexedDB database. The caller must
116 // close the database.
117 const createNamedDatabase = (testCase, databaseName, setupCallback) => {
118 const request = indexedDB.deleteDatabase(databaseName);
119 const eventWatcher = requestWatcher(testCase, request);
120
121 return eventWatcher.wait_for('success').then(event =>
122 migrateNamedDatabase(testCase, databaseName, 1, setupCallback));
123 };
124
125 // Opens an IndexedDB database without performing schema changes.
126 //
127 // The given version number must match the database's current version.
128 //
129 // Returns a promise that resolves to an IndexedDB database. The caller must
130 // close the database.
131 const openDatabase = (testCase, version) => {
132 return openNamedDatabase(testCase, databaseName(testCase), version);
133 }
134
135 // Opens an IndexedDB database without performing schema changes.
136 //
137 // The given version number must match the database's current version.
138 //
139 // Returns a promise that resolves to an IndexedDB database. The caller must
140 // close the database.
141 const openNamedDatabase = (testCase, databaseName, version) => {
142 const request = indexedDB.open(databaseName, version);
143 const eventWatcher = requestWatcher(testCase, request);
144 return eventWatcher.wait_for('success').then(event => event.target.result);
145 }
146
147 // The data in the 'books' object store records in the first example of the
148 // IndexedDB specification.
149 const BOOKS_RECORD_DATA = [
150 { title: 'Quarry Memories', author: 'Fred', isbn: 123456 },
151 { title: 'Water Buffaloes', author: 'Fred', isbn: 234567 },
152 { title: 'Bedrock Nights', author: 'Barney', isbn: 345678 },
153 ];
154
155 // Creates a 'books' object store whose contents closely resembles the first
156 // example in the IndexedDB specification.
157 const createBooksStore = (testCase, database) => {
158 const store = database.createObjectStore('books',
159 { keyPath: 'isbn', autoIncrement: true });
160 store.createIndex('by_author', 'author');
161 store.createIndex('by_title', 'title', { unique: true });
162 for (let record of BOOKS_RECORD_DATA)
163 store.put(record);
164 return store;
165 };
166
167 // Creates a 'not_books' object store used to test renaming into existing or
168 // deleted store names.
169 const createNotBooksStore = (testCase, database) => {
170 const store = database.createObjectStore('not_books');
171 store.createIndex('not_by_author', 'author');
172 store.createIndex('not_by_title', 'title', { unique: true });
173 return store;
174 };
175
176 // Verifies that an object store's indexes match the indexes used to create the
177 // books store in the test database's version 1.
178 //
179 // The errorMessage is used if the assertions fail. It can state that the
180 // IndexedDB implementation being tested is incorrect, or that the testing code
181 // is using it incorrectly.
182 const checkStoreIndexes = (testCase, store, errorMessage) => {
183 assert_array_equals(
184 store.indexNames, ['by_author', 'by_title'], errorMessage);
185 const authorIndex = store.index('by_author');
186 const titleIndex = store.index('by_title');
187 return Promise.all([
188 checkAuthorIndexContents(testCase, authorIndex, errorMessage),
189 checkTitleIndexContents(testCase, titleIndex, errorMessage),
190 ]);
191 };
192
193 // Verifies that an object store's key generator is in the same state as the
194 // key generator created for the books store in the test database's version 1.
195 //
196 // The errorMessage is used if the assertions fail. It can state that the
197 // IndexedDB implementation being tested is incorrect, or that the testing code
198 // is using it incorrectly.
199 const checkStoreGenerator = (testCase, store, expectedKey, errorMessage) => {
200 const request = store.put(
201 { title: 'Bedrock Nights ' + expectedKey, author: 'Barney' });
202 const eventWatcher = requestWatcher(testCase, request);
203 return eventWatcher.wait_for('success').then(() => {
204 const result = request.result;
205 assert_equals(result, expectedKey, errorMessage);
206 });
207 };
208
209 // Verifies that an object store's contents matches the contents used to create
210 // the books store in the test database's version 1.
211 //
212 // The errorMessage is used if the assertions fail. It can state that the
213 // IndexedDB implementation being tested is incorrect, or that the testing code
214 // is using it incorrectly.
215 const checkStoreContents = (testCase, store, errorMessage) => {
216 const request = store.get(123456);
217 const eventWatcher = requestWatcher(testCase, request);
218 return eventWatcher.wait_for('success').then(() => {
219 const result = request.result;
220 assert_equals(result.isbn, BOOKS_RECORD_DATA[0].isbn, errorMessage);
221 assert_equals(result.author, BOOKS_RECORD_DATA[0].author, errorMessage);
222 assert_equals(result.title, BOOKS_RECORD_DATA[0].title, errorMessage);
223 });
224 };
225
226 // Verifies that index matches the 'by_author' index used to create the
227 // by_author books store in the test database's version 1.
228 //
229 // The errorMessage is used if the assertions fail. It can state that the
230 // IndexedDB implementation being tested is incorrect, or that the testing code
231 // is using it incorrectly.
232 const checkAuthorIndexContents = (testCase, index, errorMessage) => {
233 const request = index.get(BOOKS_RECORD_DATA[2].author);
234 const eventWatcher = requestWatcher(testCase, request);
235 return eventWatcher.wait_for('success').then(() => {
236 const result = request.result;
237 assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
238 assert_equals(result.title, BOOKS_RECORD_DATA[2].title, errorMessage);
239 });
240 };
241
242 // Verifies that an index matches the 'by_title' index used to create the books
243 // store in the test database's version 1.
244 //
245 // The errorMessage is used if the assertions fail. It can state that the
246 // IndexedDB implementation being tested is incorrect, or that the testing code
247 // is using it incorrectly.
248 const checkTitleIndexContents = (testCase, index, errorMessage) => {
249 const request = index.get(BOOKS_RECORD_DATA[2].title);
250 const eventWatcher = requestWatcher(testCase, request);
251 return eventWatcher.wait_for('success').then(() => {
252 const result = request.result;
253 assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
254 assert_equals(result.author, BOOKS_RECORD_DATA[2].author, errorMessage);
255 });
256 };
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/LayoutTests/storage/indexeddb/upgrade-transaction-lifecycle-backend-aborted.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698