Extension syncing: Introduce a NeedsSync pref
[chromium-blink-merge.git] / ipc / mojo / async_handle_waiter_unittest.cc
blob46d4c7ef73937b9a11fd772176e396f62a472052
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"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/run_loop.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/threading/thread.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/mojo/src/mojo/public/cpp/system/message_pipe.h"
15 namespace IPC {
16 namespace internal {
17 namespace {
19 void ReadOneByteOfX(MojoHandle pipe) {
20 uint32_t size = 1;
21 char buffer = ' ';
22 MojoResult rv = MojoReadMessage(pipe, &buffer, &size, nullptr, nullptr,
23 MOJO_READ_MESSAGE_FLAG_NONE);
24 CHECK_EQ(rv, MOJO_RESULT_OK);
25 CHECK_EQ(size, 1U);
26 CHECK_EQ(buffer, 'X');
29 class AsyncHandleWaiterTest : public testing::Test {
30 public:
31 AsyncHandleWaiterTest() : worker_("test_worker") {
32 worker_.StartWithOptions(
33 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
36 void SetUp() override {
37 message_loop_.reset(new base::MessageLoopForIO());
38 ResetSignaledStates();
39 mojo::CreateMessagePipe(nullptr, &pipe_to_write_, &pipe_to_read_);
40 target_.reset(new AsyncHandleWaiter(base::Bind(
41 &AsyncHandleWaiterTest::HandleIsReady, base::Unretained(this))));
44 protected:
45 MojoResult Start() {
46 return target_->Wait(pipe_to_read_.get().value(),
47 MOJO_HANDLE_SIGNAL_READABLE);
50 void ResetSignaledStates() {
51 signaled_result_ = MOJO_RESULT_UNKNOWN;
52 run_loop_.reset(new base::RunLoop());
55 void WriteToPipe() {
56 MojoResult rv = MojoWriteMessage(pipe_to_write_.get().value(), "X", 1,
57 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
58 CHECK_EQ(rv, MOJO_RESULT_OK);
61 void WriteToPipeFromWorker() {
62 worker_.task_runner()->PostTask(
63 FROM_HERE, base::Bind(&AsyncHandleWaiterTest::WriteToPipe,
64 base::Unretained(this)));
67 void WaitAndAssertSignaledAndMessageIsArrived() {
68 run_loop_->Run();
69 EXPECT_EQ(MOJO_RESULT_OK, signaled_result_);
71 ReadOneByteOfX(pipe_to_read_.get().value());
74 void WaitAndAssertNotSignaled() {
75 run_loop_->RunUntilIdle();
76 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(pipe_to_read_.get().value(),
77 MOJO_HANDLE_SIGNAL_READABLE, 0,
78 nullptr));
79 EXPECT_EQ(MOJO_RESULT_UNKNOWN, signaled_result_);
82 void HandleIsReady(MojoResult result) {
83 CHECK_EQ(base::MessageLoop::current(), message_loop_.get());
84 CHECK_EQ(signaled_result_, MOJO_RESULT_UNKNOWN);
85 signaled_result_ = result;
86 run_loop_->Quit();
89 base::Thread worker_;
90 scoped_ptr<base::MessageLoop> message_loop_;
91 scoped_ptr<base::RunLoop> run_loop_;
92 mojo::ScopedMessagePipeHandle pipe_to_write_;
93 mojo::ScopedMessagePipeHandle pipe_to_read_;
95 scoped_ptr<AsyncHandleWaiter> target_;
96 MojoResult signaled_result_;
99 TEST_F(AsyncHandleWaiterTest, SignalFromSameThread) {
100 EXPECT_EQ(MOJO_RESULT_OK, Start());
101 WriteToPipe();
102 WaitAndAssertSignaledAndMessageIsArrived();
104 // Ensures that the waiter is reusable.
105 ResetSignaledStates();
107 EXPECT_EQ(MOJO_RESULT_OK, Start());
108 WriteToPipe();
109 WaitAndAssertSignaledAndMessageIsArrived();
112 TEST_F(AsyncHandleWaiterTest, SignalFromDifferentThread) {
113 EXPECT_EQ(MOJO_RESULT_OK, Start());
114 WriteToPipeFromWorker();
115 WaitAndAssertSignaledAndMessageIsArrived();
117 // Ensures that the waiter is reusable.
118 ResetSignaledStates();
120 EXPECT_EQ(MOJO_RESULT_OK, Start());
121 WriteToPipeFromWorker();
122 WaitAndAssertSignaledAndMessageIsArrived();
125 TEST_F(AsyncHandleWaiterTest, DeleteWaiterBeforeWrite) {
126 EXPECT_EQ(MOJO_RESULT_OK, Start());
128 target_.reset();
130 WriteToPipe();
131 WaitAndAssertNotSignaled();
134 TEST_F(AsyncHandleWaiterTest, DeleteWaiterBeforeSignal) {
135 EXPECT_EQ(MOJO_RESULT_OK, Start());
136 WriteToPipe();
138 target_.reset();
140 WaitAndAssertNotSignaled();
143 class HandlerThatReenters {
144 public:
145 HandlerThatReenters(base::RunLoop* loop, MojoHandle handle)
146 : target_(nullptr), handle_(handle), loop_(loop), step_(0) {}
148 void set_target(AsyncHandleWaiter* target) { target_ = target; }
150 void HandleIsReady(MojoResult result) {
151 switch (step_) {
152 case 0:
153 RestartAndClose(result);
154 break;
155 case 1:
156 HandleClosingSignal(result);
157 break;
158 default:
159 NOTREACHED();
160 break;
164 void RestartAndClose(MojoResult result) {
165 CHECK_EQ(step_, 0);
166 CHECK_EQ(result, MOJO_RESULT_OK);
167 step_ = 1;
169 ReadOneByteOfX(handle_);
170 target_->Wait(handle_, MOJO_HANDLE_SIGNAL_READABLE);
172 // This signals the |AsyncHandleWaiter|.
173 MojoResult rv = MojoClose(handle_);
174 CHECK_EQ(rv, MOJO_RESULT_OK);
177 void HandleClosingSignal(MojoResult result) {
178 CHECK_EQ(step_, 1);
179 CHECK_EQ(result, MOJO_RESULT_CANCELLED);
180 step_ = 2;
181 loop_->Quit();
184 bool IsClosingHandled() const { return step_ == 2; }
186 AsyncHandleWaiter* target_;
187 MojoHandle handle_;
188 base::RunLoop* loop_;
189 int step_;
192 TEST_F(AsyncHandleWaiterTest, RestartWaitingWhileSignaled) {
193 HandlerThatReenters handler(run_loop_.get(), pipe_to_read_.get().value());
194 target_.reset(new AsyncHandleWaiter(base::Bind(
195 &HandlerThatReenters::HandleIsReady, base::Unretained(&handler))));
196 handler.set_target(target_.get());
198 EXPECT_EQ(MOJO_RESULT_OK, Start());
199 WriteToPipe();
200 run_loop_->Run();
202 EXPECT_TRUE(handler.IsClosingHandled());
204 // |HandlerThatReenters::RestartAndClose| already closed it.
205 ::ignore_result(pipe_to_read_.release());
208 class AsyncHandleWaiterIOObserverTest : public testing::Test {
209 public:
210 void SetUp() override {
211 message_loop_.reset(new base::MessageLoopForIO());
212 target_.reset(new AsyncHandleWaiter(
213 base::Bind(&AsyncHandleWaiterIOObserverTest::HandleIsReady,
214 base::Unretained(this))));
215 invocation_count_ = 0;
218 void HandleIsReady(MojoResult result) { invocation_count_++; }
220 scoped_ptr<base::MessageLoop> message_loop_;
221 scoped_ptr<AsyncHandleWaiter> target_;
222 size_t invocation_count_;
225 TEST_F(AsyncHandleWaiterIOObserverTest, OutsideIOEvnet) {
226 target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
227 EXPECT_EQ(0U, invocation_count_);
228 message_loop_->RunUntilIdle();
229 EXPECT_EQ(1U, invocation_count_);
232 TEST_F(AsyncHandleWaiterIOObserverTest, InsideIOEvnet) {
233 target_->GetIOObserverForTest()->WillProcessIOEvent();
234 target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
235 EXPECT_EQ(0U, invocation_count_);
236 target_->GetIOObserverForTest()->DidProcessIOEvent();
237 EXPECT_EQ(1U, invocation_count_);
240 TEST_F(AsyncHandleWaiterIOObserverTest, Reenter) {
241 target_->GetIOObserverForTest()->WillProcessIOEvent();
242 target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
243 EXPECT_EQ(0U, invocation_count_);
245 // As if some other io handler start nested loop.
246 target_->GetIOObserverForTest()->WillProcessIOEvent();
247 target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
248 target_->GetIOObserverForTest()->DidProcessIOEvent();
249 EXPECT_EQ(0U, invocation_count_);
251 target_->GetIOObserverForTest()->DidProcessIOEvent();
252 EXPECT_EQ(1U, invocation_count_);
255 } // namespace
256 } // namespace internal
257 } // namespace IPC