tor-browser

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

test_filestreams.js (8311B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // We need the profile directory so the test harness will clean up our test
      7 // files.
      8 do_get_profile();
      9 
     10 const OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/file-output-stream;1";
     11 const SAFE_OUTPUT_STREAM_CONTRACT_ID =
     12  "@mozilla.org/network/safe-file-output-stream;1";
     13 
     14 ////////////////////////////////////////////////////////////////////////////////
     15 //// Helper Methods
     16 
     17 /**
     18 * Generates a leafName for a file that does not exist, but does *not*
     19 * create the file. Similar to createUnique except for the fact that createUnique
     20 * does create the file.
     21 *
     22 * @param aFile
     23 *        The file to modify in order for it to have a unique leafname.
     24 */
     25 function ensure_unique(aFile) {
     26  ensure_unique.fileIndex = ensure_unique.fileIndex || 0;
     27 
     28  var leafName = aFile.leafName;
     29  while (aFile.clone().exists()) {
     30    aFile.leafName = leafName + "_" + ensure_unique.fileIndex++;
     31  }
     32 }
     33 
     34 /**
     35 * Tests for files being accessed at the right time. Streams that use
     36 * DEFER_OPEN should only open or create the file when an operation is
     37 * done, and not during Init().
     38 *
     39 * Note that for writing, we check for actual writing in test_NetUtil (async)
     40 * and in sync_operations in this file (sync), whereas in this function we
     41 * just check that the file is *not* created during init.
     42 *
     43 * @param aContractId
     44 *        The contract ID to use for the output stream
     45 * @param aDeferOpen
     46 *        Whether to check with DEFER_OPEN or not
     47 * @param aTrickDeferredOpen
     48 *        Whether we try to 'trick' deferred opens by changing the file object before
     49 *        the actual open. The stream should have a clone, so changes to the file
     50 *        object after Init and before Open should not affect it.
     51 */
     52 function check_access(aContractId, aDeferOpen, aTrickDeferredOpen) {
     53  const LEAF_NAME = "filestreams-test-file.tmp";
     54  const TRICKY_LEAF_NAME = "BetYouDidNotExpectThat.tmp";
     55  let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
     56  file.append(LEAF_NAME);
     57 
     58  // Writing
     59 
     60  ensure_unique(file);
     61  let ostream = Cc[aContractId].createInstance(Ci.nsIFileOutputStream);
     62  ostream.init(
     63    file,
     64    -1,
     65    -1,
     66    aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0
     67  );
     68  Assert.equal(aDeferOpen, !file.clone().exists()); // If defer, should not exist and vice versa
     69  if (aDeferOpen) {
     70    // File should appear when we do write to it.
     71    if (aTrickDeferredOpen) {
     72      // See |@param aDeferOpen| in the JavaDoc comment for this function
     73      file.leafName = TRICKY_LEAF_NAME;
     74    }
     75    ostream.write("data", 4);
     76    if (aTrickDeferredOpen) {
     77      file.leafName = LEAF_NAME;
     78    }
     79    // We did a write, so the file should now exist
     80    Assert.ok(file.clone().exists());
     81  }
     82  ostream.close();
     83 
     84  // Reading
     85 
     86  ensure_unique(file);
     87  let istream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
     88    Ci.nsIFileInputStream
     89  );
     90  var initOk, getOk;
     91  try {
     92    istream.init(
     93      file,
     94      -1,
     95      0,
     96      aDeferOpen ? Ci.nsIFileInputStream.DEFER_OPEN : 0
     97    );
     98    initOk = true;
     99  } catch (e) {
    100    initOk = false;
    101  }
    102  try {
    103    let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
    104      Ci.nsIFileInputStream
    105    );
    106    fstream.init(file, -1, 0, 0);
    107    getOk = true;
    108  } catch (e) {
    109    getOk = false;
    110  }
    111 
    112  // If the open is deferred, then Init should succeed even though the file we
    113  // intend to read does not exist, and then trying to read from it should
    114  // fail. The other case is where the open is not deferred, and there we should
    115  // get an error when we Init (and also when we try to read).
    116  Assert.ok(
    117    (aDeferOpen && initOk && !getOk) || (!aDeferOpen && !initOk && !getOk)
    118  );
    119  istream.close();
    120 }
    121 
    122 /**
    123 * We test async operations in test_NetUtil.js, and here test for simple sync
    124 * operations on input streams.
    125 *
    126 * @param aDeferOpen
    127 *        Whether to use DEFER_OPEN in the streams.
    128 */
    129 function sync_operations(aDeferOpen) {
    130  const TEST_DATA = "this is a test string";
    131  const LEAF_NAME = "filestreams-test-file.tmp";
    132 
    133  let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
    134  file.append(LEAF_NAME);
    135  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
    136 
    137  let ostream = Cc[OUTPUT_STREAM_CONTRACT_ID].createInstance(
    138    Ci.nsIFileOutputStream
    139  );
    140  ostream.init(
    141    file,
    142    -1,
    143    -1,
    144    aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0
    145  );
    146 
    147  ostream.write(TEST_DATA, TEST_DATA.length);
    148  ostream.close();
    149 
    150  let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
    151    Ci.nsIFileInputStream
    152  );
    153  fstream.init(file, -1, 0, aDeferOpen ? Ci.nsIFileInputStream.DEFER_OPEN : 0);
    154 
    155  let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(
    156    Ci.nsIConverterInputStream
    157  );
    158  cstream.init(fstream, "UTF-8", 0, 0);
    159 
    160  let string = {};
    161  cstream.readString(-1, string);
    162  cstream.close();
    163  fstream.close();
    164 
    165  Assert.equal(string.value, TEST_DATA);
    166 }
    167 
    168 ////////////////////////////////////////////////////////////////////////////////
    169 //// Tests
    170 
    171 function test_access() {
    172  check_access(OUTPUT_STREAM_CONTRACT_ID, false, false);
    173 }
    174 
    175 function test_access_trick() {
    176  check_access(OUTPUT_STREAM_CONTRACT_ID, false, true);
    177 }
    178 
    179 function test_access_defer() {
    180  check_access(OUTPUT_STREAM_CONTRACT_ID, true, false);
    181 }
    182 
    183 function test_access_defer_trick() {
    184  check_access(OUTPUT_STREAM_CONTRACT_ID, true, true);
    185 }
    186 
    187 function test_access_safe() {
    188  check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, false, false);
    189 }
    190 
    191 function test_access_safe_trick() {
    192  check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, false, true);
    193 }
    194 
    195 function test_access_safe_defer() {
    196  check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, true, false);
    197 }
    198 
    199 function test_access_safe_defer_trick() {
    200  check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, true, true);
    201 }
    202 
    203 function test_sync_operations() {
    204  sync_operations();
    205 }
    206 
    207 function test_sync_operations_deferred() {
    208  sync_operations(true);
    209 }
    210 
    211 function do_test_zero_size_buffered(disableBuffering) {
    212  const LEAF_NAME = "filestreams-test-file.tmp";
    213  const BUFFERSIZE = 4096;
    214 
    215  let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
    216  file.append(LEAF_NAME);
    217  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
    218 
    219  let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
    220    Ci.nsIFileInputStream
    221  );
    222  fstream.init(
    223    file,
    224    -1,
    225    0,
    226    Ci.nsIFileInputStream.CLOSE_ON_EOF | Ci.nsIFileInputStream.REOPEN_ON_REWIND
    227  );
    228 
    229  var buffered = Cc[
    230    "@mozilla.org/network/buffered-input-stream;1"
    231  ].createInstance(Ci.nsIBufferedInputStream);
    232  buffered.init(fstream, BUFFERSIZE);
    233 
    234  if (disableBuffering) {
    235    buffered.QueryInterface(Ci.nsIStreamBufferAccess).disableBuffering();
    236  }
    237 
    238  // Scriptable input streams clamp read sizes to the return value of
    239  // available(), so don't quite do what we want here.
    240  let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(
    241    Ci.nsIConverterInputStream
    242  );
    243  cstream.init(buffered, "UTF-8", 0, 0);
    244 
    245  Assert.equal(buffered.available(), 0);
    246 
    247  // Now try reading from this stream
    248  let string = {};
    249  Assert.equal(cstream.readString(BUFFERSIZE, string), 0);
    250  Assert.equal(string.value, "");
    251 
    252  // Now check that available() throws
    253  var exceptionThrown = false;
    254  try {
    255    Assert.equal(buffered.available(), 0);
    256  } catch (e) {
    257    exceptionThrown = true;
    258  }
    259  Assert.ok(exceptionThrown);
    260 
    261  // OK, now seek back to start
    262  buffered.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
    263 
    264  // Now check that available() does not throw
    265  exceptionThrown = false;
    266  try {
    267    Assert.equal(buffered.available(), 0);
    268  } catch (e) {
    269    exceptionThrown = true;
    270  }
    271  Assert.ok(!exceptionThrown);
    272 }
    273 
    274 function test_zero_size_buffered() {
    275  do_test_zero_size_buffered(false);
    276  do_test_zero_size_buffered(true);
    277 }
    278 
    279 ////////////////////////////////////////////////////////////////////////////////
    280 //// Test Runner
    281 
    282 var tests = [
    283  test_access,
    284  test_access_trick,
    285  test_access_defer,
    286  test_access_defer_trick,
    287  test_access_safe,
    288  test_access_safe_trick,
    289  test_access_safe_defer,
    290  test_access_safe_defer_trick,
    291  test_sync_operations,
    292  test_sync_operations_deferred,
    293  test_zero_size_buffered,
    294 ];
    295 
    296 function run_test() {
    297  tests.forEach(function (test) {
    298    test();
    299  });
    300 }