зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1421176 - nsMultiplexInputStream::Available() sanitize - gtests - r=smaug
This commit is contained in:
Родитель
bc6f11d624
Коммит
10c57af6af
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче