Bug 1339710 - Remove nsIPartialFileInputStream, r=smaug

This commit is contained in:
Andrea Marchesini 2017-02-22 09:41:51 +01:00
parent 0500e8f2e7
commit e87ad16573
12 changed files with 12 additions and 867 deletions

View File

@ -231,13 +231,21 @@ const uint32_t sFileStreamFlags =
void
FileBlobImpl::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
{
if (mWholeFile) {
aRv = NS_NewLocalFileInputStream(aStream, mFile, -1, -1, sFileStreamFlags);
nsCOMPtr<nsIInputStream> stream;
aRv = NS_NewLocalFileInputStream(getter_AddRefs(stream), mFile, -1, -1,
sFileStreamFlags);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
aRv = NS_NewPartialLocalFileInputStream(aStream, mFile, mStart, mLength,
-1, -1, sFileStreamFlags);
if (mWholeFile) {
stream.forget(aStream);
return;
}
RefPtr<SlicedInputStream> slicedInputStream =
new SlicedInputStream(stream, mStart, mLength);
slicedInputStream.forget(aStream);
}
bool

View File

@ -29,13 +29,6 @@ struct FileInputStreamParams
int32_t ioFlags;
};
struct PartialFileInputStreamParams
{
FileInputStreamParams fileStreamParams;
uint64_t begin;
uint64_t length;
};
struct TemporaryFileInputStreamParams
{
uint32_t fileDescriptorIndex;
@ -77,7 +70,6 @@ union InputStreamParams
{
StringInputStreamParams;
FileInputStreamParams;
PartialFileInputStreamParams;
TemporaryFileInputStreamParams;
BufferedInputStreamParams;
MIMEInputStreamParams;

View File

@ -30,7 +30,6 @@ namespace {
NS_DEFINE_CID(kStringInputStreamCID, NS_STRINGINPUTSTREAM_CID);
NS_DEFINE_CID(kFileInputStreamCID, NS_LOCALFILEINPUTSTREAM_CID);
NS_DEFINE_CID(kPartialFileInputStreamCID, NS_PARTIALLOCALFILEINPUTSTREAM_CID);
NS_DEFINE_CID(kBufferedInputStreamCID, NS_BUFFEREDINPUTSTREAM_CID);
NS_DEFINE_CID(kMIMEInputStreamCID, NS_MIMEINPUTSTREAM_CID);
NS_DEFINE_CID(kMultiplexInputStreamCID, NS_MULTIPLEXINPUTSTREAM_CID);
@ -91,10 +90,6 @@ DeserializeInputStream(const InputStreamParams& aParams,
serializable = do_CreateInstance(kFileInputStreamCID);
break;
case InputStreamParams::TPartialFileInputStreamParams:
serializable = do_CreateInstance(kPartialFileInputStreamCID);
break;
case InputStreamParams::TTemporaryFileInputStreamParams:
serializable = new nsTemporaryFileInputStream();
break;

View File

@ -253,9 +253,6 @@ nsFileStreamBase::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
// wrap a BufferedInputStream around the file stream. That will call
// Read().
// If this is ever implemented you might need to modify
// nsPartialFileInputStream::ReadSegments
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -687,224 +684,6 @@ nsFileInputStream::ExpectedSerializedLength()
return Nothing();
}
////////////////////////////////////////////////////////////////////////////////
// nsPartialFileInputStream
NS_IMPL_ADDREF_INHERITED(nsPartialFileInputStream, nsFileStreamBase)
NS_IMPL_RELEASE_INHERITED(nsPartialFileInputStream, nsFileStreamBase)
NS_IMPL_CLASSINFO(nsPartialFileInputStream, nullptr, nsIClassInfo::THREADSAFE,
NS_PARTIALLOCALFILEINPUTSTREAM_CID)
// Don't forward to nsFileInputStream as we don't want to QI to
// nsIFileInputStream
NS_INTERFACE_MAP_BEGIN(nsPartialFileInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsIPartialFileInputStream)
NS_INTERFACE_MAP_ENTRY(nsILineInputStream)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableInputStream)
NS_IMPL_QUERY_CLASSINFO(nsPartialFileInputStream)
NS_INTERFACE_MAP_END_INHERITING(nsFileStreamBase)
NS_IMPL_CI_INTERFACE_GETTER(nsPartialFileInputStream,
nsIInputStream,
nsIPartialFileInputStream,
nsISeekableStream,
nsILineInputStream)
nsresult
nsPartialFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID,
void **aResult)
{
NS_ENSURE_NO_AGGREGATION(aOuter);
nsPartialFileInputStream* stream = new nsPartialFileInputStream();
NS_ADDREF(stream);
nsresult rv = stream->QueryInterface(aIID, aResult);
NS_RELEASE(stream);
return rv;
}
NS_IMETHODIMP
nsPartialFileInputStream::Init(nsIFile* aFile, uint64_t aStart,
uint64_t aLength, int32_t aIOFlags,
int32_t aPerm, int32_t aBehaviorFlags)
{
mStart = aStart;
mLength = aLength;
mPosition = 0;
nsresult rv = nsFileInputStream::Init(aFile, aIOFlags, aPerm,
aBehaviorFlags);
// aFile is a partial file, it must exist.
NS_ENSURE_SUCCESS(rv, rv);
mDeferredSeek = true;
return rv;
}
NS_IMETHODIMP
nsPartialFileInputStream::Tell(int64_t *aResult)
{
int64_t tell = 0;
nsresult rv = DoPendingSeek();
NS_ENSURE_SUCCESS(rv, rv);
rv = nsFileInputStream::Tell(&tell);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = tell - mStart;
return rv;
}
NS_IMETHODIMP
nsPartialFileInputStream::Available(uint64_t* aResult)
{
uint64_t available = 0;
nsresult rv = DoPendingSeek();
NS_ENSURE_SUCCESS(rv, rv);
rv = nsFileInputStream::Available(&available);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = TruncateSize(available);
return rv;
}
NS_IMETHODIMP
nsPartialFileInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* aResult)
{
nsresult rv = DoPendingSeek();
NS_ENSURE_SUCCESS(rv, rv);
uint32_t readsize = (uint32_t) TruncateSize(aCount);
if (readsize == 0 && mBehaviorFlags & CLOSE_ON_EOF) {
Close();
*aResult = 0;
return NS_OK;
}
rv = nsFileInputStream::Read(aBuf, readsize, aResult);
NS_ENSURE_SUCCESS(rv, rv);
mPosition += readsize;
return rv;
}
NS_IMETHODIMP
nsPartialFileInputStream::Seek(int32_t aWhence, int64_t aOffset)
{
nsresult rv = DoPendingSeek();
NS_ENSURE_SUCCESS(rv, rv);
int64_t offset;
switch (aWhence) {
case NS_SEEK_SET:
offset = mStart + aOffset;
break;
case NS_SEEK_CUR:
offset = mStart + mPosition + aOffset;
break;
case NS_SEEK_END:
offset = mStart + mLength + aOffset;
break;
default:
return NS_ERROR_ILLEGAL_VALUE;
}
if (offset < (int64_t)mStart || offset > (int64_t)(mStart + mLength)) {
return NS_ERROR_INVALID_ARG;
}
rv = nsFileInputStream::Seek(NS_SEEK_SET, offset);
NS_ENSURE_SUCCESS(rv, rv);
mPosition = offset - mStart;
return rv;
}
void
nsPartialFileInputStream::Serialize(InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors)
{
// Serialize the base class first.
InputStreamParams fileParams;
nsFileInputStream::Serialize(fileParams, aFileDescriptors);
PartialFileInputStreamParams params;
params.fileStreamParams() = fileParams.get_FileInputStreamParams();
params.begin() = mStart;
params.length() = mLength;
aParams = params;
}
bool
nsPartialFileInputStream::Deserialize(
const InputStreamParams& aParams,
const FileDescriptorArray& aFileDescriptors)
{
NS_ASSERTION(!mFD, "Already have a file descriptor?!");
NS_ASSERTION(!mStart, "Already have a start?!");
NS_ASSERTION(!mLength, "Already have a length?!");
NS_ASSERTION(!mPosition, "Already have a position?!");
if (aParams.type() != InputStreamParams::TPartialFileInputStreamParams) {
NS_WARNING("Received unknown parameters from the other process!");
return false;
}
const PartialFileInputStreamParams& params =
aParams.get_PartialFileInputStreamParams();
// Deserialize the base class first.
InputStreamParams fileParams(params.fileStreamParams());
if (!nsFileInputStream::Deserialize(fileParams, aFileDescriptors)) {
NS_WARNING("Base class deserialize failed!");
return false;
}
NS_ASSERTION(mFD, "Must have a file descriptor now!");
mStart = params.begin();
mLength = params.length();
mPosition = 0;
if (!mStart) {
return true;
}
// XXX This is so broken. Main thread IO alert.
return NS_SUCCEEDED(nsFileInputStream::Seek(NS_SEEK_SET, mStart));
}
Maybe<uint64_t>
nsPartialFileInputStream::ExpectedSerializedLength()
{
return Some(mLength);
}
nsresult
nsPartialFileInputStream::DoPendingSeek()
{
if (!mDeferredSeek) {
return NS_OK;
}
mDeferredSeek = false;
// This is the first time to open the file, don't clear mLinebuffer.
// mLineBuffer might be already initialized by ReadLine().
return nsFileInputStream::SeekInternal(NS_SEEK_SET, mStart, false);
}
////////////////////////////////////////////////////////////////////////////////
// nsFileOutputStream

