Index: ppapi/tests/test_utils.h |
diff --git a/ppapi/tests/test_utils.h b/ppapi/tests/test_utils.h |
index 8cff24e15f172e2f2f84759fc9223341ed675005..1e2ec369316475accbd41d986e2a22f40d0d1bb0 100644 |
--- a/ppapi/tests/test_utils.h |
+++ b/ppapi/tests/test_utils.h |
@@ -1,4 +1,4 @@ |
-// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
@@ -11,6 +11,7 @@ |
#include "ppapi/c/pp_instance.h" |
#include "ppapi/c/pp_stdint.h" |
#include "ppapi/cpp/completion_callback.h" |
+#include "ppapi/utility/completion_callback_factory.h" |
// Timeout to wait for some action to complete. |
extern const int kActionTimeoutMs; |
@@ -20,36 +21,149 @@ std::string ReportError(const char* method, int32_t error); |
void PlatformSleep(int duration_ms); |
bool GetLocalHostPort(PP_Instance instance, std::string* host, uint16_t* port); |
+// NestedEvent allows you to run a nested MessageLoop and wait for a particular |
+// event to complete. For example, you can use it to wait for a callback on a |
+// PPP interface, which will "Signal" the event and make the loop quit. |
+// "Wait()" will return immediately if it has already been signalled. Otherwise, |
+// it will run a nested message loop (using PPB_Testing.RunMessageLoop) and will |
+// return only after it has been signalled. |
+// Example: |
+// std::string TestFullscreen::TestNormalToFullscreen() { |
+// pp::Fullscreen screen_mode(instance); |
+// screen_mode.SetFullscreen(true); |
+// SimulateUserGesture(); |
+// // Let DidChangeView run in a nested message loop. |
+// nested_event_.Wait(); |
+// Pass(); |
+// } |
+// |
+// void TestFullscreen::DidChangeView(const pp::View& view) { |
+// nested_event_.Signal(); |
+// } |
+class NestedEvent { |
+ public: |
+ explicit NestedEvent(PP_Instance instance) |
+ : instance_(instance), waiting_(false), signalled_(false) { |
+ } |
+ // Run a nested message loop and wait until Signal() is called. If Signal() |
+ // has already been called, return immediately without running a nested loop. |
+ void Wait(); |
+ // Signal the NestedEvent. If Wait() has been called, quit the message loop. |
+ void Signal(); |
+ private: |
+ PP_Instance instance_; |
+ bool waiting_; |
+ bool signalled_; |
+ // Disable copy and assign. |
+ NestedEvent(const NestedEvent&); |
+ NestedEvent& operator=(const NestedEvent&); |
+}; |
+ |
+enum CallbackType { PP_REQUIRED, PP_OPTIONAL, PP_BLOCKING }; |
class TestCompletionCallback { |
public: |
- TestCompletionCallback(PP_Instance instance); |
+ explicit TestCompletionCallback(PP_Instance instance); |
+ // TODO(dmichael): Remove this constructor. |
TestCompletionCallback(PP_Instance instance, bool force_async); |
+ TestCompletionCallback(PP_Instance instance, CallbackType callback_type); |
+ |
// Waits for the callback to be called and returns the |
// result. Returns immediately if the callback was previously called |
// and the result wasn't returned (i.e. each result value received |
// by the callback is returned by WaitForResult() once and only |
- // once). |
+ // once). DEPRECATED: Please use the one below. |
+ // TODO(dmichael): Remove this one when all the tests are updated. |
int32_t WaitForResult(); |
- operator pp::CompletionCallback() const; |
+ // Wait for a result, given the return from the call which took this callback |
+ // as a parameter. If |result| is PP_OK_COMPLETIONPENDING, WaitForResult will |
+ // block until its callback has been invoked (in some cases, this will already |
+ // have happened, and WaitForCallback can return immediately). |
+ // For any other values, WaitForResult will simply set its internal "result_" |
+ // field. To retrieve the final result of the operation (i.e., the result |
+ // the callback has run, if necessary), call result(). You can call result() |
+ // as many times as necessary until a new pp::CompletionCallback is retrieved. |
+ // |
+ // In some cases, you may want to check that the callback was invoked in the |
+ // expected way (i.e., if the callback was "Required", then it should be |
+ // invoked asynchronously). Within the body of a test (where returning a non- |
+ // empty string indicates test failure), you can use the |
+ // CHECK_CALLBACK_BEHAVIOR(callback) macro. From within a helper function, |
+ // you can use failed() and errors(). |
+ // |
+ // Example usage within a test: |
+ // callback.WaitForResult(foo.DoSomething(callback)); |
+ // CHECK_CALLBACK_BEHAVIOR(callback); |
+ // ASSERT_EQ(PP_OK, callback.result()); |
+ // |
+ // Example usage within a helper function: |
+ // void HelperFunction(std::string* error_message) { |
+ // callback.WaitForResult(foo.DoSomething(callback)); |
+ // if (callback.failed()) |
+ // error_message->assign(callback.errors()); |
+ // } |
+ void WaitForResult(int32_t result); |
+ // Used when you expect to receive either synchronous completion with PP_OK |
+ // or a PP_ERROR_ABORTED asynchronously. |
+ // Example usage: |
+ // int32_t result = 0; |
+ // { |
+ // pp::URLLoader temp(instance_); |
+ // result = temp.Open(request, callback); |
+ // } |
+ // callback.WaitForAbortResult(result); |
+ // CHECK_CALLBACK_BEHAVIOR(callback); |
+ void WaitForAbortResult(int32_t result); |
+ |
+ // Retrieve a pp::CompletionCallback for use in testing. This Reset()s the |
+ // TestCompletionCallback. |
+ pp::CompletionCallback GetCallback(); |
+ operator pp::CompletionCallback() { |
+ return GetCallback(); |
+ } |
+ |
+ // TODO(dmichael): Remove run_count when all tests are updated. Most cases |
+ // that use this can simply use CHECK_CALLBACK_BEHAVIOR. |
unsigned run_count() const { return run_count_; } |
+ // TODO(dmichael): Remove this; tests should use Reset() instead. |
void reset_run_count() { run_count_ = 0; } |
+ bool failed() { return !errors_.empty(); } |
+ const std::string& errors() { return errors_; } |
+ |
int32_t result() const { return result_; } |
+ // Reset so that this callback can be used again. |
+ void Reset(); |
+ |
private: |
static void Handler(void* user_data, int32_t result); |
+ // Used to check that WaitForResult is only called once for each usage of the |
+ // callback. |
+ bool wait_for_result_called_; |
+ // Indicates whether we have already been invoked. |
bool have_result_; |
+ // The last result received (or PP_OK_COMPLETIONCALLBACK if none). |
int32_t result_; |
- bool force_async_; |
+ CallbackType callback_type_; |
bool post_quit_task_; |
+ std::string errors_; |
unsigned run_count_; |
PP_Instance instance_; |
}; |
+// Verifies that the callback didn't record any errors. If the callback is run |
+// in an unexpected way (e.g., if it's invoked asynchronously when the call |
+// should have blocked), this returns an appropriate error string. |
+#define CHECK_CALLBACK_BEHAVIOR(callback) \ |
+do { \ |
+ if ((callback).failed()) \ |
+ return (callback).errors(); \ |
+} while (false) |
+ |
/* |
* A set of macros to use for platform detection. These were largely copied |
* from chromium's build_config.h. |
@@ -71,7 +185,7 @@ class TestCompletionCallback { |
#elif defined(__sun) |
#define PPAPI_OS_SOLARIS 1 |
#else |
-#error Please add support for your platform in ppapi/c/pp_macros.h. |
+#error Please add support for your platform in ppapi/tests/test_utils.h |
#endif |
/* These are used to determine POSIX-like implementations vs Windows. */ |