michael@0: // Utility functions michael@0: var testRanCounter = 0; michael@0: var expectedTestCount = 0; michael@0: michael@0: function testHasRun() { michael@0: //alert(testRanCounter); michael@0: ++testRanCounter; michael@0: if (testRanCounter == expectedTestCount) { michael@0: SimpleTest.finish(); michael@0: } michael@0: } michael@0: michael@0: michael@0: function testFile(file, contents, test) { michael@0: SimpleTest.requestLongerTimeout(2); michael@0: michael@0: // Load file using FileReader michael@0: var r = new FileReader(); michael@0: r.onload = getFileReaderLoadHandler(contents, contents.length, "FileReader.readAsBinaryString of " + test); michael@0: r.readAsBinaryString(file); michael@0: expectedTestCount++; michael@0: michael@0: // Load file using URL.createObjectURL and XMLHttpRequest michael@0: var xhr = new XMLHttpRequest; michael@0: xhr.open("GET", URL.createObjectURL(file)); michael@0: xhr.onload = getXHRLoadHandler(contents, contents.length, false, michael@0: "XMLHttpRequest load of " + test); michael@0: xhr.overrideMimeType('text/plain; charset=x-user-defined'); michael@0: xhr.send(); michael@0: expectedTestCount++; michael@0: michael@0: // Send file to server using FormData and XMLHttpRequest michael@0: xhr = new XMLHttpRequest(); michael@0: xhr.onload = function(event) { michael@0: checkMPSubmission(JSON.parse(event.target.responseText), michael@0: [{ name: "hello", value: "world"}, michael@0: { name: "myfile", michael@0: value: contents, michael@0: fileName: file.name || "blob", michael@0: contentType: file.type || "application/octet-stream" }]); michael@0: testHasRun(); michael@0: } michael@0: xhr.open("POST", "../../html/content/test/form_submit_server.sjs"); michael@0: var fd = new FormData; michael@0: fd.append("hello", "world"); michael@0: fd.append("myfile", file); michael@0: xhr.send(fd); michael@0: expectedTestCount++; michael@0: michael@0: // Send file to server using plain XMLHttpRequest michael@0: var xhr = new XMLHttpRequest; michael@0: xhr.open("POST", "file_XHRSendData.sjs"); michael@0: xhr.onload = function (event) { michael@0: is(event.target.getResponseHeader("Result-Content-Type"), michael@0: file.type ? file.type : null, michael@0: "request content-type in XMLHttpRequest send of " + test); michael@0: is(event.target.getResponseHeader("Result-Content-Length"), michael@0: file.size, michael@0: "request content-length in XMLHttpRequest send of " + test); michael@0: }; michael@0: xhr.addEventListener("load", michael@0: getXHRLoadHandler(contents, contents.length, true, michael@0: "XMLHttpRequest send of " + test), michael@0: false); michael@0: xhr.overrideMimeType('text/plain; charset=x-user-defined'); michael@0: xhr.send(file); michael@0: expectedTestCount++; michael@0: } michael@0: michael@0: function getFileReaderLoadHandler(expectedResult, expectedLength, testName) { michael@0: return function (event) { michael@0: is(event.target.readyState, FileReader.DONE, michael@0: "[FileReader] readyState in test " + testName); michael@0: is(event.target.error, null, michael@0: "[FileReader] no error in test " + testName); michael@0: // Do not use |is(event.target.result, expectedResult, "...");| that may output raw binary data. michael@0: is(event.target.result.length, expectedResult.length, michael@0: "[FileReader] Length of result in test " + testName); michael@0: ok(event.target.result == expectedResult, michael@0: "[FileReader] Content of result in test " + testName); michael@0: is(event.lengthComputable, true, michael@0: "[FileReader] lengthComputable in test " + testName); michael@0: is(event.loaded, expectedLength, michael@0: "[FileReader] Loaded length in test " + testName); michael@0: is(event.total, expectedLength, michael@0: "[FileReader] Total length in test " + testName); michael@0: testHasRun(); michael@0: } michael@0: } michael@0: michael@0: function getXHRLoadHandler(expectedResult, expectedLength, statusWorking, testName) { michael@0: return function (event) { michael@0: is(event.target.readyState, 4, michael@0: "[XHR] readyState in test " + testName); michael@0: if (statusWorking) { michael@0: is(event.target.status, 200, michael@0: "[XHR] no error in test " + testName); michael@0: } michael@0: else { michael@0: todo_is(event.target.status, 200, michael@0: "[XHR] no error in test " + testName); michael@0: } michael@0: // Do not use |is(convertXHRBinary(event.target.responseText), expectedResult, "...");| that may output raw binary data. michael@0: var convertedData = convertXHRBinary(event.target.responseText); michael@0: is(convertedData.length, expectedResult.length, michael@0: "[XHR] Length of result in test " + testName); michael@0: ok(convertedData == expectedResult, michael@0: "[XHR] Content of result in test " + testName); michael@0: is(event.lengthComputable, true, michael@0: "[XHR] lengthComputable in test " + testName); michael@0: is(event.loaded, expectedLength, michael@0: "[XHR] Loaded length in test " + testName); michael@0: is(event.total, expectedLength, michael@0: "[XHR] Total length in test " + testName); michael@0: michael@0: testHasRun(); michael@0: } michael@0: } michael@0: michael@0: function convertXHRBinary(s) { michael@0: var res = ""; michael@0: for (var i = 0; i < s.length; ++i) { michael@0: res += String.fromCharCode(s.charCodeAt(i) & 255); michael@0: } michael@0: return res; michael@0: } michael@0: michael@0: function testHasRun() { michael@0: //alert(testRanCounter); michael@0: ++testRanCounter; michael@0: if (testRanCounter == expectedTestCount) { michael@0: SimpleTest.finish(); michael@0: } michael@0: } michael@0: michael@0: function createFileWithData(fileData) { michael@0: var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"].getService(SpecialPowers.Ci.nsIProperties); michael@0: var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile); michael@0: testFile.append("fileAPItestfile2-" + fileNum); michael@0: fileNum++; michael@0: var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].createInstance(SpecialPowers.Ci.nsIFileOutputStream); michael@0: outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate michael@0: 0666, 0); michael@0: outStream.write(fileData, fileData.length); michael@0: outStream.close(); michael@0: michael@0: var fileList = document.getElementById('fileList'); michael@0: SpecialPowers.wrap(fileList).value = testFile.path; michael@0: michael@0: return fileList.files[0]; michael@0: } michael@0: michael@0: function gc() { michael@0: window.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor) michael@0: .getInterface(SpecialPowers.Ci.nsIDOMWindowUtils) michael@0: .garbageCollect(); michael@0: } michael@0: michael@0: function checkMPSubmission(sub, expected) { michael@0: function getPropCount(o) { michael@0: var x, l = 0; michael@0: for (x in o) ++l; michael@0: return l; michael@0: } michael@0: michael@0: is(sub.length, expected.length, michael@0: "Correct number of items"); michael@0: var i; michael@0: for (i = 0; i < expected.length; ++i) { michael@0: if (!("fileName" in expected[i])) { michael@0: is(sub[i].headers["Content-Disposition"], michael@0: "form-data; name=\"" + expected[i].name + "\"", michael@0: "Correct name (A)"); michael@0: is (getPropCount(sub[i].headers), 1, michael@0: "Wrong number of headers (A)"); michael@0: } michael@0: else { michael@0: is(sub[i].headers["Content-Disposition"], michael@0: "form-data; name=\"" + expected[i].name + "\"; filename=\"" + michael@0: expected[i].fileName + "\"", michael@0: "Correct name (B)"); michael@0: is(sub[i].headers["Content-Type"], michael@0: expected[i].contentType, michael@0: "Correct content type (B)"); michael@0: is (getPropCount(sub[i].headers), 2, michael@0: "Wrong number of headers (B)"); michael@0: } michael@0: // Do not use |is(sub[i].body, expected[i].value, "...");| that may output raw binary data. michael@0: is(sub[i].body.length, expected[i].value.length, michael@0: "Length of correct value"); michael@0: ok(sub[i].body == expected[i].value, michael@0: "Content of correct value"); michael@0: } michael@0: } michael@0: michael@0: function testSlice(file, size, type, contents, fileType) { michael@0: is(file.type, type, fileType + " file is correct type"); michael@0: is(file.size, size, fileType + " file is correct size"); michael@0: ok(file instanceof File, fileType + " file is a File"); michael@0: ok(file instanceof Blob, fileType + " file is also a Blob"); michael@0: michael@0: var slice = file.slice(0, size); michael@0: ok(slice instanceof Blob, fileType + " fullsize slice is a Blob"); michael@0: ok(!(slice instanceof File), fileType + " fullsize slice is not a File"); michael@0: michael@0: slice = file.slice(0, 1234); michael@0: ok(slice instanceof Blob, fileType + " sized slice is a Blob"); michael@0: ok(!(slice instanceof File), fileType + " sized slice is not a File"); michael@0: michael@0: slice = file.slice(0, size, "foo/bar"); michael@0: is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type"); michael@0: michael@0: slice = file.slice(0, 5432, "foo/bar"); michael@0: is(slice.type, "foo/bar", fileType + " sized slice foo/bar type"); michael@0: michael@0: is(slice.slice(0, 10).type, "", fileType + " slice-slice type"); michael@0: is(slice.slice(0, 10).size, 10, fileType + " slice-slice size"); michael@0: is(slice.slice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type"); michael@0: is(slice.slice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size"); michael@0: michael@0: // Start, end, expected size michael@0: var indexes = [[0, size, size], michael@0: [0, 1234, 1234], michael@0: [size-500, size, 500], michael@0: [size-500, size+500, 500], michael@0: [size+500, size+1500, 0], michael@0: [0, 0, 0], michael@0: [1000, 1000, 0], michael@0: [size, size, 0], michael@0: [undefined, undefined, size], michael@0: [0, undefined, size], michael@0: [100, undefined, size-100], michael@0: [-100, undefined, 100], michael@0: [100, -100, size-200], michael@0: [-size-100, undefined, size], michael@0: [-2*size-100, 500, 500], michael@0: [0, -size-100, 0], michael@0: [100, -size-100, 0], michael@0: [50, -size+100, 50], michael@0: [0, 33000, 33000], michael@0: [1000, 34000, 33000], michael@0: ]; michael@0: michael@0: for (var i = 0; i < indexes.length; ++i) { michael@0: var sliceContents; michael@0: var testName; michael@0: if (indexes[i][0] == undefined) { michael@0: slice = file.slice(); michael@0: sliceContents = contents.slice(); michael@0: testName = fileType + " slice()"; michael@0: } michael@0: else if (indexes[i][1] == undefined) { michael@0: slice = file.slice(indexes[i][0]); michael@0: sliceContents = contents.slice(indexes[i][0]); michael@0: testName = fileType + " slice(" + indexes[i][0] + ")"; michael@0: } michael@0: else { michael@0: slice = file.slice(indexes[i][0], indexes[i][1]); michael@0: sliceContents = contents.slice(indexes[i][0], indexes[i][1]); michael@0: testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")"; michael@0: } michael@0: is(slice.type, "", testName + " type"); michael@0: is(slice.size, indexes[i][2], testName + " size"); michael@0: is(sliceContents.length, indexes[i][2], testName + " data size"); michael@0: testFile(slice, sliceContents, testName); michael@0: } michael@0: michael@0: // Slice of slice michael@0: var slice = file.slice(0, 40000); michael@0: testFile(slice.slice(5000, 42000), contents.slice(5000, 40000), "file slice slice"); michael@0: michael@0: // ...of slice of slice michael@0: slice = slice.slice(5000, 42000).slice(400, 700); michael@0: SpecialPowers.gc(); michael@0: testFile(slice, contents.slice(5400, 5700), "file slice slice slice"); michael@0: } michael@0: