Chromium Code Reviews| Index: mojo/public/cpp/utility/tests/run_loop_unittest.cc |
| diff --git a/mojo/public/cpp/utility/tests/run_loop_unittest.cc b/mojo/public/cpp/utility/tests/run_loop_unittest.cc |
| index ba17fe856a5711b244d1b00c82ac24caa5f54b2e..c29cc72909e370590c09b98f9783f589a691b341 100644 |
| --- a/mojo/public/cpp/utility/tests/run_loop_unittest.cc |
| +++ b/mojo/public/cpp/utility/tests/run_loop_unittest.cc |
| @@ -190,7 +190,100 @@ TEST_F(RunLoopTest, Current) { |
| EXPECT_TRUE(RunLoop::current() == NULL); |
| } |
| -// TODO(darin): Add tests for nested calls to RunLoop::Run(). See crbug/384633. |
| + |
|
viettrungluu
2014/07/16 02:46:08
nit: Remove extra blank line.
|
| +class NestingRunLoopHandler : public TestRunLoopHandler { |
| + public: |
| + static const size_t kDepthLimit; |
| + static const char kSignalMagic; |
| + |
| + NestingRunLoopHandler() |
| + : run_loop_(NULL), |
| + pipe_(NULL), |
| + depth_(0), |
| + reached_depth_limit_(false) {} |
| + |
| + virtual ~NestingRunLoopHandler() {} |
| + |
| + void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } |
| + void set_pipe(MessagePipe* pipe) { pipe_ = pipe; } |
| + bool reached_depth_limit() const { return reached_depth_limit_; } |
| + |
| + // RunLoopHandler: |
| + virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE { |
| + TestRunLoopHandler::OnHandleReady(handle); |
| + EXPECT_EQ(handle.value(), pipe_->handle0.get().value()); |
| + |
| + ReadSignal(); |
| + size_t current_depth = ++depth_; |
| + if (current_depth < kDepthLimit) { |
| + WriteSignal(); |
| + run_loop_->Run(); |
| + if (current_depth == kDepthLimit - 1) { |
| + // The topmost loop Quit()-ed, so its parent takes back the |
| + // control without exeeding deadline. |
| + EXPECT_EQ(error_count(), 0); |
| + } else { |
| + EXPECT_EQ(error_count(), 1); |
| + } |
| + |
| + } else { |
| + EXPECT_EQ(current_depth, kDepthLimit); |
| + reached_depth_limit_ = true; |
| + run_loop_->Quit(); |
| + } |
| + --depth_; |
| + } |
| + |
| + void WriteSignal() { |
| + char write_byte = kSignalMagic; |
| + MojoResult write_result = WriteMessageRaw( |
| + pipe_->handle1.get(), |
| + &write_byte, 1, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); |
| + EXPECT_EQ(write_result, MOJO_RESULT_OK); |
| + } |
| + |
| + void ReadSignal() { |
| + char read_byte = 0; |
| + uint32_t bytes_read = 1; |
| + uint32_t handles_read = 0; |
| + MojoResult read_result = ReadMessageRaw( |
| + pipe_->handle0.get(), |
| + &read_byte, &bytes_read, NULL, &handles_read, |
| + MOJO_READ_MESSAGE_FLAG_NONE); |
| + EXPECT_EQ(read_result, MOJO_RESULT_OK); |
| + EXPECT_EQ(read_byte, kSignalMagic); |
| + } |
| + |
| + private: |
| + RunLoop* run_loop_; |
| + MessagePipe* pipe_; |
| + size_t depth_; |
| + bool reached_depth_limit_; |
| + |
| + MOJO_DISALLOW_COPY_AND_ASSIGN(NestingRunLoopHandler); |
| +}; |
| + |
| +const size_t NestingRunLoopHandler::kDepthLimit = 10; |
| +const char NestingRunLoopHandler::kSignalMagic = 'X'; |
| + |
| +TEST_F(RunLoopTest, NestedRun) { |
| + NestingRunLoopHandler handler; |
| + MessagePipe test_pipe; |
| + RunLoop run_loop; |
| + handler.set_run_loop(&run_loop); |
| + handler.set_pipe(&test_pipe); |
| + run_loop.AddHandler(&handler, test_pipe.handle0.get(), |
| + MOJO_HANDLE_SIGNAL_READABLE, |
| + static_cast<MojoDeadline>(10000)); |
| + handler.WriteSignal(); |
| + run_loop.Run(); |
| + |
| + EXPECT_TRUE(handler.reached_depth_limit()); |
| + // Got MOJO_RESULT_DEADLINE_EXCEEDED once then removed from the |
| + // RunLoop's handler list. |
| + EXPECT_EQ(handler.error_count(), 1); |
| + EXPECT_EQ(handler.last_error_result(), MOJO_RESULT_DEADLINE_EXCEEDED); |
| +} |
| } // namespace |
| } // namespace mojo |