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

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 NetAddressPtr CopyAddress(const NetAddressPtr& addr) {
60 if (addr.is_null())
61 return NetAddressPtr();
62
63 NetAddressPtr copy(NetAddress::New());
64 copy->family = addr->family;
65 if (!addr->ipv4.is_null()) {
66 copy->ipv4 = NetAddressIPv4::New();
67 copy->ipv4->port = addr->ipv4->port;
68 copy->ipv4->addr = Array<uint8_t>::From(addr->ipv4->addr.storage());
69 } else if (!addr->ipv6.is_null()) {
70 copy->ipv6 = NetAddressIPv6::New();
71 copy->ipv6->port = addr->ipv6->port;
72 copy->ipv6->addr = Array<uint8_t>::From(addr->ipv6->addr.storage());
73 }
74 return copy.Pass();
75 }
76
77 class TestCallback {
78 public:
79 typedef Callback<void(NetworkErrorPtr)> CallbackType;
80
81 TestCallback() : state_(new State(this)),
82 callback_(static_cast<CallbackType::Runnable*>(state_)),
83 run_loop_(NULL) {
84 }
85 ~TestCallback() {
86 state_->test_callback_ = NULL;
87 }
88
89 CallbackType callback() const { return callback_; }
90 const NetworkErrorPtr& result() const { return result_; }
91
92 void WaitForResult() {
93 if (!result_.is_null())
94 return;
95
96 base::RunLoop run_loop;
97 run_loop_ = &run_loop;
98 run_loop.Run();
99 run_loop_ = NULL;
100 }
101
102 private:
103 struct State : public CallbackType::Runnable {
104 explicit State(TestCallback* test_callback)
105 : test_callback_(test_callback) {}
106 virtual ~State() {}
107
108 virtual void Run(NetworkErrorPtr result) const OVERRIDE {
109 if (test_callback_) {
110 test_callback_->result_ = result.Pass();
111 if (test_callback_->run_loop_)
112 test_callback_->run_loop_->Quit();
113 }
114 }
115
116 TestCallback* test_callback_;
117 };
118
119 // The lifespan is managed by |callback_| (and its copies).
120 State* state_;
121 CallbackType callback_;
122 base::RunLoop* run_loop_;
123 NetworkErrorPtr result_;
124
125 DISALLOW_COPY_AND_ASSIGN(TestCallback);
126 };
127
128 class TestCallbackWithAddress {
129 public:
130 typedef Callback<void(NetworkErrorPtr, NetAddressPtr)> CallbackType;
131
132 TestCallbackWithAddress()
133 : state_(new State(this)),
134 callback_(static_cast<CallbackType::Runnable*>(state_)),
135 run_loop_(NULL) {
136 }
137 ~TestCallbackWithAddress() {
138 state_->test_callback_ = NULL;
139 }
140
141 CallbackType callback() const { return callback_; }
142 const NetworkErrorPtr& result() const { return result_; }
143 const NetAddressPtr& net_address() const { return net_address_; }
144
145 void WaitForResult() {
146 if (!result_.is_null())
147 return;
148
149 base::RunLoop run_loop;
150 run_loop_ = &run_loop;
151 run_loop.Run();
152 run_loop_ = NULL;
153 }
154
155 private:
156 struct State : public CallbackType::Runnable {
157 State(TestCallbackWithAddress* test_callback)
158 : test_callback_(test_callback) {}
159 virtual ~State() {}
160
161 virtual void Run(NetworkErrorPtr result,
162 NetAddressPtr net_address) const OVERRIDE {
163 if (test_callback_) {
164 test_callback_->result_ = result.Pass();
165 test_callback_->net_address_ = net_address.Pass();
166 if (test_callback_->run_loop_)
167 test_callback_->run_loop_->Quit();
168 }
169 }
170
171 TestCallbackWithAddress* test_callback_;
172 };
173
174 // The lifespan is managed by |callback_| (and its copies).
175 State* state_;
176 CallbackType callback_;
177 base::RunLoop* run_loop_;
178 NetworkErrorPtr result_;
179 NetAddressPtr net_address_;
180
181 DISALLOW_COPY_AND_ASSIGN(TestCallbackWithAddress);
182 };
183
184 class UDPSocketTest : public testing::Test {
185 public:
186 UDPSocketTest() {}
187 virtual ~UDPSocketTest() {}
188
189 virtual void SetUp() OVERRIDE {
190 test_helper_.Init();
191
192 test_helper_.application_manager()->ConnectToService(
193 GURL("mojo:mojo_network_service"), &network_service_);
194
195 network_service_->CreateUDPSocket(Get(&udp_socket_));
196 udp_socket_.set_client(&udp_socket_client_);
197 }
198
199 protected:
200 struct ReceiveResult {
201 NetworkErrorPtr result;
202 NetAddressPtr addr;
203 Array<uint8_t> data;
204 };
205
206 class UDPSocketClientImpl : public UDPSocketClient {
207 public:
208
209 UDPSocketClientImpl() : run_loop_(NULL), expected_receive_count_(0) {}
210
211 virtual ~UDPSocketClientImpl() {
212 while (!results_.empty()) {
213 delete results_.front();
214 results_.pop();
215 }
216 }
217
218 virtual void OnReceived(NetworkErrorPtr result,
219 NetAddressPtr addr,
220 Array<uint8_t> data) OVERRIDE {
221 ReceiveResult* entry = new ReceiveResult();
222 entry->result = result.Pass();
223 entry->addr = addr.Pass();
224 entry->data = data.Pass();
225
226 results_.push(entry);
227
228 if (results_.size() == expected_receive_count_ && run_loop_) {
229 expected_receive_count_ = 0;
230 run_loop_->Quit();
231 }
232 }
233
234 base::RunLoop* run_loop_;
235 std::queue<ReceiveResult*> results_;
236 size_t expected_receive_count_;
237
238 DISALLOW_COPY_AND_ASSIGN(UDPSocketClientImpl);
239 };
240
241 std::queue<ReceiveResult*>* GetReceiveResults() {
242 return &udp_socket_client_.results_;
243 }
244
245 void WaitForReceiveResults(size_t count) {
246 if (GetReceiveResults()->size() == count)
247 return;
248
249 udp_socket_client_.expected_receive_count_ = count;
250 base::RunLoop run_loop;
251 udp_socket_client_.run_loop_ = &run_loop;
252 run_loop.Run();
253 udp_socket_client_.run_loop_ = NULL;
254 }
255
256 base::ShadowingAtExitManager at_exit_;
257 shell::ShellTestHelper test_helper_;
258
259 NetworkServicePtr network_service_;
260 UDPSocketPtr udp_socket_;
261 UDPSocketClientImpl udp_socket_client_;
262
263 DISALLOW_COPY_AND_ASSIGN(UDPSocketTest);
264 };
265
266 } // namespace
267
268 TEST_F(UDPSocketTest, Settings) {
269 TestCallback callback1;
270 udp_socket_->AllowAddressReuse(callback1.callback());
271 callback1.WaitForResult();
272 EXPECT_EQ(net::OK, callback1.result()->code);
273
274 // Should fail because the socket hasn't been bound.
275 TestCallback callback2;
276 udp_socket_->SetSendBufferSize(1024, callback2.callback());
277 callback2.WaitForResult();
278 EXPECT_NE(net::OK, callback2.result()->code);
279
280 // Should fail because the socket hasn't been bound.
281 TestCallback callback3;
282 udp_socket_->SetReceiveBufferSize(2048, callback3.callback());
283 callback3.WaitForResult();
284 EXPECT_NE(net::OK, callback3.result()->code);
285
286 TestCallbackWithAddress callback4;
287 udp_socket_->Bind(GetLocalHostWithAnyPort(), callback4.callback());
288 callback4.WaitForResult();
289 EXPECT_EQ(net::OK, callback4.result()->code);
290 EXPECT_NE(0u, callback4.net_address()->ipv4->port);
291
292 // Should fail because the socket has been bound.
293 TestCallback callback5;
294 udp_socket_->AllowAddressReuse(callback5.callback());
295 callback5.WaitForResult();
296 EXPECT_NE(net::OK, callback5.result()->code);
297
298 TestCallback callback6;
299 udp_socket_->SetSendBufferSize(1024, callback6.callback());
300 callback6.WaitForResult();
301 EXPECT_EQ(net::OK, callback6.result()->code);
302
303 TestCallback callback7;
304 udp_socket_->SetReceiveBufferSize(2048, callback7.callback());
305 callback7.WaitForResult();
306 EXPECT_EQ(net::OK, callback7.result()->code);
307 }
308
309 TEST_F(UDPSocketTest, TestReadWrite) {
310 TestCallbackWithAddress callback1;
311 udp_socket_->Bind(GetLocalHostWithAnyPort(), callback1.callback());
312 callback1.WaitForResult();
313 ASSERT_EQ(net::OK, callback1.result()->code);
314 ASSERT_NE(0u, callback1.net_address()->ipv4->port);
315
316 NetAddressPtr server_addr = CopyAddress(callback1.net_address());
317
318 UDPSocketPtr client_socket;
319 network_service_->CreateUDPSocket(Get(&client_socket));
320
321 TestCallbackWithAddress callback2;
322 client_socket->Bind(GetLocalHostWithAnyPort(), callback2.callback());
323 callback2.WaitForResult();
324 ASSERT_EQ(net::OK, callback2.result()->code);
325 ASSERT_NE(0u, callback2.net_address()->ipv4->port);
326
327 const size_t kPacketCount = 6;
328 const size_t kPacketSize = 255;
329 udp_socket_->ReceiveMorePackets(kPacketCount);
330
331 for (size_t i = 0; i < kPacketCount; ++i) {
332 if (i % 2) {
333 TestCallback callback;
334 client_socket->SendTo(CopyAddress(server_addr),
335 CreateTestMessage(static_cast<uint8_t>(i),
336 kPacketSize),
337 callback.callback());
338 callback.WaitForResult();
339 EXPECT_EQ(255, callback.result()->code);
340 } else {
341 client_socket->SendToAndForget(CopyAddress(server_addr),
342 CreateTestMessage(static_cast<uint8_t>(i),
343 kPacketSize));
344 }
345 }
346
347 WaitForReceiveResults(kPacketCount);
348 for (size_t i = 0; i < kPacketCount; ++i) {
349 scoped_ptr<ReceiveResult> result(GetReceiveResults()->front());
350 GetReceiveResults()->pop();
351
352 EXPECT_EQ(static_cast<int>(kPacketSize), result->result->code);
353 EXPECT_TRUE(AreEqualArrays(
354 CreateTestMessage(static_cast<uint8_t>(i), kPacketSize),
355 result->data));
356 }
357 }
358
359 } // namespace service
360 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698