Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1210)

Side by Side Diff: mojo/edk/system/watch_unittest.cc

Issue 1748503002: [mojo-edk] Add MojoWatch and MojoCancelWatch APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 <functional>
6
7 #include "base/macros.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "mojo/edk/test/mojo_test_base.h"
11 #include "mojo/public/c/system/functions.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace mojo {
15 namespace edk {
16 namespace {
17
18 void IgnoreResult(uintptr_t context,
19 MojoResult result,
20 MojoHandleSignalsState signals) {
21 }
22
23 class Watcher {
24 public:
25 using Callback =
26 std::function<void(MojoResult result, MojoHandleSignalsState state)>;
27
28 Watcher(MojoHandle handle,
29 MojoHandleSignals signals,
30 const Callback& callback)
31 : handle_(handle), callback_(callback) {
32 watching_ = true;
33 CHECK_EQ(MOJO_RESULT_OK, MojoWatch(handle_, signals, &Watcher::OnNotify,
34 reinterpret_cast<uintptr_t>(this)));
35 }
36
37 ~Watcher() {
38 if (watching_)
39 Cancel();
40 }
41
42 bool is_watching() const { return watching_; }
43
44 void Cancel() {
45 CHECK(watching_);
46 watching_ = false;
47 CHECK_EQ(MOJO_RESULT_OK,
48 MojoCancelWatch(handle_, reinterpret_cast<uintptr_t>(this)));
49 }
50
51 private:
52 static void OnNotify(uintptr_t context,
53 MojoResult result,
54 MojoHandleSignalsState state) {
55 Watcher* watcher = reinterpret_cast<Watcher*>(context);
56 CHECK(watcher->watching_);
57 if (result == MOJO_RESULT_CANCELLED)
58 watcher->watching_ = false;
59 watcher->callback_(result, state);
60 }
61
62 bool watching_ = false;
63 MojoHandle handle_;
64 Callback callback_;
65
66 DISALLOW_COPY_AND_ASSIGN(Watcher);
67 };
68
69 class WatchTest : public test::MojoTestBase {
70 public:
71 WatchTest() {}
72 ~WatchTest() override {}
73
74 protected:
75
76 private:
77 base::MessageLoop message_loop_;
78
79 DISALLOW_COPY_AND_ASSIGN(WatchTest);
80 };
81
82 TEST_F(WatchTest, NotifyBasic) {
83 MojoHandle a, b;
84 CreateMessagePipe(&a, &b);
85
86 base::RunLoop loop;
87 Watcher b_watcher(
88 b, MOJO_HANDLE_SIGNAL_READABLE,
89 [&] (MojoResult result, MojoHandleSignalsState state) {
90 EXPECT_EQ(MOJO_RESULT_OK, result);
91 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
92 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
93 EXPECT_TRUE(b_watcher.is_watching());
94 loop.Quit();
95 });
96
97 WriteMessage(a, "Hello!");
98 loop.Run();
99
100 EXPECT_TRUE(b_watcher.is_watching());
101 b_watcher.Cancel();
102
103 CloseHandle(a);
104 CloseHandle(b);
105 }
106
107 TEST_F(WatchTest, NotifyUnsatisfiable) {
108 MojoHandle a, b;
109 CreateMessagePipe(&a, &b);
110
111 base::RunLoop loop;
112 Watcher b_watcher(
113 b, MOJO_HANDLE_SIGNAL_READABLE,
114 [&] (MojoResult result, MojoHandleSignalsState state) {
115 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
116 EXPECT_EQ(0u,
117 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
118 EXPECT_EQ(0u,
119 state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
120 EXPECT_TRUE(b_watcher.is_watching());
121 loop.Quit();
122 });
123
124 CloseHandle(a);
125 loop.Run();
126
127 b_watcher.Cancel();
128
129 CloseHandle(b);
130 }
131
132 TEST_F(WatchTest, NotifyCancellation) {
133 MojoHandle a, b;
134 CreateMessagePipe(&a, &b);
135
136 base::RunLoop loop;
137 Watcher b_watcher(
138 b, MOJO_HANDLE_SIGNAL_READABLE,
139 [&] (MojoResult result, MojoHandleSignalsState state) {
140 EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
141 EXPECT_EQ(0u, state.satisfied_signals);
142 EXPECT_EQ(0u, state.satisfiable_signals);
143 EXPECT_FALSE(b_watcher.is_watching());
144 loop.Quit();
145 });
146
147 CloseHandle(b);
148 loop.Run();
149
150 CloseHandle(a);
151 }
152
153 TEST_F(WatchTest, InvalidArguemnts) {
154 MojoHandle a, b;
155 CreateMessagePipe(&a, &b);
156
157 uintptr_t context = reinterpret_cast<uintptr_t>(this);
158 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(a, MOJO_HANDLE_SIGNAL_READABLE,
159 &IgnoreResult, context));
160
161 // Can't cancel a watch that doesn't exist.
162 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCancelWatch(a, ~context));
163 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCancelWatch(b, context));
164
165 CloseHandle(a);
166 CloseHandle(b);
167
168 // Can't watch a handle that doesn't exist.
169 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
170 MojoWatch(a, MOJO_HANDLE_SIGNAL_READABLE, &IgnoreResult, context));
171 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
172 MojoWatch(b, MOJO_HANDLE_SIGNAL_READABLE, &IgnoreResult, context));
173 }
174
175 TEST_F(WatchTest, NoDuplicateContext) {
176 MojoHandle a, b;
177 CreateMessagePipe(&a, &b);
178
179 // Try to add the same watch twice; should fail.
180 uintptr_t context = reinterpret_cast<uintptr_t>(this);
181 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(a, MOJO_HANDLE_SIGNAL_READABLE,
182 &IgnoreResult, context));
183 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
184 MojoWatch(a, MOJO_HANDLE_SIGNAL_READABLE, &IgnoreResult, context));
185
186 // Cancel and add it again; should be OK.
187 EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(a, context));
188 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(a, MOJO_HANDLE_SIGNAL_READABLE,
189 &IgnoreResult, context));
190
191 CloseHandle(a);
192 CloseHandle(b);
193 }
194
195 TEST_F(WatchTest, MultipleWatchers) {
196 MojoHandle a, b;
197 CreateMessagePipe(&a, &b);
198
199 // Add multiple watchers to |b| and see that they are both notified by a
200 // single write to |a|.
201 base::RunLoop loop;
202 int expected_notifications = 2;
203 auto on_readable = [&] (MojoResult result, MojoHandleSignalsState state) {
204 EXPECT_EQ(MOJO_RESULT_OK, result);
205 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
206 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
207 EXPECT_GT(expected_notifications, 0);
208 if (--expected_notifications == 0)
209 loop.Quit();
210 };
211 Watcher watcher1(b, MOJO_HANDLE_SIGNAL_READABLE, on_readable);
212 Watcher watcher2(b, MOJO_HANDLE_SIGNAL_READABLE, on_readable);
213
214 WriteMessage(a, "Ping!");
215 loop.Run();
216
217 watcher1.Cancel();
218 watcher2.Cancel();
219
220 CloseHandle(a);
221 CloseHandle(b);
222 }
223
224 TEST_F(WatchTest, WatchWhileSatisfied) {
225 MojoHandle a, b;
226 CreateMessagePipe(&a, &b);
227
228 // Write to |a| and then start watching |b|. The callback should be invoked
229 // synchronously.
230 WriteMessage(a, "hey");
231 bool signaled = false;
232 Watcher b_watcher(
233 b, MOJO_HANDLE_SIGNAL_READABLE,
234 [&] (MojoResult result, MojoHandleSignalsState state) {
235 EXPECT_EQ(MOJO_RESULT_OK, result);
236 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
237 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
238 signaled = true;
239 });
240 EXPECT_TRUE(signaled);
241 b_watcher.Cancel();
242
243 CloseHandle(a);
244 CloseHandle(b);
245 }
246
247 TEST_F(WatchTest, WatchWhileUnsatisfiable) {
248 MojoHandle a, b;
249 CreateMessagePipe(&a, &b);
250
251 // Close |a| and then try to watch |b|. MojoWatch() should fail.
252 CloseHandle(a);
253 uintptr_t context = reinterpret_cast<uintptr_t>(this);
254 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
255 MojoWatch(b, MOJO_HANDLE_SIGNAL_READABLE, &IgnoreResult, context));
256
257 CloseHandle(b);
258 }
259
260 TEST_F(WatchTest, CancelFromCallback) {
261 MojoHandle a, b;
262 CreateMessagePipe(&a, &b);
263
264 // Verify that we can safely cancel the watcher from within its own callback.
265 base::RunLoop loop;
266 Watcher b_watcher(
267 b, MOJO_HANDLE_SIGNAL_READABLE,
268 [&] (MojoResult result, MojoHandleSignalsState state) {
269 EXPECT_EQ(MOJO_RESULT_OK, result);
270 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
271 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
272 EXPECT_TRUE(b_watcher.is_watching());
273 b_watcher.Cancel();
274 loop.Quit();
275 });
276 WriteMessage(a, "hey!");
277 loop.Run();
278
279 CloseHandle(b);
280 }
281
282 TEST_F(WatchTest, RespondFromCallback) {
283 MojoHandle a, b;
284 CreateMessagePipe(&a, &b);
285
286 // Watch |a| and |b|. Write to |a|, then write to |b| from within the callback
287 // which notifies it of the available message. Then cancel both watchers from
288 // |a|'s callback before quitting.
289 const std::string kTestMessage = "hello worlds.";
290 base::RunLoop loop;
291 Watcher b_watcher(
292 b, MOJO_HANDLE_SIGNAL_READABLE,
293 [&] (MojoResult result, MojoHandleSignalsState state) {
294 EXPECT_EQ(MOJO_RESULT_OK, result);
295 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
296 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
297 EXPECT_TRUE(b_watcher.is_watching());
298
299 // Echo a's message back to it.
300 WriteMessage(b, ReadMessage(b));
301 });
302
303 Watcher a_watcher(
304 a, MOJO_HANDLE_SIGNAL_READABLE,
305 [&] (MojoResult result, MojoHandleSignalsState state) {
306 EXPECT_EQ(MOJO_RESULT_OK, result);
307 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
308 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
309 EXPECT_TRUE(a_watcher.is_watching());
310
311 // Expect to receive back the message that was originally sent to |b|.
312 EXPECT_EQ(kTestMessage, ReadMessage(a));
313
314 a_watcher.Cancel();
315 b_watcher.Cancel();
316
317 loop.Quit();
318 });
319
320 WriteMessage(a, kTestMessage);
321 loop.Run();
322
323 CloseHandle(a);
324 CloseHandle(b);
325 }
326
327 } // namespace
328 } // namespace edk
329 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698