Bug 1754004 - Part 9: Remove PartiallySeekableInputStream, r=asuth,necko-reviewers,kershaw

This interface is misleading, as it doesn't allow seeking the entire type
despite providing a `nsISeekableStream` interface, and is no longer necessary
due to the changes in an earlier part.

Differential Revision: https://phabricator.services.mozilla.com/D141046
This commit is contained in:
Nika Layzell
2022-05-03 23:30:35 +00:00
parent 051080f739
commit 9a77d1d4ce
5 changed files with 0 additions and 1056 deletions

View File

@@ -1,445 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "PartiallySeekableInputStream.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "nsISeekableStream.h"
#include "nsStreamUtils.h"
namespace mozilla {
namespace net {
NS_IMPL_ADDREF(PartiallySeekableInputStream);
NS_IMPL_RELEASE(PartiallySeekableInputStream);
NS_INTERFACE_MAP_BEGIN(PartiallySeekableInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
NS_INTERFACE_MAP_ENTRY(nsITellableStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
mWeakCloneableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
mWeakIPCSerializableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, mWeakAsyncInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
mWeakAsyncInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamLength,
mWeakInputStreamLength)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStreamLength,
mWeakAsyncInputStreamLength)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamLengthCallback,
mWeakAsyncInputStreamLength)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
PartiallySeekableInputStream::PartiallySeekableInputStream(
already_AddRefed<nsIInputStream> aInputStream, uint64_t aBufferSize)
: mInputStream(std::move(aInputStream)),
mWeakCloneableInputStream(nullptr),
mWeakIPCSerializableInputStream(nullptr),
mWeakAsyncInputStream(nullptr),
mWeakInputStreamLength(nullptr),
mWeakAsyncInputStreamLength(nullptr),
mBufferSize(aBufferSize),
mPos(0),
mClosed(false),
mMutex("PartiallySeekableInputStream::mMutex") {
Init();
}
PartiallySeekableInputStream::PartiallySeekableInputStream(
already_AddRefed<nsIInputStream> aClonedBaseStream,
PartiallySeekableInputStream* aClonedFrom)
: mInputStream(std::move(aClonedBaseStream)),
mWeakCloneableInputStream(nullptr),
mWeakIPCSerializableInputStream(nullptr),
mWeakAsyncInputStream(nullptr),
mWeakInputStreamLength(nullptr),
mWeakAsyncInputStreamLength(nullptr),
mCachedBuffer(aClonedFrom->mCachedBuffer.Clone()),
mBufferSize(aClonedFrom->mBufferSize),
mPos(aClonedFrom->mPos),
mClosed(aClonedFrom->mClosed),
mMutex("PartiallySeekableInputStream::mMutex") {
Init();
}
void PartiallySeekableInputStream::Init() {
MOZ_ASSERT(mInputStream);
#ifdef DEBUG
nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mInputStream);
MOZ_ASSERT(!seekableStream);
#endif
nsCOMPtr<nsICloneableInputStream> cloneableStream =
do_QueryInterface(mInputStream);
if (cloneableStream && SameCOMIdentity(mInputStream, cloneableStream)) {
mWeakCloneableInputStream = cloneableStream;
}
nsCOMPtr<nsIIPCSerializableInputStream> serializableStream =
do_QueryInterface(mInputStream);
if (serializableStream && SameCOMIdentity(mInputStream, serializableStream)) {
mWeakIPCSerializableInputStream = serializableStream;
}
nsCOMPtr<nsIAsyncInputStream> asyncInputStream =
do_QueryInterface(mInputStream);
if (asyncInputStream && SameCOMIdentity(mInputStream, asyncInputStream)) {
mWeakAsyncInputStream = asyncInputStream;
}
nsCOMPtr<nsIInputStreamLength> inputStreamLength =
do_QueryInterface(mInputStream);
if (inputStreamLength && SameCOMIdentity(mInputStream, inputStreamLength)) {
mWeakInputStreamLength = inputStreamLength;
}
nsCOMPtr<nsIAsyncInputStreamLength> asyncInputStreamLength =
do_QueryInterface(mInputStream);
if (asyncInputStreamLength &&
SameCOMIdentity(mInputStream, asyncInputStreamLength)) {
mWeakAsyncInputStreamLength = asyncInputStreamLength;
}
}
NS_IMETHODIMP
PartiallySeekableInputStream::Close() {
mInputStream->Close();
mCachedBuffer.Clear();
mPos = 0;
mClosed = true;
return NS_OK;
}
// nsIInputStream interface
NS_IMETHODIMP
PartiallySeekableInputStream::Available(uint64_t* aLength) {
if (mClosed) {
return NS_BASE_STREAM_CLOSED;
}
nsresult rv = mInputStream->Available(aLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mPos < mCachedBuffer.Length()) {
*aLength += mCachedBuffer.Length() - mPos;
}
return NS_OK;
}
NS_IMETHODIMP
PartiallySeekableInputStream::Read(char* aBuffer, uint32_t aCount,
uint32_t* aReadCount) {
*aReadCount = 0;
if (mClosed) {
return NS_OK;
}
uint32_t byteRead = 0;
if (mPos < mCachedBuffer.Length()) {
// We are reading from the cached buffer.
byteRead = XPCOM_MIN(mCachedBuffer.Length() - mPos, (uint64_t)aCount);
memcpy(aBuffer, mCachedBuffer.Elements() + mPos, byteRead);
*aReadCount = byteRead;
mPos += byteRead;
}
if (byteRead < aCount) {
MOZ_ASSERT(mPos >= mCachedBuffer.Length());
MOZ_ASSERT_IF(mPos > mCachedBuffer.Length(),
mCachedBuffer.Length() == mBufferSize);
// We can read from the stream.
uint32_t byteWritten;
nsresult rv =
mInputStream->Read(aBuffer + byteRead, aCount - byteRead, &byteWritten);
if (NS_WARN_IF(NS_FAILED(rv)) || byteWritten == 0) {
return rv;
}
*aReadCount += byteWritten;
// Maybe we have to cache something.
if (mPos < mBufferSize) {
uint32_t size = XPCOM_MIN(mPos + byteWritten, mBufferSize);
mCachedBuffer.SetLength(size);
memcpy(mCachedBuffer.Elements() + mPos, aBuffer + byteRead, size - mPos);
}
mPos += byteWritten;
}
return NS_OK;
}
NS_IMETHODIMP
PartiallySeekableInputStream::ReadSegments(nsWriteSegmentFun aWriter,
void* aClosure, uint32_t aCount,
uint32_t* aResult) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
PartiallySeekableInputStream::IsNonBlocking(bool* aNonBlocking) {
return mInputStream->IsNonBlocking(aNonBlocking);
}
// nsICloneableInputStream interface
NS_IMETHODIMP
PartiallySeekableInputStream::GetCloneable(bool* aCloneable) {
NS_ENSURE_STATE(mWeakCloneableInputStream);
return mWeakCloneableInputStream->GetCloneable(aCloneable);
}
NS_IMETHODIMP
PartiallySeekableInputStream::Clone(nsIInputStream** aResult) {
NS_ENSURE_STATE(mWeakCloneableInputStream);
nsCOMPtr<nsIInputStream> clonedStream;
nsresult rv = mWeakCloneableInputStream->Clone(getter_AddRefs(clonedStream));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIInputStream> stream =
new PartiallySeekableInputStream(clonedStream.forget(), this);
stream.forget(aResult);
return NS_OK;
}
// nsIAsyncInputStream interface
NS_IMETHODIMP
PartiallySeekableInputStream::CloseWithStatus(nsresult aStatus) {
NS_ENSURE_STATE(mWeakAsyncInputStream);
return mWeakAsyncInputStream->CloseWithStatus(aStatus);
}
NS_IMETHODIMP
PartiallySeekableInputStream::AsyncWait(nsIInputStreamCallback* aCallback,
uint32_t aFlags,
uint32_t aRequestedCount,
nsIEventTarget* aEventTarget) {
if (mClosed) {
if (aCallback) {
if (aEventTarget) {
nsCOMPtr<nsIInputStreamCallback> callable = NS_NewInputStreamReadyEvent(
"PartiallySeekableInputStream::OnInputStreamReady", aCallback,
aEventTarget);
callable->OnInputStreamReady(this);
} else {
aCallback->OnInputStreamReady(this);
}
}
return NS_OK;
}
{
MutexAutoLock lock(mMutex);
if (NS_WARN_IF(mAsyncWaitCallback && aCallback &&
mAsyncWaitCallback != aCallback)) {
return NS_ERROR_FAILURE;
}
mAsyncWaitCallback = aCallback;
}
NS_ENSURE_STATE(mWeakAsyncInputStream);
nsCOMPtr<nsIInputStreamCallback> callback = aCallback ? this : nullptr;
return mWeakAsyncInputStream->AsyncWait(callback, aFlags, aRequestedCount,
aEventTarget);
}
// nsIInputStreamCallback
NS_IMETHODIMP
PartiallySeekableInputStream::OnInputStreamReady(nsIAsyncInputStream* aStream) {
MOZ_ASSERT(mWeakAsyncInputStream);
MOZ_ASSERT(mWeakAsyncInputStream == aStream);
nsCOMPtr<nsIInputStreamCallback> callback;
{
MutexAutoLock lock(mMutex);
// We have been canceled in the meanwhile.
if (!mAsyncWaitCallback) {
return NS_OK;
}
callback.swap(mAsyncWaitCallback);
}
MOZ_ASSERT(callback);
return callback->OnInputStreamReady(this);
}
// nsIIPCSerializableInputStream
void PartiallySeekableInputStream::SerializedComplexity(
uint32_t aMaxSize, uint32_t* aSizeUsed, uint32_t* aPipes,
uint32_t* aTransferables) {
mozilla::ipc::InputStreamHelper::SerializedComplexity(
mInputStream, aMaxSize, aSizeUsed, aPipes, aTransferables);
}
void PartiallySeekableInputStream::Serialize(
mozilla::ipc::InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
uint32_t aMaxSize, uint32_t* aSizeUsed,
mozilla::ipc::ParentToChildStreamActorManager* aManager) {
SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
aSizeUsed, aManager);
}
void PartiallySeekableInputStream::Serialize(
mozilla::ipc::InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
uint32_t aMaxSize, uint32_t* aSizeUsed,
mozilla::ipc::ChildToParentStreamActorManager* aManager) {
SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
aSizeUsed, aManager);
}
template <typename M>
void PartiallySeekableInputStream::SerializeInternal(
mozilla::ipc::InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
uint32_t aMaxSize, uint32_t* aSizeUsed, M* aManager) {
MOZ_ASSERT(mWeakIPCSerializableInputStream);
MOZ_DIAGNOSTIC_ASSERT(mCachedBuffer.IsEmpty());
mozilla::ipc::InputStreamHelper::SerializeInputStream(
mInputStream, aParams, aFileDescriptors, aDelayedStart, aMaxSize,
aSizeUsed, aManager);
}
bool PartiallySeekableInputStream::Deserialize(
const mozilla::ipc::InputStreamParams& aParams,
const FileDescriptorArray& aFileDescriptors) {
MOZ_CRASH("This method should never be called!");
return false;
}
// nsISeekableStream
NS_IMETHODIMP
PartiallySeekableInputStream::Seek(int32_t aWhence, int64_t aOffset) {
if (mClosed) {
return NS_BASE_STREAM_CLOSED;
}
int64_t offset;
switch (aWhence) {
case NS_SEEK_SET:
offset = aOffset;
break;
case NS_SEEK_CUR:
offset = mPos + aOffset;
break;
case NS_SEEK_END: {
return NS_ERROR_NOT_IMPLEMENTED;
}
default:
return NS_ERROR_ILLEGAL_VALUE;
}
if (offset < 0) {
return NS_ERROR_ILLEGAL_VALUE;
}
if ((uint64_t)offset >= mCachedBuffer.Length() || mPos > mBufferSize) {
return NS_ERROR_NOT_IMPLEMENTED;
}
mPos = offset;
return NS_OK;
}
NS_IMETHODIMP
PartiallySeekableInputStream::Tell(int64_t* aResult) {
if (mClosed) {
return NS_BASE_STREAM_CLOSED;
}
*aResult = mPos;
return NS_OK;
}
NS_IMETHODIMP
PartiallySeekableInputStream::SetEOF() { return Close(); }
// nsIInputStreamLength
NS_IMETHODIMP
PartiallySeekableInputStream::Length(int64_t* aLength) {
NS_ENSURE_STATE(mWeakInputStreamLength);
return mWeakInputStreamLength->Length(aLength);
}
// nsIAsyncInputStreamLength
NS_IMETHODIMP
PartiallySeekableInputStream::AsyncLengthWait(
nsIInputStreamLengthCallback* aCallback, nsIEventTarget* aEventTarget) {
if (mClosed) {
if (aCallback) {
const RefPtr<PartiallySeekableInputStream> self = this;
const nsCOMPtr<nsIInputStreamLengthCallback> callback = aCallback;
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
"PartiallySeekableInputStream::OnInputStreamLengthReady",
[self, callback] { callback->OnInputStreamLengthReady(self, -1); });
if (aEventTarget) {
aEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL);
} else {
runnable->Run();
}
}
return NS_OK;
}
NS_ENSURE_STATE(mWeakAsyncInputStreamLength);
nsCOMPtr<nsIInputStreamLengthCallback> callback = aCallback ? this : nullptr;
{
MutexAutoLock lock(mMutex);
mAsyncInputStreamLengthCallback = aCallback;
}
return mWeakAsyncInputStreamLength->AsyncLengthWait(callback, aEventTarget);
}
NS_IMETHODIMP
PartiallySeekableInputStream::OnInputStreamLengthReady(
nsIAsyncInputStreamLength* aStream, int64_t aLength) {
nsCOMPtr<nsIInputStreamLengthCallback> callback;
{
MutexAutoLock lock(mMutex);
// We have been canceled in the meanwhile.
if (!mAsyncInputStreamLengthCallback) {
return NS_OK;
}
callback.swap(mAsyncInputStreamLengthCallback);
}
return callback->OnInputStreamLengthReady(this, aLength);
}
} // namespace net
} // namespace mozilla

