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.
5 #include "content/renderer/gpu/queue_message_swap_promise.h"
9 #include "base/memory/scoped_vector.h"
10 #include "cc/output/swap_promise.h"
11 #include "content/renderer/gpu/frame_swap_message_queue.h"
12 #include "content/renderer/gpu/render_widget_compositor.h"
13 #include "content/renderer/render_widget.h"
14 #include "content/test/mock_render_process.h"
15 #include "ipc/ipc_message.h"
16 #include "ipc/ipc_sync_message_filter.h"
17 #include "ipc/ipc_test_sink.h"
18 #include "testing/gtest/include/gtest/gtest.h"
22 class TestRenderWidget
: public RenderWidget
{
24 using RenderWidget::QueueMessageImpl
;
27 ~TestRenderWidget() override
{}
29 DISALLOW_COPY_AND_ASSIGN(TestRenderWidget
);
32 class TestSyncMessageFilter
: public IPC::SyncMessageFilter
{
34 TestSyncMessageFilter() : IPC::SyncMessageFilter(NULL
) {}
36 bool Send(IPC::Message
* message
) override
{
37 messages_
.push_back(message
);
41 ScopedVector
<IPC::Message
>& messages() { return messages_
; }
44 ~TestSyncMessageFilter() override
{}
46 ScopedVector
<IPC::Message
> messages_
;
48 DISALLOW_COPY_AND_ASSIGN(TestSyncMessageFilter
);
51 struct QueueMessageData
{
52 MessageDeliveryPolicy policy
;
53 int source_frame_number
;
56 class QueueMessageSwapPromiseTest
: public testing::Test
{
58 QueueMessageSwapPromiseTest()
59 : frame_swap_message_queue_(new FrameSwapMessageQueue()),
60 sync_message_filter_(new TestSyncMessageFilter()) {}
62 ~QueueMessageSwapPromiseTest() override
{}
64 scoped_ptr
<cc::SwapPromise
> QueueMessageImpl(IPC::Message
* msg
,
65 MessageDeliveryPolicy policy
,
66 int source_frame_number
) {
67 return TestRenderWidget::QueueMessageImpl(msg
,
69 frame_swap_message_queue_
.get(),
71 source_frame_number
).Pass();
74 ScopedVector
<IPC::Message
>& DirectSendMessages() {
75 return sync_message_filter_
->messages();
78 ScopedVector
<IPC::Message
>& NextSwapMessages() {
79 next_swap_messages_
.clear();
80 scoped_ptr
<FrameSwapMessageQueue::SendMessageScope
> send_message_scope
=
81 frame_swap_message_queue_
->AcquireSendMessageScope();
82 frame_swap_message_queue_
->DrainMessages(&next_swap_messages_
);
83 return next_swap_messages_
;
86 bool ContainsMessage(const ScopedVector
<IPC::Message
>& messages
,
87 const IPC::Message
& message
) {
90 for (ScopedVector
<IPC::Message
>::const_iterator i
= messages
.begin();
93 if ((*i
)->type() == message
.type())
99 bool NextSwapHasMessage(const IPC::Message
& message
) {
100 return ContainsMessage(NextSwapMessages(), message
);
103 void QueueMessages(QueueMessageData data
[], size_t count
) {
104 for (size_t i
= 0; i
< count
; ++i
) {
106 IPC::Message(0, i
+ 1, IPC::Message::PRIORITY_NORMAL
));
108 QueueMessageImpl(new IPC::Message(messages_
[i
]),
110 data
[i
].source_frame_number
).release());
114 void CleanupPromises() {
115 for (ScopedVector
<cc::SwapPromise
>::iterator i
= promises_
.begin();
116 i
!= promises_
.end();
124 void VisualStateSwapPromiseDidNotSwap(
125 cc::SwapPromise::DidNotSwapReason reason
);
127 scoped_refptr
<FrameSwapMessageQueue
> frame_swap_message_queue_
;
128 scoped_refptr
<TestSyncMessageFilter
> sync_message_filter_
;
129 std::vector
<IPC::Message
> messages_
;
130 ScopedVector
<cc::SwapPromise
> promises_
;
133 ScopedVector
<IPC::Message
> next_swap_messages_
;
135 DISALLOW_COPY_AND_ASSIGN(QueueMessageSwapPromiseTest
);
138 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicySchedulesMessageForNextSwap
) {
139 QueueMessageData data
[] = {
140 /* { policy, source_frame_number } */
141 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
143 QueueMessages(data
, arraysize(data
));
145 ASSERT_TRUE(promises_
[0]);
146 EXPECT_TRUE(DirectSendMessages().empty());
147 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
148 EXPECT_TRUE(NextSwapHasMessage(messages_
[0]));
153 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicyNeedsAtMostOnePromise
) {
154 QueueMessageData data
[] = {
155 /* { policy, source_frame_number } */
156 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
157 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
159 QueueMessages(data
, arraysize(data
));
161 ASSERT_TRUE(promises_
[0]);
162 ASSERT_FALSE(promises_
[1]);
167 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicySendsMessageOnNoUpdate
) {
168 QueueMessageData data
[] = {
169 /* { policy, source_frame_number } */
170 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
172 QueueMessages(data
, arraysize(data
));
174 promises_
[0]->DidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE
);
175 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[0]));
176 EXPECT_TRUE(NextSwapMessages().empty());
177 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
180 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicySendsMessageOnSwapFails
) {
181 QueueMessageData data
[] = {
182 /* { policy, source_frame_number } */
183 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
185 QueueMessages(data
, arraysize(data
));
187 promises_
[0]->DidNotSwap(cc::SwapPromise::SWAP_FAILS
);
188 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[0]));
189 EXPECT_TRUE(NextSwapMessages().empty());
190 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
193 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicyRetainsMessageOnCommitFails
) {
194 QueueMessageData data
[] = {
195 /* { policy, source_frame_number } */
196 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
198 QueueMessages(data
, arraysize(data
));
200 promises_
[0]->DidNotSwap(cc::SwapPromise::COMMIT_FAILS
);
201 EXPECT_TRUE(DirectSendMessages().empty());
202 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
203 EXPECT_TRUE(NextSwapHasMessage(messages_
[0]));
206 TEST_F(QueueMessageSwapPromiseTest
,
207 VisualStateQueuesMessageWhenCommitRequested
) {
208 QueueMessageData data
[] = {
209 /* { policy, source_frame_number } */
210 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
212 QueueMessages(data
, arraysize(data
));
214 ASSERT_TRUE(promises_
[0]);
215 EXPECT_TRUE(DirectSendMessages().empty());
216 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
217 EXPECT_TRUE(NextSwapMessages().empty());
222 TEST_F(QueueMessageSwapPromiseTest
,
223 VisualStateQueuesMessageWhenOtherMessageAlreadyQueued
) {
224 QueueMessageData data
[] = {
225 /* { policy, source_frame_number } */
226 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
227 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
229 QueueMessages(data
, arraysize(data
));
231 EXPECT_TRUE(DirectSendMessages().empty());
232 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
233 EXPECT_FALSE(NextSwapHasMessage(messages_
[1]));
238 TEST_F(QueueMessageSwapPromiseTest
, VisualStateSwapPromiseDidSwap
) {
239 QueueMessageData data
[] = {
240 /* { policy, source_frame_number } */
241 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
242 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
243 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 2},
245 QueueMessages(data
, arraysize(data
));
247 promises_
[0]->DidSwap(NULL
);
248 ASSERT_FALSE(promises_
[1]);
249 ScopedVector
<IPC::Message
> messages
;
250 messages
.swap(NextSwapMessages());
251 EXPECT_EQ(2u, messages
.size());
252 EXPECT_TRUE(ContainsMessage(messages
, messages_
[0]));
253 EXPECT_TRUE(ContainsMessage(messages
, messages_
[1]));
254 EXPECT_FALSE(ContainsMessage(messages
, messages_
[2]));
256 promises_
[2]->DidSwap(NULL
);
257 messages
.swap(NextSwapMessages());
258 EXPECT_EQ(1u, messages
.size());
259 EXPECT_TRUE(ContainsMessage(messages
, messages_
[2]));
261 EXPECT_TRUE(DirectSendMessages().empty());
262 EXPECT_TRUE(NextSwapMessages().empty());
263 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
266 void QueueMessageSwapPromiseTest::VisualStateSwapPromiseDidNotSwap(
267 cc::SwapPromise::DidNotSwapReason reason
) {
268 QueueMessageData data
[] = {
269 /* { policy, source_frame_number } */
270 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
271 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
272 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 2},
274 QueueMessages(data
, arraysize(data
));
276 promises_
[0]->DidNotSwap(reason
);
277 ASSERT_FALSE(promises_
[1]);
278 EXPECT_TRUE(NextSwapMessages().empty());
279 EXPECT_EQ(2u, DirectSendMessages().size());
280 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[0]));
281 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[1]));
282 EXPECT_FALSE(ContainsMessage(DirectSendMessages(), messages_
[2]));
284 promises_
[2]->DidNotSwap(reason
);
285 EXPECT_TRUE(NextSwapMessages().empty());
286 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[2]));
288 EXPECT_TRUE(NextSwapMessages().empty());
289 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
292 TEST_F(QueueMessageSwapPromiseTest
, VisalStateSwapPromiseDidNotSwapNoUpdate
) {
293 VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE
);
296 TEST_F(QueueMessageSwapPromiseTest
,
297 VisualStateSwapPromiseDidNotSwapCommitFails
) {
298 // COMMIT_FAILS is treated differently:
299 // If we fail to swap with COMMIT_FAILS, then the renderer is
300 // shutting down, which implies that the RenderFrameHostImpl
301 // destructor will eventually be called, firing the remaining
302 // response callbacks (with swap_success = false) itself.
303 QueueMessageData data
[] = {
304 /* { policy, source_frame_number } */
305 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
306 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
307 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 2},
309 QueueMessages(data
, arraysize(data
));
311 promises_
[0]->DidNotSwap(cc::SwapPromise::COMMIT_FAILS
);
312 ASSERT_FALSE(promises_
[1]);
313 EXPECT_TRUE(NextSwapMessages().empty());
314 EXPECT_EQ(0u, DirectSendMessages().size());
315 EXPECT_FALSE(ContainsMessage(DirectSendMessages(), messages_
[0]));
316 EXPECT_FALSE(ContainsMessage(DirectSendMessages(), messages_
[1]));
317 EXPECT_FALSE(ContainsMessage(DirectSendMessages(), messages_
[2]));
319 promises_
[2]->DidNotSwap(cc::SwapPromise::COMMIT_FAILS
);
320 EXPECT_TRUE(NextSwapMessages().empty());
321 EXPECT_FALSE(ContainsMessage(DirectSendMessages(), messages_
[2]));
323 EXPECT_TRUE(NextSwapMessages().empty());
324 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
327 TEST_F(QueueMessageSwapPromiseTest
, VisalStateSwapPromiseDidNotSwapSwapFails
) {
328 VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::SWAP_FAILS
);
331 } // namespace content