| // 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. | |
| #include "ppapi/tests/test_message_loop.h" | |
| #include "ppapi/c/pp_macros.h" | |
| #include "ppapi/cpp/core.h" | |
| #include "ppapi/cpp/logging.h" | |
| #include "ppapi/cpp/message_loop.h" | |
| #include "ppapi/cpp/module.h" | |
| #include "ppapi/tests/testing_instance.h" | |
| #include "ppapi/utility/threading/simple_thread.h" | |
| REGISTER_TEST_CASE(MessageLoop); | |
| TestMessageLoop::TestMessageLoop(TestingInstance* instance) | |
| : TestCase(instance), | |
| param_(kInvalid), | |
| callback_factory_(this), | |
| main_loop_task_ran_(instance->pp_instance()) { | |
| } | |
| TestMessageLoop::~TestMessageLoop() { | |
| } | |
| void TestMessageLoop::RunTests(const std::string& filter) { | |
| RUN_TEST(Basics, filter); | |
| RUN_TEST(Post, filter); | |
| } | |
| std::string TestMessageLoop::TestBasics() { | |
| // The main thread message loop should be valid, and equal to the "current" | |
| // one. | |
| ASSERT_NE(0, pp::MessageLoop::GetForMainThread().pp_resource()); | |
| ASSERT_EQ(pp::MessageLoop::GetForMainThread().pp_resource(), | |
| pp::MessageLoop::GetCurrent().pp_resource()); | |
| // We shouldn't be able to attach a new loop to the main thread. | |
| pp::MessageLoop loop(instance_); | |
| ASSERT_EQ(PP_ERROR_INPROGRESS, loop.AttachToCurrentThread()); | |
| // Nested loops aren't allowed. | |
| ASSERT_EQ(PP_ERROR_INPROGRESS, | |
| pp::MessageLoop::GetForMainThread().Run()); | |
| // We can't run on a loop that isn't attached to a thread. | |
| ASSERT_EQ(PP_ERROR_WRONG_THREAD, loop.Run()); | |
| PASS(); | |
| } | |
| std::string TestMessageLoop::TestPost() { | |
| // Make sure we can post a task from the main thread back to the main thread. | |
| pp::MessageLoop::GetCurrent().PostWork(callback_factory_.NewCallback( | |
| &TestMessageLoop::SetParamAndQuitTask, kMainToMain)); | |
| main_loop_task_ran_.Wait(); | |
| ASSERT_EQ(param_, kMainToMain); | |
| main_loop_task_ran_.Reset(); | |
| pp::SimpleThread thread(instance_); | |
| // Post a task before the thread is started, to make sure it is run. | |
| // TODO(dmichael): CompletionCallbackFactory is not 100% thread safe for | |
| // posting tasks to a thread other than where the factory was created. It | |
| // should be OK for this test, since we know that the | |
| // CompletionCallbackFactory and its target object outlive all callbacks. But | |
| // developers are likely to misuse CompletionCallbackFactory. Maybe we should | |
| // make it safe to use a callback on another thread? | |
| thread.message_loop().PostWork(callback_factory_.NewCallback( | |
| &TestMessageLoop::EchoParamToMainTask, kBeforeStart)); | |
| ASSERT_TRUE(thread.Start()); | |
| main_loop_task_ran_.Wait(); | |
| ASSERT_EQ(param_, kBeforeStart); | |
| main_loop_task_ran_.Reset(); | |
| // Now post another one after start. This is the more normal case. | |
| // Nested loops aren't allowed. | |
| ASSERT_EQ(PP_ERROR_INPROGRESS, | |
| pp::MessageLoop::GetForMainThread().Run()); | |
| thread.message_loop().PostWork(callback_factory_.NewCallback( | |
| &TestMessageLoop::EchoParamToMainTask, kAfterStart)); | |
| main_loop_task_ran_.Wait(); | |
| ASSERT_EQ(param_, kAfterStart); | |
| main_loop_task_ran_.Reset(); | |
| // Quit and join the thread. | |
| ASSERT_TRUE(thread.Join()); | |
| PASS(); | |
| } | |
| void TestMessageLoop::SetParamAndQuitTask(int32_t result, TestParam param) { | |
| PP_DCHECK(result == PP_OK); | |
| param_ = param; | |
| main_loop_task_ran_.Signal(); | |
| } | |
| void TestMessageLoop::EchoParamToMainTask(int32_t result, TestParam param) { | |
| PP_DCHECK(result == PP_OK); | |
| pp::MessageLoop::GetForMainThread().PostWork( | |
| callback_factory_.NewCallback( | |
| &TestMessageLoop::SetParamAndQuitTask, param)); | |
| } | |