OLD | NEW |
| (Empty) |
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/simple_watcher.h" | |
6 | |
7 #include <memory> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/callback.h" | |
11 #include "base/macros.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/run_loop.h" | |
14 #include "base/threading/thread_task_runner_handle.h" | |
15 #include "mojo/public/c/system/types.h" | |
16 #include "mojo/public/cpp/system/message_pipe.h" | |
17 #include "testing/gtest/include/gtest/gtest.h" | |
18 | |
19 namespace mojo { | |
20 namespace { | |
21 | |
22 template <typename Handler> | |
23 void RunResultHandler(Handler f, MojoResult result) { | |
24 f(result); | |
25 } | |
26 | |
27 template <typename Handler> | |
28 SimpleWatcher::ReadyCallback OnReady(Handler f) { | |
29 return base::Bind(&RunResultHandler<Handler>, f); | |
30 } | |
31 | |
32 SimpleWatcher::ReadyCallback NotReached() { | |
33 return OnReady([](MojoResult) { NOTREACHED(); }); | |
34 } | |
35 | |
36 class SimpleWatcherTest : public testing::Test { | |
37 public: | |
38 SimpleWatcherTest() {} | |
39 ~SimpleWatcherTest() override {} | |
40 | |
41 private: | |
42 base::MessageLoop message_loop_; | |
43 | |
44 DISALLOW_COPY_AND_ASSIGN(SimpleWatcherTest); | |
45 }; | |
46 | |
47 TEST_F(SimpleWatcherTest, WatchBasic) { | |
48 ScopedMessagePipeHandle a, b; | |
49 CreateMessagePipe(nullptr, &a, &b); | |
50 | |
51 bool notified = false; | |
52 base::RunLoop run_loop; | |
53 SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); | |
54 EXPECT_EQ(MOJO_RESULT_OK, | |
55 b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, | |
56 OnReady([&](MojoResult result) { | |
57 EXPECT_EQ(MOJO_RESULT_OK, result); | |
58 notified = true; | |
59 run_loop.Quit(); | |
60 }))); | |
61 EXPECT_TRUE(b_watcher.IsWatching()); | |
62 | |
63 EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, | |
64 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
65 run_loop.Run(); | |
66 EXPECT_TRUE(notified); | |
67 | |
68 b_watcher.Cancel(); | |
69 } | |
70 | |
71 TEST_F(SimpleWatcherTest, WatchUnsatisfiable) { | |
72 ScopedMessagePipeHandle a, b; | |
73 CreateMessagePipe(nullptr, &a, &b); | |
74 a.reset(); | |
75 | |
76 SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL); | |
77 EXPECT_EQ( | |
78 MOJO_RESULT_OK, | |
79 b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, NotReached())); | |
80 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, b_watcher.Arm()); | |
81 } | |
82 | |
83 TEST_F(SimpleWatcherTest, WatchInvalidHandle) { | |
84 ScopedMessagePipeHandle a, b; | |
85 CreateMessagePipe(nullptr, &a, &b); | |
86 a.reset(); | |
87 b.reset(); | |
88 | |
89 SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); | |
90 EXPECT_EQ( | |
91 MOJO_RESULT_INVALID_ARGUMENT, | |
92 b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, NotReached())); | |
93 EXPECT_FALSE(b_watcher.IsWatching()); | |
94 } | |
95 | |
96 TEST_F(SimpleWatcherTest, Cancel) { | |
97 ScopedMessagePipeHandle a, b; | |
98 CreateMessagePipe(nullptr, &a, &b); | |
99 | |
100 base::RunLoop run_loop; | |
101 SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); | |
102 EXPECT_EQ( | |
103 MOJO_RESULT_OK, | |
104 b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, NotReached())); | |
105 EXPECT_TRUE(b_watcher.IsWatching()); | |
106 b_watcher.Cancel(); | |
107 EXPECT_FALSE(b_watcher.IsWatching()); | |
108 | |
109 // This should never trigger the watcher. | |
110 EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, | |
111 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
112 | |
113 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | |
114 run_loop.QuitClosure()); | |
115 run_loop.Run(); | |
116 } | |
117 | |
118 TEST_F(SimpleWatcherTest, CancelOnClose) { | |
119 ScopedMessagePipeHandle a, b; | |
120 CreateMessagePipe(nullptr, &a, &b); | |
121 | |
122 base::RunLoop run_loop; | |
123 SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); | |
124 EXPECT_EQ(MOJO_RESULT_OK, | |
125 b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, | |
126 OnReady([&](MojoResult result) { | |
127 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | |
128 run_loop.Quit(); | |
129 }))); | |
130 EXPECT_TRUE(b_watcher.IsWatching()); | |
131 | |
132 // This should trigger the watcher above. | |
133 b.reset(); | |
134 | |
135 run_loop.Run(); | |
136 | |
137 EXPECT_FALSE(b_watcher.IsWatching()); | |
138 } | |
139 | |
140 TEST_F(SimpleWatcherTest, CancelOnDestruction) { | |
141 ScopedMessagePipeHandle a, b; | |
142 CreateMessagePipe(nullptr, &a, &b); | |
143 base::RunLoop run_loop; | |
144 { | |
145 SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); | |
146 EXPECT_EQ( | |
147 MOJO_RESULT_OK, | |
148 b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, NotReached())); | |
149 EXPECT_TRUE(b_watcher.IsWatching()); | |
150 | |
151 // |b_watcher| should be cancelled when it goes out of scope. | |
152 } | |
153 | |
154 // This should never trigger the watcher above. | |
155 EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, | |
156 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
157 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | |
158 run_loop.QuitClosure()); | |
159 run_loop.Run(); | |
160 } | |
161 | |
162 TEST_F(SimpleWatcherTest, CloseAndCancel) { | |
163 ScopedMessagePipeHandle a, b; | |
164 CreateMessagePipe(nullptr, &a, &b); | |
165 | |
166 SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); | |
167 EXPECT_EQ(MOJO_RESULT_OK, | |
168 b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, | |
169 OnReady([](MojoResult result) { FAIL(); }))); | |
170 EXPECT_TRUE(b_watcher.IsWatching()); | |
171 | |
172 // This should trigger the watcher above... | |
173 b.reset(); | |
174 // ...but the watcher is cancelled first. | |
175 b_watcher.Cancel(); | |
176 | |
177 EXPECT_FALSE(b_watcher.IsWatching()); | |
178 | |
179 base::RunLoop().RunUntilIdle(); | |
180 } | |
181 | |
182 TEST_F(SimpleWatcherTest, UnarmedCancel) { | |
183 ScopedMessagePipeHandle a, b; | |
184 CreateMessagePipe(nullptr, &a, &b); | |
185 | |
186 SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL); | |
187 base::RunLoop loop; | |
188 EXPECT_EQ(MOJO_RESULT_OK, | |
189 b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, | |
190 base::Bind( | |
191 [](base::RunLoop* loop, MojoResult result) { | |
192 EXPECT_EQ(result, MOJO_RESULT_CANCELLED); | |
193 loop->Quit(); | |
194 }, | |
195 &loop))); | |
196 | |
197 // This message write will not wake up the watcher since the watcher isn't | |
198 // armed. Instead, the cancellation will dispatch due to the reset below. | |
199 EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, | |
200 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
201 b.reset(); | |
202 loop.Run(); | |
203 } | |
204 | |
205 TEST_F(SimpleWatcherTest, ManualArming) { | |
206 ScopedMessagePipeHandle a, b; | |
207 CreateMessagePipe(nullptr, &a, &b); | |
208 | |
209 SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL); | |
210 base::RunLoop loop; | |
211 EXPECT_EQ(MOJO_RESULT_OK, | |
212 b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, | |
213 base::Bind( | |
214 [](base::RunLoop* loop, MojoResult result) { | |
215 EXPECT_EQ(result, MOJO_RESULT_OK); | |
216 loop->Quit(); | |
217 }, | |
218 &loop))); | |
219 EXPECT_EQ(MOJO_RESULT_OK, b_watcher.Arm()); | |
220 | |
221 EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, | |
222 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
223 loop.Run(); | |
224 } | |
225 | |
226 TEST_F(SimpleWatcherTest, ManualArmOrNotifyWhileSignaled) { | |
227 ScopedMessagePipeHandle a, b; | |
228 CreateMessagePipe(nullptr, &a, &b); | |
229 | |
230 base::RunLoop loop1; | |
231 SimpleWatcher b_watcher1(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL); | |
232 bool notified1 = false; | |
233 EXPECT_EQ(MOJO_RESULT_OK, | |
234 b_watcher1.Watch( | |
235 b.get(), MOJO_HANDLE_SIGNAL_READABLE, | |
236 base::Bind( | |
237 [](base::RunLoop* loop, bool* notified, MojoResult result) { | |
238 EXPECT_EQ(result, MOJO_RESULT_OK); | |
239 *notified = true; | |
240 loop->Quit(); | |
241 }, | |
242 &loop1, ¬ified1))); | |
243 | |
244 base::RunLoop loop2; | |
245 SimpleWatcher b_watcher2(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL); | |
246 bool notified2 = false; | |
247 EXPECT_EQ(MOJO_RESULT_OK, | |
248 b_watcher2.Watch( | |
249 b.get(), MOJO_HANDLE_SIGNAL_READABLE, | |
250 base::Bind( | |
251 [](base::RunLoop* loop, bool* notified, MojoResult result) { | |
252 EXPECT_EQ(result, MOJO_RESULT_OK); | |
253 *notified = true; | |
254 loop->Quit(); | |
255 }, | |
256 &loop2, ¬ified2))); | |
257 | |
258 // First ensure that |b| is readable. | |
259 EXPECT_EQ(MOJO_RESULT_OK, b_watcher1.Arm()); | |
260 EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, | |
261 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
262 loop1.Run(); | |
263 | |
264 EXPECT_TRUE(notified1); | |
265 EXPECT_FALSE(notified2); | |
266 notified1 = false; | |
267 | |
268 // Now verify that ArmOrNotify results in a notification. | |
269 b_watcher2.ArmOrNotify(); | |
270 loop2.Run(); | |
271 | |
272 EXPECT_FALSE(notified1); | |
273 EXPECT_TRUE(notified2); | |
274 } | |
275 | |
276 } // namespace | |
277 } // namespace mojo | |
OLD | NEW |