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/base/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 virtual ~TestRenderWidget() {}
29 DISALLOW_COPY_AND_ASSIGN(TestRenderWidget
);
32 class TestSyncMessageFilter
: public IPC::SyncMessageFilter
{
34 TestSyncMessageFilter() : IPC::SyncMessageFilter(NULL
) {}
36 virtual bool Send(IPC::Message
* message
) OVERRIDE
{
37 messages_
.push_back(message
);
41 ScopedVector
<IPC::Message
>& messages() { return messages_
; }
44 virtual ~TestSyncMessageFilter() {}
46 ScopedVector
<IPC::Message
> messages_
;
48 DISALLOW_COPY_AND_ASSIGN(TestSyncMessageFilter
);
51 struct QueueMessageData
{
52 MessageDeliveryPolicy policy
;
53 bool commit_requested
;
54 int source_frame_number
;
57 class QueueMessageSwapPromiseTest
: public testing::Test
{
59 QueueMessageSwapPromiseTest()
60 : frame_swap_message_queue_(new FrameSwapMessageQueue()),
61 sync_message_filter_(new TestSyncMessageFilter()) {}
63 virtual ~QueueMessageSwapPromiseTest() {}
65 scoped_ptr
<cc::SwapPromise
> QueueMessageImpl(IPC::Message
* msg
,
66 MessageDeliveryPolicy policy
,
67 bool commit_requested
,
68 int source_frame_number
) {
69 return TestRenderWidget::QueueMessageImpl(msg
,
71 frame_swap_message_queue_
.get(),
74 source_frame_number
).Pass();
77 ScopedVector
<IPC::Message
>& DirectSendMessages() {
78 return sync_message_filter_
->messages();
81 ScopedVector
<IPC::Message
>& NextSwapMessages() {
82 next_swap_messages_
.clear();
83 scoped_ptr
<FrameSwapMessageQueue::SendMessageScope
> send_message_scope
=
84 frame_swap_message_queue_
->AcquireSendMessageScope();
85 frame_swap_message_queue_
->DrainMessages(&next_swap_messages_
);
86 return next_swap_messages_
;
89 bool ContainsMessage(const ScopedVector
<IPC::Message
>& messages
,
90 const IPC::Message
& message
) {
93 for (ScopedVector
<IPC::Message
>::const_iterator i
= messages
.begin();
96 if ((*i
)->type() == message
.type())
102 bool NextSwapHasMessage(const IPC::Message
& message
) {
103 return ContainsMessage(NextSwapMessages(), message
);
106 void QueueMessages(QueueMessageData data
[], size_t count
) {
107 for (size_t i
= 0; i
< count
; ++i
) {
109 IPC::Message(0, i
+ 1, IPC::Message::PRIORITY_NORMAL
));
111 QueueMessageImpl(new IPC::Message(messages_
[i
]),
113 data
[i
].commit_requested
,
114 data
[i
].source_frame_number
).release());
118 void CleanupPromises() {
119 for (ScopedVector
<cc::SwapPromise
>::iterator i
= promises_
.begin();
120 i
!= promises_
.end();
128 void VisualStateSwapPromiseDidNotSwap(
129 cc::SwapPromise::DidNotSwapReason reason
);
131 scoped_refptr
<FrameSwapMessageQueue
> frame_swap_message_queue_
;
132 scoped_refptr
<TestSyncMessageFilter
> sync_message_filter_
;
133 std::vector
<IPC::Message
> messages_
;
134 ScopedVector
<cc::SwapPromise
> promises_
;
137 ScopedVector
<IPC::Message
> next_swap_messages_
;
139 DISALLOW_COPY_AND_ASSIGN(QueueMessageSwapPromiseTest
);
142 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicySchedulesMessageForNextSwap
) {
143 QueueMessageData data
[] = {
144 /* { policy, commit_requested, source_frame_number } */
145 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, false, 1},
147 QueueMessages(data
, arraysize(data
));
149 ASSERT_TRUE(promises_
[0]);
150 EXPECT_TRUE(DirectSendMessages().empty());
151 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
152 EXPECT_TRUE(NextSwapHasMessage(messages_
[0]));
157 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicyNeedsAtMostOnePromise
) {
158 QueueMessageData data
[] = {
159 /* { policy, commit_requested, source_frame_number } */
160 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, false, 1},
161 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, false, 1},
163 QueueMessages(data
, arraysize(data
));
165 ASSERT_TRUE(promises_
[0]);
166 ASSERT_FALSE(promises_
[1]);
171 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicySendsMessageOnNoUpdate
) {
172 QueueMessageData data
[] = {
173 /* { policy, commit_requested, source_frame_number } */
174 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, false, 1},
176 QueueMessages(data
, arraysize(data
));
178 promises_
[0]->DidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE
);
179 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[0]));
180 EXPECT_TRUE(NextSwapMessages().empty());
181 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
184 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicySendsMessageOnSwapFails
) {
185 QueueMessageData data
[] = {
186 /* { policy, commit_requested, source_frame_number } */
187 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, false, 1},
189 QueueMessages(data
, arraysize(data
));
191 promises_
[0]->DidNotSwap(cc::SwapPromise::SWAP_FAILS
);
192 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[0]));
193 EXPECT_TRUE(NextSwapMessages().empty());
194 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
197 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicyRetainsMessageOnCommitFails
) {
198 QueueMessageData data
[] = {
199 /* { policy, commit_requested, source_frame_number } */
200 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, false, 1},
202 QueueMessages(data
, arraysize(data
));
204 promises_
[0]->DidNotSwap(cc::SwapPromise::COMMIT_FAILS
);
205 EXPECT_TRUE(DirectSendMessages().empty());
206 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
207 EXPECT_TRUE(NextSwapHasMessage(messages_
[0]));
210 TEST_F(QueueMessageSwapPromiseTest
, VisualStateDirectSend
) {
211 QueueMessageData data
[] = {
212 /* { policy, commit_requested, source_frame_number } */
213 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, false, 1},
215 QueueMessages(data
, arraysize(data
));
217 ASSERT_FALSE(promises_
[0]);
218 EXPECT_FALSE(DirectSendMessages().empty());
219 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
220 EXPECT_TRUE(NextSwapMessages().empty());
223 TEST_F(QueueMessageSwapPromiseTest
,
224 VisualStateQueuesMessageWhenCommitRequested
) {
225 QueueMessageData data
[] = {
226 /* { policy, commit_requested, source_frame_number } */
227 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, true, 1},
229 QueueMessages(data
, arraysize(data
));
231 ASSERT_TRUE(promises_
[0]);
232 EXPECT_TRUE(DirectSendMessages().empty());
233 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
234 EXPECT_TRUE(NextSwapMessages().empty());
239 TEST_F(QueueMessageSwapPromiseTest
,
240 VisualStateQueuesMessageWhenOtherMessageAlreadyQueued
) {
241 QueueMessageData data
[] = {
242 /* { policy, commit_requested, source_frame_number } */
243 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, true, 1},
244 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, true, 1},
246 QueueMessages(data
, arraysize(data
));
248 EXPECT_TRUE(DirectSendMessages().empty());
249 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
250 EXPECT_FALSE(NextSwapHasMessage(messages_
[1]));
255 TEST_F(QueueMessageSwapPromiseTest
, VisualStateSwapPromiseDidSwap
) {
256 QueueMessageData data
[] = {
257 /* { policy, commit_requested, source_frame_number } */
258 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, true, 1},
259 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, false, 1},
260 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, false, 2},
262 QueueMessages(data
, arraysize(data
));
264 promises_
[0]->DidSwap(NULL
);
265 ASSERT_FALSE(promises_
[1]);
266 ScopedVector
<IPC::Message
> messages
;
267 messages
.swap(NextSwapMessages());
268 EXPECT_EQ(2u, messages
.size());
269 EXPECT_TRUE(ContainsMessage(messages
, messages_
[0]));
270 EXPECT_TRUE(ContainsMessage(messages
, messages_
[1]));
271 EXPECT_FALSE(ContainsMessage(messages
, messages_
[2]));
273 promises_
[2]->DidSwap(NULL
);
274 messages
.swap(NextSwapMessages());
275 EXPECT_EQ(1u, messages
.size());
276 EXPECT_TRUE(ContainsMessage(messages
, messages_
[2]));
278 EXPECT_TRUE(DirectSendMessages().empty());
279 EXPECT_TRUE(NextSwapMessages().empty());
280 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
283 void QueueMessageSwapPromiseTest::VisualStateSwapPromiseDidNotSwap(
284 cc::SwapPromise::DidNotSwapReason reason
) {
285 QueueMessageData data
[] = {
286 /* { policy, commit_requested, source_frame_number } */
287 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, true, 1},
288 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, false, 1},
289 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, false, 2},
291 QueueMessages(data
, arraysize(data
));
293 promises_
[0]->DidNotSwap(reason
);
294 ASSERT_FALSE(promises_
[1]);
295 EXPECT_TRUE(NextSwapMessages().empty());
296 EXPECT_EQ(2u, DirectSendMessages().size());
297 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[0]));
298 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[1]));
299 EXPECT_FALSE(ContainsMessage(DirectSendMessages(), messages_
[2]));
301 promises_
[2]->DidNotSwap(reason
);
302 EXPECT_TRUE(NextSwapMessages().empty());
303 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[2]));
305 EXPECT_TRUE(NextSwapMessages().empty());
306 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
309 TEST_F(QueueMessageSwapPromiseTest
, VisalStateSwapPromiseDidNotSwapNoUpdate
) {
310 VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE
);
313 TEST_F(QueueMessageSwapPromiseTest
,
314 VisalStateSwapPromiseDidNotSwapCommitFails
) {
315 VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_FAILS
);
318 TEST_F(QueueMessageSwapPromiseTest
, VisalStateSwapPromiseDidNotSwapSwapFails
) {
319 VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::SWAP_FAILS
);
322 } // namespace content