michael@0: /* run some tests on the file:// protocol handler */ michael@0: michael@0: const PR_RDONLY = 0x1; // see prio.h michael@0: michael@0: const special_type = "application/x-our-special-type"; michael@0: michael@0: [ michael@0: test_read_file, michael@0: test_read_dir_1, michael@0: test_read_dir_2, michael@0: test_upload_file, michael@0: test_load_replace, michael@0: do_test_finished michael@0: ].forEach(add_test); michael@0: michael@0: function getFile(key) { michael@0: var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"] michael@0: .getService(Components.interfaces.nsIProperties); michael@0: return dirSvc.get(key, Components.interfaces.nsILocalFile); michael@0: } michael@0: michael@0: function new_file_input_stream(file, buffered) { michael@0: var stream = michael@0: Cc["@mozilla.org/network/file-input-stream;1"]. michael@0: createInstance(Ci.nsIFileInputStream); michael@0: stream.init(file, PR_RDONLY, 0, 0); michael@0: if (!buffered) michael@0: return stream; michael@0: michael@0: var buffer = michael@0: Cc["@mozilla.org/network/buffered-input-stream;1"]. michael@0: createInstance(Ci.nsIBufferedInputStream); michael@0: buffer.init(stream, 4096); michael@0: return buffer; michael@0: } michael@0: michael@0: function new_file_channel(file) { michael@0: var ios = michael@0: Cc["@mozilla.org/network/io-service;1"]. michael@0: getService(Ci.nsIIOService); michael@0: return ios.newChannelFromURI(ios.newFileURI(file)); michael@0: } michael@0: michael@0: /* michael@0: * stream listener michael@0: * this listener has some additional file-specific tests, so we can't just use michael@0: * ChannelListener here. michael@0: */ michael@0: function FileStreamListener(closure) { michael@0: this._closure = closure; michael@0: } michael@0: FileStreamListener.prototype = { michael@0: _closure: null, michael@0: _buffer: "", michael@0: _got_onstartrequest: false, michael@0: _got_onstoprequest: false, michael@0: _contentLen: -1, michael@0: michael@0: _isDir: function(request) { michael@0: request.QueryInterface(Ci.nsIFileChannel); michael@0: return request.file.isDirectory(); michael@0: }, michael@0: michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Ci.nsIStreamListener) || michael@0: iid.equals(Ci.nsIRequestObserver) || michael@0: iid.equals(Ci.nsISupports)) michael@0: return this; michael@0: throw Cr.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: onStartRequest: function(request, context) { michael@0: if (this._got_onstartrequest) michael@0: do_throw("Got second onStartRequest event!"); michael@0: this._got_onstartrequest = true; michael@0: michael@0: if (!this._isDir(request)) { michael@0: request.QueryInterface(Ci.nsIChannel); michael@0: this._contentLen = request.contentLength; michael@0: if (this._contentLen == -1) michael@0: do_throw("Content length is unknown in onStartRequest!"); michael@0: } michael@0: }, michael@0: michael@0: onDataAvailable: function(request, context, stream, offset, count) { michael@0: if (!this._got_onstartrequest) michael@0: do_throw("onDataAvailable without onStartRequest event!"); michael@0: if (this._got_onstoprequest) michael@0: do_throw("onDataAvailable after onStopRequest event!"); michael@0: if (!request.isPending()) michael@0: do_throw("request reports itself as not pending from onStartRequest!"); michael@0: michael@0: this._buffer = this._buffer.concat(read_stream(stream, count)); michael@0: }, michael@0: michael@0: onStopRequest: function(request, context, status) { michael@0: if (!this._got_onstartrequest) michael@0: do_throw("onStopRequest without onStartRequest event!"); michael@0: if (this._got_onstoprequest) michael@0: do_throw("Got second onStopRequest event!"); michael@0: this._got_onstoprequest = true; michael@0: if (!Components.isSuccessCode(status)) michael@0: do_throw("Failed to load file: " + status.toString(16)); michael@0: if (status != request.status) michael@0: do_throw("request.status does not match status arg to onStopRequest!"); michael@0: if (request.isPending()) michael@0: do_throw("request reports itself as pending from onStopRequest!"); michael@0: if (this._contentLen != -1 && this._buffer.length != this._contentLen) michael@0: do_throw("did not read nsIChannel.contentLength number of bytes!"); michael@0: michael@0: this._closure(this._buffer); michael@0: } michael@0: }; michael@0: michael@0: function test_read_file() { michael@0: dump("*** test_read_file\n"); michael@0: michael@0: var file = do_get_file("../unit/data/test_readline6.txt"); michael@0: var chan = new_file_channel(file); michael@0: michael@0: function on_read_complete(data) { michael@0: dump("*** test_read_file.on_read_complete\n"); michael@0: michael@0: // bug 326693 michael@0: if (chan.contentType != special_type) michael@0: do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" + michael@0: special_type + ">") michael@0: michael@0: /* read completed successfully. now read data directly from file, michael@0: and compare the result. */ michael@0: var stream = new_file_input_stream(file, false); michael@0: var result = read_stream(stream, stream.available()); michael@0: if (result != data) michael@0: do_throw("Stream contents do not match with direct read!"); michael@0: run_next_test(); michael@0: } michael@0: michael@0: chan.contentType = special_type; michael@0: chan.asyncOpen(new FileStreamListener(on_read_complete), null); michael@0: } michael@0: michael@0: function do_test_read_dir(set_type, expected_type) { michael@0: dump("*** test_read_dir(" + set_type + ", " + expected_type + ")\n"); michael@0: michael@0: var file = do_get_tempdir(); michael@0: var chan = new_file_channel(file); michael@0: michael@0: function on_read_complete(data) { michael@0: dump("*** test_read_dir.on_read_complete(" + set_type + ", " + expected_type + ")\n"); michael@0: michael@0: // bug 326693 michael@0: if (chan.contentType != expected_type) michael@0: do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" + michael@0: expected_type + ">") michael@0: michael@0: run_next_test(); michael@0: } michael@0: michael@0: if (set_type) michael@0: chan.contentType = expected_type; michael@0: chan.asyncOpen(new FileStreamListener(on_read_complete), null); michael@0: } michael@0: michael@0: function test_read_dir_1() { michael@0: return do_test_read_dir(false, "application/http-index-format"); michael@0: } michael@0: michael@0: function test_read_dir_2() { michael@0: return do_test_read_dir(true, special_type); michael@0: } michael@0: michael@0: function test_upload_file() { michael@0: dump("*** test_upload_file\n"); michael@0: michael@0: var file = do_get_file("../unit/data/test_readline6.txt"); // file to upload michael@0: var dest = do_get_tempdir(); // file upload destination michael@0: dest.append("junk.dat"); michael@0: dest.createUnique(dest.NORMAL_FILE_TYPE, 0600); michael@0: michael@0: var uploadstream = new_file_input_stream(file, true); michael@0: michael@0: var chan = new_file_channel(dest); michael@0: chan.QueryInterface(Ci.nsIUploadChannel); michael@0: chan.setUploadStream(uploadstream, "", file.fileSize); michael@0: michael@0: function on_upload_complete(data) { michael@0: dump("*** test_upload_file.on_upload_complete\n"); michael@0: michael@0: // bug 326693 michael@0: if (chan.contentType != special_type) michael@0: do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" + michael@0: special_type + ">") michael@0: michael@0: /* upload of file completed successfully. */ michael@0: if (data.length != 0) michael@0: do_throw("Upload resulted in data!"); michael@0: michael@0: var oldstream = new_file_input_stream(file, false); michael@0: var newstream = new_file_input_stream(dest, false); michael@0: var olddata = read_stream(oldstream, oldstream.available()); michael@0: var newdata = read_stream(newstream, newstream.available()); michael@0: if (olddata != newdata) michael@0: do_throw("Stream contents do not match after file copy!"); michael@0: oldstream.close(); michael@0: newstream.close(); michael@0: michael@0: /* cleanup... also ensures that the destination file is not in michael@0: use when OnStopRequest is called. */ michael@0: try { michael@0: dest.remove(false); michael@0: } catch (e) { michael@0: dump(e + "\n"); michael@0: do_throw("Unable to remove uploaded file!\n"); michael@0: } michael@0: michael@0: run_next_test(); michael@0: } michael@0: michael@0: chan.contentType = special_type; michael@0: chan.asyncOpen(new FileStreamListener(on_upload_complete), null); michael@0: } michael@0: michael@0: function test_load_replace() { michael@0: // lnk files should resolve to their targets michael@0: const isWindows = ("@mozilla.org/windows-registry-key;1" in Cc); michael@0: if (isWindows) { michael@0: dump("*** test_load_replace\n"); michael@0: file = do_get_file("data/system_root.lnk", false); michael@0: var chan = new_file_channel(file); michael@0: michael@0: // The LOAD_REPLACE flag should be set michael@0: do_check_eq(chan.loadFlags & chan.LOAD_REPLACE, chan.LOAD_REPLACE); michael@0: michael@0: // The original URI path should differ from the URI path michael@0: do_check_neq(chan.URI.path, chan.originalURI.path); michael@0: michael@0: // The original URI path should be the same as the lnk file path michael@0: var ios = Cc["@mozilla.org/network/io-service;1"]. michael@0: getService(Ci.nsIIOService); michael@0: do_check_eq(chan.originalURI.path, ios.newFileURI(file).path); michael@0: } michael@0: run_next_test(); michael@0: } michael@0: michael@0: function run_test() { michael@0: run_next_test(); michael@0: }