[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef PPAPI_TESTS_TEST_UTILS_H_ |
| 6 | #define PPAPI_TESTS_TEST_UTILS_H_ |
| 7 | |
| 8 | #include <string> |
| 9 | |
| 10 | #include "ppapi/c/dev/ppb_testing_dev.h" |
[email protected] | 7358d57 | 2011-02-15 18:44:40 | [diff] [blame] | 11 | #include "ppapi/c/pp_instance.h" |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 12 | #include "ppapi/c/pp_stdint.h" |
| 13 | #include "ppapi/cpp/completion_callback.h" |
[email protected] | d4ab9471 | 2012-11-15 21:01:23 | [diff] [blame] | 14 | #include "ppapi/cpp/message_loop.h" |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 15 | #include "ppapi/utility/completion_callback_factory.h" |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 16 | |
[email protected] | 3c149c6 | 2011-11-11 23:22:52 | [diff] [blame] | 17 | // Timeout to wait for some action to complete. |
| 18 | extern const int kActionTimeoutMs; |
| 19 | |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 20 | const PPB_Testing_Dev* GetTestingInterface(); |
| 21 | std::string ReportError(const char* method, int32_t error); |
[email protected] | 3c149c6 | 2011-11-11 23:22:52 | [diff] [blame] | 22 | void PlatformSleep(int duration_ms); |
[email protected] | 961e897 | 2011-12-15 15:29:19 | [diff] [blame] | 23 | bool GetLocalHostPort(PP_Instance instance, std::string* host, uint16_t* port); |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 24 | |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 25 | // NestedEvent allows you to run a nested MessageLoop and wait for a particular |
| 26 | // event to complete. For example, you can use it to wait for a callback on a |
| 27 | // PPP interface, which will "Signal" the event and make the loop quit. |
| 28 | // "Wait()" will return immediately if it has already been signalled. Otherwise, |
| 29 | // it will run a nested message loop (using PPB_Testing.RunMessageLoop) and will |
| 30 | // return only after it has been signalled. |
| 31 | // Example: |
| 32 | // std::string TestFullscreen::TestNormalToFullscreen() { |
| 33 | // pp::Fullscreen screen_mode(instance); |
| 34 | // screen_mode.SetFullscreen(true); |
| 35 | // SimulateUserGesture(); |
| 36 | // // Let DidChangeView run in a nested message loop. |
| 37 | // nested_event_.Wait(); |
| 38 | // Pass(); |
| 39 | // } |
| 40 | // |
| 41 | // void TestFullscreen::DidChangeView(const pp::View& view) { |
| 42 | // nested_event_.Signal(); |
| 43 | // } |
| 44 | class NestedEvent { |
| 45 | public: |
| 46 | explicit NestedEvent(PP_Instance instance) |
| 47 | : instance_(instance), waiting_(false), signalled_(false) { |
| 48 | } |
| 49 | // Run a nested message loop and wait until Signal() is called. If Signal() |
| 50 | // has already been called, return immediately without running a nested loop. |
| 51 | void Wait(); |
| 52 | // Signal the NestedEvent. If Wait() has been called, quit the message loop. |
| 53 | void Signal(); |
[email protected] | 6de743a | 2012-08-30 20:03:22 | [diff] [blame] | 54 | // Reset the NestedEvent so it can be used again. |
| 55 | void Reset(); |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 56 | private: |
| 57 | PP_Instance instance_; |
| 58 | bool waiting_; |
| 59 | bool signalled_; |
| 60 | // Disable copy and assign. |
| 61 | NestedEvent(const NestedEvent&); |
| 62 | NestedEvent& operator=(const NestedEvent&); |
| 63 | }; |
| 64 | |
| 65 | enum CallbackType { PP_REQUIRED, PP_OPTIONAL, PP_BLOCKING }; |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 66 | class TestCompletionCallback { |
| 67 | public: |
[email protected] | cc2386c4 | 2012-06-29 04:41:42 | [diff] [blame] | 68 | class Delegate { |
| 69 | public: |
| 70 | virtual ~Delegate() {} |
| 71 | virtual void OnCallback(void* user_data, int32_t result) = 0; |
| 72 | }; |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 73 | explicit TestCompletionCallback(PP_Instance instance); |
| 74 | // TODO(dmichael): Remove this constructor. |
[email protected] | 917e86a | 2011-06-30 21:42:37 | [diff] [blame] | 75 | TestCompletionCallback(PP_Instance instance, bool force_async); |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 76 | |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 77 | TestCompletionCallback(PP_Instance instance, CallbackType callback_type); |
| 78 | |
[email protected] | cc2386c4 | 2012-06-29 04:41:42 | [diff] [blame] | 79 | // Sets a Delegate instance. OnCallback() of this instance will be invoked |
| 80 | // when the completion callback is invoked. |
| 81 | // The delegate will be reset when Reset() or GetCallback() is called. |
| 82 | void SetDelegate(Delegate* delegate) { delegate_ = delegate; } |
| 83 | |
[email protected] | 26d912d3 | 2011-05-02 17:28:10 | [diff] [blame] | 84 | // Waits for the callback to be called and returns the |
| 85 | // result. Returns immediately if the callback was previously called |
| 86 | // and the result wasn't returned (i.e. each result value received |
| 87 | // by the callback is returned by WaitForResult() once and only |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 88 | // once). DEPRECATED: Please use the one below. |
| 89 | // TODO(dmichael): Remove this one when all the tests are updated. |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 90 | int32_t WaitForResult(); |
| 91 | |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 92 | // Wait for a result, given the return from the call which took this callback |
| 93 | // as a parameter. If |result| is PP_OK_COMPLETIONPENDING, WaitForResult will |
| 94 | // block until its callback has been invoked (in some cases, this will already |
| 95 | // have happened, and WaitForCallback can return immediately). |
| 96 | // For any other values, WaitForResult will simply set its internal "result_" |
| 97 | // field. To retrieve the final result of the operation (i.e., the result |
| 98 | // the callback has run, if necessary), call result(). You can call result() |
| 99 | // as many times as necessary until a new pp::CompletionCallback is retrieved. |
| 100 | // |
| 101 | // In some cases, you may want to check that the callback was invoked in the |
| 102 | // expected way (i.e., if the callback was "Required", then it should be |
| 103 | // invoked asynchronously). Within the body of a test (where returning a non- |
| 104 | // empty string indicates test failure), you can use the |
| 105 | // CHECK_CALLBACK_BEHAVIOR(callback) macro. From within a helper function, |
| 106 | // you can use failed() and errors(). |
| 107 | // |
| 108 | // Example usage within a test: |
| 109 | // callback.WaitForResult(foo.DoSomething(callback)); |
| 110 | // CHECK_CALLBACK_BEHAVIOR(callback); |
| 111 | // ASSERT_EQ(PP_OK, callback.result()); |
| 112 | // |
| 113 | // Example usage within a helper function: |
| 114 | // void HelperFunction(std::string* error_message) { |
| 115 | // callback.WaitForResult(foo.DoSomething(callback)); |
| 116 | // if (callback.failed()) |
| 117 | // error_message->assign(callback.errors()); |
| 118 | // } |
| 119 | void WaitForResult(int32_t result); |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 120 | |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 121 | // Used when you expect to receive either synchronous completion with PP_OK |
| 122 | // or a PP_ERROR_ABORTED asynchronously. |
| 123 | // Example usage: |
| 124 | // int32_t result = 0; |
| 125 | // { |
| 126 | // pp::URLLoader temp(instance_); |
| 127 | // result = temp.Open(request, callback); |
| 128 | // } |
| 129 | // callback.WaitForAbortResult(result); |
| 130 | // CHECK_CALLBACK_BEHAVIOR(callback); |
| 131 | void WaitForAbortResult(int32_t result); |
| 132 | |
| 133 | // Retrieve a pp::CompletionCallback for use in testing. This Reset()s the |
| 134 | // TestCompletionCallback. |
| 135 | pp::CompletionCallback GetCallback(); |
| 136 | operator pp::CompletionCallback() { |
| 137 | return GetCallback(); |
| 138 | } |
| 139 | |
| 140 | // TODO(dmichael): Remove run_count when all tests are updated. Most cases |
| 141 | // that use this can simply use CHECK_CALLBACK_BEHAVIOR. |
[email protected] | 64264ef | 2010-12-21 00:45:43 | [diff] [blame] | 142 | unsigned run_count() const { return run_count_; } |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 143 | // TODO(dmichael): Remove this; tests should use Reset() instead. |
[email protected] | 64264ef | 2010-12-21 00:45:43 | [diff] [blame] | 144 | void reset_run_count() { run_count_ = 0; } |
| 145 | |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 146 | bool failed() { return !errors_.empty(); } |
| 147 | const std::string& errors() { return errors_; } |
| 148 | |
[email protected] | db567f2b | 2011-04-12 23:28:59 | [diff] [blame] | 149 | int32_t result() const { return result_; } |
| 150 | |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 151 | // Reset so that this callback can be used again. |
| 152 | void Reset(); |
| 153 | |
[email protected] | bcc801f | 2012-11-16 07:41:09 | [diff] [blame] | 154 | protected: |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 155 | static void Handler(void* user_data, int32_t result); |
[email protected] | 77c3417 | 2012-11-08 18:55:16 | [diff] [blame] | 156 | void RunMessageLoop(); |
| 157 | void QuitMessageLoop(); |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 158 | |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 159 | // Used to check that WaitForResult is only called once for each usage of the |
| 160 | // callback. |
| 161 | bool wait_for_result_called_; |
| 162 | // Indicates whether we have already been invoked. |
[email protected] | 26d912d3 | 2011-05-02 17:28:10 | [diff] [blame] | 163 | bool have_result_; |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 164 | // The last result received (or PP_OK_COMPLETIONCALLBACK if none). |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 165 | int32_t result_; |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 166 | CallbackType callback_type_; |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 167 | bool post_quit_task_; |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 168 | std::string errors_; |
[email protected] | 64264ef | 2010-12-21 00:45:43 | [diff] [blame] | 169 | unsigned run_count_; |
[email protected] | 7358d57 | 2011-02-15 18:44:40 | [diff] [blame] | 170 | PP_Instance instance_; |
[email protected] | cc2386c4 | 2012-06-29 04:41:42 | [diff] [blame] | 171 | Delegate* delegate_; |
[email protected] | d4ab9471 | 2012-11-15 21:01:23 | [diff] [blame] | 172 | pp::MessageLoop target_loop_; |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 173 | }; |
| 174 | |
[email protected] | bcc801f | 2012-11-16 07:41:09 | [diff] [blame] | 175 | template <typename OutputT> |
| 176 | class TestCompletionCallbackWithOutput : public TestCompletionCallback { |
| 177 | public: |
| 178 | explicit TestCompletionCallbackWithOutput(PP_Instance instance) : |
| 179 | TestCompletionCallback(instance) { |
| 180 | } |
[email protected] | 7878436 | 2012-12-11 09:49:13 | [diff] [blame] | 181 | |
| 182 | TestCompletionCallbackWithOutput(PP_Instance instance, bool force_async) : |
| 183 | TestCompletionCallback(instance, force_async) { |
| 184 | } |
[email protected] | bcc801f | 2012-11-16 07:41:09 | [diff] [blame] | 185 | |
| 186 | TestCompletionCallbackWithOutput(PP_Instance instance, |
| 187 | CallbackType callback_type) : |
| 188 | TestCompletionCallback(instance, callback_type) { |
| 189 | } |
| 190 | |
| 191 | pp::CompletionCallbackWithOutput<OutputT> GetCallbackWithOutput(); |
| 192 | operator pp::CompletionCallbackWithOutput<OutputT>() { |
| 193 | return GetCallbackWithOutput(); |
| 194 | } |
| 195 | |
| 196 | const OutputT& output() { return output_storage_.output(); } |
| 197 | |
| 198 | typename pp::CompletionCallbackWithOutput<OutputT>::OutputStorageType |
| 199 | output_storage_; |
| 200 | }; |
| 201 | |
| 202 | template <typename OutputT> |
| 203 | pp::CompletionCallbackWithOutput<OutputT> |
| 204 | TestCompletionCallbackWithOutput<OutputT>::GetCallbackWithOutput() { |
| 205 | Reset(); |
[email protected] | 7878436 | 2012-12-11 09:49:13 | [diff] [blame] | 206 | if (callback_type_ == PP_BLOCKING) { |
| 207 | pp::CompletionCallbackWithOutput<OutputT> cc( |
| 208 | &TestCompletionCallback::Handler, |
| 209 | this, |
| 210 | &output_storage_); |
| 211 | return cc; |
| 212 | } |
| 213 | |
[email protected] | bcc801f | 2012-11-16 07:41:09 | [diff] [blame] | 214 | target_loop_ = pp::MessageLoop::GetCurrent(); |
| 215 | pp::CompletionCallbackWithOutput<OutputT> cc( |
| 216 | &TestCompletionCallback::Handler, |
| 217 | this, |
| 218 | &output_storage_); |
| 219 | if (callback_type_ == PP_OPTIONAL) |
| 220 | cc.set_flags(PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 221 | return cc; |
| 222 | } |
| 223 | |
| 224 | |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 225 | // Verifies that the callback didn't record any errors. If the callback is run |
| 226 | // in an unexpected way (e.g., if it's invoked asynchronously when the call |
| 227 | // should have blocked), this returns an appropriate error string. |
| 228 | #define CHECK_CALLBACK_BEHAVIOR(callback) \ |
| 229 | do { \ |
| 230 | if ((callback).failed()) \ |
| 231 | return (callback).errors(); \ |
| 232 | } while (false) |
| 233 | |
[email protected] | 2059f3d | 2011-12-01 20:12:37 | [diff] [blame] | 234 | /* |
| 235 | * A set of macros to use for platform detection. These were largely copied |
| 236 | * from chromium's build_config.h. |
| 237 | */ |
| 238 | #if defined(__APPLE__) |
| 239 | #define PPAPI_OS_MACOSX 1 |
| 240 | #elif defined(ANDROID) |
| 241 | #define PPAPI_OS_ANDROID 1 |
| 242 | #elif defined(__native_client__) |
| 243 | #define PPAPI_OS_NACL 1 |
| 244 | #elif defined(__linux__) |
| 245 | #define PPAPI_OS_LINUX 1 |
| 246 | #elif defined(_WIN32) |
| 247 | #define PPAPI_OS_WIN 1 |
| 248 | #elif defined(__FreeBSD__) |
| 249 | #define PPAPI_OS_FREEBSD 1 |
| 250 | #elif defined(__OpenBSD__) |
| 251 | #define PPAPI_OS_OPENBSD 1 |
| 252 | #elif defined(__sun) |
| 253 | #define PPAPI_OS_SOLARIS 1 |
| 254 | #else |
[email protected] | 3ab6127 | 2012-04-07 00:09:08 | [diff] [blame] | 255 | #error Please add support for your platform in ppapi/tests/test_utils.h |
[email protected] | 2059f3d | 2011-12-01 20:12:37 | [diff] [blame] | 256 | #endif |
| 257 | |
| 258 | /* These are used to determine POSIX-like implementations vs Windows. */ |
| 259 | #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ |
| 260 | defined(__OpenBSD__) || defined(__sun) || defined(__native_client__) |
| 261 | #define PPAPI_POSIX 1 |
| 262 | #endif |
| 263 | |
[email protected] | de9bdd1 | 2010-11-04 00:36:22 | [diff] [blame] | 264 | #endif // PPAPI_TESTS_TEST_UTILS_H_ |