• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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/handle_signal_tracker.h"
6 
7 #include "base/macros.h"
8 #include "base/run_loop.h"
9 #include "base/test/scoped_task_environment.h"
10 #include "mojo/public/cpp/system/message_pipe.h"
11 #include "mojo/public/cpp/system/wait.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace mojo {
15 namespace {
16 
17 class HandleSignalTrackerTest : public testing::Test {
18  public:
HandleSignalTrackerTest()19   HandleSignalTrackerTest() {}
~HandleSignalTrackerTest()20   ~HandleSignalTrackerTest() override {}
21 
WaitForNextNotification(HandleSignalTracker * tracker)22   void WaitForNextNotification(HandleSignalTracker* tracker) {
23     base::RunLoop loop;
24     tracker->set_notification_callback(base::Bind(
25         [](base::RunLoop* loop, const HandleSignalsState& signals_state) {
26           loop->Quit();
27         },
28         &loop));
29     loop.Run();
30     tracker->set_notification_callback(
31         HandleSignalTracker::NotificationCallback());
32   }
33 
34  private:
35   base::test::ScopedTaskEnvironment task_environment_;
36 
37   DISALLOW_COPY_AND_ASSIGN(HandleSignalTrackerTest);
38 };
39 
TEST_F(HandleSignalTrackerTest,StartsWithCorrectState)40 TEST_F(HandleSignalTrackerTest, StartsWithCorrectState) {
41   MessagePipe pipe;
42   {
43     HandleSignalTracker tracker(pipe.handle0.get(),
44                                 MOJO_HANDLE_SIGNAL_READABLE);
45     EXPECT_FALSE(tracker.last_known_state().readable());
46   }
47 
48   WriteMessageRaw(pipe.handle1.get(), "hi", 2, nullptr, 0,
49                   MOJO_WRITE_MESSAGE_FLAG_NONE);
50   Wait(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
51        MOJO_WATCH_CONDITION_SATISFIED);
52 
53   {
54     HandleSignalTracker tracker(pipe.handle0.get(),
55                                 MOJO_HANDLE_SIGNAL_READABLE);
56     EXPECT_TRUE(tracker.last_known_state().readable());
57   }
58 }
59 
TEST_F(HandleSignalTrackerTest,BasicTracking)60 TEST_F(HandleSignalTrackerTest, BasicTracking) {
61   MessagePipe pipe;
62   HandleSignalTracker tracker(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
63   EXPECT_FALSE(tracker.last_known_state().readable());
64 
65   WriteMessageRaw(pipe.handle1.get(), "hi", 2, nullptr, 0,
66                   MOJO_WRITE_MESSAGE_FLAG_NONE);
67   WaitForNextNotification(&tracker);
68   EXPECT_TRUE(tracker.last_known_state().readable());
69 
70   std::vector<uint8_t> bytes;
71   ReadMessageRaw(pipe.handle0.get(), &bytes, nullptr,
72                  MOJO_READ_MESSAGE_FLAG_NONE);
73   WaitForNextNotification(&tracker);
74   EXPECT_FALSE(tracker.last_known_state().readable());
75 }
76 
TEST_F(HandleSignalTrackerTest,DoesntUpdateOnIrrelevantChanges)77 TEST_F(HandleSignalTrackerTest, DoesntUpdateOnIrrelevantChanges) {
78   MessagePipe pipe;
79   HandleSignalTracker readable_tracker(pipe.handle0.get(),
80                                        MOJO_HANDLE_SIGNAL_READABLE);
81   HandleSignalTracker peer_closed_tracker(pipe.handle0.get(),
82                                           MOJO_HANDLE_SIGNAL_PEER_CLOSED);
83   EXPECT_FALSE(readable_tracker.last_known_state().readable());
84   EXPECT_FALSE(peer_closed_tracker.last_known_state().peer_closed());
85 
86   WriteMessageRaw(pipe.handle1.get(), "hi", 2, nullptr, 0,
87                   MOJO_WRITE_MESSAGE_FLAG_NONE);
88   WaitForNextNotification(&readable_tracker);
89   EXPECT_TRUE(readable_tracker.last_known_state().readable());
90   EXPECT_FALSE(readable_tracker.last_known_state().peer_closed());
91 
92   // Closing the peer won't change the |readable_tracker|'s state since there's
93   // still an unread message. Therefore the tracker's last known state should
94   // continue to reflect the state prior to peer closure even after the handle's
95   // signals state has updated.
96   pipe.handle1.reset();
97   WaitForNextNotification(&peer_closed_tracker);
98   EXPECT_TRUE(pipe.handle0->QuerySignalsState().peer_closed());
99   EXPECT_TRUE(peer_closed_tracker.last_known_state().peer_closed());
100   EXPECT_FALSE(readable_tracker.last_known_state().peer_closed());
101 
102   // Now read the message, which will ultimately trigger the pipe becoming
103   // unreadable.
104   std::vector<uint8_t> bytes;
105   ReadMessageRaw(pipe.handle0.get(), &bytes, nullptr,
106                  MOJO_READ_MESSAGE_FLAG_NONE);
107   WaitForNextNotification(&readable_tracker);
108   EXPECT_FALSE(readable_tracker.last_known_state().readable());
109 
110   // And note that the |peer_closed_tracker| should not have seen the readable
111   // state change above since it's not relevant to its tracked signal.
112   EXPECT_TRUE(peer_closed_tracker.last_known_state().readable());
113 }
114 
115 }  // namespace
116 }  // namespace mojo
117