• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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"
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_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);
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 bool ReplacePort(PP_Instance instance,
38                  const pp::NetAddress& input_addr,
39                  uint16_t port,
40                  pp::NetAddress* output_addr);
41 uint16_t GetPort(const pp::NetAddress& addr);
42 
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.
49 // Example:
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();
56 //    Pass();
57 //  }
58 //
59 //  void TestFullscreen::DidChangeView(const pp::View& view) {
60 //    nested_event_.Signal();
61 //  }
62 //
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.
66 class NestedEvent {
67  public:
NestedEvent(PP_Instance instance)68   explicit NestedEvent(PP_Instance instance)
69       : instance_(instance), waiting_(false), signalled_(false) {
70   }
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.
73   void Wait();
74   // Signal the NestedEvent. If Wait() has been called, quit the message loop.
75   // This can be called from any thread.
76   void Signal();
77   // Signal the NestedEvent in |wait_ms| milliseconds. This can be called from
78   // any thread.
79   void PostSignal(int32_t wait_ms);
80 
81   // Reset the NestedEvent so it can be used again.
82   void Reset();
83  private:
84   void SignalOnMainThread();
85   static void SignalThunk(void* async_event, int32_t result);
86 
87   PP_Instance instance_;
88   bool waiting_;
89   bool signalled_;
90   // Disable copy and assign.
91   NestedEvent(const NestedEvent&);
92   NestedEvent& operator=(const NestedEvent&);
93 };
94 
95 enum CallbackType { PP_REQUIRED, PP_OPTIONAL, PP_BLOCKING };
96 class TestCompletionCallback {
97  public:
98   class Delegate {
99    public:
~Delegate()100     virtual ~Delegate() {}
101     virtual void OnCallback(void* user_data, int32_t result) = 0;
102   };
103   explicit TestCompletionCallback(PP_Instance instance);
104   // TODO(dmichael): Remove this constructor.
105   TestCompletionCallback(PP_Instance instance, bool force_async);
106 
107   TestCompletionCallback(PP_Instance instance, CallbackType callback_type);
108 
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.
SetDelegate(Delegate * delegate)112   void SetDelegate(Delegate* delegate) { delegate_ = delegate; }
113 
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.
122   //
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().
129   //
130   // Example usage within a test:
131   //  callback.WaitForResult(foo.DoSomething(callback));
132   //  CHECK_CALLBACK_BEHAVIOR(callback);
133   //  ASSERT_EQ(PP_OK, callback.result());
134   //
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());
140   //  }
141   void WaitForResult(int32_t result);
142 
143   // Used when you expect to receive either synchronous completion with PP_OK
144   // or a PP_ERROR_ABORTED asynchronously.
145   //  Example usage:
146   //  int32_t result = 0;
147   //  {
148   //    pp::URLLoader temp(instance_);
149   //    result = temp.Open(request, callback);
150   //  }
151   //  callback.WaitForAbortResult(result);
152   //  CHECK_CALLBACK_BEHAVIOR(callback);
153   void WaitForAbortResult(int32_t result);
154 
155   // Retrieve a pp::CompletionCallback for use in testing. This Reset()s the
156   // TestCompletionCallback.
157   pp::CompletionCallback GetCallback();
158 
failed()159   bool failed() { return !errors_.empty(); }
errors()160   const std::string& errors() { return errors_; }
161 
result()162   int32_t result() const { return result_; }
163 
164   // Reset so that this callback can be used again.
165   void Reset();
166 
callback_type()167   CallbackType callback_type() { return callback_type_; }
set_target_loop(const pp::MessageLoop & loop)168   void set_target_loop(const pp::MessageLoop& loop) { target_loop_ = loop; }
169   static void Handler(void* user_data, int32_t result);
170 
171  protected:
172   void RunMessageLoop();
173   void QuitMessageLoop();
174 
175   // Used to check that WaitForResult is only called once for each usage of the
176   // callback.
177   bool wait_for_result_called_;
178   // Indicates whether we have already been invoked.
179   bool have_result_;
180   // The last result received (or PP_OK_COMPLETIONCALLBACK if none).
181   int32_t result_;
182   CallbackType callback_type_;
183   bool post_quit_task_;
184   std::string errors_;
185   PP_Instance instance_;
186   Delegate* delegate_;
187   pp::MessageLoop target_loop_;
188 };
189 
190 template <typename OutputT>
191 class TestCompletionCallbackWithOutput {
192  public:
TestCompletionCallbackWithOutput(PP_Instance instance)193   explicit TestCompletionCallbackWithOutput(PP_Instance instance)
194       : callback_(instance),
195         output_storage_() {
196     pp::internal::CallbackOutputTraits<OutputT>::Initialize(&output_storage_);
197   }
198 
TestCompletionCallbackWithOutput(PP_Instance instance,bool force_async)199   TestCompletionCallbackWithOutput(PP_Instance instance, bool force_async)
200       : callback_(instance, force_async),
201         output_storage_() {
202     pp::internal::CallbackOutputTraits<OutputT>::Initialize(&output_storage_);
203   }
204 
TestCompletionCallbackWithOutput(PP_Instance instance,CallbackType callback_type)205   TestCompletionCallbackWithOutput(PP_Instance instance,
206                                    CallbackType callback_type)
207       : callback_(instance, callback_type),
208         output_storage_() {
209     pp::internal::CallbackOutputTraits<OutputT>::Initialize(&output_storage_);
210   }
211 
212   pp::CompletionCallbackWithOutput<OutputT> GetCallback();
output()213   OutputT output() {
214     return pp::internal::CallbackOutputTraits<OutputT>::StorageToPluginArg(
215         output_storage_);
216   }
217 
218   // Delegate functions to TestCompletionCallback
SetDelegate(TestCompletionCallback::Delegate * delegate)219   void SetDelegate(TestCompletionCallback::Delegate* delegate) {
220     callback_.SetDelegate(delegate);
221   }
WaitForResult(int32_t result)222   void WaitForResult(int32_t result) { callback_.WaitForResult(result); }
WaitForAbortResult(int32_t result)223   void WaitForAbortResult(int32_t result) {
224     callback_.WaitForAbortResult(result);
225   }
failed()226   bool failed() { return callback_.failed(); }
errors()227   const std::string& errors() { return callback_.errors(); }
result()228   int32_t result() const { return callback_.result(); }
Reset()229   void Reset() {
230     pp::internal::CallbackOutputTraits<OutputT>::Initialize(&output_storage_);
231     return callback_.Reset();
232   }
233 
234  private:
235   TestCompletionCallback callback_;
236   typename pp::CompletionCallbackWithOutput<OutputT>::OutputStorageType
237       output_storage_;
238 };
239 
240 template <typename OutputT>
241 pp::CompletionCallbackWithOutput<OutputT>
GetCallback()242 TestCompletionCallbackWithOutput<OutputT>::GetCallback() {
243   this->Reset();
244   if (callback_.callback_type() == PP_BLOCKING) {
245     pp::CompletionCallbackWithOutput<OutputT> cc(&output_storage_);
246     return cc;
247   }
248 
249   callback_.set_target_loop(pp::MessageLoop::GetCurrent());
250   pp::CompletionCallbackWithOutput<OutputT> cc(
251       &TestCompletionCallback::Handler,
252       this,
253       &output_storage_);
254   if (callback_.callback_type() == PP_OPTIONAL)
255     cc.set_flags(PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
256   return cc;
257 }
258 
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) \
263 do { \
264   if ((callback).failed()) \
265     return MakeFailureMessage(__FILE__, __LINE__, \
266                               (callback).errors().c_str()); \
267 } while (false)
268 
269 /*
270  * A set of macros to use for platform detection. These were largely copied
271  * from chromium's build_config.h.
272  */
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
287 #elif defined(__sun)
288 #define PPAPI_OS_SOLARIS 1
289 #else
290 #error Please add support for your platform in ppapi/tests/test_utils.h
291 #endif
292 
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
297 #endif
298 
299 #endif  // PPAPI_TESTS_TEST_UTILS_H_
300