Bug 1636823 - nsMultiplexInputStream should not be blocking and nsIAsyncInputStream at the same time - part 3 - tests, r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D76998
This commit is contained in:
Andrea Marchesini 2020-06-01 10:31:46 +00:00
Родитель 699028c74a
Коммит 8c01ca65b0
1 изменённых файлов: 276 добавлений и 0 удалений

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

@ -49,6 +49,7 @@ TEST(MultiplexInputStream, Seek_SET)
rv = multiplexStream->AppendStream(inputStream3);
ASSERT_TRUE(NS_SUCCEEDED(rv));
int64_t tell;
uint64_t length;
uint32_t count;
char readBuf[4096];
@ -62,6 +63,9 @@ TEST(MultiplexInputStream, Seek_SET)
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf1.Length() + buf2.Length() + buf3.Length() - 1,
length);
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, 1);
// Check read is correct
rv = stream->Read(readBuf, 3, &count);
@ -72,6 +76,9 @@ TEST(MultiplexInputStream, Seek_SET)
ASSERT_EQ((uint64_t)buf1.Length() + buf2.Length() + buf3.Length() - 4,
length);
ASSERT_EQ(0, strncmp(readBuf, "ell", count));
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, 4);
// Seek to start of third input stream
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET,
@ -80,6 +87,9 @@ TEST(MultiplexInputStream, Seek_SET)
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf3.Length(), length);
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, buf1.Length() + buf2.Length());
// Check read is correct
rv = stream->Read(readBuf, 5, &count);
@ -89,6 +99,9 @@ TEST(MultiplexInputStream, Seek_SET)
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf3.Length() - 5, length);
ASSERT_EQ(0, strncmp(readBuf, "Foo b", count));
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, buf1.Length() + buf2.Length() + 5);
// Seek back to start of second stream (covers bug 1272371)
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET, buf1.Length());
@ -96,6 +109,9 @@ TEST(MultiplexInputStream, Seek_SET)
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf2.Length() + buf3.Length(), length);
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, buf1.Length());
// Check read is correct
rv = stream->Read(readBuf, 6, &count);
@ -105,6 +121,177 @@ TEST(MultiplexInputStream, Seek_SET)
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf2.Length() - 6 + buf3.Length(), length);
ASSERT_EQ(0, strncmp(readBuf, "The qu", count));
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, buf1.Length() + 6);
}
TEST(MultiplexInputStream, Seek_CUR)
{
nsCString buf1;
nsCString buf2;
nsCString buf3;
buf1.AssignLiteral("Hello world");
buf2.AssignLiteral("The quick brown fox jumped over the lazy dog");
buf3.AssignLiteral("Foo bar");
nsCOMPtr<nsIInputStream> inputStream1;
nsCOMPtr<nsIInputStream> inputStream2;
nsCOMPtr<nsIInputStream> inputStream3;
nsresult rv = NS_NewCStringInputStream(getter_AddRefs(inputStream1), buf1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = NS_NewCStringInputStream(getter_AddRefs(inputStream2), buf2);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = NS_NewCStringInputStream(getter_AddRefs(inputStream3), buf3);
ASSERT_TRUE(NS_SUCCEEDED(rv));
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
ASSERT_TRUE(multiplexStream);
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multiplexStream));
ASSERT_TRUE(stream);
rv = multiplexStream->AppendStream(inputStream1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = multiplexStream->AppendStream(inputStream2);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = multiplexStream->AppendStream(inputStream3);
ASSERT_TRUE(NS_SUCCEEDED(rv));
int64_t tell;
uint64_t length;
uint32_t count;
char readBuf[4096];
nsCOMPtr<nsISeekableStream> seekStream = do_QueryInterface(multiplexStream);
ASSERT_TRUE(seekStream);
// Seek forward in first input stream
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_CUR, 1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf1.Length() + buf2.Length() + buf3.Length() - 1,
length);
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, 1);
// Check read is correct
rv = stream->Read(readBuf, 3, &count);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)3, count);
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf1.Length() + buf2.Length() + buf3.Length() - 4,
length);
ASSERT_EQ(0, strncmp(readBuf, "ell", count));
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, 4);
// Let's go to the second stream
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_CUR, 11);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, 15);
rv = stream->Read(readBuf, 3, &count);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)3, count);
ASSERT_EQ(0, strncmp(readBuf, "qui", count));
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, 18);
// Let's go back to the first stream
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_CUR, -9);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, 9);
rv = stream->Read(readBuf, 3, &count);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)3, count);
ASSERT_EQ(0, strncmp(readBuf, "ldT", count));
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, 12);
}
TEST(MultiplexInputStream, Seek_END)
{
nsCString buf1;
nsCString buf2;
nsCString buf3;
buf1.AssignLiteral("Hello world");
buf2.AssignLiteral("The quick brown fox jumped over the lazy dog");
buf3.AssignLiteral("Foo bar");
nsCOMPtr<nsIInputStream> inputStream1;
nsCOMPtr<nsIInputStream> inputStream2;
nsCOMPtr<nsIInputStream> inputStream3;
nsresult rv = NS_NewCStringInputStream(getter_AddRefs(inputStream1), buf1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = NS_NewCStringInputStream(getter_AddRefs(inputStream2), buf2);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = NS_NewCStringInputStream(getter_AddRefs(inputStream3), buf3);
ASSERT_TRUE(NS_SUCCEEDED(rv));
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
ASSERT_TRUE(multiplexStream);
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multiplexStream));
ASSERT_TRUE(stream);
rv = multiplexStream->AppendStream(inputStream1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = multiplexStream->AppendStream(inputStream2);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = multiplexStream->AppendStream(inputStream3);
ASSERT_TRUE(NS_SUCCEEDED(rv));
int64_t tell;
uint64_t length;
nsCOMPtr<nsISeekableStream> seekStream = do_QueryInterface(multiplexStream);
ASSERT_TRUE(seekStream);
// SEEK_END wants <=0 values
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_END, 1);
ASSERT_TRUE(NS_FAILED(rv));
// Let's go to the end.
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_END, 0);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((int64_t)0, length);
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, buf1.Length() + buf2.Length() + buf3.Length());
// -1
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_END, -1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(1, length);
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, buf1.Length() + buf2.Length() + buf3.Length() - 1);
// Almost at the beginning
tell = 1;
tell -= buf1.Length();
tell -= buf2.Length();
tell -= buf3.Length();
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_END, tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(length, buf1.Length() + buf2.Length() + buf3.Length() - 1);
rv = seekStream->Tell(&tell);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(tell, 1);
}
static already_AddRefed<nsIInputStream> CreateStreamHelper() {
@ -302,6 +489,42 @@ class AsyncStream final : public nsIAsyncInputStream {
NS_IMPL_ISUPPORTS(AsyncStream, nsIInputStream, nsIAsyncInputStream)
class BlockingStream final : public nsIInputStream {
public:
NS_DECL_THREADSAFE_ISUPPORTS
BlockingStream() = default;
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 {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD
Close() override { return NS_OK; }
NS_IMETHOD
IsNonBlocking(bool* aNonBlocking) override {
*aNonBlocking = false;
return NS_OK;
}
private:
~BlockingStream() = default;
};
NS_IMPL_ISUPPORTS(BlockingStream, nsIInputStream)
TEST(TestMultiplexInputStream, Available)
{
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
@ -586,3 +809,56 @@ TEST(TestMultiplexInputStream, LengthInputStream)
ASSERT_FALSE(callback1->Called());
ASSERT_TRUE(callback2->Called());
}
void BlockingVsAsyncHelper(nsIMultiplexInputStream* aStream, bool aNonBlocking,
bool aAsyncStream) {
MOZ_ASSERT(aStream);
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(aStream);
ASSERT_TRUE(!!stream);
bool nonBlocking = false;
nsresult rv = stream->IsNonBlocking(&nonBlocking);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_TRUE(nonBlocking == aNonBlocking);
nsCOMPtr<nsIAsyncInputStream> asyncStream(do_QueryInterface(aStream));
ASSERT_TRUE(!!asyncStream == aAsyncStream);
}
TEST(TestMultiplexInputStream, BlockingVsAsync)
{
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
// An empty stream is non-blocking and not-async
BlockingVsAsyncHelper(multiplexStream, true, false);
// Adding a non-blocking, not-async stream, we are still non-blocking and
// not-async.
nsCString buf;
buf.AssignLiteral("Hello world");
nsCOMPtr<nsIInputStream> inputStream;
nsresult rv = NS_NewCStringInputStream(getter_AddRefs(inputStream), buf);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = multiplexStream->AppendStream(inputStream);
ASSERT_TRUE(NS_SUCCEEDED(rv));
BlockingVsAsyncHelper(multiplexStream, true, false);
// Let's add a blocking stream, not-async. It will become blocking.
RefPtr<BlockingStream> bs = new BlockingStream();
rv = multiplexStream->AppendStream(bs);
ASSERT_TRUE(NS_SUCCEEDED(rv));
BlockingVsAsyncHelper(multiplexStream, false, false);
// Let's add an async stream. Now we are async!
RefPtr<AsyncStream> as = new AsyncStream(10);
rv = multiplexStream->AppendStream(as);
ASSERT_TRUE(NS_SUCCEEDED(rv));
BlockingVsAsyncHelper(multiplexStream, false, false);
}