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

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: revert RequestContext usage, nits 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
« no previous file with comments | « mojo/edk/system/request_context.cc ('k') | mojo/edk/system/watcher.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // A test helper class for watching a handle. The WatchHelper instance is used
24 // as a watch context for a single watch callback.
25 class WatchHelper {
26 public:
27 using Callback =
28 std::function<void(MojoResult result, MojoHandleSignalsState state)>;
29
30 WatchHelper() {}
31 ~WatchHelper() {
32 CHECK(!watching_);
33 }
34
35 void Watch(MojoHandle handle,
36 MojoHandleSignals signals,
37 const Callback& callback) {
38 CHECK(!watching_);
39
40 handle_ = handle;
41 callback_ = callback;
42 watching_ = true;
43 CHECK_EQ(MOJO_RESULT_OK, MojoWatch(handle_, signals, &WatchHelper::OnNotify,
44 reinterpret_cast<uintptr_t>(this)));
45 }
46
47 bool is_watching() const { return watching_; }
48
49 void Cancel() {
50 CHECK_EQ(MOJO_RESULT_OK,
51 MojoCancelWatch(handle_, reinterpret_cast<uintptr_t>(this)));
52 CHECK(watching_);
53 watching_ = false;
54 }
55
56 private:
57 static void OnNotify(uintptr_t context,
58 MojoResult result,
59 MojoHandleSignalsState state) {
60 WatchHelper* watcher = reinterpret_cast<WatchHelper*>(context);
61 CHECK(watcher->watching_);
62 if (result == MOJO_RESULT_CANCELLED)
63 watcher->watching_ = false;
64 watcher->callback_(result, state);
65 }
66
67 bool watching_ = false;
68 MojoHandle handle_;
69 Callback callback_;
70
71 DISALLOW_COPY_AND_ASSIGN(WatchHelper);
72 };
73
74 class WatchTest : public test::MojoTestBase {
75 public:
76 WatchTest() {}
77 ~WatchTest() override {}
78
79 protected:
80
81 private:
82 base::MessageLoop message_loop_;
83
84 DISALLOW_COPY_AND_ASSIGN(WatchTest);
85 };
86
87 TEST_F(WatchTest, NotifyBasic) {
88 MojoHandle a, b;
89 CreateMessagePipe(&a, &b);
90
91 base::RunLoop loop;
92 WatchHelper b_watcher;
93 b_watcher.Watch(
94 b, MOJO_HANDLE_SIGNAL_READABLE,
95 [&] (MojoResult result, MojoHandleSignalsState state) {
96 EXPECT_EQ(MOJO_RESULT_OK, result);
97 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
98 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
99 EXPECT_TRUE(b_watcher.is_watching());
100 loop.Quit();
101 });
102
103 WriteMessage(a, "Hello!");
104 loop.Run();
105
106 EXPECT_TRUE(b_watcher.is_watching());
107 b_watcher.Cancel();
108
109 CloseHandle(a);
110 CloseHandle(b);
111 }
112
113 TEST_F(WatchTest, NotifyUnsatisfiable) {
114 MojoHandle a, b;
115 CreateMessagePipe(&a, &b);
116
117 base::RunLoop loop;
118 WatchHelper b_watcher;
119 b_watcher.Watch(
120 b, MOJO_HANDLE_SIGNAL_READABLE,
121 [&] (MojoResult result, MojoHandleSignalsState state) {
122 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
123 EXPECT_EQ(0u,
124 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
125 EXPECT_EQ(0u,
126 state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
127 EXPECT_TRUE(b_watcher.is_watching());
128 loop.Quit();
129 });
130
131 CloseHandle(a);
132 loop.Run();
133
134 b_watcher.Cancel();
135
136 CloseHandle(b);
137 }
138
139 TEST_F(WatchTest, NotifyCancellation) {
140 MojoHandle a, b;
141 CreateMessagePipe(&a, &b);
142
143 base::RunLoop loop;
144 WatchHelper b_watcher;
145 b_watcher.Watch(
146 b, MOJO_HANDLE_SIGNAL_READABLE,
147 [&] (MojoResult result, MojoHandleSignalsState state) {
148 EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
149 EXPECT_EQ(0u, state.satisfied_signals);
150 EXPECT_EQ(0u, state.satisfiable_signals);
151 EXPECT_FALSE(b_watcher.is_watching());
152 loop.Quit();
153 });
154
155 CloseHandle(b);
156 loop.Run();
157
158 CloseHandle(a);
159 }
160
161 TEST_F(WatchTest, InvalidArguemnts) {
162 MojoHandle a, b;
163 CreateMessagePipe(&a, &b);
164
165 uintptr_t context = reinterpret_cast<uintptr_t>(this);
166 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(a, MOJO_HANDLE_SIGNAL_READABLE,
167 &IgnoreResult, context));
168
169 // Can't cancel a watch that doesn't exist.
170 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCancelWatch(a, ~context));
171 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCancelWatch(b, context));
172
173 CloseHandle(a);
174 CloseHandle(b);
175
176 // Can't watch a handle that doesn't exist.
177 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
178 MojoWatch(a, MOJO_HANDLE_SIGNAL_READABLE, &IgnoreResult, context));
179 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
180 MojoWatch(b, MOJO_HANDLE_SIGNAL_READABLE, &IgnoreResult, context));
181 }
182
183 TEST_F(WatchTest, NoDuplicateContext) {
184 MojoHandle a, b;
185 CreateMessagePipe(&a, &b);
186
187 // Try to add the same watch twice; should fail.
188 uintptr_t context = reinterpret_cast<uintptr_t>(this);
189 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(a, MOJO_HANDLE_SIGNAL_READABLE,
190 &IgnoreResult, context));
191 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
192 MojoWatch(a, MOJO_HANDLE_SIGNAL_READABLE, &IgnoreResult, context));
193
194 // Cancel and add it again; should be OK.
195 EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(a, context));
196 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(a, MOJO_HANDLE_SIGNAL_READABLE,
197 &IgnoreResult, context));
198
199 CloseHandle(a);
200 CloseHandle(b);
201 }
202
203 TEST_F(WatchTest, MultipleWatches) {
204 MojoHandle a, b;
205 CreateMessagePipe(&a, &b);
206
207 // Add multiple watchers to |b| and see that they are both notified by a
208 // single write to |a|.
209 base::RunLoop loop;
210 int expected_notifications = 2;
211 auto on_readable = [&] (MojoResult result, MojoHandleSignalsState state) {
212 EXPECT_EQ(MOJO_RESULT_OK, result);
213 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
214 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
215 EXPECT_GT(expected_notifications, 0);
216 if (--expected_notifications == 0)
217 loop.Quit();
218 };
219 WatchHelper watcher1;
220 WatchHelper watcher2;
221 watcher1.Watch(b, MOJO_HANDLE_SIGNAL_READABLE, on_readable);
222 watcher2.Watch(b, MOJO_HANDLE_SIGNAL_READABLE, on_readable);
223
224 WriteMessage(a, "Ping!");
225 loop.Run();
226
227 watcher1.Cancel();
228 watcher2.Cancel();
229
230 CloseHandle(a);
231 CloseHandle(b);
232 }
233
234 TEST_F(WatchTest, WatchWhileSatisfied) {
235 MojoHandle a, b;
236 CreateMessagePipe(&a, &b);
237
238 // Write to |a| and then start watching |b|. The callback should be invoked
239 // synchronously.
240 WriteMessage(a, "hey");
241 bool signaled = false;
242 WatchHelper b_watcher;
243 b_watcher.Watch(
244 b, MOJO_HANDLE_SIGNAL_READABLE,
245 [&] (MojoResult result, MojoHandleSignalsState state) {
246 EXPECT_EQ(MOJO_RESULT_OK, result);
247 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
248 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
249 signaled = true;
250 });
251 EXPECT_TRUE(signaled);
252 b_watcher.Cancel();
253
254 CloseHandle(a);
255 CloseHandle(b);
256 }
257
258 TEST_F(WatchTest, WatchWhileUnsatisfiable) {
259 MojoHandle a, b;
260 CreateMessagePipe(&a, &b);
261
262 // Close |a| and then try to watch |b|. MojoWatch() should fail.
263 CloseHandle(a);
264 uintptr_t context = reinterpret_cast<uintptr_t>(this);
265 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
266 MojoWatch(b, MOJO_HANDLE_SIGNAL_READABLE, &IgnoreResult, context));
267
268 CloseHandle(b);
269 }
270
271 TEST_F(WatchTest, RespondFromCallback) {
272 MojoHandle a, b;
273 CreateMessagePipe(&a, &b);
274
275 // Watch |a| and |b|. Write to |a|, then write to |b| from within the callback
276 // which notifies it of the available message.
277 const std::string kTestMessage = "hello worlds.";
278 base::RunLoop loop;
279 WatchHelper b_watcher;
280 b_watcher.Watch(
281 b, MOJO_HANDLE_SIGNAL_READABLE,
282 [&] (MojoResult result, MojoHandleSignalsState state) {
283 EXPECT_EQ(MOJO_RESULT_OK, result);
284 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
285 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
286 EXPECT_TRUE(b_watcher.is_watching());
287
288 // Echo a's message back to it.
289 WriteMessage(b, ReadMessage(b));
290 });
291
292 WatchHelper a_watcher;
293 a_watcher.Watch(
294 a, MOJO_HANDLE_SIGNAL_READABLE,
295 [&] (MojoResult result, MojoHandleSignalsState state) {
296 EXPECT_EQ(MOJO_RESULT_OK, result);
297 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
298 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
299 EXPECT_TRUE(a_watcher.is_watching());
300
301 // Expect to receive back the message that was originally sent to |b|.
302 EXPECT_EQ(kTestMessage, ReadMessage(a));
303
304 loop.Quit();
305 });
306
307 WriteMessage(a, kTestMessage);
308 loop.Run();
309
310 a_watcher.Cancel();
311 b_watcher.Cancel();
312
313 CloseHandle(a);
314 CloseHandle(b);
315 }
316
317 TEST_F(WatchTest, WatchDataPipeConsumer) {
318 MojoHandle a, b;
319 CreateDataPipe(&a, &b, 64);
320
321 base::RunLoop loop;
322 WatchHelper b_watcher;
323 b_watcher.Watch(
324 b, MOJO_HANDLE_SIGNAL_READABLE,
325 [&] (MojoResult result, MojoHandleSignalsState state) {
326 EXPECT_EQ(MOJO_RESULT_OK, result);
327 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
328 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
329 EXPECT_TRUE(b_watcher.is_watching());
330 loop.Quit();
331 });
332
333 WriteData(a, "Hello!");
334 loop.Run();
335
336 EXPECT_TRUE(b_watcher.is_watching());
337 b_watcher.Cancel();
338
339 CloseHandle(a);
340 CloseHandle(b);
341 }
342
343 TEST_F(WatchTest, WatchDataPipeProducer) {
344 MojoHandle a, b;
345 CreateDataPipe(&a, &b, 8);
346
347 // Fill the pipe to capacity so writes will block.
348 WriteData(a, "xxxxxxxx");
349
350 base::RunLoop loop;
351 WatchHelper a_watcher;
352 a_watcher.Watch(
353 a, MOJO_HANDLE_SIGNAL_WRITABLE,
354 [&] (MojoResult result, MojoHandleSignalsState state) {
355 EXPECT_EQ(MOJO_RESULT_OK, result);
356 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE,
357 state.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
358 EXPECT_TRUE(a_watcher.is_watching());
359 loop.Quit();
360 });
361
362 EXPECT_EQ("xxxxxxxx", ReadData(b, 8));
363 loop.Run();
364
365 EXPECT_TRUE(a_watcher.is_watching());
366 a_watcher.Cancel();
367
368 CloseHandle(a);
369 CloseHandle(b);
370 }
371
372 } // namespace
373 } // namespace edk
374 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/request_context.cc ('k') | mojo/edk/system/watcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698