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.
5 #include "base/macros.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/run_loop.h"
8 #include "mojo/application/application_test_base_chromium.h"
9 #include "mojo/public/cpp/application/application_connection.h"
10 #include "mojo/public/cpp/application/application_impl.h"
11 #include "mojo/public/cpp/bindings/callback.h"
12 #include "mojo/services/network/public/cpp/udp_socket_wrapper.h"
13 #include "mojo/services/network/public/interfaces/network_service.mojom.h"
14 #include "mojo/services/network/public/interfaces/udp_socket.mojom.h"
15 #include "net/base/net_errors.h"
16 #include "testing/gtest/include/gtest/gtest.h"
22 NetAddressPtr
GetLocalHostWithAnyPort() {
23 NetAddressPtr
addr(NetAddress::New());
24 addr
->family
= NET_ADDRESS_FAMILY_IPV4
;
25 addr
->ipv4
= NetAddressIPv4::New();
27 addr
->ipv4
->addr
.resize(4);
28 addr
->ipv4
->addr
[0] = 127;
29 addr
->ipv4
->addr
[1] = 0;
30 addr
->ipv4
->addr
[2] = 0;
31 addr
->ipv4
->addr
[3] = 1;
36 Array
<uint8_t> CreateTestMessage(uint8_t initial
, size_t size
) {
37 Array
<uint8_t> array(size
);
38 for (size_t i
= 0; i
< size
; ++i
)
39 array
[i
] = static_cast<uint8_t>((i
+ initial
) % 256);
43 template <typename CallbackType
>
44 class TestCallbackBase
{
46 TestCallbackBase() : state_(nullptr), run_loop_(nullptr), ran_(false) {}
49 state_
->set_test_callback(nullptr);
52 CallbackType
callback() const { return callback_
; }
54 void WaitForResult() {
58 base::RunLoop run_loop
;
59 run_loop_
= &run_loop
;
65 struct StateBase
: public CallbackType::Runnable
{
66 StateBase() : test_callback_(nullptr) {}
67 ~StateBase() override
{}
69 void set_test_callback(TestCallbackBase
* test_callback
) {
70 test_callback_
= test_callback
;
74 void NotifyRun() const {
76 test_callback_
->ran_
= true;
77 if (test_callback_
->run_loop_
)
78 test_callback_
->run_loop_
->Quit();
82 TestCallbackBase
* test_callback_
;
85 DISALLOW_COPY_AND_ASSIGN(StateBase
);
88 // Takes ownership of |state|, and guarantees that it lives at least as long
90 void Initialize(StateBase
* state
) {
92 state_
->set_test_callback(this);
93 callback_
= CallbackType(
94 static_cast<typename
CallbackType::Runnable
*>(state_
));
98 // The lifespan is managed by |callback_| (and its copies).
100 CallbackType callback_
;
101 base::RunLoop
* run_loop_
;
104 DISALLOW_COPY_AND_ASSIGN(TestCallbackBase
);
107 class TestCallback
: public TestCallbackBase
<Callback
<void(NetworkErrorPtr
)>> {
110 Initialize(new State());
114 const NetworkErrorPtr
& result() const { return result_
; }
117 struct State
: public StateBase
{
120 void Run(NetworkErrorPtr result
) const override
{
121 if (test_callback_
) {
122 TestCallback
* callback
= static_cast<TestCallback
*>(test_callback_
);
123 callback
->result_
= result
.Pass();
129 NetworkErrorPtr result_
;
132 class TestCallbackWithAddressAndReceiver
133 : public TestCallbackBase
<
134 Callback
<void(NetworkErrorPtr
,
136 InterfaceRequest
<UDPSocketReceiver
>)>> {
138 TestCallbackWithAddressAndReceiver() { Initialize(new State()); }
139 ~TestCallbackWithAddressAndReceiver() {}
141 const NetworkErrorPtr
& result() const { return result_
; }
142 const NetAddressPtr
& net_address() const { return net_address_
; }
143 InterfaceRequest
<UDPSocketReceiver
>& receiver() { return receiver_
; }
146 struct State
: public StateBase
{
149 void Run(NetworkErrorPtr result
,
150 NetAddressPtr net_address
,
151 InterfaceRequest
<UDPSocketReceiver
> receiver
) const override
{
152 if (test_callback_
) {
153 TestCallbackWithAddressAndReceiver
* callback
=
154 static_cast<TestCallbackWithAddressAndReceiver
*>(test_callback_
);
155 callback
->result_
= result
.Pass();
156 callback
->net_address_
= net_address
.Pass();
157 callback
->receiver_
= receiver
.Pass();
163 NetworkErrorPtr result_
;
164 NetAddressPtr net_address_
;
165 InterfaceRequest
<UDPSocketReceiver
> receiver_
;
168 class TestCallbackWithAddress
169 : public TestCallbackBase
<Callback
<void(NetworkErrorPtr
, NetAddressPtr
)>> {
171 TestCallbackWithAddress() {
172 Initialize(new State());
174 ~TestCallbackWithAddress() {}
176 const NetworkErrorPtr
& result() const { return result_
; }
177 const NetAddressPtr
& net_address() const { return net_address_
; }
180 struct State
: public StateBase
{
183 void Run(NetworkErrorPtr result
, NetAddressPtr net_address
) const override
{
184 if (test_callback_
) {
185 TestCallbackWithAddress
* callback
=
186 static_cast<TestCallbackWithAddress
*>(test_callback_
);
187 callback
->result_
= result
.Pass();
188 callback
->net_address_
= net_address
.Pass();
194 NetworkErrorPtr result_
;
195 NetAddressPtr net_address_
;
198 class TestCallbackWithUint32
199 : public TestCallbackBase
<Callback
<void(uint32_t)>> {
201 TestCallbackWithUint32() : result_(0) {
202 Initialize(new State());
204 ~TestCallbackWithUint32() {}
206 uint32_t result() const { return result_
; }
209 struct State
: public StateBase
{
212 void Run(uint32_t result
) const override
{
213 if (test_callback_
) {
214 TestCallbackWithUint32
* callback
=
215 static_cast<TestCallbackWithUint32
*>(test_callback_
);
216 callback
->result_
= result
;
225 class TestReceiveCallback
226 : public TestCallbackBase
<
227 Callback
<void(NetworkErrorPtr
, NetAddressPtr
, Array
<uint8_t>)>> {
229 TestReceiveCallback() {
230 Initialize(new State());
232 ~TestReceiveCallback() {}
234 const NetworkErrorPtr
& result() const { return result_
; }
235 const NetAddressPtr
& src_addr() const { return src_addr_
; }
236 const Array
<uint8_t>& data() const { return data_
; }
239 struct State
: public StateBase
{
242 void Run(NetworkErrorPtr result
,
243 NetAddressPtr src_addr
,
244 Array
<uint8_t> data
) const override
{
245 if (test_callback_
) {
246 TestReceiveCallback
* callback
=
247 static_cast<TestReceiveCallback
*>(test_callback_
);
248 callback
->result_
= result
.Pass();
249 callback
->src_addr_
= src_addr
.Pass();
250 callback
->data_
= data
.Pass();
256 NetworkErrorPtr result_
;
257 NetAddressPtr src_addr_
;
258 Array
<uint8_t> data_
;
261 struct ReceiveResult
{
262 NetworkErrorPtr result
;
267 class UDPSocketReceiverImpl
: public UDPSocketReceiver
{
269 UDPSocketReceiverImpl() : run_loop_(nullptr), expected_receive_count_(0) {}
271 ~UDPSocketReceiverImpl() override
{
272 while (!results_
.empty()) {
273 delete results_
.front();
278 std::queue
<ReceiveResult
*>* results() {
282 void WaitForReceiveResults(size_t count
) {
283 if (results_
.size() == count
)
286 expected_receive_count_
= count
;
287 base::RunLoop run_loop
;
288 run_loop_
= &run_loop
;
294 void OnReceived(NetworkErrorPtr result
,
295 NetAddressPtr src_addr
,
296 Array
<uint8_t> data
) override
{
297 ReceiveResult
* entry
= new ReceiveResult();
298 entry
->result
= result
.Pass();
299 entry
->addr
= src_addr
.Pass();
300 entry
->data
= data
.Pass();
302 results_
.push(entry
);
304 if (results_
.size() == expected_receive_count_
&& run_loop_
) {
305 expected_receive_count_
= 0;
310 base::RunLoop
* run_loop_
;
311 std::queue
<ReceiveResult
*> results_
;
312 size_t expected_receive_count_
;
314 DISALLOW_COPY_AND_ASSIGN(UDPSocketReceiverImpl
);
317 class UDPSocketAppTest
: public test::ApplicationTestBase
{
319 UDPSocketAppTest() : receiver_binding_(&receiver_
) {}
320 ~UDPSocketAppTest() override
{}
322 void SetUp() override
{
323 ApplicationTestBase::SetUp();
325 ApplicationConnection
* connection
=
326 application_impl()->ConnectToApplication("mojo:network_service");
327 connection
->ConnectToService(&network_service_
);
329 network_service_
->CreateUDPSocket(GetProxy(&socket_
));
333 NetworkServicePtr network_service_
;
334 UDPSocketPtr socket_
;
335 UDPSocketReceiverImpl receiver_
;
336 Binding
<UDPSocketReceiver
> receiver_binding_
;
338 DISALLOW_COPY_AND_ASSIGN(UDPSocketAppTest
);
343 TEST_F(UDPSocketAppTest
, Settings
) {
344 TestCallback callback1
;
345 socket_
->AllowAddressReuse(callback1
.callback());
346 callback1
.WaitForResult();
347 EXPECT_EQ(net::OK
, callback1
.result()->code
);
349 // Should fail because the socket hasn't been bound.
350 TestCallback callback2
;
351 socket_
->SetSendBufferSize(1024, callback2
.callback());
352 callback2
.WaitForResult();
353 EXPECT_NE(net::OK
, callback2
.result()->code
);
355 // Should fail because the socket hasn't been bound.
356 TestCallback callback3
;
357 socket_
->SetReceiveBufferSize(2048, callback3
.callback());
358 callback3
.WaitForResult();
359 EXPECT_NE(net::OK
, callback3
.result()->code
);
361 TestCallbackWithAddressAndReceiver callback4
;
362 socket_
->Bind(GetLocalHostWithAnyPort(), callback4
.callback());
363 callback4
.WaitForResult();
364 EXPECT_EQ(net::OK
, callback4
.result()->code
);
365 EXPECT_NE(0u, callback4
.net_address()->ipv4
->port
);
367 // Should fail because the socket has been bound.
368 TestCallback callback5
;
369 socket_
->AllowAddressReuse(callback5
.callback());
370 callback5
.WaitForResult();
371 EXPECT_NE(net::OK
, callback5
.result()->code
);
373 TestCallback callback6
;
374 socket_
->SetSendBufferSize(1024, callback6
.callback());
375 callback6
.WaitForResult();
376 EXPECT_EQ(net::OK
, callback6
.result()->code
);
378 TestCallback callback7
;
379 socket_
->SetReceiveBufferSize(2048, callback7
.callback());
380 callback7
.WaitForResult();
381 EXPECT_EQ(net::OK
, callback7
.result()->code
);
383 TestCallbackWithUint32 callback8
;
384 socket_
->NegotiateMaxPendingSendRequests(0, callback8
.callback());
385 callback8
.WaitForResult();
386 EXPECT_GT(callback8
.result(), 0u);
388 TestCallbackWithUint32 callback9
;
389 socket_
->NegotiateMaxPendingSendRequests(16, callback9
.callback());
390 callback9
.WaitForResult();
391 EXPECT_GT(callback9
.result(), 0u);
394 TEST_F(UDPSocketAppTest
, TestReadWrite
) {
395 TestCallbackWithAddressAndReceiver callback1
;
396 socket_
->Bind(GetLocalHostWithAnyPort(), callback1
.callback());
397 callback1
.WaitForResult();
398 ASSERT_EQ(net::OK
, callback1
.result()->code
);
399 ASSERT_NE(0u, callback1
.net_address()->ipv4
->port
);
401 receiver_binding_
.Bind(callback1
.receiver().Pass());
403 NetAddressPtr server_addr
= callback1
.net_address().Clone();
405 UDPSocketPtr client_socket
;
406 network_service_
->CreateUDPSocket(GetProxy(&client_socket
));
408 TestCallbackWithAddressAndReceiver callback2
;
409 client_socket
->Bind(GetLocalHostWithAnyPort(), callback2
.callback());
410 callback2
.WaitForResult();
411 ASSERT_EQ(net::OK
, callback2
.result()->code
);
412 ASSERT_NE(0u, callback2
.net_address()->ipv4
->port
);
414 NetAddressPtr client_addr
= callback2
.net_address().Clone();
416 const size_t kDatagramCount
= 6;
417 const size_t kDatagramSize
= 255;
418 socket_
->ReceiveMore(kDatagramCount
);
420 for (size_t i
= 0; i
< kDatagramCount
; ++i
) {
421 TestCallback callback
;
422 client_socket
->SendTo(
424 CreateTestMessage(static_cast<uint8_t>(i
), kDatagramSize
),
425 callback
.callback());
426 callback
.WaitForResult();
427 EXPECT_EQ(255, callback
.result()->code
);
430 receiver_
.WaitForReceiveResults(kDatagramCount
);
431 for (size_t i
= 0; i
< kDatagramCount
; ++i
) {
432 scoped_ptr
<ReceiveResult
> result(receiver_
.results()->front());
433 receiver_
.results()->pop();
435 EXPECT_EQ(static_cast<int>(kDatagramSize
), result
->result
->code
);
436 EXPECT_TRUE(result
->addr
.Equals(client_addr
));
437 EXPECT_TRUE(result
->data
.Equals(
438 CreateTestMessage(static_cast<uint8_t>(i
), kDatagramSize
)));
442 TEST_F(UDPSocketAppTest
, TestConnectedReadWrite
) {
443 TestCallbackWithAddressAndReceiver callback1
;
444 socket_
->Bind(GetLocalHostWithAnyPort(), callback1
.callback());
445 callback1
.WaitForResult();
446 ASSERT_EQ(net::OK
, callback1
.result()->code
);
447 ASSERT_NE(0u, callback1
.net_address()->ipv4
->port
);
449 receiver_binding_
.Bind(callback1
.receiver().Pass());
451 NetAddressPtr server_addr
= callback1
.net_address().Clone();
453 UDPSocketPtr client_socket
;
454 network_service_
->CreateUDPSocket(GetProxy(&client_socket
));
456 TestCallbackWithAddressAndReceiver callback2
;
457 client_socket
->Connect(server_addr
.Clone(), callback2
.callback());
458 callback2
.WaitForResult();
459 ASSERT_EQ(net::OK
, callback2
.result()->code
);
460 ASSERT_NE(0u, callback2
.net_address()->ipv4
->port
);
462 UDPSocketReceiverImpl client_socket_receiver
;
463 Binding
<UDPSocketReceiver
> client_receiver_binding(
464 &client_socket_receiver
, callback2
.receiver().Pass());
466 NetAddressPtr client_addr
= callback2
.net_address().Clone();
468 const size_t kDatagramCount
= 6;
469 const size_t kDatagramSize
= 255;
471 // Test send using a connected socket.
472 socket_
->ReceiveMore(kDatagramCount
);
474 for (size_t i
= 0; i
< kDatagramCount
; ++i
) {
475 TestCallback callback
;
476 client_socket
->SendTo(
478 CreateTestMessage(static_cast<uint8_t>(i
), kDatagramSize
),
479 callback
.callback());
480 callback
.WaitForResult();
481 EXPECT_EQ(255, callback
.result()->code
);
484 receiver_
.WaitForReceiveResults(kDatagramCount
);
485 for (size_t i
= 0; i
< kDatagramCount
; ++i
) {
486 scoped_ptr
<ReceiveResult
> result(receiver_
.results()->front());
487 receiver_
.results()->pop();
489 EXPECT_EQ(static_cast<int>(kDatagramSize
), result
->result
->code
);
490 EXPECT_TRUE(result
->addr
.Equals(client_addr
));
491 EXPECT_TRUE(result
->data
.Equals(
492 CreateTestMessage(static_cast<uint8_t>(i
), kDatagramSize
)));
495 // Test receive using a connected socket.
496 client_socket
->ReceiveMore(kDatagramCount
);
498 for (size_t i
= 0; i
< kDatagramCount
; ++i
) {
499 TestCallback callback
;
502 CreateTestMessage(static_cast<uint8_t>(i
), kDatagramSize
),
503 callback
.callback());
504 callback
.WaitForResult();
505 EXPECT_EQ(255, callback
.result()->code
);
508 client_socket_receiver
.WaitForReceiveResults(kDatagramCount
);
509 for (size_t i
= 0; i
< kDatagramCount
; ++i
) {
510 scoped_ptr
<ReceiveResult
> result(client_socket_receiver
.results()->front());
511 client_socket_receiver
.results()->pop();
513 EXPECT_EQ(static_cast<int>(kDatagramSize
), result
->result
->code
);
514 EXPECT_FALSE(result
->addr
);
515 EXPECT_TRUE(result
->data
.Equals(
516 CreateTestMessage(static_cast<uint8_t>(i
), kDatagramSize
)));
520 TEST_F(UDPSocketAppTest
, TestWrapperReadWrite
) {
521 UDPSocketWrapper
socket(socket_
.Pass(), 4, 4);
523 TestCallbackWithAddress callback1
;
524 socket
.Bind(GetLocalHostWithAnyPort(), callback1
.callback());
525 callback1
.WaitForResult();
526 ASSERT_EQ(net::OK
, callback1
.result()->code
);
527 ASSERT_NE(0u, callback1
.net_address()->ipv4
->port
);
529 NetAddressPtr server_addr
= callback1
.net_address().Clone();
531 UDPSocketPtr raw_client_socket
;
532 network_service_
->CreateUDPSocket(GetProxy(&raw_client_socket
));
533 UDPSocketWrapper
client_socket(raw_client_socket
.Pass(), 4, 4);
535 TestCallbackWithAddress callback2
;
536 client_socket
.Bind(GetLocalHostWithAnyPort(), callback2
.callback());
537 callback2
.WaitForResult();
538 ASSERT_EQ(net::OK
, callback2
.result()->code
);
539 ASSERT_NE(0u, callback2
.net_address()->ipv4
->port
);
541 NetAddressPtr client_addr
= callback2
.net_address().Clone();
543 const size_t kDatagramCount
= 16;
544 const size_t kDatagramSize
= 255;
546 for (size_t i
= 1; i
< kDatagramCount
; ++i
) {
547 scoped_ptr
<TestCallback
[]> send_callbacks(new TestCallback
[i
]);
548 scoped_ptr
<TestReceiveCallback
[]> receive_callbacks(
549 new TestReceiveCallback
[i
]);
551 for (size_t j
= 0; j
< i
; ++j
) {
552 client_socket
.SendTo(
554 CreateTestMessage(static_cast<uint8_t>(j
), kDatagramSize
),
555 send_callbacks
[j
].callback());
557 socket
.ReceiveFrom(receive_callbacks
[j
].callback());
560 receive_callbacks
[i
- 1].WaitForResult();
562 for (size_t j
= 0; j
< i
; ++j
) {
563 EXPECT_EQ(static_cast<int>(kDatagramSize
),
564 receive_callbacks
[j
].result()->code
);
565 EXPECT_TRUE(receive_callbacks
[j
].src_addr().Equals(client_addr
));
566 EXPECT_TRUE(receive_callbacks
[j
].data().Equals(
567 CreateTestMessage(static_cast<uint8_t>(j
), kDatagramSize
)));
572 TEST_F(UDPSocketAppTest
, TestWrapperConnectedReadWrite
) {
573 UDPSocketWrapper
socket(socket_
.Pass(), 4, 4);
575 TestCallbackWithAddress callback1
;
576 socket
.Bind(GetLocalHostWithAnyPort(), callback1
.callback());
577 callback1
.WaitForResult();
578 ASSERT_EQ(net::OK
, callback1
.result()->code
);
579 ASSERT_NE(0u, callback1
.net_address()->ipv4
->port
);
581 NetAddressPtr server_addr
= callback1
.net_address().Clone();
583 UDPSocketPtr raw_client_socket
;
584 network_service_
->CreateUDPSocket(GetProxy(&raw_client_socket
));
585 UDPSocketWrapper
client_socket(raw_client_socket
.Pass(), 4, 4);
587 TestCallbackWithAddress callback2
;
588 client_socket
.Connect(server_addr
.Pass(), callback2
.callback());
589 callback2
.WaitForResult();
590 ASSERT_EQ(net::OK
, callback2
.result()->code
);
591 ASSERT_NE(0u, callback2
.net_address()->ipv4
->port
);
593 NetAddressPtr client_addr
= callback2
.net_address().Clone();
595 const size_t kDatagramCount
= 16;
596 const size_t kDatagramSize
= 255;
598 // Test send using a connected socket.
599 for (size_t i
= 1; i
< kDatagramCount
; ++i
) {
600 scoped_ptr
<TestCallback
[]> send_callbacks(new TestCallback
[i
]);
601 scoped_ptr
<TestReceiveCallback
[]> receive_callbacks(
602 new TestReceiveCallback
[i
]);
604 for (size_t j
= 0; j
< i
; ++j
) {
605 client_socket
.SendTo(
607 CreateTestMessage(static_cast<uint8_t>(j
), kDatagramSize
),
608 send_callbacks
[j
].callback());
610 socket
.ReceiveFrom(receive_callbacks
[j
].callback());
613 receive_callbacks
[i
- 1].WaitForResult();
615 for (size_t j
= 0; j
< i
; ++j
) {
616 EXPECT_EQ(static_cast<int>(kDatagramSize
),
617 receive_callbacks
[j
].result()->code
);
618 EXPECT_TRUE(receive_callbacks
[j
].src_addr().Equals(client_addr
));
619 EXPECT_TRUE(receive_callbacks
[j
].data().Equals(
620 CreateTestMessage(static_cast<uint8_t>(j
), kDatagramSize
)));
624 // Test receive using a connected socket.
625 for (size_t i
= 1; i
< kDatagramCount
; ++i
) {
626 scoped_ptr
<TestCallback
[]> send_callbacks(new TestCallback
[i
]);
627 scoped_ptr
<TestReceiveCallback
[]> receive_callbacks(
628 new TestReceiveCallback
[i
]);
630 for (size_t j
= 0; j
< i
; ++j
) {
633 CreateTestMessage(static_cast<uint8_t>(j
), kDatagramSize
),
634 send_callbacks
[j
].callback());
636 client_socket
.ReceiveFrom(receive_callbacks
[j
].callback());
639 receive_callbacks
[i
- 1].WaitForResult();
641 for (size_t j
= 0; j
< i
; ++j
) {
642 EXPECT_EQ(static_cast<int>(kDatagramSize
),
643 receive_callbacks
[j
].result()->code
);
644 EXPECT_FALSE(receive_callbacks
[j
].src_addr());
645 EXPECT_TRUE(receive_callbacks
[j
].data().Equals(
646 CreateTestMessage(static_cast<uint8_t>(j
), kDatagramSize
)));
651 } // namespace service