tor-browser

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

TestBufferedInputStream.cpp (7508B)


      1 #include "gtest/gtest.h"
      2 
      3 #include "mozilla/SpinEventLoopUntil.h"
      4 #include "nsBufferedStreams.h"
      5 #include "nsIThread.h"
      6 #include "nsNetUtil.h"
      7 #include "nsStreamUtils.h"
      8 #include "nsThreadUtils.h"
      9 #include "Helpers.h"
     10 
     11 // Helper function for creating a testing::AsyncStringStream
     12 already_AddRefed<nsBufferedInputStream> CreateStream(uint32_t aSize,
     13                                                     nsCString& aBuffer) {
     14  aBuffer.SetLength(aSize);
     15  for (uint32_t i = 0; i < aSize; ++i) {
     16    aBuffer.BeginWriting()[i] = i % 10;
     17  }
     18 
     19  nsCOMPtr<nsIInputStream> stream = new testing::AsyncStringStream(aBuffer);
     20 
     21  RefPtr<nsBufferedInputStream> bis = new nsBufferedInputStream();
     22  bis->Init(stream, aSize);
     23  return bis.forget();
     24 }
     25 
     26 // Simple reading.
     27 TEST(TestBufferedInputStream, SimpleRead)
     28 {
     29  const size_t kBufSize = 10;
     30 
     31  nsCString buf;
     32  RefPtr<nsBufferedInputStream> bis = CreateStream(kBufSize, buf);
     33 
     34  uint64_t length;
     35  ASSERT_EQ(NS_OK, bis->Available(&length));
     36  ASSERT_EQ((uint64_t)kBufSize, length);
     37 
     38  char buf2[kBufSize];
     39  uint32_t count;
     40  ASSERT_EQ(NS_OK, bis->Read(buf2, sizeof(buf2), &count));
     41  ASSERT_EQ(count, buf.Length());
     42  ASSERT_TRUE(nsCString(buf.get(), kBufSize).Equals(nsCString(buf2, count)));
     43 }
     44 
     45 // Simple segment reading.
     46 TEST(TestBufferedInputStream, SimpleReadSegments)
     47 {
     48  const size_t kBufSize = 10;
     49 
     50  nsCString buf;
     51  RefPtr<nsBufferedInputStream> bis = CreateStream(kBufSize, buf);
     52 
     53  char buf2[kBufSize];
     54  uint32_t count;
     55  ASSERT_EQ(NS_OK, bis->ReadSegments(NS_CopySegmentToBuffer, buf2, sizeof(buf2),
     56                                     &count));
     57  ASSERT_EQ(count, buf.Length());
     58  ASSERT_TRUE(nsCString(buf.get(), kBufSize).Equals(nsCString(buf2, count)));
     59 }
     60 
     61 // AsyncWait - sync
     62 TEST(TestBufferedInputStream, AsyncWait_sync)
     63 {
     64  const size_t kBufSize = 10;
     65 
     66  nsCString buf;
     67  RefPtr<nsBufferedInputStream> bis = CreateStream(kBufSize, buf);
     68 
     69  RefPtr<testing::InputStreamCallback> cb = new testing::InputStreamCallback();
     70 
     71  ASSERT_EQ(NS_OK, bis->AsyncWait(cb, 0, 0, nullptr));
     72 
     73  // Immediatelly called
     74  ASSERT_TRUE(cb->Called());
     75 }
     76 
     77 // AsyncWait - async
     78 TEST(TestBufferedInputStream, AsyncWait_async)
     79 {
     80  const size_t kBufSize = 10;
     81 
     82  nsCString buf;
     83  RefPtr<nsBufferedInputStream> bis = CreateStream(kBufSize, buf);
     84 
     85  RefPtr<testing::InputStreamCallback> cb = new testing::InputStreamCallback();
     86  nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
     87 
     88  ASSERT_EQ(NS_OK, bis->AsyncWait(cb, 0, 0, thread));
     89 
     90  ASSERT_FALSE(cb->Called());
     91 
     92  // Eventually it is called.
     93  MOZ_ALWAYS_TRUE(mozilla::SpinEventLoopUntil(
     94      "TEST(TestBufferedInputStream, AsyncWait_async)"_ns,
     95      [&]() { return cb->Called(); }));
     96  ASSERT_TRUE(cb->Called());
     97 }
     98 
     99 // AsyncWait - sync - closureOnly
    100 TEST(TestBufferedInputStream, AsyncWait_sync_closureOnly)
    101 {
    102  const size_t kBufSize = 10;
    103 
    104  nsCString buf;
    105  RefPtr<nsBufferedInputStream> bis = CreateStream(kBufSize, buf);
    106 
    107  RefPtr<testing::InputStreamCallback> cb = new testing::InputStreamCallback();
    108 
    109  ASSERT_EQ(NS_OK, bis->AsyncWait(cb, nsIAsyncInputStream::WAIT_CLOSURE_ONLY, 0,
    110                                  nullptr));
    111  ASSERT_FALSE(cb->Called());
    112 
    113  bis->CloseWithStatus(NS_ERROR_FAILURE);
    114 
    115  // Immediatelly called
    116  ASSERT_TRUE(cb->Called());
    117 }
    118 
    119 // AsyncWait - async
    120 TEST(TestBufferedInputStream, AsyncWait_async_closureOnly)
    121 {
    122  const size_t kBufSize = 10;
    123 
    124  nsCString buf;
    125  RefPtr<nsBufferedInputStream> bis = CreateStream(kBufSize, buf);
    126 
    127  RefPtr<testing::InputStreamCallback> cb = new testing::InputStreamCallback();
    128  nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
    129 
    130  ASSERT_EQ(NS_OK, bis->AsyncWait(cb, nsIAsyncInputStream::WAIT_CLOSURE_ONLY, 0,
    131                                  thread));
    132 
    133  ASSERT_FALSE(cb->Called());
    134  bis->CloseWithStatus(NS_ERROR_FAILURE);
    135  ASSERT_FALSE(cb->Called());
    136 
    137  // Eventually it is called.
    138  MOZ_ALWAYS_TRUE(mozilla::SpinEventLoopUntil(
    139      "TEST(TestBufferedInputStream, AsyncWait_async_closureOnly)"_ns,
    140      [&]() { return cb->Called(); }));
    141  ASSERT_TRUE(cb->Called());
    142 }
    143 
    144 TEST(TestBufferedInputStream, AsyncWait_after_close)
    145 {
    146  const size_t kBufSize = 10;
    147 
    148  nsCString buf;
    149  RefPtr<nsBufferedInputStream> bis = CreateStream(kBufSize, buf);
    150 
    151  nsCOMPtr<nsIThread> eventTarget = do_GetCurrentThread();
    152 
    153  auto cb = mozilla::MakeRefPtr<testing::InputStreamCallback>();
    154  ASSERT_EQ(NS_OK, bis->AsyncWait(cb, 0, 0, eventTarget));
    155  MOZ_ALWAYS_TRUE(mozilla::SpinEventLoopUntil(
    156      "TEST(TestBufferedInputStream, AsyncWait_after_close) 1"_ns,
    157      [&]() { return cb->Called(); }));
    158  ASSERT_TRUE(cb->Called());
    159 
    160  ASSERT_EQ(NS_OK, bis->Close());
    161 
    162  cb = mozilla::MakeRefPtr<testing::InputStreamCallback>();
    163  ASSERT_EQ(NS_OK, bis->AsyncWait(cb, 0, 0, eventTarget));
    164  MOZ_ALWAYS_TRUE(mozilla::SpinEventLoopUntil(
    165      "TEST(TestBufferedInputStream, AsyncWait_after_close) 2"_ns,
    166      [&]() { return cb->Called(); }));
    167  ASSERT_TRUE(cb->Called());
    168 }
    169 
    170 TEST(TestBufferedInputStream, AsyncLengthWait_after_close)
    171 {
    172  nsCString buf{"The Quick Brown Fox Jumps over the Lazy Dog"};
    173  const size_t kBufSize = 44;
    174 
    175  RefPtr<nsBufferedInputStream> bis = CreateStream(kBufSize, buf);
    176 
    177  nsCOMPtr<nsIThread> eventTarget = do_GetCurrentThread();
    178 
    179  auto cb = mozilla::MakeRefPtr<testing::LengthCallback>();
    180  ASSERT_EQ(NS_OK, bis->AsyncLengthWait(cb, eventTarget));
    181  MOZ_ALWAYS_TRUE(mozilla::SpinEventLoopUntil(
    182      "TEST(TestBufferedInputStream, AsyncLengthWait_after_close) 1"_ns,
    183      [&]() { return cb->Called(); }));
    184  ASSERT_TRUE(cb->Called());
    185 
    186  uint64_t length;
    187  ASSERT_EQ(NS_OK, bis->Available(&length));
    188  ASSERT_EQ((uint64_t)kBufSize, length);
    189 
    190  cb = mozilla::MakeRefPtr<testing::LengthCallback>();
    191  ASSERT_EQ(NS_OK, bis->AsyncLengthWait(cb, eventTarget));
    192  MOZ_ALWAYS_TRUE(mozilla::SpinEventLoopUntil(
    193      "TEST(TestBufferedInputStream, AsyncLengthWait_after_close) 2"_ns,
    194      [&]() { return cb->Called(); }));
    195  ASSERT_TRUE(cb->Called());
    196 }
    197 
    198 // This stream returns a few bytes on the first read, and error on the second.
    199 class BrokenInputStream : public nsIInputStream {
    200  NS_DECL_THREADSAFE_ISUPPORTS
    201  NS_DECL_NSIINPUTSTREAM
    202 private:
    203  virtual ~BrokenInputStream() = default;
    204  bool mFirst = true;
    205 };
    206 
    207 NS_IMPL_ISUPPORTS(BrokenInputStream, nsIInputStream)
    208 
    209 NS_IMETHODIMP BrokenInputStream::Close(void) { return NS_OK; }
    210 
    211 NS_IMETHODIMP BrokenInputStream::Available(uint64_t* _retval) {
    212  *_retval = 100;
    213  return NS_OK;
    214 }
    215 
    216 NS_IMETHODIMP BrokenInputStream::StreamStatus(void) { return NS_OK; }
    217 
    218 NS_IMETHODIMP BrokenInputStream::Read(char* aBuf, uint32_t aCount,
    219                                      uint32_t* _retval) {
    220  if (mFirst) {
    221    aBuf[0] = 'h';
    222    aBuf[1] = 'e';
    223    aBuf[2] = 'l';
    224    aBuf[3] = 0;
    225    *_retval = 4;
    226    mFirst = false;
    227    return NS_OK;
    228  }
    229  return NS_ERROR_CORRUPTED_CONTENT;
    230 }
    231 
    232 NS_IMETHODIMP BrokenInputStream::ReadSegments(nsWriteSegmentFun aWriter,
    233                                              void* aClosure, uint32_t aCount,
    234                                              uint32_t* _retval) {
    235  return NS_ERROR_NOT_IMPLEMENTED;
    236 }
    237 
    238 NS_IMETHODIMP BrokenInputStream::IsNonBlocking(bool* _retval) {
    239  *_retval = false;
    240  return NS_OK;
    241 }
    242 
    243 // Check that the error from BrokenInputStream::Read is propagated
    244 // through NS_ReadInputStreamToString
    245 TEST(TestBufferedInputStream, BrokenInputStreamToBuffer)
    246 {
    247  nsAutoCString out;
    248  RefPtr<BrokenInputStream> stream = new BrokenInputStream();
    249 
    250  nsresult rv = NS_ReadInputStreamToString(stream, out, -1);
    251  ASSERT_EQ(rv, NS_ERROR_CORRUPTED_CONTENT);
    252 }