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:
TestRunLoopHandler()20 TestRunLoopHandler()
21 : ready_count_(0),
22 error_count_(0),
23 last_error_result_(MOJO_RESULT_OK) {
24 }
~TestRunLoopHandler()25 virtual ~TestRunLoopHandler() {}
26
clear_ready_count()27 void clear_ready_count() { ready_count_ = 0; }
ready_count() const28 int ready_count() const { return ready_count_; }
29
clear_error_count()30 void clear_error_count() { error_count_ = 0; }
error_count() const31 int error_count() const { return error_count_; }
32
last_error_result() const33 MojoResult last_error_result() const { return last_error_result_; }
34
35 // RunLoopHandler:
OnHandleReady(const Handle & handle)36 virtual void OnHandleReady(const Handle& handle) OVERRIDE {
37 ready_count_++;
38 }
OnHandleError(const Handle & handle,MojoResult result)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:
RunLoopTest()54 RunLoopTest() {}
55
SetUp()56 virtual void SetUp() OVERRIDE {
57 Test::SetUp();
58 RunLoop::SetUp();
59 }
TearDown()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.
TEST_F(RunLoopTest,ExitsWithNoHandles)70 TEST_F(RunLoopTest, ExitsWithNoHandles) {
71 RunLoop run_loop;
72 run_loop.Run();
73 }
74
75 class RemoveOnReadyRunLoopHandler : public TestRunLoopHandler {
76 public:
RemoveOnReadyRunLoopHandler()77 RemoveOnReadyRunLoopHandler() : run_loop_(NULL) {
78 }
~RemoveOnReadyRunLoopHandler()79 virtual ~RemoveOnReadyRunLoopHandler() {}
80
set_run_loop(RunLoop * run_loop)81 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
82
83 // RunLoopHandler:
OnHandleReady(const Handle & handle)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).
TEST_F(RunLoopTest,HandleReady)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:
QuitOnReadyRunLoopHandler()112 QuitOnReadyRunLoopHandler() : run_loop_(NULL) {
113 }
~QuitOnReadyRunLoopHandler()114 virtual ~QuitOnReadyRunLoopHandler() {}
115
set_run_loop(RunLoop * run_loop)116 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
117
118 // RunLoopHandler:
OnHandleReady(const Handle & handle)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.
TEST_F(RunLoopTest,QuitFromReady)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:
QuitOnErrorRunLoopHandler()147 QuitOnErrorRunLoopHandler() : run_loop_(NULL) {
148 }
~QuitOnErrorRunLoopHandler()149 virtual ~QuitOnErrorRunLoopHandler() {}
150
set_run_loop(RunLoop * run_loop)151 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
152
153 // RunLoopHandler:
OnHandleError(const Handle & handle,MojoResult result)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.
TEST_F(RunLoopTest,QuitWhenDeadlineExpired)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
TEST_F(RunLoopTest,Current)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