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
, false) {}
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();
126 void VisualStateSwapPromiseDidNotSwap(
127 cc::SwapPromise::DidNotSwapReason reason
);
129 base::MessageLoop message_loop_
;
130 scoped_refptr
<FrameSwapMessageQueue
> frame_swap_message_queue_
;
131 scoped_refptr
<TestSyncMessageFilter
> sync_message_filter_
;
132 std::vector
<IPC::Message
> messages_
;
133 ScopedVector
<cc::SwapPromise
> promises_
;
136 ScopedVector
<IPC::Message
> next_swap_messages_
;
138 DISALLOW_COPY_AND_ASSIGN(QueueMessageSwapPromiseTest
);
141 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicySchedulesMessageForNextSwap
) {
142 QueueMessageData data
[] = {
143 /* { policy, source_frame_number } */
144 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
146 QueueMessages(data
, arraysize(data
));
148 ASSERT_TRUE(promises_
[0]);
149 promises_
[0]->DidActivate();
150 promises_
[0]->DidSwap(NULL
);
152 EXPECT_TRUE(DirectSendMessages().empty());
153 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
154 // frame_swap_message_queue_->DidSwap(1);
155 EXPECT_TRUE(NextSwapHasMessage(messages_
[0]));
158 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicyNeedsAtMostOnePromise
) {
159 QueueMessageData data
[] = {
160 /* { policy, source_frame_number } */
161 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
162 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
164 QueueMessages(data
, arraysize(data
));
166 ASSERT_TRUE(promises_
[0]);
167 ASSERT_FALSE(promises_
[1]);
172 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicySendsMessageOnNoUpdate
) {
173 QueueMessageData data
[] = {
174 /* { policy, source_frame_number } */
175 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
177 QueueMessages(data
, arraysize(data
));
179 promises_
[0]->DidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE
);
180 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[0]));
181 EXPECT_TRUE(NextSwapMessages().empty());
182 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
185 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicySendsMessageOnSwapFails
) {
186 QueueMessageData data
[] = {
187 /* { policy, source_frame_number } */
188 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
190 QueueMessages(data
, arraysize(data
));
192 promises_
[0]->DidNotSwap(cc::SwapPromise::SWAP_FAILS
);
193 EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_
[0]));
194 EXPECT_TRUE(NextSwapMessages().empty());
195 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
198 TEST_F(QueueMessageSwapPromiseTest
, NextSwapPolicyRetainsMessageOnCommitFails
) {
199 QueueMessageData data
[] = {
200 /* { policy, source_frame_number } */
201 {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 1},
203 QueueMessages(data
, arraysize(data
));
205 promises_
[0]->DidNotSwap(cc::SwapPromise::COMMIT_FAILS
);
206 EXPECT_TRUE(DirectSendMessages().empty());
207 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
208 frame_swap_message_queue_
->DidSwap(2);
209 EXPECT_TRUE(NextSwapHasMessage(messages_
[0]));
212 TEST_F(QueueMessageSwapPromiseTest
,
213 VisualStateQueuesMessageWhenCommitRequested
) {
214 QueueMessageData data
[] = {
215 /* { policy, source_frame_number } */
216 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
218 QueueMessages(data
, arraysize(data
));
220 ASSERT_TRUE(promises_
[0]);
221 EXPECT_TRUE(DirectSendMessages().empty());
222 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
223 EXPECT_TRUE(NextSwapMessages().empty());
228 TEST_F(QueueMessageSwapPromiseTest
,
229 VisualStateQueuesMessageWhenOtherMessageAlreadyQueued
) {
230 QueueMessageData data
[] = {
231 /* { policy, source_frame_number } */
232 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
233 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
235 QueueMessages(data
, arraysize(data
));
237 EXPECT_TRUE(DirectSendMessages().empty());
238 EXPECT_FALSE(frame_swap_message_queue_
->Empty());
239 EXPECT_FALSE(NextSwapHasMessage(messages_
[1]));
244 TEST_F(QueueMessageSwapPromiseTest
, VisualStateSwapPromiseDidActivate
) {
245 QueueMessageData data
[] = {
246 /* { policy, source_frame_number } */
247 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
248 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
249 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 2},
251 QueueMessages(data
, arraysize(data
));
253 promises_
[0]->DidActivate();
254 promises_
[0]->DidSwap(NULL
);
255 ASSERT_FALSE(promises_
[1]);
256 ScopedVector
<IPC::Message
> messages
;
257 messages
.swap(NextSwapMessages());
258 EXPECT_EQ(2u, messages
.size());
259 EXPECT_TRUE(ContainsMessage(messages
, messages_
[0]));
260 EXPECT_TRUE(ContainsMessage(messages
, messages_
[1]));
261 EXPECT_FALSE(ContainsMessage(messages
, messages_
[2]));
263 promises_
[2]->DidActivate();
264 promises_
[2]->DidNotSwap(cc::SwapPromise::SWAP_FAILS
);
265 messages
.swap(NextSwapMessages());
266 EXPECT_EQ(1u, messages
.size());
267 EXPECT_TRUE(ContainsMessage(messages
, messages_
[2]));
269 EXPECT_TRUE(DirectSendMessages().empty());
270 EXPECT_TRUE(NextSwapMessages().empty());
271 EXPECT_TRUE(frame_swap_message_queue_
->Empty());
274 void QueueMessageSwapPromiseTest::VisualStateSwapPromiseDidNotSwap(
275 cc::SwapPromise::DidNotSwapReason reason
) {
276 QueueMessageData data
[] = {
277 /* { policy, source_frame_number } */
278 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
279 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 1},
280 {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
, 2},
282 QueueMessages(data
, arraysize(data
));
284 // If we fail to swap with COMMIT_FAILS or ACTIVATE_FAILS, then
285 // messages are delivered by the RenderFrameHostImpl destructor,
286 // rather than directly by the swap promise.
287 bool msg_delivered
= reason
!= cc::SwapPromise::COMMIT_FAILS
&&
288 reason
!= cc::SwapPromise::ACTIVATION_FAILS
;
290 promises_
[0]->DidNotSwap(reason
);
291 ASSERT_FALSE(promises_
[1]);
292 EXPECT_TRUE(NextSwapMessages().empty());
293 EXPECT_EQ(msg_delivered
, ContainsMessage(DirectSendMessages(), messages_
[0]));
294 EXPECT_EQ(msg_delivered
, ContainsMessage(DirectSendMessages(), messages_
[1]));
295 EXPECT_FALSE(ContainsMessage(DirectSendMessages(), messages_
[2]));
297 promises_
[2]->DidNotSwap(reason
);
298 EXPECT_TRUE(NextSwapMessages().empty());
299 EXPECT_EQ(msg_delivered
, ContainsMessage(DirectSendMessages(), messages_
[2]));
301 EXPECT_TRUE(NextSwapMessages().empty());
302 EXPECT_EQ(msg_delivered
, frame_swap_message_queue_
->Empty());
305 TEST_F(QueueMessageSwapPromiseTest
, VisualStateSwapPromiseDidNotSwapNoUpdate
) {
306 VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE
);
309 TEST_F(QueueMessageSwapPromiseTest
,
310 VisualStateSwapPromiseDidNotSwapCommitFails
) {
311 VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_FAILS
);
314 TEST_F(QueueMessageSwapPromiseTest
, VisualStateSwapPromiseDidNotSwapSwapFails
) {
315 VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::SWAP_FAILS
);
318 TEST_F(QueueMessageSwapPromiseTest
,
319 VisualStateSwapPromiseDidNotSwapActivationFails
) {
320 VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::ACTIVATION_FAILS
);
323 } // namespace content