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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/LayoutTests/external/wpt/IndexedDB/large-nested-cloning.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/large-nested-cloning.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/large-nested-cloning.html
new file mode 100644
index 0000000000000000000000000000000000000000..c955f0247dcc3fdcc0076347851f79ee3f7505d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/large-nested-cloning.html
@@ -0,0 +1,288 @@
+<!doctype html>
+<meta charset="utf8">
+<meta name="timeout" content="long">
+<title>IndexedDB: large nested objects are cloned correctly</title>
+<link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+'use strict';
+
+// Should be large enough to trigger large value handling in the IndexedDB
+// engines that have special code paths for large values.
+const wrapThreshold = 128 * 1024;
+
+// Returns an IndexedDB value created from a descriptor.
+//
+// See the bottom of the file for descriptor samples.
+function createValue(descriptor) {
+ if (typeof(descriptor) != 'object')
+ return descriptor;
+
+ if (Array.isArray(descriptor))
+ return descriptor.map((element) => createValue(element));
+
+ if (!descriptor.hasOwnProperty('type')) {
+ const value = {};
+ for (let property of Object.getOwnPropertyNames(descriptor))
+ value[property] = createValue(descriptor[property]);
+ return value;
+ }
+
+ switch (descriptor.type) {
+ case 'blob':
+ return new Blob(
+ [largeValue(descriptor.size, descriptor.seed)],
+ { type: descriptor.mimeType });
+ case 'buffer':
+ return largeValue(descriptor.size, descriptor.seed);
+ }
+}
+
+// Checks an IndexedDB value against a descriptor.
+//
+// Returns a Promise that resolves if the value passes the check.
+//
+// See the bottom of the file for descriptor samples.
+function checkValue(testCase, value, descriptor) {
+ if (typeof(descriptor) != 'object') {
+ assert_equals(
+ descriptor, value,
+ 'IndexedDB result should match put() argument');
+ return Promise.resolve();
+ }
+
+ if (Array.isArray(descriptor)) {
+ assert_true(
+ Array.isArray(value),
+ 'IndexedDB result type should match put() argument');
+ assert_equals(
+ descriptor.length, value.length,
+ 'IndexedDB result array size should match put() argument');
+
+ const subChecks = [];
+ for (let i = 0; i < descriptor.length; ++i)
+ subChecks.push(checkValue(testCase, value[i], descriptor[i]));
+ return Promise.all(subChecks);
+ }
+
+ if (!descriptor.hasOwnProperty('type')) {
+ assert_array_equals(
+ Object.getOwnPropertyNames(value).sort(),
+ Object.getOwnPropertyNames(descriptor).sort(),
+ 'IndexedDB result object properties should match put() argument');
+ const subChecks = [];
+ return Promise.all(Object.getOwnPropertyNames(descriptor).map(property =>
+ checkValue(testCase, value[property], descriptor[property])));
+ }
+
+ switch (descriptor.type) {
+ case 'blob':
+ assert_class_string(
+ value, 'Blob',
+ 'IndexedDB result class should match put() argument');
+ assert_equals(
+ descriptor.mimeType, value.type,
+ 'IndexedDB result Blob MIME type should match put() argument');
+ assert_equals(descriptor.size, value.size, 'incorrect Blob size');
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.onloadend = testCase.step_func(() => {
+ if (reader.error) {
+ reject(reader.error);
+ return;
+ }
+ const view = new Uint8Array(reader.result);
+ assert_equals(
+ view.join(','),
+ largeValue(descriptor.size, descriptor.seed).join(','),
+ 'IndexedDB result Blob content should match put() argument');
+ resolve();
+ });
+ reader.readAsArrayBuffer(value);
+ });
+
+ case 'buffer':
+ assert_class_string(
+ value, 'Uint8Array',
+ 'IndexedDB result type should match put() argument');
+ assert_equals(
+ value.join(','),
+ largeValue(descriptor.size, descriptor.seed).join(','),
+ 'IndexedDB result typed array content should match put() argument');
+ return Promise.resolve();
+ }
+}
+
+// Performs a series of put()s and verifies that get()s and getAll() match.
+//
+// Each element of the valueDescriptors array is fed into createValue(), and the
+// resulting value is written to IndexedDB via a put() request. After the writes
+// complete, the values are read in the same order in which they were written.
+// Last, all the results are read one more time via a getAll().
+//
+// The test verifies that the get() / getAll() results match the arguments to
+// put() and that the order in which the get() result events are fired matches
+// the order of the get() requests.
+function cloningTest(label, valueDescriptors) {
+ promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ const store = database.createObjectStore('test-store');
+ for (let i = 0; i < valueDescriptors.length; ++i) {
+ store.put(createValue(valueDescriptors[i]), i);
+ }
+ }).then(database => {
+ const transaction = database.transaction(['test-store'], 'readonly');
+ const store = transaction.objectStore('test-store');
+ const subChecks = [];
+ let resultIndex = 0;
+ for (let i = 0; i < valueDescriptors.length; ++i) {
+ subChecks.push(new Promise((resolve, reject) => {
+ const requestIndex = i;
+ const request = store.get(requestIndex);
+ request.onerror =
+ testCase.step_func(() => { reject(request.error); });
+ request.onsuccess = testCase.step_func(() => {
+ assert_equals(
+ resultIndex, requestIndex,
+ 'IDBRequest success events should be fired in request order');
+ ++resultIndex;
+ resolve(checkValue(
+ testCase, request.result, valueDescriptors[requestIndex]));
+ });
+ }));
+ }
+
+ subChecks.push(new Promise((resolve, reject) => {
+ const requestIndex = valueDescriptors.length;
+ const request = store.getAll();
+ request.onerror =
+ testCase.step_func(() => { reject(request.error); });
+ request.onsuccess = testCase.step_func(() => {
+ assert_equals(
+ resultIndex, requestIndex,
+ 'IDBRequest success events should be fired in request order');
+ ++resultIndex;
+ resolve(checkValue(
+ testCase, request.result, valueDescriptors));
+ });
+ }));
+
+ return Promise.all(subChecks);
+ });
+ }, label);
+}
+
+cloningTest('small typed array', [
+ { type: 'buffer', size: 64, seed: 1 },
+]);
+
+cloningTest('large typed array', [
+ { type: 'buffer', size: wrapThreshold, seed: 1 },
+])
+
+cloningTest('blob', [
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-1', seed: 1 },
+]);
+
+cloningTest('blob with small typed array', [
+ {
+ blob: { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-01',
+ seed: 1 },
+ buffer: { type: 'buffer', size: 64, seed: 2 },
+ },
+]);
+
+cloningTest('blob with large typed array', [
+ {
+ blob: { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-01',
+ seed: 1 },
+ buffer: { type: 'buffer', size: wrapThreshold, seed: 2 },
+ },
+]);
+
+cloningTest('blob array', [
+ [
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-1', seed: 1 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-2', seed: 2 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-3', seed: 3 },
+ ],
+]);
+
+cloningTest('array of blobs and small typed arrays', [
+ [
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-01', seed: 1 },
+ { type: 'buffer', size: 64, seed: 2 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-03', seed: 3 },
+ { type: 'buffer', size: 64, seed: 4 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-05', seed: 5 },
+ ],
+]);
+
+cloningTest('array of blobs and large typed arrays', [
+ [
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-01', seed: 1 },
+ { type: 'buffer', size: wrapThreshold, seed: 2 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-03', seed: 3 },
+ { type: 'buffer', size: wrapThreshold, seed: 4 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-05', seed: 5 },
+ ],
+]);
+
+cloningTest('object with blobs and large typed arrays', [
+ {
+ blob: { type: 'blob', size: wrapThreshold,
+ mimeType: 'text/x-blink1', seed: 1 },
+ more: [
+ { type: 'buffer', size: wrapThreshold, seed: 2 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink3', seed: 3 },
+ { type: 'buffer', size: wrapThreshold, seed: 4 },
+ ],
+ blob2: { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink5',
+ seed: 5 },
+ },
+]);
+
+cloningTest('multiple requests of objects with blobs and large typed arrays', [
+ {
+ blob: { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink1',
+ seed: 1 },
+ more: [
+ { type: 'buffer', size: wrapThreshold, seed: 2 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink3', seed: 3 },
+ { type: 'buffer', size: wrapThreshold, seed: 4 },
+ ],
+ blob2: { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink5',
+ seed: 5 },
+ },
+ [
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink06', seed: 6 },
+ { type: 'buffer', size: wrapThreshold, seed: 7 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink08', seed: 8 },
+ { type: 'buffer', size: wrapThreshold, seed: 9 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink10', seed: 10 },
+ ],
+ {
+ data: [
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-11',
+ seed: 11 },
+ { type: 'buffer', size: wrapThreshold, seed: 12 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-13',
+ seed: 13 },
+ { type: 'buffer', size: wrapThreshold, seed: 14 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink-15',
+ seed: 15 },
+ ],
+ },
+ [
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink16', seed: 16 },
+ { type: 'buffer', size: wrapThreshold, seed: 17 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink18', seed: 18 },
+ { type: 'buffer', size: wrapThreshold, seed: 19 },
+ { type: 'blob', size: wrapThreshold, mimeType: 'text/x-blink20', seed: 20 },
+ ],
+]);
+
+</script>
« 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