Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / renderer / gpu / queue_message_swap_promise_unittest.cc
blob76294fbd5299ac31a51d74d46fa93727aa96ec4f
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"
7 #include <vector>
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"
20 namespace content {
22 class TestRenderWidget : public RenderWidget {
23 public:
24 using RenderWidget::QueueMessageImpl;
26 private:
27 ~TestRenderWidget() override {}
29 DISALLOW_COPY_AND_ASSIGN(TestRenderWidget);
32 class TestSyncMessageFilter : public IPC::SyncMessageFilter {
33 public:
34 TestSyncMessageFilter() : IPC::SyncMessageFilter(NULL, false) {}
36 bool Send(IPC::Message* message) override {
37 messages_.push_back(message);
38 return true;
41 ScopedVector<IPC::Message>& messages() { return messages_; }
43 private:
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 {
57 public:
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,
68 policy,
69 frame_swap_message_queue_.get(),
70 sync_message_filter_,
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) {
88 if (messages.empty())
89 return false;
90 for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
91 i != messages.end();
92 ++i) {
93 if ((*i)->type() == message.type())
94 return true;
96 return false;
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) {
105 messages_.push_back(
106 IPC::Message(0, i + 1, IPC::Message::PRIORITY_NORMAL));
107 promises_.push_back(
108 QueueMessageImpl(new IPC::Message(messages_[i]),
109 data[i].policy,
110 data[i].source_frame_number).release());
114 void CleanupPromises() {
115 for (ScopedVector<cc::SwapPromise>::iterator i = promises_.begin();
116 i != promises_.end();
117 ++i) {
118 if (*i) {
119 (*i)->DidActivate();
120 (*i)->DidSwap(NULL);
125 protected:
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_;
135 private:
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]);
169 CleanupPromises();
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());
225 CleanupPromises();
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]));
241 CleanupPromises();
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