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

Side by Side Diff: third_party/WebKit/LayoutTests/external/wpt/IndexedDB/request-event-ordering.html

Issue 2822453003: Wrap large IndexedDB values into Blobs before writing to LevelDB. (Closed)
Patch Set: WIP: Getting IDBRequestTest.EventsAfterStopping to pass. Created 3 years, 7 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 <meta charset="utf8">
3 <title>IndexedDB: request result events are delivered in order</title>
4 <link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
5 <link rel="author" href="pwnall@chromium.org" title="Victor Costan">
6 <script src="/resources/testharness.js"></script>
7 <script src="/resources/testharnessreport.js"></script>
8 <script src="support-promises.js"></script>
9 <script>
10 'use strict';
11
12 // Should be large enough to trigger value wrapping in the IndexedDB engines
13 // that implement wrapping.
14 const wrapThreshold = 128 * 1024;
15
16 // Returns an Uint8Array with pseudorandom data.
17 function largeValue(size, seed) {
jsbell 2017/05/15 23:37:37 Move this to support.js or support-promises.js ?
pwnall 2017/05/19 18:27:33 Done.
18 const buffer = new Uint8Array(size);
19
20 // 32-bit xorshift - the seed can't be zero
21 let state = 1000 + seed;
22
23 for (let i = 0; i < size; ++i) {
24 state ^= state << 13;
25 state ^= state >> 17;
26 state ^= state << 5;
27 buffer[i] = state & 0xff;
28 }
29
30 return buffer;
31 }
32
33 function populateStore(store) {
34 store.put({id: 1, key: 'k1', value: largeValue(wrapThreshold, 1) });
35 store.put({id: 2, key: 'k2', value: ['small-2'] });
36 store.put({id: 3, key: 'k3', value: largeValue(wrapThreshold, 3) });
37 store.put({id: 4, key: 'k4', value: ['small-4'] });
38 }
39
40 // Assigns cursor indexes for operations that require open cursors.
41 //
42 // Returns the number of open cursors required to perform all operations.
43 function assignCursors(operations) {
44 return cursorCount;
45 }
46
47 // Opens index cursors for operations that require open cursors.
48 //
49 // onsuccess is called if all cursors are opened successfully. Otherwise,
50 // onerror will be called at least once.
51 function openCursors(testCase, index, operations, onerror, onsuccess) {
52 let pendingCursors = 0;
53
54 nextOperation:
55 for (let operation of operations) {
56 const opcode = operation[0];
57 const primaryKey = operation[1];
58 let request;
59 switch (opcode) {
60 case 'continue':
61 request = index.openCursor(
62 IDBKeyRange.lowerBound(`k${primaryKey - 1}`));
63 break;
64 case 'continue-empty':
65 // k4 is the last key in the data set, so calling continue() will get
66 // the cursor past the end of the store.
67 request = index.openCursor(IDBKeyRange.lowerBound('k4'));
68 break;
69 default:
70 continue nextOperation;
jsbell 2017/05/15 23:37:37 This label doesn't appear necessary
pwnall 2017/05/19 18:27:33 Done.
71 }
72
73 operation[2] = request;
74 ++pendingCursors;
75
76 request.onsuccess = testCase.step_func(() => {
77 --pendingCursors;
78 if (!pendingCursors)
79 onsuccess();
80 });
81 request.onerror = testCase.step_func(onerror);
82 }
83
84 if (!pendingCursors)
85 onsuccess();
86 }
87
88 function doOperation(testCase, store, index, operation, requestId, results) {
89 const opcode = operation[0];
90 const primaryKey = operation[1];
91 const cursor = operation[2];
92
93 return new Promise((resolve, reject) => {
94 let request;
95 switch (opcode) {
96 case 'put': // Tests returning a primary key.
97 request = store.put(
98 { key: `k${primaryKey}`, value: [`small-${primaryKey}`] });
99 break;
100 case 'get': // Tests returning a value.
101 case 'get-empty': // Tests returning undefined.
102 request = store.get(primaryKey);
103 break;
104 case 'error': // Tests returning an error.
105 request = store.put(
106 { key: `k${primaryKey}`, value: [`small-${primaryKey}`] });
107 request.onerror = testCase.step_func(event => {
108 results.push([requestId, request.error]);
109 resolve();
110 event.preventDefault();
111 });
112 request.onsuccess = testCase.step_func(() => {
113 reject(new Error('put with duplicate primary key succeded'));
114 });
115 break;
116 case 'continue': // Tests returning a key, primary key, and value.
117 request = cursor;
118 cursor.result.continue();
119 request.onsuccess = testCase.step_func(() => {
120 const result = request.result;
121 results.push(
122 [requestId, result.key, result.primaryKey, result.value]);
123 resolve();
124 });
125 request.onerror = null;
126 break;
127 case 'open': // Tests returning a cursor, key, primary key, and value.
128 request = index.openCursor(IDBKeyRange.lowerBound(`k${primaryKey}`));
129 request.onsuccess = testCase.step_func(() => {
130 const result = request.result;
131 results.push(
132 [requestId, result.key, result.primaryKey, result.value]);
133 resolve();
134 });
135 break;
136 case 'continue-empty': // Tests returning a null result.
137 request = cursor;
138 cursor.result.continue();
139 request.onsuccess = testCase.step_func(() => {
140 results.push([requestId, request.result]);
141 resolve();
142 });
143 request.onerror = null;
144 break;
145 case 'open-empty': // Tests returning a null cursor.
146 request = index.openCursor(IDBKeyRange.lowerBound(`k${primaryKey}`));
147 request.onsuccess = testCase.step_func(() => {
148 const result = request.result;
149 results.push([requestId, request.result]);
150 resolve();
151 });
152 break;
153 case 'count': // Tests returning a numeric result.
154 request = index.count();
155 request.onsuccess = testCase.step_func(() => {
156 results.push([requestId, request.result]);
157 resolve();
158 });
159 break;
160 };
161
162 if (!request.onsuccess) {
163 request.onsuccess = testCase.step_func(() => {
164 results.push([requestId, request.result]);
165 resolve();
166 });
167 }
168 if (!request.onerror)
169 request.onerror = testCase.step_func(event => {
170 reject(request.error);
171 event.preventDefault();
172 });
173 });
174 }
175
176 function checkOperationResult(operation, result, requestId) {
177 const opcode = operation[0];
178 const primaryKey = operation[1];
179
180 const expectedValue = (primaryKey == 1 || primaryKey == 3) ?
181 largeValue(wrapThreshold, primaryKey) : [`small-${primaryKey}`];
182
183 const requestIndex = result[0];
184 assert_equals(
185 requestIndex, requestId, 'result event order should match request order');
186 switch (opcode) {
187 case 'put':
188 assert_equals(
189 result[1], primaryKey,
190 "put result should be the new object's primary key");
191 break;
192 case 'get':
193 assert_equals(
194 result[1].id, primaryKey,
195 'get result should match put value (primary key)');
196 assert_equals(
197 result[1].key, `k${primaryKey}`,
198 'get result should match put value (key)');
199 assert_equals(
200 result[1].value.join(','), expectedValue.join(','),
201 'get result should match put value (nested value)');
202 break;
203 case 'get-empty':
204 assert_equals(
205 result[1], undefined, 'get-empty result should be undefined');
206 break;
207 case 'error':
208 assert_equals(
209 result[1].name, 'ConstraintError',
210 'incorrect error from put with duplicate primary key');
211 break;
212 case 'continue':
213 case 'open':
214 assert_equals(
215 result[1], `k${primaryKey}`,
216 `${opcode} key should match the key in the put value`);
217 assert_equals(
218 result[2], primaryKey,
219 `${opcode} primary key should match the put value's primary key`);
220 assert_equals(
221 result[3].id, primaryKey,
222 `${opcode} value should match put value (primary key)`);
223 assert_equals(
224 result[3].key, `k${primaryKey}`,
225 `${opcode} value should match put value (key)`);
226 assert_equals(
227 result[3].value.join(','), expectedValue.join(','),
228 `${opcode} value should match put value (nested value)`);
229 break;
230 case 'continue-empty':
231 case 'open-empty':
232 assert_equals(result[1], null, `${opcode} result should be null`);
233 break;
234 }
235 }
236
237 function eventsTest(label, operations) {
238 promise_test(testCase => {
239 return createDatabase(testCase, (database, transaction) => {
240 const store = database.createObjectStore(
241 'test-store', { autoIncrement: true, keyPath: 'id' });
242 store.createIndex('test-index', 'key', { unique: true });
243 populateStore(store);
244 }).then(database => {
245 const transaction = database.transaction(['test-store'], 'readwrite');
246 const store = transaction.objectStore('test-store');
247 const index = store.index('test-index');
248 return new Promise((resolve, reject) => {
249 openCursors(testCase, index, operations, reject, () => {
250 const results = [];
251 const promises = [];
252 for (let i = 0; i < operations.length; ++i) {
253 const promise = doOperation(
254 testCase, store, index, operations[i], i, results);
255 promises.push(promise);
256 };
257 resolve(Promise.all(promises).then(() => results));
258 });
259 });
260 }).then(results => {
261 assert_equals(
262 results.length, operations.length,
263 'Promise.all should resolve after all sub-promises resolve');
264 for (let i = 0; i < operations.length; ++i)
265 checkOperationResult(operations[i], results[i], i);
266 });
267 }, label);
268 }
269
270 eventsTest('small values', [
271 ['get', 2],
272 ['count', 4],
273 ['continue-empty', null],
274 ['get-empty', 5],
275 ['put', 5],
276 ['open', 2],
277 ['continue', 2],
278 ['get', 4],
279 ['get-empty', 6],
280 ['count', 5],
281 ['put', 6],
282 ['error', 3],
283 ['continue', 4],
284 ['count', 6],
285 ['get-empty', 7],
286 ['open', 4],
287 ['open-empty', 7],
288 ]);
289
290 eventsTest('large values', [
291 ['open', 1],
292 ['get', 1],
293 ['get', 3],
294 ['continue', 3],
295 ['open', 3],
296 ]);
297
298 eventsTest('large value followed by small values', [
299 ['get', 1],
300 ['open', 2],
301 ['continue-empty', null],
302 ['get', 2],
303 ['get-empty', 5],
304 ['count', 4],
305 ['continue-empty', null],
306 ['open-empty', 5],
307 ['put', 5],
308 ['error', 1],
309 ['continue', 2],
310 ['get-empty', 6],
311 ]);
312
313 eventsTest('large values mixed with small values', [
314 ['get', 1],
315 ['get', 2],
316 ['get-empty', 5],
317 ['count', 4],
318 ['continue-empty', null],
319 ['open', 1],
320 ['continue', 2],
321 ['open-empty', 5],
322 ['open', 2],
323 ['continue-empty', null],
324 ['put', 5],
325 ['get', 3],
326 ['count', 5],
327 ['get-empty', 6],
328 ['continue', 3],
329 ['open-empty', 6],
330 ['put', 6],
331 ['error', 1],
332 ['continue', 2],
333 ['open', 4],
334 ['get-empty', 7],
335 ['continue', 3],
336 ['error', 3],
337 ['count', 6],
338 ]);
339
340 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698