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