GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / ipc / mojo / async_handle_waiter_unittest.cc
blob38f3bd68e40cde36f9ce1d098b25bb8ba4e481f2
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/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"
14 namespace IPC {
15 namespace internal {
16 namespace {
18 void ReadOneByteOfX(MojoHandle pipe) {
19 uint32_t size = 1;
20 char buffer = ' ';
21 MojoResult rv = MojoReadMessage(pipe, &buffer, &size, nullptr, nullptr,
22 MOJO_READ_MESSAGE_FLAG_NONE);
23 CHECK_EQ(rv, MOJO_RESULT_OK);
24 CHECK_EQ(size, 1U);
25 CHECK_EQ(buffer, 'X');
28 class AsyncHandleWaiterTest : public testing::Test {
29 public:
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))));
43 protected:
44 MojoResult Start() {
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());
54 void WriteToPipe() {
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() {
67 run_loop_->Run();
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,
77 nullptr));
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;
85 run_loop_->Quit();
88 base::Thread worker_;
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());
100 WriteToPipe();
101 WaitAndAssertSignaledAndMessageIsArrived();
103 // Ensures that the waiter is reusable.
104 ResetSignaledStates();
106 EXPECT_EQ(MOJO_RESULT_OK, Start());
107 WriteToPipe();
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());
127 target_.reset();
129 WriteToPipe();
130 WaitAndAssertNotSignaled();
133 TEST_F(AsyncHandleWaiterTest, DeleteWaiterBeforeSignal) {
134 EXPECT_EQ(MOJO_RESULT_OK, Start());
135 WriteToPipe();
137 target_.reset();
139 WaitAndAssertNotSignaled();
142 class HandlerThatReenters {
143 public:
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) {
150 switch (step_) {
151 case 0:
152 RestartAndClose(result);
153 break;
154 case 1:
155 HandleClosingSignal(result);
156 break;
157 default:
158 NOTREACHED();
159 break;
163 void RestartAndClose(MojoResult result) {
164 CHECK_EQ(step_, 0);
165 CHECK_EQ(result, MOJO_RESULT_OK);
166 step_ = 1;
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) {
177 CHECK_EQ(step_, 1);
178 CHECK_EQ(result, MOJO_RESULT_CANCELLED);
179 step_ = 2;
180 loop_->Quit();
183 bool IsClosingHandled() const { return step_ == 2; }
185 AsyncHandleWaiter* target_;
186 MojoHandle handle_;
187 base::RunLoop* loop_;
188 int step_;
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());
198 WriteToPipe();
199 run_loop_->Run();
201 EXPECT_TRUE(handler.IsClosingHandled());
203 // |HandlerThatReenters::RestartAndClose| already closed it.
204 ignore_result(pipe_to_read_.release());
207 class AsyncHandleWaiterIOObserverTest : public testing::Test {
208 public:
209 void SetUp() override {
210 message_loop_.reset(new base::MessageLoopForIO());
211 target_.reset(new AsyncHandleWaiter(
212 base::Bind(&AsyncHandleWaiterIOObserverTest::HandleIsReady,
213 base::Unretained(this))));
214 invocation_count_ = 0;
217 void HandleIsReady(MojoResult result) { invocation_count_++; }
219 scoped_ptr<base::MessageLoop> message_loop_;
220 scoped_ptr<AsyncHandleWaiter> target_;
221 size_t invocation_count_;
224 TEST_F(AsyncHandleWaiterIOObserverTest, OutsideIOEvnet) {
225 target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
226 EXPECT_EQ(0U, invocation_count_);
227 message_loop_->RunUntilIdle();
228 EXPECT_EQ(1U, invocation_count_);
231 TEST_F(AsyncHandleWaiterIOObserverTest, InsideIOEvnet) {
232 target_->GetIOObserverForTest()->WillProcessIOEvent();
233 target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
234 EXPECT_EQ(0U, invocation_count_);
235 target_->GetIOObserverForTest()->DidProcessIOEvent();
236 EXPECT_EQ(1U, invocation_count_);
239 TEST_F(AsyncHandleWaiterIOObserverTest, Reenter) {
240 target_->GetIOObserverForTest()->WillProcessIOEvent();
241 target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
242 EXPECT_EQ(0U, invocation_count_);
244 // As if some other io handler start nested loop.
245 target_->GetIOObserverForTest()->WillProcessIOEvent();
246 target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
247 target_->GetIOObserverForTest()->DidProcessIOEvent();
248 EXPECT_EQ(0U, invocation_count_);
250 target_->GetIOObserverForTest()->DidProcessIOEvent();
251 EXPECT_EQ(1U, invocation_count_);
254 } // namespace
255 } // namespace internal
256 } // namespace IPC