diff options
Diffstat (limited to 'netwerk/test/unit/test_file_protocol.js')
-rw-r--r-- | netwerk/test/unit/test_file_protocol.js | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_file_protocol.js b/netwerk/test/unit/test_file_protocol.js new file mode 100644 index 0000000000..707bddef24 --- /dev/null +++ b/netwerk/test/unit/test_file_protocol.js @@ -0,0 +1,277 @@ +/* run some tests on the file:// protocol handler */ + +"use strict"; + +const PR_RDONLY = 0x1; // see prio.h + +const special_type = "application/x-our-special-type"; + +[ + test_read_file, + test_read_dir_1, + test_read_dir_2, + test_upload_file, + test_load_shelllink, + do_test_finished, +].forEach(f => add_test(f)); + +function new_file_input_stream(file, buffered) { + var stream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance( + Ci.nsIFileInputStream + ); + stream.init(file, PR_RDONLY, 0, 0); + if (!buffered) { + return stream; + } + + var buffer = Cc[ + "@mozilla.org/network/buffered-input-stream;1" + ].createInstance(Ci.nsIBufferedInputStream); + buffer.init(stream, 4096); + return buffer; +} + +function new_file_channel(file) { + let uri = Services.io.newFileURI(file); + return NetUtil.newChannel({ + uri, + loadingPrincipal: Services.scriptSecurityManager.createContentPrincipal( + uri, + {} + ), + securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT, + contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT, + }); +} + +/* + * stream listener + * this listener has some additional file-specific tests, so we can't just use + * ChannelListener here. + */ +function FileStreamListener(closure) { + this._closure = closure; +} +FileStreamListener.prototype = { + _closure: null, + _buffer: "", + _got_onstartrequest: false, + _got_onstoprequest: false, + _contentLen: -1, + + _isDir(request) { + request.QueryInterface(Ci.nsIFileChannel); + return request.file.isDirectory(); + }, + + QueryInterface: ChromeUtils.generateQI([ + "nsIStreamListener", + "nsIRequestObserver", + ]), + + onStartRequest(request) { + if (this._got_onstartrequest) { + do_throw("Got second onStartRequest event!"); + } + this._got_onstartrequest = true; + + if (!this._isDir(request)) { + request.QueryInterface(Ci.nsIChannel); + this._contentLen = request.contentLength; + if (this._contentLen == -1) { + do_throw("Content length is unknown in onStartRequest!"); + } + } + }, + + onDataAvailable(request, stream, offset, count) { + if (!this._got_onstartrequest) { + do_throw("onDataAvailable without onStartRequest event!"); + } + if (this._got_onstoprequest) { + do_throw("onDataAvailable after onStopRequest event!"); + } + if (!request.isPending()) { + do_throw("request reports itself as not pending from onStartRequest!"); + } + + this._buffer = this._buffer.concat(read_stream(stream, count)); + }, + + onStopRequest(request, status) { + if (!this._got_onstartrequest) { + do_throw("onStopRequest without onStartRequest event!"); + } + if (this._got_onstoprequest) { + do_throw("Got second onStopRequest event!"); + } + this._got_onstoprequest = true; + if (!Components.isSuccessCode(status)) { + do_throw("Failed to load file: " + status.toString(16)); + } + if (status != request.status) { + do_throw("request.status does not match status arg to onStopRequest!"); + } + if (request.isPending()) { + do_throw("request reports itself as pending from onStopRequest!"); + } + if (this._contentLen != -1 && this._buffer.length != this._contentLen) { + do_throw("did not read nsIChannel.contentLength number of bytes!"); + } + + this._closure(this._buffer); + }, +}; + +function test_read_file() { + dump("*** test_read_file\n"); + + var file = do_get_file("../unit/data/test_readline6.txt"); + var chan = new_file_channel(file); + + function on_read_complete(data) { + dump("*** test_read_file.on_read_complete\n"); + + // bug 326693 + if (chan.contentType != special_type) { + do_throw( + "Type mismatch! Is <" + + chan.contentType + + ">, should be <" + + special_type + + ">" + ); + } + + /* read completed successfully. now read data directly from file, + and compare the result. */ + var stream = new_file_input_stream(file, false); + var result = read_stream(stream, stream.available()); + if (result != data) { + do_throw("Stream contents do not match with direct read!"); + } + run_next_test(); + } + + chan.contentType = special_type; + chan.asyncOpen(new FileStreamListener(on_read_complete)); +} + +function do_test_read_dir(set_type, expected_type) { + dump("*** test_read_dir(" + set_type + ", " + expected_type + ")\n"); + + var file = do_get_tempdir(); + var chan = new_file_channel(file); + + function on_read_complete(data) { + dump( + "*** test_read_dir.on_read_complete(" + + set_type + + ", " + + expected_type + + ")\n" + ); + + // bug 326693 + if (chan.contentType != expected_type) { + do_throw( + "Type mismatch! Is <" + + chan.contentType + + ">, should be <" + + expected_type + + ">" + ); + } + + run_next_test(); + } + + if (set_type) { + chan.contentType = expected_type; + } + chan.asyncOpen(new FileStreamListener(on_read_complete)); +} + +function test_read_dir_1() { + return do_test_read_dir(false, "application/http-index-format"); +} + +function test_read_dir_2() { + return do_test_read_dir(true, special_type); +} + +function test_upload_file() { + dump("*** test_upload_file\n"); + + var file = do_get_file("../unit/data/test_readline6.txt"); // file to upload + var dest = do_get_tempdir(); // file upload destination + dest.append("junk.dat"); + dest.createUnique(dest.NORMAL_FILE_TYPE, 0o600); + + var uploadstream = new_file_input_stream(file, true); + + var chan = new_file_channel(dest); + chan.QueryInterface(Ci.nsIUploadChannel); + chan.setUploadStream(uploadstream, "", file.fileSize); + + function on_upload_complete(data) { + dump("*** test_upload_file.on_upload_complete\n"); + + // bug 326693 + if (chan.contentType != special_type) { + do_throw( + "Type mismatch! Is <" + + chan.contentType + + ">, should be <" + + special_type + + ">" + ); + } + + /* upload of file completed successfully. */ + if (data.length) { + do_throw("Upload resulted in data!"); + } + + var oldstream = new_file_input_stream(file, false); + var newstream = new_file_input_stream(dest, false); + var olddata = read_stream(oldstream, oldstream.available()); + var newdata = read_stream(newstream, newstream.available()); + if (olddata != newdata) { + do_throw("Stream contents do not match after file copy!"); + } + oldstream.close(); + newstream.close(); + + /* cleanup... also ensures that the destination file is not in + use when OnStopRequest is called. */ + try { + dest.remove(false); + } catch (e) { + dump(e + "\n"); + do_throw("Unable to remove uploaded file!\n"); + } + + run_next_test(); + } + + chan.contentType = special_type; + chan.asyncOpen(new FileStreamListener(on_upload_complete)); +} + +function test_load_shelllink() { + // lnk files should not resolve to their targets + dump("*** test_load_shelllink\n"); + let file = do_get_file("data/system_root.lnk", false); + var chan = new_file_channel(file); + + // The original URI path should be the same as the URI path + Assert.equal(chan.URI.pathQueryRef, chan.originalURI.pathQueryRef); + + // The original URI path should be the same as the lnk file path + Assert.equal( + chan.originalURI.pathQueryRef, + Services.io.newFileURI(file).pathQueryRef + ); + run_next_test(); +} |