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