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