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