1 // Copyright (c) 2012 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_utils.h"
16 #include "ppapi/c/pp_errors.h"
17 #include "ppapi/cpp/instance_handle.h"
18 #include "ppapi/cpp/module.h"
19 #include "ppapi/cpp/net_address.h"
20 #include "ppapi/cpp/private/host_resolver_private.h"
21 #include "ppapi/cpp/private/net_address_private.h"
22 #include "ppapi/cpp/var.h"
30 } data
= { 0x01020304 };
32 return data
.integer8
[0] == 1;
37 const int kActionTimeoutMs
= 10000;
39 const PPB_Testing_Dev
* GetTestingInterface() {
40 static const PPB_Testing_Dev
* g_testing_interface
=
41 static_cast<const PPB_Testing_Dev
*>(
42 pp::Module::Get()->GetBrowserInterface(PPB_TESTING_DEV_INTERFACE
));
43 return g_testing_interface
;
46 std::string
ReportError(const char* method
, int32_t error
) {
47 char error_as_string
[12];
48 sprintf(error_as_string
, "%d", static_cast<int>(error
));
49 std::string result
= method
+ std::string(" failed with error: ") +
54 void PlatformSleep(int duration_ms
) {
58 usleep(duration_ms
* 1000);
62 bool GetLocalHostPort(PP_Instance instance
, std::string
* host
, uint16_t* port
) {
66 const PPB_Testing_Dev
* testing
= GetTestingInterface();
70 PP_URLComponents_Dev components
;
71 pp::Var
pp_url(pp::PASS_REF
,
72 testing
->GetDocumentURL(instance
, &components
));
73 if (!pp_url
.is_string())
75 std::string url
= pp_url
.AsString();
77 if (components
.host
.len
< 0)
79 host
->assign(url
.substr(components
.host
.begin
, components
.host
.len
));
81 if (components
.port
.len
<= 0)
84 int i
= atoi(url
.substr(components
.port
.begin
, components
.port
.len
).c_str());
85 if (i
< 0 || i
> 65535)
87 *port
= static_cast<uint16_t>(i
);
92 uint16_t ConvertFromNetEndian16(uint16_t x
) {
96 return (x
<< 8) | (x
>> 8);
99 uint16_t ConvertToNetEndian16(uint16_t x
) {
103 return (x
<< 8) | (x
>> 8);
106 bool EqualNetAddress(const pp::NetAddress
& addr1
, const pp::NetAddress
& addr2
) {
107 if (addr1
.GetFamily() == PP_NETADDRESS_FAMILY_UNSPECIFIED
||
108 addr2
.GetFamily() == PP_NETADDRESS_FAMILY_UNSPECIFIED
) {
112 if (addr1
.GetFamily() == PP_NETADDRESS_FAMILY_IPV4
) {
113 PP_NetAddress_IPv4 ipv4_addr1
, ipv4_addr2
;
114 if (!addr1
.DescribeAsIPv4Address(&ipv4_addr1
) ||
115 !addr2
.DescribeAsIPv4Address(&ipv4_addr2
)) {
119 return ipv4_addr1
.port
== ipv4_addr2
.port
&&
120 !memcmp(ipv4_addr1
.addr
, ipv4_addr2
.addr
, sizeof(ipv4_addr1
.addr
));
122 PP_NetAddress_IPv6 ipv6_addr1
, ipv6_addr2
;
123 if (!addr1
.DescribeAsIPv6Address(&ipv6_addr1
) ||
124 !addr2
.DescribeAsIPv6Address(&ipv6_addr2
)) {
128 return ipv6_addr1
.port
== ipv6_addr2
.port
&&
129 !memcmp(ipv6_addr1
.addr
, ipv6_addr2
.addr
, sizeof(ipv6_addr1
.addr
));
133 bool ResolveHost(PP_Instance instance
,
134 const std::string
& host
,
136 pp::NetAddress
* addr
) {
137 // TODO(yzshen): Change to use the public host resolver once it is supported.
138 pp::InstanceHandle
instance_handle(instance
);
139 pp::HostResolverPrivate
host_resolver(instance_handle
);
140 PP_HostResolver_Private_Hint hint
=
141 { PP_NETADDRESSFAMILY_PRIVATE_UNSPECIFIED
, 0 };
143 TestCompletionCallback
callback(instance
);
144 callback
.WaitForResult(
145 host_resolver
.Resolve(host
, port
, hint
, callback
.GetCallback()));
147 PP_NetAddress_Private addr_private
;
148 if (callback
.result() != PP_OK
|| host_resolver
.GetSize() == 0 ||
149 !host_resolver
.GetNetAddress(0, &addr_private
)) {
153 switch (pp::NetAddressPrivate::GetFamily(addr_private
)) {
154 case PP_NETADDRESSFAMILY_PRIVATE_IPV4
: {
155 PP_NetAddress_IPv4 ipv4_addr
;
156 ipv4_addr
.port
= ConvertToNetEndian16(
157 pp::NetAddressPrivate::GetPort(addr_private
));
158 if (!pp::NetAddressPrivate::GetAddress(addr_private
, ipv4_addr
.addr
,
159 sizeof(ipv4_addr
.addr
))) {
162 *addr
= pp::NetAddress(instance_handle
, ipv4_addr
);
165 case PP_NETADDRESSFAMILY_PRIVATE_IPV6
: {
166 PP_NetAddress_IPv6 ipv6_addr
;
167 ipv6_addr
.port
= ConvertToNetEndian16(
168 pp::NetAddressPrivate::GetPort(addr_private
));
169 if (!pp::NetAddressPrivate::GetAddress(addr_private
, ipv6_addr
.addr
,
170 sizeof(ipv6_addr
.addr
))) {
173 *addr
= pp::NetAddress(instance_handle
, ipv6_addr
);
182 void NestedEvent::Wait() {
183 PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
184 // Don't allow nesting more than once; it doesn't work with the code as-is,
185 // and probably is a bad idea most of the time anyway.
186 PP_DCHECK(!waiting_
);
191 GetTestingInterface()->RunMessageLoop(instance_
);
195 void NestedEvent::Signal() {
196 if (pp::Module::Get()->core()->IsMainThread())
197 SignalOnMainThread();
202 void NestedEvent::PostSignal(int32_t wait_ms
) {
203 pp::Module::Get()->core()->CallOnMainThread(
205 pp::CompletionCallback(&SignalThunk
, this),
209 void NestedEvent::Reset() {
210 PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
211 // It doesn't make sense to reset when we're still waiting.
212 PP_DCHECK(!waiting_
);
216 void NestedEvent::SignalOnMainThread() {
217 PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
220 GetTestingInterface()->QuitMessageLoop(instance_
);
223 void NestedEvent::SignalThunk(void* event
, int32_t /* result */) {
224 static_cast<NestedEvent
*>(event
)->SignalOnMainThread();
227 TestCompletionCallback::TestCompletionCallback(PP_Instance instance
)
228 : wait_for_result_called_(false),
230 result_(PP_OK_COMPLETIONPENDING
),
231 // TODO(dmichael): The default should probably be PP_REQUIRED, but this is
232 // what the tests currently expect.
233 callback_type_(PP_OPTIONAL
),
234 post_quit_task_(false),
239 TestCompletionCallback::TestCompletionCallback(PP_Instance instance
,
241 : wait_for_result_called_(false),
243 result_(PP_OK_COMPLETIONPENDING
),
244 callback_type_(force_async
? PP_REQUIRED
: PP_OPTIONAL
),
245 post_quit_task_(false),
250 TestCompletionCallback::TestCompletionCallback(PP_Instance instance
,
251 CallbackType callback_type
)
252 : wait_for_result_called_(false),
254 result_(PP_OK_COMPLETIONPENDING
),
255 callback_type_(callback_type
),
256 post_quit_task_(false),
261 void TestCompletionCallback::WaitForResult(int32_t result
) {
262 PP_DCHECK(!wait_for_result_called_
);
263 wait_for_result_called_
= true;
265 if (result
== PP_OK_COMPLETIONPENDING
) {
267 post_quit_task_
= true;
270 if (callback_type_
== PP_BLOCKING
) {
272 ReportError("TestCompletionCallback: Call did not run synchronously "
273 "when passed a blocking completion callback!",
280 if (callback_type_
== PP_REQUIRED
) {
282 ReportError("TestCompletionCallback: Call ran synchronously when "
283 "passed a required completion callback!",
288 PP_DCHECK(have_result_
== true);
291 void TestCompletionCallback::WaitForAbortResult(int32_t result
) {
292 WaitForResult(result
);
293 int32_t final_result
= result_
;
294 if (result
== PP_OK_COMPLETIONPENDING
) {
295 if (final_result
!= PP_ERROR_ABORTED
) {
297 ReportError("TestCompletionCallback: Expected PP_ERROR_ABORTED or "
298 "PP_OK. Ran asynchronously.",
302 } else if (result
< PP_OK
) {
304 ReportError("TestCompletionCallback: Expected PP_ERROR_ABORTED or "
305 "non-error response. Ran synchronously.",
311 pp::CompletionCallback
TestCompletionCallback::GetCallback() {
314 if (callback_type_
== PP_BLOCKING
)
315 return pp::CompletionCallback();
316 else if (callback_type_
== PP_OPTIONAL
)
317 flags
= PP_COMPLETIONCALLBACK_FLAG_OPTIONAL
;
318 target_loop_
= pp::MessageLoop::GetCurrent();
319 return pp::CompletionCallback(&TestCompletionCallback::Handler
,
320 const_cast<TestCompletionCallback
*>(this),
324 void TestCompletionCallback::Reset() {
325 wait_for_result_called_
= false;
326 result_
= PP_OK_COMPLETIONPENDING
;
327 have_result_
= false;
328 post_quit_task_
= false;
334 void TestCompletionCallback::Handler(void* user_data
, int32_t result
) {
335 TestCompletionCallback
* callback
=
336 static_cast<TestCompletionCallback
*>(user_data
);
337 // If this check fails, it means that the callback was invoked twice or that
338 // the PPAPI call completed synchronously, but also ran the callback.
339 PP_DCHECK(!callback
->have_result_
);
340 callback
->result_
= result
;
341 callback
->have_result_
= true;
342 if (callback
->delegate_
)
343 callback
->delegate_
->OnCallback(user_data
, result
);
344 if (callback
->post_quit_task_
) {
345 callback
->post_quit_task_
= false;
346 callback
->QuitMessageLoop();
348 if (callback
->target_loop_
!= pp::MessageLoop::GetCurrent()) {
349 // Note, in-process, loop_ and GetCurrent() will both be NULL, so should
351 callback
->errors_
.assign(
352 ReportError("TestCompletionCallback: Callback ran on the wrong message "
358 void TestCompletionCallback::RunMessageLoop() {
359 pp::MessageLoop
loop(pp::MessageLoop::GetCurrent());
360 // If we don't have a message loop, we're probably running in process, where
361 // PPB_MessageLoop is not supported. Just use the Testing message loop.
362 if (loop
.is_null() || loop
== pp::MessageLoop::GetForMainThread())
363 GetTestingInterface()->RunMessageLoop(instance_
);
368 void TestCompletionCallback::QuitMessageLoop() {
369 pp::MessageLoop
loop(pp::MessageLoop::GetCurrent());
370 // If we don't have a message loop, we're probably running in process, where
371 // PPB_MessageLoop is not supported. Just use the Testing message loop.
372 if (loop
.is_null() || loop
== pp::MessageLoop::GetForMainThread()) {
373 GetTestingInterface()->QuitMessageLoop(instance_
);
375 const bool should_quit
= false;
376 loop
.PostQuit(should_quit
);