1 // Copyright 2013 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 "mojo/public/utility/run_loop.h" 6 7 #include "base/basictypes.h" 8 #include "base/compiler_specific.h" 9 #include "mojo/public/system/core_cpp.h" 10 #include "mojo/public/tests/test_support.h" 11 #include "mojo/public/utility/run_loop_handler.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 namespace mojo { 15 namespace utility { 16 namespace { 17 18 class TestRunLoopHandler : public RunLoopHandler { 19 public: 20 TestRunLoopHandler() 21 : ready_count_(0), 22 error_count_(0), 23 last_error_result_(MOJO_RESULT_OK) { 24 } 25 virtual ~TestRunLoopHandler() {} 26 27 void clear_ready_count() { ready_count_ = 0; } 28 int ready_count() const { return ready_count_; } 29 30 void clear_error_count() { error_count_ = 0; } 31 int error_count() const { return error_count_; } 32 33 MojoResult last_error_result() const { return last_error_result_; } 34 35 // RunLoopHandler: 36 virtual void OnHandleReady(const Handle& handle) OVERRIDE { 37 ready_count_++; 38 } 39 virtual void OnHandleError(const Handle& handle, MojoResult result) OVERRIDE { 40 error_count_++; 41 last_error_result_ = result; 42 } 43 44 private: 45 int ready_count_; 46 int error_count_; 47 MojoResult last_error_result_; 48 49 DISALLOW_COPY_AND_ASSIGN(TestRunLoopHandler); 50 }; 51 52 class RunLoopTest : public testing::Test { 53 public: 54 RunLoopTest() {} 55 56 virtual void SetUp() OVERRIDE { 57 Test::SetUp(); 58 RunLoop::SetUp(); 59 } 60 virtual void TearDown() OVERRIDE { 61 RunLoop::TearDown(); 62 Test::TearDown(); 63 } 64 65 private: 66 DISALLOW_COPY_AND_ASSIGN(RunLoopTest); 67 }; 68 69 // Trivial test to verify Run() with no added handles returns. 70 TEST_F(RunLoopTest, ExitsWithNoHandles) { 71 RunLoop run_loop; 72 run_loop.Run(); 73 } 74 75 class RemoveOnReadyRunLoopHandler : public TestRunLoopHandler { 76 public: 77 RemoveOnReadyRunLoopHandler() : run_loop_(NULL) { 78 } 79 virtual ~RemoveOnReadyRunLoopHandler() {} 80 81 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } 82 83 // RunLoopHandler: 84 virtual void OnHandleReady(const Handle& handle) OVERRIDE { 85 run_loop_->RemoveHandler(handle); 86 TestRunLoopHandler::OnHandleReady(handle); 87 } 88 89 private: 90 RunLoop* run_loop_; 91 92 DISALLOW_COPY_AND_ASSIGN(RemoveOnReadyRunLoopHandler); 93 }; 94 95 // Verifies RunLoop quits when no more handles (handle is removed when ready). 96 TEST_F(RunLoopTest, HandleReady) { 97 RemoveOnReadyRunLoopHandler handler; 98 test::MessagePipe test_pipe; 99 EXPECT_EQ(MOJO_RESULT_OK, test::WriteEmptyMessage(test_pipe.handle_1.get())); 100 101 RunLoop run_loop; 102 handler.set_run_loop(&run_loop); 103 run_loop.AddHandler(&handler, test_pipe.handle_0.get(), 104 MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE); 105 run_loop.Run(); 106 EXPECT_EQ(1, handler.ready_count()); 107 EXPECT_EQ(0, handler.error_count()); 108 } 109 110 class QuitOnReadyRunLoopHandler : public TestRunLoopHandler { 111 public: 112 QuitOnReadyRunLoopHandler() : run_loop_(NULL) { 113 } 114 virtual ~QuitOnReadyRunLoopHandler() {} 115 116 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } 117 118 // RunLoopHandler: 119 virtual void OnHandleReady(const Handle& handle) OVERRIDE { 120 run_loop_->Quit(); 121 TestRunLoopHandler::OnHandleReady(handle); 122 } 123 124 private: 125 RunLoop* run_loop_; 126 127 DISALLOW_COPY_AND_ASSIGN(QuitOnReadyRunLoopHandler); 128 }; 129 130 // Verifies Quit() from OnHandleReady() quits the loop. 131 TEST_F(RunLoopTest, QuitFromReady) { 132 QuitOnReadyRunLoopHandler handler; 133 test::MessagePipe test_pipe; 134 EXPECT_EQ(MOJO_RESULT_OK, test::WriteEmptyMessage(test_pipe.handle_1.get())); 135 136 RunLoop run_loop; 137 handler.set_run_loop(&run_loop); 138 run_loop.AddHandler(&handler, test_pipe.handle_0.get(), 139 MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE); 140 run_loop.Run(); 141 EXPECT_EQ(1, handler.ready_count()); 142 EXPECT_EQ(0, handler.error_count()); 143 } 144 145 class QuitOnErrorRunLoopHandler : public TestRunLoopHandler { 146 public: 147 QuitOnErrorRunLoopHandler() : run_loop_(NULL) { 148 } 149 virtual ~QuitOnErrorRunLoopHandler() {} 150 151 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } 152 153 // RunLoopHandler: 154 virtual void OnHandleError(const Handle& handle, MojoResult result) OVERRIDE { 155 run_loop_->Quit(); 156 TestRunLoopHandler::OnHandleError(handle, result); 157 } 158 159 private: 160 RunLoop* run_loop_; 161 162 DISALLOW_COPY_AND_ASSIGN(QuitOnErrorRunLoopHandler); 163 }; 164 165 // Verifies Quit() when the deadline is reached works. 166 TEST_F(RunLoopTest, QuitWhenDeadlineExpired) { 167 QuitOnErrorRunLoopHandler handler; 168 test::MessagePipe test_pipe; 169 RunLoop run_loop; 170 handler.set_run_loop(&run_loop); 171 run_loop.AddHandler(&handler, test_pipe.handle_0.get(), 172 MOJO_WAIT_FLAG_READABLE, 173 static_cast<MojoDeadline>(10000)); 174 run_loop.Run(); 175 EXPECT_EQ(0, handler.ready_count()); 176 EXPECT_EQ(1, handler.error_count()); 177 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, handler.last_error_result()); 178 } 179 180 TEST_F(RunLoopTest, Current) { 181 EXPECT_TRUE(RunLoop::current() == NULL); 182 { 183 RunLoop run_loop; 184 EXPECT_EQ(&run_loop, RunLoop::current()); 185 } 186 EXPECT_TRUE(RunLoop::current() == NULL); 187 } 188 189 } // namespace 190 } // namespace utility 191 } // namespace mojo 192