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/scheduler/renderer_task_queue_selector.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/scoped_vector.h"
10 #include "base/pending_task.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
16 class RendererTaskQueueSelectorTest
: public testing::Test
{
18 RendererTaskQueueSelectorTest()
20 base::Bind(&RendererTaskQueueSelectorTest::TestFunction
)) {}
21 ~RendererTaskQueueSelectorTest() override
{}
23 std::vector
<base::PendingTask
> GetTasks(int count
) {
24 std::vector
<base::PendingTask
> tasks
;
25 for (int i
= 0; i
< count
; i
++) {
26 base::PendingTask task
= base::PendingTask(FROM_HERE
, test_closure_
);
27 task
.sequence_num
= i
;
28 tasks
.push_back(task
);
33 void PushTasks(const std::vector
<base::PendingTask
>& tasks
,
34 const size_t queue_indices
[]) {
35 for (size_t i
= 0; i
< tasks
.size(); i
++) {
36 task_queues_
[queue_indices
[i
]]->push(tasks
[i
]);
40 std::vector
<size_t> PopTasks() {
41 std::vector
<size_t> order
;
42 size_t chosen_queue_index
;
43 while (selector_
.SelectWorkQueueToService(&chosen_queue_index
)) {
44 order
.push_back(chosen_queue_index
);
45 task_queues_
[chosen_queue_index
]->pop();
50 static void TestFunction() {}
54 std::vector
<const base::TaskQueue
*> const_task_queues
;
55 for (size_t i
= 0; i
< kTaskQueueCount
; i
++) {
56 scoped_ptr
<base::TaskQueue
> task_queue(new base::TaskQueue());
57 const_task_queues
.push_back(task_queue
.get());
58 task_queues_
.push_back(task_queue
.release());
60 selector_
.RegisterWorkQueues(const_task_queues
);
63 const size_t kTaskQueueCount
= 5;
64 base::Closure test_closure_
;
65 RendererTaskQueueSelector selector_
;
66 ScopedVector
<base::TaskQueue
> task_queues_
;
69 TEST_F(RendererTaskQueueSelectorTest
, TestDefaultPriority
) {
70 std::vector
<base::PendingTask
> tasks
= GetTasks(5);
71 size_t queue_order
[] = {4, 3, 2, 1, 0};
72 PushTasks(tasks
, queue_order
);
73 EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 3, 2, 1, 0));
76 TEST_F(RendererTaskQueueSelectorTest
, TestHighPriority
) {
77 std::vector
<base::PendingTask
> tasks
= GetTasks(5);
78 size_t queue_order
[] = {0, 1, 2, 3, 4};
79 PushTasks(tasks
, queue_order
);
80 selector_
.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY
);
81 EXPECT_THAT(PopTasks(), testing::ElementsAre(2, 0, 1, 3, 4));
84 TEST_F(RendererTaskQueueSelectorTest
, TestBestEffortPriority
) {
85 std::vector
<base::PendingTask
> tasks
= GetTasks(5);
86 size_t queue_order
[] = {0, 1, 2, 3, 4};
87 PushTasks(tasks
, queue_order
);
88 selector_
.SetQueuePriority(0,
89 RendererTaskQueueSelector::BEST_EFFORT_PRIORITY
);
90 selector_
.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY
);
91 EXPECT_THAT(PopTasks(), testing::ElementsAre(2, 1, 3, 4, 0));
94 TEST_F(RendererTaskQueueSelectorTest
, TestControlPriority
) {
95 std::vector
<base::PendingTask
> tasks
= GetTasks(5);
96 size_t queue_order
[] = {0, 1, 2, 3, 4};
97 PushTasks(tasks
, queue_order
);
98 selector_
.SetQueuePriority(4, RendererTaskQueueSelector::CONTROL_PRIORITY
);
99 selector_
.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY
);
100 EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 2, 0, 1, 3));
103 TEST_F(RendererTaskQueueSelectorTest
, TestDisableEnable
) {
104 std::vector
<base::PendingTask
> tasks
= GetTasks(5);
105 size_t queue_order
[] = {0, 1, 2, 3, 4};
106 PushTasks(tasks
, queue_order
);
107 selector_
.DisableQueue(2);
108 selector_
.DisableQueue(4);
109 EXPECT_THAT(PopTasks(), testing::ElementsAre(0, 1, 3));
110 selector_
.EnableQueue(2, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY
);
111 EXPECT_THAT(PopTasks(), testing::ElementsAre(2));
112 selector_
.EnableQueue(4, RendererTaskQueueSelector::NORMAL_PRIORITY
);
113 EXPECT_THAT(PopTasks(), testing::ElementsAre(4));
116 TEST_F(RendererTaskQueueSelectorTest
, TestEmptyQueues
) {
117 size_t chosen_queue_index
= 0;
118 EXPECT_FALSE(selector_
.SelectWorkQueueToService(&chosen_queue_index
));
120 // Test only disabled queues.
121 std::vector
<base::PendingTask
> tasks
= GetTasks(1);
122 size_t queue_order
[] = {0};
123 PushTasks(tasks
, queue_order
);
124 selector_
.DisableQueue(0);
125 EXPECT_FALSE(selector_
.SelectWorkQueueToService(&chosen_queue_index
));
128 TEST_F(RendererTaskQueueSelectorTest
, TestDelay
) {
129 std::vector
<base::PendingTask
> tasks
= GetTasks(5);
130 tasks
[0].delayed_run_time
=
131 base::TimeTicks() + base::TimeDelta::FromMilliseconds(200);
132 tasks
[3].delayed_run_time
=
133 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
134 size_t queue_order
[] = {0, 1, 2, 3, 4};
135 PushTasks(tasks
, queue_order
);
136 EXPECT_THAT(PopTasks(), testing::ElementsAre(1, 2, 4, 3, 0));
139 TEST_F(RendererTaskQueueSelectorTest
, TestControlStarvesOthers
) {
140 std::vector
<base::PendingTask
> tasks
= GetTasks(4);
141 size_t queue_order
[] = {0, 1, 2, 3};
142 PushTasks(tasks
, queue_order
);
143 selector_
.SetQueuePriority(3, RendererTaskQueueSelector::CONTROL_PRIORITY
);
144 selector_
.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY
);
145 selector_
.SetQueuePriority(1,
146 RendererTaskQueueSelector::BEST_EFFORT_PRIORITY
);
147 for (int i
= 0; i
< 100; i
++) {
148 size_t chosen_queue_index
= 0;
149 EXPECT_TRUE(selector_
.SelectWorkQueueToService(&chosen_queue_index
));
150 EXPECT_EQ(3ul, chosen_queue_index
);
151 // Don't remove task from queue to simulate all queues still being full.
155 TEST_F(RendererTaskQueueSelectorTest
, TestHighPriorityDoesNotStarveNormal
) {
156 std::vector
<base::PendingTask
> tasks
= GetTasks(3);
157 size_t queue_order
[] = {0, 1, 2};
158 PushTasks(tasks
, queue_order
);
159 selector_
.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY
);
160 selector_
.SetQueuePriority(1,
161 RendererTaskQueueSelector::BEST_EFFORT_PRIORITY
);
162 size_t counts
[] = {0, 0, 0};
163 for (int i
= 0; i
< 100; i
++) {
164 size_t chosen_queue_index
= 0;
165 EXPECT_TRUE(selector_
.SelectWorkQueueToService(&chosen_queue_index
));
166 counts
[chosen_queue_index
]++;
167 // Don't remove task from queue to simulate all queues still being full.
169 EXPECT_GT(counts
[0], 0ul); // Check high doesn't starve normal.
170 EXPECT_GT(counts
[2], counts
[0]); // Check high gets more chance to run.
171 EXPECT_EQ(0ul, counts
[1]); // Check best effort is starved.
174 TEST_F(RendererTaskQueueSelectorTest
, TestBestEffortGetsStarved
) {
175 std::vector
<base::PendingTask
> tasks
= GetTasks(2);
176 size_t queue_order
[] = {0, 1};
177 PushTasks(tasks
, queue_order
);
178 selector_
.SetQueuePriority(0,
179 RendererTaskQueueSelector::BEST_EFFORT_PRIORITY
);
180 selector_
.SetQueuePriority(1, RendererTaskQueueSelector::NORMAL_PRIORITY
);
181 size_t chosen_queue_index
= 0;
182 for (int i
= 0; i
< 100; i
++) {
183 EXPECT_TRUE(selector_
.SelectWorkQueueToService(&chosen_queue_index
));
184 EXPECT_EQ(1ul, chosen_queue_index
);
185 // Don't remove task from queue to simulate all queues still being full.
187 selector_
.SetQueuePriority(1, RendererTaskQueueSelector::HIGH_PRIORITY
);
188 for (int i
= 0; i
< 100; i
++) {
189 EXPECT_TRUE(selector_
.SelectWorkQueueToService(&chosen_queue_index
));
190 EXPECT_EQ(1ul, chosen_queue_index
);
191 // Don't remove task from queue to simulate all queues still being full.
193 selector_
.SetQueuePriority(1, RendererTaskQueueSelector::CONTROL_PRIORITY
);
194 for (int i
= 0; i
< 100; i
++) {
195 EXPECT_TRUE(selector_
.SelectWorkQueueToService(&chosen_queue_index
));
196 EXPECT_EQ(1ul, chosen_queue_index
);
197 // Don't remove task from queue to simulate all queues still being full.
201 } // namespace content