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

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: Fixed compilation errors on Windows and no-DCHECKs. 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>
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) {
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)) {
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');
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 function cloningTest(label, descriptors) {
dmurph 2017/05/04 22:27:07 descriptors -> valueDescriptors
pwnall 2017/05/11 23:54:23 Done. I also added a comment here that briefly exp
128 promise_test(testCase => {
129 return createDatabase(testCase, (database, transaction) => {
130 const store = database.createObjectStore('test-store', { keyPath: null });
131 for (let i = 0; i < descriptors.length; ++i) {
132 store.put(createValue(descriptors[i]), i);
133 }
134 }).then(database => {
135 const transaction = database.transaction(['test-store'], 'readonly');
136 const store = transaction.objectStore('test-store');
137 const subChecks = [];
138 let resultIndex = 0;
139 for (let i = 0; i < descriptors.length; ++i) {
140 subChecks.push(new Promise((resolve, reject) => {
141 const requestIndex = i;
142 const request = store.get(requestIndex);
143 request.onerror =
144 testCase.step_func(() => { reject(request.error); });
145 request.onsuccess = testCase.step_func(() => {
146 assert_equals(
147 resultIndex, requestIndex,
148 'IDBRequest success events should be fired in request order');
149 ++resultIndex;
150 resolve(checkValue(
151 testCase, request.result, descriptors[requestIndex]));
152 });
153 }));
154 }
155 return Promise.all(subChecks);
156 });
157 }, label);
158 }
159
160 cloningTest('small typed array', [
161 { type: 'buffer', size: 64, seed: 1 },
162 ]);
163
164 cloningTest('large typed array', [
165 { type: 'buffer', size: wrapThreshold, seed: 1 },
166 ])
167
168 cloningTest('blob', [
169 { type: 'blob', size: wrapThreshold, seed: 1 },
170 ]);
171
172 cloningTest('blob with small typed array', [
173 {
174 blob: { type: 'blob', size: wrapThreshold, seed: 1 },
175 buffer: { type: 'buffer', size: 64, seed: 2 },
176 },
177 ]);
178
179 cloningTest('blob with large typed array', [
180 {
181 blob: { type: 'blob', size: wrapThreshold, seed: 1 },
182 buffer: { type: 'buffer', size: wrapThreshold, seed: 2 },
183 },
184 ]);
185
186 cloningTest('blob array', [
187 [
188 { type: 'blob', size: wrapThreshold, seed: 1 },
189 { type: 'blob', size: wrapThreshold, seed: 2 },
190 { type: 'blob', size: wrapThreshold, seed: 3 },
191 ],
192 ]);
193
194 cloningTest('array of blobs and small typed arrays', [
195 [
196 { type: 'blob', size: wrapThreshold, seed: 1 },
197 { type: 'buffer', size: 64, seed: 2 },
198 { type: 'blob', size: wrapThreshold, seed: 3 },
199 { type: 'buffer', size: 64, seed: 4 },
200 { type: 'blob', size: wrapThreshold, seed: 5 },
201 ],
202 ]);
203
204 cloningTest('array of blobs and large typed arrays', [
205 [
206 { type: 'blob', size: wrapThreshold, seed: 1 },
207 { type: 'buffer', size: wrapThreshold, seed: 2 },
208 { type: 'blob', size: wrapThreshold, seed: 3 },
209 { type: 'buffer', size: wrapThreshold, seed: 4 },
210 { type: 'blob', size: wrapThreshold, seed: 5 },
211 ],
212 ]);
213
214 cloningTest('object with blobs and large typed arrays', [
215 {
216 blob: { type: 'blob', size: wrapThreshold, seed: 1 },
217 more: [
218 { type: 'buffer', size: wrapThreshold, seed: 2 },
219 { type: 'blob', size: wrapThreshold, seed: 3 },
220 { type: 'buffer', size: wrapThreshold, seed: 4 },
221 ],
222 blob2: { type: 'blob', size: wrapThreshold, seed: 5 },
223 },
224 ]);
225
226 cloningTest('multiple requests of objects with blobs and large typed arrays', [
227 {
228 blob: { type: 'blob', size: wrapThreshold, seed: 1 },
229 more: [
230 { type: 'buffer', size: wrapThreshold, seed: 2 },
231 { type: 'blob', size: wrapThreshold, seed: 3 },
232 { type: 'buffer', size: wrapThreshold, seed: 4 },
233 ],
234 blob2: { type: 'blob', size: wrapThreshold, seed: 5 },
235 },
236 [
237 { type: 'blob', size: wrapThreshold, seed: 6 },
238 { type: 'buffer', size: wrapThreshold, seed: 7 },
239 { type: 'blob', size: wrapThreshold, seed: 8 },
240 { type: 'buffer', size: wrapThreshold, seed: 9 },
241 { type: 'blob', size: wrapThreshold, seed: 10 },
242 ],
243 {
244 data: [
245 { type: 'blob', size: wrapThreshold, seed: 11 },
246 { type: 'buffer', size: wrapThreshold, seed: 12 },
247 { type: 'blob', size: wrapThreshold, seed: 13 },
248 { type: 'buffer', size: wrapThreshold, seed: 14 },
249 { type: 'blob', size: wrapThreshold, seed: 15 },
250 ],
251 },
252 [
253 { type: 'blob', size: wrapThreshold, seed: 16 },
254 { type: 'buffer', size: wrapThreshold, seed: 17 },
255 { type: 'blob', size: wrapThreshold, seed: 18 },
256 { type: 'buffer', size: wrapThreshold, seed: 19 },
257 { type: 'blob', size: wrapThreshold, seed: 20 },
258 ],
259 ]);
260
261 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698