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> |