netwerk/test/unit/test_file_partial_inputstream.js

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 // Test nsIPartialFileInputStream
     6 // NOTE! These tests often use do_check_true(a == b) rather than
     7 //       do_check_eq(a, b) to avoid outputting characters which confuse
     8 //       the console
    10 const CC = Components.Constructor;
    11 const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
    12                              "nsIBinaryInputStream",
    13                              "setInputStream");
    14 const PR_RDONLY = 0x1;  // see prio.h
    16 // We need the profile directory so the test harness will clean up our test
    17 // files.
    18 do_get_profile();
    20 var binary_test_file_name = "data/image.png";
    21 var text_test_file_name = "test_file_partial_inputstream.js";
    22 // This is a global variable since if it's passed as an argument stack traces
    23 // become unreadable.
    24 var test_file_data;
    26 function run_test()
    27 {
    28   // Binary tests
    29   let binaryFile = do_get_file(binary_test_file_name);
    30   let size = binaryFile.fileSize;
    31   // Want to make sure we're working with a large enough file
    32   dump("**** binary file size is: " + size + " ****\n");
    33   do_check_true(size > 65536);
    35   let binaryStream = new BinaryInputStream(new_file_input_stream(binaryFile));
    36   test_file_data = "";
    37   while ((avail = binaryStream.available()) > 0) {
    38     test_file_data += binaryStream.readBytes(avail);
    39   }
    40   do_check_eq(test_file_data.length, size);
    41   binaryStream.close();
    43   test_binary_portion(0, 10);
    44   test_binary_portion(0, 20000);
    45   test_binary_portion(0, size);
    46   test_binary_portion(20000, 10);
    47   test_binary_portion(20000, 20000);
    48   test_binary_portion(20000, size-20000);
    49   test_binary_portion(size-10, 10);
    50   test_binary_portion(size-20000, 20000);
    51   test_binary_portion(0, 0);
    52   test_binary_portion(20000, 0);
    53   test_binary_portion(size-1, 1);
    56   // Text-file tests
    57   let textFile = do_get_file(binary_test_file_name);
    58   size = textFile.fileSize;
    59   // Want to make sure we're working with a large enough file
    60   dump("**** text file size is: " + size + " ****\n");
    61   do_check_true(size > 7000);
    63   let textStream = new BinaryInputStream(new_file_input_stream(textFile));
    64   test_file_data = "";
    65   while ((avail = textStream.available()) > 0)
    66     test_file_data += textStream.readBytes(avail);
    67   do_check_eq(test_file_data.length, size);
    68   textStream.close();
    70   test_text_portion(0, 100);
    71   test_text_portion(0, size);
    72   test_text_portion(5000, 1000);
    73   test_text_portion(size-10, 10);
    74   test_text_portion(size-5000, 5000);
    75   test_text_portion(10, 0);
    76   test_text_portion(size-1, 1);
    78   // Test auto-closing files
    79   // Test behavior when *not* autoclosing
    80   let tempFile = create_temp_file("01234567890123456789");
    81   let tempInputStream = new_partial_file_input_stream(tempFile, 5, 10);
    82   tempInputStream.QueryInterface(Ci.nsILineInputStream);
    83   do_check_eq(read_line_stream(tempInputStream)[1], "5678901234");
    84   try {
    85     // This fails on some platforms
    86     tempFile.remove(false);
    87   }
    88   catch (ex) {
    89   }
    90   tempInputStream.QueryInterface(Ci.nsISeekableStream);
    91   tempInputStream.seek(SET, 1);
    92   do_check_eq(read_line_stream(tempInputStream)[1], "678901234");
    94   // Test removing the file when autoclosing
    95   tempFile = create_temp_file("01234567890123456789");
    96   tempInputStream = new_partial_file_input_stream(tempFile, 5, 10,
    97                                                   Ci.nsIFileInputStream.CLOSE_ON_EOF |
    98                                                   Ci.nsIFileInputStream.REOPEN_ON_REWIND);
    99   tempInputStream.QueryInterface(Ci.nsILineInputStream);
   100   do_check_eq(read_line_stream(tempInputStream)[1], "5678901234");
   101   tempFile.remove(false);
   102   tempInputStream.QueryInterface(Ci.nsISeekableStream);
   103   try {
   104     // The seek should reopen the file, which should fail.
   105     tempInputStream.seek(SET, 1);
   106     do_check_true(false);
   107   }
   108   catch (ex) {
   109   }
   111   // Test editing the file when autoclosing
   112   tempFile = create_temp_file("01234567890123456789");
   113   tempInputStream = new_partial_file_input_stream(tempFile, 5, 10,
   114                                                   Ci.nsIFileInputStream.CLOSE_ON_EOF |
   115                                                   Ci.nsIFileInputStream.REOPEN_ON_REWIND);
   116   tempInputStream.QueryInterface(Ci.nsILineInputStream);
   117   do_check_eq(read_line_stream(tempInputStream)[1], "5678901234");
   118   let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
   119                 createInstance(Ci.nsIFileOutputStream);
   120   ostream.init(tempFile, 0x02 | 0x08 | 0x20, // write, create, truncate
   121                0666, 0);
   122   let newData = "abcdefghijklmnopqrstuvwxyz";
   123   ostream.write(newData, newData.length);
   124   ostream.close();
   125   tempInputStream.QueryInterface(Ci.nsISeekableStream);
   126   tempInputStream.seek(SET, 1);
   127   do_check_eq(read_line_stream(tempInputStream)[1], newData.substr(6,9));
   129   // Test auto-delete and auto-close together
   130   tempFile = create_temp_file("01234567890123456789");
   131   tempInputStream = new_partial_file_input_stream(tempFile, 5, 10,
   132                                                   Ci.nsIFileInputStream.CLOSE_ON_EOF |
   133                                                   Ci.nsIFileInputStream.DELETE_ON_CLOSE);
   134   tempInputStream.QueryInterface(Ci.nsILineInputStream);
   135   do_check_eq(read_line_stream(tempInputStream)[1], "5678901234");
   136   do_check_false(tempFile.exists());
   137 }
   139 function test_binary_portion(start, length) {
   140   let subFile = create_temp_file(test_file_data.substr(start, length));
   142   let streamTests = [
   143     test_4k_read,
   144     test_max_read,
   145     test_seek,
   146     test_seek_then_read,
   147   ];
   149   for each(test in streamTests) {
   150     let fileStream = new_file_input_stream(subFile);
   151     let partialStream = new_partial_file_input_stream(do_get_file(binary_test_file_name),
   152                                                       start, length);
   153     test(fileStream, partialStream, length);
   154     fileStream.close();
   155     partialStream.close();
   156   }
   157 }
   159 function test_4k_read(fileStreamA, fileStreamB) {
   160   fileStreamA.QueryInterface(Ci.nsISeekableStream);
   161   fileStreamB.QueryInterface(Ci.nsISeekableStream);
   162   let streamA = new BinaryInputStream(fileStreamA);
   163   let streamB = new BinaryInputStream(fileStreamB);
   165   while(1) {
   166     do_check_eq(fileStreamA.tell(), fileStreamB.tell());
   168     let availA = streamA.available();
   169     let availB = streamB.available();
   170     do_check_eq(availA, availB);
   171     if (availA == 0)
   172       return;
   174     let readSize = availA > 4096 ? 4096 : availA;
   176     do_check_true(streamA.readBytes(readSize) ==
   177                   streamB.readBytes(readSize));
   178   }
   179 }
   181 function test_max_read(fileStreamA, fileStreamB) {
   182   fileStreamA.QueryInterface(Ci.nsISeekableStream);
   183   fileStreamB.QueryInterface(Ci.nsISeekableStream);
   184   let streamA = new BinaryInputStream(fileStreamA);
   185   let streamB = new BinaryInputStream(fileStreamB);
   187   while(1) {
   188     do_check_eq(fileStreamA.tell(), fileStreamB.tell());
   190     let availA = streamA.available();
   191     let availB = streamB.available();
   192     do_check_eq(availA, availB);
   193     if (availA == 0)
   194       return;
   196     do_check_true(streamA.readBytes(availA) ==
   197                   streamB.readBytes(availB));
   198   }
   199 }
   201 const SET = Ci.nsISeekableStream.NS_SEEK_SET;
   202 const CUR = Ci.nsISeekableStream.NS_SEEK_CUR;
   203 const END = Ci.nsISeekableStream.NS_SEEK_END;
   204 function test_seek(dummy, partialFileStream, size) {
   205   // We can't test the "real" filestream here as our existing file streams
   206   // are very broken and allows searching past the end of the file.
   208   partialFileStream.QueryInterface(Ci.nsISeekableStream);
   210   tests = [
   211     [SET, 0],
   212     [SET, 5],
   213     [SET, 1000],
   214     [SET, size-10],
   215     [SET, size-5],
   216     [SET, size-1],
   217     [SET, size],
   218     [SET, size+10],
   219     [SET, 0],
   220     [CUR, 5],
   221     [CUR, -5],
   222     [SET, 5000],
   223     [CUR, -100],
   224     [CUR, 200],
   225     [CUR, -5000],
   226     [CUR, 5000],
   227     [CUR, size * 2],
   228     [SET, 1],
   229     [CUR, -1],
   230     [CUR, -1],
   231     [CUR, -1],
   232     [CUR, -1],
   233     [CUR, -1],
   234     [SET, size-1],
   235     [CUR, 1],
   236     [CUR, 1],
   237     [CUR, 1],
   238     [CUR, 1],
   239     [CUR, 1],
   240     [END, 0],
   241     [END, -1],
   242     [END, -5],
   243     [END, -1000],
   244     [END, -size+10],
   245     [END, -size+5],
   246     [END, -size+1],
   247     [END, -size],
   248     [END, -size-10],
   249     [END, 10],
   250     [CUR, 10],
   251     [CUR, 10],
   252     [CUR, 100],
   253     [CUR, 1000],
   254     [END, -1000],
   255     [CUR, 100],
   256     [CUR, 900],
   257     [CUR, 100],
   258     [CUR, 100],
   259   ];
   261   let pos = 0;
   262   for each(test in tests) {
   263     let didThrow = false;
   264     try {
   265       partialFileStream.seek(test[0], test[1]);
   266     }
   267     catch (ex) {
   268       didThrow = true;
   269     }
   271     let newPos = test[0] == SET ? test[1] :
   272                  test[0] == CUR ? pos + test[1] :
   273                  size + test[1];
   274     if (newPos > size || newPos < 0) {
   275       do_check_true(didThrow);
   276     }
   277     else {
   278       do_check_false(didThrow);
   279       pos = newPos;
   280     }
   282     do_check_eq(partialFileStream.tell(), pos);
   283     do_check_eq(partialFileStream.available(), size - pos);
   284   }
   285 }
   287 function test_seek_then_read(fileStreamA, fileStreamB, size) {
   288   // For now we only test seeking inside the file since our existing file
   289   // streams behave very strange when seeking to past the end of the file.
   290   if (size < 20000) {
   291     return;
   292   }
   294   fileStreamA.QueryInterface(Ci.nsISeekableStream);
   295   fileStreamB.QueryInterface(Ci.nsISeekableStream);
   296   let streamA = new BinaryInputStream(fileStreamA);
   297   let streamB = new BinaryInputStream(fileStreamB);
   299   let read = {};
   301   tests = [
   302     [SET, 0],
   303     [read, 1000],
   304     [read, 1000],
   305     [SET, 5],
   306     [read, 1000],
   307     [read, 5000],
   308     [CUR, 100],
   309     [read, 1000],
   310     [read, 5000],
   311     [CUR, -100],
   312     [read, 1000],
   313     [CUR, -100],
   314     [read, 5000],
   315     [END, -10],
   316     [read, 10],
   317     [END, -100],
   318     [read, 101],
   319     [CUR, -100],
   320     [read, 10],
   321     [SET, 0],
   322     [read, 20000],
   323     [read, 1],
   324     [read, 100],
   325   ];
   327   for each(test in tests) {
   328     if (test[0] === read) {
   330       let didThrowA = false;
   331       let didThrowB = false;
   333       let bytesA, bytesB;
   334       try {
   335         bytesA = streamA.readBytes(test[1]);
   336       }
   337       catch (ex) {
   338         didThrowA = true;
   339       }
   340       try {
   341         bytesB = streamB.readBytes(test[1]);
   342       }
   343       catch (ex) {
   344         didThrowB = true;
   345       }
   347       do_check_eq(didThrowA, didThrowB);
   348       do_check_true(bytesA == bytesB);
   349     }
   350     else {
   351       fileStreamA.seek(test[0], test[1]);
   352       fileStreamB.seek(test[0], test[1]);
   353     }
   354     do_check_eq(fileStreamA.tell(), fileStreamB.tell());
   355     do_check_eq(fileStreamA.available(), fileStreamB.available());
   356   }
   357 }
   359 function test_text_portion(start, length) {
   360   let subFile = create_temp_file(test_file_data.substr(start, length));
   362   let streamTests = [
   363     test_readline,
   364     test_seek_then_readline,
   365   ];
   367   for each(test in streamTests) {
   368     let fileStream = new_file_input_stream(subFile)
   369                      .QueryInterface(Ci.nsILineInputStream);
   370     let partialStream = new_partial_file_input_stream(do_get_file(binary_test_file_name),
   371                                                       start, length)
   372                         .QueryInterface(Ci.nsILineInputStream);
   373     test(fileStream, partialStream, length);
   374     fileStream.close();
   375     partialStream.close();
   376   }
   377 }
   379 function test_readline(fileStreamA, fileStreamB)
   380 {
   381   let moreA = true, moreB;
   382   while(moreA) {
   383     let lineA, lineB;
   384     [moreA, lineA] = read_line_stream(fileStreamA);
   385     [moreB, lineB] = read_line_stream(fileStreamB);
   386     do_check_eq(moreA, moreB);
   387     do_check_true(lineA.value == lineB.value);
   388   }
   389 }
   391 function test_seek_then_readline(fileStreamA, fileStreamB, size) {
   392   // For now we only test seeking inside the file since our existing file
   393   // streams behave very strange when seeking to past the end of the file.
   394   if (size < 100) {
   395     return;
   396   }
   398   fileStreamA.QueryInterface(Ci.nsISeekableStream);
   399   fileStreamB.QueryInterface(Ci.nsISeekableStream);
   401   let read = {};
   403   tests = [
   404     [SET, 0],
   405     [read, 5],
   406     [read, 5],
   407     [SET, 5],
   408     [read, 5],
   409     [read, 15],
   410     [CUR, 100],
   411     [read, 5],
   412     [read, 15],
   413     [CUR, -100],
   414     [read, 5],
   415     [CUR, -100],
   416     [read, 25],
   417     [END, -10],
   418     [read, 1],
   419     [END, -50],
   420     [read, 30],
   421     [read, 1],
   422     [read, 1],
   423     [CUR, -100],
   424     [read, 1],
   425     [SET, 0],
   426     [read, 10000],
   427     [read, 1],
   428     [read, 1],
   429     [SET, 0],
   430     [read, 1],
   431   ];
   433   for each(test in tests) {
   434     if (test[0] === read) {
   436       for (let i = 0; i < test[1]; ++i) {
   437         let didThrowA = false;
   438         let didThrowB = false;
   440         let lineA, lineB, moreA, moreB;
   441         try {
   442           [moreA, lineA] = read_line_stream(fileStreamA);
   443         }
   444         catch (ex) {
   445           didThrowA = true;
   446         }
   447         try {
   448           [moreB, lineB] = read_line_stream(fileStreamB);
   449         }
   450         catch (ex) {
   451           didThrowB = true;
   452         }
   454         do_check_eq(didThrowA, didThrowB);
   455         do_check_eq(moreA, moreB);
   456         do_check_true(lineA == lineB);
   457         do_check_eq(fileStreamA.tell(), fileStreamB.tell());
   458         do_check_eq(fileStreamA.available(), fileStreamB.available());
   459         if (!moreA)
   460           break;
   461       }
   462     }
   463     else {
   464       if (!(test[0] == CUR && (test[1] > fileStreamA.available() ||
   465                                test[1] < -fileStreamA.tell()))) {
   466         fileStreamA.seek(test[0], test[1]);
   467         fileStreamB.seek(test[0], test[1]);
   468         do_check_eq(fileStreamA.tell(), fileStreamB.tell());
   469         do_check_eq(fileStreamA.available(), fileStreamB.available());
   470       }
   471     }
   472   }
   473 }
   475 function read_line_stream(stream) {
   476   let line = {};
   477   let more = stream.readLine(line);
   478   return [more, line.value];
   479 }
   481 function new_file_input_stream(file) {
   482   var stream =
   483       Cc["@mozilla.org/network/file-input-stream;1"]
   484       .createInstance(Ci.nsIFileInputStream);
   485   stream.init(file, PR_RDONLY, 0, 0);
   486   return stream.QueryInterface(Ci.nsIInputStream);
   487 }
   489 function new_partial_file_input_stream(file, start, length, flags) {
   490   var stream =
   491       Cc["@mozilla.org/network/partial-file-input-stream;1"]
   492       .createInstance(Ci.nsIPartialFileInputStream);
   493   stream.init(file, start, length, PR_RDONLY, 0, flags || 0);
   494   return stream.QueryInterface(Ci.nsIInputStream);
   495 }
   497 function create_temp_file(data) {
   498   let file = Cc["@mozilla.org/file/directory_service;1"].
   499              getService(Ci.nsIProperties).
   500              get("ProfD", Ci.nsIFile);
   501   file.append("fileinputstream-test-file.tmp");
   502   file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
   504   let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
   505                 createInstance(Ci.nsIFileOutputStream);
   506   ostream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
   507                0666, 0);
   508   do_check_eq(ostream.write(data, data.length), data.length);
   509   ostream.close();
   511   return file;
   512 }

mercurial