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

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: Trim blank lines. Created 4 years 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 'use strict';
2
3 // Returns an IndexedDB database name likely to be unique to the test case.
4 const databaseName = testCase => {
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.
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
54 // We wrap IDBTransaction.abort so we can set up the correct event
55 // listeners and expectations if the test chooses to abort the
56 // versionchange transaction.
57 const transactionAbort = transaction.abort.bind(transaction);
58 transaction.abort = () => {
59 transaction._willBeAborted();
60 transactionAbort();
61 }
62 transaction._willBeAborted = () => {
63 request.onerror = event => {
64 event.preventDefault();
65 resolve(event);
66 };
67 request.onsuccess = () => reject(new Error(
68 'indexedDB.open should not succeed for an aborted versionchange ' +
69 'transaction'));
70 shouldBeAborted = true;
71 }
72
73 migrationCallback(database, transaction, request);
74 if (!shouldBeAborted) {
75 request.onerror = null;
76 request.onsuccess = null;
77 resolve(requestWatcher(testCase, request).wait_for('success'));
78 }
79 });
80 request.onerror = event => reject(event.target.error);
81 request.onsuccess = () => reject(new Error(
82 'indexedDB.open should not succeed without creating a ' +
83 'versionchange transaction'));
84 }).then(event => event.target.result || event.target.error);
85 };
86
87 // Creates an IndexedDB database whose name is unique for the test case.
88 //
89 // setupCallback will be called during a versionchange transaction, and will be
90 // given the created database, the versionchange transaction, and the database
91 // open request.
92 //
93 // Returns a promise that resolves to an IndexedDB database. The caller must
94 // close the database.
95 const createDatabase = (testCase, setupCallback) => {
96 return createNamedDatabase(testCase, databaseName(testCase), setupCallback);
97 };
98
99 // Creates an IndexedDB database.
100 //
101 // setupCallback will be called during a versionchange transaction, and will be
102 // given the created database, the versionchange transaction, and the database
103 // open request.
104 //
105 // Returns a promise that resolves to an IndexedDB database. The caller must
106 // close the database.
107 const createNamedDatabase = (testCase, databaseName, setupCallback) => {
108 const request = indexedDB.deleteDatabase(databaseName);
109 const eventWatcher = requestWatcher(testCase, request);
110
111 return eventWatcher.wait_for('success').then(event =>
112 migrateNamedDatabase(testCase, databaseName, 1, setupCallback));
113 };
114
115 // Opens an IndexedDB database without performing schema changes.
116 //
117 // The given version number must match the database's current version.
118 //
119 // Returns a promise that resolves to an IndexedDB database. The caller must
120 // close the database.
121 const openDatabase = (testCase, version) => {
122 return openNamedDatabase(testCase, databaseName(testCase), version);
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 openNamedDatabase = (testCase, databaseName, version) => {
132 const request = indexedDB.open(databaseName, version);
133 const eventWatcher = requestWatcher(testCase, request);
134 return eventWatcher.wait_for('success').then(event => event.target.result);
135 }
136
137 // The data in the 'books' object store records in the first example of the
138 // IndexedDB specification.
139 const BOOKS_RECORD_DATA = [
140 { title: 'Quarry Memories', author: 'Fred', isbn: 123456 },
141 { title: 'Water Buffaloes', author: 'Fred', isbn: 234567 },
142 { title: 'Bedrock Nights', author: 'Barney', isbn: 345678 },
143 ];
144
145 // Creates a 'books' object store whose contents closely resembles the first
146 // example in the IndexedDB specification.
147 const createBooksStore = (testCase, database) => {
148 const store = database.createObjectStore('books',
149 { keyPath: 'isbn', autoIncrement: true });
150 store.createIndex('by_author', 'author');
151 store.createIndex('by_title', 'title', { unique: true });
152 for (let record of BOOKS_RECORD_DATA)
153 store.put(record);
154 return store;
155 };
156
157 // Creates a 'not_books' object store used to test renaming into existing or
158 // deleted store names.
159 const createNotBooksStore = (testCase, database) => {
160 const store = database.createObjectStore('not_books');
161 store.createIndex('not_by_author', 'author');
162 store.createIndex('not_by_title', 'title', { unique: true });
163 return store;
164 };
165
166 // Verifies that an object store's indexes match the indexes used to create the
167 // books store in the test database's version 1.
168 //
169 // The errorMessage is used if the assertions fail. It can state that the
170 // IndexedDB implementation being tested is incorrect, or that the testing code
171 // is using it incorrectly.
172 const checkStoreIndexes = (testCase, store, errorMessage) => {
173 assert_array_equals(
174 store.indexNames, ['by_author', 'by_title'], errorMessage);
175 const authorIndex = store.index('by_author');
176 const titleIndex = store.index('by_title');
177 return Promise.all([
178 checkAuthorIndexContents(testCase, authorIndex, errorMessage),
179 checkTitleIndexContents(testCase, titleIndex, errorMessage),
180 ]);
181 };
182
183 // Verifies that an object store's key generator is in the same state as the
184 // key generator created for the books store in the test database's version 1.
185 //
186 // The errorMessage is used if the assertions fail. It can state that the
187 // IndexedDB implementation being tested is incorrect, or that the testing code
188 // is using it incorrectly.
189 const checkStoreGenerator = (testCase, store, expectedKey, errorMessage) => {
190 const request = store.put(
191 { title: 'Bedrock Nights ' + expectedKey, author: 'Barney' });
192 const eventWatcher = requestWatcher(testCase, request);
193 return eventWatcher.wait_for('success').then(() => {
194 const result = request.result;
195 assert_equals(result, expectedKey, errorMessage);
196 });
197 };
198
199 // Verifies that an object store's contents matches the contents used to create
200 // the books store in the test database's version 1.
201 //
202 // The errorMessage is used if the assertions fail. It can state that the
203 // IndexedDB implementation being tested is incorrect, or that the testing code
204 // is using it incorrectly.
205 const checkStoreContents = (testCase, store, errorMessage) => {
206 const request = store.get(123456);
207 const eventWatcher = requestWatcher(testCase, request);
208 return eventWatcher.wait_for('success').then(() => {
209 const result = request.result;
210 assert_equals(result.isbn, BOOKS_RECORD_DATA[0].isbn, errorMessage);
211 assert_equals(result.author, BOOKS_RECORD_DATA[0].author, errorMessage);
212 assert_equals(result.title, BOOKS_RECORD_DATA[0].title, errorMessage);
213 });
214 };
215
216 // Verifies that index matches the 'by_author' index used to create the
217 // by_author books store in the test database's version 1.
218 //
219 // The errorMessage is used if the assertions fail. It can state that the
220 // IndexedDB implementation being tested is incorrect, or that the testing code
221 // is using it incorrectly.
222 const checkAuthorIndexContents = (testCase, index, errorMessage) => {
223 const request = index.get(BOOKS_RECORD_DATA[2].author);
224 const eventWatcher = requestWatcher(testCase, request);
225 return eventWatcher.wait_for('success').then(() => {
226 const result = request.result;
227 assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
228 assert_equals(result.title, BOOKS_RECORD_DATA[2].title, errorMessage);
229 });
230 };
231
232 // Verifies that an index matches the 'by_title' index used to create the books
233 // store in the test database's version 1.
234 //
235 // The errorMessage is used if the assertions fail. It can state that the
236 // IndexedDB implementation being tested is incorrect, or that the testing code
237 // is using it incorrectly.
238 const checkTitleIndexContents = (testCase, index, errorMessage) => {
239 const request = index.get(BOOKS_RECORD_DATA[2].title);
240 const eventWatcher = requestWatcher(testCase, request);
241 return eventWatcher.wait_for('success').then(() => {
242 const result = request.result;
243 assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
244 assert_equals(result.author, BOOKS_RECORD_DATA[2].author, errorMessage);
245 });
246 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698