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_
->DidSwap(source_frame_number
);
51 scoped_ptr
<FrameSwapMessageQueue::SendMessageScope
> send_message_scope
=
52 queue_
->AcquireSendMessageScope();
53 queue_
->DrainMessages(messages
);
56 bool HasMessageForId(const ScopedVector
<IPC::Message
>& messages
,
58 for (ScopedVector
<IPC::Message
>::const_iterator i
= messages
.begin();
61 if ((*i
)->routing_id() == routing_id
)
67 scoped_ptr
<IPC::Message
> CloneMessage(const IPC::Message
& other
) {
68 return make_scoped_ptr(new IPC::Message(other
)).Pass();
71 void TestDidNotSwap(cc::SwapPromise::DidNotSwapReason reason
);
73 IPC::Message first_message_
;
74 IPC::Message second_message_
;
75 IPC::Message third_message_
;
76 scoped_refptr
<FrameSwapMessageQueue
> queue_
;
79 TEST_F(FrameSwapMessageQueueTest
, TestEmptyQueueDrain
) {
80 ScopedVector
<IPC::Message
> messages
;
82 DrainMessages(0, &messages
);
83 ASSERT_TRUE(messages
.empty());
86 TEST_F(FrameSwapMessageQueueTest
, TestEmpty
) {
87 ScopedVector
<IPC::Message
> messages
;
88 ASSERT_TRUE(queue_
->Empty());
89 QueueNextSwapMessage(CloneMessage(first_message_
));
90 ASSERT_FALSE(queue_
->Empty());
91 DrainMessages(0, &messages
);
92 ASSERT_TRUE(queue_
->Empty());
93 QueueVisualStateMessage(1, CloneMessage(first_message_
));
94 ASSERT_FALSE(queue_
->Empty());
96 ASSERT_FALSE(queue_
->Empty());
99 TEST_F(FrameSwapMessageQueueTest
, TestQueueMessageFirst
) {
100 ScopedVector
<IPC::Message
> messages
;
101 bool visual_state_first
= false;
102 bool next_swap_first
= false;
104 // Queuing the first time should result in true.
105 QueueVisualStateMessage(1, CloneMessage(first_message_
), &visual_state_first
);
106 ASSERT_TRUE(visual_state_first
);
107 // Queuing the second time should result in true.
108 QueueVisualStateMessage(
109 1, CloneMessage(second_message_
), &visual_state_first
);
110 ASSERT_FALSE(visual_state_first
);
111 // Queuing for a different frame should result in true.
112 QueueVisualStateMessage(2, CloneMessage(first_message_
), &visual_state_first
);
113 ASSERT_TRUE(visual_state_first
);
115 // Queuing for a different policy should result in true.
116 QueueNextSwapMessage(CloneMessage(first_message_
), &next_swap_first
);
117 ASSERT_TRUE(next_swap_first
);
118 // Second time for the same policy is still false.
119 QueueNextSwapMessage(CloneMessage(first_message_
), &next_swap_first
);
120 ASSERT_FALSE(next_swap_first
);
122 DrainMessages(4, &messages
);
123 // Queuing after all messages are drained is a true again.
124 QueueVisualStateMessage(4, CloneMessage(first_message_
), &visual_state_first
);
125 ASSERT_TRUE(visual_state_first
);
128 TEST_F(FrameSwapMessageQueueTest
, TestNextSwapMessageSentWithNextFrame
) {
129 ScopedVector
<IPC::Message
> messages
;
131 DrainMessages(1, &messages
);
132 QueueNextSwapMessage(CloneMessage(first_message_
));
133 DrainMessages(2, &messages
);
134 ASSERT_EQ(1u, messages
.size());
135 ASSERT_EQ(first_message_
.routing_id(), messages
.front()->routing_id());
138 DrainMessages(2, &messages
);
139 ASSERT_TRUE(messages
.empty());
142 TEST_F(FrameSwapMessageQueueTest
, TestNextSwapMessageSentWithCurrentFrame
) {
143 ScopedVector
<IPC::Message
> messages
;
145 DrainMessages(1, &messages
);
146 QueueNextSwapMessage(CloneMessage(first_message_
));
147 DrainMessages(1, &messages
);
148 ASSERT_EQ(1u, messages
.size());
149 ASSERT_EQ(first_message_
.routing_id(), messages
.front()->routing_id());
152 DrainMessages(1, &messages
);
153 ASSERT_TRUE(messages
.empty());
156 TEST_F(FrameSwapMessageQueueTest
,
157 TestDrainsVisualStateMessagesForCorrespondingFrames
) {
158 ScopedVector
<IPC::Message
> messages
;
160 QueueVisualStateMessage(1, CloneMessage(first_message_
));
161 QueueVisualStateMessage(2, CloneMessage(second_message_
));
162 QueueVisualStateMessage(3, CloneMessage(third_message_
));
163 DrainMessages(0, &messages
);
164 ASSERT_TRUE(messages
.empty());
166 DrainMessages(2, &messages
);
167 ASSERT_EQ(2u, messages
.size());
168 ASSERT_TRUE(HasMessageForId(messages
, first_message_
.routing_id()));
169 ASSERT_TRUE(HasMessageForId(messages
, second_message_
.routing_id()));
172 DrainMessages(2, &messages
);
173 ASSERT_TRUE(messages
.empty());
175 DrainMessages(5, &messages
);
176 ASSERT_EQ(1u, messages
.size());
177 ASSERT_EQ(third_message_
.routing_id(), messages
.front()->routing_id());
180 TEST_F(FrameSwapMessageQueueTest
,
181 TestQueueNextSwapMessagePreservesFifoOrdering
) {
182 ScopedVector
<IPC::Message
> messages
;
184 QueueNextSwapMessage(CloneMessage(first_message_
));
185 QueueNextSwapMessage(CloneMessage(second_message_
));
186 DrainMessages(1, &messages
);
187 ASSERT_EQ(2u, messages
.size());
188 ASSERT_EQ(first_message_
.routing_id(), messages
[0]->routing_id());
189 ASSERT_EQ(second_message_
.routing_id(), messages
[1]->routing_id());
192 TEST_F(FrameSwapMessageQueueTest
,
193 TestQueueVisualStateMessagePreservesFifoOrdering
) {
194 ScopedVector
<IPC::Message
> messages
;
196 QueueVisualStateMessage(1, CloneMessage(first_message_
));
197 QueueVisualStateMessage(1, CloneMessage(second_message_
));
198 DrainMessages(1, &messages
);
199 ASSERT_EQ(2u, messages
.size());
200 ASSERT_EQ(first_message_
.routing_id(), messages
[0]->routing_id());
201 ASSERT_EQ(second_message_
.routing_id(), messages
[1]->routing_id());
204 void FrameSwapMessageQueueTest::TestDidNotSwap(
205 cc::SwapPromise::DidNotSwapReason reason
) {
206 ScopedVector
<IPC::Message
> messages
;
208 QueueNextSwapMessage(CloneMessage(first_message_
));
209 QueueVisualStateMessage(2, CloneMessage(second_message_
));
210 QueueVisualStateMessage(3, CloneMessage(third_message_
));
212 queue_
->DidNotSwap(2, cc::SwapPromise::COMMIT_NO_UPDATE
, &messages
);
213 ASSERT_EQ(2u, messages
.size());
214 ASSERT_TRUE(HasMessageForId(messages
, first_message_
.routing_id()));
215 ASSERT_TRUE(HasMessageForId(messages
, second_message_
.routing_id()));
218 queue_
->DidNotSwap(3, cc::SwapPromise::COMMIT_NO_UPDATE
, &messages
);
219 ASSERT_EQ(1u, messages
.size());
220 ASSERT_TRUE(HasMessageForId(messages
, third_message_
.routing_id()));
224 TEST_F(FrameSwapMessageQueueTest
, TestDidNotSwapNoUpdate
) {
225 TestDidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE
);
228 TEST_F(FrameSwapMessageQueueTest
, TestDidNotSwapSwapFails
) {
229 TestDidNotSwap(cc::SwapPromise::SWAP_FAILS
);
232 TEST_F(FrameSwapMessageQueueTest
, TestDidNotSwapCommitFails
) {
233 ScopedVector
<IPC::Message
> messages
;
235 QueueNextSwapMessage(CloneMessage(first_message_
));
236 QueueVisualStateMessage(2, CloneMessage(second_message_
));
237 QueueVisualStateMessage(3, CloneMessage(third_message_
));
239 queue_
->DidNotSwap(2, cc::SwapPromise::COMMIT_FAILS
, &messages
);
240 ASSERT_EQ(0u, messages
.size());
243 queue_
->DidNotSwap(3, cc::SwapPromise::COMMIT_FAILS
, &messages
);
244 ASSERT_EQ(0u, messages
.size());
247 DrainMessages(1, &messages
);
248 ASSERT_EQ(1u, messages
.size());
249 ASSERT_TRUE(HasMessageForId(messages
, first_message_
.routing_id()));
252 class NotifiesDeletionMessage
: public IPC::Message
{
254 NotifiesDeletionMessage(bool* deleted
, const IPC::Message
& other
)
255 : IPC::Message(other
), deleted_(deleted
) {}
256 ~NotifiesDeletionMessage() override
{ *deleted_
= true; }
262 TEST_F(FrameSwapMessageQueueTest
, TestDeletesNextSwapMessage
) {
263 bool message_deleted
= false;
264 QueueNextSwapMessage(make_scoped_ptr(
265 new NotifiesDeletionMessage(&message_deleted
, first_message_
)));
267 ASSERT_TRUE(message_deleted
);
270 TEST_F(FrameSwapMessageQueueTest
, TestDeletesVisualStateMessage
) {
271 bool message_deleted
= false;
272 QueueVisualStateMessage(1,
273 make_scoped_ptr(new NotifiesDeletionMessage(
274 &message_deleted
, first_message_
)));
276 ASSERT_TRUE(message_deleted
);
279 TEST_F(FrameSwapMessageQueueTest
, TestDeletesQueuedVisualStateMessage
) {
280 bool message_deleted
= false;
281 QueueVisualStateMessage(1,
282 make_scoped_ptr(new NotifiesDeletionMessage(
283 &message_deleted
, first_message_
)));
286 ASSERT_TRUE(message_deleted
);
289 } // namespace content