diff --git a/xpcom/tests/gtest/Helpers.cpp b/xpcom/tests/gtest/Helpers.cpp index faa019b6686..8a98a5aa096 100644 --- a/xpcom/tests/gtest/Helpers.cpp +++ b/xpcom/tests/gtest/Helpers.cpp @@ -94,4 +94,22 @@ ConsumeAndValidateStream(nsIInputStream* aStream, ASSERT_TRUE(aExpectedData.Equals(outputData)); } +NS_IMPL_ISUPPORTS(OutputStreamCallback, nsIOutputStreamCallback); + +OutputStreamCallback::OutputStreamCallback() + : mCalled(false) +{ +} + +OutputStreamCallback::~OutputStreamCallback() +{ +} + +NS_IMETHODIMP +OutputStreamCallback::OnOutputStreamReady(nsIAsyncOutputStream* aStream) +{ + mCalled = true; + return NS_OK; +} + } // namespace testing diff --git a/xpcom/tests/gtest/Helpers.h b/xpcom/tests/gtest/Helpers.h index 0e501ae63e9..1a52370007d 100644 --- a/xpcom/tests/gtest/Helpers.h +++ b/xpcom/tests/gtest/Helpers.h @@ -7,6 +7,7 @@ #ifndef __Helpers_h #define __Helpers_h +#include "nsIAsyncOutputStream.h" #include "nsString.h" #include @@ -34,6 +35,22 @@ void ConsumeAndValidateStream(nsIInputStream* aStream, const nsACString& aExpectedData); +class OutputStreamCallback MOZ_FINAL : public nsIOutputStreamCallback +{ +public: + OutputStreamCallback(); + + bool Called() const { return mCalled; } + +private: + ~OutputStreamCallback(); + + bool mCalled; +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOUTPUTSTREAMCALLBACK +}; + } // namespace testing #endif // __Helpers_h diff --git a/xpcom/tests/gtest/TestPipes.cpp b/xpcom/tests/gtest/TestPipes.cpp index 7120a0b5c24..de0942c9055 100644 --- a/xpcom/tests/gtest/TestPipes.cpp +++ b/xpcom/tests/gtest/TestPipes.cpp @@ -660,3 +660,127 @@ TEST(Pipes, Clone_DuringWrite_ReadDuringWrite_CloseDuringWrite) 2, // num clones to add after each write 3); // num streams to read after each write } + +TEST(Pipes, Write_AsyncWait) +{ + nsCOMPtr reader; + nsCOMPtr writer; + + const uint32_t segmentSize = 1024; + const uint32_t numSegments = 1; + + nsresult rv = NS_NewPipe2(getter_AddRefs(reader), getter_AddRefs(writer), + true, true, // non-blocking - reader, writer + segmentSize, numSegments); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + nsTArray inputData; + testing::CreateData(segmentSize, inputData); + + uint32_t numWritten = 0; + rv = writer->Write(inputData.Elements(), inputData.Length(), &numWritten); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + rv = writer->Write(inputData.Elements(), inputData.Length(), &numWritten); + ASSERT_EQ(NS_BASE_STREAM_WOULD_BLOCK, rv); + + nsRefPtr cb = + new testing::OutputStreamCallback(); + + rv = writer->AsyncWait(cb, 0, 0, nullptr); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + ASSERT_FALSE(cb->Called()); + + testing::ConsumeAndValidateStream(reader, inputData); + + ASSERT_TRUE(cb->Called()); +} + +TEST(Pipes, Write_AsyncWait_Clone) +{ + nsCOMPtr reader; + nsCOMPtr writer; + + const uint32_t segmentSize = 1024; + const uint32_t numSegments = 1; + + nsresult rv = NS_NewPipe2(getter_AddRefs(reader), getter_AddRefs(writer), + true, true, // non-blocking - reader, writer + segmentSize, numSegments); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + nsCOMPtr clone; + rv = NS_CloneInputStream(reader, getter_AddRefs(clone)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + nsTArray inputData; + testing::CreateData(segmentSize, inputData); + + uint32_t numWritten = 0; + rv = writer->Write(inputData.Elements(), inputData.Length(), &numWritten); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + rv = writer->Write(inputData.Elements(), inputData.Length(), &numWritten); + ASSERT_EQ(NS_BASE_STREAM_WOULD_BLOCK, rv); + + nsRefPtr cb = + new testing::OutputStreamCallback(); + + rv = writer->AsyncWait(cb, 0, 0, nullptr); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + ASSERT_FALSE(cb->Called()); + + testing::ConsumeAndValidateStream(reader, inputData); + + ASSERT_FALSE(cb->Called()); + + testing::ConsumeAndValidateStream(clone, inputData); + + ASSERT_TRUE(cb->Called()); +} + +TEST(Pipes, Write_AsyncWait_Clone_CloseOriginal) +{ + nsCOMPtr reader; + nsCOMPtr writer; + + const uint32_t segmentSize = 1024; + const uint32_t numSegments = 1; + + nsresult rv = NS_NewPipe2(getter_AddRefs(reader), getter_AddRefs(writer), + true, true, // non-blocking - reader, writer + segmentSize, numSegments); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + nsCOMPtr clone; + rv = NS_CloneInputStream(reader, getter_AddRefs(clone)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + nsTArray inputData; + testing::CreateData(segmentSize, inputData); + + uint32_t numWritten = 0; + rv = writer->Write(inputData.Elements(), inputData.Length(), &numWritten); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + rv = writer->Write(inputData.Elements(), inputData.Length(), &numWritten); + ASSERT_EQ(NS_BASE_STREAM_WOULD_BLOCK, rv); + + nsRefPtr cb = + new testing::OutputStreamCallback(); + + rv = writer->AsyncWait(cb, 0, 0, nullptr); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + ASSERT_FALSE(cb->Called()); + + testing::ConsumeAndValidateStream(clone, inputData); + + ASSERT_FALSE(cb->Called()); + + reader->Close(); + + ASSERT_TRUE(cb->Called()); +}