1 // Copyright 2013 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 "ppapi/tests/test_udp_socket.h"
9 #include "ppapi/cpp/pass_ref.h"
10 #include "ppapi/cpp/tcp_socket.h"
11 #include "ppapi/cpp/udp_socket.h"
12 #include "ppapi/cpp/var.h"
13 #include "ppapi/tests/test_utils.h"
14 #include "ppapi/tests/testing_instance.h"
16 REGISTER_TEST_CASE(UDPSocket
);
20 const uint16_t kPortScanFrom
= 1024;
21 const uint16_t kPortScanTo
= 4096;
23 pp::NetAddress
ReplacePort(const pp::InstanceHandle
& instance
,
24 const pp::NetAddress
& addr
,
26 switch (addr
.GetFamily()) {
27 case PP_NETADDRESS_FAMILY_IPV4
: {
28 PP_NetAddress_IPv4 ipv4_addr
;
29 if (!addr
.DescribeAsIPv4Address(&ipv4_addr
))
31 ipv4_addr
.port
= ConvertToNetEndian16(port
);
32 return pp::NetAddress(instance
, ipv4_addr
);
34 case PP_NETADDRESS_FAMILY_IPV6
: {
35 PP_NetAddress_IPv6 ipv6_addr
;
36 if (!addr
.DescribeAsIPv6Address(&ipv6_addr
))
38 ipv6_addr
.port
= ConvertToNetEndian16(port
);
39 return pp::NetAddress(instance
, ipv6_addr
);
45 return pp::NetAddress();
50 TestUDPSocket::TestUDPSocket(TestingInstance
* instance
) : TestCase(instance
) {
53 bool TestUDPSocket::Init() {
54 bool tcp_socket_is_available
= pp::TCPSocket::IsAvailable();
55 if (!tcp_socket_is_available
)
56 instance_
->AppendError("PPB_TCPSocket interface not available");
58 bool udp_socket_is_available
= pp::UDPSocket::IsAvailable();
59 if (!udp_socket_is_available
)
60 instance_
->AppendError("PPB_UDPSocket interface not available");
62 bool net_address_is_available
= pp::NetAddress::IsAvailable();
63 if (!net_address_is_available
)
64 instance_
->AppendError("PPB_NetAddress interface not available");
69 GetLocalHostPort(instance_
->pp_instance(), &host
, &port
) &&
70 ResolveHost(instance_
->pp_instance(), host
, port
, &address_
);
72 instance_
->AppendError("Can't init address");
74 return tcp_socket_is_available
&&
75 udp_socket_is_available
&&
76 net_address_is_available
&&
78 CheckTestingInterface() &&
79 EnsureRunningOverHTTP();
82 void TestUDPSocket::RunTests(const std::string
& filter
) {
83 RUN_CALLBACK_TEST(TestUDPSocket
, ReadWrite
, filter
);
84 RUN_CALLBACK_TEST(TestUDPSocket
, Broadcast
, filter
);
85 RUN_CALLBACK_TEST(TestUDPSocket
, SetOption
, filter
);
86 RUN_CALLBACK_TEST(TestUDPSocket
, ParallelSend
, filter
);
89 std::string
TestUDPSocket::GetLocalAddress(pp::NetAddress
* address
) {
90 pp::TCPSocket
socket(instance_
);
91 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
92 callback
.WaitForResult(socket
.Connect(address_
, callback
.GetCallback()));
93 CHECK_CALLBACK_BEHAVIOR(callback
);
94 ASSERT_EQ(PP_OK
, callback
.result());
95 *address
= socket
.GetLocalAddress();
96 ASSERT_NE(0, address
->pp_resource());
101 std::string
TestUDPSocket::SetBroadcastOptions(pp::UDPSocket
* socket
) {
102 TestCompletionCallback
callback_1(instance_
->pp_instance(), callback_type());
103 callback_1
.WaitForResult(socket
->SetOption(
104 PP_UDPSOCKET_OPTION_ADDRESS_REUSE
, pp::Var(true),
105 callback_1
.GetCallback()));
106 CHECK_CALLBACK_BEHAVIOR(callback_1
);
107 ASSERT_EQ(PP_OK
, callback_1
.result());
109 TestCompletionCallback
callback_2(instance_
->pp_instance(), callback_type());
110 callback_2
.WaitForResult(socket
->SetOption(
111 PP_UDPSOCKET_OPTION_BROADCAST
, pp::Var(true), callback_2
.GetCallback()));
112 CHECK_CALLBACK_BEHAVIOR(callback_2
);
113 ASSERT_EQ(PP_OK
, callback_2
.result());
118 std::string
TestUDPSocket::BindUDPSocket(pp::UDPSocket
* socket
,
119 const pp::NetAddress
& address
) {
120 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
121 callback
.WaitForResult(socket
->Bind(address
, callback
.GetCallback()));
122 CHECK_CALLBACK_BEHAVIOR(callback
);
123 ASSERT_EQ(PP_OK
, callback
.result());
127 std::string
TestUDPSocket::LookupPortAndBindUDPSocket(
128 pp::UDPSocket
* socket
,
129 pp::NetAddress
* address
) {
130 pp::NetAddress base_address
;
131 ASSERT_SUBTEST_SUCCESS(GetLocalAddress(&base_address
));
133 bool is_free_port_found
= false;
134 for (uint16_t port
= kPortScanFrom
; port
< kPortScanTo
; ++port
) {
135 pp::NetAddress new_address
= ReplacePort(instance_
, base_address
, port
);
136 ASSERT_NE(0, new_address
.pp_resource());
137 if (BindUDPSocket(socket
, new_address
).empty()) {
138 is_free_port_found
= true;
142 if (!is_free_port_found
)
143 return "Can't find available port";
145 *address
= socket
->GetBoundAddress();
146 ASSERT_NE(0, address
->pp_resource());
151 std::string
TestUDPSocket::ReadSocket(pp::UDPSocket
* socket
,
152 pp::NetAddress
* address
,
154 std::string
* message
) {
155 std::vector
<char> buffer(size
);
156 TestCompletionCallbackWithOutput
<pp::NetAddress
> callback(
157 instance_
->pp_instance(), callback_type());
158 callback
.WaitForResult(
159 socket
->RecvFrom(&buffer
[0], size
, callback
.GetCallback()));
160 CHECK_CALLBACK_BEHAVIOR(callback
);
161 ASSERT_FALSE(callback
.result() < 0);
162 ASSERT_EQ(size
, static_cast<size_t>(callback
.result()));
163 *address
= callback
.output();
164 message
->assign(buffer
.begin(), buffer
.end());
168 std::string
TestUDPSocket::PassMessage(pp::UDPSocket
* target
,
169 pp::UDPSocket
* source
,
170 const pp::NetAddress
& target_address
,
171 const std::string
& message
,
172 pp::NetAddress
* recvfrom_address
) {
173 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
174 int32_t rv
= source
->SendTo(message
.c_str(), message
.size(),
176 callback
.GetCallback());
178 ASSERT_SUBTEST_SUCCESS(ReadSocket(target
, recvfrom_address
, message
.size(),
181 callback
.WaitForResult(rv
);
182 CHECK_CALLBACK_BEHAVIOR(callback
);
183 ASSERT_FALSE(callback
.result() < 0);
184 ASSERT_EQ(message
.size(), static_cast<size_t>(callback
.result()));
185 ASSERT_EQ(message
, str
);
189 std::string
TestUDPSocket::TestReadWrite() {
190 pp::UDPSocket
server_socket(instance_
), client_socket(instance_
);
191 pp::NetAddress server_address
, client_address
;
193 ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&server_socket
,
195 ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&client_socket
,
197 const std::string message
= "Simple message that will be sent via UDP";
198 pp::NetAddress recvfrom_address
;
199 ASSERT_SUBTEST_SUCCESS(PassMessage(&server_socket
, &client_socket
,
200 server_address
, message
,
202 ASSERT_TRUE(EqualNetAddress(recvfrom_address
, client_address
));
204 server_socket
.Close();
205 client_socket
.Close();
207 if (server_socket
.GetBoundAddress().pp_resource() != 0)
208 return "PPB_UDPSocket::GetBoundAddress: expected failure";
213 std::string
TestUDPSocket::TestBroadcast() {
214 pp::UDPSocket
server1(instance_
), server2(instance_
);
216 ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server1
));
217 ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server2
));
219 PP_NetAddress_IPv4 any_ipv4_address
= { 0, { 0, 0, 0, 0 } };
220 pp::NetAddress
any_address(instance_
, any_ipv4_address
);
221 ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server1
, any_address
));
222 // Fill port field of |server_address|.
223 pp::NetAddress server_address
= server1
.GetBoundAddress();
224 ASSERT_NE(0, server_address
.pp_resource());
225 ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server2
, server_address
));
227 PP_NetAddress_IPv4 server_ipv4_address
;
228 ASSERT_TRUE(server_address
.DescribeAsIPv4Address(&server_ipv4_address
));
230 PP_NetAddress_IPv4 broadcast_ipv4_address
= {
231 server_ipv4_address
.port
, { 0xff, 0xff, 0xff, 0xff }
233 pp::NetAddress
broadcast_address(instance_
, broadcast_ipv4_address
);
236 const std::string first_message
= "first message";
237 const std::string second_message
= "second_message";
239 pp::NetAddress recvfrom_address
;
240 ASSERT_SUBTEST_SUCCESS(PassMessage(&server1
, &server2
, broadcast_address
,
241 first_message
, &recvfrom_address
));
242 // |first_message| was also received by |server2|.
243 ASSERT_SUBTEST_SUCCESS(ReadSocket(&server2
, &recvfrom_address
,
244 first_message
.size(), &message
));
245 ASSERT_EQ(first_message
, message
);
247 ASSERT_SUBTEST_SUCCESS(PassMessage(&server2
, &server1
, broadcast_address
,
248 second_message
, &recvfrom_address
));
249 // |second_message| was also received by |server1|.
250 ASSERT_SUBTEST_SUCCESS(ReadSocket(&server1
, &recvfrom_address
,
251 second_message
.size(), &message
));
252 ASSERT_EQ(second_message
, message
);
259 std::string
TestUDPSocket::TestSetOption() {
260 pp::UDPSocket
socket(instance_
);
262 ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&socket
));
264 // Try to pass incorrect option value's type.
265 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
266 callback
.WaitForResult(socket
.SetOption(
267 PP_UDPSOCKET_OPTION_ADDRESS_REUSE
, pp::Var(1), callback
.GetCallback()));
268 CHECK_CALLBACK_BEHAVIOR(callback
);
269 ASSERT_EQ(PP_ERROR_BADARGUMENT
, callback
.result());
271 callback
.WaitForResult(socket
.SetOption(
272 PP_UDPSOCKET_OPTION_BROADCAST
, pp::Var(false), callback
.GetCallback()));
273 CHECK_CALLBACK_BEHAVIOR(callback
);
274 ASSERT_EQ(PP_OK
, callback
.result());
276 callback
.WaitForResult(socket
.SetOption(
277 PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE
, pp::Var(4096),
278 callback
.GetCallback()));
279 CHECK_CALLBACK_BEHAVIOR(callback
);
280 ASSERT_EQ(PP_OK
, callback
.result());
282 callback
.WaitForResult(socket
.SetOption(
283 PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE
, pp::Var(512),
284 callback
.GetCallback()));
285 CHECK_CALLBACK_BEHAVIOR(callback
);
286 ASSERT_EQ(PP_OK
, callback
.result());
288 pp::NetAddress address
;
289 ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&socket
, &address
));
291 // ADDRESS_REUSE won't take effect after the socket is bound.
292 callback
.WaitForResult(socket
.SetOption(
293 PP_UDPSOCKET_OPTION_ADDRESS_REUSE
, pp::Var(true),
294 callback
.GetCallback()));
295 CHECK_CALLBACK_BEHAVIOR(callback
);
296 ASSERT_EQ(PP_ERROR_FAILED
, callback
.result());
298 // BROADCAST, SEND_BUFFER_SIZE and RECV_BUFFER_SIZE can be set after the
300 callback
.WaitForResult(socket
.SetOption(
301 PP_UDPSOCKET_OPTION_BROADCAST
, pp::Var(true), callback
.GetCallback()));
302 CHECK_CALLBACK_BEHAVIOR(callback
);
303 ASSERT_EQ(PP_OK
, callback
.result());
305 callback
.WaitForResult(socket
.SetOption(
306 PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE
, pp::Var(2048),
307 callback
.GetCallback()));
308 CHECK_CALLBACK_BEHAVIOR(callback
);
309 ASSERT_EQ(PP_OK
, callback
.result());
311 callback
.WaitForResult(socket
.SetOption(
312 PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE
, pp::Var(1024),
313 callback
.GetCallback()));
314 CHECK_CALLBACK_BEHAVIOR(callback
);
315 ASSERT_EQ(PP_OK
, callback
.result());
320 std::string
TestUDPSocket::TestParallelSend() {
321 // This test only makes sense when callbacks are optional.
322 if (callback_type() != PP_OPTIONAL
)
325 pp::UDPSocket
server_socket(instance_
), client_socket(instance_
);
326 pp::NetAddress server_address
, client_address
;
328 ASSERT_SUBTEST_SUCCESS(
329 LookupPortAndBindUDPSocket(&server_socket
, &server_address
));
330 ASSERT_SUBTEST_SUCCESS(
331 LookupPortAndBindUDPSocket(&client_socket
, &client_address
));
332 const std::string message
= "Simple message that will be sent via UDP";
333 pp::NetAddress recvfrom_address
;
335 const size_t kParallelSends
= 10;
336 std::vector
<TestCompletionCallback
*> sendto_callbacks(kParallelSends
);
337 std::vector
<int32_t> sendto_results(kParallelSends
);
339 for (size_t i
= 0; i
< kParallelSends
; i
++) {
340 sendto_callbacks
[i
] =
341 new TestCompletionCallback(instance_
->pp_instance(), callback_type());
343 client_socket
.SendTo(message
.c_str(),
346 sendto_callbacks
[i
]->GetCallback());
348 if (sendto_results
[i
] == PP_ERROR_INPROGRESS
) {
349 // Run a pending send to completion to free a slot for the current send.
350 ASSERT_GT(i
, pending
);
351 sendto_callbacks
[pending
]->WaitForResult(sendto_results
[pending
]);
352 CHECK_CALLBACK_BEHAVIOR(*sendto_callbacks
[pending
]);
353 ASSERT_EQ(message
.size(),
354 static_cast<size_t>(sendto_callbacks
[pending
]->result()));
356 // Try to send the message again.
358 client_socket
.SendTo(message
.c_str(),
361 sendto_callbacks
[i
]->GetCallback());
362 ASSERT_NE(PP_ERROR_INPROGRESS
, sendto_results
[i
]);
366 // Finish all pending sends.
367 for (size_t i
= pending
; i
< kParallelSends
; i
++) {
368 sendto_callbacks
[i
]->WaitForResult(sendto_results
[i
]);
369 CHECK_CALLBACK_BEHAVIOR(*sendto_callbacks
[i
]);
370 ASSERT_EQ(message
.size(),
371 static_cast<size_t>(sendto_callbacks
[i
]->result()));
374 for (size_t i
= 0; i
< kParallelSends
; ++i
)
375 delete sendto_callbacks
[i
];
377 for (size_t i
= 0; i
< kParallelSends
; i
++) {
379 ASSERT_SUBTEST_SUCCESS(
380 ReadSocket(&server_socket
, &recvfrom_address
, message
.size(), &str
));
381 ASSERT_EQ(message
, str
);
384 server_socket
.Close();
385 client_socket
.Close();