1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ppapi/tests/test_message_loop.h" 6 7 #include "ppapi/c/pp_macros.h" 8 #include "ppapi/cpp/core.h" 9 #include "ppapi/cpp/logging.h" 10 #include "ppapi/cpp/message_loop.h" 11 #include "ppapi/cpp/module.h" 12 #include "ppapi/tests/testing_instance.h" 13 #include "ppapi/utility/threading/simple_thread.h" 14 15 REGISTER_TEST_CASE(MessageLoop); 16 17 TestMessageLoop::TestMessageLoop(TestingInstance* instance) 18 : TestCase(instance), 19 param_(kInvalid), 20 PP_ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), 21 main_loop_task_ran_(instance->pp_instance()) { 22 } 23 24 TestMessageLoop::~TestMessageLoop() { 25 } 26 27 void TestMessageLoop::RunTests(const std::string& filter) { 28 RUN_TEST(Basics, filter); 29 RUN_TEST(Post, filter); 30 } 31 32 std::string TestMessageLoop::TestBasics() { 33 // The main thread message loop should be valid, and equal to the "current" 34 // one. 35 ASSERT_NE(0, pp::MessageLoop::GetForMainThread().pp_resource()); 36 ASSERT_EQ(pp::MessageLoop::GetForMainThread().pp_resource(), 37 pp::MessageLoop::GetCurrent().pp_resource()); 38 39 // We shouldn't be able to attach a new loop to the main thread. 40 pp::MessageLoop loop(instance_); 41 ASSERT_EQ(PP_ERROR_INPROGRESS, loop.AttachToCurrentThread()); 42 43 // Nested loops aren't allowed. 44 ASSERT_EQ(PP_ERROR_INPROGRESS, 45 pp::MessageLoop::GetForMainThread().Run()); 46 47 // We can't run on a loop that isn't attached to a thread. 48 ASSERT_EQ(PP_ERROR_WRONG_THREAD, loop.Run()); 49 50 PASS(); 51 } 52 53 std::string TestMessageLoop::TestPost() { 54 // Make sure we can post a task from the main thread back to the main thread. 55 pp::MessageLoop::GetCurrent().PostWork(callback_factory_.NewCallback( 56 &TestMessageLoop::SetParamAndQuitTask, kMainToMain)); 57 main_loop_task_ran_.Wait(); 58 ASSERT_EQ(param_, kMainToMain); 59 main_loop_task_ran_.Reset(); 60 61 pp::SimpleThread thread(instance_); 62 // Post a task before the thread is started, to make sure it is run. 63 // TODO(dmichael): CompletionCallbackFactory is not 100% thread safe for 64 // posting tasks to a thread other than where the factory was created. It 65 // should be OK for this test, since we know that the 66 // CompletionCallbackFactory and its target object outlive all callbacks. But 67 // developers are likely to misuse CompletionCallbackFactory. Maybe we should 68 // make it safe to use a callback on another thread? 69 thread.message_loop().PostWork(callback_factory_.NewCallback( 70 &TestMessageLoop::EchoParamToMainTask, kBeforeStart)); 71 ASSERT_TRUE(thread.Start()); 72 main_loop_task_ran_.Wait(); 73 ASSERT_EQ(param_, kBeforeStart); 74 main_loop_task_ran_.Reset(); 75 76 // Now post another one after start. This is the more normal case. 77 78 // Nested loops aren't allowed. 79 ASSERT_EQ(PP_ERROR_INPROGRESS, 80 pp::MessageLoop::GetForMainThread().Run()); 81 thread.message_loop().PostWork(callback_factory_.NewCallback( 82 &TestMessageLoop::EchoParamToMainTask, kAfterStart)); 83 main_loop_task_ran_.Wait(); 84 ASSERT_EQ(param_, kAfterStart); 85 main_loop_task_ran_.Reset(); 86 87 // Quit and join the thread. 88 ASSERT_TRUE(thread.Join()); 89 90 PASS(); 91 } 92 93 void TestMessageLoop::SetParamAndQuitTask(int32_t result, TestParam param) { 94 PP_DCHECK(result == PP_OK); 95 param_ = param; 96 main_loop_task_ran_.Signal(); 97 } 98 99 void TestMessageLoop::EchoParamToMainTask(int32_t result, TestParam param) { 100 PP_DCHECK(result == PP_OK); 101 pp::MessageLoop::GetForMainThread().PostWork( 102 callback_factory_.NewCallback( 103 &TestMessageLoop::SetParamAndQuitTask, param)); 104 } 105 106