| // Copyright 2013 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 "mojo/public/utility/run_loop.h" |
| |
| #include "base/basictypes.h" |
| #include "base/compiler_specific.h" |
| #include "mojo/public/system/core_cpp.h" |
| #include "mojo/public/tests/test_support.h" |
| #include "mojo/public/utility/run_loop_handler.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace mojo { |
| namespace utility { |
| namespace { |
| |
| class TestRunLoopHandler : public RunLoopHandler { |
| public: |
| TestRunLoopHandler() |
| : ready_count_(0), |
| error_count_(0), |
| last_error_result_(MOJO_RESULT_OK) { |
| } |
| virtual ~TestRunLoopHandler() {} |
| |
| void clear_ready_count() { ready_count_ = 0; } |
| int ready_count() const { return ready_count_; } |
| |
| void clear_error_count() { error_count_ = 0; } |
| int error_count() const { return error_count_; } |
| |
| MojoResult last_error_result() const { return last_error_result_; } |
| |
| // RunLoopHandler: |
| virtual void OnHandleReady(const Handle& handle) OVERRIDE { |
| ready_count_++; |
| } |
| virtual void OnHandleError(const Handle& handle, MojoResult result) OVERRIDE { |
| error_count_++; |
| last_error_result_ = result; |
| } |
| |
| private: |
| int ready_count_; |
| int error_count_; |
| MojoResult last_error_result_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestRunLoopHandler); |
| }; |
| |
| class RunLoopTest : public testing::Test { |
| public: |
| RunLoopTest() {} |
| |
| virtual void SetUp() OVERRIDE { |
| Test::SetUp(); |
| RunLoop::SetUp(); |
| } |
| virtual void TearDown() OVERRIDE { |
| RunLoop::TearDown(); |
| Test::TearDown(); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(RunLoopTest); |
| }; |
| |
| // Trivial test to verify Run() with no added handles returns. |
| TEST_F(RunLoopTest, ExitsWithNoHandles) { |
| RunLoop run_loop; |
| run_loop.Run(); |
| } |
| |
| class RemoveOnReadyRunLoopHandler : public TestRunLoopHandler { |
| public: |
| RemoveOnReadyRunLoopHandler() : run_loop_(NULL) { |
| } |
| virtual ~RemoveOnReadyRunLoopHandler() {} |
| |
| void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } |
| |
| // RunLoopHandler: |
| virtual void OnHandleReady(const Handle& handle) OVERRIDE { |
| run_loop_->RemoveHandler(handle); |
| TestRunLoopHandler::OnHandleReady(handle); |
| } |
| |
| private: |
| RunLoop* run_loop_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RemoveOnReadyRunLoopHandler); |
| }; |
| |
| // Verifies RunLoop quits when no more handles (handle is removed when ready). |
| TEST_F(RunLoopTest, HandleReady) { |
| RemoveOnReadyRunLoopHandler handler; |
| test::MessagePipe test_pipe; |
| EXPECT_EQ(MOJO_RESULT_OK, test::WriteEmptyMessage(test_pipe.handle_1.get())); |
| |
| RunLoop run_loop; |
| handler.set_run_loop(&run_loop); |
| run_loop.AddHandler(&handler, test_pipe.handle_0.get(), |
| MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE); |
| run_loop.Run(); |
| EXPECT_EQ(1, handler.ready_count()); |
| EXPECT_EQ(0, handler.error_count()); |
| } |
| |
| class QuitOnReadyRunLoopHandler : public TestRunLoopHandler { |
| public: |
| QuitOnReadyRunLoopHandler() : run_loop_(NULL) { |
| } |
| virtual ~QuitOnReadyRunLoopHandler() {} |
| |
| void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } |
| |
| // RunLoopHandler: |
| virtual void OnHandleReady(const Handle& handle) OVERRIDE { |
| run_loop_->Quit(); |
| TestRunLoopHandler::OnHandleReady(handle); |
| } |
| |
| private: |
| RunLoop* run_loop_; |
| |
| DISALLOW_COPY_AND_ASSIGN(QuitOnReadyRunLoopHandler); |
| }; |
| |
| // Verifies Quit() from OnHandleReady() quits the loop. |
| TEST_F(RunLoopTest, QuitFromReady) { |
| QuitOnReadyRunLoopHandler handler; |
| test::MessagePipe test_pipe; |
| EXPECT_EQ(MOJO_RESULT_OK, test::WriteEmptyMessage(test_pipe.handle_1.get())); |
| |
| RunLoop run_loop; |
| handler.set_run_loop(&run_loop); |
| run_loop.AddHandler(&handler, test_pipe.handle_0.get(), |
| MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE); |
| run_loop.Run(); |
| EXPECT_EQ(1, handler.ready_count()); |
| EXPECT_EQ(0, handler.error_count()); |
| } |
| |
| class QuitOnErrorRunLoopHandler : public TestRunLoopHandler { |
| public: |
| QuitOnErrorRunLoopHandler() : run_loop_(NULL) { |
| } |
| virtual ~QuitOnErrorRunLoopHandler() {} |
| |
| void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } |
| |
| // RunLoopHandler: |
| virtual void OnHandleError(const Handle& handle, MojoResult result) OVERRIDE { |
| run_loop_->Quit(); |
| TestRunLoopHandler::OnHandleError(handle, result); |
| } |
| |
| private: |
| RunLoop* run_loop_; |
| |
| DISALLOW_COPY_AND_ASSIGN(QuitOnErrorRunLoopHandler); |
| }; |
| |
| // Verifies Quit() when the deadline is reached works. |
| TEST_F(RunLoopTest, QuitWhenDeadlineExpired) { |
| QuitOnErrorRunLoopHandler handler; |
| test::MessagePipe test_pipe; |
| RunLoop run_loop; |
| handler.set_run_loop(&run_loop); |
| run_loop.AddHandler(&handler, test_pipe.handle_0.get(), |
| MOJO_WAIT_FLAG_READABLE, |
| static_cast<MojoDeadline>(10000)); |
| run_loop.Run(); |
| EXPECT_EQ(0, handler.ready_count()); |
| EXPECT_EQ(1, handler.error_count()); |
| EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, handler.last_error_result()); |
| } |
| |
| TEST_F(RunLoopTest, Current) { |
| EXPECT_TRUE(RunLoop::current() == NULL); |
| { |
| RunLoop run_loop; |
| EXPECT_EQ(&run_loop, RunLoop::current()); |
| } |
| EXPECT_TRUE(RunLoop::current() == NULL); |
| } |
| |
| } // namespace |
| } // namespace utility |
| } // namespace mojo |