tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_NetUtil.js (22960B)


      1 /* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
      6 
      7 /**
      8 * This file tests the methods on NetUtil.sys.mjs.
      9 */
     10 
     11 "use strict";
     12 
     13 const { HttpServer } = ChromeUtils.importESModule(
     14  "resource://testing-common/httpd.sys.mjs"
     15 );
     16 
     17 // We need the profile directory so the test harness will clean up our test
     18 // files.
     19 do_get_profile();
     20 
     21 const OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/file-output-stream;1";
     22 const SAFE_OUTPUT_STREAM_CONTRACT_ID =
     23  "@mozilla.org/network/safe-file-output-stream;1";
     24 
     25 ////////////////////////////////////////////////////////////////////////////////
     26 //// Helper Methods
     27 
     28 /**
     29 * Reads the contents of a file and returns it as a string.
     30 *
     31 * @param aFile
     32 *        The file to return from.
     33 * @return the contents of the file in the form of a string.
     34 */
     35 function getFileContents(aFile) {
     36  "use strict";
     37 
     38  let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
     39    Ci.nsIFileInputStream
     40  );
     41  fstream.init(aFile, -1, 0, 0);
     42 
     43  let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(
     44    Ci.nsIConverterInputStream
     45  );
     46  cstream.init(fstream, "UTF-8", 0, 0);
     47 
     48  let string = {};
     49  cstream.readString(-1, string);
     50  cstream.close();
     51  return string.value;
     52 }
     53 
     54 /**
     55 * Tests asynchronously writing a file using NetUtil.asyncCopy.
     56 *
     57 * @param aContractId
     58 *        The contract ID to use for the output stream
     59 * @param aDeferOpen
     60 *        Whether to use DEFER_OPEN in the output stream.
     61 */
     62 function async_write_file(aContractId, aDeferOpen) {
     63  do_test_pending();
     64 
     65  // First, we need an output file to write to.
     66  let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
     67  file.append("NetUtil-async-test-file.tmp");
     68  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
     69 
     70  // Then, we need an output stream to our output file.
     71  let ostream = Cc[aContractId].createInstance(Ci.nsIFileOutputStream);
     72  ostream.init(
     73    file,
     74    -1,
     75    -1,
     76    aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0
     77  );
     78 
     79  // Finally, we need an input stream to take data from.
     80  const TEST_DATA = "this is a test string";
     81  let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
     82    Ci.nsIStringInputStream
     83  );
     84  istream.setByteStringData(TEST_DATA);
     85 
     86  NetUtil.asyncCopy(istream, ostream, function (aResult) {
     87    // Make sure the copy was successful!
     88    Assert.ok(Components.isSuccessCode(aResult));
     89 
     90    // Check the file contents.
     91    Assert.equal(TEST_DATA, getFileContents(file));
     92 
     93    // Finish the test.
     94    do_test_finished();
     95    run_next_test();
     96  });
     97 }
     98 
     99 ////////////////////////////////////////////////////////////////////////////////
    100 //// Tests
    101 
    102 // Test NetUtil.asyncCopy for all possible buffering scenarios
    103 function test_async_copy() {
    104  // Create a data sample
    105  function make_sample(text) {
    106    let data = [];
    107    for (let i = 0; i <= 100; ++i) {
    108      data.push(text);
    109    }
    110    return data.join();
    111  }
    112 
    113  // Create an input buffer holding some data
    114  function make_input(isBuffered, data) {
    115    if (isBuffered) {
    116      // String input streams are buffered
    117      let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
    118        Ci.nsIStringInputStream
    119      );
    120      istream.setByteStringData(data);
    121      return istream;
    122    }
    123 
    124    // File input streams are not buffered, so let's create a file
    125    let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
    126    file.append("NetUtil-asyncFetch-test-file.tmp");
    127    file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
    128 
    129    let ostream = Cc[
    130      "@mozilla.org/network/file-output-stream;1"
    131    ].createInstance(Ci.nsIFileOutputStream);
    132    ostream.init(file, -1, -1, 0);
    133    ostream.write(data, data.length);
    134    ostream.close();
    135 
    136    let istream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
    137      Ci.nsIFileInputStream
    138    );
    139    istream.init(file, -1, 0, 0);
    140 
    141    return istream;
    142  }
    143 
    144  // Create an output buffer holding some data
    145  function make_output(isBuffered) {
    146    let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
    147    file.append("NetUtil-asyncFetch-test-file.tmp");
    148    file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
    149 
    150    let ostream = Cc[
    151      "@mozilla.org/network/file-output-stream;1"
    152    ].createInstance(Ci.nsIFileOutputStream);
    153    ostream.init(file, -1, -1, 0);
    154 
    155    if (!isBuffered) {
    156      return { file, sink: ostream };
    157    }
    158 
    159    let bstream = Cc[
    160      "@mozilla.org/network/buffered-output-stream;1"
    161    ].createInstance(Ci.nsIBufferedOutputStream);
    162    bstream.init(ostream, 256);
    163    return { file, sink: bstream };
    164  }
    165  (async function () {
    166    do_test_pending();
    167    for (let bufferedInput of [true, false]) {
    168      for (let bufferedOutput of [true, false]) {
    169        let text =
    170          "test_async_copy with " +
    171          (bufferedInput ? "buffered input" : "unbuffered input") +
    172          ", " +
    173          (bufferedOutput ? "buffered output" : "unbuffered output");
    174        info(text);
    175        let TEST_DATA = "[" + make_sample(text) + "]";
    176        let source = make_input(bufferedInput, TEST_DATA);
    177        let { file, sink } = make_output(bufferedOutput);
    178        let result = await new Promise(resolve => {
    179          NetUtil.asyncCopy(source, sink, resolve);
    180        });
    181 
    182        // Make sure the copy was successful!
    183        if (!Components.isSuccessCode(result)) {
    184          do_throw(new Components.Exception("asyncCopy error", result));
    185        }
    186 
    187        // Check the file contents.
    188        Assert.equal(TEST_DATA, getFileContents(file));
    189      }
    190    }
    191 
    192    do_test_finished();
    193    run_next_test();
    194  })();
    195 }
    196 
    197 function test_async_write_file() {
    198  async_write_file(OUTPUT_STREAM_CONTRACT_ID);
    199 }
    200 
    201 function test_async_write_file_deferred() {
    202  async_write_file(OUTPUT_STREAM_CONTRACT_ID, true);
    203 }
    204 
    205 function test_async_write_file_safe() {
    206  async_write_file(SAFE_OUTPUT_STREAM_CONTRACT_ID);
    207 }
    208 
    209 function test_async_write_file_safe_deferred() {
    210  async_write_file(SAFE_OUTPUT_STREAM_CONTRACT_ID, true);
    211 }
    212 
    213 function test_newURI_no_spec_throws() {
    214  try {
    215    NetUtil.newURI();
    216    do_throw("should throw!");
    217  } catch (e) {
    218    Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
    219  }
    220 
    221  run_next_test();
    222 }
    223 
    224 function test_newURI() {
    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 = Services.io.newURI(TEST_URI);
    229  let NetUtilURI = NetUtil.newURI(TEST_URI);
    230  Assert.ok(iosURI.equals(NetUtilURI));
    231 
    232  run_next_test();
    233 }
    234 
    235 function test_newURI_takes_nsIFile() {
    236  // Create a test file that we can pass into NetUtil.newURI
    237  let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
    238  file.append("NetUtil-test-file.tmp");
    239 
    240  // Check that we get the same URI back from the IO service and the utility
    241  // method.
    242  let iosURI = Services.io.newFileURI(file);
    243  let NetUtilURI = NetUtil.newURI(file);
    244  Assert.ok(iosURI.equals(NetUtilURI));
    245 
    246  run_next_test();
    247 }
    248 
    249 function test_asyncFetch_no_channel() {
    250  try {
    251    NetUtil.asyncFetch(null, function () {});
    252    do_throw("should throw!");
    253  } catch (e) {
    254    Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
    255  }
    256 
    257  run_next_test();
    258 }
    259 
    260 function test_asyncFetch_no_callback() {
    261  try {
    262    NetUtil.asyncFetch({});
    263    do_throw("should throw!");
    264  } catch (e) {
    265    Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
    266  }
    267 
    268  run_next_test();
    269 }
    270 
    271 function test_asyncFetch_with_nsIChannel() {
    272  const TEST_DATA = "this is a test string";
    273 
    274  // Start the http server, and register our handler.
    275  let server = new HttpServer();
    276  server.registerPathHandler("/test", function (aRequest, aResponse) {
    277    aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
    278    aResponse.setHeader("Content-Type", "text/plain", false);
    279    aResponse.write(TEST_DATA);
    280  });
    281  server.start(-1);
    282 
    283  // Create our channel.
    284  let channel = NetUtil.newChannel({
    285    uri: "http://localhost:" + server.identity.primaryPort + "/test",
    286    loadUsingSystemPrincipal: true,
    287  });
    288 
    289  // Open our channel asynchronously.
    290  NetUtil.asyncFetch(channel, function (aInputStream, aResult) {
    291    // Check that we had success.
    292    Assert.ok(Components.isSuccessCode(aResult));
    293 
    294    // Check that we got the right data.
    295    Assert.equal(aInputStream.available(), TEST_DATA.length);
    296    let is = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
    297      Ci.nsIScriptableInputStream
    298    );
    299    is.init(aInputStream);
    300    let result = is.read(TEST_DATA.length);
    301    Assert.equal(TEST_DATA, result);
    302 
    303    server.stop(run_next_test);
    304  });
    305 }
    306 
    307 function test_asyncFetch_with_nsIURI() {
    308  const TEST_DATA = "this is a test string";
    309 
    310  // Start the http server, and register our handler.
    311  let server = new HttpServer();
    312  server.registerPathHandler("/test", function (aRequest, aResponse) {
    313    aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
    314    aResponse.setHeader("Content-Type", "text/plain", false);
    315    aResponse.write(TEST_DATA);
    316  });
    317  server.start(-1);
    318 
    319  // Create our URI.
    320  let uri = NetUtil.newURI(
    321    "http://localhost:" + server.identity.primaryPort + "/test"
    322  );
    323 
    324  // Open our URI asynchronously.
    325  NetUtil.asyncFetch(
    326    {
    327      uri,
    328      loadUsingSystemPrincipal: true,
    329    },
    330    function (aInputStream, aResult) {
    331      // Check that we had success.
    332      Assert.ok(Components.isSuccessCode(aResult));
    333 
    334      // Check that we got the right data.
    335      Assert.equal(aInputStream.available(), TEST_DATA.length);
    336      let is = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
    337        Ci.nsIScriptableInputStream
    338      );
    339      is.init(aInputStream);
    340      let result = is.read(TEST_DATA.length);
    341      Assert.equal(TEST_DATA, result);
    342 
    343      server.stop(run_next_test);
    344    },
    345    null, // aLoadingNode
    346    Services.scriptSecurityManager.getSystemPrincipal(),
    347    null, // aTriggeringPrincipal
    348    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    349    Ci.nsIContentPolicy.TYPE_OTHER
    350  );
    351 }
    352 
    353 function test_asyncFetch_with_string() {
    354  const TEST_DATA = "this is a test string";
    355 
    356  // Start the http server, and register our handler.
    357  let server = new HttpServer();
    358  server.registerPathHandler("/test", function (aRequest, aResponse) {
    359    aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
    360    aResponse.setHeader("Content-Type", "text/plain", false);
    361    aResponse.write(TEST_DATA);
    362  });
    363  server.start(-1);
    364 
    365  // Open our location asynchronously.
    366  NetUtil.asyncFetch(
    367    {
    368      uri: "http://localhost:" + server.identity.primaryPort + "/test",
    369      loadUsingSystemPrincipal: true,
    370    },
    371    function (aInputStream, aResult) {
    372      // Check that we had success.
    373      Assert.ok(Components.isSuccessCode(aResult));
    374 
    375      // Check that we got the right data.
    376      Assert.equal(aInputStream.available(), TEST_DATA.length);
    377      let is = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
    378        Ci.nsIScriptableInputStream
    379      );
    380      is.init(aInputStream);
    381      let result = is.read(TEST_DATA.length);
    382      Assert.equal(TEST_DATA, result);
    383 
    384      server.stop(run_next_test);
    385    },
    386    null, // aLoadingNode
    387    Services.scriptSecurityManager.getSystemPrincipal(),
    388    null, // aTriggeringPrincipal
    389    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    390    Ci.nsIContentPolicy.TYPE_OTHER
    391  );
    392 }
    393 
    394 function test_asyncFetch_with_nsIFile() {
    395  const TEST_DATA = "this is a test string";
    396 
    397  // First we need a file to read from.
    398  let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
    399  file.append("NetUtil-asyncFetch-test-file.tmp");
    400  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
    401 
    402  // Write the test data to the file.
    403  let ostream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(
    404    Ci.nsIFileOutputStream
    405  );
    406  ostream.init(file, -1, -1, 0);
    407  ostream.write(TEST_DATA, TEST_DATA.length);
    408 
    409  // Sanity check to make sure the data was written.
    410  Assert.equal(TEST_DATA, getFileContents(file));
    411 
    412  // Open our file asynchronously.
    413  // Note that this causes main-tread I/O and should be avoided in production.
    414  NetUtil.asyncFetch(
    415    {
    416      uri: NetUtil.newURI(file),
    417      loadUsingSystemPrincipal: true,
    418    },
    419    function (aInputStream, aResult) {
    420      // Check that we had success.
    421      Assert.ok(Components.isSuccessCode(aResult));
    422 
    423      // Check that we got the right data.
    424      Assert.equal(aInputStream.available(), TEST_DATA.length);
    425      let is = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
    426        Ci.nsIScriptableInputStream
    427      );
    428      is.init(aInputStream);
    429      let result = is.read(TEST_DATA.length);
    430      Assert.equal(TEST_DATA, result);
    431 
    432      run_next_test();
    433    },
    434    null, // aLoadingNode
    435    Services.scriptSecurityManager.getSystemPrincipal(),
    436    null, // aTriggeringPrincipal
    437    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    438    Ci.nsIContentPolicy.TYPE_OTHER
    439  );
    440 }
    441 
    442 function test_asyncFetch_with_nsIInputString() {
    443  const TEST_DATA = "this is a test string";
    444  let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
    445    Ci.nsIStringInputStream
    446  );
    447  istream.setByteStringData(TEST_DATA);
    448 
    449  // Read the input stream asynchronously.
    450  NetUtil.asyncFetch(
    451    istream,
    452    function (aInputStream, aResult) {
    453      // Check that we had success.
    454      Assert.ok(Components.isSuccessCode(aResult));
    455 
    456      // Check that we got the right data.
    457      Assert.equal(aInputStream.available(), TEST_DATA.length);
    458      Assert.equal(
    459        NetUtil.readInputStreamToString(aInputStream, TEST_DATA.length),
    460        TEST_DATA
    461      );
    462 
    463      run_next_test();
    464    },
    465    null, // aLoadingNode
    466    Services.scriptSecurityManager.getSystemPrincipal(),
    467    null, // aTriggeringPrincipal
    468    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    469    Ci.nsIContentPolicy.TYPE_OTHER
    470  );
    471 }
    472 
    473 function test_asyncFetch_does_not_block() {
    474  // Create our channel that has no data.
    475  let channel = NetUtil.newChannel({
    476    uri: "data:text/plain,",
    477    loadUsingSystemPrincipal: true,
    478  });
    479 
    480  // Open our channel asynchronously.
    481  NetUtil.asyncFetch(channel, function (aInputStream, aResult) {
    482    // Check that we had success.
    483    Assert.ok(Components.isSuccessCode(aResult));
    484 
    485    // Check that reading a byte throws that the stream was closed (as opposed
    486    // saying it would block).
    487    let is = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
    488      Ci.nsIScriptableInputStream
    489    );
    490    is.init(aInputStream);
    491    try {
    492      is.read(1);
    493      do_throw("should throw!");
    494    } catch (e) {
    495      Assert.equal(e.result, Cr.NS_BASE_STREAM_CLOSED);
    496    }
    497 
    498    run_next_test();
    499  });
    500 }
    501 
    502 function test_newChannel_no_specifier() {
    503  try {
    504    NetUtil.newChannel();
    505    do_throw("should throw!");
    506  } catch (e) {
    507    Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
    508  }
    509 
    510  run_next_test();
    511 }
    512 
    513 function test_newChannel_with_string() {
    514  const TEST_SPEC = "http://mozilla.org";
    515 
    516  // Check that we get the same URI back from channel the IO service creates and
    517  // the channel the utility method creates.
    518  let iosChannel = Services.io.newChannel(
    519    TEST_SPEC,
    520    null,
    521    null,
    522    null, // aLoadingNode
    523    Services.scriptSecurityManager.getSystemPrincipal(),
    524    null, // aTriggeringPrincipal
    525    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    526    Ci.nsIContentPolicy.TYPE_OTHER
    527  );
    528  let NetUtilChannel = NetUtil.newChannel({
    529    uri: TEST_SPEC,
    530    loadUsingSystemPrincipal: true,
    531  });
    532  Assert.ok(iosChannel.URI.equals(NetUtilChannel.URI));
    533 
    534  run_next_test();
    535 }
    536 
    537 function test_newChannel_with_nsIURI() {
    538  const TEST_SPEC = "http://mozilla.org";
    539 
    540  // Check that we get the same URI back from channel the IO service creates and
    541  // the channel the utility method creates.
    542  let uri = NetUtil.newURI(TEST_SPEC);
    543  let iosChannel = Services.io.newChannelFromURI(
    544    uri,
    545    null, // aLoadingNode
    546    Services.scriptSecurityManager.getSystemPrincipal(),
    547    null, // aTriggeringPrincipal
    548    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    549    Ci.nsIContentPolicy.TYPE_OTHER
    550  );
    551  let NetUtilChannel = NetUtil.newChannel({
    552    uri,
    553    loadUsingSystemPrincipal: true,
    554  });
    555  Assert.ok(iosChannel.URI.equals(NetUtilChannel.URI));
    556 
    557  run_next_test();
    558 }
    559 
    560 function test_newChannel_with_options() {
    561  let uri = "data:text/plain,";
    562 
    563  let iosChannel = Services.io.newChannelFromURI(
    564    NetUtil.newURI(uri),
    565    null, // aLoadingNode
    566    Services.scriptSecurityManager.getSystemPrincipal(),
    567    null, // aTriggeringPrincipal
    568    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    569    Ci.nsIContentPolicy.TYPE_OTHER
    570  );
    571 
    572  function checkEqualToIOSChannel(channel) {
    573    Assert.ok(iosChannel.URI.equals(channel.URI));
    574  }
    575 
    576  checkEqualToIOSChannel(
    577    NetUtil.newChannel({
    578      uri,
    579      loadingPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
    580      securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    581      contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
    582    })
    583  );
    584 
    585  checkEqualToIOSChannel(
    586    NetUtil.newChannel({
    587      uri,
    588      loadUsingSystemPrincipal: true,
    589    })
    590  );
    591 
    592  run_next_test();
    593 }
    594 
    595 function test_newChannel_with_wrong_options() {
    596  let uri = "data:text/plain,";
    597  let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
    598 
    599  Assert.throws(() => {
    600    NetUtil.newChannel({ uri, loadUsingSystemPrincipal: true }, null, null);
    601  }, /requires a single object argument/);
    602 
    603  Assert.throws(() => {
    604    NetUtil.newChannel({ loadUsingSystemPrincipal: true });
    605  }, /requires the 'uri' property/);
    606 
    607  Assert.throws(() => {
    608    NetUtil.newChannel({ uri, loadingNode: true });
    609  }, /requires the 'securityFlags'/);
    610 
    611  Assert.throws(() => {
    612    NetUtil.newChannel({ uri, securityFlags: 0 });
    613  }, /requires at least one of the 'loadingNode'/);
    614 
    615  Assert.throws(() => {
    616    NetUtil.newChannel({
    617      uri,
    618      loadingPrincipal: systemPrincipal,
    619      securityFlags: 0,
    620    });
    621  }, /requires the 'contentPolicyType'/);
    622 
    623  Assert.throws(() => {
    624    NetUtil.newChannel({
    625      uri,
    626      loadUsingSystemPrincipal: systemPrincipal,
    627    });
    628  }, /to be 'true' or 'undefined'/);
    629 
    630  Assert.throws(() => {
    631    NetUtil.newChannel({
    632      uri,
    633      loadingPrincipal: systemPrincipal,
    634      loadUsingSystemPrincipal: true,
    635    });
    636  }, /does not accept 'loadUsingSystemPrincipal'/);
    637 
    638  run_next_test();
    639 }
    640 
    641 function test_readInputStreamToString() {
    642  const TEST_DATA = "this is a test string\0 with an embedded null";
    643  let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
    644    Ci.nsISupportsCString
    645  );
    646  istream.data = TEST_DATA;
    647 
    648  Assert.equal(
    649    NetUtil.readInputStreamToString(istream, TEST_DATA.length),
    650    TEST_DATA
    651  );
    652 
    653  run_next_test();
    654 }
    655 
    656 function test_readInputStreamToString_no_input_stream() {
    657  try {
    658    NetUtil.readInputStreamToString("hi", 2);
    659    do_throw("should throw!");
    660  } catch (e) {
    661    Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
    662  }
    663 
    664  run_next_test();
    665 }
    666 
    667 function test_readInputStreamToString_no_bytes_arg() {
    668  const TEST_DATA = "this is a test string";
    669  let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
    670    Ci.nsIStringInputStream
    671  );
    672  istream.setByteStringData(TEST_DATA);
    673 
    674  try {
    675    NetUtil.readInputStreamToString(istream);
    676    do_throw("should throw!");
    677  } catch (e) {
    678    Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
    679  }
    680 
    681  run_next_test();
    682 }
    683 
    684 function test_readInputStreamToString_blocking_stream() {
    685  let pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
    686  pipe.init(true, true, 0, 0, null);
    687 
    688  try {
    689    NetUtil.readInputStreamToString(pipe.inputStream, 10);
    690    do_throw("should throw!");
    691  } catch (e) {
    692    Assert.equal(e.result, Cr.NS_BASE_STREAM_WOULD_BLOCK);
    693  }
    694  run_next_test();
    695 }
    696 
    697 function test_readInputStreamToString_too_many_bytes() {
    698  const TEST_DATA = "this is a test string";
    699  let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
    700    Ci.nsIStringInputStream
    701  );
    702  istream.setByteStringData(TEST_DATA);
    703 
    704  try {
    705    NetUtil.readInputStreamToString(istream, TEST_DATA.length + 10);
    706    do_throw("should throw!");
    707  } catch (e) {
    708    Assert.equal(e.result, Cr.NS_ERROR_FAILURE);
    709  }
    710 
    711  run_next_test();
    712 }
    713 
    714 function test_readInputStreamToString_with_charset() {
    715  const TEST_DATA = "\uff10\uff11\uff12\uff13";
    716  const TEST_DATA_UTF8 = "\xef\xbc\x90\xef\xbc\x91\xef\xbc\x92\xef\xbc\x93";
    717  const TEST_DATA_SJIS = "\x82\x4f\x82\x50\x82\x51\x82\x52";
    718 
    719  let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
    720    Ci.nsIStringInputStream
    721  );
    722 
    723  istream.setByteStringData(TEST_DATA_UTF8);
    724  Assert.equal(
    725    NetUtil.readInputStreamToString(istream, TEST_DATA_UTF8.length, {
    726      charset: "UTF-8",
    727    }),
    728    TEST_DATA
    729  );
    730 
    731  istream.setByteStringData(TEST_DATA_SJIS);
    732  Assert.equal(
    733    NetUtil.readInputStreamToString(istream, TEST_DATA_SJIS.length, {
    734      charset: "Shift_JIS",
    735    }),
    736    TEST_DATA
    737  );
    738 
    739  run_next_test();
    740 }
    741 
    742 function test_readInputStreamToString_invalid_sequence() {
    743  const TEST_DATA = "\ufffd\ufffd\ufffd\ufffd";
    744  const TEST_DATA_UTF8 = "\xaa\xaa\xaa\xaa";
    745 
    746  let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
    747    Ci.nsIStringInputStream
    748  );
    749 
    750  istream.setByteStringData(TEST_DATA_UTF8);
    751  try {
    752    NetUtil.readInputStreamToString(istream, TEST_DATA_UTF8.length, {
    753      charset: "UTF-8",
    754    });
    755    do_throw("should throw!");
    756  } catch (e) {
    757    Assert.equal(e.result, Cr.NS_ERROR_ILLEGAL_INPUT);
    758  }
    759 
    760  istream.setByteStringData(TEST_DATA_UTF8);
    761  Assert.equal(
    762    NetUtil.readInputStreamToString(istream, TEST_DATA_UTF8.length, {
    763      charset: "UTF-8",
    764      replacement: Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER,
    765    }),
    766    TEST_DATA
    767  );
    768 
    769  run_next_test();
    770 }
    771 
    772 ////////////////////////////////////////////////////////////////////////////////
    773 //// Test Runner
    774 
    775 [
    776  test_async_copy,
    777  test_async_write_file,
    778  test_async_write_file_deferred,
    779  test_async_write_file_safe,
    780  test_async_write_file_safe_deferred,
    781  test_newURI_no_spec_throws,
    782  test_newURI,
    783  test_newURI_takes_nsIFile,
    784  test_asyncFetch_no_channel,
    785  test_asyncFetch_no_callback,
    786  test_asyncFetch_with_nsIChannel,
    787  test_asyncFetch_with_nsIURI,
    788  test_asyncFetch_with_string,
    789  test_asyncFetch_with_nsIFile,
    790  test_asyncFetch_with_nsIInputString,
    791  test_asyncFetch_does_not_block,
    792  test_newChannel_no_specifier,
    793  test_newChannel_with_string,
    794  test_newChannel_with_nsIURI,
    795  test_newChannel_with_options,
    796  test_newChannel_with_wrong_options,
    797  test_readInputStreamToString,
    798  test_readInputStreamToString_no_input_stream,
    799  test_readInputStreamToString_no_bytes_arg,
    800  test_readInputStreamToString_blocking_stream,
    801  test_readInputStreamToString_too_many_bytes,
    802  test_readInputStreamToString_with_charset,
    803  test_readInputStreamToString_invalid_sequence,
    804 ].forEach(f => add_test(f));