|
1 /* run some tests on the file:// protocol handler */ |
|
2 |
|
3 const PR_RDONLY = 0x1; // see prio.h |
|
4 |
|
5 const special_type = "application/x-our-special-type"; |
|
6 |
|
7 [ |
|
8 test_read_file, |
|
9 test_read_dir_1, |
|
10 test_read_dir_2, |
|
11 test_upload_file, |
|
12 test_load_replace, |
|
13 do_test_finished |
|
14 ].forEach(add_test); |
|
15 |
|
16 function getFile(key) { |
|
17 var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"] |
|
18 .getService(Components.interfaces.nsIProperties); |
|
19 return dirSvc.get(key, Components.interfaces.nsILocalFile); |
|
20 } |
|
21 |
|
22 function new_file_input_stream(file, buffered) { |
|
23 var stream = |
|
24 Cc["@mozilla.org/network/file-input-stream;1"]. |
|
25 createInstance(Ci.nsIFileInputStream); |
|
26 stream.init(file, PR_RDONLY, 0, 0); |
|
27 if (!buffered) |
|
28 return stream; |
|
29 |
|
30 var buffer = |
|
31 Cc["@mozilla.org/network/buffered-input-stream;1"]. |
|
32 createInstance(Ci.nsIBufferedInputStream); |
|
33 buffer.init(stream, 4096); |
|
34 return buffer; |
|
35 } |
|
36 |
|
37 function new_file_channel(file) { |
|
38 var ios = |
|
39 Cc["@mozilla.org/network/io-service;1"]. |
|
40 getService(Ci.nsIIOService); |
|
41 return ios.newChannelFromURI(ios.newFileURI(file)); |
|
42 } |
|
43 |
|
44 /* |
|
45 * stream listener |
|
46 * this listener has some additional file-specific tests, so we can't just use |
|
47 * ChannelListener here. |
|
48 */ |
|
49 function FileStreamListener(closure) { |
|
50 this._closure = closure; |
|
51 } |
|
52 FileStreamListener.prototype = { |
|
53 _closure: null, |
|
54 _buffer: "", |
|
55 _got_onstartrequest: false, |
|
56 _got_onstoprequest: false, |
|
57 _contentLen: -1, |
|
58 |
|
59 _isDir: function(request) { |
|
60 request.QueryInterface(Ci.nsIFileChannel); |
|
61 return request.file.isDirectory(); |
|
62 }, |
|
63 |
|
64 QueryInterface: function(iid) { |
|
65 if (iid.equals(Ci.nsIStreamListener) || |
|
66 iid.equals(Ci.nsIRequestObserver) || |
|
67 iid.equals(Ci.nsISupports)) |
|
68 return this; |
|
69 throw Cr.NS_ERROR_NO_INTERFACE; |
|
70 }, |
|
71 |
|
72 onStartRequest: function(request, context) { |
|
73 if (this._got_onstartrequest) |
|
74 do_throw("Got second onStartRequest event!"); |
|
75 this._got_onstartrequest = true; |
|
76 |
|
77 if (!this._isDir(request)) { |
|
78 request.QueryInterface(Ci.nsIChannel); |
|
79 this._contentLen = request.contentLength; |
|
80 if (this._contentLen == -1) |
|
81 do_throw("Content length is unknown in onStartRequest!"); |
|
82 } |
|
83 }, |
|
84 |
|
85 onDataAvailable: function(request, context, stream, offset, count) { |
|
86 if (!this._got_onstartrequest) |
|
87 do_throw("onDataAvailable without onStartRequest event!"); |
|
88 if (this._got_onstoprequest) |
|
89 do_throw("onDataAvailable after onStopRequest event!"); |
|
90 if (!request.isPending()) |
|
91 do_throw("request reports itself as not pending from onStartRequest!"); |
|
92 |
|
93 this._buffer = this._buffer.concat(read_stream(stream, count)); |
|
94 }, |
|
95 |
|
96 onStopRequest: function(request, context, status) { |
|
97 if (!this._got_onstartrequest) |
|
98 do_throw("onStopRequest without onStartRequest event!"); |
|
99 if (this._got_onstoprequest) |
|
100 do_throw("Got second onStopRequest event!"); |
|
101 this._got_onstoprequest = true; |
|
102 if (!Components.isSuccessCode(status)) |
|
103 do_throw("Failed to load file: " + status.toString(16)); |
|
104 if (status != request.status) |
|
105 do_throw("request.status does not match status arg to onStopRequest!"); |
|
106 if (request.isPending()) |
|
107 do_throw("request reports itself as pending from onStopRequest!"); |
|
108 if (this._contentLen != -1 && this._buffer.length != this._contentLen) |
|
109 do_throw("did not read nsIChannel.contentLength number of bytes!"); |
|
110 |
|
111 this._closure(this._buffer); |
|
112 } |
|
113 }; |
|
114 |
|
115 function test_read_file() { |
|
116 dump("*** test_read_file\n"); |
|
117 |
|
118 var file = do_get_file("../unit/data/test_readline6.txt"); |
|
119 var chan = new_file_channel(file); |
|
120 |
|
121 function on_read_complete(data) { |
|
122 dump("*** test_read_file.on_read_complete\n"); |
|
123 |
|
124 // bug 326693 |
|
125 if (chan.contentType != special_type) |
|
126 do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" + |
|
127 special_type + ">") |
|
128 |
|
129 /* read completed successfully. now read data directly from file, |
|
130 and compare the result. */ |
|
131 var stream = new_file_input_stream(file, false); |
|
132 var result = read_stream(stream, stream.available()); |
|
133 if (result != data) |
|
134 do_throw("Stream contents do not match with direct read!"); |
|
135 run_next_test(); |
|
136 } |
|
137 |
|
138 chan.contentType = special_type; |
|
139 chan.asyncOpen(new FileStreamListener(on_read_complete), null); |
|
140 } |
|
141 |
|
142 function do_test_read_dir(set_type, expected_type) { |
|
143 dump("*** test_read_dir(" + set_type + ", " + expected_type + ")\n"); |
|
144 |
|
145 var file = do_get_tempdir(); |
|
146 var chan = new_file_channel(file); |
|
147 |
|
148 function on_read_complete(data) { |
|
149 dump("*** test_read_dir.on_read_complete(" + set_type + ", " + expected_type + ")\n"); |
|
150 |
|
151 // bug 326693 |
|
152 if (chan.contentType != expected_type) |
|
153 do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" + |
|
154 expected_type + ">") |
|
155 |
|
156 run_next_test(); |
|
157 } |
|
158 |
|
159 if (set_type) |
|
160 chan.contentType = expected_type; |
|
161 chan.asyncOpen(new FileStreamListener(on_read_complete), null); |
|
162 } |
|
163 |
|
164 function test_read_dir_1() { |
|
165 return do_test_read_dir(false, "application/http-index-format"); |
|
166 } |
|
167 |
|
168 function test_read_dir_2() { |
|
169 return do_test_read_dir(true, special_type); |
|
170 } |
|
171 |
|
172 function test_upload_file() { |
|
173 dump("*** test_upload_file\n"); |
|
174 |
|
175 var file = do_get_file("../unit/data/test_readline6.txt"); // file to upload |
|
176 var dest = do_get_tempdir(); // file upload destination |
|
177 dest.append("junk.dat"); |
|
178 dest.createUnique(dest.NORMAL_FILE_TYPE, 0600); |
|
179 |
|
180 var uploadstream = new_file_input_stream(file, true); |
|
181 |
|
182 var chan = new_file_channel(dest); |
|
183 chan.QueryInterface(Ci.nsIUploadChannel); |
|
184 chan.setUploadStream(uploadstream, "", file.fileSize); |
|
185 |
|
186 function on_upload_complete(data) { |
|
187 dump("*** test_upload_file.on_upload_complete\n"); |
|
188 |
|
189 // bug 326693 |
|
190 if (chan.contentType != special_type) |
|
191 do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" + |
|
192 special_type + ">") |
|
193 |
|
194 /* upload of file completed successfully. */ |
|
195 if (data.length != 0) |
|
196 do_throw("Upload resulted in data!"); |
|
197 |
|
198 var oldstream = new_file_input_stream(file, false); |
|
199 var newstream = new_file_input_stream(dest, false); |
|
200 var olddata = read_stream(oldstream, oldstream.available()); |
|
201 var newdata = read_stream(newstream, newstream.available()); |
|
202 if (olddata != newdata) |
|
203 do_throw("Stream contents do not match after file copy!"); |
|
204 oldstream.close(); |
|
205 newstream.close(); |
|
206 |
|
207 /* cleanup... also ensures that the destination file is not in |
|
208 use when OnStopRequest is called. */ |
|
209 try { |
|
210 dest.remove(false); |
|
211 } catch (e) { |
|
212 dump(e + "\n"); |
|
213 do_throw("Unable to remove uploaded file!\n"); |
|
214 } |
|
215 |
|
216 run_next_test(); |
|
217 } |
|
218 |
|
219 chan.contentType = special_type; |
|
220 chan.asyncOpen(new FileStreamListener(on_upload_complete), null); |
|
221 } |
|
222 |
|
223 function test_load_replace() { |
|
224 // lnk files should resolve to their targets |
|
225 const isWindows = ("@mozilla.org/windows-registry-key;1" in Cc); |
|
226 if (isWindows) { |
|
227 dump("*** test_load_replace\n"); |
|
228 file = do_get_file("data/system_root.lnk", false); |
|
229 var chan = new_file_channel(file); |
|
230 |
|
231 // The LOAD_REPLACE flag should be set |
|
232 do_check_eq(chan.loadFlags & chan.LOAD_REPLACE, chan.LOAD_REPLACE); |
|
233 |
|
234 // The original URI path should differ from the URI path |
|
235 do_check_neq(chan.URI.path, chan.originalURI.path); |
|
236 |
|
237 // The original URI path should be the same as the lnk file path |
|
238 var ios = Cc["@mozilla.org/network/io-service;1"]. |
|
239 getService(Ci.nsIIOService); |
|
240 do_check_eq(chan.originalURI.path, ios.newFileURI(file).path); |
|
241 } |
|
242 run_next_test(); |
|
243 } |
|
244 |
|
245 function run_test() { |
|
246 run_next_test(); |
|
247 } |