1e21a134aa21bf27d9159341650f78f62abb2a50
[platform/framework/web/crosswalk.git] / src / mojo / public / cpp / utility / tests / run_loop_unittest.cc
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_(NULL) {
75   }
76   ~RemoveOnReadyRunLoopHandler() override {}
77
78   void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
79
80   // RunLoopHandler:
81   void OnHandleReady(const Handle& handle) override {
82     run_loop_->RemoveHandler(handle);
83     TestRunLoopHandler::OnHandleReady(handle);
84   }
85
86  private:
87   RunLoop* run_loop_;
88
89   MOJO_DISALLOW_COPY_AND_ASSIGN(RemoveOnReadyRunLoopHandler);
90 };
91
92 // Verifies RunLoop quits when no more handles (handle is removed when ready).
93 TEST_F(RunLoopTest, HandleReady) {
94   RemoveOnReadyRunLoopHandler handler;
95   MessagePipe test_pipe;
96   EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
97
98   RunLoop run_loop;
99   handler.set_run_loop(&run_loop);
100   run_loop.AddHandler(&handler, test_pipe.handle0.get(),
101                       MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE);
102   run_loop.Run();
103   EXPECT_EQ(1, handler.ready_count());
104   EXPECT_EQ(0, handler.error_count());
105   EXPECT_FALSE(run_loop.HasHandler(test_pipe.handle0.get()));
106 }
107
108 class QuitOnReadyRunLoopHandler : public TestRunLoopHandler {
109  public:
110   QuitOnReadyRunLoopHandler() : run_loop_(NULL) {
111   }
112   ~QuitOnReadyRunLoopHandler() override {}
113
114   void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
115
116   // RunLoopHandler:
117   void OnHandleReady(const Handle& handle) override {
118     run_loop_->Quit();
119     TestRunLoopHandler::OnHandleReady(handle);
120   }
121
122  private:
123   RunLoop* run_loop_;
124
125   MOJO_DISALLOW_COPY_AND_ASSIGN(QuitOnReadyRunLoopHandler);
126 };
127
128 // Verifies Quit() from OnHandleReady() quits the loop.
129 TEST_F(RunLoopTest, QuitFromReady) {
130   QuitOnReadyRunLoopHandler handler;
131   MessagePipe test_pipe;
132   EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
133
134   RunLoop run_loop;
135   handler.set_run_loop(&run_loop);
136   run_loop.AddHandler(&handler, test_pipe.handle0.get(),
137                       MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE);
138   run_loop.Run();
139   EXPECT_EQ(1, handler.ready_count());
140   EXPECT_EQ(0, handler.error_count());
141   EXPECT_TRUE(run_loop.HasHandler(test_pipe.handle0.get()));
142 }
143
144 class QuitOnErrorRunLoopHandler : public TestRunLoopHandler {
145  public:
146   QuitOnErrorRunLoopHandler() : run_loop_(NULL) {
147   }
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   MOJO_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_(NULL) {
198   }
199   ~RemoveManyRunLoopHandler() override {}
200
201   void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
202   void add_handle(const Handle& handle) { handles_.push_back(handle); }
203
204   // RunLoopHandler:
205   void OnHandleError(const Handle& handle, MojoResult result) override {
206     for (size_t i = 0; i < handles_.size(); i++)
207       run_loop_->RemoveHandler(handles_[i]);
208     TestRunLoopHandler::OnHandleError(handle, result);
209   }
210
211  private:
212   std::vector<Handle> handles_;
213   RunLoop* run_loop_;
214
215   MOJO_DISALLOW_COPY_AND_ASSIGN(RemoveManyRunLoopHandler);
216 };
217
218 // Test that handlers are notified of loop destruction.
219 TEST_F(RunLoopTest, MultipleHandleDestruction) {
220   RemoveManyRunLoopHandler odd_handler;
221   TestRunLoopHandler even_handler;
222   MessagePipe test_pipe1, test_pipe2, test_pipe3;
223   {
224     RunLoop run_loop;
225     odd_handler.set_run_loop(&run_loop);
226     odd_handler.add_handle(test_pipe1.handle0.get());
227     odd_handler.add_handle(test_pipe3.handle0.get());
228     run_loop.AddHandler(&odd_handler,
229                         test_pipe1.handle0.get(),
230                         MOJO_HANDLE_SIGNAL_READABLE,
231                         MOJO_DEADLINE_INDEFINITE);
232     run_loop.AddHandler(&even_handler,
233                         test_pipe2.handle0.get(),
234                         MOJO_HANDLE_SIGNAL_READABLE,
235                         MOJO_DEADLINE_INDEFINITE);
236     run_loop.AddHandler(&odd_handler,
237                         test_pipe3.handle0.get(),
238                         MOJO_HANDLE_SIGNAL_READABLE,
239                         MOJO_DEADLINE_INDEFINITE);
240   }
241   EXPECT_EQ(1, odd_handler.error_count());
242   EXPECT_EQ(1, even_handler.error_count());
243   EXPECT_EQ(MOJO_RESULT_ABORTED, odd_handler.last_error_result());
244   EXPECT_EQ(MOJO_RESULT_ABORTED, even_handler.last_error_result());
245 }
246
247 class AddHandlerOnErrorHandler : public TestRunLoopHandler {
248  public:
249   AddHandlerOnErrorHandler() : run_loop_(NULL) {
250   }
251   ~AddHandlerOnErrorHandler() override {}
252
253   void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
254
255   // RunLoopHandler:
256   void OnHandleError(const Handle& handle, MojoResult result) override {
257     run_loop_->AddHandler(this, handle,
258                           MOJO_HANDLE_SIGNAL_READABLE,
259                           MOJO_DEADLINE_INDEFINITE);
260     TestRunLoopHandler::OnHandleError(handle, result);
261   }
262
263  private:
264   RunLoop* run_loop_;
265
266   MOJO_DISALLOW_COPY_AND_ASSIGN(AddHandlerOnErrorHandler);
267 };
268
269 TEST_F(RunLoopTest, AddHandlerOnError) {
270   AddHandlerOnErrorHandler handler;
271   MessagePipe test_pipe;
272   {
273     RunLoop run_loop;
274     handler.set_run_loop(&run_loop);
275     run_loop.AddHandler(&handler,
276                         test_pipe.handle0.get(),
277                         MOJO_HANDLE_SIGNAL_READABLE,
278                         MOJO_DEADLINE_INDEFINITE);
279   }
280   EXPECT_EQ(1, handler.error_count());
281   EXPECT_EQ(MOJO_RESULT_ABORTED, handler.last_error_result());
282 }
283
284 TEST_F(RunLoopTest, Current) {
285   EXPECT_TRUE(RunLoop::current() == NULL);
286   {
287     RunLoop run_loop;
288     EXPECT_EQ(&run_loop, RunLoop::current());
289   }
290   EXPECT_TRUE(RunLoop::current() == NULL);
291 }
292
293 class NestingRunLoopHandler : public TestRunLoopHandler {
294  public:
295   static const size_t kDepthLimit;
296   static const char kSignalMagic;
297
298   NestingRunLoopHandler()
299       : run_loop_(NULL),
300         pipe_(NULL),
301         depth_(0),
302         reached_depth_limit_(false) {}
303
304   ~NestingRunLoopHandler() override {}
305
306   void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
307   void set_pipe(MessagePipe* pipe) { pipe_ = pipe; }
308   bool reached_depth_limit() const { return reached_depth_limit_; }
309
310   // RunLoopHandler:
311   void OnHandleReady(const Handle& handle) override {
312     TestRunLoopHandler::OnHandleReady(handle);
313     EXPECT_EQ(handle.value(), pipe_->handle0.get().value());
314
315     ReadSignal();
316     size_t current_depth = ++depth_;
317     if (current_depth < kDepthLimit) {
318       WriteSignal();
319       run_loop_->Run();
320       if (current_depth == kDepthLimit - 1) {
321         // The topmost loop Quit()-ed, so its parent takes back the
322         // control without exeeding deadline.
323         EXPECT_EQ(error_count(), 0);
324       } else {
325         EXPECT_EQ(error_count(), 1);
326       }
327
328     } else {
329       EXPECT_EQ(current_depth, kDepthLimit);
330       reached_depth_limit_ = true;
331       run_loop_->Quit();
332     }
333     --depth_;
334   }
335
336   void WriteSignal() {
337     char write_byte = kSignalMagic;
338     MojoResult write_result = WriteMessageRaw(
339         pipe_->handle1.get(),
340         &write_byte, 1, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
341     EXPECT_EQ(write_result, MOJO_RESULT_OK);
342   }
343
344   void ReadSignal() {
345     char read_byte = 0;
346     uint32_t bytes_read = 1;
347     uint32_t handles_read = 0;
348     MojoResult read_result = ReadMessageRaw(
349         pipe_->handle0.get(),
350         &read_byte, &bytes_read, NULL, &handles_read,
351         MOJO_READ_MESSAGE_FLAG_NONE);
352     EXPECT_EQ(read_result, MOJO_RESULT_OK);
353     EXPECT_EQ(read_byte, kSignalMagic);
354   }
355
356  private:
357   RunLoop* run_loop_;
358   MessagePipe* pipe_;
359   size_t depth_;
360   bool reached_depth_limit_;
361
362   MOJO_DISALLOW_COPY_AND_ASSIGN(NestingRunLoopHandler);
363 };
364
365 const size_t NestingRunLoopHandler::kDepthLimit = 10;
366 const char NestingRunLoopHandler::kSignalMagic = 'X';
367
368 TEST_F(RunLoopTest, NestedRun) {
369   NestingRunLoopHandler handler;
370   MessagePipe test_pipe;
371   RunLoop run_loop;
372   handler.set_run_loop(&run_loop);
373   handler.set_pipe(&test_pipe);
374   run_loop.AddHandler(&handler, test_pipe.handle0.get(),
375                       MOJO_HANDLE_SIGNAL_READABLE,
376                       static_cast<MojoDeadline>(10000));
377   handler.WriteSignal();
378   run_loop.Run();
379
380   EXPECT_TRUE(handler.reached_depth_limit());
381   // Got MOJO_RESULT_DEADLINE_EXCEEDED once then removed from the
382   // RunLoop's handler list.
383   EXPECT_EQ(handler.error_count(), 1);
384   EXPECT_EQ(handler.last_error_result(), MOJO_RESULT_DEADLINE_EXCEEDED);
385 }
386
387 struct Task {
388   Task(int num, std::vector<int>* sequence) : num(num), sequence(sequence) {}
389
390   void Run() const { sequence->push_back(num); }
391
392   int num;
393   std::vector<int>* sequence;
394 };
395
396 TEST_F(RunLoopTest, DelayedTaskOrder) {
397   std::vector<int> sequence;
398   RunLoop run_loop;
399   run_loop.PostDelayedTask(Closure(Task(1, &sequence)), 0);
400   run_loop.PostDelayedTask(Closure(Task(2, &sequence)), 0);
401   run_loop.PostDelayedTask(Closure(Task(3, &sequence)), 0);
402   run_loop.RunUntilIdle();
403
404   ASSERT_EQ(3u, sequence.size());
405   EXPECT_EQ(1, sequence[0]);
406   EXPECT_EQ(2, sequence[1]);
407   EXPECT_EQ(3, sequence[2]);
408 }
409
410 struct QuittingTask {
411   explicit QuittingTask(RunLoop* run_loop) : run_loop(run_loop) {}
412
413   void Run() const { run_loop->Quit(); }
414
415   RunLoop* run_loop;
416 };
417
418 TEST_F(RunLoopTest, QuitFromDelayedTask) {
419   TestRunLoopHandler handler;
420   MessagePipe test_pipe;
421   RunLoop run_loop;
422   run_loop.AddHandler(&handler,
423                       test_pipe.handle0.get(),
424                       MOJO_HANDLE_SIGNAL_READABLE,
425                       MOJO_DEADLINE_INDEFINITE);
426   run_loop.PostDelayedTask(Closure(QuittingTask(&run_loop)), 0);
427   run_loop.Run();
428 }
429
430 }  // namespace
431 }  // namespace mojo