Home | History | Annotate | Download | only in tests
      1 // Copyright 2016 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/public/cpp/system/watcher.h"
      6 
      7 #include <memory>
      8 
      9 #include "base/bind.h"
     10 #include "base/callback.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/run_loop.h"
     13 #include "base/threading/thread_task_runner_handle.h"
     14 #include "mojo/public/c/system/types.h"
     15 #include "mojo/public/cpp/system/message_pipe.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace mojo {
     19 namespace {
     20 
     21 template <typename Handler>
     22 void RunResultHandler(Handler f, MojoResult result) { f(result); }
     23 
     24 template <typename Handler>
     25 Watcher::ReadyCallback OnReady(Handler f) {
     26   return base::Bind(&RunResultHandler<Handler>, f);
     27 }
     28 
     29 Watcher::ReadyCallback NotReached() {
     30   return OnReady([] (MojoResult) { NOTREACHED(); });
     31 }
     32 
     33 class WatcherTest : public testing::Test {
     34  public:
     35   WatcherTest() {}
     36   ~WatcherTest() override {}
     37 
     38   void SetUp() override {
     39     message_loop_.reset(new base::MessageLoop);
     40   }
     41 
     42   void TearDown() override {
     43     message_loop_.reset();
     44   }
     45 
     46  protected:
     47   std::unique_ptr<base::MessageLoop> message_loop_;
     48 };
     49 
     50 TEST_F(WatcherTest, WatchBasic) {
     51   ScopedMessagePipeHandle a, b;
     52   CreateMessagePipe(nullptr, &a, &b);
     53 
     54   bool notified = false;
     55   base::RunLoop run_loop;
     56   Watcher b_watcher;
     57   EXPECT_EQ(MOJO_RESULT_OK,
     58             b_watcher.Start(b.get(), MOJO_HANDLE_SIGNAL_READABLE,
     59                             OnReady([&] (MojoResult result) {
     60                               EXPECT_EQ(MOJO_RESULT_OK, result);
     61                               notified = true;
     62                               run_loop.Quit();
     63                             })));
     64   EXPECT_TRUE(b_watcher.IsWatching());
     65 
     66   EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0,
     67                                             MOJO_WRITE_MESSAGE_FLAG_NONE));
     68   run_loop.Run();
     69   EXPECT_TRUE(notified);
     70 
     71   b_watcher.Cancel();
     72 }
     73 
     74 TEST_F(WatcherTest, WatchUnsatisfiable) {
     75   ScopedMessagePipeHandle a, b;
     76   CreateMessagePipe(nullptr, &a, &b);
     77   a.reset();
     78 
     79   Watcher b_watcher;
     80   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
     81             b_watcher.Start(b.get(), MOJO_HANDLE_SIGNAL_READABLE,
     82                             NotReached()));
     83   EXPECT_FALSE(b_watcher.IsWatching());
     84 }
     85 
     86 TEST_F(WatcherTest, WatchInvalidHandle) {
     87   ScopedMessagePipeHandle a, b;
     88   CreateMessagePipe(nullptr, &a, &b);
     89   a.reset();
     90   b.reset();
     91 
     92   Watcher b_watcher;
     93   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
     94             b_watcher.Start(b.get(), MOJO_HANDLE_SIGNAL_READABLE,
     95                             NotReached()));
     96   EXPECT_FALSE(b_watcher.IsWatching());
     97 }
     98 
     99 TEST_F(WatcherTest, Cancel) {
    100   ScopedMessagePipeHandle a, b;
    101   CreateMessagePipe(nullptr, &a, &b);
    102 
    103   base::RunLoop run_loop;
    104   Watcher b_watcher;
    105   EXPECT_EQ(MOJO_RESULT_OK,
    106             b_watcher.Start(b.get(), MOJO_HANDLE_SIGNAL_READABLE,
    107                             NotReached()));
    108   EXPECT_TRUE(b_watcher.IsWatching());
    109   b_watcher.Cancel();
    110   EXPECT_FALSE(b_watcher.IsWatching());
    111 
    112   // This should never trigger the watcher.
    113   EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0,
    114                                             MOJO_WRITE_MESSAGE_FLAG_NONE));
    115 
    116   base::ThreadTaskRunnerHandle::Get()->PostTask(
    117       FROM_HERE, run_loop.QuitClosure());
    118   run_loop.Run();
    119 }
    120 
    121 TEST_F(WatcherTest, CancelOnClose) {
    122   ScopedMessagePipeHandle a, b;
    123   CreateMessagePipe(nullptr, &a, &b);
    124 
    125   base::RunLoop run_loop;
    126   Watcher b_watcher;
    127   EXPECT_EQ(MOJO_RESULT_OK,
    128             b_watcher.Start(b.get(), MOJO_HANDLE_SIGNAL_READABLE,
    129                             OnReady([&] (MojoResult result) {
    130                               EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
    131                               run_loop.Quit();
    132                             })));
    133   EXPECT_TRUE(b_watcher.IsWatching());
    134 
    135   // This should trigger the watcher above.
    136   b.reset();
    137 
    138   run_loop.Run();
    139 
    140   EXPECT_FALSE(b_watcher.IsWatching());
    141 }
    142 
    143 TEST_F(WatcherTest, CancelOnDestruction) {
    144   ScopedMessagePipeHandle a, b;
    145   CreateMessagePipe(nullptr, &a, &b);
    146   base::RunLoop run_loop;
    147   {
    148     Watcher b_watcher;
    149     EXPECT_EQ(MOJO_RESULT_OK,
    150               b_watcher.Start(b.get(), MOJO_HANDLE_SIGNAL_READABLE,
    151                               NotReached()));
    152     EXPECT_TRUE(b_watcher.IsWatching());
    153 
    154     // |b_watcher| should be cancelled when it goes out of scope.
    155   }
    156 
    157   // This should never trigger the watcher above.
    158   EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0,
    159                                             MOJO_WRITE_MESSAGE_FLAG_NONE));
    160   base::ThreadTaskRunnerHandle::Get()->PostTask(
    161       FROM_HERE, run_loop.QuitClosure());
    162   run_loop.Run();
    163 }
    164 
    165 TEST_F(WatcherTest, NotifyOnMessageLoopDestruction) {
    166   ScopedMessagePipeHandle a, b;
    167   CreateMessagePipe(nullptr, &a, &b);
    168 
    169   bool notified = false;
    170   Watcher b_watcher;
    171   EXPECT_EQ(MOJO_RESULT_OK,
    172             b_watcher.Start(b.get(), MOJO_HANDLE_SIGNAL_READABLE,
    173                             OnReady([&] (MojoResult result) {
    174                               EXPECT_EQ(MOJO_RESULT_ABORTED, result);
    175                               notified = true;
    176                             })));
    177   EXPECT_TRUE(b_watcher.IsWatching());
    178 
    179   message_loop_.reset();
    180 
    181   EXPECT_TRUE(notified);
    182 
    183   EXPECT_TRUE(b_watcher.IsWatching());
    184   b_watcher.Cancel();
    185 }
    186 
    187 TEST_F(WatcherTest, CloseAndCancel) {
    188   ScopedMessagePipeHandle a, b;
    189   CreateMessagePipe(nullptr, &a, &b);
    190 
    191   Watcher b_watcher;
    192   EXPECT_EQ(MOJO_RESULT_OK,
    193             b_watcher.Start(b.get(), MOJO_HANDLE_SIGNAL_READABLE,
    194                             OnReady([](MojoResult result) { FAIL(); })));
    195   EXPECT_TRUE(b_watcher.IsWatching());
    196 
    197   // This should trigger the watcher above...
    198   b.reset();
    199   // ...but the watcher is cancelled first.
    200   b_watcher.Cancel();
    201 
    202   EXPECT_FALSE(b_watcher.IsWatching());
    203 
    204   base::RunLoop().RunUntilIdle();
    205 }
    206 
    207 }  // namespace
    208 }  // namespace mojo
    209