Android: Remove unneeded Compositor::SetNeedsRedraw()
[chromium-blink-merge.git] / ppapi / tests / test_utils.cc
blobeecbe7a96e2570becfc1b9964296f2d34af9a0ae
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"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #if defined(_MSC_VER)
11 #include <windows.h>
12 #else
13 #include <unistd.h>
14 #endif
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"
24 namespace {
26 bool IsBigEndian() {
27 union {
28 uint32_t integer32;
29 uint8_t integer8[4];
30 } data = { 0x01020304 };
32 return data.integer8[0] == 1;
35 } // namespace
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: ") +
50 error_as_string;
51 return result;
54 void PlatformSleep(int duration_ms) {
55 #if defined(_MSC_VER)
56 ::Sleep(duration_ms);
57 #else
58 usleep(duration_ms * 1000);
59 #endif
62 bool GetLocalHostPort(PP_Instance instance, std::string* host, uint16_t* port) {
63 if (!host || !port)
64 return false;
66 const PPB_Testing_Dev* testing = GetTestingInterface();
67 if (!testing)
68 return false;
70 PP_URLComponents_Dev components;
71 pp::Var pp_url(pp::PASS_REF,
72 testing->GetDocumentURL(instance, &components));
73 if (!pp_url.is_string())
74 return false;
75 std::string url = pp_url.AsString();
77 if (components.host.len < 0)
78 return false;
79 host->assign(url.substr(components.host.begin, components.host.len));
81 if (components.port.len <= 0)
82 return false;
84 int i = atoi(url.substr(components.port.begin, components.port.len).c_str());
85 if (i < 0 || i > 65535)
86 return false;
87 *port = static_cast<uint16_t>(i);
89 return true;
92 uint16_t ConvertFromNetEndian16(uint16_t x) {
93 if (IsBigEndian())
94 return x;
95 else
96 return (x << 8) | (x >> 8);
99 uint16_t ConvertToNetEndian16(uint16_t x) {
100 if (IsBigEndian())
101 return x;
102 else
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) {
109 return false;
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)) {
116 return false;
119 return ipv4_addr1.port == ipv4_addr2.port &&
120 !memcmp(ipv4_addr1.addr, ipv4_addr2.addr, sizeof(ipv4_addr1.addr));
121 } else {
122 PP_NetAddress_IPv6 ipv6_addr1, ipv6_addr2;
123 if (!addr1.DescribeAsIPv6Address(&ipv6_addr1) ||
124 !addr2.DescribeAsIPv6Address(&ipv6_addr2)) {
125 return false;
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,
135 uint16_t port,
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)) {
150 return false;
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))) {
160 return false;
162 *addr = pp::NetAddress(instance_handle, ipv4_addr);
163 return true;
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))) {
171 return false;
173 *addr = pp::NetAddress(instance_handle, ipv6_addr);
174 return true;
176 default: {
177 return false;
182 bool ReplacePort(PP_Instance instance,
183 const pp::NetAddress& input_addr,
184 uint16_t port,
185 pp::NetAddress* output_addr) {
186 switch (input_addr.GetFamily()) {
187 case PP_NETADDRESS_FAMILY_IPV4: {
188 PP_NetAddress_IPv4 ipv4_addr;
189 if (!input_addr.DescribeAsIPv4Address(&ipv4_addr))
190 return false;
191 ipv4_addr.port = ConvertToNetEndian16(port);
192 *output_addr = pp::NetAddress(pp::InstanceHandle(instance), ipv4_addr);
193 return true;
195 case PP_NETADDRESS_FAMILY_IPV6: {
196 PP_NetAddress_IPv6 ipv6_addr;
197 if (!input_addr.DescribeAsIPv6Address(&ipv6_addr))
198 return false;
199 ipv6_addr.port = ConvertToNetEndian16(port);
200 *output_addr = pp::NetAddress(pp::InstanceHandle(instance), ipv6_addr);
201 return true;
203 default: {
204 return false;
209 uint16_t GetPort(const pp::NetAddress& addr) {
210 switch (addr.GetFamily()) {
211 case PP_NETADDRESS_FAMILY_IPV4: {
212 PP_NetAddress_IPv4 ipv4_addr;
213 if (!addr.DescribeAsIPv4Address(&ipv4_addr))
214 return 0;
215 return ConvertFromNetEndian16(ipv4_addr.port);
217 case PP_NETADDRESS_FAMILY_IPV6: {
218 PP_NetAddress_IPv6 ipv6_addr;
219 if (!addr.DescribeAsIPv6Address(&ipv6_addr))
220 return 0;
221 return ConvertFromNetEndian16(ipv6_addr.port);
223 default: {
224 return 0;
229 void NestedEvent::Wait() {
230 PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
231 // Don't allow nesting more than once; it doesn't work with the code as-is,
232 // and probably is a bad idea most of the time anyway.
233 PP_DCHECK(!waiting_);
234 if (signalled_)
235 return;
236 waiting_ = true;
237 while (!signalled_)
238 GetTestingInterface()->RunMessageLoop(instance_);
239 waiting_ = false;
242 void NestedEvent::Signal() {
243 if (pp::Module::Get()->core()->IsMainThread())
244 SignalOnMainThread();
245 else
246 PostSignal(0);
249 void NestedEvent::PostSignal(int32_t wait_ms) {
250 pp::Module::Get()->core()->CallOnMainThread(
251 wait_ms,
252 pp::CompletionCallback(&SignalThunk, this),
256 void NestedEvent::Reset() {
257 PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
258 // It doesn't make sense to reset when we're still waiting.
259 PP_DCHECK(!waiting_);
260 signalled_ = false;
263 void NestedEvent::SignalOnMainThread() {
264 PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
265 signalled_ = true;
266 if (waiting_)
267 GetTestingInterface()->QuitMessageLoop(instance_);
270 void NestedEvent::SignalThunk(void* event, int32_t /* result */) {
271 static_cast<NestedEvent*>(event)->SignalOnMainThread();
274 TestCompletionCallback::TestCompletionCallback(PP_Instance instance)
275 : wait_for_result_called_(false),
276 have_result_(false),
277 result_(PP_OK_COMPLETIONPENDING),
278 // TODO(dmichael): The default should probably be PP_REQUIRED, but this is
279 // what the tests currently expect.
280 callback_type_(PP_OPTIONAL),
281 post_quit_task_(false),
282 instance_(instance),
283 delegate_(NULL) {
286 TestCompletionCallback::TestCompletionCallback(PP_Instance instance,
287 bool force_async)
288 : wait_for_result_called_(false),
289 have_result_(false),
290 result_(PP_OK_COMPLETIONPENDING),
291 callback_type_(force_async ? PP_REQUIRED : PP_OPTIONAL),
292 post_quit_task_(false),
293 instance_(instance),
294 delegate_(NULL) {
297 TestCompletionCallback::TestCompletionCallback(PP_Instance instance,
298 CallbackType callback_type)
299 : wait_for_result_called_(false),
300 have_result_(false),
301 result_(PP_OK_COMPLETIONPENDING),
302 callback_type_(callback_type),
303 post_quit_task_(false),
304 instance_(instance),
305 delegate_(NULL) {
308 void TestCompletionCallback::WaitForResult(int32_t result) {
309 PP_DCHECK(!wait_for_result_called_);
310 wait_for_result_called_ = true;
311 errors_.clear();
312 if (result == PP_OK_COMPLETIONPENDING) {
313 if (!have_result_) {
314 post_quit_task_ = true;
315 RunMessageLoop();
317 if (callback_type_ == PP_BLOCKING) {
318 errors_.assign(
319 ReportError("TestCompletionCallback: Call did not run synchronously "
320 "when passed a blocking completion callback!",
321 result_));
322 return;
324 } else {
325 result_ = result;
326 have_result_ = true;
327 if (callback_type_ == PP_REQUIRED) {
328 errors_.assign(
329 ReportError("TestCompletionCallback: Call ran synchronously when "
330 "passed a required completion callback!",
331 result_));
332 return;
335 PP_DCHECK(have_result_ == true);
338 void TestCompletionCallback::WaitForAbortResult(int32_t result) {
339 WaitForResult(result);
340 int32_t final_result = result_;
341 if (result == PP_OK_COMPLETIONPENDING) {
342 if (final_result != PP_ERROR_ABORTED) {
343 errors_.assign(
344 ReportError("TestCompletionCallback: Expected PP_ERROR_ABORTED or "
345 "PP_OK. Ran asynchronously.",
346 final_result));
347 return;
349 } else if (result < PP_OK) {
350 errors_.assign(
351 ReportError("TestCompletionCallback: Expected PP_ERROR_ABORTED or "
352 "non-error response. Ran synchronously.",
353 result));
354 return;
358 pp::CompletionCallback TestCompletionCallback::GetCallback() {
359 Reset();
360 int32_t flags = 0;
361 if (callback_type_ == PP_BLOCKING)
362 return pp::CompletionCallback();
363 else if (callback_type_ == PP_OPTIONAL)
364 flags = PP_COMPLETIONCALLBACK_FLAG_OPTIONAL;
365 target_loop_ = pp::MessageLoop::GetCurrent();
366 return pp::CompletionCallback(&TestCompletionCallback::Handler,
367 const_cast<TestCompletionCallback*>(this),
368 flags);
371 void TestCompletionCallback::Reset() {
372 wait_for_result_called_ = false;
373 result_ = PP_OK_COMPLETIONPENDING;
374 have_result_ = false;
375 post_quit_task_ = false;
376 delegate_ = NULL;
377 errors_.clear();
380 // static
381 void TestCompletionCallback::Handler(void* user_data, int32_t result) {
382 TestCompletionCallback* callback =
383 static_cast<TestCompletionCallback*>(user_data);
384 // If this check fails, it means that the callback was invoked twice or that
385 // the PPAPI call completed synchronously, but also ran the callback.
386 PP_DCHECK(!callback->have_result_);
387 callback->result_ = result;
388 callback->have_result_ = true;
389 if (callback->delegate_)
390 callback->delegate_->OnCallback(user_data, result);
391 if (callback->post_quit_task_) {
392 callback->post_quit_task_ = false;
393 callback->QuitMessageLoop();
395 if (callback->target_loop_ != pp::MessageLoop::GetCurrent()) {
396 // Note, in-process, loop_ and GetCurrent() will both be NULL, so should
397 // still be equal.
398 callback->errors_.assign(
399 ReportError("TestCompletionCallback: Callback ran on the wrong message "
400 "loop!",
401 result));
405 void TestCompletionCallback::RunMessageLoop() {
406 pp::MessageLoop loop(pp::MessageLoop::GetCurrent());
407 // If we don't have a message loop, we're probably running in process, where
408 // PPB_MessageLoop is not supported. Just use the Testing message loop.
409 if (loop.is_null() || loop == pp::MessageLoop::GetForMainThread())
410 GetTestingInterface()->RunMessageLoop(instance_);
411 else
412 loop.Run();
415 void TestCompletionCallback::QuitMessageLoop() {
416 pp::MessageLoop loop(pp::MessageLoop::GetCurrent());
417 // If we don't have a message loop, we're probably running in process, where
418 // PPB_MessageLoop is not supported. Just use the Testing message loop.
419 if (loop.is_null() || loop == pp::MessageLoop::GetForMainThread()) {
420 GetTestingInterface()->QuitMessageLoop(instance_);
421 } else {
422 const bool should_quit = false;
423 loop.PostQuit(should_quit);