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

Side by Side Diff: third_party/WebKit/LayoutTests/external/wpt/IndexedDB/large-nested-cloning.html

Issue 2822453003: Wrap large IndexedDB values into Blobs before writing to LevelDB. (Closed)
Patch Set: Addressed last round of feedback. 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
« no previous file with comments | « no previous file | third_party/WebKit/LayoutTests/external/wpt/IndexedDB/large-requests-abort.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 <!doctype html>
2 <meta charset="utf8">
3 <meta name="timeout" content="long">
4 <title>IndexedDB: large nested objects are cloned correctly</title>
5 <link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
6 <link rel="author" href="pwnall@chromium.org" title="Victor Costan">
7 <script src="/resources/testharness.js"></script>
8 <script src="/resources/testharnessreport.js"></script>
9 <script src="support-promises.js"></script>
10 <script>
11 'use strict';
12
13 // Should be large enough to trigger large value handling in the IndexedDB
14 // engines that have special code paths for large values.
15 const wrapThreshold = 128 * 1024;
16
17 // Returns an IndexedDB value created from a descriptor.
18 //
19 // See the bottom of the file for descriptor samples.
20 function createValue(descriptor) {
21 if (typeof(descriptor) != 'object')
22 return descriptor;
23
24 if (Array.isArray(descriptor))
25 return descriptor.map((element) => createValue(element));
26
27 if (!descriptor.hasOwnProperty('type')) {
28 const value = {};
29 for (let property of Object.getOwnPropertyNames(descriptor))
30 value[property] = createValue(descriptor[property]);
31 return value;
32 }
33
34 switch (descriptor.type) {
35 case 'blob':
36 return new Blob(
37 [largeValue(descriptor.size, descriptor.seed)],
38 { type: descriptor.mimeType });
39 case 'buffer':
40 return largeValue(descriptor.size, descriptor.seed);
41 }
42 }
43
44 // Checks an IndexedDB value against a descriptor.
45 //
46 // Returns a Promise that resolves if the value passes the check.
47 //
48 // See the bottom of the file for descriptor samples.
49 function checkValue(testCase, value, descriptor) {
50 if (typeof(descriptor) != 'object') {
51 assert_equals(
52 descriptor, value,
53 'IndexedDB result should match put() argument');
54 return Promise.resolve();
55 }
56
57 if (Array.isArray(descriptor)) {
58 assert_true(
59 Array.isArray(value),
60 'IndexedDB result type should match put() argument');
61 assert_equals(
62 descriptor.length, value.length,
63 'IndexedDB result array size should match put() argument');
64
65 const subChecks = [];
66 for (let i = 0; i < descriptor.length; ++i)
67 subChecks.push(checkValue(testCase, value[i], descriptor[i]));
68 return Promise.all(subChecks);
69 }
70
71 if (!descriptor.hasOwnProperty('type')) {
72 assert_array_equals(
73 Object.getOwnPropertyNames(value).sort(),
74 Object.getOwnPropertyNames(descriptor).sort(),
75 'IndexedDB result object properties should match put() argument');
76 const subChecks = [];
77 return Promise.all(Object.getOwnPropertyNames(descriptor).map(property =>
78 checkValue(testCase, value[property], descriptor[property])));
79 }
80
81 switch (descriptor.type) {
82 case 'blob':
83 assert_class_string(
84 value, 'Blob',
85 'IndexedDB result class should match put() argument');
86 assert_equals(
87 descriptor.mimeType, value.type,
88 'IndexedDB result Blob MIME type should match put() argument');
89 assert_equals(descriptor.size, value.size, 'incorrect Blob size');
90 return new Promise((resolve, reject) => {
91 const reader = new FileReader();
92 reader.onloadend = testCase.step_func(() => {
93 if (reader.error) {
94 reject(reader.error);
95 return;
96 }
97 const view = new Uint8Array(reader.result);
98 assert_equals(
99 view.join(','),
100 largeValue(descriptor.size, descriptor.seed).join(','),
101 'IndexedDB result Blob content should match put() argument');
102 resolve();
103 });
104 reader.readAsArrayBuffer(value);
105 });
106
107 case 'buffer':
108 assert_class_string(
109 value, 'Uint8Array',
110 'IndexedDB result type should match put() argument');
111 assert_equals(
112 value.join(','),
113 largeValue(descriptor.size, descriptor.seed).join(','),
114 'IndexedDB result typed array content should match put() argument');
115 return Promise.resolve();
116 }
117 }
118
119 // Performs a series of put()s and verifies that get()s and getAll() match.
120 //
121 // Each element of the valueDescriptors array is fed into createValue(), and the
122 // resulting value is written to IndexedDB via a put() request. After the writes
123 // complete, the values are read in the same order in which they were written.
124 // Last, all the results are read one more time via a getAll().
125 //
126 // The test verifies that the get() / getAll() results match the arguments to
127 // put() and that the order in which the get() result events are fired matches
128 // the order of the get() requests.
129 function cloningTest(label, valueDescriptors) {
130 promise_test(testCase => {
131 return createDatabase(testCase, (database, transaction) => {
132 const store = database.createObjectStore('test-store');
133 for (let i = 0; i < valueDescriptors.length; ++i) {
134 store.put(createValue(valueDescriptors[i]), i);
135 }
136 }).then(database => {
137 const transaction = database.transaction(['test-store'], 'readonly');
138 const store = transaction.objectStore('test-store');
139 const subChecks = [];
140 let resultIndex = 0;
141 for (let i = 0; i < valueDescriptors.length; ++i) {
142 subChecks.push(new Promise((resolve, reject) => {
143 const requestIndex = i;
144 const request = store.get(requestIndex);
145 request.onerror =
146 testCase.step_func(() => { reject(request.error); });
147 request.onsuccess = testCase.step_func(() => {
148 assert_equals(
149 resultIndex, requestIndex,
150 'IDBRequest success events should be fired in request order');
151 ++resultIndex;
152 resolve(checkValue(
153 testCase, request.result, valueDescriptors[requestIndex]));
154 });
155 }));
156 }
157
158 subChecks.push(new Promise((resolve, reject) => {
159 const requestIndex = valueDescriptors.length;
160 const request = store.getAll();
161 request.onerror =
162 testCase.step_func(() => { reject(request.error); });
163 request.onsuccess = testCase.step_func(() => {
164 assert_equals(
165 resultIndex, requestIndex,
166 'IDBRequest success events should be fired in request order');
167 ++resultIndex;
168 resolve(checkValue(
169 testCase, request.result, valueDescriptors));
170 });
171 }));
172
173 return Promise.all(subChecks);
174 });
175 }, label);
176 }
177
178 cloningTest('small typed array', [
179 { type: 'buffer', size: 64, seed: 1 },
180 ]);
181
182 cloningTest('large typed array', [
183 { type: 'buffer', size: wrapThreshold, seed: 1 },
184 ])
185
186 cloningTest('blob', [
187 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-1', seed: 1 },
188 ]);
189
190 cloningTest('blob with small typed array', [
191 {
192 blob: { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-01',
193 seed: 1 },
194 buffer: { type: 'buffer', size: 64, seed: 2 },
195 },
196 ]);
197
198 cloningTest('blob with large typed array', [
199 {
200 blob: { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-01',
201 seed: 1 },
202 buffer: { type: 'buffer', size: wrapThreshold, seed: 2 },
203 },
204 ]);
205
206 cloningTest('blob array', [
207 [
208 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-1', seed: 1 },
209 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-2', seed: 2 },
210 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-3', seed: 3 },
211 ],
212 ]);
213
214 cloningTest('array of blobs and small typed arrays', [
215 [
216 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-01', seed: 1 },
217 { type: 'buffer', size: 64, seed: 2 },
218 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-03', seed: 3 },
219 { type: 'buffer', size: 64, seed: 4 },
220 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-05', seed: 5 },
221 ],
222 ]);
223
224 cloningTest('array of blobs and large typed arrays', [
225 [
226 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-01', seed: 1 },
227 { type: 'buffer', size: wrapThreshold, seed: 2 },
228 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-03', seed: 3 },
229 { type: 'buffer', size: wrapThreshold, seed: 4 },
230 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-05', seed: 5 },
231 ],
232 ]);
233
234 cloningTest('object with blobs and large typed arrays', [
235 {
236 blob: { type: 'blob', size: wrapThreshold,
237 mimeType: 'text/x-blink1', seed: 1 },
238 more: [
239 { type: 'buffer', size: wrapThreshold, seed: 2 },
240 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink3', seed: 3 },
241 { type: 'buffer', size: wrapThreshold, seed: 4 },
242 ],
243 blob2: { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink5',
244 seed: 5 },
245 },
246 ]);
247
248 cloningTest('multiple requests of objects with blobs and large typed arrays', [
249 {
250 blob: { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink1',
251 seed: 1 },
252 more: [
253 { type: 'buffer', size: wrapThreshold, seed: 2 },
254 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink3', seed: 3 },
255 { type: 'buffer', size: wrapThreshold, seed: 4 },
256 ],
257 blob2: { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink5',
258 seed: 5 },
259 },
260 [
261 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink06', seed: 6 },
262 { type: 'buffer', size: wrapThreshold, seed: 7 },
263 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink08', seed: 8 },
264 { type: 'buffer', size: wrapThreshold, seed: 9 },
265 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink10', seed: 10 },
266 ],
267 {
268 data: [
269 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-11',
270 seed: 11 },
271 { type: 'buffer', size: wrapThreshold, seed: 12 },
272 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-13',
273 seed: 13 },
274 { type: 'buffer', size: wrapThreshold, seed: 14 },
275 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-15',
276 seed: 15 },
277 ],
278 },
279 [
280 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink16', seed: 16 },
281 { type: 'buffer', size: wrapThreshold, seed: 17 },
282 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink18', seed: 18 },
283 { type: 'buffer', size: wrapThreshold, seed: 19 },
284 { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink20', seed: 20 },
285 ],
286 ]);
287
288 </script>
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/LayoutTests/external/wpt/IndexedDB/large-requests-abort.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698