View File

@ -175,47 +175,6 @@ protected:
////////////////////////////////////////////////////////////////////////////////
class nsPartialFileInputStream : public nsFileInputStream,
public nsIPartialFileInputStream
{
public:
using nsFileInputStream::Init;
using nsFileInputStream::Read;
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIPARTIALFILEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
nsPartialFileInputStream()
: mStart(0), mLength(0), mPosition(0), mDeferredSeek(false)
{ }
NS_IMETHOD Tell(int64_t *aResult) override;
NS_IMETHOD Available(uint64_t *aResult) override;
NS_IMETHOD Read(char* aBuf, uint32_t aCount, uint32_t* aResult) override;
NS_IMETHOD Seek(int32_t aWhence, int64_t aOffset) override;
static nsresult
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
protected:
~nsPartialFileInputStream()
{ }
inline nsresult DoPendingSeek();
private:
uint64_t TruncateSize(uint64_t aSize) {
return std::min<uint64_t>(mLength - mPosition, aSize);
}
uint64_t mStart;
uint64_t mLength;
uint64_t mPosition;
bool mDeferredSeek;
};
////////////////////////////////////////////////////////////////////////////////
class nsFileOutputStream : public nsFileStreamBase,
public nsIFileOutputStream
{

View File

@ -137,37 +137,6 @@ interface nsIFileOutputStream : nsIOutputStream
const long DEFER_OPEN = 1<<0;
};
/**
* An input stream that allows you to read from a slice of a file.
*/
[scriptable, uuid(3ce03a2f-97f7-4375-b6bb-1788a60cad3b)]
interface nsIPartialFileInputStream : nsISupports
{
/**
* Initialize with a file and new start/end positions. Both start and
* start+length must be smaller than the size of the file. Not doing so
* will lead to undefined behavior.
* You must initialize the stream, and only initialize it once, before it
* can be used.
*
* @param file file to read from
* @param start start offset of slice to read. Must be smaller
* than the size of the file.
* @param length length of slice to read. Must be small enough that
* start+length is smaller than the size of the file.
* @param ioFlags file open flags listed in prio.h (see
* PR_Open documentation) or -1 to open the
* file in default mode (PR_RDONLY).
* @param perm file mode bits listed in prio.h or -1 to
* use the default value (0)
* @param behaviorFlags flags specifying various behaviors of the class
* (see enumerations in nsIFileInputStream)
*/
void init(in nsIFile file, in unsigned long long start,
in unsigned long long length,
in long ioFlags, in long perm, in long behaviorFlags);
};
/**
* A stream that allows you to read from a file or stream to a file.
*/

