3 <script src=
"../../resources/js-test.js"></script>
4 <script src=
"resources/shared.js"></script>
7 <input type=
"file" id=
"fileInput" multiple
></input>
10 description("Test structured clone permutations in IndexedDB. File/FileList tests require DumpRenderTree.");
12 if (self
.eventSender
) {
13 var fileInput
= document
.getElementById("fileInput");
14 var fileRect
= fileInput
.getClientRects()[0];
15 var targetX
= fileRect
.left
+ fileRect
.width
/ 2;
16 var targetY
= fileRect
.top
+ fileRect
.height
/ 2;
17 eventSender
.beginDragWithFiles(['resources/test-data.html', 'resources/test-data.txt']);
18 eventSender
.mouseMoveTo(targetX
, targetY
);
19 eventSender
.mouseUp();
22 indexedDBTest(prepareDatabase
, startTests
);
23 function prepareDatabase()
25 db
= event
.target
.result
;
26 evalAndLog("store = db.createObjectStore('storeName')");
27 debug("This index is not used, but evaluating key path on each put() call will exercise (de)serialization:");
28 evalAndLog("store.createIndex('indexName', 'dummyKeyPath')");
34 debug("Running tests...");
57 if (tests_to_run
.length
) {
58 var test
= tests_to_run
.shift();
59 test(nextTest
); // When done, call this again.
67 function forEachWithCallback(testFunction
, values
, callback
)
69 function nextValue() {
71 testFunction(values
.shift(), nextValue
);
80 function testValue(value
, callback
)
82 // One transaction per test, since some tests require asynchronous
83 // operations to verify the result (e.g. via FileReader)
84 evalAndLog("transaction = db.transaction('storeName', 'readwrite')");
85 transaction
.onerror
= unexpectedErrorCallback
;
86 transaction
.onabort
= unexpectedAbortCallback
;
87 evalAndLog("store = transaction.objectStore('storeName')");
90 request
= evalAndLog("store.put(value, 'key')");
91 request
.onerror
= unexpectedErrorCallback
;
92 request
.onsuccess = function(e
) {
93 request
= evalAndLog("store.get('key')");
94 request
.onerror
= unexpectedErrorCallback
;
95 request
.onsuccess = function(e
) {
96 callback(request
.result
);
101 // Identity testing, sensitive to NaN and -0
104 return x
!== 0 || 1 / x
=== 1 / y
;
106 return x
!== x
&& y
!== y
;
109 function arrayCompare(a
, b
) {
110 if (a
.length
!== b
.length
) {
113 for (var i
= 0; i
< a
.length
; ++i
) {
114 if (!is(a
[i
], b
[i
])) {
121 function testPrimitiveValue(string
, callback
)
123 debug("Testing: " + string
);
124 var value
= eval("value = (" + string
+ ")");
126 testValue(test_data
, function(result
) {
127 self
.result
= result
;
128 shouldBeTrue("is(test_data, result)");
134 function testObjectWithValue(string
, callback
)
136 debug("Testing: " + string
);
137 var value
= eval("value = (" + string
+ ")");
139 testValue(test_data
, function(result
) {
140 self
.result
= result
;
141 shouldBeEqualToString("typeof result", "object");
142 shouldBe("Object.prototype.toString.call(result)", "Object.prototype.toString.call(test_data)");
143 shouldBeTrue("test_data !== result");
144 shouldBe("result.toString()", "test_data.toString()");
145 shouldBeTrue("is(test_data.valueOf(), result.valueOf())");
151 function testUndefined(callback
)
153 testPrimitiveValue("undefined", callback
);
156 function testNull(callback
)
158 testPrimitiveValue("null", callback
);
161 function testBoolean(callback
)
163 debug("Testing boolean primitives");
165 forEachWithCallback(testPrimitiveValue
, ["true", "false"], callback
);
168 function testBooleanObject(callback
)
170 debug("Testing Boolean objects");
172 forEachWithCallback(testObjectWithValue
, [
178 function testString(callback
)
180 debug("Testing string primitives");
182 forEachWithCallback(testPrimitiveValue
, [
184 "'this is a sample string'",
189 function testStringObject(callback
)
191 debug("Testing String objects");
193 forEachWithCallback(testObjectWithValue
, [
195 "new String('this is a sample string')",
196 "new String('null(\\0)')"
200 function testNumber(callback
)
202 debug("Testing number primitives");
204 forEachWithCallback(testPrimitiveValue
, [
225 function testNumberObject(callback
)
227 debug("Testing Number objects");
229 forEachWithCallback(testObjectWithValue
, [
231 "new Number(-Infinity)",
232 "new Number(-Number.MAX_VALUE)",
233 "new Number(-Number.MIN_VALUE)",
236 "new Number(Number.MIN_VALUE)",
237 "new Number(Number.MAX_VALUE)",
238 "new Number(Infinity)"
242 function testDateObject(callback
)
244 debug("Testing Date objects");
246 forEachWithCallback(testObjectWithValue
, [
261 function testRegExpObject(callback
)
263 debug("Testing RegExp objects");
265 function testRegExp(string
, callback
) {
266 debug("Testing RegExp: " + string
);
267 var value
= eval("value = (" + string
+ ")");
269 testValue(test_data
, function(result
) {
270 self
.result
= result
;
271 shouldBeTrue("test_data !== result");
272 shouldBeEqualToString("Object.prototype.toString.call(result)", "[object RegExp]");
273 shouldBe("result.toString()", "test_data.toString()");
279 forEachWithCallback(testRegExp
, [
292 function testImageData(callback
)
294 debug("Testing ImageData");
295 evalAndLog("canvas = document.createElement('canvas')");
296 evalAndLog("canvas.width = 8");
297 evalAndLog("canvas.height = 8");
298 evalAndLog("test_data = canvas.getContext('2d').getImageData(0, 0, 8, 8)");
300 for (var i
= 0; i
< 256; ++i
) {
301 test_data
.data
[i
] = i
;
304 testValue(test_data
, function(result
) {
305 self
.result
= result
;
306 shouldBeTrue("test_data !== result");
307 shouldBeEqualToString("Object.prototype.toString.call(result)", "[object ImageData]");
308 shouldBe("result.width", "test_data.width");
309 shouldBe("result.height", "test_data.height");
310 shouldBe("result.data.length", "test_data.data.length");
311 if (arrayCompare(test_data
.data
, result
.data
)) {
312 testPassed("result data matches");
314 testFailed("result data doesn't match");
320 function readBlobAsText(blob
, callback
)
322 var reader
= new FileReader();
323 reader
.onload = function(e
) {
324 if (e
.target
.readyState
=== FileReader
.DONE
) {
325 callback(e
.target
.result
);
328 reader
.onerror = function(e
) {
329 testFailed("Error reading blob as text: " + e
);
332 reader
.readAsText(blob
);
335 function checkBlobContents(blob
, expected
, callback
)
337 readBlobAsText(blob
, function(text
) {
339 shouldBeEqualToString("text", expected
);
344 function compareBlobs(blob1
, blob2
, callback
)
346 readBlobAsText(blob1
, function(text1
) {
347 readBlobAsText(blob2
, function(text2
) {
350 shouldBeEqualToString("text2", text1
);
356 function testBlob(callback
)
358 debug("Testing Blob");
360 shouldBeTrue("FileReader != null");
361 evalAndLog("test_content = 'This is a test. This is only a test.'");
362 evalAndLog("test_data = new Blob([test_content])");
363 testValue(test_data
, function(result
) {
364 self
.result
= result
;
365 shouldBeTrue("test_data !== result");
366 shouldBeEqualToString("Object.prototype.toString.call(result)", "[object Blob]");
367 shouldBe("result.size", "test_data.size");
368 shouldBe("result.type", "test_data.type");
369 checkBlobContents(result
, test_content
, callback
);
373 function compareFiles(file1
, file2
, callback
)
377 shouldBeTrue("file1 !== file2");
378 shouldBeEqualToString("Object.prototype.toString.call(file1)", "[object File]");
379 shouldBeEqualToString("Object.prototype.toString.call(file2)", "[object File]");
380 debug("file1.size: " + file1
.size
);
381 shouldBe("file1.size", "file2.size");
382 debug("file1.type: " + file1
.type
);
383 shouldBe("file1.type", "file2.type");
384 debug("file1.name: " + file1
.name
);
385 shouldBe("file1.name", "file2.name");
386 shouldBe("String(file1.lastModifiedDate)", "String(file2.lastModifiedDate)");
388 compareBlobs(file1
, file2
, callback
);
392 function testFile(callback
)
394 debug("Testing File");
396 evalAndLog("test_content = fileInput.files[0]");
398 self
.test_data
= test_content
;
399 testValue(test_data
, function(result
) {
400 self
.result
= result
;
401 compareFiles(result
, test_data
, callback
);
406 function testFileList(callback
)
408 debug("Testing FileList");
410 evalAndLog("test_content = fileInput.files");
412 self
.test_data
= test_content
;
413 testValue(test_data
, function(result
) {
414 self
.result
= result
;
415 shouldBeTrue("test_data !== result");
416 shouldBeEqualToString("Object.prototype.toString.call(result)", "[object FileList]");
417 shouldBe("result.length", "test_data.length");
420 if (i
>= test_data
.length
) {
423 debug("comparing file[" + i
+ "]");
424 compareFiles(result
[i
], test_data
[i
++], doNext
);
431 function testArray(callback
) {
432 debug("Testing Array");
433 evalAndLog("test_data = []");
434 evalAndLog("test_data[0] = 'foo'");
435 evalAndLog("test_data[1] = 'bar'");
436 evalAndLog("test_data[10] = true");
437 evalAndLog("test_data[11] = false");
438 evalAndLog("test_data[20] = 123");
439 evalAndLog("test_data[21] = 456");
440 evalAndLog("test_data[30] = null");
442 testValue(test_data
, function(result
) {
443 self
.result
= result
;
444 shouldBeTrue("test_data !== result");
445 shouldBeTrue("test_data.length === result.length");
446 Object
.keys(test_data
).forEach(
448 shouldBe("test_data[" + key
+ "]", "result[" + key
+ "]");
454 function testObject(callback
) {
455 debug("Testing Object");
456 evalAndLog("test_data = []");
457 evalAndLog("test_data[0] = 'foo'");
458 evalAndLog("test_data[1] = 'bar'");
459 evalAndLog("test_data['a'] = true");
460 evalAndLog("test_data['b'] = false");
461 evalAndLog("test_data['foo'] = 123");
462 evalAndLog("test_data['bar'] = 456");
463 evalAndLog("test_data[''] = null");
465 testValue(test_data
, function(result
) {
466 self
.result
= result
;
467 shouldBeTrue("test_data !== result");
468 shouldBeTrue("arrayCompare(Object.keys(result).sort(), Object.keys(test_data).sort())");
469 Object
.keys(test_data
).forEach(
471 shouldBe("test_data[" + JSON
.stringify(key
) + "]", "result[" + JSON
.stringify(key
) + "]");
477 function testTypedArray(callback
) {
478 debug("Testing TypedArray");
480 function testTypedArrayValue(string
, callback
) {
481 evalAndLog("value = " + string
);
483 testValue(test_data
, function(result
) {
484 self
.result
= result
;
485 shouldBeTrue("test_data !== result");
486 shouldBe("Object.prototype.toString.call(result)", "Object.prototype.toString.call(test_data)");
487 shouldBeTrue("test_data.length === result.length");
488 for (i
= 0; i
< test_data
.length
; ++i
) {
489 shouldBeTrue("is(test_data[" + i
+ "], result[" + i
+ "])");
496 forEachWithCallback(testTypedArrayValue
, [
497 "new Uint8Array([])",
498 "new Uint8Array([0, 1, 254, 255])",
499 "new Uint16Array([0x0000, 0x0001, 0xFFFE, 0xFFFF])",
500 "new Uint32Array([0x00000000, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF])",
501 "new Int8Array([0, 1, 254, 255])",
502 "new Int16Array([0x0000, 0x0001, 0xFFFE, 0xFFFF])",
503 "new Int32Array([0x00000000, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF])",
504 "new Uint8ClampedArray([0, 1, 254, 255])",
505 "new Float32Array([-Infinity, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, Infinity, NaN])",
506 "new Float64Array([-Infinity, -Number.MAX_VALUE, -Number.MIN_VALUE, 0, Number.MIN_VALUE, Number.MAX_VALUE, Infinity, NaN])"
510 function testBadTypes()
513 debug("Test types that can't be cloned:");
516 evalAndLog("transaction = db.transaction('storeName', 'readwrite')");
517 evalAndLog("store = transaction.objectStore('storeName')");
518 transaction
.onerror
= unexpectedErrorCallback
;
519 transaction
.onabort
= unexpectedAbortCallback
;
520 transaction
.oncomplete
= finishJSTest
;
523 debug("Other JavaScript object types:");
524 evalAndExpectException("store.put(new Error, 'key')", "DOMException.DATA_CLONE_ERR");
525 evalAndExpectException("store.put(new Function, 'key')", "DOMException.DATA_CLONE_ERR");
528 debug("Other host object types:");
529 evalAndExpectException("store.put(self, 'key')", "DOMException.DATA_CLONE_ERR");
530 evalAndExpectException("store.put(document, 'key')", "DOMException.DATA_CLONE_ERR");
531 evalAndExpectException("store.put(document.body, 'key')", "DOMException.DATA_CLONE_ERR");