tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestInputStreamTransport.cpp (5306B)


      1 #include "gtest/gtest.h"
      2 
      3 #include "nsIStreamTransportService.h"
      4 #include "nsStreamUtils.h"
      5 #include "nsThreadUtils.h"
      6 #include "Helpers.h"
      7 #include "nsNetCID.h"
      8 #include "nsServiceManagerUtils.h"
      9 #include "nsITransport.h"
     10 #include "nsNetUtil.h"
     11 
     12 static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
     13 
     14 void CreateStream(already_AddRefed<nsIInputStream> aSource,
     15                  nsIAsyncInputStream** aStream) {
     16  nsCOMPtr<nsIInputStream> source = std::move(aSource);
     17 
     18  nsresult rv;
     19  nsCOMPtr<nsIStreamTransportService> sts =
     20      do_GetService(kStreamTransportServiceCID, &rv);
     21  ASSERT_EQ(NS_OK, rv);
     22 
     23  nsCOMPtr<nsITransport> transport;
     24  rv = sts->CreateInputTransport(source, true, getter_AddRefs(transport));
     25  ASSERT_EQ(NS_OK, rv);
     26 
     27  nsCOMPtr<nsIInputStream> wrapper;
     28  rv = transport->OpenInputStream(0, 0, 0, getter_AddRefs(wrapper));
     29  ASSERT_EQ(NS_OK, rv);
     30 
     31  nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(wrapper);
     32  MOZ_RELEASE_ASSERT(asyncStream);
     33 
     34  asyncStream.forget(aStream);
     35 }
     36 
     37 class BlockingSyncStream final : public nsIInputStream {
     38  nsCOMPtr<nsIInputStream> mStream;
     39 
     40 public:
     41  NS_DECL_THREADSAFE_ISUPPORTS
     42 
     43  explicit BlockingSyncStream(const nsACString& aBuffer) {
     44    NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer);
     45  }
     46 
     47  NS_IMETHOD
     48  Available(uint64_t* aLength) override { return mStream->Available(aLength); }
     49 
     50  NS_IMETHOD
     51  StreamStatus() override { return mStream->StreamStatus(); }
     52 
     53  NS_IMETHOD
     54  Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
     55    return mStream->Read(aBuffer, aCount, aReadCount);
     56  }
     57 
     58  NS_IMETHOD
     59  ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount,
     60               uint32_t* aResult) override {
     61    return mStream->ReadSegments(aWriter, aClosure, aCount, aResult);
     62  }
     63 
     64  NS_IMETHOD
     65  Close() override { return mStream->Close(); }
     66 
     67  NS_IMETHOD
     68  IsNonBlocking(bool* aNonBlocking) override {
     69    *aNonBlocking = false;
     70    return NS_OK;
     71  }
     72 
     73 private:
     74  ~BlockingSyncStream() = default;
     75 };
     76 
     77 NS_IMPL_ISUPPORTS(BlockingSyncStream, nsIInputStream)
     78 
     79 // Testing a simple blocking stream.
     80 TEST(TestInputStreamTransport, BlockingNotAsync)
     81 {
     82  RefPtr<BlockingSyncStream> stream = new BlockingSyncStream("Hello world"_ns);
     83 
     84  nsCOMPtr<nsIAsyncInputStream> ais;
     85  CreateStream(stream.forget(), getter_AddRefs(ais));
     86  ASSERT_TRUE(!!ais);
     87 
     88  nsAutoCString data;
     89  nsresult rv = NS_ReadInputStreamToString(ais, data, -1);
     90  ASSERT_EQ(NS_OK, rv);
     91 
     92  ASSERT_TRUE(data.EqualsLiteral("Hello world"));
     93 }
     94 
     95 class BlockingAsyncStream final : public nsIAsyncInputStream {
     96  nsCOMPtr<nsIInputStream> mStream;
     97  bool mPending;
     98 
     99 public:
    100  NS_DECL_THREADSAFE_ISUPPORTS
    101 
    102  explicit BlockingAsyncStream(const nsACString& aBuffer) : mPending(false) {
    103    NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer);
    104  }
    105 
    106  NS_IMETHOD
    107  Available(uint64_t* aLength) override {
    108    mStream->Available(aLength);
    109 
    110    // 1 char at the time, just to test the asyncWait+Read loop a bit more.
    111    if (*aLength > 0) {
    112      *aLength = 1;
    113    }
    114 
    115    return NS_OK;
    116  }
    117 
    118  NS_IMETHOD
    119  StreamStatus() override { return mStream->StreamStatus(); }
    120 
    121  NS_IMETHOD
    122  Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
    123    mPending = !mPending;
    124    if (mPending) {
    125      return NS_BASE_STREAM_WOULD_BLOCK;
    126    }
    127 
    128    // 1 char at the time, just to test the asyncWait+Read loop a bit more.
    129    aCount = 1;
    130 
    131    return mStream->Read(aBuffer, aCount, aReadCount);
    132  }
    133 
    134  NS_IMETHOD
    135  ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount,
    136               uint32_t* aResult) override {
    137    mPending = !mPending;
    138    if (mPending) {
    139      return NS_BASE_STREAM_WOULD_BLOCK;
    140    }
    141 
    142    // 1 char at the time, just to test the asyncWait+Read loop a bit more.
    143    aCount = 1;
    144 
    145    return mStream->ReadSegments(aWriter, aClosure, aCount, aResult);
    146  }
    147 
    148  NS_IMETHOD
    149  Close() override { return mStream->Close(); }
    150 
    151  NS_IMETHOD
    152  IsNonBlocking(bool* aNonBlocking) override {
    153    *aNonBlocking = false;
    154    return NS_OK;
    155  }
    156 
    157  NS_IMETHOD
    158  CloseWithStatus(nsresult aStatus) override { return Close(); }
    159 
    160  NS_IMETHOD
    161  AsyncWait(nsIInputStreamCallback* aCallback, uint32_t aFlags,
    162            uint32_t aRequestedCount, nsIEventTarget* aEventTarget) override {
    163    if (!aCallback) {
    164      return NS_OK;
    165    }
    166 
    167    RefPtr<BlockingAsyncStream> self = this;
    168    nsCOMPtr<nsIInputStreamCallback> callback = aCallback;
    169 
    170    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
    171        "gtest-asyncwait",
    172        [self, callback]() { callback->OnInputStreamReady(self); });
    173 
    174    if (aEventTarget) {
    175      aEventTarget->Dispatch(r.forget());
    176    } else {
    177      r->Run();
    178    }
    179 
    180    return NS_OK;
    181  }
    182 
    183 private:
    184  ~BlockingAsyncStream() = default;
    185 };
    186 
    187 NS_IMPL_ISUPPORTS(BlockingAsyncStream, nsIInputStream, nsIAsyncInputStream)
    188 
    189 // Testing an async blocking stream.
    190 TEST(TestInputStreamTransport, BlockingAsync)
    191 {
    192  RefPtr<BlockingAsyncStream> stream =
    193      new BlockingAsyncStream("Hello world"_ns);
    194 
    195  nsCOMPtr<nsIAsyncInputStream> ais;
    196  CreateStream(stream.forget(), getter_AddRefs(ais));
    197  ASSERT_TRUE(!!ais);
    198 
    199  nsAutoCString data;
    200  nsresult rv = NS_ReadInputStreamToString(ais, data, -1);
    201  ASSERT_EQ(NS_OK, rv);
    202 
    203  ASSERT_TRUE(data.EqualsLiteral("Hello world"));
    204 }