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

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

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