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 <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 
     23 void ObserveCallback(bool* was_signaled,
     24                      MojoResult* result_observed,
     25                      MojoResult result) {
     26   *was_signaled = true;
     27   *result_observed = result;
     28 }
     29 
     30 void RunUntilIdle() {
     31   base::RunLoop run_loop;
     32   run_loop.RunUntilIdle();
     33 }
     34 
     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:
     51   CallbackHelper()
     52       : got_callback_(false),
     53         run_loop_(NULL),
     54         weak_factory_(this) {}
     55   ~CallbackHelper() {}
     56 
     57   // See description above |got_callback_|.
     58   bool got_callback() const { return got_callback_; }
     59   void clear_callback() { got_callback_ = false; }
     60 
     61   // Runs the current MessageLoop until the callback returned from GetCallback()
     62   // is notified.
     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 
     70   base::Callback<void(MojoResult)> GetCallback() {
     71     return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr());
     72   }
     73 
     74   void Start(HandleWatcher* watcher, const MessagePipeHandle& handle) {
     75     StartWithCallback(watcher, handle, GetCallback());
     76   }
     77 
     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:
     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:
    106   HandleWatcherTest() {}
    107   virtual ~HandleWatcherTest() {
    108     test::SetTickClockForTest(NULL);
    109   }
    110 
    111  protected:
    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.
    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.
    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.
    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.
    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 
    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 
    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