|
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 "prio.h" |
|
11 |
|
12 #include "nsCOMPtr.h" |
|
13 #include "nsNetCID.h" |
|
14 #include "nsXPCOM.h" |
|
15 #include "nsXPCOMGlue.h" |
|
16 |
|
17 #include "nsIComponentManager.h" |
|
18 #include "nsIComponentRegistrar.h" |
|
19 #include "nsIIOService.h" |
|
20 #include "nsIServiceManager.h" |
|
21 #include "nsISocketTransportService.h" |
|
22 |
|
23 #include "nsASocketHandler.h" |
|
24 #include "nsServiceManagerUtils.h" |
|
25 #include "nsThreadUtils.h" |
|
26 |
|
27 #include "mtransport_test_utils.h" |
|
28 |
|
29 #define GTEST_HAS_RTTI 0 |
|
30 #include "gtest/gtest.h" |
|
31 #include "gtest_utils.h" |
|
32 |
|
33 MtransportTestUtils *test_utils; |
|
34 |
|
35 namespace { |
|
36 class SocketTransportServiceTest : public ::testing::Test { |
|
37 public: |
|
38 SocketTransportServiceTest() : received_(0), |
|
39 readpipe_(nullptr), |
|
40 writepipe_(nullptr), |
|
41 registered_(false) { |
|
42 } |
|
43 |
|
44 ~SocketTransportServiceTest() { |
|
45 if (readpipe_) |
|
46 PR_Close(readpipe_); |
|
47 if (writepipe_) |
|
48 PR_Close(writepipe_); |
|
49 } |
|
50 |
|
51 void SetUp(); |
|
52 void RegisterHandler(); |
|
53 void SendEvent(); |
|
54 void SendPacket(); |
|
55 |
|
56 void ReceivePacket() { |
|
57 ++received_; |
|
58 } |
|
59 |
|
60 void ReceiveEvent() { |
|
61 ++received_; |
|
62 } |
|
63 |
|
64 size_t Received() { |
|
65 return received_; |
|
66 } |
|
67 |
|
68 private: |
|
69 nsCOMPtr<nsISocketTransportService> stservice_; |
|
70 nsCOMPtr<nsIEventTarget> target_; |
|
71 size_t received_; |
|
72 PRFileDesc *readpipe_; |
|
73 PRFileDesc *writepipe_; |
|
74 bool registered_; |
|
75 }; |
|
76 |
|
77 |
|
78 // Received an event. |
|
79 class EventReceived : public nsRunnable { |
|
80 public: |
|
81 EventReceived(SocketTransportServiceTest *test) : |
|
82 test_(test) {} |
|
83 |
|
84 NS_IMETHOD Run() { |
|
85 test_->ReceiveEvent(); |
|
86 return NS_OK; |
|
87 } |
|
88 |
|
89 SocketTransportServiceTest *test_; |
|
90 }; |
|
91 |
|
92 |
|
93 // Register our listener on the socket |
|
94 class RegisterEvent : public nsRunnable { |
|
95 public: |
|
96 RegisterEvent(SocketTransportServiceTest *test) : |
|
97 test_(test) {} |
|
98 |
|
99 NS_IMETHOD Run() { |
|
100 test_->RegisterHandler(); |
|
101 return NS_OK; |
|
102 } |
|
103 |
|
104 SocketTransportServiceTest *test_; |
|
105 }; |
|
106 |
|
107 |
|
108 class SocketHandler : public nsASocketHandler { |
|
109 public: |
|
110 SocketHandler(SocketTransportServiceTest *test) : test_(test) { |
|
111 } |
|
112 virtual ~SocketHandler() {} |
|
113 |
|
114 void OnSocketReady(PRFileDesc *fd, int16_t outflags) { |
|
115 unsigned char buf[1600]; |
|
116 |
|
117 int32_t rv; |
|
118 rv = PR_Recv(fd, buf, sizeof(buf), 0, PR_INTERVAL_NO_WAIT); |
|
119 if (rv > 0) { |
|
120 std::cerr << "Read " << rv << " bytes" << std::endl; |
|
121 test_->ReceivePacket(); |
|
122 } |
|
123 } |
|
124 |
|
125 void OnSocketDetached(PRFileDesc *fd) {} |
|
126 |
|
127 void IsLocal(bool *aIsLocal) { |
|
128 // TODO(jesup): better check? Does it matter? (likely no) |
|
129 *aIsLocal = false; |
|
130 } |
|
131 |
|
132 virtual uint64_t ByteCountSent() { return 0; } |
|
133 virtual uint64_t ByteCountReceived() { return 0; } |
|
134 |
|
135 NS_DECL_ISUPPORTS |
|
136 |
|
137 private: |
|
138 SocketTransportServiceTest *test_; |
|
139 }; |
|
140 |
|
141 NS_IMPL_ISUPPORTS0(SocketHandler) |
|
142 |
|
143 void SocketTransportServiceTest::SetUp() { |
|
144 // Get the transport service as a dispatch target |
|
145 nsresult rv; |
|
146 target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); |
|
147 ASSERT_TRUE(NS_SUCCEEDED(rv)); |
|
148 |
|
149 // Get the transport service as a transport service |
|
150 stservice_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); |
|
151 ASSERT_TRUE(NS_SUCCEEDED(rv)); |
|
152 |
|
153 // Create a loopback pipe |
|
154 PRStatus status = PR_CreatePipe(&readpipe_, &writepipe_); |
|
155 ASSERT_EQ(status, PR_SUCCESS); |
|
156 |
|
157 // Register ourselves as a listener for the read side of the |
|
158 // socket. The registration has to happen on the STS thread, |
|
159 // hence this event stuff. |
|
160 rv = target_->Dispatch(new RegisterEvent(this), 0); |
|
161 ASSERT_TRUE(NS_SUCCEEDED(rv)); |
|
162 ASSERT_TRUE_WAIT(registered_, 10000); |
|
163 |
|
164 } |
|
165 |
|
166 void SocketTransportServiceTest::RegisterHandler() { |
|
167 nsresult rv; |
|
168 |
|
169 rv = stservice_->AttachSocket(readpipe_, new SocketHandler(this)); |
|
170 ASSERT_TRUE(NS_SUCCEEDED(rv)); |
|
171 |
|
172 registered_ = true; |
|
173 } |
|
174 |
|
175 void SocketTransportServiceTest::SendEvent() { |
|
176 nsresult rv; |
|
177 |
|
178 rv = target_->Dispatch(new EventReceived(this), 0); |
|
179 ASSERT_TRUE(NS_SUCCEEDED(rv)); |
|
180 ASSERT_TRUE_WAIT(Received() == 1, 10000); |
|
181 } |
|
182 |
|
183 void SocketTransportServiceTest::SendPacket() { |
|
184 unsigned char buffer[1024]; |
|
185 memset(buffer, 0, sizeof(buffer)); |
|
186 |
|
187 int32_t status = PR_Write(writepipe_, buffer, sizeof(buffer)); |
|
188 uint32_t size = status & 0xffff; |
|
189 ASSERT_EQ(sizeof(buffer), size); |
|
190 } |
|
191 |
|
192 |
|
193 |
|
194 // The unit tests themselves |
|
195 TEST_F(SocketTransportServiceTest, SendEvent) { |
|
196 SendEvent(); |
|
197 } |
|
198 |
|
199 TEST_F(SocketTransportServiceTest, SendPacket) { |
|
200 SendPacket(); |
|
201 } |
|
202 |
|
203 |
|
204 } // end namespace |
|
205 |
|
206 |
|
207 int main(int argc, char **argv) { |
|
208 test_utils = new MtransportTestUtils(); |
|
209 |
|
210 // Start the tests |
|
211 ::testing::InitGoogleTest(&argc, argv); |
|
212 |
|
213 int rv = RUN_ALL_TESTS(); |
|
214 delete test_utils; |
|
215 return rv; |
|
216 } |