View File

@@ -1,91 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef PartiallySeekableInputStream_h
#define PartiallySeekableInputStream_h
#include "mozilla/Attributes.h"
#include "mozilla/Mutex.h"
#include "nsCOMPtr.h"
#include "nsIAsyncInputStream.h"
#include "nsICloneableInputStream.h"
#include "nsIInputStreamLength.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsISeekableStream.h"
namespace mozilla {
namespace net {
// A wrapper for making a stream seekable for the first |aBufferSize| bytes.
// Note that this object takes the ownership of the underlying stream.
class PartiallySeekableInputStream final : public nsISeekableStream,
public nsIAsyncInputStream,
public nsICloneableInputStream,
public nsIIPCSerializableInputStream,
public nsIInputStreamCallback,
public nsIInputStreamLength,
public nsIAsyncInputStreamLength,
public nsIInputStreamLengthCallback {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIINPUTSTREAMLENGTH
NS_DECL_NSIASYNCINPUTSTREAMLENGTH
NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK
explicit PartiallySeekableInputStream(
already_AddRefed<nsIInputStream> aInputStream,
uint64_t aBufferSize = 4096);
private:
PartiallySeekableInputStream(
already_AddRefed<nsIInputStream> aClonedBaseStream,
PartiallySeekableInputStream* aClonedFrom);
~PartiallySeekableInputStream() = default;
void Init();
template <typename M>
void SerializeInternal(mozilla::ipc::InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors,
bool aDelayedStart, uint32_t aMaxSize,
uint32_t* aSizeUsed, M* aManager);
nsCOMPtr<nsIInputStream> mInputStream;
// Raw pointers because these are just QI of mInputStream.
nsICloneableInputStream* mWeakCloneableInputStream;
nsIIPCSerializableInputStream* mWeakIPCSerializableInputStream;
nsIAsyncInputStream* mWeakAsyncInputStream;
nsIInputStreamLength* mWeakInputStreamLength;
nsIAsyncInputStreamLength* mWeakAsyncInputStreamLength;
// Protected by mutex.
nsCOMPtr<nsIInputStreamCallback> mAsyncWaitCallback;
// Protected by mutex.
nsCOMPtr<nsIInputStreamLengthCallback> mAsyncInputStreamLengthCallback;
nsTArray<char> mCachedBuffer;
uint64_t mBufferSize;
uint64_t mPos;
bool mClosed;
Mutex mMutex MOZ_UNANNOTATED;
};
} // namespace net
} // namespace mozilla
#endif // PartiallySeekableInputStream_h

