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

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

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

Powered by Google App Engine
This is Rietveld 408576698