Bug 1421176 - nsMultiplexInputStream::Available() sanitize - gtests - r=smaug

This commit is contained in:
Andrea Marchesini 2017-11-30 20:00:23 +01:00
Родитель bc6f11d624
Коммит 10c57af6af
1 изменённых файлов: 181 добавлений и 0 удалений

Просмотреть файл

@ -213,3 +213,184 @@ TEST(TestMultiplexInputStream, AsyncWait_withEventTarget_closureOnly) {
MOZ_ALWAYS_TRUE(mozilla::SpinEventLoopUntil([&]() { return cb->Called(); }));
ASSERT_TRUE(cb->Called());
}
class ClosedStream final : public nsIInputStream
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
ClosedStream() {}
NS_IMETHOD
Available(uint64_t* aLength) override
{
return NS_BASE_STREAM_CLOSED;
}
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override
{
MOZ_CRASH("This should not be called!");
return NS_OK;
}
NS_IMETHOD
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t *aResult) override
{
MOZ_CRASH("This should not be called!");
return NS_OK;
}
NS_IMETHOD
Close() override { return NS_OK; }
NS_IMETHOD
IsNonBlocking(bool* aNonBlocking) override
{
*aNonBlocking = true;
return NS_OK;
}
private:
~ClosedStream() = default;
};
NS_IMPL_ISUPPORTS(ClosedStream, nsIInputStream)
class AsyncStream final : public nsIAsyncInputStream
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
explicit AsyncStream(int64_t aSize) : mState(eBlocked), mSize(aSize) {}
void
Unblock()
{
mState = eUnblocked;
}
NS_IMETHOD
Available(uint64_t* aLength) override
{
*aLength = mState == eBlocked ? 0 : mSize;
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_OK;
}
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override
{
MOZ_CRASH("This should not be called!");
return NS_OK;
}
NS_IMETHOD
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t *aResult) override
{
MOZ_CRASH("This should not be called!");
return NS_OK;
}
NS_IMETHOD
Close() override
{
mState = eClosed;
return NS_OK;
}
NS_IMETHOD
IsNonBlocking(bool* aNonBlocking) override
{
*aNonBlocking = true;
return NS_OK;
}
NS_IMETHOD
AsyncWait(nsIInputStreamCallback* aCallback,
uint32_t aFlags, uint32_t aRequestedCount,
nsIEventTarget* aEventTarget) override
{
MOZ_CRASH("This should not be called!");
return NS_OK;
}
NS_IMETHOD
CloseWithStatus(nsresult aStatus) override
{
return NS_OK;
}
private:
~AsyncStream() = default;
enum {
eBlocked,
eUnblocked,
eClosed
} mState;
uint64_t mSize;
};
NS_IMPL_ISUPPORTS(AsyncStream, nsIInputStream, nsIAsyncInputStream)
TEST(TestMultiplexInputStream, Available) {
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
nsCOMPtr<nsIInputStream> s = do_QueryInterface(multiplexStream);
ASSERT_TRUE(!!s);
nsCOMPtr<nsIAsyncInputStream> as = do_QueryInterface(multiplexStream);
ASSERT_TRUE(!as);
uint64_t length;
// The stream returns NS_BASE_STREAM_CLOSED if there are no substreams.
nsresult rv = s->Available(&length);
ASSERT_EQ(NS_BASE_STREAM_CLOSED, rv);
rv = multiplexStream->AppendStream(new ClosedStream());
ASSERT_EQ(NS_OK, rv);
uint64_t asyncSize = 2;
RefPtr<AsyncStream> asyncStream = new AsyncStream(2);
rv = multiplexStream->AppendStream(asyncStream);
ASSERT_EQ(NS_OK, rv);
nsCString buffer;
buffer.Assign("World!!!");
nsCOMPtr<nsIInputStream> stringStream;
rv = NS_NewCStringInputStream(getter_AddRefs(stringStream), buffer);
ASSERT_EQ(NS_OK, rv);
rv = multiplexStream->AppendStream(stringStream);
ASSERT_EQ(NS_OK, rv);
// Now we are async.
as = do_QueryInterface(multiplexStream);
ASSERT_TRUE(!!as);
// Available should skip the closed stream and return 0 because the
// asyncStream returns 0 and it's async.
rv = s->Available(&length);
ASSERT_EQ(NS_OK, rv);
ASSERT_EQ((uint64_t)0, length);
asyncStream->Unblock();
// Now we should return only the size of the async stream because we don't
// know when this is completed.
rv = s->Available(&length);
ASSERT_EQ(NS_OK, rv);
ASSERT_EQ(asyncSize, length);
asyncStream->Close();
rv = s->Available(&length);
ASSERT_EQ(NS_OK, rv);
ASSERT_EQ(buffer.Length(), length);
}