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

Side by Side Diff: mojo/public/cpp/utility/tests/run_loop_unittest.cc

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 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/public/cpp/utility/tests/BUILD.gn ('k') | mojo/public/dart/.analysis_options » ('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 2014 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/utility/run_loop.h"
6
7 #include <string>
8
9 #include "gtest/gtest.h"
10 #include "mojo/public/cpp/system/macros.h"
11 #include "mojo/public/cpp/system/message_pipe.h"
12 #include "mojo/public/cpp/test_support/test_utils.h"
13 #include "mojo/public/cpp/utility/run_loop_handler.h"
14
15 namespace mojo {
16 namespace {
17
18 class TestRunLoopHandler : public RunLoopHandler {
19 public:
20 TestRunLoopHandler() {}
21 ~TestRunLoopHandler() override {}
22
23 void clear_ready_count() { ready_count_ = 0; }
24 int ready_count() const { return ready_count_; }
25
26 void clear_error_count() { error_count_ = 0; }
27 int error_count() const { return error_count_; }
28
29 void clear_expected_handler_id() { have_expected_handler_id_ = false; }
30 void set_expected_handler_id(Id id) {
31 have_expected_handler_id_ = true;
32 expected_handler_id_ = id;
33 }
34
35 MojoResult last_error_result() const { return last_error_result_; }
36
37 // RunLoopHandler:
38 void OnHandleReady(Id id) override {
39 ready_count_++;
40 if (have_expected_handler_id_) {
41 EXPECT_EQ(expected_handler_id_, id);
42 clear_expected_handler_id();
43 }
44 }
45
46 void OnHandleError(Id id, MojoResult result) override {
47 error_count_++;
48 last_error_result_ = result;
49 if (have_expected_handler_id_) {
50 EXPECT_EQ(expected_handler_id_, id);
51 clear_expected_handler_id();
52 }
53 }
54
55 private:
56 int ready_count_ = 0;
57 int error_count_ = 0;
58 bool have_expected_handler_id_ = false;
59 Id expected_handler_id_ = 0u;
60 MojoResult last_error_result_ = MOJO_RESULT_OK;
61
62 MOJO_DISALLOW_COPY_AND_ASSIGN(TestRunLoopHandler);
63 };
64
65 // Trivial test to verify Run() with no added handles returns.
66 TEST(RunLoopTest, ExitsWithNoHandles) {
67 RunLoop run_loop;
68 run_loop.Run();
69 }
70
71 class RemoveOnReadyRunLoopHandler : public TestRunLoopHandler {
72 public:
73 RemoveOnReadyRunLoopHandler() : run_loop_(nullptr) {}
74 ~RemoveOnReadyRunLoopHandler() override {}
75
76 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
77
78 // RunLoopHandler:
79 void OnHandleReady(Id id) override {
80 run_loop_->RemoveHandler(id);
81 TestRunLoopHandler::OnHandleReady(id);
82 }
83
84 private:
85 RunLoop* run_loop_;
86
87 MOJO_DISALLOW_COPY_AND_ASSIGN(RemoveOnReadyRunLoopHandler);
88 };
89
90 // Verifies RunLoop quits when no more handles (handle is removed when ready).
91 TEST(RunLoopTest, HandleReady) {
92 RemoveOnReadyRunLoopHandler handler;
93 MessagePipe test_pipe;
94 EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
95
96 RunLoop run_loop;
97 handler.set_run_loop(&run_loop);
98 auto id = run_loop.AddHandler(&handler, test_pipe.handle0.get(),
99 MOJO_HANDLE_SIGNAL_READABLE,
100 MOJO_DEADLINE_INDEFINITE);
101 handler.set_expected_handler_id(id);
102 run_loop.Run();
103 EXPECT_EQ(1, handler.ready_count());
104 EXPECT_EQ(0, handler.error_count());
105 EXPECT_EQ(0u, run_loop.num_handlers());
106 }
107
108 class QuitOnReadyRunLoopHandler : public TestRunLoopHandler {
109 public:
110 QuitOnReadyRunLoopHandler() {}
111 ~QuitOnReadyRunLoopHandler() override {}
112
113 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
114
115 // RunLoopHandler:
116 void OnHandleReady(Id id) override {
117 run_loop_->Quit();
118 TestRunLoopHandler::OnHandleReady(id);
119 }
120
121 private:
122 RunLoop* run_loop_ = nullptr;
123
124 MOJO_DISALLOW_COPY_AND_ASSIGN(QuitOnReadyRunLoopHandler);
125 };
126
127 // Verifies Quit() from OnHandleReady() quits the loop.
128 TEST(RunLoopTest, QuitFromReady) {
129 QuitOnReadyRunLoopHandler handler;
130 MessagePipe test_pipe;
131 EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
132
133 RunLoopHandler::Id id2;
134 {
135 RunLoop run_loop;
136 handler.set_run_loop(&run_loop);
137 auto id1 = run_loop.AddHandler(&handler, test_pipe.handle0.get(),
138 MOJO_HANDLE_SIGNAL_READABLE,
139 MOJO_DEADLINE_INDEFINITE);
140 handler.set_expected_handler_id(id1);
141 // Quitting should keep this handler.
142 id2 = run_loop.AddHandler(&handler, test_pipe.handle1.get(),
143 MOJO_HANDLE_SIGNAL_READABLE,
144 MOJO_DEADLINE_INDEFINITE);
145 EXPECT_NE(id2, id1);
146 run_loop.Run();
147 EXPECT_EQ(1, handler.ready_count());
148 EXPECT_EQ(0, handler.error_count());
149 EXPECT_EQ(1u, run_loop.num_handlers());
150
151 // Destroying the RunLoop should call the second handler's OnHandleError().
152 handler.set_expected_handler_id(id2);
153 }
154 }
155
156 class QuitOnErrorRunLoopHandler : public TestRunLoopHandler {
157 public:
158 QuitOnErrorRunLoopHandler() {}
159 ~QuitOnErrorRunLoopHandler() override {}
160
161 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
162
163 // RunLoopHandler:
164 void OnHandleError(Id id, MojoResult result) override {
165 run_loop_->Quit();
166 TestRunLoopHandler::OnHandleError(id, result);
167 }
168
169 private:
170 RunLoop* run_loop_ = nullptr;
171
172 MOJO_DISALLOW_COPY_AND_ASSIGN(QuitOnErrorRunLoopHandler);
173 };
174
175 // Verifies Quit() when the deadline is reached works.
176 TEST(RunLoopTest, QuitWhenDeadlineExpired) {
177 QuitOnErrorRunLoopHandler handler;
178 MessagePipe test_pipe;
179 RunLoop run_loop;
180 handler.set_run_loop(&run_loop);
181 auto id = run_loop.AddHandler(&handler, test_pipe.handle0.get(),
182 MOJO_HANDLE_SIGNAL_READABLE,
183 static_cast<MojoDeadline>(10000));
184 handler.set_expected_handler_id(id);
185 run_loop.Run();
186 EXPECT_EQ(0, handler.ready_count());
187 EXPECT_EQ(1, handler.error_count());
188 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, handler.last_error_result());
189 EXPECT_EQ(0u, run_loop.num_handlers());
190 }
191
192 // Test that handlers are notified of loop destruction.
193 TEST(RunLoopTest, Destruction) {
194 TestRunLoopHandler handler;
195 MessagePipe test_pipe;
196 {
197 RunLoop run_loop;
198 auto id = run_loop.AddHandler(&handler, test_pipe.handle0.get(),
199 MOJO_HANDLE_SIGNAL_READABLE,
200 MOJO_DEADLINE_INDEFINITE);
201 handler.set_expected_handler_id(id);
202 }
203 EXPECT_EQ(1, handler.error_count());
204 EXPECT_EQ(MOJO_RESULT_ABORTED, handler.last_error_result());
205 }
206
207 class RemoveManyRunLoopHandler : public TestRunLoopHandler {
208 public:
209 RemoveManyRunLoopHandler() {}
210 ~RemoveManyRunLoopHandler() override {}
211
212 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
213 void add_id(Id id) { ids_.push_back(id); }
214
215 // RunLoopHandler:
216 void OnHandleError(Id id, MojoResult result) override {
217 for (size_t i = 0; i < ids_.size(); i++)
218 run_loop_->RemoveHandler(ids_[i]);
219 TestRunLoopHandler::OnHandleError(id, result);
220 }
221
222 private:
223 std::vector<Id> ids_;
224 RunLoop* run_loop_ = nullptr;
225
226 MOJO_DISALLOW_COPY_AND_ASSIGN(RemoveManyRunLoopHandler);
227 };
228
229 // Test that handlers are notified of loop destruction.
230 TEST(RunLoopTest, MultipleHandleDestruction) {
231 RemoveManyRunLoopHandler odd_handler;
232 TestRunLoopHandler even_handler;
233 MessagePipe test_pipe1, test_pipe2, test_pipe3;
234 {
235 RunLoop run_loop;
236 odd_handler.set_run_loop(&run_loop);
237 odd_handler.add_id(run_loop.AddHandler(
238 &odd_handler, test_pipe1.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
239 MOJO_DEADLINE_INDEFINITE));
240 auto even_id = run_loop.AddHandler(&even_handler, test_pipe2.handle0.get(),
241 MOJO_HANDLE_SIGNAL_READABLE,
242 MOJO_DEADLINE_INDEFINITE);
243 even_handler.set_expected_handler_id(even_id);
244 odd_handler.add_id(run_loop.AddHandler(
245 &odd_handler, test_pipe3.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
246 MOJO_DEADLINE_INDEFINITE));
247 }
248 EXPECT_EQ(1, odd_handler.error_count());
249 EXPECT_EQ(1, even_handler.error_count());
250 EXPECT_EQ(MOJO_RESULT_ABORTED, odd_handler.last_error_result());
251 EXPECT_EQ(MOJO_RESULT_ABORTED, even_handler.last_error_result());
252 }
253
254 class AddHandlerOnErrorHandler : public TestRunLoopHandler {
255 public:
256 AddHandlerOnErrorHandler() {}
257 ~AddHandlerOnErrorHandler() override {}
258
259 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
260 void set_handle(Handle handle) { handle_ = handle; }
261
262 // RunLoopHandler:
263 void OnHandleError(Id id, MojoResult result) override {
264 EXPECT_EQ(MOJO_RESULT_ABORTED, result);
265
266 TestRunLoopHandler::OnHandleError(id, result);
267
268 if (!on_handle_error_was_called_) {
269 on_handle_error_was_called_ = true;
270 auto id = run_loop_->AddHandler(
271 this, handle_, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE);
272 set_expected_handler_id(id);
273 }
274 }
275
276 private:
277 RunLoop* run_loop_ = nullptr;
278 bool on_handle_error_was_called_ = false;
279 Handle handle_;
280
281 MOJO_DISALLOW_COPY_AND_ASSIGN(AddHandlerOnErrorHandler);
282 };
283
284 TEST(RunLoopTest, AddHandlerOnError) {
285 AddHandlerOnErrorHandler handler;
286 MessagePipe test_pipe;
287 {
288 RunLoop run_loop;
289 handler.set_run_loop(&run_loop);
290 handler.set_handle(test_pipe.handle0.get());
291 auto id = run_loop.AddHandler(&handler, test_pipe.handle0.get(),
292 MOJO_HANDLE_SIGNAL_READABLE,
293 MOJO_DEADLINE_INDEFINITE);
294 handler.set_expected_handler_id(id);
295 }
296 EXPECT_EQ(2, handler.error_count());
297 }
298
299 TEST(RunLoopTest, Current) {
300 EXPECT_TRUE(RunLoop::current() == nullptr);
301 {
302 RunLoop run_loop;
303 EXPECT_EQ(&run_loop, RunLoop::current());
304 }
305 EXPECT_TRUE(RunLoop::current() == nullptr);
306 }
307
308 class NestingRunLoopHandler : public TestRunLoopHandler {
309 public:
310 static constexpr size_t kDepthLimit = 10;
311 static constexpr char kSignalMagic = 'X';
312
313 NestingRunLoopHandler() {}
314 ~NestingRunLoopHandler() override {}
315
316 void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
317 void set_pipe(MessagePipe* pipe) { pipe_ = pipe; }
318 bool reached_depth_limit() const { return reached_depth_limit_; }
319
320 // RunLoopHandler:
321 void OnHandleReady(Id id) override {
322 TestRunLoopHandler::OnHandleReady(id);
323
324 ReadSignal();
325 size_t current_depth = ++depth_;
326 if (current_depth < kDepthLimit) {
327 AddHandlerAndWriteSignal();
328 run_loop_->Run();
329 // The innermost loop stops running due to Quit() being called; the outer
330 // loops stop running due to having no more handlers. No errors/timeouts
331 // should ever occur.
332 EXPECT_EQ(error_count(), 0);
333 } else {
334 EXPECT_EQ(current_depth, kDepthLimit);
335 reached_depth_limit_ = true;
336 run_loop_->Quit();
337 }
338 --depth_;
339 }
340
341 void AddHandlerAndWriteSignal() {
342 run_loop_->AddHandler(this, pipe_->handle0.get(),
343 MOJO_HANDLE_SIGNAL_READABLE,
344 static_cast<MojoDeadline>(10000));
345 MojoResult write_result =
346 WriteMessageRaw(pipe_->handle1.get(), &kSignalMagic, 1, nullptr, 0,
347 MOJO_WRITE_MESSAGE_FLAG_NONE);
348 EXPECT_EQ(write_result, MOJO_RESULT_OK);
349 }
350
351 void ReadSignal() {
352 char read_byte = 0;
353 uint32_t bytes_read = 1;
354 uint32_t handles_read = 0;
355 MojoResult read_result =
356 ReadMessageRaw(pipe_->handle0.get(), &read_byte, &bytes_read, nullptr,
357 &handles_read, MOJO_READ_MESSAGE_FLAG_NONE);
358 EXPECT_EQ(read_result, MOJO_RESULT_OK);
359 EXPECT_EQ(read_byte, kSignalMagic);
360 }
361
362 private:
363 RunLoop* run_loop_ = nullptr;
364 MessagePipe* pipe_ = nullptr;
365 size_t depth_ = 0u;
366 bool reached_depth_limit_ = false;
367
368 MOJO_DISALLOW_COPY_AND_ASSIGN(NestingRunLoopHandler);
369 };
370
371 // static
372 const size_t NestingRunLoopHandler::kDepthLimit;
373
374 // static
375 const char NestingRunLoopHandler::kSignalMagic;
376
377 TEST(RunLoopTest, NestedRun) {
378 NestingRunLoopHandler handler;
379 MessagePipe test_pipe;
380 RunLoop run_loop;
381 handler.set_run_loop(&run_loop);
382 handler.set_pipe(&test_pipe);
383 handler.AddHandlerAndWriteSignal();
384 run_loop.Run();
385
386 EXPECT_TRUE(handler.reached_depth_limit());
387 // See the comment in NestingRunLoopHandler::OnHandleReady() above.
388 EXPECT_EQ(handler.error_count(), 0);
389 }
390
391 struct Task {
392 Task(int num, std::vector<int>* sequence) : num(num), sequence(sequence) {}
393
394 void Run() const { sequence->push_back(num); }
395
396 int num;
397 std::vector<int>* sequence;
398 };
399
400 TEST(RunLoopTest, DelayedTaskOrder) {
401 std::vector<int> sequence;
402 RunLoop run_loop;
403 run_loop.PostDelayedTask(Closure(Task(1, &sequence)), 0);
404 run_loop.PostDelayedTask(Closure(Task(2, &sequence)), 0);
405 run_loop.PostDelayedTask(Closure(Task(3, &sequence)), 0);
406 run_loop.RunUntilIdle();
407
408 ASSERT_EQ(3u, sequence.size());
409 EXPECT_EQ(1, sequence[0]);
410 EXPECT_EQ(2, sequence[1]);
411 EXPECT_EQ(3, sequence[2]);
412 }
413
414 struct QuittingTask {
415 explicit QuittingTask(RunLoop* run_loop) : run_loop(run_loop) {}
416
417 void Run() const { run_loop->Quit(); }
418
419 RunLoop* run_loop;
420 };
421
422 TEST(RunLoopTest, QuitFromDelayedTask) {
423 TestRunLoopHandler handler;
424 MessagePipe test_pipe;
425 RunLoop run_loop;
426 run_loop.AddHandler(&handler,
427 test_pipe.handle0.get(),
428 MOJO_HANDLE_SIGNAL_READABLE,
429 MOJO_DEADLINE_INDEFINITE);
430 run_loop.PostDelayedTask(Closure(QuittingTask(&run_loop)), 0);
431 run_loop.Run();
432 }
433
434 } // namespace
435 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/public/cpp/utility/tests/BUILD.gn ('k') | mojo/public/dart/.analysis_options » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698