Home | History | Annotate | Download | only in common
      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 
     15 namespace mojo {
     16 namespace common {
     17 namespace test {
     18 
     19 void RunUntilIdle() {
     20   base::RunLoop run_loop;
     21   run_loop.RunUntilIdle();
     22 }
     23 
     24 void 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();
     38 class 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 
     93 class 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.
    114 TEST_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.
    130 TEST_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.
    195 TEST_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.
    248 TEST_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 
    291 TEST_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