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 #ifndef PPAPI_TESTS_TEST_UTILS_H_
6 #define PPAPI_TESTS_TEST_UTILS_H_
10 #include "ppapi/c/pp_instance.h"
11 #include "ppapi/c/pp_stdint.h"
12 #include "ppapi/c/private/ppb_testing_private.h"
13 #include "ppapi/cpp/completion_callback.h"
14 #include "ppapi/cpp/message_loop.h"
15 #include "ppapi/utility/completion_callback_factory.h"
21 // Timeout to wait for some action to complete.
22 extern const int kActionTimeoutMs
;
24 const PPB_Testing_Private
* GetTestingInterface();
25 std::string
ReportError(const char* method
, int32_t error
);
26 void PlatformSleep(int duration_ms
);
27 bool GetLocalHostPort(PP_Instance instance
, std::string
* host
, uint16_t* port
);
29 uint16_t ConvertFromNetEndian16(uint16_t x
);
30 uint16_t ConvertToNetEndian16(uint16_t x
);
31 bool EqualNetAddress(const pp::NetAddress
& addr1
, const pp::NetAddress
& addr2
);
32 // Only returns the first address if there are more than one available.
33 bool ResolveHost(PP_Instance instance
,
34 const std::string
& host
,
36 pp::NetAddress
* addr
);
37 bool ReplacePort(PP_Instance instance
,
38 const pp::NetAddress
& input_addr
,
40 pp::NetAddress
* output_addr
);
41 uint16_t GetPort(const pp::NetAddress
& addr
);
43 // NestedEvent allows you to run a nested MessageLoop and wait for a particular
44 // event to complete. For example, you can use it to wait for a callback on a
45 // PPP interface, which will "Signal" the event and make the loop quit.
46 // "Wait()" will return immediately if it has already been signalled. Otherwise,
47 // it will run a nested message loop (using PPB_Testing.RunMessageLoop) and will
48 // return only after it has been signalled.
50 // std::string TestFullscreen::TestNormalToFullscreen() {
51 // pp::Fullscreen screen_mode(instance);
52 // screen_mode.SetFullscreen(true);
53 // SimulateUserGesture();
54 // // Let DidChangeView run in a nested message loop.
55 // nested_event_.Wait();
59 // void TestFullscreen::DidChangeView(const pp::View& view) {
60 // nested_event_.Signal();
63 // All methods except Signal and PostSignal must be invoked on the main thread.
64 // It's OK to signal from a background thread, so you can (for example) Signal()
65 // from the Audio thread.
68 explicit NestedEvent(PP_Instance instance
)
69 : instance_(instance
), waiting_(false), signalled_(false) {
71 // Run a nested message loop and wait until Signal() is called. If Signal()
72 // has already been called, return immediately without running a nested loop.
74 // Signal the NestedEvent. If Wait() has been called, quit the message loop.
75 // This can be called from any thread.
77 // Signal the NestedEvent in |wait_ms| milliseconds. This can be called from
79 void PostSignal(int32_t wait_ms
);
81 // Reset the NestedEvent so it can be used again.
84 void SignalOnMainThread();
85 static void SignalThunk(void* async_event
, int32_t result
);
87 PP_Instance instance_
;
90 // Disable copy and assign.
91 NestedEvent(const NestedEvent
&);
92 NestedEvent
& operator=(const NestedEvent
&);
95 enum CallbackType
{ PP_REQUIRED
, PP_OPTIONAL
, PP_BLOCKING
};
96 class TestCompletionCallback
{
100 virtual ~Delegate() {}
101 virtual void OnCallback(void* user_data
, int32_t result
) = 0;
103 explicit TestCompletionCallback(PP_Instance instance
);
104 // TODO(dmichael): Remove this constructor.
105 TestCompletionCallback(PP_Instance instance
, bool force_async
);
107 TestCompletionCallback(PP_Instance instance
, CallbackType callback_type
);
109 // Sets a Delegate instance. OnCallback() of this instance will be invoked
110 // when the completion callback is invoked.
111 // The delegate will be reset when Reset() or GetCallback() is called.
112 void SetDelegate(Delegate
* delegate
) { delegate_
= delegate
; }
114 // Wait for a result, given the return from the call which took this callback
115 // as a parameter. If |result| is PP_OK_COMPLETIONPENDING, WaitForResult will
116 // block until its callback has been invoked (in some cases, this will already
117 // have happened, and WaitForCallback can return immediately).
118 // For any other values, WaitForResult will simply set its internal "result_"
119 // field. To retrieve the final result of the operation (i.e., the result
120 // the callback has run, if necessary), call result(). You can call result()
121 // as many times as necessary until a new pp::CompletionCallback is retrieved.
123 // In some cases, you may want to check that the callback was invoked in the
124 // expected way (i.e., if the callback was "Required", then it should be
125 // invoked asynchronously). Within the body of a test (where returning a non-
126 // empty string indicates test failure), you can use the
127 // CHECK_CALLBACK_BEHAVIOR(callback) macro. From within a helper function,
128 // you can use failed() and errors().
130 // Example usage within a test:
131 // callback.WaitForResult(foo.DoSomething(callback));
132 // CHECK_CALLBACK_BEHAVIOR(callback);
133 // ASSERT_EQ(PP_OK, callback.result());
135 // Example usage within a helper function:
136 // void HelperFunction(std::string* error_message) {
137 // callback.WaitForResult(foo.DoSomething(callback));
138 // if (callback.failed())
139 // error_message->assign(callback.errors());
141 void WaitForResult(int32_t result
);
143 // Used when you expect to receive either synchronous completion with PP_OK
144 // or a PP_ERROR_ABORTED asynchronously.
146 // int32_t result = 0;
148 // pp::URLLoader temp(instance_);
149 // result = temp.Open(request, callback);
151 // callback.WaitForAbortResult(result);
152 // CHECK_CALLBACK_BEHAVIOR(callback);
153 void WaitForAbortResult(int32_t result
);
155 // Retrieve a pp::CompletionCallback for use in testing. This Reset()s the
156 // TestCompletionCallback.
157 pp::CompletionCallback
GetCallback();
159 bool failed() { return !errors_
.empty(); }
160 const std::string
& errors() { return errors_
; }
162 int32_t result() const { return result_
; }
164 // Reset so that this callback can be used again.
167 CallbackType
callback_type() { return callback_type_
; }
168 void set_target_loop(const pp::MessageLoop
& loop
) { target_loop_
= loop
; }
169 static void Handler(void* user_data
, int32_t result
);
172 void RunMessageLoop();
173 void QuitMessageLoop();
175 // Used to check that WaitForResult is only called once for each usage of the
177 bool wait_for_result_called_
;
178 // Indicates whether we have already been invoked.
180 // The last result received (or PP_OK_COMPLETIONCALLBACK if none).
182 CallbackType callback_type_
;
183 bool post_quit_task_
;
185 PP_Instance instance_
;
187 pp::MessageLoop target_loop_
;
190 template <typename OutputT
>
191 class TestCompletionCallbackWithOutput
{
193 explicit TestCompletionCallbackWithOutput(PP_Instance instance
)
194 : callback_(instance
),
196 pp::internal::CallbackOutputTraits
<OutputT
>::Initialize(&output_storage_
);
199 TestCompletionCallbackWithOutput(PP_Instance instance
, bool force_async
)
200 : callback_(instance
, force_async
),
202 pp::internal::CallbackOutputTraits
<OutputT
>::Initialize(&output_storage_
);
205 TestCompletionCallbackWithOutput(PP_Instance instance
,
206 CallbackType callback_type
)
207 : callback_(instance
, callback_type
),
209 pp::internal::CallbackOutputTraits
<OutputT
>::Initialize(&output_storage_
);
212 pp::CompletionCallbackWithOutput
<OutputT
> GetCallback();
214 return pp::internal::CallbackOutputTraits
<OutputT
>::StorageToPluginArg(
218 // Delegate functions to TestCompletionCallback
219 void SetDelegate(TestCompletionCallback::Delegate
* delegate
) {
220 callback_
.SetDelegate(delegate
);
222 void WaitForResult(int32_t result
) { callback_
.WaitForResult(result
); }
223 void WaitForAbortResult(int32_t result
) {
224 callback_
.WaitForAbortResult(result
);
226 bool failed() { return callback_
.failed(); }
227 const std::string
& errors() { return callback_
.errors(); }
228 int32_t result() const { return callback_
.result(); }
230 pp::internal::CallbackOutputTraits
<OutputT
>::Initialize(&output_storage_
);
231 return callback_
.Reset();
235 TestCompletionCallback callback_
;
236 typename
pp::CompletionCallbackWithOutput
<OutputT
>::OutputStorageType
240 template <typename OutputT
>
241 pp::CompletionCallbackWithOutput
<OutputT
>
242 TestCompletionCallbackWithOutput
<OutputT
>::GetCallback() {
244 if (callback_
.callback_type() == PP_BLOCKING
) {
245 pp::CompletionCallbackWithOutput
<OutputT
> cc(&output_storage_
);
249 callback_
.set_target_loop(pp::MessageLoop::GetCurrent());
250 pp::CompletionCallbackWithOutput
<OutputT
> cc(
251 &TestCompletionCallback::Handler
,
254 if (callback_
.callback_type() == PP_OPTIONAL
)
255 cc
.set_flags(PP_COMPLETIONCALLBACK_FLAG_OPTIONAL
);
259 // Verifies that the callback didn't record any errors. If the callback is run
260 // in an unexpected way (e.g., if it's invoked asynchronously when the call
261 // should have blocked), this returns an appropriate error string.
262 #define CHECK_CALLBACK_BEHAVIOR(callback) \
264 if ((callback).failed()) \
265 return MakeFailureMessage(__FILE__, __LINE__, \
266 (callback).errors().c_str()); \
270 * A set of macros to use for platform detection. These were largely copied
271 * from chromium's build_config.h.
273 #if defined(__APPLE__)
274 #define PPAPI_OS_MACOSX 1
275 #elif defined(ANDROID)
276 #define PPAPI_OS_ANDROID 1
277 #elif defined(__native_client__)
278 #define PPAPI_OS_NACL 1
279 #elif defined(__linux__)
280 #define PPAPI_OS_LINUX 1
281 #elif defined(_WIN32)
282 #define PPAPI_OS_WIN 1
283 #elif defined(__FreeBSD__)
284 #define PPAPI_OS_FREEBSD 1
285 #elif defined(__OpenBSD__)
286 #define PPAPI_OS_OPENBSD 1
288 #define PPAPI_OS_SOLARIS 1
290 #error Please add support for your platform in ppapi/tests/test_utils.h
293 /* These are used to determine POSIX-like implementations vs Windows. */
294 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
295 defined(__OpenBSD__) || defined(__sun) || defined(__native_client__)
296 #define PPAPI_POSIX 1
299 #endif // PPAPI_TESTS_TEST_UTILS_H_