cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / ppapi / tests / test_utils.cc
blobf9fd7b699fa1b7d407d48f1e88dd7db794070609
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 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_);
187 if (signalled_)
188 return;
189 waiting_ = true;
190 while (!signalled_)
191 GetTestingInterface()->RunMessageLoop(instance_);
192 waiting_ = false;
195 void NestedEvent::Signal() {
196 if (pp::Module::Get()->core()->IsMainThread())
197 SignalOnMainThread();
198 else
199 PostSignal(0);
202 void NestedEvent::PostSignal(int32_t wait_ms) {
203 pp::Module::Get()->core()->CallOnMainThread(
204 wait_ms,
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_);
213 signalled_ = false;
216 void NestedEvent::SignalOnMainThread() {
217 PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
218 signalled_ = true;
219 if (waiting_)
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),
229 have_result_(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),
235 instance_(instance),
236 delegate_(NULL) {
239 TestCompletionCallback::TestCompletionCallback(PP_Instance instance,
240 bool force_async)
241 : wait_for_result_called_(false),
242 have_result_(false),
243 result_(PP_OK_COMPLETIONPENDING),
244 callback_type_(force_async ? PP_REQUIRED : PP_OPTIONAL),
245 post_quit_task_(false),
246 instance_(instance),
247 delegate_(NULL) {
250 TestCompletionCallback::TestCompletionCallback(PP_Instance instance,
251 CallbackType callback_type)
252 : wait_for_result_called_(false),
253 have_result_(false),
254 result_(PP_OK_COMPLETIONPENDING),
255 callback_type_(callback_type),
256 post_quit_task_(false),
257 instance_(instance),
258 delegate_(NULL) {
261 void TestCompletionCallback::WaitForResult(int32_t result) {
262 PP_DCHECK(!wait_for_result_called_);
263 wait_for_result_called_ = true;
264 errors_.clear();
265 if (result == PP_OK_COMPLETIONPENDING) {
266 if (!have_result_) {
267 post_quit_task_ = true;
268 RunMessageLoop();
270 if (callback_type_ == PP_BLOCKING) {
271 errors_.assign(
272 ReportError("TestCompletionCallback: Call did not run synchronously "
273 "when passed a blocking completion callback!",
274 result_));
275 return;
277 } else {
278 result_ = result;
279 have_result_ = true;
280 if (callback_type_ == PP_REQUIRED) {
281 errors_.assign(
282 ReportError("TestCompletionCallback: Call ran synchronously when "
283 "passed a required completion callback!",
284 result_));
285 return;
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) {
296 errors_.assign(
297 ReportError("TestCompletionCallback: Expected PP_ERROR_ABORTED or "
298 "PP_OK. Ran asynchronously.",
299 final_result));
300 return;
302 } else if (result < PP_OK) {
303 errors_.assign(
304 ReportError("TestCompletionCallback: Expected PP_ERROR_ABORTED or "
305 "non-error response. Ran synchronously.",
306 result));
307 return;
311 pp::CompletionCallback TestCompletionCallback::GetCallback() {
312 Reset();
313 int32_t flags = 0;
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),
321 flags);
324 void TestCompletionCallback::Reset() {
325 wait_for_result_called_ = false;
326 result_ = PP_OK_COMPLETIONPENDING;
327 have_result_ = false;
328 post_quit_task_ = false;
329 delegate_ = NULL;
330 errors_.clear();
333 // static
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
350 // still be equal.
351 callback->errors_.assign(
352 ReportError("TestCompletionCallback: Callback ran on the wrong message "
353 "loop!",
354 result));
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_);
364 else
365 loop.Run();
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_);
374 } else {
375 const bool should_quit = false;
376 loop.PostQuit(should_quit);