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/common/handle_watcher.h"
6
7 #include <string>
8
9 #include "base/at_exit.h"
10 #include "base/auto_reset.h"
11 #include "base/bind.h"
12 #include "base/run_loop.h"
13 #include "base/test/simple_test_tick_clock.h"
14 #include "mojo/common/time_helper.h"
15 #include "mojo/public/cpp/system/core.h"
16 #include "mojo/public/cpp/test_support/test_utils.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace mojo {
20 namespace common {
21 namespace test {
22
ObserveCallback(bool * was_signaled,MojoResult * result_observed,MojoResult result)23 void ObserveCallback(bool* was_signaled,
24 MojoResult* result_observed,
25 MojoResult result) {
26 *was_signaled = true;
27 *result_observed = result;
28 }
29
RunUntilIdle()30 void RunUntilIdle() {
31 base::RunLoop run_loop;
32 run_loop.RunUntilIdle();
33 }
34
DeleteWatcherAndForwardResult(HandleWatcher * watcher,base::Callback<void (MojoResult)> next_callback,MojoResult result)35 void DeleteWatcherAndForwardResult(
36 HandleWatcher* watcher,
37 base::Callback<void(MojoResult)> next_callback,
38 MojoResult result) {
39 delete watcher;
40 next_callback.Run(result);
41 }
42
43 // Helper class to manage the callback and running the message loop waiting for
44 // message to be received. Typical usage is something like:
45 // Schedule callback returned from GetCallback().
46 // RunUntilGotCallback();
47 // EXPECT_TRUE(got_callback());
48 // clear_callback();
49 class CallbackHelper {
50 public:
CallbackHelper()51 CallbackHelper()
52 : got_callback_(false),
53 run_loop_(NULL),
54 weak_factory_(this) {}
~CallbackHelper()55 ~CallbackHelper() {}
56
57 // See description above |got_callback_|.
got_callback() const58 bool got_callback() const { return got_callback_; }
clear_callback()59 void clear_callback() { got_callback_ = false; }
60
61 // Runs the current MessageLoop until the callback returned from GetCallback()
62 // is notified.
RunUntilGotCallback()63 void RunUntilGotCallback() {
64 ASSERT_TRUE(run_loop_ == NULL);
65 base::RunLoop run_loop;
66 base::AutoReset<base::RunLoop*> reseter(&run_loop_, &run_loop);
67 run_loop.Run();
68 }
69
GetCallback()70 base::Callback<void(MojoResult)> GetCallback() {
71 return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr());
72 }
73
Start(HandleWatcher * watcher,const MessagePipeHandle & handle)74 void Start(HandleWatcher* watcher, const MessagePipeHandle& handle) {
75 StartWithCallback(watcher, handle, GetCallback());
76 }
77
StartWithCallback(HandleWatcher * watcher,const MessagePipeHandle & handle,const base::Callback<void (MojoResult)> & callback)78 void StartWithCallback(HandleWatcher* watcher,
79 const MessagePipeHandle& handle,
80 const base::Callback<void(MojoResult)>& callback) {
81 watcher->Start(handle, MOJO_HANDLE_SIGNAL_READABLE,
82 MOJO_DEADLINE_INDEFINITE, callback);
83 }
84
85 private:
OnCallback(MojoResult result)86 void OnCallback(MojoResult result) {
87 got_callback_ = true;
88 if (run_loop_)
89 run_loop_->Quit();
90 }
91
92 // Set to true when the callback is called.
93 bool got_callback_;
94
95 // If non-NULL we're in RunUntilGotCallback().
96 base::RunLoop* run_loop_;
97
98 base::WeakPtrFactory<CallbackHelper> weak_factory_;
99
100 private:
101 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
102 };
103
104 class HandleWatcherTest : public testing::Test {
105 public:
HandleWatcherTest()106 HandleWatcherTest() {}
~HandleWatcherTest()107 virtual ~HandleWatcherTest() {
108 test::SetTickClockForTest(NULL);
109 }
110
111 protected:
InstallTickClock()112 void InstallTickClock() {
113 test::SetTickClockForTest(&tick_clock_);
114 }
115
116 base::SimpleTestTickClock tick_clock_;
117
118 private:
119 base::ShadowingAtExitManager at_exit_;
120 base::MessageLoop message_loop_;
121
122 DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest);
123 };
124
125 // Trivial test case with a single handle to watch.
TEST_F(HandleWatcherTest,SingleHandler)126 TEST_F(HandleWatcherTest, SingleHandler) {
127 MessagePipe test_pipe;
128 ASSERT_TRUE(test_pipe.handle0.is_valid());
129 CallbackHelper callback_helper;
130 HandleWatcher watcher;
131 callback_helper.Start(&watcher, test_pipe.handle0.get());
132 RunUntilIdle();
133 EXPECT_FALSE(callback_helper.got_callback());
134 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(),
135 std::string()));
136 callback_helper.RunUntilGotCallback();
137 EXPECT_TRUE(callback_helper.got_callback());
138 }
139
140 // Creates three handles and notfies them in reverse order ensuring each one is
141 // notified appropriately.
TEST_F(HandleWatcherTest,ThreeHandles)142 TEST_F(HandleWatcherTest, ThreeHandles) {
143 MessagePipe test_pipe1;
144 MessagePipe test_pipe2;
145 MessagePipe test_pipe3;
146 CallbackHelper callback_helper1;
147 CallbackHelper callback_helper2;
148 CallbackHelper callback_helper3;
149 ASSERT_TRUE(test_pipe1.handle0.is_valid());
150 ASSERT_TRUE(test_pipe2.handle0.is_valid());
151 ASSERT_TRUE(test_pipe3.handle0.is_valid());
152
153 HandleWatcher watcher1;
154 callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
155 RunUntilIdle();
156 EXPECT_FALSE(callback_helper1.got_callback());
157 EXPECT_FALSE(callback_helper2.got_callback());
158 EXPECT_FALSE(callback_helper3.got_callback());
159
160 HandleWatcher watcher2;
161 callback_helper2.Start(&watcher2, test_pipe2.handle0.get());
162 RunUntilIdle();
163 EXPECT_FALSE(callback_helper1.got_callback());
164 EXPECT_FALSE(callback_helper2.got_callback());
165 EXPECT_FALSE(callback_helper3.got_callback());
166
167 HandleWatcher watcher3;
168 callback_helper3.Start(&watcher3, test_pipe3.handle0.get());
169 RunUntilIdle();
170 EXPECT_FALSE(callback_helper1.got_callback());
171 EXPECT_FALSE(callback_helper2.got_callback());
172 EXPECT_FALSE(callback_helper3.got_callback());
173
174 // Write to 3 and make sure it's notified.
175 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(),
176 std::string()));
177 callback_helper3.RunUntilGotCallback();
178 EXPECT_FALSE(callback_helper1.got_callback());
179 EXPECT_FALSE(callback_helper2.got_callback());
180 EXPECT_TRUE(callback_helper3.got_callback());
181 callback_helper3.clear_callback();
182
183 // Write to 1 and 3. Only 1 should be notified since 3 was is no longer
184 // running.
185 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
186 std::string()));
187 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(),
188 std::string()));
189 callback_helper1.RunUntilGotCallback();
190 EXPECT_TRUE(callback_helper1.got_callback());
191 EXPECT_FALSE(callback_helper2.got_callback());
192 EXPECT_FALSE(callback_helper3.got_callback());
193 callback_helper1.clear_callback();
194
195 // Write to 1 and 2. Only 2 should be notified (since 1 was already notified).
196 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
197 std::string()));
198 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(),
199 std::string()));
200 callback_helper2.RunUntilGotCallback();
201 EXPECT_FALSE(callback_helper1.got_callback());
202 EXPECT_TRUE(callback_helper2.got_callback());
203 EXPECT_FALSE(callback_helper3.got_callback());
204 }
205
206 // Verifies Start() invoked a second time works.
TEST_F(HandleWatcherTest,Restart)207 TEST_F(HandleWatcherTest, Restart) {
208 MessagePipe test_pipe1;
209 MessagePipe test_pipe2;
210 CallbackHelper callback_helper1;
211 CallbackHelper callback_helper2;
212 ASSERT_TRUE(test_pipe1.handle0.is_valid());
213 ASSERT_TRUE(test_pipe2.handle0.is_valid());
214
215 HandleWatcher watcher1;
216 callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
217 RunUntilIdle();
218 EXPECT_FALSE(callback_helper1.got_callback());
219 EXPECT_FALSE(callback_helper2.got_callback());
220
221 HandleWatcher watcher2;
222 callback_helper2.Start(&watcher2, test_pipe2.handle0.get());
223 RunUntilIdle();
224 EXPECT_FALSE(callback_helper1.got_callback());
225 EXPECT_FALSE(callback_helper2.got_callback());
226
227 // Write to 1 and make sure it's notified.
228 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
229 std::string()));
230 callback_helper1.RunUntilGotCallback();
231 EXPECT_TRUE(callback_helper1.got_callback());
232 EXPECT_FALSE(callback_helper2.got_callback());
233 callback_helper1.clear_callback();
234 EXPECT_TRUE(mojo::test::DiscardMessage(test_pipe1.handle0.get()));
235
236 // Write to 2 and make sure it's notified.
237 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(),
238 std::string()));
239 callback_helper2.RunUntilGotCallback();
240 EXPECT_FALSE(callback_helper1.got_callback());
241 EXPECT_TRUE(callback_helper2.got_callback());
242 callback_helper2.clear_callback();
243
244 // Listen on 1 again.
245 callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
246 RunUntilIdle();
247 EXPECT_FALSE(callback_helper1.got_callback());
248 EXPECT_FALSE(callback_helper2.got_callback());
249
250 // Write to 1 and make sure it's notified.
251 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
252 std::string()));
253 callback_helper1.RunUntilGotCallback();
254 EXPECT_TRUE(callback_helper1.got_callback());
255 EXPECT_FALSE(callback_helper2.got_callback());
256 }
257
258 // Verifies deadline is honored.
TEST_F(HandleWatcherTest,Deadline)259 TEST_F(HandleWatcherTest, Deadline) {
260 InstallTickClock();
261
262 MessagePipe test_pipe1;
263 MessagePipe test_pipe2;
264 MessagePipe test_pipe3;
265 CallbackHelper callback_helper1;
266 CallbackHelper callback_helper2;
267 CallbackHelper callback_helper3;
268 ASSERT_TRUE(test_pipe1.handle0.is_valid());
269 ASSERT_TRUE(test_pipe2.handle0.is_valid());
270 ASSERT_TRUE(test_pipe3.handle0.is_valid());
271
272 // Add a watcher with an infinite timeout.
273 HandleWatcher watcher1;
274 callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
275 RunUntilIdle();
276 EXPECT_FALSE(callback_helper1.got_callback());
277 EXPECT_FALSE(callback_helper2.got_callback());
278 EXPECT_FALSE(callback_helper3.got_callback());
279
280 // Add another watcher wth a timeout of 500 microseconds.
281 HandleWatcher watcher2;
282 watcher2.Start(test_pipe2.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 500,
283 callback_helper2.GetCallback());
284 RunUntilIdle();
285 EXPECT_FALSE(callback_helper1.got_callback());
286 EXPECT_FALSE(callback_helper2.got_callback());
287 EXPECT_FALSE(callback_helper3.got_callback());
288
289 // Advance the clock passed the deadline. We also have to start another
290 // watcher to wake up the background thread.
291 tick_clock_.Advance(base::TimeDelta::FromMicroseconds(501));
292
293 HandleWatcher watcher3;
294 callback_helper3.Start(&watcher3, test_pipe3.handle0.get());
295
296 callback_helper2.RunUntilGotCallback();
297 EXPECT_FALSE(callback_helper1.got_callback());
298 EXPECT_TRUE(callback_helper2.got_callback());
299 EXPECT_FALSE(callback_helper3.got_callback());
300 }
301
TEST_F(HandleWatcherTest,DeleteInCallback)302 TEST_F(HandleWatcherTest, DeleteInCallback) {
303 MessagePipe test_pipe;
304 CallbackHelper callback_helper;
305
306 HandleWatcher* watcher = new HandleWatcher();
307 callback_helper.StartWithCallback(watcher, test_pipe.handle1.get(),
308 base::Bind(&DeleteWatcherAndForwardResult,
309 watcher,
310 callback_helper.GetCallback()));
311 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle0.get(),
312 std::string()));
313 callback_helper.RunUntilGotCallback();
314 EXPECT_TRUE(callback_helper.got_callback());
315 }
316
TEST(HandleWatcherCleanEnvironmentTest,AbortedOnMessageLoopDestruction)317 TEST(HandleWatcherCleanEnvironmentTest, AbortedOnMessageLoopDestruction) {
318 bool was_signaled = false;
319 MojoResult result = MOJO_RESULT_OK;
320
321 base::ShadowingAtExitManager at_exit;
322 MessagePipe pipe;
323 HandleWatcher watcher;
324 {
325 base::MessageLoop loop;
326
327 watcher.Start(pipe.handle0.get(),
328 MOJO_HANDLE_SIGNAL_READABLE,
329 MOJO_DEADLINE_INDEFINITE,
330 base::Bind(&ObserveCallback, &was_signaled, &result));
331
332 // Now, let the MessageLoop get torn down. We expect our callback to run.
333 }
334
335 EXPECT_TRUE(was_signaled);
336 EXPECT_EQ(MOJO_RESULT_ABORTED, result);
337 }
338
339 } // namespace test
340 } // namespace common
341 } // namespace mojo
342