summaryrefslogtreecommitdiffstats
path: root/netwerk/test/gtest/TestInputStreamTransport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/test/gtest/TestInputStreamTransport.cpp')
-rw-r--r--netwerk/test/gtest/TestInputStreamTransport.cpp204
1 files changed, 204 insertions, 0 deletions
diff --git a/netwerk/test/gtest/TestInputStreamTransport.cpp b/netwerk/test/gtest/TestInputStreamTransport.cpp
new file mode 100644
index 0000000000..43df0e193a
--- /dev/null
+++ b/netwerk/test/gtest/TestInputStreamTransport.cpp
@@ -0,0 +1,204 @@
+#include "gtest/gtest.h"
+
+#include "nsIStreamTransportService.h"
+#include "nsStreamUtils.h"
+#include "nsThreadUtils.h"
+#include "Helpers.h"
+#include "nsNetCID.h"
+#include "nsServiceManagerUtils.h"
+#include "nsITransport.h"
+#include "nsNetUtil.h"
+
+static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
+
+void CreateStream(already_AddRefed<nsIInputStream> aSource,
+ nsIAsyncInputStream** aStream) {
+ nsCOMPtr<nsIInputStream> source = std::move(aSource);
+
+ nsresult rv;
+ nsCOMPtr<nsIStreamTransportService> sts =
+ do_GetService(kStreamTransportServiceCID, &rv);
+ ASSERT_EQ(NS_OK, rv);
+
+ nsCOMPtr<nsITransport> transport;
+ rv = sts->CreateInputTransport(source, true, getter_AddRefs(transport));
+ ASSERT_EQ(NS_OK, rv);
+
+ nsCOMPtr<nsIInputStream> wrapper;
+ rv = transport->OpenInputStream(0, 0, 0, getter_AddRefs(wrapper));
+ ASSERT_EQ(NS_OK, rv);
+
+ nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(wrapper);
+ MOZ_ASSERT(asyncStream);
+
+ asyncStream.forget(aStream);
+}
+
+class BlockingSyncStream final : public nsIInputStream {
+ nsCOMPtr<nsIInputStream> mStream;
+
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+
+ explicit BlockingSyncStream(const nsACString& aBuffer) {
+ NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer);
+ }
+
+ NS_IMETHOD
+ Available(uint64_t* aLength) override { return mStream->Available(aLength); }
+
+ NS_IMETHOD
+ StreamStatus() override { return mStream->StreamStatus(); }
+
+ 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 {
+ *aNonBlocking = false;
+ return NS_OK;
+ }
+
+ private:
+ ~BlockingSyncStream() = default;
+};
+
+NS_IMPL_ISUPPORTS(BlockingSyncStream, nsIInputStream)
+
+// Testing a simple blocking stream.
+TEST(TestInputStreamTransport, BlockingNotAsync)
+{
+ RefPtr<BlockingSyncStream> stream = new BlockingSyncStream("Hello world"_ns);
+
+ nsCOMPtr<nsIAsyncInputStream> ais;
+ CreateStream(stream.forget(), getter_AddRefs(ais));
+ ASSERT_TRUE(!!ais);
+
+ nsAutoCString data;
+ nsresult rv = NS_ReadInputStreamToString(ais, data, -1);
+ ASSERT_EQ(NS_OK, rv);
+
+ ASSERT_TRUE(data.EqualsLiteral("Hello world"));
+}
+
+class BlockingAsyncStream final : public nsIAsyncInputStream {
+ nsCOMPtr<nsIInputStream> mStream;
+ bool mPending;
+
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+
+ explicit BlockingAsyncStream(const nsACString& aBuffer) : mPending(false) {
+ NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer);
+ }
+
+ NS_IMETHOD
+ Available(uint64_t* aLength) override {
+ mStream->Available(aLength);
+
+ // 1 char at the time, just to test the asyncWait+Read loop a bit more.
+ if (*aLength > 0) {
+ *aLength = 1;
+ }
+
+ return NS_OK;
+ }
+
+ NS_IMETHOD
+ StreamStatus() override { return mStream->StreamStatus(); }
+
+ NS_IMETHOD
+ Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
+ mPending = !mPending;
+ if (mPending) {
+ return NS_BASE_STREAM_WOULD_BLOCK;
+ }
+
+ // 1 char at the time, just to test the asyncWait+Read loop a bit more.
+ aCount = 1;
+
+ return mStream->Read(aBuffer, aCount, aReadCount);
+ }
+
+ NS_IMETHOD
+ ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount,
+ uint32_t* aResult) override {
+ mPending = !mPending;
+ if (mPending) {
+ return NS_BASE_STREAM_WOULD_BLOCK;
+ }
+
+ // 1 char at the time, just to test the asyncWait+Read loop a bit more.
+ aCount = 1;
+
+ return mStream->ReadSegments(aWriter, aClosure, aCount, aResult);
+ }
+
+ NS_IMETHOD
+ Close() override { return mStream->Close(); }
+
+ NS_IMETHOD
+ IsNonBlocking(bool* aNonBlocking) override {
+ *aNonBlocking = false;
+ return NS_OK;
+ }
+
+ NS_IMETHOD
+ CloseWithStatus(nsresult aStatus) override { return Close(); }
+
+ NS_IMETHOD
+ AsyncWait(nsIInputStreamCallback* aCallback, uint32_t aFlags,
+ uint32_t aRequestedCount, nsIEventTarget* aEventTarget) override {
+ if (!aCallback) {
+ return NS_OK;
+ }
+
+ RefPtr<BlockingAsyncStream> self = this;
+ nsCOMPtr<nsIInputStreamCallback> callback = aCallback;
+
+ nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+ "gtest-asyncwait",
+ [self, callback]() { callback->OnInputStreamReady(self); });
+
+ if (aEventTarget) {
+ aEventTarget->Dispatch(r.forget());
+ } else {
+ r->Run();
+ }
+
+ return NS_OK;
+ }
+
+ private:
+ ~BlockingAsyncStream() = default;
+};
+
+NS_IMPL_ISUPPORTS(BlockingAsyncStream, nsIInputStream, nsIAsyncInputStream)
+
+// Testing an async blocking stream.
+TEST(TestInputStreamTransport, BlockingAsync)
+{
+ RefPtr<BlockingAsyncStream> stream =
+ new BlockingAsyncStream("Hello world"_ns);
+
+ nsCOMPtr<nsIAsyncInputStream> ais;
+ CreateStream(stream.forget(), getter_AddRefs(ais));
+ ASSERT_TRUE(!!ais);
+
+ nsAutoCString data;
+ nsresult rv = NS_ReadInputStreamToString(ais, data, -1);
+ ASSERT_EQ(NS_OK, rv);
+
+ ASSERT_TRUE(data.EqualsLiteral("Hello world"));
+}