• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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