1 // Copyright 2015 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.
5 #include "ipc/mojo/async_handle_waiter.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/threading/thread.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/mojo/src/mojo/public/cpp/system/message_pipe.h"
18 void ReadOneByteOfX(MojoHandle pipe
) {
21 MojoResult rv
= MojoReadMessage(pipe
, &buffer
, &size
, nullptr, nullptr,
22 MOJO_READ_MESSAGE_FLAG_NONE
);
23 CHECK_EQ(rv
, MOJO_RESULT_OK
);
25 CHECK_EQ(buffer
, 'X');
28 class AsyncHandleWaiterTest
: public testing::Test
{
30 AsyncHandleWaiterTest() : worker_("test_worker") {
31 worker_
.StartWithOptions(
32 base::Thread::Options(base::MessageLoop::TYPE_IO
, 0));
35 void SetUp() override
{
36 message_loop_
.reset(new base::MessageLoopForIO());
37 ResetSignaledStates();
38 mojo::CreateMessagePipe(nullptr, &pipe_to_write_
, &pipe_to_read_
);
39 target_
.reset(new AsyncHandleWaiter(base::Bind(
40 &AsyncHandleWaiterTest::HandleIsReady
, base::Unretained(this))));
45 return target_
->Wait(pipe_to_read_
.get().value(),
46 MOJO_HANDLE_SIGNAL_READABLE
);
49 void ResetSignaledStates() {
50 signaled_result_
= MOJO_RESULT_UNKNOWN
;
51 run_loop_
.reset(new base::RunLoop());
55 MojoResult rv
= MojoWriteMessage(pipe_to_write_
.get().value(), "X", 1,
56 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE
);
57 CHECK_EQ(rv
, MOJO_RESULT_OK
);
60 void WriteToPipeFromWorker() {
61 worker_
.message_loop_proxy()->PostTask(
62 FROM_HERE
, base::Bind(&AsyncHandleWaiterTest::WriteToPipe
,
63 base::Unretained(this)));
66 void WaitAndAssertSignaledAndMessageIsArrived() {
68 EXPECT_EQ(MOJO_RESULT_OK
, signaled_result_
);
70 ReadOneByteOfX(pipe_to_read_
.get().value());
73 void WaitAndAssertNotSignaled() {
74 run_loop_
->RunUntilIdle();
75 EXPECT_EQ(MOJO_RESULT_OK
, MojoWait(pipe_to_read_
.get().value(),
76 MOJO_HANDLE_SIGNAL_READABLE
, 0,
78 EXPECT_EQ(MOJO_RESULT_UNKNOWN
, signaled_result_
);
81 void HandleIsReady(MojoResult result
) {
82 CHECK_EQ(base::MessageLoop::current(), message_loop_
.get());
83 CHECK_EQ(signaled_result_
, MOJO_RESULT_UNKNOWN
);
84 signaled_result_
= result
;
89 scoped_ptr
<base::MessageLoop
> message_loop_
;
90 scoped_ptr
<base::RunLoop
> run_loop_
;
91 mojo::ScopedMessagePipeHandle pipe_to_write_
;
92 mojo::ScopedMessagePipeHandle pipe_to_read_
;
94 scoped_ptr
<AsyncHandleWaiter
> target_
;
95 MojoResult signaled_result_
;
98 TEST_F(AsyncHandleWaiterTest
, SignalFromSameThread
) {
99 EXPECT_EQ(MOJO_RESULT_OK
, Start());
101 WaitAndAssertSignaledAndMessageIsArrived();
103 // Ensures that the waiter is reusable.
104 ResetSignaledStates();
106 EXPECT_EQ(MOJO_RESULT_OK
, Start());
108 WaitAndAssertSignaledAndMessageIsArrived();
111 TEST_F(AsyncHandleWaiterTest
, SignalFromDifferentThread
) {
112 EXPECT_EQ(MOJO_RESULT_OK
, Start());
113 WriteToPipeFromWorker();
114 WaitAndAssertSignaledAndMessageIsArrived();
116 // Ensures that the waiter is reusable.
117 ResetSignaledStates();
119 EXPECT_EQ(MOJO_RESULT_OK
, Start());
120 WriteToPipeFromWorker();
121 WaitAndAssertSignaledAndMessageIsArrived();
124 TEST_F(AsyncHandleWaiterTest
, DeleteWaiterBeforeWrite
) {
125 EXPECT_EQ(MOJO_RESULT_OK
, Start());
130 WaitAndAssertNotSignaled();
133 TEST_F(AsyncHandleWaiterTest
, DeleteWaiterBeforeSignal
) {
134 EXPECT_EQ(MOJO_RESULT_OK
, Start());
139 WaitAndAssertNotSignaled();
142 class HandlerThatReenters
{
144 HandlerThatReenters(base::RunLoop
* loop
, MojoHandle handle
)
145 : target_(nullptr), handle_(handle
), loop_(loop
), step_(0) {}
147 void set_target(AsyncHandleWaiter
* target
) { target_
= target
; }
149 void HandleIsReady(MojoResult result
) {
152 RestartAndClose(result
);
155 HandleClosingSignal(result
);
163 void RestartAndClose(MojoResult result
) {
165 CHECK_EQ(result
, MOJO_RESULT_OK
);
168 ReadOneByteOfX(handle_
);
169 target_
->Wait(handle_
, MOJO_HANDLE_SIGNAL_READABLE
);
171 // This signals the |AsyncHandleWaiter|.
172 MojoResult rv
= MojoClose(handle_
);
173 CHECK_EQ(rv
, MOJO_RESULT_OK
);
176 void HandleClosingSignal(MojoResult result
) {
178 CHECK_EQ(result
, MOJO_RESULT_CANCELLED
);
183 bool IsClosingHandled() const { return step_
== 2; }
185 AsyncHandleWaiter
* target_
;
187 base::RunLoop
* loop_
;
191 TEST_F(AsyncHandleWaiterTest
, RestartWaitingWhileSignaled
) {
192 HandlerThatReenters
handler(run_loop_
.get(), pipe_to_read_
.get().value());
193 target_
.reset(new AsyncHandleWaiter(base::Bind(
194 &HandlerThatReenters::HandleIsReady
, base::Unretained(&handler
))));
195 handler
.set_target(target_
.get());
197 EXPECT_EQ(MOJO_RESULT_OK
, Start());
201 EXPECT_TRUE(handler
.IsClosingHandled());
203 // |HandlerThatReenters::RestartAndClose| already closed it.
204 ignore_result(pipe_to_read_
.release());
208 } // namespace internal