View File

@@ -162,7 +162,6 @@ EXPORTS.mozilla.net += [
"IOActivityMonitor.h",
"MemoryDownloader.h",
"NetworkConnectivityService.h",
"PartiallySeekableInputStream.h",
"Predictor.h",
"PrivateBrowsingChannel.h",
"RedirectChannelRegistrar.h",
@@ -227,7 +226,6 @@ UNIFIED_SOURCES += [
"nsSyncStreamListener.cpp",
"nsTransportUtils.cpp",
"nsUDPSocket.cpp",
"PartiallySeekableInputStream.cpp",
"PollableEvent.cpp",
"Predictor.cpp",
"ProxyAutoConfig.cpp",

View File

@@ -1,517 +0,0 @@
#include "gtest/gtest.h"
#include "Helpers.h"
#include "nsCOMPtr.h"
#include "nsStreamUtils.h"
#include "nsString.h"
#include "nsStringStream.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/net/PartiallySeekableInputStream.h"
using mozilla::GetCurrentSerialEventTarget;
using mozilla::MakeRefPtr;
using mozilla::SpinEventLoopUntil;
using mozilla::net::PartiallySeekableInputStream;
class NonSeekableStream final : public nsIInputStream {
nsCOMPtr<nsIInputStream> mStream;
public:
NS_DECL_THREADSAFE_ISUPPORTS
explicit NonSeekableStream(const nsACString& aBuffer) {
NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer);
}
NS_IMETHOD
Available(uint64_t* aLength) override { return mStream->Available(aLength); }
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
return mStream->Read(aBuffer, aCount, aReadCount);
}
NS_IMETHOD
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount,
uint32_t* aResult) override {
return mStream->ReadSegments(aWriter, aClosure, aCount, aResult);
}
NS_IMETHOD
Close() override { return mStream->Close(); }
NS_IMETHOD
IsNonBlocking(bool* aNonBlocking) override {
return mStream->IsNonBlocking(aNonBlocking);
}
private:
~NonSeekableStream() = default;
};
NS_IMPL_ISUPPORTS(NonSeekableStream, nsIInputStream)
// Helper function for creating a non-seekable nsIInputStream + a
// PartiallySeekableInputStream.
PartiallySeekableInputStream* CreateStream(uint32_t aSize, uint64_t aStreamSize,
nsCString& aBuffer) {
aBuffer.SetLength(aSize);
for (uint32_t i = 0; i < aSize; ++i) {
aBuffer.BeginWriting()[i] = i % 10;
}
RefPtr<NonSeekableStream> stream = new NonSeekableStream(aBuffer);
return new PartiallySeekableInputStream(stream.forget(), aStreamSize);
}
// Simple reading.
TEST(TestPartiallySeekableInputStream, SimpleRead)
{
const size_t kBufSize = 10;
nsCString buf;
RefPtr<PartiallySeekableInputStream> psi = CreateStream(kBufSize, 5, buf);
uint64_t length;
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)kBufSize, length);
char buf2[kBufSize];
uint32_t count;
ASSERT_EQ(NS_OK, psi->Read(buf2, sizeof(buf2), &count));
ASSERT_EQ(count, buf.Length());
ASSERT_TRUE(nsCString(buf.get(), kBufSize).Equals(nsCString(buf2, count)));
// At this point, after reading more than the buffer size, seek is not
// allowed.
ASSERT_EQ(NS_ERROR_NOT_IMPLEMENTED,
psi->Seek(nsISeekableStream::NS_SEEK_SET, 0));
ASSERT_EQ(NS_ERROR_NOT_IMPLEMENTED,
psi->Seek(nsISeekableStream::NS_SEEK_END, 0));
ASSERT_EQ(NS_ERROR_NOT_IMPLEMENTED,
psi->Seek(nsISeekableStream::NS_SEEK_CUR, 0));
// Position is at the end of the stream.
int64_t pos;
ASSERT_EQ(NS_OK, psi->Tell(&pos));
ASSERT_EQ((int64_t)kBufSize, pos);
}
// Simple seek
TEST(TestPartiallySeekableInputStream, SimpleSeek)
{
const size_t kBufSize = 10;
nsCString buf;
RefPtr<PartiallySeekableInputStream> psi = CreateStream(kBufSize, 5, buf);
uint64_t length;
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)kBufSize, length);
uint32_t count;
{
char buf2[3];
ASSERT_EQ(NS_OK, psi->Read(buf2, sizeof(buf2), &count));
ASSERT_EQ(count, sizeof(buf2));
ASSERT_TRUE(nsCString(buf.get(), sizeof(buf2))
.Equals(nsCString(buf2, sizeof(buf2))));
int64_t pos;
ASSERT_EQ(NS_OK, psi->Tell(&pos));
ASSERT_EQ((int64_t)sizeof(buf2), pos);
uint64_t length;
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)kBufSize - sizeof(buf2), length);
}
// Let's seek back to the beginning using NS_SEEK_SET
ASSERT_EQ(NS_OK, psi->Seek(nsISeekableStream::NS_SEEK_SET, 0));
{
uint64_t length;
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)kBufSize, length);
char buf2[3];
ASSERT_EQ(NS_OK, psi->Read(buf2, sizeof(buf2), &count));
ASSERT_EQ(count, sizeof(buf2));
ASSERT_TRUE(nsCString(buf.get(), sizeof(buf2))
.Equals(nsCString(buf2, sizeof(buf2))));
int64_t pos;
ASSERT_EQ(NS_OK, psi->Tell(&pos));
ASSERT_EQ((int64_t)sizeof(buf2), pos);
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)kBufSize - sizeof(buf2), length);
}
// Let's seek back of 2 bytes using NS_SEEK_CUR
ASSERT_EQ(NS_OK, psi->Seek(nsISeekableStream::NS_SEEK_CUR, -2));
{
uint64_t length;
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)kBufSize - 1, length);
char buf2[3];
ASSERT_EQ(NS_OK, psi->Read(buf2, sizeof(buf2), &count));
ASSERT_EQ(count, sizeof(buf2));
ASSERT_TRUE(nsCString(buf.get() + 1, sizeof(buf2))
.Equals(nsCString(buf2, sizeof(buf2))));
int64_t pos;
ASSERT_EQ(NS_OK, psi->Tell(&pos));
ASSERT_EQ((int64_t)sizeof(buf2) + 1, pos);
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)kBufSize - sizeof(buf2) - 1, length);
}
// Let's seek back to the beginning using NS_SEEK_SET
ASSERT_EQ(NS_OK, psi->Seek(nsISeekableStream::NS_SEEK_SET, 0));
{
uint64_t length;
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)kBufSize, length);
char buf2[kBufSize];
ASSERT_EQ(NS_OK, psi->Read(buf2, sizeof(buf2), &count));
ASSERT_EQ(count, buf.Length());
ASSERT_TRUE(nsCString(buf.get(), kBufSize).Equals(nsCString(buf2, count)));
}
}
// Full in cache
TEST(TestPartiallySeekableInputStream, FullCachedSeek)
{
const size_t kBufSize = 10;
nsCString buf;
RefPtr<PartiallySeekableInputStream> psi = CreateStream(kBufSize, 4096, buf);
uint64_t length;
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)kBufSize, length);
char buf2[kBufSize];
uint32_t count;
ASSERT_EQ(NS_OK, psi->Read(buf2, sizeof(buf2), &count));
ASSERT_EQ(count, buf.Length());
ASSERT_TRUE(nsCString(buf.get(), kBufSize).Equals(nsCString(buf2, count)));
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)0, length);
ASSERT_EQ(NS_OK, psi->Seek(nsISeekableStream::NS_SEEK_SET, 0));
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)kBufSize, length);
ASSERT_EQ(NS_OK, psi->Read(buf2, sizeof(buf2), &count));
ASSERT_EQ(count, buf.Length());
ASSERT_TRUE(nsCString(buf.get(), kBufSize).Equals(nsCString(buf2, count)));
ASSERT_EQ(NS_OK, psi->Available(&length));
ASSERT_EQ((uint64_t)0, length);
}
TEST(TestPartiallySeekableInputStream, QIInputStreamLength)
{
nsCString buf;
buf.AssignLiteral("Hello world");
for (int i = 0; i < 4; i++) {
nsCOMPtr<nsIInputStream> psis;
{
RefPtr<testing::LengthInputStream> stream =
new testing::LengthInputStream(buf, i % 2, i > 1);
psis = new PartiallySeekableInputStream(stream.forget());
}
{
nsCOMPtr<nsIInputStreamLength> qi = do_QueryInterface(psis);
ASSERT_EQ(!!(i % 2), !!qi);
}
{
nsCOMPtr<nsIAsyncInputStreamLength> qi = do_QueryInterface(psis);
ASSERT_EQ(i > 1, !!qi);
}
}
}
TEST(TestPartiallySeekableInputStream, InputStreamLength)
{
nsCString buf;
buf.AssignLiteral("Hello world");
nsCOMPtr<nsIInputStream> psis;
{
RefPtr<testing::LengthInputStream> stream =
new testing::LengthInputStream(buf, true, false);
psis = new PartiallySeekableInputStream(stream.forget());
}
nsCOMPtr<nsIInputStreamLength> qi = do_QueryInterface(psis);
ASSERT_TRUE(!!qi);
int64_t size;
nsresult rv = qi->Length(&size);
ASSERT_EQ(NS_OK, rv);
ASSERT_EQ(int64_t(buf.Length()), size);
}
TEST(TestPartiallySeekableInputStream, NegativeInputStreamLength)
{
nsCString buf;
buf.AssignLiteral("Hello world");
nsCOMPtr<nsIInputStream> psis;
{
RefPtr<testing::LengthInputStream> stream =
new testing::LengthInputStream(buf, true, false, NS_OK, true);
psis = new PartiallySeekableInputStream(stream.forget());
}
nsCOMPtr<nsIInputStreamLength> qi = do_QueryInterface(psis);
ASSERT_TRUE(!!qi);
int64_t size;
nsresult rv = qi->Length(&size);
ASSERT_EQ(NS_OK, rv);
ASSERT_EQ(-1, size);
}
TEST(TestPartiallySeekableInputStream, AsyncInputStreamLength)
{
nsCString buf;
buf.AssignLiteral("Hello world");
nsCOMPtr<nsIInputStream> psis;
{
RefPtr<testing::LengthInputStream> stream =
new testing::LengthInputStream(buf, false, true);
psis = new PartiallySeekableInputStream(stream.forget());
}
nsCOMPtr<nsIAsyncInputStreamLength> qi = do_QueryInterface(psis);
ASSERT_TRUE(!!qi);
RefPtr<testing::LengthCallback> callback = new testing::LengthCallback();
nsresult rv = qi->AsyncLengthWait(callback, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, AsyncInputStreamLength)"_ns,
[&]() { return callback->Called(); }));
ASSERT_EQ(int64_t(buf.Length()), callback->Size());
}
TEST(TestPartiallySeekableInputStream, NegativeAsyncInputStreamLength)
{
nsCString buf;
buf.AssignLiteral("Hello world");
nsCOMPtr<nsIInputStream> psis;
{
RefPtr<testing::LengthInputStream> stream =
new testing::LengthInputStream(buf, false, true, NS_OK, true);
psis = new PartiallySeekableInputStream(stream.forget());
}
nsCOMPtr<nsIAsyncInputStreamLength> qi = do_QueryInterface(psis);
ASSERT_TRUE(!!qi);
RefPtr<testing::LengthCallback> callback = new testing::LengthCallback();
nsresult rv = qi->AsyncLengthWait(callback, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, NegativeAsyncInputStreamLength)"_ns,
[&]() { return callback->Called(); }));
ASSERT_EQ(-1, callback->Size());
}
TEST(TestPartiallySeekableInputStream, AbortLengthCallback)
{
nsCString buf;
buf.AssignLiteral("Hello world");
nsCOMPtr<nsIInputStream> psis;
{
RefPtr<testing::LengthInputStream> stream =
new testing::LengthInputStream(buf, false, true, NS_OK, true);
psis = new PartiallySeekableInputStream(stream.forget());
}
nsCOMPtr<nsIAsyncInputStreamLength> qi = do_QueryInterface(psis);
ASSERT_TRUE(!!qi);
RefPtr<testing::LengthCallback> callback1 = new testing::LengthCallback();
nsresult rv = qi->AsyncLengthWait(callback1, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
RefPtr<testing::LengthCallback> callback2 = new testing::LengthCallback();
rv = qi->AsyncLengthWait(callback2, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, AbortLengthCallback)"_ns,
[&]() { return callback2->Called(); }));
ASSERT_TRUE(!callback1->Called());
ASSERT_EQ(-1, callback2->Size());
}
TEST(TestPartiallySeekableInputStream, AsyncWaitAfterConsumed)
{
nsCString buf{"The Quick Brown Fox Jumps over the Lazy Dog"};
const size_t bufsize = 44;
auto stream = MakeRefPtr<testing::AsyncStringStream>(buf);
nsCOMPtr<nsIAsyncInputStream> psis =
new PartiallySeekableInputStream(stream.forget(), bufsize);
ASSERT_TRUE(psis);
auto callback = MakeRefPtr<testing::InputStreamCallback>();
nsresult rv = psis->AsyncWait(callback, 0, 0, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, AsyncWaitAfterConsumed) 1"_ns,
[&]() { return callback->Called(); }));
char rdbuf[bufsize] = {'\0'};
uint32_t count;
ASSERT_EQ(NS_OK, psis->Read(rdbuf, sizeof(rdbuf), &count));
ASSERT_STREQ(rdbuf, buf.Data());
callback = MakeRefPtr<testing::InputStreamCallback>();
rv = psis->AsyncWait(callback, 0, 0, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, AsyncWaitAfterConsumed) 2"_ns,
[&]() { return callback->Called(); }));
memset(rdbuf, 0x0, bufsize);
ASSERT_EQ(NS_OK, psis->Read(rdbuf, sizeof(rdbuf), &count));
ASSERT_EQ(0U, count);
}
TEST(TestPartiallySeekableInputStream, AsyncWaitAfterClosed)
{
nsCString buf{"The Quick Brown Fox Jumps over the Lazy Dog"};
const size_t bufsize = 44;
auto stream = MakeRefPtr<testing::AsyncStringStream>(buf);
nsCOMPtr<nsIAsyncInputStream> psis =
new PartiallySeekableInputStream(stream.forget(), bufsize);
ASSERT_TRUE(psis);
auto callback = MakeRefPtr<testing::InputStreamCallback>();
nsresult rv = psis->AsyncWait(callback, 0, 0, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, AsyncWaitAfterClosed) 1"_ns,
[&]() { return callback->Called(); }));
ASSERT_EQ(NS_OK, psis->Close());
callback = MakeRefPtr<testing::InputStreamCallback>();
rv = psis->AsyncWait(callback, 0, 0, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, AsyncWaitAfterClosed) 2"_ns,
[&]() { return callback->Called(); }));
}
TEST(TestPartiallySeekableInputStream, AsyncLengthWaitAfterClosed)
{
nsCString buf{"The Quick Brown Fox Jumps over the Lazy Dog"};
auto stream = MakeRefPtr<testing::LengthInputStream>(buf, false, true);
nsCOMPtr<nsIInputStream> psis =
new PartiallySeekableInputStream(stream.forget());
nsCOMPtr<nsIAsyncInputStreamLength> qi = do_QueryInterface(psis);
ASSERT_TRUE(qi);
auto callback = MakeRefPtr<testing::LengthCallback>();
nsresult rv = qi->AsyncLengthWait(callback, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, AsyncLengthWaitAfterClosed) 1"_ns,
[&]() { return callback->Called(); }));
ASSERT_EQ(int64_t(buf.Length()), callback->Size());
ASSERT_EQ(NS_OK, psis->Close());
callback = MakeRefPtr<testing::LengthCallback>();
rv = qi->AsyncLengthWait(callback, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, AsyncLengthWaitAfterClosed) 2"_ns,
[&]() { return callback->Called(); }));
ASSERT_EQ(-1, callback->Size());
}
TEST(TestPartiallySeekableInputStream, AsyncLengthWaitAfterConsumed)
{
nsCString buf{"The Quick Brown Fox Jumps over the Lazy Dog"};
const size_t bufsize = 44;
auto stream = MakeRefPtr<testing::LengthInputStream>(buf, false, true);
nsCOMPtr<nsIInputStream> psis =
new PartiallySeekableInputStream(stream.forget());
nsCOMPtr<nsIAsyncInputStreamLength> qi = do_QueryInterface(psis);
ASSERT_TRUE(qi);
auto callback = MakeRefPtr<testing::LengthCallback>();
nsresult rv = qi->AsyncLengthWait(callback, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, AsyncLengthWaitAfterConsumed) 1"_ns,
[&]() { return callback->Called(); }));
ASSERT_EQ(int64_t(buf.Length()), callback->Size());
char rdbuf[bufsize] = {'\0'};
uint32_t count;
ASSERT_EQ(NS_OK, psis->Read(rdbuf, sizeof(rdbuf), &count));
ASSERT_STREQ(rdbuf, buf.Data());
callback = MakeRefPtr<testing::LengthCallback>();
rv = qi->AsyncLengthWait(callback, GetCurrentSerialEventTarget());
ASSERT_EQ(NS_OK, rv);
MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
"TEST(TestPartiallySeekableInputStream, AsyncLengthWaitAfterConsumed) 2"_ns,
[&]() { return callback->Called(); }));
ASSERT_EQ(0U, callback->Size());
memset(rdbuf, 0x0, bufsize);
ASSERT_EQ(NS_OK, psis->Read(rdbuf, sizeof(rdbuf), &count));
ASSERT_EQ(0U, count);
}

View File

@@ -37,7 +37,6 @@ if CONFIG["OS_TARGET"] == "WINNT":
if not (CONFIG["OS_TARGET"] == "WINNT" and CONFIG["CPU_ARCH"] == "aarch64"):
UNIFIED_SOURCES += [
"TestPACMan.cpp",
"TestPartiallySeekableInputStream.cpp",
"TestURIMutator.cpp",
]