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

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: 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: large nested objects are cloned correctly</title>
jsbell 2017/05/15 23:37:37 aside: I wonder if we should create a subdir for w
pwnall 2017/05/19 18:27:33 That sounds like a very reasonable proposal. So, w
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>
jsbell 2017/05/15 23:37:37 Since this test involves multiple sequential trans
pwnall 2017/05/19 18:27:33 Done. Both tests can probably use that tag. Thank
10 'use strict';
11
12 // Should be large enough to trigger value wrapping in the IndexedDB engines
jsbell 2017/05/15 23:37:37 Maybe explain "wrapping" or say "that have special
pwnall 2017/05/19 18:27:33 Done.
13 // that implement wrapping.
14 const wrapThreshold = 128 * 1024;
15
16 // Returns an Uint8Array with pseudorandom data.
17 function largeValue(size, seed) {
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 // Returns an IndexedDB value created from a descriptor.
34 //
35 // See the bottom of the file for descriptor samples.
36 function createValue(descriptor) {
37 if (typeof(descriptor) != 'object')
38 return descriptor;
39
40 if (Array.isArray(descriptor))
41 return descriptor.map((element) => createValue(element));
42
43 if (!descriptor.hasOwnProperty('type')) {
44 const value = {};
45 for (let property of Object.getOwnPropertyNames(descriptor))
46 value[property] = createValue(descriptor[property]);
47 return value;
48 }
49
50 switch (descriptor.type) {
51 case 'blob':
52 return new Blob(
53 [largeValue(descriptor.size, descriptor.seed)],
54 { type: descriptor.type });
55 case 'buffer':
56 return largeValue(descriptor.size, descriptor.seed);
57 }
58 }
59
60
61 // Checks an IndexedDB value against a descriptor.
62 //
63 // Returns a Promise that resolves if the value passes the check.
64 //
65 // See the bottom of the file for descriptor samples.
66 function checkValue(testCase, value, descriptor) {
67 if (typeof(descriptor) != 'object') {
68 assert_equals(descriptor, value, 'incorrect value');
69 return Promise.resolve();
70 }
71
72 if (Array.isArray(descriptor)) {
73 assert_true(Array.isArray(value), 'incorrect value type');
74 assert_equals(descriptor.length, value.length, 'incorrect array size');
75
76 const subChecks = [];
77 for (let i = 0; i < descriptor.length; ++i)
78 subChecks.push(checkValue(testCase, value[i], descriptor[i]));
79 return Promise.all(subChecks);
80 }
81
82 if (!descriptor.hasOwnProperty('type')) {
83 assert_array_equals(
84 Object.getOwnPropertyNames(value).sort(),
85 Object.getOwnPropertyNames(descriptor).sort(),
86 'incorrect object properties');
87 const subChecks = [];
88 for (let property of Object.getOwnPropertyNames(descriptor)) {
jsbell 2017/05/15 23:37:37 If you're feeling fancy, you could do this as: re
pwnall 2017/05/19 18:27:33 Done.
89 subChecks.push(
90 checkValue(testCase, value[property], descriptor[property]));
91 }
92 return Promise.all(subChecks);
93 }
94
95 switch (descriptor.type) {
96 case 'blob':
97 assert_class_string(value, 'Blob', 'incorrect value type');
jsbell 2017/05/15 23:37:37 nit: Word the message in terms of the *expected* o
pwnall 2017/05/19 18:27:33 Done.
98 assert_equals(descriptor.type, value.type, 'incorrect Blob type');
99 assert_equals(descriptor.size, value.size, 'incorrect Blob size');
100 return new Promise((resolve, reject) => {
101 const reader = new FileReader();
102 reader.onloadend = testCase.step_func(() => {
103 if (reader.error) {
104 reject(reader.error);
105 return;
106 }
107 const view = new Uint8Array(reader.result);
108 assert_equals(
109 view.join(','),
110 largeValue(descriptor.size, descriptor.seed).join(','),
111 'incorrect Blob content from IndexedDB');
112 resolve();
113 });
114 reader.readAsArrayBuffer(value);
115 });
116
117 case 'buffer':
118 assert_class_string(value, 'Uint8Array', 'incorrect value type');
119 assert_equals(
120 value.join(','),
121 largeValue(descriptor.size, descriptor.seed).join(','),
122 'incorrect typed array content');
123 return Promise.resolve();
124 }
125 }
126
127 // Test that performs a series of put()s and verifies that gets() match.
128 //
129 // Each element of the valueDescriptors array is fed into createValue(), and the
130 // resulting value is written to IndexedDB via a put() request. After the writes
131 // complete, the values are read in the same order in which they were written.
132 //
133 // The test verifies that the get() values match the arguments to put() and that
jsbell 2017/05/15 23:37:37 This tests get() but not getAll()
pwnall 2017/05/19 18:27:33 Done. Thanks, I don't know how I managed to miss t
134 // the order in which the get() result events are fired matches the order of the
135 // get() requests.
136 function cloningTest(label, valueDescriptors) {
137 promise_test(testCase => {
138 return createDatabase(testCase, (database, transaction) => {
139 const store = database.createObjectStore('test-store', { keyPath: null });
jsbell 2017/05/15 23:37:37 Why specify keyPath: null which is the default?
pwnall 2017/05/19 18:27:33 Done.
140 for (let i = 0; i < valueDescriptors.length; ++i) {
141 store.put(createValue(valueDescriptors[i]), i);
142 }
143 }).then(database => {
144 const transaction = database.transaction(['test-store'], 'readonly');
145 const store = transaction.objectStore('test-store');
146 const subChecks = [];
147 let resultIndex = 0;
148 for (let i = 0; i < valueDescriptors.length; ++i) {
149 subChecks.push(new Promise((resolve, reject) => {
150 const requestIndex = i;
151 const request = store.get(requestIndex);
152 request.onerror =
153 testCase.step_func(() => { reject(request.error); });
154 request.onsuccess = testCase.step_func(() => {
155 assert_equals(
156 resultIndex, requestIndex,
157 'IDBRequest success events should be fired in request order');
158 ++resultIndex;
159 resolve(checkValue(
160 testCase, request.result, valueDescriptors[requestIndex]));
161 });
162 }));
163 }
164 return Promise.all(subChecks);
165 });
166 }, label);
167 }
168
169 cloningTest('small typed array', [
170 { type: 'buffer', size: 64, seed: 1 },
171 ]);
172
173 cloningTest('large typed array', [
174 { type: 'buffer', size: wrapThreshold, seed: 1 },
175 ])
176
177 cloningTest('blob', [
178 { type: 'blob', size: wrapThreshold, seed: 1 },
179 ]);
180
181 cloningTest('blob with small typed array', [
182 {
183 blob: { type: 'blob', size: wrapThreshold, seed: 1 },
184 buffer: { type: 'buffer', size: 64, seed: 2 },
185 },
186 ]);
187
188 cloningTest('blob with large typed array', [
189 {
190 blob: { type: 'blob', size: wrapThreshold, seed: 1 },
191 buffer: { type: 'buffer', size: wrapThreshold, seed: 2 },
192 },
193 ]);
194
195 cloningTest('blob array', [
196 [
197 { type: 'blob', size: wrapThreshold, seed: 1 },
198 { type: 'blob', size: wrapThreshold, seed: 2 },
199 { type: 'blob', size: wrapThreshold, seed: 3 },
200 ],
201 ]);
202
203 cloningTest('array of blobs and small typed arrays', [
204 [
205 { type: 'blob', size: wrapThreshold, seed: 1 },
206 { type: 'buffer', size: 64, seed: 2 },
207 { type: 'blob', size: wrapThreshold, seed: 3 },
208 { type: 'buffer', size: 64, seed: 4 },
209 { type: 'blob', size: wrapThreshold, seed: 5 },
210 ],
211 ]);
212
213 cloningTest('array of blobs and large typed arrays', [
214 [
215 { type: 'blob', size: wrapThreshold, seed: 1 },
216 { type: 'buffer', size: wrapThreshold, seed: 2 },
217 { type: 'blob', size: wrapThreshold, seed: 3 },
218 { type: 'buffer', size: wrapThreshold, seed: 4 },
219 { type: 'blob', size: wrapThreshold, seed: 5 },
220 ],
221 ]);
222
223 cloningTest('object with blobs and large typed arrays', [
224 {
225 blob: { type: 'blob', size: wrapThreshold, seed: 1 },
226 more: [
227 { type: 'buffer', size: wrapThreshold, seed: 2 },
228 { type: 'blob', size: wrapThreshold, seed: 3 },
229 { type: 'buffer', size: wrapThreshold, seed: 4 },
230 ],
231 blob2: { type: 'blob', size: wrapThreshold, seed: 5 },
232 },
233 ]);
234
235 cloningTest('multiple requests of objects with blobs and large typed arrays', [
236 {
237 blob: { type: 'blob', size: wrapThreshold, seed: 1 },
238 more: [
239 { type: 'buffer', size: wrapThreshold, seed: 2 },
240 { type: 'blob', size: wrapThreshold, seed: 3 },
241 { type: 'buffer', size: wrapThreshold, seed: 4 },
242 ],
243 blob2: { type: 'blob', size: wrapThreshold, seed: 5 },
244 },
245 [
246 { type: 'blob', size: wrapThreshold, seed: 6 },
247 { type: 'buffer', size: wrapThreshold, seed: 7 },
248 { type: 'blob', size: wrapThreshold, seed: 8 },
249 { type: 'buffer', size: wrapThreshold, seed: 9 },
250 { type: 'blob', size: wrapThreshold, seed: 10 },
251 ],
252 {
253 data: [
254 { type: 'blob', size: wrapThreshold, seed: 11 },
255 { type: 'buffer', size: wrapThreshold, seed: 12 },
256 { type: 'blob', size: wrapThreshold, seed: 13 },
257 { type: 'buffer', size: wrapThreshold, seed: 14 },
258 { type: 'blob', size: wrapThreshold, seed: 15 },
259 ],
260 },
261 [
262 { type: 'blob', size: wrapThreshold, seed: 16 },
263 { type: 'buffer', size: wrapThreshold, seed: 17 },
264 { type: 'blob', size: wrapThreshold, seed: 18 },
265 { type: 'buffer', size: wrapThreshold, seed: 19 },
266 { type: 'blob', size: wrapThreshold, seed: 20 },
267 ],
268 ]);
269
270 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698