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. 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" 11 #include "ppapi/c/pp_instance.h" 12 #include "ppapi/c/pp_stdint.h" 13 #include "ppapi/cpp/completion_callback.h" 14 #include "ppapi/cpp/message_loop.h" 15 #include "ppapi/utility/completion_callback_factory.h" 16 17 namespace pp { 18 class NetAddress; 19 } 20 21 // Timeout to wait for some action to complete. 22 extern const int kActionTimeoutMs; 23 24 const PPB_Testing_Dev* 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); 28 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, 35 uint16_t port, 36 pp::NetAddress* addr); 37 38 // NestedEvent allows you to run a nested MessageLoop and wait for a particular 39 // event to complete. For example, you can use it to wait for a callback on a 40 // PPP interface, which will "Signal" the event and make the loop quit. 41 // "Wait()" will return immediately if it has already been signalled. Otherwise, 42 // it will run a nested message loop (using PPB_Testing.RunMessageLoop) and will 43 // return only after it has been signalled. 44 // Example: 45 // std::string TestFullscreen::TestNormalToFullscreen() { 46 // pp::Fullscreen screen_mode(instance); 47 // screen_mode.SetFullscreen(true); 48 // SimulateUserGesture(); 49 // // Let DidChangeView run in a nested message loop. 50 // nested_event_.Wait(); 51 // Pass(); 52 // } 53 // 54 // void TestFullscreen::DidChangeView(const pp::View& view) { 55 // nested_event_.Signal(); 56 // } 57 // 58 // All methods except Signal and PostSignal must be invoked on the main thread. 59 // It's OK to signal from a background thread, so you can (for example) Signal() 60 // from the Audio thread. 61 class NestedEvent { 62 public: 63 explicit NestedEvent(PP_Instance instance) 64 : instance_(instance), waiting_(false), signalled_(false) { 65 } 66 // Run a nested message loop and wait until Signal() is called. If Signal() 67 // has already been called, return immediately without running a nested loop. 68 void Wait(); 69 // Signal the NestedEvent. If Wait() has been called, quit the message loop. 70 // This can be called from any thread. 71 void Signal(); 72 // Signal the NestedEvent in |wait_ms| milliseconds. This can be called from 73 // any thread. 74 void PostSignal(int32_t wait_ms); 75 76 // Reset the NestedEvent so it can be used again. 77 void Reset(); 78 private: 79 void SignalOnMainThread(); 80 static void SignalThunk(void* async_event, int32_t result); 81 82 PP_Instance instance_; 83 bool waiting_; 84 bool signalled_; 85 // Disable copy and assign. 86 NestedEvent(const NestedEvent&); 87 NestedEvent& operator=(const NestedEvent&); 88 }; 89 90 enum CallbackType { PP_REQUIRED, PP_OPTIONAL, PP_BLOCKING }; 91 class TestCompletionCallback { 92 public: 93 class Delegate { 94 public: 95 virtual ~Delegate() {} 96 virtual void OnCallback(void* user_data, int32_t result) = 0; 97 }; 98 explicit TestCompletionCallback(PP_Instance instance); 99 // TODO(dmichael): Remove this constructor. 100 TestCompletionCallback(PP_Instance instance, bool force_async); 101 102 TestCompletionCallback(PP_Instance instance, CallbackType callback_type); 103 104 // Sets a Delegate instance. OnCallback() of this instance will be invoked 105 // when the completion callback is invoked. 106 // The delegate will be reset when Reset() or GetCallback() is called. 107 void SetDelegate(Delegate* delegate) { delegate_ = delegate; } 108 109 // Wait for a result, given the return from the call which took this callback 110 // as a parameter. If |result| is PP_OK_COMPLETIONPENDING, WaitForResult will 111 // block until its callback has been invoked (in some cases, this will already 112 // have happened, and WaitForCallback can return immediately). 113 // For any other values, WaitForResult will simply set its internal "result_" 114 // field. To retrieve the final result of the operation (i.e., the result 115 // the callback has run, if necessary), call result(). You can call result() 116 // as many times as necessary until a new pp::CompletionCallback is retrieved. 117 // 118 // In some cases, you may want to check that the callback was invoked in the 119 // expected way (i.e., if the callback was "Required", then it should be 120 // invoked asynchronously). Within the body of a test (where returning a non- 121 // empty string indicates test failure), you can use the 122 // CHECK_CALLBACK_BEHAVIOR(callback) macro. From within a helper function, 123 // you can use failed() and errors(). 124 // 125 // Example usage within a test: 126 // callback.WaitForResult(foo.DoSomething(callback)); 127 // CHECK_CALLBACK_BEHAVIOR(callback); 128 // ASSERT_EQ(PP_OK, callback.result()); 129 // 130 // Example usage within a helper function: 131 // void HelperFunction(std::string* error_message) { 132 // callback.WaitForResult(foo.DoSomething(callback)); 133 // if (callback.failed()) 134 // error_message->assign(callback.errors()); 135 // } 136 void WaitForResult(int32_t result); 137 138 // Used when you expect to receive either synchronous completion with PP_OK 139 // or a PP_ERROR_ABORTED asynchronously. 140 // Example usage: 141 // int32_t result = 0; 142 // { 143 // pp::URLLoader temp(instance_); 144 // result = temp.Open(request, callback); 145 // } 146 // callback.WaitForAbortResult(result); 147 // CHECK_CALLBACK_BEHAVIOR(callback); 148 void WaitForAbortResult(int32_t result); 149 150 // Retrieve a pp::CompletionCallback for use in testing. This Reset()s the 151 // TestCompletionCallback. 152 pp::CompletionCallback GetCallback(); 153 154 bool failed() { return !errors_.empty(); } 155 const std::string& errors() { return errors_; } 156 157 int32_t result() const { return result_; } 158 159 // Reset so that this callback can be used again. 160 void Reset(); 161 162 CallbackType callback_type() { return callback_type_; } 163 void set_target_loop(const pp::MessageLoop& loop) { target_loop_ = loop; } 164 static void Handler(void* user_data, int32_t result); 165 166 protected: 167 void RunMessageLoop(); 168 void QuitMessageLoop(); 169 170 // Used to check that WaitForResult is only called once for each usage of the 171 // callback. 172 bool wait_for_result_called_; 173 // Indicates whether we have already been invoked. 174 bool have_result_; 175 // The last result received (or PP_OK_COMPLETIONCALLBACK if none). 176 int32_t result_; 177 CallbackType callback_type_; 178 bool post_quit_task_; 179 std::string errors_; 180 PP_Instance instance_; 181 Delegate* delegate_; 182 pp::MessageLoop target_loop_; 183 }; 184 185 namespace internal { 186 187 template <typename OutputT, typename CallbackT> 188 class TestCompletionCallbackWithOutputBase { 189 public: 190 explicit TestCompletionCallbackWithOutputBase(PP_Instance instance) 191 : callback_(instance), 192 output_storage_() { 193 CallbackT::TraitsType::Initialize(&output_storage_); 194 } 195 196 TestCompletionCallbackWithOutputBase(PP_Instance instance, bool force_async) 197 : callback_(instance, force_async), 198 output_storage_() { 199 CallbackT::TraitsType::Initialize(&output_storage_); 200 } 201 202 TestCompletionCallbackWithOutputBase(PP_Instance instance, 203 CallbackType callback_type) 204 : callback_(instance, callback_type), 205 output_storage_() { 206 CallbackT::TraitsType::Initialize(&output_storage_); 207 } 208 209 CallbackT GetCallback(); 210 OutputT output() { 211 return CallbackT::TraitsType::StorageToPluginArg( 212 output_storage_); 213 } 214 215 // Delegate functions to TestCompletionCallback 216 void SetDelegate(TestCompletionCallback::Delegate* delegate) { 217 callback_.SetDelegate(delegate); 218 } 219 void WaitForResult(int32_t result) { callback_.WaitForResult(result); } 220 void WaitForAbortResult(int32_t result) { 221 callback_.WaitForAbortResult(result); 222 } 223 bool failed() { return callback_.failed(); } 224 const std::string& errors() { return callback_.errors(); } 225 int32_t result() const { return callback_.result(); } 226 void Reset() { 227 CallbackT::TraitsType::Initialize(&output_storage_); 228 return callback_.Reset(); 229 } 230 231 private: 232 TestCompletionCallback callback_; 233 typename CallbackT::OutputStorageType output_storage_; 234 }; 235 236 template <typename OutputT, typename CallbackT> 237 CallbackT 238 TestCompletionCallbackWithOutputBase<OutputT, CallbackT>::GetCallback() { 239 this->Reset(); 240 if (callback_.callback_type() == PP_BLOCKING) { 241 CallbackT cc(&output_storage_); 242 return cc; 243 } 244 245 callback_.set_target_loop(pp::MessageLoop::GetCurrent()); 246 CallbackT cc(&TestCompletionCallback::Handler, this, &output_storage_); 247 if (callback_.callback_type() == PP_OPTIONAL) 248 cc.set_flags(PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 249 return cc; 250 } 251 252 } // namespace internal 253 254 template <typename OutputT> 255 class TestCompletionCallbackWithOutput 256 : public internal::TestCompletionCallbackWithOutputBase< 257 OutputT, pp::CompletionCallbackWithOutput<OutputT> > { 258 public: 259 explicit TestCompletionCallbackWithOutput(PP_Instance instance) 260 : BaseType(instance) { 261 } 262 263 TestCompletionCallbackWithOutput(PP_Instance instance, bool force_async) 264 : BaseType(instance, force_async) { 265 } 266 267 TestCompletionCallbackWithOutput(PP_Instance instance, 268 CallbackType callback_type) 269 : BaseType(instance, callback_type) { 270 } 271 272 private: 273 typedef internal::TestCompletionCallbackWithOutputBase< 274 OutputT, pp::CompletionCallbackWithOutput<OutputT> > BaseType; 275 }; 276 277 template <typename OutputT> 278 class TestExtCompletionCallbackWithOutput 279 : public internal::TestCompletionCallbackWithOutputBase< 280 OutputT, pp::ext::ExtCompletionCallbackWithOutput<OutputT> > { 281 public: 282 explicit TestExtCompletionCallbackWithOutput(PP_Instance instance) 283 : BaseType(instance) { 284 } 285 286 TestExtCompletionCallbackWithOutput(PP_Instance instance, bool force_async) 287 : BaseType(instance, force_async) { 288 } 289 290 TestExtCompletionCallbackWithOutput(PP_Instance instance, 291 CallbackType callback_type) 292 : BaseType(instance, callback_type) { 293 } 294 295 private: 296 typedef internal::TestCompletionCallbackWithOutputBase< 297 OutputT, pp::ext::ExtCompletionCallbackWithOutput<OutputT> > BaseType; 298 }; 299 300 // Verifies that the callback didn't record any errors. If the callback is run 301 // in an unexpected way (e.g., if it's invoked asynchronously when the call 302 // should have blocked), this returns an appropriate error string. 303 #define CHECK_CALLBACK_BEHAVIOR(callback) \ 304 do { \ 305 if ((callback).failed()) \ 306 return MakeFailureMessage(__FILE__, __LINE__, \ 307 (callback).errors().c_str()); \ 308 } while (false) 309 310 /* 311 * A set of macros to use for platform detection. These were largely copied 312 * from chromium's build_config.h. 313 */ 314 #if defined(__APPLE__) 315 #define PPAPI_OS_MACOSX 1 316 #elif defined(ANDROID) 317 #define PPAPI_OS_ANDROID 1 318 #elif defined(__native_client__) 319 #define PPAPI_OS_NACL 1 320 #elif defined(__linux__) 321 #define PPAPI_OS_LINUX 1 322 #elif defined(_WIN32) 323 #define PPAPI_OS_WIN 1 324 #elif defined(__FreeBSD__) 325 #define PPAPI_OS_FREEBSD 1 326 #elif defined(__OpenBSD__) 327 #define PPAPI_OS_OPENBSD 1 328 #elif defined(__sun) 329 #define PPAPI_OS_SOLARIS 1 330 #else 331 #error Please add support for your platform in ppapi/tests/test_utils.h 332 #endif 333 334 /* These are used to determine POSIX-like implementations vs Windows. */ 335 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ 336 defined(__OpenBSD__) || defined(__sun) || defined(__native_client__) 337 #define PPAPI_POSIX 1 338 #endif 339 340 #endif // PPAPI_TESTS_TEST_UTILS_H_ 341