Chromium Code Reviews| 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) \ |