tor-browser

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

sockettransportservice_unittest.cpp (4614B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 // Original author: ekr@rtfm.com
      8 #include <iostream>
      9 
     10 #include "nsASocketHandler.h"
     11 #include "nsCOMPtr.h"
     12 #include "nsISocketTransportService.h"
     13 #include "nsNetCID.h"
     14 #include "nsServiceManagerUtils.h"
     15 #include "nsThreadUtils.h"
     16 #include "prio.h"
     17 
     18 #define GTEST_HAS_RTTI 0
     19 #include "gtest/gtest.h"
     20 #include "gtest_utils.h"
     21 
     22 using namespace mozilla;
     23 
     24 namespace {
     25 class SocketTransportServiceTest : public MtransportTest {
     26 public:
     27  SocketTransportServiceTest()
     28      : received_(0),
     29        readpipe_(nullptr),
     30        writepipe_(nullptr),
     31        registered_(false) {}
     32 
     33  ~SocketTransportServiceTest() {
     34    if (readpipe_) PR_Close(readpipe_);
     35    if (writepipe_) PR_Close(writepipe_);
     36  }
     37 
     38  void SetUp();
     39  void RegisterHandler();
     40  void SendEvent();
     41  void SendPacket();
     42 
     43  void ReceivePacket() { ++received_; }
     44 
     45  void ReceiveEvent() { ++received_; }
     46 
     47  size_t Received() { return received_; }
     48 
     49 private:
     50  nsCOMPtr<nsISocketTransportService> stservice_;
     51  nsCOMPtr<nsIEventTarget> target_;
     52  std::atomic<size_t> received_;
     53  PRFileDesc* readpipe_;
     54  PRFileDesc* writepipe_;
     55  std::atomic<bool> registered_;
     56 };
     57 
     58 // Received an event.
     59 class EventReceived : public Runnable {
     60 public:
     61  explicit EventReceived(SocketTransportServiceTest* test)
     62      : Runnable("EventReceived"), test_(test) {}
     63 
     64  NS_IMETHOD Run() override {
     65    test_->ReceiveEvent();
     66    return NS_OK;
     67  }
     68 
     69  SocketTransportServiceTest* test_;
     70 };
     71 
     72 // Register our listener on the socket
     73 class RegisterEvent : public Runnable {
     74 public:
     75  explicit RegisterEvent(SocketTransportServiceTest* test)
     76      : Runnable("RegisterEvent"), test_(test) {}
     77 
     78  NS_IMETHOD Run() override {
     79    test_->RegisterHandler();
     80    return NS_OK;
     81  }
     82 
     83  SocketTransportServiceTest* test_;
     84 };
     85 
     86 class SocketHandler : public nsASocketHandler {
     87 public:
     88  explicit SocketHandler(SocketTransportServiceTest* test) : test_(test) {}
     89 
     90  void OnSocketReady(PRFileDesc* fd, int16_t outflags) override {
     91    unsigned char buf[1600];
     92 
     93    int32_t rv;
     94    rv = PR_Recv(fd, buf, sizeof(buf), 0, PR_INTERVAL_NO_WAIT);
     95    if (rv > 0) {
     96      std::cerr << "Read " << rv << " bytes\n";
     97      test_->ReceivePacket();
     98    }
     99  }
    100 
    101  void OnSocketDetached(PRFileDesc* fd) override {}
    102 
    103  void IsLocal(bool* aIsLocal) override {
    104    // TODO(jesup): better check? Does it matter? (likely no)
    105    *aIsLocal = false;
    106  }
    107 
    108  virtual uint64_t ByteCountSent() override { return 0; }
    109  virtual uint64_t ByteCountReceived() override { return 0; }
    110 
    111  NS_DECL_ISUPPORTS
    112 
    113 protected:
    114  virtual ~SocketHandler() = default;
    115 
    116 private:
    117  SocketTransportServiceTest* test_;
    118 };
    119 
    120 NS_IMPL_ISUPPORTS0(SocketHandler)
    121 
    122 void SocketTransportServiceTest::SetUp() {
    123  MtransportTest::SetUp();
    124 
    125  // Get the transport service as a dispatch target
    126  nsresult rv;
    127  target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
    128  ASSERT_TRUE(NS_SUCCEEDED(rv));
    129 
    130  // Get the transport service as a transport service
    131  stservice_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
    132  ASSERT_TRUE(NS_SUCCEEDED(rv));
    133 
    134  // Create a loopback pipe
    135  PRStatus status = PR_CreatePipe(&readpipe_, &writepipe_);
    136  ASSERT_EQ(status, PR_SUCCESS);
    137 
    138  // Register ourselves as a listener for the read side of the
    139  // socket. The registration has to happen on the STS thread,
    140  // hence this event stuff.
    141  rv = target_->Dispatch(new RegisterEvent(this), NS_DISPATCH_NORMAL);
    142  ASSERT_TRUE(NS_SUCCEEDED(rv));
    143  ASSERT_TRUE_WAIT(registered_, 10000);
    144 }
    145 
    146 void SocketTransportServiceTest::RegisterHandler() {
    147  nsresult rv;
    148 
    149  rv = stservice_->AttachSocket(readpipe_, new SocketHandler(this));
    150  ASSERT_TRUE(NS_SUCCEEDED(rv));
    151 
    152  registered_ = true;
    153 }
    154 
    155 void SocketTransportServiceTest::SendEvent() {
    156  nsresult rv;
    157 
    158  rv = target_->Dispatch(new EventReceived(this), NS_DISPATCH_NORMAL);
    159  ASSERT_TRUE(NS_SUCCEEDED(rv));
    160  ASSERT_TRUE_WAIT(Received() == 1, 10000);
    161 }
    162 
    163 void SocketTransportServiceTest::SendPacket() {
    164  unsigned char buffer[1024];
    165  memset(buffer, 0, sizeof(buffer));
    166 
    167  int32_t status = PR_Write(writepipe_, buffer, sizeof(buffer));
    168  uint32_t size = status & 0xffff;
    169  ASSERT_EQ(sizeof(buffer), size);
    170 }
    171 
    172 // The unit tests themselves
    173 TEST_F(SocketTransportServiceTest, SendEvent) { SendEvent(); }
    174 
    175 TEST_F(SocketTransportServiceTest, SendPacket) { SendPacket(); }
    176 
    177 }  // end namespace