handle_watcher_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
107b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// Copyright 2013 The Chromium Authors. All rights reserved.
207b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// Use of this source code is governed by a BSD-style license that can be
39be1d37a9a6561f135412db66806def9f82a29c1steveblock@chromium.org// found in the LICENSE file.
407b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org
507b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "mojo/common/handle_watcher.h"
607b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org
707b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include <string>
87a9d1ab1b214d7342b5a6d3ae4837fd572a8f4d0evan@chromium.org
907b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "base/auto_reset.h"
1007b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "base/bind.h"
1107b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "base/run_loop.h"
1207b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "base/test/simple_test_tick_clock.h"
1307b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "mojo/public/system/core_cpp.h"
1407b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "mojo/public/tests/test_utils.h"
1507b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "testing/gtest/include/gtest/gtest.h"
16dc9d50a9c015fa86d8ffae123d63173cf5bd7b73torne@chromium.org
17dc9d50a9c015fa86d8ffae123d63173cf5bd7b73torne@chromium.orgnamespace mojo {
1807b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.orgnamespace common {
1907b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.orgnamespace test {
2007b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org
218051f4242ca0291165aef138ab4b621eb3128d92thomasvl@chromium.orgvoid RunUntilIdle() {
2207b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org  base::RunLoop run_loop;
2307b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org  run_loop.RunUntilIdle();
247a9d1ab1b214d7342b5a6d3ae4837fd572a8f4d0evan@chromium.org}
2507b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org
2607b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.orgvoid DeleteWatcherAndForwardResult(
2707b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org    HandleWatcher* watcher,
2807b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org    base::Callback<void(MojoResult)> next_callback,
2907b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org    MojoResult result) {
3007b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org  delete watcher;
31a7fd578d98e5fff82dfd51d8a8e41f8392ff38b7bradnelson@google.com  next_callback.Run(result);
3207b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org}
337a9d1ab1b214d7342b5a6d3ae4837fd572a8f4d0evan@chromium.org
3407b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// Helper class to manage the callback and running the message loop waiting for
3507b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// message to be received. Typical usage is something like:
3607b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org//   Schedule callback returned from GetCallback().
3707b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org//   RunUntilGotCallback();
388051f4242ca0291165aef138ab4b621eb3128d92thomasvl@chromium.org//   EXPECT_TRUE(got_callback());
3907b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org//   clear_callback();
4007b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.orgclass CallbackHelper {
4107b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org public:
42a7fd578d98e5fff82dfd51d8a8e41f8392ff38b7bradnelson@google.com  CallbackHelper()
4307b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org      : got_callback_(false),
4407b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org        run_loop_(NULL),
45        weak_factory_(this) {}
46  ~CallbackHelper() {}
47
48  // See description above |got_callback_|.
49  bool got_callback() const { return got_callback_; }
50  void clear_callback() { got_callback_ = false; }
51
52  // Runs the current MessageLoop until the callback returned from GetCallback()
53  // is notified.
54  void RunUntilGotCallback() {
55    ASSERT_TRUE(run_loop_ == NULL);
56    base::RunLoop run_loop;
57    base::AutoReset<base::RunLoop*> reseter(&run_loop_, &run_loop);
58    run_loop.Run();
59  }
60
61  base::Callback<void(MojoResult)> GetCallback() {
62    return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr());
63  }
64
65  void Start(HandleWatcher* watcher, const MessagePipeHandle& handle) {
66    StartWithCallback(watcher, handle, GetCallback());
67  }
68
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,
73                   callback);
74  }
75
76 private:
77  void OnCallback(MojoResult result) {
78    got_callback_ = true;
79    if (run_loop_)
80      run_loop_->Quit();
81  }
82
83  // Set to true when the callback is called.
84  bool got_callback_;
85
86  // If non-NULL we're in RunUntilGotCallback().
87  base::RunLoop* run_loop_;
88
89  base::WeakPtrFactory<CallbackHelper> weak_factory_;
90
91 private:
92  DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
93};
94
95class HandleWatcherTest : public testing::Test {
96 public:
97  HandleWatcherTest() {}
98  virtual ~HandleWatcherTest() {
99    HandleWatcher::tick_clock_ = NULL;
100  }
101
102 protected:
103  void InstallTickClock() {
104    HandleWatcher::tick_clock_ = &tick_clock_;
105  }
106
107  base::SimpleTestTickClock tick_clock_;
108
109 private:
110  base::MessageLoop message_loop_;
111
112  DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest);
113};
114
115// Trivial test case with a single handle to watch.
116TEST_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());
122  RunUntilIdle();
123  EXPECT_FALSE(callback_helper.got_callback());
124  EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(),
125                                           std::string()));
126  callback_helper.RunUntilGotCallback();
127  EXPECT_TRUE(callback_helper.got_callback());
128}
129
130// Creates three handles and notfies them in reverse order ensuring each one is
131// notified appropriately.
132TEST_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());
142
143  HandleWatcher watcher1;
144  callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
145  RunUntilIdle();
146  EXPECT_FALSE(callback_helper1.got_callback());
147  EXPECT_FALSE(callback_helper2.got_callback());
148  EXPECT_FALSE(callback_helper3.got_callback());
149
150  HandleWatcher watcher2;
151  callback_helper2.Start(&watcher2, test_pipe2.handle0.get());
152  RunUntilIdle();
153  EXPECT_FALSE(callback_helper1.got_callback());
154  EXPECT_FALSE(callback_helper2.got_callback());
155  EXPECT_FALSE(callback_helper3.got_callback());
156
157  HandleWatcher watcher3;
158  callback_helper3.Start(&watcher3, test_pipe3.handle0.get());
159  RunUntilIdle();
160  EXPECT_FALSE(callback_helper1.got_callback());
161  EXPECT_FALSE(callback_helper2.got_callback());
162  EXPECT_FALSE(callback_helper3.got_callback());
163
164  // Write to 3 and make sure it's notified.
165  EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(),
166                                           std::string()));
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();
172
173  // Write to 1 and 3. Only 1 should be notified since 3 was is no longer
174  // running.
175  EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
176                                           std::string()));
177  EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(),
178                                           std::string()));
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();
184
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(),
187                                           std::string()));
188  EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(),
189                                           std::string()));
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());
194}
195
196// Verifies Start() invoked a second time works.
197TEST_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());
204
205  HandleWatcher watcher1;
206  callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
207  RunUntilIdle();
208  EXPECT_FALSE(callback_helper1.got_callback());
209  EXPECT_FALSE(callback_helper2.got_callback());
210
211  HandleWatcher watcher2;
212  callback_helper2.Start(&watcher2, test_pipe2.handle0.get());
213  RunUntilIdle();
214  EXPECT_FALSE(callback_helper1.got_callback());
215  EXPECT_FALSE(callback_helper2.got_callback());
216
217  // Write to 1 and make sure it's notified.
218  EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
219                                           std::string()));
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()));
225
226  // Write to 2 and make sure it's notified.
227  EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(),
228                                           std::string()));
229  callback_helper2.RunUntilGotCallback();
230  EXPECT_FALSE(callback_helper1.got_callback());
231  EXPECT_TRUE(callback_helper2.got_callback());
232  callback_helper2.clear_callback();
233
234  // Listen on 1 again.
235  callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
236  RunUntilIdle();
237  EXPECT_FALSE(callback_helper1.got_callback());
238  EXPECT_FALSE(callback_helper2.got_callback());
239
240  // Write to 1 and make sure it's notified.
241  EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
242                                           std::string()));
243  callback_helper1.RunUntilGotCallback();
244  EXPECT_TRUE(callback_helper1.got_callback());
245  EXPECT_FALSE(callback_helper2.got_callback());
246}
247
248// Verifies deadline is honored.
249TEST_F(HandleWatcherTest, Deadline) {
250  InstallTickClock();
251
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());
261
262  // Add a watcher with an infinite timeout.
263  HandleWatcher watcher1;
264  callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
265  RunUntilIdle();
266  EXPECT_FALSE(callback_helper1.got_callback());
267  EXPECT_FALSE(callback_helper2.got_callback());
268  EXPECT_FALSE(callback_helper3.got_callback());
269
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());
274  RunUntilIdle();
275  EXPECT_FALSE(callback_helper1.got_callback());
276  EXPECT_FALSE(callback_helper2.got_callback());
277  EXPECT_FALSE(callback_helper3.got_callback());
278
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));
282
283  HandleWatcher watcher3;
284  callback_helper3.Start(&watcher3, test_pipe3.handle0.get());
285
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());
290}
291
292TEST_F(HandleWatcherTest, DeleteInCallback) {
293  MessagePipe test_pipe;
294  CallbackHelper callback_helper;
295
296  HandleWatcher* watcher = new HandleWatcher();
297  callback_helper.StartWithCallback(watcher, test_pipe.handle1.get(),
298                                    base::Bind(&DeleteWatcherAndForwardResult,
299                                               watcher,
300                                               callback_helper.GetCallback()));
301  EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle0.get(),
302                                           std::string()));
303  callback_helper.RunUntilGotCallback();
304  EXPECT_TRUE(callback_helper.got_callback());
305}
306
307}  // namespace test
308}  // namespace common
309}  // namespace mojo
310