1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/test/test_fileapi.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,461 @@ 1.4 +<!DOCTYPE HTML> 1.5 +<html> 1.6 +<head> 1.7 +<!-- 1.8 +https://bugzilla.mozilla.org/show_bug.cgi?id=414796 1.9 +--> 1.10 + <title>Test for Bug 414796</title> 1.11 + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 1.12 + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 1.13 +</head> 1.14 + 1.15 +<body> 1.16 +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=414796">Mozilla Bug 414796</a> 1.17 +<p id="display"> 1.18 + <input id="fileList" type="file"></input> 1.19 +</p> 1.20 +<div id="content" style="display: none"> 1.21 +</div> 1.22 + 1.23 +<pre id="test"> 1.24 +<script class="testbody" type="text/javascript"> 1.25 + 1.26 +// File constructors should not work from non-chrome code 1.27 +try { 1.28 + var file = File("/etc/passwd"); 1.29 + ok(false, "Did not throw on unprivileged attempt to construct a File"); 1.30 +} catch (e) { 1.31 + ok(true, "Threw on an unprivileged attempt to construct a File"); 1.32 +} 1.33 + 1.34 +const minFileSize = 20000; 1.35 +var fileNum = 1; 1.36 +var testRanCounter = 0; 1.37 +var expectedTestCount = 0; 1.38 +SimpleTest.waitForExplicitFinish(); 1.39 + 1.40 +is(FileReader.EMPTY, 0, "correct EMPTY value"); 1.41 +is(FileReader.LOADING, 1, "correct LOADING value"); 1.42 +is(FileReader.DONE, 2, "correct DONE value"); 1.43 + 1.44 +// Create strings containing data we'll test with. We'll want long 1.45 +// strings to ensure they span multiple buffers while loading 1.46 +var testTextData = "asd b\tlah\u1234w\u00a0r"; 1.47 +while (testTextData.length < minFileSize) { 1.48 + testTextData = testTextData + testTextData; 1.49 +} 1.50 + 1.51 +var testASCIIData = "abcdef 123456\n"; 1.52 +while (testASCIIData.length < minFileSize) { 1.53 + testASCIIData = testASCIIData + testASCIIData; 1.54 +} 1.55 + 1.56 +var testBinaryData = ""; 1.57 +for (var i = 0; i < 256; i++) { 1.58 + testBinaryData += String.fromCharCode(i); 1.59 +} 1.60 +while (testBinaryData.length < minFileSize) { 1.61 + testBinaryData = testBinaryData + testBinaryData; 1.62 +} 1.63 + 1.64 + 1.65 +//Set up files for testing 1.66 +var asciiFile = createFileWithData(testASCIIData); 1.67 +var binaryFile = createFileWithData(testBinaryData); 1.68 + 1.69 +var fileList = document.getElementById('fileList'); 1.70 +SpecialPowers.wrap(fileList).value = "/none/existing/path/fileAPI/testing"; 1.71 +var nonExistingFile = fileList.files[0]; 1.72 + 1.73 +// Test that plain reading works and fires events as expected, both 1.74 +// for text and binary reading 1.75 + 1.76 +var onloadHasRunText = false; 1.77 +var onloadStartHasRunText = false; 1.78 +r = new FileReader(); 1.79 +is(r.readyState, FileReader.EMPTY, "correct initial text readyState"); 1.80 +r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "plain reading"); 1.81 +r.addEventListener("load", function() { onloadHasRunText = true }, false); 1.82 +r.addEventListener("loadstart", function() { onloadStartHasRunText = true }, false); 1.83 +r.readAsText(asciiFile); 1.84 +is(r.readyState, FileReader.LOADING, "correct loading text readyState"); 1.85 +is(onloadHasRunText, false, "text loading must be async"); 1.86 +is(onloadStartHasRunText, true, "text loadstart should fire sync"); 1.87 +expectedTestCount++; 1.88 + 1.89 +var onloadHasRunBinary = false; 1.90 +var onloadStartHasRunBinary = false; 1.91 +r = new FileReader(); 1.92 +is(r.readyState, FileReader.EMPTY, "correct initial binary readyState"); 1.93 +r.addEventListener("load", function() { onloadHasRunBinary = true }, false); 1.94 +r.addEventListener("loadstart", function() { onloadStartHasRunBinary = true }, false); 1.95 +r.readAsBinaryString(binaryFile); 1.96 +r.onload = getLoadHandler(testBinaryData, testBinaryData.length, "binary reading"); 1.97 +is(r.readyState, FileReader.LOADING, "correct loading binary readyState"); 1.98 +is(onloadHasRunBinary, false, "binary loading must be async"); 1.99 +is(onloadStartHasRunBinary, true, "binary loadstart should fire sync"); 1.100 +expectedTestCount++; 1.101 + 1.102 +var onloadHasRunArrayBuffer = false; 1.103 +var onloadStartHasRunArrayBuffer = false; 1.104 +r = new FileReader(); 1.105 +is(r.readyState, FileReader.EMPTY, "correct initial arrayBuffer readyState"); 1.106 +r.addEventListener("load", function() { onloadHasRunArrayBuffer = true }, false); 1.107 +r.addEventListener("loadstart", function() { onloadStartHasRunArrayBuffer = true }, false); 1.108 +r.readAsArrayBuffer(binaryFile); 1.109 +r.onload = getLoadHandlerForArrayBuffer(testBinaryData, testBinaryData.length, "array buffer reading"); 1.110 +is(r.readyState, FileReader.LOADING, "correct loading arrayBuffer readyState"); 1.111 +is(onloadHasRunArrayBuffer, false, "arrayBuffer loading must be async"); 1.112 +is(onloadStartHasRunArrayBuffer, true, "arrayBuffer loadstart should fire sync"); 1.113 +expectedTestCount++; 1.114 + 1.115 +// Test a variety of encodings, and make sure they work properly 1.116 +r = new FileReader(); 1.117 +r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "no encoding reading"); 1.118 +r.readAsText(asciiFile, ""); 1.119 +expectedTestCount++; 1.120 + 1.121 +r = new FileReader(); 1.122 +r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "iso8859 reading"); 1.123 +r.readAsText(asciiFile, "iso-8859-1"); 1.124 +expectedTestCount++; 1.125 + 1.126 +r = new FileReader(); 1.127 +r.onload = getLoadHandler(testTextData, 1.128 + convertToUTF8(testTextData).length, 1.129 + "utf8 reading"); 1.130 +r.readAsText(createFileWithData(convertToUTF8(testTextData)), "utf8"); 1.131 +expectedTestCount++; 1.132 + 1.133 +r = new FileReader(); 1.134 +r.readAsText(createFileWithData(convertToUTF16(testTextData)), "utf-16"); 1.135 +r.onload = getLoadHandler(testTextData, 1.136 + convertToUTF16(testTextData).length, 1.137 + "utf16 reading"); 1.138 +expectedTestCount++; 1.139 + 1.140 +// Test get result without reading 1.141 +r = new FileReader(); 1.142 +is(r.readyState, FileReader.EMPTY, 1.143 + "readyState in test reader get result without reading"); 1.144 +is(r.error, null, 1.145 + "no error in test reader get result without reading"); 1.146 +is(r.result, null, 1.147 + "result in test reader get result without reading"); 1.148 + 1.149 +// Test loading an empty file works (and doesn't crash!) 1.150 +var emptyFile = createFileWithData(""); 1.151 +dump("hello nurse"); 1.152 +r = new FileReader(); 1.153 +r.onload = getLoadHandler("", 0, "empty no encoding reading"); 1.154 +r.readAsText(emptyFile, ""); 1.155 +expectedTestCount++; 1.156 + 1.157 +r = new FileReader(); 1.158 +r.onload = getLoadHandler("", 0, "empty utf8 reading"); 1.159 +r.readAsText(emptyFile, "utf8"); 1.160 +expectedTestCount++; 1.161 + 1.162 +r = new FileReader(); 1.163 +r.onload = getLoadHandler("", 0, "empty utf16 reading"); 1.164 +r.readAsText(emptyFile, "utf-16"); 1.165 +expectedTestCount++; 1.166 + 1.167 +r = new FileReader(); 1.168 +r.onload = getLoadHandler("", 0, "empty binary string reading"); 1.169 +r.readAsBinaryString(emptyFile); 1.170 +expectedTestCount++; 1.171 + 1.172 +r = new FileReader(); 1.173 +r.onload = getLoadHandlerForArrayBuffer("", 0, "empty array buffer reading"); 1.174 +r.readAsArrayBuffer(emptyFile); 1.175 +expectedTestCount++; 1.176 + 1.177 +r = new FileReader(); 1.178 +r.onload = getLoadHandler(convertToDataURL(""), 0, "empt binary string reading"); 1.179 +r.readAsDataURL(emptyFile); 1.180 +expectedTestCount++; 1.181 + 1.182 +// Test reusing a FileReader to read multiple times 1.183 +r = new FileReader(); 1.184 +r.onload = getLoadHandler(testASCIIData, 1.185 + testASCIIData.length, 1.186 + "to-be-reused reading text") 1.187 +var makeAnotherReadListener = function(event) { 1.188 + r = event.target; 1.189 + r.removeEventListener("load", makeAnotherReadListener, false); 1.190 + r.onload = getLoadHandler(testASCIIData, 1.191 + testASCIIData.length, 1.192 + "reused reading text"); 1.193 + r.readAsText(asciiFile); 1.194 +}; 1.195 +r.addEventListener("load", makeAnotherReadListener, false); 1.196 +r.readAsText(asciiFile); 1.197 +expectedTestCount += 2; 1.198 + 1.199 +r = new FileReader(); 1.200 +r.onload = getLoadHandler(testBinaryData, 1.201 + testBinaryData.length, 1.202 + "to-be-reused reading binary") 1.203 +var makeAnotherReadListener2 = function(event) { 1.204 + r = event.target; 1.205 + r.removeEventListener("load", makeAnotherReadListener2, false); 1.206 + r.onload = getLoadHandler(testBinaryData, 1.207 + testBinaryData.length, 1.208 + "reused reading binary"); 1.209 + r.readAsBinaryString(binaryFile); 1.210 +}; 1.211 +r.addEventListener("load", makeAnotherReadListener2, false); 1.212 +r.readAsBinaryString(binaryFile); 1.213 +expectedTestCount += 2; 1.214 + 1.215 +r = new FileReader(); 1.216 +r.onload = getLoadHandler(convertToDataURL(testBinaryData), 1.217 + testBinaryData.length, 1.218 + "to-be-reused reading data url") 1.219 +var makeAnotherReadListener3 = function(event) { 1.220 + r = event.target; 1.221 + r.removeEventListener("load", makeAnotherReadListener3, false); 1.222 + r.onload = getLoadHandler(convertToDataURL(testBinaryData), 1.223 + testBinaryData.length, 1.224 + "reused reading data url"); 1.225 + r.readAsDataURL(binaryFile); 1.226 +}; 1.227 +r.addEventListener("load", makeAnotherReadListener3, false); 1.228 +r.readAsDataURL(binaryFile); 1.229 +expectedTestCount += 2; 1.230 + 1.231 +r = new FileReader(); 1.232 +r.onload = getLoadHandlerForArrayBuffer(testBinaryData, 1.233 + testBinaryData.length, 1.234 + "to-be-reused reading arrayBuffer") 1.235 +var makeAnotherReadListener4 = function(event) { 1.236 + r = event.target; 1.237 + r.removeEventListener("load", makeAnotherReadListener4, false); 1.238 + r.onload = getLoadHandlerForArrayBuffer(testBinaryData, 1.239 + testBinaryData.length, 1.240 + "reused reading arrayBuffer"); 1.241 + r.readAsArrayBuffer(binaryFile); 1.242 +}; 1.243 +r.addEventListener("load", makeAnotherReadListener4, false); 1.244 +r.readAsArrayBuffer(binaryFile); 1.245 +expectedTestCount += 2; 1.246 + 1.247 +// Test first reading as ArrayBuffer then read as something else 1.248 +// (BinaryString) and doesn't crash 1.249 +r = new FileReader(); 1.250 +r.onload = getLoadHandlerForArrayBuffer(testBinaryData, 1.251 + testBinaryData.length, 1.252 + "to-be-reused reading arrayBuffer") 1.253 +var makeAnotherReadListener5 = function(event) { 1.254 + r = event.target; 1.255 + r.removeEventListener("load", makeAnotherReadListener5, false); 1.256 + r.onload = getLoadHandler(testBinaryData, 1.257 + testBinaryData.length, 1.258 + "reused reading binary string"); 1.259 + r.readAsBinaryString(binaryFile); 1.260 +}; 1.261 +r.addEventListener("load", makeAnotherReadListener5, false); 1.262 +r.readAsArrayBuffer(binaryFile); 1.263 +expectedTestCount += 2; 1.264 + 1.265 +//Test data-URI encoding on differing file sizes 1.266 +dataurldata = testBinaryData.substr(0, testBinaryData.length - 1.267 + testBinaryData.length % 3); 1.268 +is(dataurldata.length % 3, 0, "Want to test data with length % 3 == 0"); 1.269 +r = new FileReader(); 1.270 +r.onload = getLoadHandler(convertToDataURL(dataurldata), 1.271 + dataurldata.length, 1.272 + "dataurl reading, %3 = 0"); 1.273 +r.readAsDataURL(createFileWithData(dataurldata)); 1.274 +expectedTestCount++; 1.275 + 1.276 +dataurldata = testBinaryData.substr(0, testBinaryData.length - 2 - 1.277 + testBinaryData.length % 3); 1.278 +is(dataurldata.length % 3, 1, "Want to test data with length % 3 == 1"); 1.279 +r = new FileReader(); 1.280 +r.onload = getLoadHandler(convertToDataURL(dataurldata), 1.281 + dataurldata.length, 1.282 + "dataurl reading, %3 = 1"); 1.283 +r.readAsDataURL(createFileWithData(dataurldata)); 1.284 +expectedTestCount++; 1.285 + 1.286 +dataurldata = testBinaryData.substr(0, testBinaryData.length - 1 - 1.287 + testBinaryData.length % 3); 1.288 +is(dataurldata.length % 3, 2, "Want to test data with length % 3 == 2"); 1.289 +r = new FileReader(); 1.290 +r.onload = getLoadHandler(convertToDataURL(dataurldata), 1.291 + dataurldata.length, 1.292 + "dataurl reading, %3 = 2"); 1.293 +r.readAsDataURL(createFileWithData(dataurldata)); 1.294 +expectedTestCount++; 1.295 + 1.296 + 1.297 +// Test abort() 1.298 +var abortHasRun = false; 1.299 +var loadEndHasRun = false; 1.300 +r = new FileReader(); 1.301 +r.onabort = function (event) { 1.302 + is(abortHasRun, false, "abort should only fire once"); 1.303 + is(loadEndHasRun, false, "loadend shouldn't have fired yet"); 1.304 + abortHasRun = true; 1.305 + is(event.target.readyState, FileReader.DONE, "should be DONE while firing onabort"); 1.306 + is(event.target.error.name, "AbortError", "error set to AbortError for aborted reads"); 1.307 + is(event.target.result, null, "file data should be null on aborted reads"); 1.308 +} 1.309 +r.onloadend = function (event) { 1.310 + is(abortHasRun, true, "abort should fire before loadend"); 1.311 + is(loadEndHasRun, false, "loadend should only fire once"); 1.312 + loadEndHasRun = true; 1.313 + is(event.target.readyState, FileReader.DONE, "should be DONE while firing onabort"); 1.314 + is(event.target.error.name, "AbortError", "error set to AbortError for aborted reads"); 1.315 + is(event.target.result, null, "file data should be null on aborted reads"); 1.316 +} 1.317 +r.onload = function() { ok(false, "load should not fire for aborted reads") }; 1.318 +r.onerror = function() { ok(false, "error should not fire for aborted reads") }; 1.319 +r.onprogress = function() { ok(false, "progress should not fire for aborted reads") }; 1.320 +var abortThrew = false; 1.321 +try { 1.322 + r.abort(); 1.323 +} catch(e) { 1.324 + abortThrew = true; 1.325 +} 1.326 +is(abortThrew, true, "abort() must throw if not loading"); 1.327 +is(abortHasRun, false, "abort() is a no-op unless loading"); 1.328 +r.readAsText(asciiFile); 1.329 +r.abort(); 1.330 +is(abortHasRun, true, "abort should fire sync"); 1.331 +is(loadEndHasRun, true, "loadend should fire sync"); 1.332 + 1.333 +// Test calling readAsX to cause abort() 1.334 +var reuseAbortHasRun = false; 1.335 +r = new FileReader(); 1.336 +r.onabort = function (event) { 1.337 + is(reuseAbortHasRun, false, "abort should only fire once"); 1.338 + reuseAbortHasRun = true; 1.339 + is(event.target.readyState, FileReader.DONE, "should be DONE while firing onabort"); 1.340 + is(event.target.error.name, "AbortError", "error set to AbortError for aborted reads"); 1.341 + is(event.target.result, null, "file data should be null on aborted reads"); 1.342 +} 1.343 +r.onload = function() { ok(false, "load should not fire for aborted reads") }; 1.344 +var abortThrew = false; 1.345 +try { 1.346 + r.abort(); 1.347 +} catch(e) { 1.348 + abortThrew = true; 1.349 +} 1.350 +is(abortThrew, true, "abort() must throw if not loading"); 1.351 +is(reuseAbortHasRun, false, "abort() is a no-op unless loading"); 1.352 +r.readAsText(asciiFile); 1.353 +r.readAsText(asciiFile); 1.354 +is(reuseAbortHasRun, true, "abort should fire sync"); 1.355 +r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "reuse-as-abort reading"); 1.356 +expectedTestCount++; 1.357 + 1.358 + 1.359 +// Test reading from nonexistent files 1.360 +r = new FileReader(); 1.361 +var didThrow = false; 1.362 +try { 1.363 + r.readAsDataURL(nonExistingFile); 1.364 +} catch(ex) { 1.365 + didThrow = true; 1.366 +} 1.367 +// Once this test passes, we should test that onerror gets called and 1.368 +// that the FileReader object is in the right state during that call. 1.369 +todo(!didThrow, "shouldn't throw when opening nonexistent file, should fire error instead"); 1.370 + 1.371 + 1.372 +function getLoadHandler(expectedResult, expectedLength, testName) { 1.373 + return function (event) { 1.374 + is(event.target.readyState, FileReader.DONE, 1.375 + "readyState in test " + testName); 1.376 + is(event.target.error, null, 1.377 + "no error in test " + testName); 1.378 + is(event.target.result, expectedResult, 1.379 + "result in test " + testName); 1.380 + is(event.lengthComputable, true, 1.381 + "lengthComputable in test " + testName); 1.382 + is(event.loaded, expectedLength, 1.383 + "loaded in test " + testName); 1.384 + is(event.total, expectedLength, 1.385 + "total in test " + testName); 1.386 + testHasRun(); 1.387 + } 1.388 +} 1.389 + 1.390 +function getLoadHandlerForArrayBuffer(expectedResult, expectedLength, testName) { 1.391 + return function (event) { 1.392 + is(event.target.readyState, FileReader.DONE, 1.393 + "readyState in test " + testName); 1.394 + is(event.target.error, null, 1.395 + "no error in test " + testName); 1.396 + is(event.lengthComputable, true, 1.397 + "lengthComputable in test " + testName); 1.398 + is(event.loaded, expectedLength, 1.399 + "loaded in test " + testName); 1.400 + is(event.total, expectedLength, 1.401 + "total in test " + testName); 1.402 + is(event.target.result.byteLength, expectedLength, 1.403 + "array buffer size in test " + testName); 1.404 + var u8v = new Uint8Array(event.target.result); 1.405 + is(String.fromCharCode.apply(String, u8v), expectedResult, 1.406 + "array buffer contents in test " + testName); 1.407 + u8v = null; 1.408 + SpecialPowers.gc(); 1.409 + is(event.target.result.byteLength, expectedLength, 1.410 + "array buffer size after gc in test " + testName); 1.411 + u8v = new Uint8Array(event.target.result); 1.412 + is(String.fromCharCode.apply(String, u8v), expectedResult, 1.413 + "array buffer contents after gc in test " + testName); 1.414 + testHasRun(); 1.415 + } 1.416 +} 1.417 + 1.418 +function testHasRun() { 1.419 + //alert(testRanCounter); 1.420 + ++testRanCounter; 1.421 + if (testRanCounter == expectedTestCount) { 1.422 + is(onloadHasRunText, true, "onload text should have fired by now"); 1.423 + is(onloadHasRunBinary, true, "onload binary should have fired by now"); 1.424 + SimpleTest.finish(); 1.425 + } 1.426 +} 1.427 + 1.428 +function createFileWithData(fileData) { 1.429 + var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"].getService(SpecialPowers.Ci.nsIProperties); 1.430 + var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile); 1.431 + testFile.append("fileAPItestfile" + fileNum); 1.432 + fileNum++; 1.433 + var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].createInstance(SpecialPowers.Ci.nsIFileOutputStream); 1.434 + outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate 1.435 + 0666, 0); 1.436 + outStream.write(fileData, fileData.length); 1.437 + outStream.close(); 1.438 + 1.439 + var fileList = document.getElementById('fileList'); 1.440 + SpecialPowers.wrap(fileList).value = testFile.path; 1.441 + 1.442 + return fileList.files[0]; 1.443 +} 1.444 + 1.445 +function convertToUTF16(s) { 1.446 + res = ""; 1.447 + for (var i = 0; i < s.length; ++i) { 1.448 + c = s.charCodeAt(i); 1.449 + res += String.fromCharCode(c & 255, c >>> 8); 1.450 + } 1.451 + return res; 1.452 +} 1.453 + 1.454 +function convertToUTF8(s) { 1.455 + return unescape(encodeURIComponent(s)); 1.456 +} 1.457 + 1.458 +function convertToDataURL(s) { 1.459 + return "data:application/octet-stream;base64," + btoa(s); 1.460 +} 1.461 + 1.462 +</script> 1.463 +</pre> 1.464 +</body> </html>