Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Side by Side Diff: mojo/services/network/udp_socket_unittest.cc

Issue 596383002: Mojo UDP API implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@udp_interface
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/at_exit.h"
6 #include "base/macros.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "mojo/public/cpp/bindings/callback.h"
9 #include "mojo/services/public/interfaces/network/network_service.mojom.h"
10 #include "mojo/services/public/interfaces/network/udp_socket.mojom.h"
11 #include "mojo/shell/shell_test_helper.h"
12 #include "net/base/net_errors.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "url/gurl.h"
15
16 namespace mojo {
17 namespace service {
18 namespace {
19
20 NetAddressPtr GetLocalHostWithAnyPort() {
21 NetAddressPtr addr(NetAddress::New());
22 addr->family = NET_ADDRESS_FAMILY_IPV4;
23 addr->ipv4 = NetAddressIPv4::New();
24 addr->ipv4->port = 0;
25 addr->ipv4->addr.resize(4);
26 addr->ipv4->addr[0] = 127;
27 addr->ipv4->addr[1] = 0;
28 addr->ipv4->addr[2] = 0;
29 addr->ipv4->addr[3] = 1;
30
31 return addr.Pass();
32 }
33
34 Array<uint8_t> CreateTestMessage(uint8_t initial, size_t size) {
35 Array<uint8_t> array(size);
36 for (size_t i = 0; i < size; ++i)
37 array[i] = static_cast<uint8_t>((i + initial) % 256);
38 return array.Pass();
39 }
40
41 bool AreEqualArrays(const Array<uint8_t>& array_1,
42 const Array<uint8_t>& array_2) {
43 if (array_1.is_null() != array_2.is_null())
44 return false;
45 else if (array_1.is_null())
46 return true;
47
48 if (array_1.size() != array_2.size())
49 return false;
50
51 for (size_t i = 0; i < array_1.size(); ++i) {
52 if (array_1[i] != array_2[i])
53 return false;
54 }
55
56 return true;
57 }
58
59 template <typename CallbackType>
60 class TestCallbackBase {
61 public:
62 TestCallbackBase() : state_(nullptr), run_loop_(nullptr), ran_(false) {}
63
64 ~TestCallbackBase() {
65 state_->set_test_callback(nullptr);
66 }
67
68 CallbackType callback() const { return callback_; }
69
70 void WaitForResult() {
71 if (ran_)
72 return;
73
74 base::RunLoop run_loop;
75 run_loop_ = &run_loop;
76 run_loop.Run();
77 run_loop_ = nullptr;
78 }
79
80 protected:
81 struct StateBase : public CallbackType::Runnable {
82 StateBase() : test_callback_(nullptr) {}
83 virtual ~StateBase() {}
84
85 void set_test_callback(TestCallbackBase* test_callback) {
86 test_callback_ = test_callback;
87 }
88
89 protected:
90 void NotifyRun() const {
91 if (test_callback_) {
92 test_callback_->ran_ = true;
93 if (test_callback_->run_loop_)
94 test_callback_->run_loop_->Quit();
95 }
96 }
97
98 TestCallbackBase* test_callback_;
99
100 private:
101 DISALLOW_COPY_AND_ASSIGN(StateBase);
102 };
103
104 // Takes ownership of |state|, and guarantees that it lives at least as long
105 // as this object.
106 void Initialize(StateBase* state) {
107 state_ = state;
108 state_->set_test_callback(this);
109 callback_ = CallbackType(
110 static_cast<typename CallbackType::Runnable*>(state_));
111 }
112
113 private:
114 // The lifespan is managed by |callback_| (and its copies).
115 StateBase* state_;
116 CallbackType callback_;
117 base::RunLoop* run_loop_;
118 bool ran_;
119
120 DISALLOW_COPY_AND_ASSIGN(TestCallbackBase);
121 };
122
123 class TestCallback : public TestCallbackBase<Callback<void(NetworkErrorPtr)>> {
124 public:
125 TestCallback() {
126 Initialize(new State());
127 }
128 ~TestCallback() {}
129
130 const NetworkErrorPtr& result() const { return result_; }
131
132 private:
133 struct State: public StateBase {
134 virtual ~State() {}
135
136 virtual void Run(NetworkErrorPtr result) const override {
137 if (test_callback_) {
138 TestCallback* callback = static_cast<TestCallback*>(test_callback_);
139 callback->result_ = result.Pass();
140 }
141 NotifyRun();
142 }
143 };
144
145 NetworkErrorPtr result_;
146 };
147
148 class TestCallbackWithAddress
149 : public TestCallbackBase<Callback<void(NetworkErrorPtr, NetAddressPtr)>> {
150 public:
151 TestCallbackWithAddress() {
152 Initialize(new State());
153 }
154 ~TestCallbackWithAddress() {}
155
156 const NetworkErrorPtr& result() const { return result_; }
157 const NetAddressPtr& net_address() const { return net_address_; }
158
159 private:
160 struct State : public StateBase {
161 virtual ~State() {}
162
163 virtual void Run(NetworkErrorPtr result,
164 NetAddressPtr net_address) const override {
165 if (test_callback_) {
166 TestCallbackWithAddress* callback =
167 static_cast<TestCallbackWithAddress*>(test_callback_);
168 callback->result_ = result.Pass();
169 callback->net_address_ = net_address.Pass();
170 }
171 NotifyRun();
172 }
173 };
174
175 NetworkErrorPtr result_;
176 NetAddressPtr net_address_;
177 };
178
179 class TestCallbackWithUint32
180 : public TestCallbackBase<Callback<void(uint32_t)>> {
181 public:
182 TestCallbackWithUint32() : result_(0) {
183 Initialize(new State());
184 }
185 ~TestCallbackWithUint32() {}
186
187 uint32_t result() const { return result_; }
188
189 private:
190 struct State : public StateBase {
191 virtual ~State() {}
192
193 virtual void Run(uint32_t result) const override {
194 if (test_callback_) {
195 TestCallbackWithUint32* callback =
196 static_cast<TestCallbackWithUint32*>(test_callback_);
197 callback->result_ = result;
198 }
199 NotifyRun();
200 }
201 };
202
203 uint32_t result_;
204 };
205
206 class UDPSocketTest : public testing::Test {
207 public:
208 UDPSocketTest() {}
209 virtual ~UDPSocketTest() {}
210
211 virtual void SetUp() OVERRIDE {
212 test_helper_.Init();
213
214 test_helper_.application_manager()->ConnectToService(
215 GURL("mojo:mojo_network_service"), &network_service_);
216
217 network_service_->CreateUDPSocket(GetProxy(&udp_socket_));
218 udp_socket_.set_client(&udp_socket_client_);
219 }
220
221 protected:
222 struct ReceiveResult {
223 NetworkErrorPtr result;
224 NetAddressPtr addr;
225 Array<uint8_t> data;
226 };
227
228 class UDPSocketClientImpl : public UDPSocketClient {
229 public:
230
231 UDPSocketClientImpl() : run_loop_(nullptr), expected_receive_count_(0) {}
232
233 virtual ~UDPSocketClientImpl() {
234 while (!results_.empty()) {
235 delete results_.front();
236 results_.pop();
237 }
238 }
239
240 virtual void OnReceived(NetworkErrorPtr result,
241 NetAddressPtr src_addr,
242 Array<uint8_t> data) OVERRIDE {
243 ReceiveResult* entry = new ReceiveResult();
244 entry->result = result.Pass();
245 entry->addr = src_addr.Pass();
246 entry->data = data.Pass();
247
248 results_.push(entry);
249
250 if (results_.size() == expected_receive_count_ && run_loop_) {
251 expected_receive_count_ = 0;
252 run_loop_->Quit();
253 }
254 }
255
256 base::RunLoop* run_loop_;
257 std::queue<ReceiveResult*> results_;
258 size_t expected_receive_count_;
259
260 DISALLOW_COPY_AND_ASSIGN(UDPSocketClientImpl);
261 };
262
263 std::queue<ReceiveResult*>* GetReceiveResults() {
264 return &udp_socket_client_.results_;
265 }
266
267 void WaitForReceiveResults(size_t count) {
268 if (GetReceiveResults()->size() == count)
269 return;
270
271 udp_socket_client_.expected_receive_count_ = count;
272 base::RunLoop run_loop;
273 udp_socket_client_.run_loop_ = &run_loop;
274 run_loop.Run();
275 udp_socket_client_.run_loop_ = nullptr;
276 }
277
278 base::ShadowingAtExitManager at_exit_;
279 shell::ShellTestHelper test_helper_;
280
281 NetworkServicePtr network_service_;
282 UDPSocketPtr udp_socket_;
283 UDPSocketClientImpl udp_socket_client_;
284
285 DISALLOW_COPY_AND_ASSIGN(UDPSocketTest);
286 };
287
288 } // namespace
289
290 TEST_F(UDPSocketTest, Settings) {
291 TestCallback callback1;
292 udp_socket_->AllowAddressReuse(callback1.callback());
293 callback1.WaitForResult();
294 EXPECT_EQ(net::OK, callback1.result()->code);
295
296 // Should fail because the socket hasn't been bound.
297 TestCallback callback2;
298 udp_socket_->SetSendBufferSize(1024, callback2.callback());
299 callback2.WaitForResult();
300 EXPECT_NE(net::OK, callback2.result()->code);
301
302 // Should fail because the socket hasn't been bound.
303 TestCallback callback3;
304 udp_socket_->SetReceiveBufferSize(2048, callback3.callback());
305 callback3.WaitForResult();
306 EXPECT_NE(net::OK, callback3.result()->code);
307
308 TestCallbackWithAddress callback4;
309 udp_socket_->Bind(GetLocalHostWithAnyPort(), callback4.callback());
310 callback4.WaitForResult();
311 EXPECT_EQ(net::OK, callback4.result()->code);
312 EXPECT_NE(0u, callback4.net_address()->ipv4->port);
313
314 // Should fail because the socket has been bound.
315 TestCallback callback5;
316 udp_socket_->AllowAddressReuse(callback5.callback());
317 callback5.WaitForResult();
318 EXPECT_NE(net::OK, callback5.result()->code);
319
320 TestCallback callback6;
321 udp_socket_->SetSendBufferSize(1024, callback6.callback());
322 callback6.WaitForResult();
323 EXPECT_EQ(net::OK, callback6.result()->code);
324
325 TestCallback callback7;
326 udp_socket_->SetReceiveBufferSize(2048, callback7.callback());
327 callback7.WaitForResult();
328 EXPECT_EQ(net::OK, callback7.result()->code);
329
330 TestCallbackWithUint32 callback8;
331 udp_socket_->NegotiateMaxPendingSendRequests(0, callback8.callback());
332 callback8.WaitForResult();
333 EXPECT_GT(callback8.result(), 0u);
334
335 TestCallbackWithUint32 callback9;
336 udp_socket_->NegotiateMaxPendingSendRequests(16, callback9.callback());
337 callback9.WaitForResult();
338 EXPECT_GT(callback9.result(), 0u);
339 }
340
341 TEST_F(UDPSocketTest, TestReadWrite) {
342 TestCallbackWithAddress callback1;
343 udp_socket_->Bind(GetLocalHostWithAnyPort(), callback1.callback());
344 callback1.WaitForResult();
345 ASSERT_EQ(net::OK, callback1.result()->code);
346 ASSERT_NE(0u, callback1.net_address()->ipv4->port);
347
348 NetAddressPtr server_addr = callback1.net_address().Clone();
349
350 UDPSocketPtr client_socket;
351 network_service_->CreateUDPSocket(GetProxy(&client_socket));
352
353 TestCallbackWithAddress callback2;
354 client_socket->Bind(GetLocalHostWithAnyPort(), callback2.callback());
355 callback2.WaitForResult();
356 ASSERT_EQ(net::OK, callback2.result()->code);
357 ASSERT_NE(0u, callback2.net_address()->ipv4->port);
358
359 const size_t kDatagramCount = 6;
360 const size_t kDatagramSize = 255;
361 udp_socket_->ReceiveMore(kDatagramCount);
362
363 for (size_t i = 0; i < kDatagramCount; ++i) {
364 TestCallback callback;
365 client_socket->SendTo(
366 server_addr.Clone(),
367 CreateTestMessage(static_cast<uint8_t>(i), kDatagramSize),
368 callback.callback());
369 callback.WaitForResult();
370 EXPECT_EQ(255, callback.result()->code);
371 }
372
373 WaitForReceiveResults(kDatagramCount);
374 for (size_t i = 0; i < kDatagramCount; ++i) {
375 scoped_ptr<ReceiveResult> result(GetReceiveResults()->front());
376 GetReceiveResults()->pop();
377
378 EXPECT_EQ(static_cast<int>(kDatagramSize), result->result->code);
379 EXPECT_TRUE(AreEqualArrays(
380 CreateTestMessage(static_cast<uint8_t>(i), kDatagramSize),
381 result->data));
382 }
383 }
384
385 } // namespace service
386 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/services/network/udp_socket_impl.cc ('k') | mojo/services/public/interfaces/network/network_service.mojom » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698