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.
5 #include "mojo/common/handle_watcher.h"
9 #include "base/auto_reset.h"
10 #include "base/bind.h"
11 #include "base/run_loop.h"
12 #include "base/test/simple_test_tick_clock.h"
13 #include "mojo/public/system/core_cpp.h"
14 #include "mojo/public/tests/test_utils.h"
15 #include "testing/gtest/include/gtest/gtest.h"
22 base::RunLoop run_loop
;
23 run_loop
.RunUntilIdle();
26 void DeleteWatcherAndForwardResult(
27 HandleWatcher
* watcher
,
28 base::Callback
<void(MojoResult
)> next_callback
,
31 next_callback
.Run(result
);
34 // Helper class to manage the callback and running the message loop waiting for
35 // message to be received. Typical usage is something like:
36 // Schedule callback returned from GetCallback().
37 // RunUntilGotCallback();
38 // EXPECT_TRUE(got_callback());
40 class CallbackHelper
{
43 : got_callback_(false),
45 weak_factory_(this) {}
48 // See description above |got_callback_|.
49 bool got_callback() const { return got_callback_
; }
50 void clear_callback() { got_callback_
= false; }
52 // Runs the current MessageLoop until the callback returned from GetCallback()
54 void RunUntilGotCallback() {
55 ASSERT_TRUE(run_loop_
== NULL
);
56 base::RunLoop run_loop
;
57 base::AutoReset
<base::RunLoop
*> reseter(&run_loop_
, &run_loop
);
61 base::Callback
<void(MojoResult
)> GetCallback() {
62 return base::Bind(&CallbackHelper::OnCallback
, weak_factory_
.GetWeakPtr());
65 void Start(HandleWatcher
* watcher
, const MessagePipeHandle
& handle
) {
66 StartWithCallback(watcher
, handle
, GetCallback());
69 void StartWithCallback(HandleWatcher
* watcher
,
70 const MessagePipeHandle
& handle
,
71 const base::Callback
<void(MojoResult
)>& callback
) {
72 watcher
->Start(handle
, MOJO_WAIT_FLAG_READABLE
, MOJO_DEADLINE_INDEFINITE
,
77 void OnCallback(MojoResult result
) {
83 // Set to true when the callback is called.
86 // If non-NULL we're in RunUntilGotCallback().
87 base::RunLoop
* run_loop_
;
89 base::WeakPtrFactory
<CallbackHelper
> weak_factory_
;
92 DISALLOW_COPY_AND_ASSIGN(CallbackHelper
);
95 class HandleWatcherTest
: public testing::Test
{
97 HandleWatcherTest() {}
98 virtual ~HandleWatcherTest() {
99 HandleWatcher::tick_clock_
= NULL
;
103 void InstallTickClock() {
104 HandleWatcher::tick_clock_
= &tick_clock_
;
107 base::SimpleTestTickClock tick_clock_
;
110 base::MessageLoop message_loop_
;
112 DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest
);
115 // Trivial test case with a single handle to watch.
116 TEST_F(HandleWatcherTest
, SingleHandler
) {
117 MessagePipe test_pipe
;
118 ASSERT_TRUE(test_pipe
.handle0
.is_valid());
119 CallbackHelper callback_helper
;
120 HandleWatcher watcher
;
121 callback_helper
.Start(&watcher
, test_pipe
.handle0
.get());
123 EXPECT_FALSE(callback_helper
.got_callback());
124 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe
.handle1
.get(),
126 callback_helper
.RunUntilGotCallback();
127 EXPECT_TRUE(callback_helper
.got_callback());
130 // Creates three handles and notfies them in reverse order ensuring each one is
131 // notified appropriately.
132 TEST_F(HandleWatcherTest
, ThreeHandles
) {
133 MessagePipe test_pipe1
;
134 MessagePipe test_pipe2
;
135 MessagePipe test_pipe3
;
136 CallbackHelper callback_helper1
;
137 CallbackHelper callback_helper2
;
138 CallbackHelper callback_helper3
;
139 ASSERT_TRUE(test_pipe1
.handle0
.is_valid());
140 ASSERT_TRUE(test_pipe2
.handle0
.is_valid());
141 ASSERT_TRUE(test_pipe3
.handle0
.is_valid());
143 HandleWatcher watcher1
;
144 callback_helper1
.Start(&watcher1
, test_pipe1
.handle0
.get());
146 EXPECT_FALSE(callback_helper1
.got_callback());
147 EXPECT_FALSE(callback_helper2
.got_callback());
148 EXPECT_FALSE(callback_helper3
.got_callback());
150 HandleWatcher watcher2
;
151 callback_helper2
.Start(&watcher2
, test_pipe2
.handle0
.get());
153 EXPECT_FALSE(callback_helper1
.got_callback());
154 EXPECT_FALSE(callback_helper2
.got_callback());
155 EXPECT_FALSE(callback_helper3
.got_callback());
157 HandleWatcher watcher3
;
158 callback_helper3
.Start(&watcher3
, test_pipe3
.handle0
.get());
160 EXPECT_FALSE(callback_helper1
.got_callback());
161 EXPECT_FALSE(callback_helper2
.got_callback());
162 EXPECT_FALSE(callback_helper3
.got_callback());
164 // Write to 3 and make sure it's notified.
165 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3
.handle1
.get(),
167 callback_helper3
.RunUntilGotCallback();
168 EXPECT_FALSE(callback_helper1
.got_callback());
169 EXPECT_FALSE(callback_helper2
.got_callback());
170 EXPECT_TRUE(callback_helper3
.got_callback());
171 callback_helper3
.clear_callback();
173 // Write to 1 and 3. Only 1 should be notified since 3 was is no longer
175 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1
.handle1
.get(),
177 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3
.handle1
.get(),
179 callback_helper1
.RunUntilGotCallback();
180 EXPECT_TRUE(callback_helper1
.got_callback());
181 EXPECT_FALSE(callback_helper2
.got_callback());
182 EXPECT_FALSE(callback_helper3
.got_callback());
183 callback_helper1
.clear_callback();
185 // Write to 1 and 2. Only 2 should be notified (since 1 was already notified).
186 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1
.handle1
.get(),
188 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2
.handle1
.get(),
190 callback_helper2
.RunUntilGotCallback();
191 EXPECT_FALSE(callback_helper1
.got_callback());
192 EXPECT_TRUE(callback_helper2
.got_callback());
193 EXPECT_FALSE(callback_helper3
.got_callback());
196 // Verifies Start() invoked a second time works.
197 TEST_F(HandleWatcherTest
, Restart
) {
198 MessagePipe test_pipe1
;
199 MessagePipe test_pipe2
;
200 CallbackHelper callback_helper1
;
201 CallbackHelper callback_helper2
;
202 ASSERT_TRUE(test_pipe1
.handle0
.is_valid());
203 ASSERT_TRUE(test_pipe2
.handle0
.is_valid());
205 HandleWatcher watcher1
;
206 callback_helper1
.Start(&watcher1
, test_pipe1
.handle0
.get());
208 EXPECT_FALSE(callback_helper1
.got_callback());
209 EXPECT_FALSE(callback_helper2
.got_callback());
211 HandleWatcher watcher2
;
212 callback_helper2
.Start(&watcher2
, test_pipe2
.handle0
.get());
214 EXPECT_FALSE(callback_helper1
.got_callback());
215 EXPECT_FALSE(callback_helper2
.got_callback());
217 // Write to 1 and make sure it's notified.
218 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1
.handle1
.get(),
220 callback_helper1
.RunUntilGotCallback();
221 EXPECT_TRUE(callback_helper1
.got_callback());
222 EXPECT_FALSE(callback_helper2
.got_callback());
223 callback_helper1
.clear_callback();
224 EXPECT_TRUE(mojo::test::DiscardMessage(test_pipe1
.handle0
.get()));
226 // Write to 2 and make sure it's notified.
227 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2
.handle1
.get(),
229 callback_helper2
.RunUntilGotCallback();
230 EXPECT_FALSE(callback_helper1
.got_callback());
231 EXPECT_TRUE(callback_helper2
.got_callback());
232 callback_helper2
.clear_callback();
234 // Listen on 1 again.
235 callback_helper1
.Start(&watcher1
, test_pipe1
.handle0
.get());
237 EXPECT_FALSE(callback_helper1
.got_callback());
238 EXPECT_FALSE(callback_helper2
.got_callback());
240 // Write to 1 and make sure it's notified.
241 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1
.handle1
.get(),
243 callback_helper1
.RunUntilGotCallback();
244 EXPECT_TRUE(callback_helper1
.got_callback());
245 EXPECT_FALSE(callback_helper2
.got_callback());
248 // Verifies deadline is honored.
249 TEST_F(HandleWatcherTest
, Deadline
) {
252 MessagePipe test_pipe1
;
253 MessagePipe test_pipe2
;
254 MessagePipe test_pipe3
;
255 CallbackHelper callback_helper1
;
256 CallbackHelper callback_helper2
;
257 CallbackHelper callback_helper3
;
258 ASSERT_TRUE(test_pipe1
.handle0
.is_valid());
259 ASSERT_TRUE(test_pipe2
.handle0
.is_valid());
260 ASSERT_TRUE(test_pipe3
.handle0
.is_valid());
262 // Add a watcher with an infinite timeout.
263 HandleWatcher watcher1
;
264 callback_helper1
.Start(&watcher1
, test_pipe1
.handle0
.get());
266 EXPECT_FALSE(callback_helper1
.got_callback());
267 EXPECT_FALSE(callback_helper2
.got_callback());
268 EXPECT_FALSE(callback_helper3
.got_callback());
270 // Add another watcher wth a timeout of 500 microseconds.
271 HandleWatcher watcher2
;
272 watcher2
.Start(test_pipe2
.handle0
.get(), MOJO_WAIT_FLAG_READABLE
, 500,
273 callback_helper2
.GetCallback());
275 EXPECT_FALSE(callback_helper1
.got_callback());
276 EXPECT_FALSE(callback_helper2
.got_callback());
277 EXPECT_FALSE(callback_helper3
.got_callback());
279 // Advance the clock passed the deadline. We also have to start another
280 // watcher to wake up the background thread.
281 tick_clock_
.Advance(base::TimeDelta::FromMicroseconds(501));
283 HandleWatcher watcher3
;
284 callback_helper3
.Start(&watcher3
, test_pipe3
.handle0
.get());
286 callback_helper2
.RunUntilGotCallback();
287 EXPECT_FALSE(callback_helper1
.got_callback());
288 EXPECT_TRUE(callback_helper2
.got_callback());
289 EXPECT_FALSE(callback_helper3
.got_callback());
292 TEST_F(HandleWatcherTest
, DeleteInCallback
) {
293 MessagePipe test_pipe
;
294 CallbackHelper callback_helper
;
296 HandleWatcher
* watcher
= new HandleWatcher();
297 callback_helper
.StartWithCallback(watcher
, test_pipe
.handle1
.get(),
298 base::Bind(&DeleteWatcherAndForwardResult
,
300 callback_helper
.GetCallback()));
301 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe
.handle0
.get(),
303 callback_helper
.RunUntilGotCallback();
304 EXPECT_TRUE(callback_helper
.got_callback());
308 } // namespace common