diff options
author | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-08 18:55:16 +0000 |
---|---|---|
committer | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-08 18:55:16 +0000 |
commit | 77c3417c441feac4bdcbad88f5a6bbf7f77bfe8f (patch) | |
tree | de665a63fc4d8137139cb976a45a938fc02b0d72 /ppapi/tests | |
parent | e92a3618d401cd78886f0a404aa28a7e7947bc37 (diff) | |
download | chromium_src-77c3417c441feac4bdcbad88f5a6bbf7f77bfe8f.zip chromium_src-77c3417c441feac4bdcbad88f5a6bbf7f77bfe8f.tar.gz chromium_src-77c3417c441feac4bdcbad88f5a6bbf7f77bfe8f.tar.bz2 |
PPAPI: Make CompletionCallbacks work right on background threads.
Now, TrackedCallback::Run will:
-Run the callback immediately if it is on the right thread.
-PostRun to the correct thread if it is not.
This was preceded by https://chromiumcodereview.appspot.com/10909244/, which removed ClearAndRun and does some other little cleanups to TrackedCallback to make it usable on background threads.
BUG=92909
Review URL: https://chromiumcodereview.appspot.com/10910099
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@166719 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/tests')
-rw-r--r-- | ppapi/tests/test_case.h | 25 | ||||
-rw-r--r-- | ppapi/tests/test_utils.cc | 37 | ||||
-rw-r--r-- | ppapi/tests/test_utils.h | 4 |
3 files changed, 57 insertions, 9 deletions
diff --git a/ppapi/tests/test_case.h b/ppapi/tests/test_case.h index 2cf2ddf..aa35046 100644 --- a/ppapi/tests/test_case.h +++ b/ppapi/tests/test_case.h @@ -122,11 +122,12 @@ class TestCase { "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. + // supported in-process). For in-process, just consider it a pass. if (!testing_interface_->IsOutOfProcess()) return std::string(); + pp::MessageLoop_Dev background_loop(instance_); ThreadedTestRunner<T> runner(instance_->pp_instance(), - static_cast<T*>(this), test_to_run); + static_cast<T*>(this), test_to_run, background_loop); RunOnThreadInternal(&ThreadedTestRunner<T>::ThreadFunction, &runner, testing_interface_); return runner.result(); @@ -162,10 +163,12 @@ class TestCase { typedef std::string(T::*TestMethodType)(); ThreadedTestRunner(PP_Instance instance, T* test_case, - TestMethodType test_to_run) + TestMethodType test_to_run, + pp::MessageLoop_Dev loop) : instance_(instance), test_case_(test_case), - test_to_run_(test_to_run) { + test_to_run_(test_to_run), + loop_(loop) { } const std::string& result() { return result_; } static void ThreadFunction(void* runner) { @@ -174,9 +177,11 @@ class TestCase { private: void Run() { - // TODO(dmichael): Create and attach a pp::MessageLoop for this thread so - // nested loops work. + PP_DCHECK(PP_OK == loop_.AttachToCurrentThread()); result_ = (test_case_->*test_to_run_)(); + // Now give the loop a chance to clean up. + loop_.PostQuit(true /* should_destroy */); + loop_.Run(); // Tell the main thread to quit its nested message loop, now that the test // is complete. TestCase::QuitMainMessageLoop(instance_); @@ -186,6 +191,7 @@ class TestCase { PP_Instance instance_; T* test_case_; TestMethodType test_to_run_; + pp::MessageLoop_Dev loop_; }; // The internals for RunOnThread. This allows us to avoid including @@ -275,6 +281,12 @@ class TestCaseFactory { CheckResourcesAndVars(RunOnThread(&test_case::Test##name))); \ } +#define RUN_TEST_BACKGROUND(test_case, name, test_filter) \ + if (MatchesFilter(#name, test_filter)) { \ + instance_->LogTest(#name"Background", \ + CheckResourcesAndVars(RunOnThread(&test_case::Test##name))); \ + } + #define RUN_TEST_FORCEASYNC_AND_NOT(name, test_filter) \ do { \ RUN_TEST_FORCEASYNC(name, test_filter); \ @@ -287,6 +299,7 @@ class TestCaseFactory { RUN_TEST_FORCEASYNC(name, test_filter); \ RUN_TEST(name, test_filter); \ RUN_TEST_BLOCKING(test_case, name, test_filter); \ + RUN_TEST_BACKGROUND(test_case, name, test_filter); \ } while (false) #define RUN_TEST_WITH_REFERENCE_CHECK(name, test_filter) \ diff --git a/ppapi/tests/test_utils.cc b/ppapi/tests/test_utils.cc index 9776e34..20a8a81 100644 --- a/ppapi/tests/test_utils.cc +++ b/ppapi/tests/test_utils.cc @@ -13,6 +13,7 @@ #endif #include "ppapi/c/pp_errors.h" +#include "ppapi/cpp/dev/message_loop_dev.h" #include "ppapi/cpp/module.h" #include "ppapi/cpp/var.h" @@ -138,7 +139,7 @@ int32_t TestCompletionCallback::WaitForResult() { errors_.clear(); if (!have_result_) { post_quit_task_ = true; - GetTestingInterface()->RunMessageLoop(instance_); + RunMessageLoop(); } return result_; } @@ -150,7 +151,7 @@ void TestCompletionCallback::WaitForResult(int32_t result) { if (result == PP_OK_COMPLETIONPENDING) { if (!have_result_) { post_quit_task_ = true; - GetTestingInterface()->RunMessageLoop(instance_); + RunMessageLoop(); } if (callback_type_ == PP_BLOCKING) { errors_.assign( @@ -200,6 +201,7 @@ pp::CompletionCallback TestCompletionCallback::GetCallback() { return pp::CompletionCallback(); else if (callback_type_ == PP_OPTIONAL) flags = PP_COMPLETIONCALLBACK_FLAG_OPTIONAL; + target_loop_ = pp::MessageLoop_Dev::GetCurrent(); return pp::CompletionCallback(&TestCompletionCallback::Handler, const_cast<TestCompletionCallback*>(this), flags); @@ -229,7 +231,36 @@ void TestCompletionCallback::Handler(void* user_data, int32_t result) { callback->delegate_->OnCallback(user_data, result); if (callback->post_quit_task_) { callback->post_quit_task_ = false; - GetTestingInterface()->QuitMessageLoop(callback->instance_); + callback->QuitMessageLoop(); + } + if (callback->target_loop_ != pp::MessageLoop_Dev::GetCurrent()) { + // Note, in-process, loop_ and GetCurrent() will both be NULL, so should + // still be equal. + callback->errors_.assign( + ReportError("TestCompletionCallback: Callback ran on the wrong message " + "loop!", + result)); } } +void TestCompletionCallback::RunMessageLoop() { + pp::MessageLoop_Dev loop(pp::MessageLoop_Dev::GetCurrent()); + // If we don't have a message loop, we're probably running in process, where + // PPB_MessageLoop is not supported. Just use the Testing message loop. + if (loop.is_null() || loop == pp::MessageLoop_Dev::GetForMainThread()) + GetTestingInterface()->RunMessageLoop(instance_); + else + loop.Run(); +} + +void TestCompletionCallback::QuitMessageLoop() { + pp::MessageLoop_Dev loop(pp::MessageLoop_Dev::GetCurrent()); + // If we don't have a message loop, we're probably running in process, where + // PPB_MessageLoop is not supported. Just use the Testing message loop. + if (loop.is_null() || loop == pp::MessageLoop_Dev::GetForMainThread()) { + GetTestingInterface()->QuitMessageLoop(instance_); + } else { + const bool should_quit = false; + loop.PostQuit(should_quit); + } +} diff --git a/ppapi/tests/test_utils.h b/ppapi/tests/test_utils.h index ab87dd3..60f7fc4 100644 --- a/ppapi/tests/test_utils.h +++ b/ppapi/tests/test_utils.h @@ -11,6 +11,7 @@ #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_stdint.h" #include "ppapi/cpp/completion_callback.h" +#include "ppapi/cpp/dev/message_loop_dev.h" #include "ppapi/utility/completion_callback_factory.h" // Timeout to wait for some action to complete. @@ -152,6 +153,8 @@ class TestCompletionCallback { private: static void Handler(void* user_data, int32_t result); + void RunMessageLoop(); + void QuitMessageLoop(); // Used to check that WaitForResult is only called once for each usage of the // callback. @@ -166,6 +169,7 @@ class TestCompletionCallback { unsigned run_count_; PP_Instance instance_; Delegate* delegate_; + pp::MessageLoop_Dev target_loop_; }; // Verifies that the callback didn't record any errors. If the callback is run |