Index: ppapi/tests/test_case.h |
diff --git a/ppapi/tests/test_case.h b/ppapi/tests/test_case.h |
index 297308489f58441da361e1dd3081ee4fb3c624c6..2cce0c1225280befa6d5c6bf18b1a41b7285b64c 100644 |
--- a/ppapi/tests/test_case.h |
+++ b/ppapi/tests/test_case.h |
@@ -12,9 +12,12 @@ |
#include "ppapi/c/pp_resource.h" |
#include "ppapi/c/dev/ppb_testing_dev.h" |
+#include "ppapi/cpp/dev/message_loop_dev.h" |
#include "ppapi/cpp/dev/scrollbar_dev.h" |
#include "ppapi/cpp/view.h" |
+#include "ppapi/tests/pp_thread.h" |
#include "ppapi/tests/test_utils.h" |
+#include "ppapi/tests/testing_instance.h" |
#if (defined __native_client__) |
#include "ppapi/cpp/var.h" |
@@ -78,6 +81,8 @@ class TestCase { |
const PPB_Testing_Dev* testing_interface() { return testing_interface_; } |
+ static void QuitMainMessageLoop(PP_Instance instance); |
+ |
protected: |
#if !(defined __native_client__) |
// Overridden by each test to supply a ScriptableObject corresponding to the |
@@ -104,12 +109,41 @@ class TestCase { |
// Check for leaked resources and vars at the end of the test. If any exist, |
// return a string with some information about the error. Otherwise, return |
// an empty string. |
- std::string CheckResourcesAndVars(); |
+ // |
+ // You should pass the error string from the test so far; if it is non-empty, |
+ // CheckResourcesAndVars will do nothing and return the same string. |
+ std::string CheckResourcesAndVars(std::string errors); |
+ |
+ // Run the given test method on a background thread and return the result. |
+ template <class T> |
+ std::string RunOnThread(std::string(T::*test_to_run)()) { |
+#ifdef ENABLE_PEPPER_THREADING |
+ if (!testing_interface_) { |
+ return "Testing blocking callbacks requires the testing interface. In " |
+ "Chrome, use the --enable-pepper-testing flag."; |
+ } |
+ // These tests are only valid if running out-of-process (threading is not |
+ // supported in-process). Just consider it a pass. |
+ if (!testing_interface_->IsOutOfProcess()) |
+ return std::string(); |
+ ThreadedTestRunner<T> runner(instance_->pp_instance(), |
+ static_cast<T*>(this), test_to_run); |
+ PP_ThreadType thread; |
+ PP_CreateThread(&thread, &ThreadedTestRunner<T>::ThreadFunction, &runner); |
+ // Run a message loop so pepper calls can be dispatched. The background |
+ // thread will make us Quit when it's done. |
+ testing_interface_->RunMessageLoop(instance_->pp_instance()); |
+ PP_JoinThread(thread); |
+ return runner.result(); |
+#else |
+ // If threading's not enabled, just treat it as success. |
+ return std::string(); |
+#endif |
+ } |
// Pointer to the instance that owns us. |
TestingInstance* instance_; |
- protected: |
// NULL unless InitTestingInterface is called. |
const PPB_Testing_Dev* testing_interface_; |
@@ -127,6 +161,40 @@ class TestCase { |
} |
private: |
+ template <class T> |
+ class ThreadedTestRunner { |
+ public: |
+ typedef std::string(T::*TestMethodType)(); |
+ explicit ThreadedTestRunner(PP_Instance instance, |
+ T* test_case, |
+ TestMethodType test_to_run) |
+ : instance_(instance), |
+ test_case_(test_case), |
+ test_to_run_(test_to_run) { |
+ } |
+ std::string result() { return result_; } |
+ static void ThreadFunction(void* runner) { |
+ static_cast<ThreadedTestRunner<T>*>(runner)->Run(); |
+ } |
+ |
+ private: |
+ void Run() { |
+ // TODO(dmichael): Create and attach a pp::MessageLoop for this thread so |
+ // nested loops work. |
+ result_ = (test_case_->*test_to_run_)(); |
+ // Tell the main thread to quit its nested message loop, now that the test |
+ // is complete. |
+ TestCase::QuitMainMessageLoop(instance_); |
+ } |
+ |
+ std::string result_; |
+ PP_Instance instance_; |
+ T* test_case_; |
+ TestMethodType test_to_run_; |
+ }; |
+ |
+ static void DoQuitMainMessageLoop(void* pp_instance, int32_t result); |
+ |
// Passed when creating completion callbacks in some tests. This determines |
// what kind of callback we use for the test. |
CallbackType callback_type_; |
@@ -184,12 +252,39 @@ class TestCaseFactory { |
#define RUN_TEST(name, test_filter) \ |
if (MatchesFilter(#name, test_filter)) { \ |
set_callback_type(PP_OPTIONAL); \ |
- std::string error_message = Test##name(); \ |
- if (error_message.empty()) \ |
- error_message = CheckResourcesAndVars(); \ |
- instance_->LogTest(#name, error_message); \ |
+ instance_->LogTest(#name, CheckResourcesAndVars(Test##name())); \ |
+ } |
+ |
+// Like RUN_TEST above but forces functions taking callbacks to complete |
+// asynchronously on success or error. |
+#define RUN_TEST_FORCEASYNC(name, test_filter) \ |
+ if (MatchesFilter(#name, test_filter)) { \ |
+ set_callback_type(PP_REQUIRED); \ |
+ instance_->LogTest(#name"ForceAsync", \ |
+ CheckResourcesAndVars(Test##name())); \ |
} |
+#define RUN_TEST_BLOCKING(test_case, name, test_filter) \ |
+ if (MatchesFilter(#name, test_filter)) { \ |
+ set_callback_type(PP_BLOCKING); \ |
+ instance_->LogTest(#name"Blocking", \ |
+ CheckResourcesAndVars(RunOnThread(&test_case::Test##name))); \ |
+ } |
+ |
+#define RUN_TEST_FORCEASYNC_AND_NOT(name, test_filter) \ |
+ do { \ |
+ RUN_TEST_FORCEASYNC(name, test_filter); \ |
+ RUN_TEST(name, test_filter); \ |
+ } while (false) |
+ |
+// Run a test with all possible callback types. |
+#define RUN_CALLBACK_TEST(test_case, name, test_filter) \ |
+ do { \ |
+ RUN_TEST_FORCEASYNC(name, test_filter); \ |
+ RUN_TEST(name, test_filter); \ |
+ RUN_TEST_BLOCKING(test_case, name, test_filter); \ |
+ } while (false) |
+ |
#define RUN_TEST_WITH_REFERENCE_CHECK(name, test_filter) \ |
if (MatchesFilter(#name, test_filter)) { \ |
set_callback_type(PP_OPTIONAL); \ |
@@ -204,21 +299,6 @@ class TestCaseFactory { |
instance_->LogTest(#name, error_message); \ |
} |
-// Like RUN_TEST above but forces functions taking callbacks to complete |
-// asynchronously on success or error. |
-#define RUN_TEST_FORCEASYNC(name, test_filter) \ |
- if (MatchesFilter(#name"ForceAsync", test_filter)) { \ |
dmichael (off chromium)
2012/04/19 20:02:00
Note the first parameter used to say '#name"ForceA
|
- set_callback_type(PP_REQUIRED); \ |
- instance_->LogTest(#name"ForceAsync", Test##name()); \ |
- } |
- |
-#define RUN_TEST_FORCEASYNC_AND_NOT(name, test_filter) \ |
- do { \ |
- RUN_TEST_FORCEASYNC(name, test_filter); \ |
- RUN_TEST(name, test_filter); \ |
- } while (false) |
- |
- |
// Helper macros for checking values in tests, and returning a location |
// description of the test fails. |
#define ASSERT_TRUE(cmd) \ |