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/frame_swap_message_queue.h"
6 #include "ipc/ipc_message.h"
7 #include "testing/gtest/include/gtest/gtest.h"
11 class FrameSwapMessageQueueTest
: public testing::Test
{
13 FrameSwapMessageQueueTest()
14 : first_message_(41, 1, IPC::Message::PRIORITY_NORMAL
),
15 second_message_(42, 2, IPC::Message::PRIORITY_NORMAL
),
16 third_message_(43, 3, IPC::Message::PRIORITY_NORMAL
),
17 queue_(new FrameSwapMessageQueue()) {}
20 void QueueNextSwapMessage(scoped_ptr
<IPC::Message
> msg
) {
21 queue_
->QueueMessageForFrame(
22 MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 0, msg
.Pass(), NULL
);
25 void QueueNextSwapMessage(scoped_ptr
<IPC::Message
> msg
, bool* first
) {
26 queue_
->QueueMessageForFrame(
27 MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP
, 0, msg
.Pass(), first
);
30 void QueueVisualStateMessage(int source_frame_number
,
31 scoped_ptr
<IPC::Message
> msg
) {
32 queue_
->QueueMessageForFrame(MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
,
38 void QueueVisualStateMessage(int source_frame_number
,
39 scoped_ptr
<IPC::Message
> msg
,
41 queue_
->QueueMessageForFrame(MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE
,
47 void DrainMessages(int source_frame_number
,
48 ScopedVector
<IPC::Message
>* messages
) {
50 queue_
->DidActivate(source_frame_number
);
51 queue_
->DidSwap(source_frame_number
);
52 scoped_ptr
<FrameSwapMessageQueue::SendMessageScope
> send_message_scope
=
53 queue_
->AcquireSendMessageScope();
54 queue_
->DrainMessages(messages
);
57 bool HasMessageForId(const ScopedVector
<IPC::Message
>& messages
,
59 for (ScopedVector
<IPC::Message
>::const_iterator i
= messages
.begin();
62 if ((*i
)->routing_id() == routing_id
)
68 scoped_ptr
<IPC::Message
> CloneMessage(const IPC::Message
& other
) {
69 return make_scoped_ptr(new IPC::Message(other
)).Pass();
72 void TestDidNotSwap(cc::SwapPromise::DidNotSwapReason reason
);
74 IPC::Message first_message_
;
75 IPC::Message second_message_
;
76 IPC::Message third_message_
;
77 scoped_refptr
<FrameSwapMessageQueue
> queue_
;
80 TEST_F(FrameSwapMessageQueueTest
, TestEmptyQueueDrain
) {
81 ScopedVector
<IPC::Message
> messages
;
83 DrainMessages(0, &messages
);
84 ASSERT_TRUE(messages
.empty());
87 TEST_F(FrameSwapMessageQueueTest
, TestEmpty
) {
88 ScopedVector
<IPC::Message
> messages
;
89 ASSERT_TRUE(queue_
->Empty());
90 QueueNextSwapMessage(CloneMessage(first_message_
));
91 ASSERT_FALSE(queue_
->Empty());
92 DrainMessages(0, &messages
);
93 ASSERT_TRUE(queue_
->Empty());
94 QueueVisualStateMessage(1, CloneMessage(first_message_
));
95 ASSERT_FALSE(queue_
->Empty());
96 queue_
->DidActivate(1);
98 ASSERT_FALSE(queue_
->Empty());
101 TEST_F(FrameSwapMessageQueueTest
, TestQueueMessageFirst
) {
102 ScopedVector
<IPC::Message
> messages
;
103 bool visual_state_first
= false;
104 bool next_swap_first
= false;
106 // Queuing the first time should result in true.
107 QueueVisualStateMessage(1, CloneMessage(first_message_
), &visual_state_first
);
108 ASSERT_TRUE(visual_state_first
);
109 // Queuing the second time should result in true.
110 QueueVisualStateMessage(
111 1, CloneMessage(second_message_
), &visual_state_first
);
112 ASSERT_FALSE(visual_state_first
);
113 // Queuing for a different frame should result in true.
114 QueueVisualStateMessage(2, CloneMessage(first_message_
), &visual_state_first
);
115 ASSERT_TRUE(visual_state_first
);
117 // Queuing for a different policy should result in true.
118 QueueNextSwapMessage(CloneMessage(first_message_
), &next_swap_first
);
119 ASSERT_TRUE(next_swap_first
);
120 // Second time for the same policy is still false.
121 QueueNextSwapMessage(CloneMessage(first_message_
), &next_swap_first
);
122 ASSERT_FALSE(next_swap_first
);
124 DrainMessages(4, &messages
);
125 // Queuing after all messages are drained is a true again.
126 QueueVisualStateMessage(4, CloneMessage(first_message_
), &visual_state_first
);
127 ASSERT_TRUE(visual_state_first
);
130 TEST_F(FrameSwapMessageQueueTest
, TestNextSwapMessageSentWithNextFrame
) {
131 ScopedVector
<IPC::Message
> messages
;
133 DrainMessages(1, &messages
);
134 QueueNextSwapMessage(CloneMessage(first_message_
));
135 DrainMessages(2, &messages
);
136 ASSERT_EQ(1u, messages
.size());
137 ASSERT_EQ(first_message_
.routing_id(), messages
.front()->routing_id());
140 DrainMessages(2, &messages
);
141 ASSERT_TRUE(messages
.empty());
144 TEST_F(FrameSwapMessageQueueTest
, TestNextSwapMessageSentWithCurrentFrame
) {
145 ScopedVector
<IPC::Message
> messages
;
147 DrainMessages(1, &messages
);
148 QueueNextSwapMessage(CloneMessage(first_message_
));
149 DrainMessages(1, &messages
);
150 ASSERT_EQ(1u, messages
.size());
151 ASSERT_EQ(first_message_
.routing_id(), messages
.front()->routing_id());
154 DrainMessages(1, &messages
);
155 ASSERT_TRUE(messages
.empty());
158 TEST_F(FrameSwapMessageQueueTest
,
159 TestDrainsVisualStateMessagesForCorrespondingFrames
) {
160 ScopedVector
<IPC::Message
> messages
;
162 QueueVisualStateMessage(1, CloneMessage(first_message_
));
163 QueueVisualStateMessage(2, CloneMessage(second_message_
));
164 QueueVisualStateMessage(3, CloneMessage(third_message_
));
165 DrainMessages(0, &messages
);
166 ASSERT_TRUE(messages
.empty());
168 DrainMessages(2, &messages
);
169 ASSERT_EQ(2u, messages
.size());
170 ASSERT_TRUE(HasMessageForId(messages
, first_message_
.routing_id()));
171 ASSERT_TRUE(HasMessageForId(messages
, second_message_
.routing_id()));
174 DrainMessages(2, &messages
);
175 ASSERT_TRUE(messages
.empty());
177 DrainMessages(5, &messages
);
178 ASSERT_EQ(1u, messages
.size());
179 ASSERT_EQ(third_message_
.routing_id(), messages
.front()->routing_id());
182 TEST_F(FrameSwapMessageQueueTest
,
183 TestQueueNextSwapMessagePreservesFifoOrdering
) {
184 ScopedVector
<IPC::Message
> messages
;
186 QueueNextSwapMessage(CloneMessage(first_message_
));
187 QueueNextSwapMessage(CloneMessage(second_message_
));
188 DrainMessages(1, &messages
);
189 ASSERT_EQ(2u, messages
.size());
190 ASSERT_EQ(first_message_
.routing_id(), messages
[0]->routing_id());
191 ASSERT_EQ(second_message_
.routing_id(), messages
[1]->routing_id());
194 TEST_F(FrameSwapMessageQueueTest
,
195 TestQueueVisualStateMessagePreservesFifoOrdering
) {
196 ScopedVector
<IPC::Message
> messages
;
198 QueueVisualStateMessage(1, CloneMessage(first_message_
));
199 QueueVisualStateMessage(1, CloneMessage(second_message_
));
200 DrainMessages(1, &messages
);
201 ASSERT_EQ(2u, messages
.size());
202 ASSERT_EQ(first_message_
.routing_id(), messages
[0]->routing_id());
203 ASSERT_EQ(second_message_
.routing_id(), messages
[1]->routing_id());
206 void FrameSwapMessageQueueTest::TestDidNotSwap(
207 cc::SwapPromise::DidNotSwapReason reason
) {
208 ScopedVector
<IPC::Message
> messages
;
210 QueueNextSwapMessage(CloneMessage(first_message_
));
211 QueueVisualStateMessage(2, CloneMessage(second_message_
));
212 QueueVisualStateMessage(3, CloneMessage(third_message_
));
213 const int rid
[] = {first_message_
.routing_id(),
214 second_message_
.routing_id(),
215 third_message_
.routing_id()};
217 bool msg_delivered
= reason
!= cc::SwapPromise::COMMIT_FAILS
&&
218 reason
!= cc::SwapPromise::ACTIVATION_FAILS
;
220 queue_
->DidNotSwap(2, reason
, &messages
);
221 ASSERT_TRUE(msg_delivered
== HasMessageForId(messages
, rid
[0]));
222 ASSERT_TRUE(msg_delivered
== HasMessageForId(messages
, rid
[1]));
223 ASSERT_FALSE(HasMessageForId(messages
, rid
[2]));
226 queue_
->DidNotSwap(3, reason
, &messages
);
227 ASSERT_FALSE(HasMessageForId(messages
, rid
[0]));
228 ASSERT_FALSE(HasMessageForId(messages
, rid
[1]));
229 ASSERT_TRUE(msg_delivered
== HasMessageForId(messages
, rid
[2]));
232 // all undelivered messages should still be available for RenderFrameHostImpl
234 DrainMessages(3, &messages
);
235 ASSERT_TRUE(msg_delivered
!= HasMessageForId(messages
, rid
[0]));
236 ASSERT_TRUE(msg_delivered
!= HasMessageForId(messages
, rid
[1]));
237 ASSERT_TRUE(msg_delivered
!= HasMessageForId(messages
, rid
[2]));
240 TEST_F(FrameSwapMessageQueueTest
, TestDidNotSwapNoUpdate
) {
241 TestDidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE
);
244 TEST_F(FrameSwapMessageQueueTest
, TestDidNotSwapSwapFails
) {
245 TestDidNotSwap(cc::SwapPromise::SWAP_FAILS
);
248 TEST_F(FrameSwapMessageQueueTest
, TestDidNotSwapCommitFails
) {
249 TestDidNotSwap(cc::SwapPromise::COMMIT_FAILS
);
252 TEST_F(FrameSwapMessageQueueTest
, TestDidNotSwapActivationFails
) {
253 TestDidNotSwap(cc::SwapPromise::ACTIVATION_FAILS
);
256 class NotifiesDeletionMessage
: public IPC::Message
{
258 NotifiesDeletionMessage(bool* deleted
, const IPC::Message
& other
)
259 : IPC::Message(other
), deleted_(deleted
) {}
260 ~NotifiesDeletionMessage() override
{ *deleted_
= true; }
266 TEST_F(FrameSwapMessageQueueTest
, TestDeletesNextSwapMessage
) {
267 bool message_deleted
= false;
268 QueueNextSwapMessage(make_scoped_ptr(
269 new NotifiesDeletionMessage(&message_deleted
, first_message_
)));
271 ASSERT_TRUE(message_deleted
);
274 TEST_F(FrameSwapMessageQueueTest
, TestDeletesVisualStateMessage
) {
275 bool message_deleted
= false;
276 QueueVisualStateMessage(1,
277 make_scoped_ptr(new NotifiesDeletionMessage(
278 &message_deleted
, first_message_
)));
280 ASSERT_TRUE(message_deleted
);
283 TEST_F(FrameSwapMessageQueueTest
, TestDeletesQueuedVisualStateMessage
) {
284 bool message_deleted
= false;
285 QueueVisualStateMessage(1,
286 make_scoped_ptr(new NotifiesDeletionMessage(
287 &message_deleted
, first_message_
)));
288 queue_
->DidActivate(1);
291 ASSERT_TRUE(message_deleted
);
294 } // namespace content