View File

@ -988,26 +988,6 @@ NS_ExtractCharsetFromContentType(const nsACString &rawContentType,
hadCharset);
}
nsresult
NS_NewPartialLocalFileInputStream(nsIInputStream **result,
nsIFile *file,
uint64_t offset,
uint64_t length,
int32_t ioFlags /* = -1 */,
int32_t perm /* = -1 */,
int32_t behaviorFlags /* = 0 */)
{
nsresult rv;
nsCOMPtr<nsIPartialFileInputStream> in =
do_CreateInstance(NS_PARTIALLOCALFILEINPUTSTREAM_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = in->Init(file, offset, length, ioFlags, perm, behaviorFlags);
if (NS_SUCCEEDED(rv))
rv = CallQueryInterface(in, result);
}
return rv;
}
nsresult
NS_NewAtomicFileOutputStream(nsIOutputStream **result,
nsIFile *file,

View File

@ -479,14 +479,6 @@ nsresult NS_NewLocalFileInputStream(nsIInputStream **result,
int32_t perm = -1,
int32_t behaviorFlags = 0);
nsresult NS_NewPartialLocalFileInputStream(nsIInputStream **result,
nsIFile *file,
uint64_t offset,
uint64_t length,
int32_t ioFlags = -1,
int32_t perm = -1,
int32_t behaviorFlags = 0);
nsresult NS_NewLocalFileOutputStream(nsIOutputStream **result,
nsIFile *file,
int32_t ioFlags = -1,

View File

@ -391,16 +391,6 @@
{0x8c, 0xda, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
}
#define NS_PARTIALLOCALFILEINPUTSTREAM_CONTRACTID \
"@mozilla.org/network/partial-file-input-stream;1"
#define NS_PARTIALLOCALFILEINPUTSTREAM_CID \
{ /* 8738afd6-162a-418d-a99b-75b3a6b10a56 */ \
0x8738afd6, \
0x162a, \
0x418d, \
{0xa9, 0x9b, 0x75, 0xb3, 0xa6, 0xb1, 0x0a, 0x56} \
}
#define NS_BUFFEREDINPUTSTREAM_CONTRACTID \
"@mozilla.org/network/buffered-input-stream;1"
#define NS_BUFFEREDINPUTSTREAM_CID \

View File

@ -756,7 +756,6 @@ NS_DEFINE_NAMED_CID(NS_STREAMLISTENERTEE_CID);
NS_DEFINE_NAMED_CID(NS_LOADGROUP_CID);
NS_DEFINE_NAMED_CID(NS_LOCALFILEINPUTSTREAM_CID);
NS_DEFINE_NAMED_CID(NS_LOCALFILEOUTPUTSTREAM_CID);
NS_DEFINE_NAMED_CID(NS_PARTIALLOCALFILEINPUTSTREAM_CID);
NS_DEFINE_NAMED_CID(NS_ATOMICLOCALFILEOUTPUTSTREAM_CID);
NS_DEFINE_NAMED_CID(NS_SAFELOCALFILEOUTPUTSTREAM_CID);
NS_DEFINE_NAMED_CID(NS_LOCALFILESTREAM_CID);
@ -909,7 +908,6 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
{ &kNS_LOADGROUP_CID, false, nullptr, nsLoadGroupConstructor },
{ &kNS_LOCALFILEINPUTSTREAM_CID, false, nullptr, nsFileInputStream::Create },
{ &kNS_LOCALFILEOUTPUTSTREAM_CID, false, nullptr, nsFileOutputStream::Create },
{ &kNS_PARTIALLOCALFILEINPUTSTREAM_CID, false, nullptr, nsPartialFileInputStream::Create },
{ &kNS_ATOMICLOCALFILEOUTPUTSTREAM_CID, false, nullptr, nsAtomicFileOutputStreamConstructor },
{ &kNS_SAFELOCALFILEOUTPUTSTREAM_CID, false, nullptr, nsSafeFileOutputStreamConstructor },
{ &kNS_LOCALFILESTREAM_CID, false, nullptr, nsFileStreamConstructor },
@ -1064,7 +1062,6 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
{ NS_LOADGROUP_CONTRACTID, &kNS_LOADGROUP_CID },
{ NS_LOCALFILEINPUTSTREAM_CONTRACTID, &kNS_LOCALFILEINPUTSTREAM_CID },
{ NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &kNS_LOCALFILEOUTPUTSTREAM_CID },
{ NS_PARTIALLOCALFILEINPUTSTREAM_CONTRACTID, &kNS_PARTIALLOCALFILEINPUTSTREAM_CID },
{ NS_ATOMICLOCALFILEOUTPUTSTREAM_CONTRACTID, &kNS_ATOMICLOCALFILEOUTPUTSTREAM_CID },
{ NS_SAFELOCALFILEOUTPUTSTREAM_CONTRACTID, &kNS_SAFELOCALFILEOUTPUTSTREAM_CID },
{ NS_LOCALFILESTREAM_CONTRACTID, &kNS_LOCALFILESTREAM_CID },

View File

@ -1,515 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Test nsIPartialFileInputStream
// NOTE! These tests often use do_check_true(a == b) rather than
// do_check_eq(a, b) to avoid outputting characters which confuse
// the console
"use strict";
var CC = Components.Constructor;
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream");
const PR_RDONLY = 0x1; // see prio.h
// We need the profile directory so the test harness will clean up our test
// files.
do_get_profile();
var binary_test_file_name = "data/image.png";
var text_test_file_name = "test_file_partial_inputstream.js";
// This is a global variable since if it's passed as an argument stack traces
// become unreadable.
var test_file_data;
function run_test()
{
// Binary tests
let binaryFile = do_get_file(binary_test_file_name);
let size = binaryFile.fileSize;
// Want to make sure we're working with a large enough file
dump("**** binary file size is: " + size + " ****\n");
do_check_true(size > 65536);
let binaryStream = new BinaryInputStream(new_file_input_stream(binaryFile));
test_file_data = "";
let avail = 0;
while ((avail = binaryStream.available()) > 0) {
test_file_data += binaryStream.readBytes(avail);
}
do_check_eq(test_file_data.length, size);
binaryStream.close();
test_binary_portion(0, 10);
test_binary_portion(0, 20000);
test_binary_portion(0, size);
test_binary_portion(20000, 10);
test_binary_portion(20000, 20000);
test_binary_portion(20000, size-20000);
test_binary_portion(size-10, 10);
test_binary_portion(size-20000, 20000);
test_binary_portion(0, 0);
test_binary_portion(20000, 0);
test_binary_portion(size-1, 1);
// Text-file tests
let textFile = do_get_file(binary_test_file_name);
size = textFile.fileSize;
// Want to make sure we're working with a large enough file
dump("**** text file size is: " + size + " ****\n");
do_check_true(size > 7000);
let textStream = new BinaryInputStream(new_file_input_stream(textFile));
test_file_data = "";
while ((avail = textStream.available()) > 0)
test_file_data += textStream.readBytes(avail);
do_check_eq(test_file_data.length, size);
textStream.close();
test_text_portion(0, 100);
test_text_portion(0, size);
test_text_portion(5000, 1000);
test_text_portion(size-10, 10);
test_text_portion(size-5000, 5000);
test_text_portion(10, 0);
test_text_portion(size-1, 1);
// Test auto-closing files
// Test behavior when *not* autoclosing
let tempFile = create_temp_file("01234567890123456789");
let tempInputStream = new_partial_file_input_stream(tempFile, 5, 10);
tempInputStream.QueryInterface(Ci.nsILineInputStream);
do_check_eq(read_line_stream(tempInputStream)[1], "5678901234");
try {
// This fails on some platforms
tempFile.remove(false);
}
catch (ex) {
}
tempInputStream.QueryInterface(Ci.nsISeekableStream);
tempInputStream.seek(SET, 1);
do_check_eq(read_line_stream(tempInputStream)[1], "678901234");
// Test removing the file when autoclosing
tempFile = create_temp_file("01234567890123456789");
tempInputStream = new_partial_file_input_stream(tempFile, 5, 10,
Ci.nsIFileInputStream.CLOSE_ON_EOF |
Ci.nsIFileInputStream.REOPEN_ON_REWIND);
tempInputStream.QueryInterface(Ci.nsILineInputStream);
do_check_eq(read_line_stream(tempInputStream)[1], "5678901234");
tempFile.remove(false);
tempInputStream.QueryInterface(Ci.nsISeekableStream);
try {
// The seek should reopen the file, which should fail.
tempInputStream.seek(SET, 1);
do_check_true(false);
}
catch (ex) {
}
// Test editing the file when autoclosing
tempFile = create_temp_file("01234567890123456789");
tempInputStream = new_partial_file_input_stream(tempFile, 5, 10,
Ci.nsIFileInputStream.CLOSE_ON_EOF |
Ci.nsIFileInputStream.REOPEN_ON_REWIND);
tempInputStream.QueryInterface(Ci.nsILineInputStream);
do_check_eq(read_line_stream(tempInputStream)[1], "5678901234");
let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
ostream.init(tempFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0o666, 0);
let newData = "abcdefghijklmnopqrstuvwxyz";
ostream.write(newData, newData.length);
ostream.close();
tempInputStream.QueryInterface(Ci.nsISeekableStream);
tempInputStream.seek(SET, 1);
do_check_eq(read_line_stream(tempInputStream)[1], newData.substr(6,9));
// Test auto-delete and auto-close together
tempFile = create_temp_file("01234567890123456789");
tempInputStream = new_partial_file_input_stream(tempFile, 5, 10,
Ci.nsIFileInputStream.CLOSE_ON_EOF |
Ci.nsIFileInputStream.DELETE_ON_CLOSE);
tempInputStream.QueryInterface(Ci.nsILineInputStream);
do_check_eq(read_line_stream(tempInputStream)[1], "5678901234");
do_check_false(tempFile.exists());
}
function test_binary_portion(start, length) {
let subFile = create_temp_file(test_file_data.substr(start, length));
let streamTests = [
test_4k_read,
test_max_read,
test_seek,
test_seek_then_read,
];
for (var test of streamTests) {
let fileStream = new_file_input_stream(subFile);
let partialStream = new_partial_file_input_stream(do_get_file(binary_test_file_name),
start, length);
test(fileStream, partialStream, length);
fileStream.close();
partialStream.close();
}
}
function test_4k_read(fileStreamA, fileStreamB) {
fileStreamA.QueryInterface(Ci.nsISeekableStream);
fileStreamB.QueryInterface(Ci.nsISeekableStream);
let streamA = new BinaryInputStream(fileStreamA);
let streamB = new BinaryInputStream(fileStreamB);
while(1) {
do_check_eq(fileStreamA.tell(), fileStreamB.tell());
let availA = streamA.available();
let availB = streamB.available();
do_check_eq(availA, availB);
if (availA == 0)
return;
let readSize = availA > 4096 ? 4096 : availA;
do_check_true(streamA.readBytes(readSize) ==
streamB.readBytes(readSize));
}
}
function test_max_read(fileStreamA, fileStreamB) {
fileStreamA.QueryInterface(Ci.nsISeekableStream);
fileStreamB.QueryInterface(Ci.nsISeekableStream);
let streamA = new BinaryInputStream(fileStreamA);
let streamB = new BinaryInputStream(fileStreamB);
while(1) {
do_check_eq(fileStreamA.tell(), fileStreamB.tell());
let availA = streamA.available();
let availB = streamB.available();
do_check_eq(availA, availB);
if (availA == 0)
return;
do_check_true(streamA.readBytes(availA) ==
streamB.readBytes(availB));
}
}
const SET = Ci.nsISeekableStream.NS_SEEK_SET;
const CUR = Ci.nsISeekableStream.NS_SEEK_CUR;
const END = Ci.nsISeekableStream.NS_SEEK_END;
function test_seek(dummy, partialFileStream, size) {
// We can't test the "real" filestream here as our existing file streams
// are very broken and allows searching past the end of the file.
partialFileStream.QueryInterface(Ci.nsISeekableStream);
var tests = [
[SET, 0],
[SET, 5],
[SET, 1000],
[SET, size-10],
[SET, size-5],
[SET, size-1],
[SET, size],
[SET, size+10],
[SET, 0],
[CUR, 5],
[CUR, -5],
[SET, 5000],
[CUR, -100],
[CUR, 200],
[CUR, -5000],
[CUR, 5000],
[CUR, size * 2],
[SET, 1],
[CUR, -1],
[CUR, -1],
[CUR, -1],
[CUR, -1],
[CUR, -1],
[SET, size-1],
[CUR, 1],
[CUR, 1],
[CUR, 1],
[CUR, 1],
[CUR, 1],
[END, 0],
[END, -1],
[END, -5],
[END, -1000],
[END, -size+10],
[END, -size+5],
[END, -size+1],
[END, -size],
[END, -size-10],
[END, 10],
[CUR, 10],
[CUR, 10],
[CUR, 100],
[CUR, 1000],
[END, -1000],
[CUR, 100],
[CUR, 900],
[CUR, 100],
[CUR, 100],
];
let pos = 0;
for (var test of tests) {
let didThrow = false;
try {
partialFileStream.seek(test[0], test[1]);
}
catch (ex) {
didThrow = true;
}
let newPos = test[0] == SET ? test[1] :
test[0] == CUR ? pos + test[1] :
size + test[1];
if (newPos > size || newPos < 0) {
do_check_true(didThrow);
}
else {
do_check_false(didThrow);
pos = newPos;
}
do_check_eq(partialFileStream.tell(), pos);
do_check_eq(partialFileStream.available(), size - pos);
}
}
function test_seek_then_read(fileStreamA, fileStreamB, size) {
// For now we only test seeking inside the file since our existing file
// streams behave very strange when seeking to past the end of the file.
if (size < 20000) {
return;
}
fileStreamA.QueryInterface(Ci.nsISeekableStream);
fileStreamB.QueryInterface(Ci.nsISeekableStream);
let streamA = new BinaryInputStream(fileStreamA);
let streamB = new BinaryInputStream(fileStreamB);
let read = {};
var tests = [
[SET, 0],
[read, 1000],
[read, 1000],
[SET, 5],
[read, 1000],
[read, 5000],
[CUR, 100],
[read, 1000],
[read, 5000],
[CUR, -100],
[read, 1000],
[CUR, -100],
[read, 5000],
[END, -10],
[read, 10],
[END, -100],
[read, 101],
[CUR, -100],
[read, 10],
[SET, 0],
[read, 20000],
[read, 1],
[read, 100],
];
for (var test of tests) {
if (test[0] === read) {
let didThrowA = false;
let didThrowB = false;
let bytesA, bytesB;
try {
bytesA = streamA.readBytes(test[1]);
}
catch (ex) {
didThrowA = true;
}
try {
bytesB = streamB.readBytes(test[1]);
}
catch (ex) {
didThrowB = true;
}
do_check_eq(didThrowA, didThrowB);
do_check_true(bytesA == bytesB);
}
else {
fileStreamA.seek(test[0], test[1]);
fileStreamB.seek(test[0], test[1]);
}
do_check_eq(fileStreamA.tell(), fileStreamB.tell());
do_check_eq(fileStreamA.available(), fileStreamB.available());
}
}
function test_text_portion(start, length) {
let subFile = create_temp_file(test_file_data.substr(start, length));
let streamTests = [
test_readline,
test_seek_then_readline,
];
for (var test of streamTests) {
let fileStream = new_file_input_stream(subFile)
.QueryInterface(Ci.nsILineInputStream);
let partialStream = new_partial_file_input_stream(do_get_file(binary_test_file_name),
start, length)
.QueryInterface(Ci.nsILineInputStream);
test(fileStream, partialStream, length);
fileStream.close();
partialStream.close();
}
}
function test_readline(fileStreamA, fileStreamB)
{
let moreA = true, moreB;
while(moreA) {
let lineA, lineB;
[moreA, lineA] = read_line_stream(fileStreamA);
[moreB, lineB] = read_line_stream(fileStreamB);
do_check_eq(moreA, moreB);
do_check_true(lineA.value == lineB.value);
}
}
function test_seek_then_readline(fileStreamA, fileStreamB, size) {
// For now we only test seeking inside the file since our existing file
// streams behave very strange when seeking to past the end of the file.
if (size < 100) {
return;
}
fileStreamA.QueryInterface(Ci.nsISeekableStream);
fileStreamB.QueryInterface(Ci.nsISeekableStream);
let read = {};
var tests = [
[SET, 0],
[read, 5],
[read, 5],
[SET, 5],
[read, 5],
[read, 15],
[CUR, 100],
[read, 5],
[read, 15],
[CUR, -100],
[read, 5],
[CUR, -100],
[read, 25],
[END, -10],
[read, 1],
[END, -50],
[read, 30],
[read, 1],
[read, 1],
[CUR, -100],
[read, 1],
[SET, 0],
[read, 10000],
[read, 1],
[read, 1],
[SET, 0],
[read, 1],
];
for (var test of tests) {
if (test[0] === read) {
for (let i = 0; i < test[1]; ++i) {
let didThrowA = false;
let didThrowB = false;
let lineA, lineB, moreA, moreB;
try {
[moreA, lineA] = read_line_stream(fileStreamA);
}
catch (ex) {
didThrowA = true;
}
try {
[moreB, lineB] = read_line_stream(fileStreamB);
}
catch (ex) {
didThrowB = true;
}
do_check_eq(didThrowA, didThrowB);
do_check_eq(moreA, moreB);
do_check_true(lineA == lineB);
do_check_eq(fileStreamA.tell(), fileStreamB.tell());
do_check_eq(fileStreamA.available(), fileStreamB.available());
if (!moreA)
break;
}
}
else {
if (!(test[0] == CUR && (test[1] > fileStreamA.available() ||
test[1] < -fileStreamA.tell()))) {
fileStreamA.seek(test[0], test[1]);
fileStreamB.seek(test[0], test[1]);
do_check_eq(fileStreamA.tell(), fileStreamB.tell());
do_check_eq(fileStreamA.available(), fileStreamB.available());
}
}
}
}
function read_line_stream(stream) {
let line = {};
let more = stream.readLine(line);
return [more, line.value];
}
function new_file_input_stream(file) {
var stream =
Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
stream.init(file, PR_RDONLY, 0, 0);
return stream.QueryInterface(Ci.nsIInputStream);
}
function new_partial_file_input_stream(file, start, length, flags) {
var stream =
Cc["@mozilla.org/network/partial-file-input-stream;1"]
.createInstance(Ci.nsIPartialFileInputStream);
stream.init(file, start, length, PR_RDONLY, 0, flags || 0);
return stream.QueryInterface(Ci.nsIInputStream);
}
function create_temp_file(data) {
let file = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).
get("ProfD", Ci.nsIFile);
file.append("fileinputstream-test-file.tmp");
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
ostream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
0o666, 0);
do_check_eq(ostream.write(data, data.length), data.length);
ostream.close();
return file;
}

View File

@ -208,7 +208,6 @@ skip-if = bits != 32
[test_fallback_request-error_passing.js]
[test_fallback_response-error_canceled.js]
[test_fallback_response-error_passing.js]
[test_file_partial_inputstream.js]
[test_file_protocol.js]
[test_filestreams.js]
[test_freshconnection.js]