2005-11-12 21:17:19 +03:00
|
|
|
/* run some tests on the file:// protocol handler */
|
|
|
|
|
|
|
|
const Cc = Components.classes;
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
const Cr = Components.results;
|
|
|
|
const PR_RDONLY = 0x1; // see prio.h
|
|
|
|
|
2006-02-14 21:46:12 +03:00
|
|
|
const special_type = "application/x-our-special-type";
|
|
|
|
|
2005-11-12 21:17:19 +03:00
|
|
|
var test_index = 0;
|
|
|
|
var test_array = [
|
|
|
|
test_read_file,
|
2006-02-14 21:46:12 +03:00
|
|
|
test_read_dir_1,
|
|
|
|
test_read_dir_2,
|
2005-11-12 21:17:19 +03:00
|
|
|
test_upload_file,
|
|
|
|
do_test_finished
|
|
|
|
];
|
|
|
|
|
|
|
|
function run_next_test() {
|
|
|
|
test_array[test_index++]();
|
|
|
|
}
|
|
|
|
|
|
|
|
function getFile(key) {
|
|
|
|
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
|
|
|
|
.getService(Components.interfaces.nsIProperties);
|
|
|
|
return dirSvc.get(key, Components.interfaces.nsILocalFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read count bytes from stream and return as a String object */
|
|
|
|
function read_stream(stream, count) {
|
|
|
|
/* assume stream has non-ASCII data */
|
|
|
|
var wrapper =
|
|
|
|
Cc["@mozilla.org/binaryinputstream;1"].
|
|
|
|
createInstance(Ci.nsIBinaryInputStream);
|
|
|
|
wrapper.setInputStream(stream);
|
2006-11-17 00:44:46 +03:00
|
|
|
/* JS methods can be called with a maximum of 65535 arguments, and input
|
|
|
|
streams don't have to return all the data they make .available() when
|
|
|
|
asked to .read() that number of bytes. */
|
|
|
|
var data = [];
|
|
|
|
while (count > 0) {
|
|
|
|
var bytes = wrapper.readByteArray(Math.min(65535, count));
|
|
|
|
data.push(String.fromCharCode.apply(null, bytes));
|
|
|
|
count -= bytes.length;
|
|
|
|
if (bytes.length == 0)
|
|
|
|
do_throw("Nothing read from input stream!");
|
|
|
|
}
|
|
|
|
return data.join('');
|
2005-11-12 21:17:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
var ios =
|
|
|
|
Cc["@mozilla.org/network/io-service;1"].
|
|
|
|
getService(Ci.nsIIOService);
|
|
|
|
return ios.newChannelFromURI(ios.newFileURI(file));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* stream listener */
|
|
|
|
function Listener(closure) {
|
|
|
|
this._closure = closure;
|
|
|
|
}
|
|
|
|
Listener.prototype = {
|
|
|
|
_closure: null,
|
|
|
|
_buffer: "",
|
|
|
|
_got_onstartrequest: false,
|
|
|
|
_got_onstoprequest: false,
|
|
|
|
_contentLen: -1,
|
|
|
|
|
|
|
|
_isDir: function(request) {
|
|
|
|
request.QueryInterface(Ci.nsIFileChannel);
|
|
|
|
return request.file.isDirectory();
|
|
|
|
},
|
|
|
|
|
|
|
|
QueryInterface: function(iid) {
|
|
|
|
if (iid.Equals(Ci.nsIStreamListener) ||
|
|
|
|
iid.Equals(Ci.nsIRequestObserver) ||
|
|
|
|
iid.Equals(Ci.nsISupports))
|
|
|
|
return this;
|
|
|
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
|
|
|
},
|
|
|
|
|
|
|
|
onStartRequest: function(request, context) {
|
|
|
|
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: function(request, context, 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: function(request, context, 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 = getFile("XpcomLib");
|
|
|
|
var chan = new_file_channel(file);
|
|
|
|
|
|
|
|
function on_read_complete(data) {
|
|
|
|
dump("*** test_read_file.on_read_complete\n");
|
|
|
|
|
2006-02-14 21:46:12 +03:00
|
|
|
// bug 326693
|
|
|
|
if (chan.contentType != special_type)
|
|
|
|
do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" +
|
|
|
|
special_type + ">")
|
|
|
|
|
2005-11-12 21:17:19 +03:00
|
|
|
/* 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();
|
|
|
|
}
|
|
|
|
|
2006-02-14 21:46:12 +03:00
|
|
|
chan.contentType = special_type;
|
2005-11-12 21:17:19 +03:00
|
|
|
chan.asyncOpen(new Listener(on_read_complete), null);
|
|
|
|
}
|
|
|
|
|
2006-02-14 21:46:12 +03:00
|
|
|
function do_test_read_dir(set_type, expected_type) {
|
|
|
|
dump("*** test_read_dir(" + set_type + ", " + expected_type + ")\n");
|
2005-11-12 21:17:19 +03:00
|
|
|
|
|
|
|
var file = getFile("TmpD");
|
|
|
|
var chan = new_file_channel(file);
|
|
|
|
|
|
|
|
function on_read_complete(data) {
|
2006-02-14 21:46:12 +03:00
|
|
|
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 + ">")
|
2005-11-12 21:17:19 +03:00
|
|
|
|
|
|
|
run_next_test();
|
|
|
|
}
|
|
|
|
|
2006-02-14 21:46:12 +03:00
|
|
|
if (set_type)
|
|
|
|
chan.contentType = expected_type;
|
2005-11-12 21:17:19 +03:00
|
|
|
chan.asyncOpen(new Listener(on_read_complete), null);
|
|
|
|
}
|
|
|
|
|
2006-02-14 21:46:12 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2005-11-12 21:17:19 +03:00
|
|
|
function test_upload_file() {
|
|
|
|
dump("*** test_upload_file\n");
|
|
|
|
|
|
|
|
var file = getFile("XpcomLib"); // file to upload
|
|
|
|
var dest = getFile("TmpD"); // file upload destination
|
|
|
|
dest.append("junk.dat");
|
|
|
|
dest.createUnique(dest.NORMAL_FILE_TYPE, 0600);
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
2006-02-14 21:46:12 +03:00
|
|
|
// bug 326693
|
|
|
|
if (chan.contentType != special_type)
|
|
|
|
do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" +
|
|
|
|
special_type + ">")
|
|
|
|
|
2005-11-12 21:17:19 +03:00
|
|
|
/* upload of file completed successfully. */
|
|
|
|
if (data.length != 0)
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2006-02-14 21:46:12 +03:00
|
|
|
chan.contentType = special_type;
|
2005-11-12 21:17:19 +03:00
|
|
|
chan.asyncOpen(new Listener(on_upload_complete), null);
|
|
|
|
}
|
|
|
|
|
|
|
|
function run_test() {
|
|
|
|
do_test_pending();
|
|
|
|
run_next_test();
|
|
|
|
}
|