Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=2 sts=2 et
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /**
8 * This file tests the methods on NetUtil.jsm.
9 */
11 Cu.import("resource://testing-common/httpd.js");
13 Cu.import("resource://gre/modules/NetUtil.jsm");
14 Cu.import("resource://gre/modules/Task.jsm");
15 Cu.import("resource://gre/modules/Promise.jsm");
17 // We need the profile directory so the test harness will clean up our test
18 // files.
19 do_get_profile();
21 const OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/file-output-stream;1";
22 const SAFE_OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/safe-file-output-stream;1";
24 ////////////////////////////////////////////////////////////////////////////////
25 //// Helper Methods
27 /**
28 * Reads the contents of a file and returns it as a string.
29 *
30 * @param aFile
31 * The file to return from.
32 * @return the contents of the file in the form of a string.
33 */
34 function getFileContents(aFile)
35 {
36 "use strict";
38 let fstream = Cc["@mozilla.org/network/file-input-stream;1"].
39 createInstance(Ci.nsIFileInputStream);
40 fstream.init(aFile, -1, 0, 0);
42 let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].
43 createInstance(Ci.nsIConverterInputStream);
44 cstream.init(fstream, "UTF-8", 0, 0);
46 let string = {};
47 cstream.readString(-1, string);
48 cstream.close();
49 return string.value;
50 }
53 /**
54 * Tests asynchronously writing a file using NetUtil.asyncCopy.
55 *
56 * @param aContractId
57 * The contract ID to use for the output stream
58 * @param aDeferOpen
59 * Whether to use DEFER_OPEN in the output stream.
60 */
61 function async_write_file(aContractId, aDeferOpen)
62 {
63 do_test_pending();
65 // First, we need an output file to write to.
66 let file = Cc["@mozilla.org/file/directory_service;1"].
67 getService(Ci.nsIProperties).
68 get("ProfD", Ci.nsIFile);
69 file.append("NetUtil-async-test-file.tmp");
70 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
72 // Then, we need an output stream to our output file.
73 let ostream = Cc[aContractId].createInstance(Ci.nsIFileOutputStream);
74 ostream.init(file, -1, -1, aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0);
76 // Finally, we need an input stream to take data from.
77 const TEST_DATA = "this is a test string";
78 let istream = Cc["@mozilla.org/io/string-input-stream;1"].
79 createInstance(Ci.nsIStringInputStream);
80 istream.setData(TEST_DATA, TEST_DATA.length);
82 NetUtil.asyncCopy(istream, ostream, function(aResult) {
83 // Make sure the copy was successful!
84 do_check_true(Components.isSuccessCode(aResult));
86 // Check the file contents.
87 do_check_eq(TEST_DATA, getFileContents(file));
89 // Finish the test.
90 do_test_finished();
91 run_next_test();
92 });
93 }
95 ////////////////////////////////////////////////////////////////////////////////
96 //// Tests
98 // Test NetUtil.asyncCopy for all possible buffering scenarios
99 function test_async_copy()
100 {
101 // Create a data sample
102 function make_sample(text) {
103 let data = [];
104 for (let i = 0; i <= 100; ++i) {
105 data.push(text);
106 }
107 return data.join();
108 }
110 // Create an input buffer holding some data
111 function make_input(isBuffered, data) {
112 if (isBuffered) {
113 // String input streams are buffered
114 let istream = Cc["@mozilla.org/io/string-input-stream;1"].
115 createInstance(Ci.nsIStringInputStream);
116 istream.setData(data, data.length);
117 return istream;
118 }
120 // File input streams are not buffered, so let's create a file
121 let file = Cc["@mozilla.org/file/directory_service;1"].
122 getService(Ci.nsIProperties).
123 get("ProfD", Ci.nsIFile);
124 file.append("NetUtil-asyncFetch-test-file.tmp");
125 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
127 let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
128 createInstance(Ci.nsIFileOutputStream);
129 ostream.init(file, -1, -1, 0);
130 ostream.write(data, data.length);
131 ostream.close();
133 let istream = Cc["@mozilla.org/network/file-input-stream;1"].
134 createInstance(Ci.nsIFileInputStream);
135 istream.init(file, -1, 0, 0);
137 return istream;
138 }
140 // Create an output buffer holding some data
141 function make_output(isBuffered) {
142 let file = Cc["@mozilla.org/file/directory_service;1"].
143 getService(Ci.nsIProperties).
144 get("ProfD", Ci.nsIFile);
145 file.append("NetUtil-asyncFetch-test-file.tmp");
146 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
148 let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
149 createInstance(Ci.nsIFileOutputStream);
150 ostream.init(file, -1, -1, 0);
152 if (!isBuffered) {
153 return {file: file, sink: ostream};
154 }
156 let bstream = Cc["@mozilla.org/network/buffered-output-stream;1"].
157 createInstance(Ci.nsIBufferedOutputStream);
158 bstream.init(ostream, 256);
159 return {file: file, sink: bstream};
160 }
161 Task.spawn(function*() {
162 do_test_pending();
163 for (let bufferedInput of [true, false]) {
164 for (let bufferedOutput of [true, false]) {
165 let text = "test_async_copy with "
166 + (bufferedInput?"buffered input":"unbuffered input")
167 + ", "
168 + (bufferedOutput?"buffered output":"unbuffered output");
169 do_print(text);
170 let TEST_DATA = "[" + make_sample(text) + "]";
171 let source = make_input(bufferedInput, TEST_DATA);
172 let {file, sink} = make_output(bufferedOutput);
173 let deferred = Promise.defer();
174 NetUtil.asyncCopy(source, sink, deferred.resolve);
175 let result = yield deferred.promise;
177 // Make sure the copy was successful!
178 if (!Components.isSuccessCode(result)) {
179 do_throw(new Components.Exception("asyncCopy error", result));
180 }
182 // Check the file contents.
183 do_check_eq(TEST_DATA, getFileContents(file));
184 }
185 }
187 do_test_finished();
188 run_next_test();
189 });
190 }
192 function test_async_write_file() {
193 async_write_file(OUTPUT_STREAM_CONTRACT_ID);
194 }
196 function test_async_write_file_deferred() {
197 async_write_file(OUTPUT_STREAM_CONTRACT_ID, true);
198 }
200 function test_async_write_file_safe() {
201 async_write_file(SAFE_OUTPUT_STREAM_CONTRACT_ID);
202 }
204 function test_async_write_file_safe_deferred() {
205 async_write_file(SAFE_OUTPUT_STREAM_CONTRACT_ID, true);
206 }
208 function test_newURI_no_spec_throws()
209 {
210 try {
211 NetUtil.newURI();
212 do_throw("should throw!");
213 }
214 catch (e) {
215 do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
216 }
218 run_next_test();
219 }
221 function test_newURI()
222 {
223 let ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
225 // Check that we get the same URI back from the IO service and the utility
226 // method.
227 const TEST_URI = "http://mozilla.org";
228 let iosURI = ios.newURI(TEST_URI, null, null);
229 let NetUtilURI = NetUtil.newURI(TEST_URI);
230 do_check_true(iosURI.equals(NetUtilURI));
232 run_next_test();
233 }
235 function test_newURI_takes_nsIFile()
236 {
237 let ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
239 // Create a test file that we can pass into NetUtil.newURI
240 let file = Cc["@mozilla.org/file/directory_service;1"].
241 getService(Ci.nsIProperties).
242 get("ProfD", Ci.nsIFile);
243 file.append("NetUtil-test-file.tmp");
245 // Check that we get the same URI back from the IO service and the utility
246 // method.
247 let iosURI = ios.newFileURI(file);
248 let NetUtilURI = NetUtil.newURI(file);
249 do_check_true(iosURI.equals(NetUtilURI));
251 run_next_test();
252 }
254 function test_ioService()
255 {
256 do_check_true(NetUtil.ioService instanceof Ci.nsIIOService);
257 run_next_test();
258 }
260 function test_asyncFetch_no_channel()
261 {
262 try {
263 NetUtil.asyncFetch(null, function() { });
264 do_throw("should throw!");
265 }
266 catch (e) {
267 do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
268 }
270 run_next_test();
271 }
273 function test_asyncFetch_no_callback()
274 {
275 try {
276 NetUtil.asyncFetch({ });
277 do_throw("should throw!");
278 }
279 catch (e) {
280 do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
281 }
283 run_next_test();
284 }
286 function test_asyncFetch_with_nsIChannel()
287 {
288 const TEST_DATA = "this is a test string";
290 // Start the http server, and register our handler.
291 let server = new HttpServer();
292 server.registerPathHandler("/test", function(aRequest, aResponse) {
293 aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
294 aResponse.setHeader("Content-Type", "text/plain", false);
295 aResponse.write(TEST_DATA);
296 });
297 server.start(-1);
299 // Create our channel.
300 let channel = NetUtil.ioService.
301 newChannel("http://localhost:" +
302 server.identity.primaryPort + "/test", null, null);
304 // Open our channel asynchronously.
305 NetUtil.asyncFetch(channel, function(aInputStream, aResult) {
306 // Check that we had success.
307 do_check_true(Components.isSuccessCode(aResult));
309 // Check that we got the right data.
310 do_check_eq(aInputStream.available(), TEST_DATA.length);
311 let is = Cc["@mozilla.org/scriptableinputstream;1"].
312 createInstance(Ci.nsIScriptableInputStream);
313 is.init(aInputStream);
314 let result = is.read(TEST_DATA.length);
315 do_check_eq(TEST_DATA, result);
317 server.stop(run_next_test);
318 });
319 }
321 function test_asyncFetch_with_nsIURI()
322 {
323 const TEST_DATA = "this is a test string";
325 // Start the http server, and register our handler.
326 let server = new HttpServer();
327 server.registerPathHandler("/test", function(aRequest, aResponse) {
328 aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
329 aResponse.setHeader("Content-Type", "text/plain", false);
330 aResponse.write(TEST_DATA);
331 });
332 server.start(-1);
334 // Create our URI.
335 let uri = NetUtil.newURI("http://localhost:" +
336 server.identity.primaryPort + "/test");
338 // Open our URI asynchronously.
339 NetUtil.asyncFetch(uri, function(aInputStream, aResult) {
340 // Check that we had success.
341 do_check_true(Components.isSuccessCode(aResult));
343 // Check that we got the right data.
344 do_check_eq(aInputStream.available(), TEST_DATA.length);
345 let is = Cc["@mozilla.org/scriptableinputstream;1"].
346 createInstance(Ci.nsIScriptableInputStream);
347 is.init(aInputStream);
348 let result = is.read(TEST_DATA.length);
349 do_check_eq(TEST_DATA, result);
351 server.stop(run_next_test);
352 });
353 }
355 function test_asyncFetch_with_string()
356 {
357 const TEST_DATA = "this is a test string";
359 // Start the http server, and register our handler.
360 let server = new HttpServer();
361 server.registerPathHandler("/test", function(aRequest, aResponse) {
362 aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
363 aResponse.setHeader("Content-Type", "text/plain", false);
364 aResponse.write(TEST_DATA);
365 });
366 server.start(-1);
368 // Open our location asynchronously.
369 NetUtil.asyncFetch("http://localhost:" +
370 server.identity.primaryPort + "/test",
371 function(aInputStream, aResult) {
372 // Check that we had success.
373 do_check_true(Components.isSuccessCode(aResult));
375 // Check that we got the right data.
376 do_check_eq(aInputStream.available(), TEST_DATA.length);
377 let is = Cc["@mozilla.org/scriptableinputstream;1"].
378 createInstance(Ci.nsIScriptableInputStream);
379 is.init(aInputStream);
380 let result = is.read(TEST_DATA.length);
381 do_check_eq(TEST_DATA, result);
383 server.stop(run_next_test);
384 });
385 }
387 function test_asyncFetch_with_nsIFile()
388 {
389 const TEST_DATA = "this is a test string";
391 // First we need a file to read from.
392 let file = Cc["@mozilla.org/file/directory_service;1"].
393 getService(Ci.nsIProperties).
394 get("ProfD", Ci.nsIFile);
395 file.append("NetUtil-asyncFetch-test-file.tmp");
396 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
398 // Write the test data to the file.
399 let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
400 createInstance(Ci.nsIFileOutputStream);
401 ostream.init(file, -1, -1, 0);
402 ostream.write(TEST_DATA, TEST_DATA.length);
404 // Sanity check to make sure the data was written.
405 do_check_eq(TEST_DATA, getFileContents(file));
407 // Open our file asynchronously.
408 NetUtil.asyncFetch(file, function(aInputStream, aResult) {
409 // Check that we had success.
410 do_check_true(Components.isSuccessCode(aResult));
412 // Check that we got the right data.
413 do_check_eq(aInputStream.available(), TEST_DATA.length);
414 let is = Cc["@mozilla.org/scriptableinputstream;1"].
415 createInstance(Ci.nsIScriptableInputStream);
416 is.init(aInputStream);
417 let result = is.read(TEST_DATA.length);
418 do_check_eq(TEST_DATA, result);
420 run_next_test();
421 });
422 }
424 function test_asyncFetch_with_nsIInputString()
425 {
426 const TEST_DATA = "this is a test string";
427 let istream = Cc["@mozilla.org/io/string-input-stream;1"].
428 createInstance(Ci.nsIStringInputStream);
429 istream.setData(TEST_DATA, TEST_DATA.length);
431 // Read the input stream asynchronously.
432 NetUtil.asyncFetch(istream, function(aInputStream, aResult) {
433 // Check that we had success.
434 do_check_true(Components.isSuccessCode(aResult));
436 // Check that we got the right data.
437 do_check_eq(aInputStream.available(), TEST_DATA.length);
438 do_check_eq(NetUtil.readInputStreamToString(aInputStream, TEST_DATA.length),
439 TEST_DATA);
441 run_next_test();
442 });
443 }
445 function test_asyncFetch_does_not_block()
446 {
447 // Create our channel that has no data.
448 let channel = NetUtil.ioService.
449 newChannel("data:text/plain,", null, null);
451 // Open our channel asynchronously.
452 NetUtil.asyncFetch(channel, function(aInputStream, aResult) {
453 // Check that we had success.
454 do_check_true(Components.isSuccessCode(aResult));
456 // Check that reading a byte throws that the stream was closed (as opposed
457 // saying it would block).
458 let is = Cc["@mozilla.org/scriptableinputstream;1"].
459 createInstance(Ci.nsIScriptableInputStream);
460 is.init(aInputStream);
461 try {
462 is.read(1);
463 do_throw("should throw!");
464 }
465 catch (e) {
466 do_check_eq(e.result, Cr.NS_BASE_STREAM_CLOSED);
467 }
469 run_next_test();
470 });
471 }
473 function test_newChannel_no_specifier()
474 {
475 try {
476 NetUtil.newChannel();
477 do_throw("should throw!");
478 }
479 catch (e) {
480 do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
481 }
483 run_next_test();
484 }
486 function test_newChannel_with_string()
487 {
488 const TEST_SPEC = "http://mozilla.org";
490 // Check that we get the same URI back from channel the IO service creates and
491 // the channel the utility method creates.
492 let ios = NetUtil.ioService;
493 let iosChannel = ios.newChannel(TEST_SPEC, null, null);
494 let NetUtilChannel = NetUtil.newChannel(TEST_SPEC);
495 do_check_true(iosChannel.URI.equals(NetUtilChannel.URI));
497 run_next_test();
498 }
500 function test_newChannel_with_nsIURI()
501 {
502 const TEST_SPEC = "http://mozilla.org";
504 // Check that we get the same URI back from channel the IO service creates and
505 // the channel the utility method creates.
506 let uri = NetUtil.newURI(TEST_SPEC);
507 let iosChannel = NetUtil.ioService.newChannelFromURI(uri);
508 let NetUtilChannel = NetUtil.newChannel(uri);
509 do_check_true(iosChannel.URI.equals(NetUtilChannel.URI));
511 run_next_test();
512 }
514 function test_newChannel_with_nsIFile()
515 {
516 let file = Cc["@mozilla.org/file/directory_service;1"].
517 getService(Ci.nsIProperties).
518 get("ProfD", Ci.nsIFile);
519 file.append("NetUtil-test-file.tmp");
521 // Check that we get the same URI back from channel the IO service creates and
522 // the channel the utility method creates.
523 let uri = NetUtil.newURI(file);
524 let iosChannel = NetUtil.ioService.newChannelFromURI(uri);
525 let NetUtilChannel = NetUtil.newChannel(uri);
526 do_check_true(iosChannel.URI.equals(NetUtilChannel.URI));
528 run_next_test();
529 }
531 function test_readInputStreamToString()
532 {
533 const TEST_DATA = "this is a test string\0 with an embedded null";
534 let istream = Cc["@mozilla.org/io/string-input-stream;1"].
535 createInstance(Ci.nsISupportsCString);
536 istream.data = TEST_DATA;
538 do_check_eq(NetUtil.readInputStreamToString(istream, TEST_DATA.length),
539 TEST_DATA);
541 run_next_test();
542 }
544 function test_readInputStreamToString_no_input_stream()
545 {
546 try {
547 NetUtil.readInputStreamToString("hi", 2);
548 do_throw("should throw!");
549 }
550 catch (e) {
551 do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
552 }
554 run_next_test();
555 }
557 function test_readInputStreamToString_no_bytes_arg()
558 {
559 const TEST_DATA = "this is a test string";
560 let istream = Cc["@mozilla.org/io/string-input-stream;1"].
561 createInstance(Ci.nsIStringInputStream);
562 istream.setData(TEST_DATA, TEST_DATA.length);
564 try {
565 NetUtil.readInputStreamToString(istream);
566 do_throw("should throw!");
567 }
568 catch (e) {
569 do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
570 }
572 run_next_test();
573 }
575 function test_readInputStreamToString_blocking_stream()
576 {
577 let pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
578 pipe.init(true, true, 0, 0, null);
580 try {
581 NetUtil.readInputStreamToString(pipe.inputStream, 10);
582 do_throw("should throw!");
583 }
584 catch (e) {
585 do_check_eq(e.result, Cr.NS_BASE_STREAM_WOULD_BLOCK);
586 }
587 run_next_test();
588 }
590 function test_readInputStreamToString_too_many_bytes()
591 {
592 const TEST_DATA = "this is a test string";
593 let istream = Cc["@mozilla.org/io/string-input-stream;1"].
594 createInstance(Ci.nsIStringInputStream);
595 istream.setData(TEST_DATA, TEST_DATA.length);
597 try {
598 NetUtil.readInputStreamToString(istream, TEST_DATA.length + 10);
599 do_throw("should throw!");
600 }
601 catch (e) {
602 do_check_eq(e.result, Cr.NS_ERROR_FAILURE);
603 }
605 run_next_test();
606 }
608 function test_readInputStreamToString_with_charset()
609 {
610 const TEST_DATA = "\uff10\uff11\uff12\uff13";
611 const TEST_DATA_UTF8 = "\xef\xbc\x90\xef\xbc\x91\xef\xbc\x92\xef\xbc\x93";
612 const TEST_DATA_SJIS = "\x82\x4f\x82\x50\x82\x51\x82\x52";
614 let istream = Cc["@mozilla.org/io/string-input-stream;1"].
615 createInstance(Ci.nsIStringInputStream);
617 istream.setData(TEST_DATA_UTF8, TEST_DATA_UTF8.length);
618 do_check_eq(NetUtil.readInputStreamToString(istream,
619 TEST_DATA_UTF8.length,
620 { charset: "UTF-8"}),
621 TEST_DATA);
623 istream.setData(TEST_DATA_SJIS, TEST_DATA_SJIS.length);
624 do_check_eq(NetUtil.readInputStreamToString(istream,
625 TEST_DATA_SJIS.length,
626 { charset: "Shift_JIS"}),
627 TEST_DATA);
629 run_next_test();
630 }
632 function test_readInputStreamToString_invalid_sequence()
633 {
634 const TEST_DATA = "\ufffd\ufffd\ufffd\ufffd";
635 const TEST_DATA_UTF8 = "\xaa\xaa\xaa\xaa";
637 let istream = Cc["@mozilla.org/io/string-input-stream;1"].
638 createInstance(Ci.nsIStringInputStream);
640 istream.setData(TEST_DATA_UTF8, TEST_DATA_UTF8.length);
641 try {
642 NetUtil.readInputStreamToString(istream,
643 TEST_DATA_UTF8.length,
644 { charset: "UTF-8" });
645 do_throw("should throw!");
646 } catch (e) {
647 do_check_eq(e.result, Cr.NS_ERROR_ILLEGAL_INPUT);
648 }
650 istream.setData(TEST_DATA_UTF8, TEST_DATA_UTF8.length);
651 do_check_eq(NetUtil.readInputStreamToString(istream,
652 TEST_DATA_UTF8.length, {
653 charset: "UTF-8",
654 replacement: Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER}),
655 TEST_DATA);
657 run_next_test();
658 }
661 ////////////////////////////////////////////////////////////////////////////////
662 //// Test Runner
664 [
665 test_async_copy,
666 test_async_write_file,
667 test_async_write_file_deferred,
668 test_async_write_file_safe,
669 test_async_write_file_safe_deferred,
670 test_newURI_no_spec_throws,
671 test_newURI,
672 test_newURI_takes_nsIFile,
673 test_ioService,
674 test_asyncFetch_no_channel,
675 test_asyncFetch_no_callback,
676 test_asyncFetch_with_nsIChannel,
677 test_asyncFetch_with_nsIURI,
678 test_asyncFetch_with_string,
679 test_asyncFetch_with_nsIFile,
680 test_asyncFetch_with_nsIInputString,
681 test_asyncFetch_does_not_block,
682 test_newChannel_no_specifier,
683 test_newChannel_with_string,
684 test_newChannel_with_nsIURI,
685 test_newChannel_with_nsIFile,
686 test_readInputStreamToString,
687 test_readInputStreamToString_no_input_stream,
688 test_readInputStreamToString_no_bytes_arg,
689 test_readInputStreamToString_blocking_stream,
690 test_readInputStreamToString_too_many_bytes,
691 test_readInputStreamToString_with_charset,
692 test_readInputStreamToString_invalid_sequence,
693 ].forEach(add_test);
694 let index = 0;
696 function run_test()
697 {
698 run_next_test();
699 }