OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "content/renderer/scheduler/renderer_task_queue_selector.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/memory/scoped_ptr.h" | |
9 #include "base/pending_task.h" | |
10 #include "testing/gmock/include/gmock/gmock.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 | |
13 namespace content { | |
14 | |
15 class RendererTaskQueueSelectorTest : public testing::Test { | |
16 public: | |
17 RendererTaskQueueSelectorTest() | |
18 : test_closure_( | |
19 base::Bind(&RendererTaskQueueSelectorTest::TestFunction)) {} | |
20 ~RendererTaskQueueSelectorTest() override {} | |
21 | |
22 std::vector<base::PendingTask> GetTasks(int count) { | |
23 std::vector<base::PendingTask> tasks; | |
24 for (int i = 0; i < count; i++) { | |
25 base::PendingTask task = base::PendingTask(FROM_HERE, test_closure_); | |
26 task.sequence_num = i; | |
27 tasks.push_back(task); | |
28 } | |
29 return tasks; | |
30 } | |
31 | |
32 void PushTasks(const std::vector<base::PendingTask>& tasks, | |
33 const std::vector<size_t>& queue_indices) { | |
34 EXPECT_EQ(tasks.size(), queue_indices.size()); | |
35 for (size_t i = 0; i < tasks.size(); i++) { | |
36 task_queues_[queue_indices[i]]->push(tasks[i]); | |
37 } | |
38 } | |
39 | |
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(); | |
46 } | |
47 return order; | |
48 } | |
49 | |
50 static void TestFunction() {} | |
51 | |
52 protected: | |
53 void SetUp() final { | |
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.Pass()); | |
59 } | |
60 selector_.RegisterWorkQueues(const_task_queues); | |
61 } | |
62 | |
63 const size_t kTaskQueueCount = 5; | |
64 base::Closure test_closure_; | |
65 RendererTaskQueueSelector selector_; | |
66 std::vector<scoped_ptr<base::TaskQueue>> task_queues_; | |
67 }; | |
68 | |
69 TEST_F(RendererTaskQueueSelectorTest, TestDefaultPriority) { | |
70 std::vector<base::PendingTask> tasks = GetTasks(5); | |
71 PushTasks(tasks, std::vector<size_t>{4, 3, 2, 1, 0}); | |
Sami
2014/10/28 18:31:48
Turns out we ended up banning uniform initializers
rmcilroy
2014/10/28 18:37:40
Yeah I just noticed this, thanks. I'll update it
| |
72 EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 3, 2, 1, 0)); | |
73 } | |
74 | |
75 TEST_F(RendererTaskQueueSelectorTest, TestHighPriority) { | |
76 std::vector<base::PendingTask> tasks = GetTasks(5); | |
77 PushTasks(tasks, std::vector<size_t>{0, 1, 2, 3, 4}); | |
78 selector_.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY); | |
79 EXPECT_THAT(PopTasks(), testing::ElementsAre(2, 0, 1, 3, 4)); | |
80 } | |
81 | |
82 TEST_F(RendererTaskQueueSelectorTest, TestBestEffortPriority) { | |
83 std::vector<base::PendingTask> tasks = GetTasks(5); | |
84 PushTasks(tasks, std::vector<size_t>{0, 1, 2, 3, 4}); | |
85 selector_.SetQueuePriority(0, | |
86 RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | |
87 selector_.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY); | |
88 EXPECT_THAT(PopTasks(), testing::ElementsAre(2, 1, 3, 4, 0)); | |
89 } | |
90 | |
91 TEST_F(RendererTaskQueueSelectorTest, TestControlPriority) { | |
92 std::vector<base::PendingTask> tasks = GetTasks(5); | |
93 PushTasks(tasks, std::vector<size_t>{0, 1, 2, 3, 4}); | |
94 selector_.SetQueuePriority(4, RendererTaskQueueSelector::CONTROL_PRIORITY); | |
95 selector_.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY); | |
96 EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 2, 0, 1, 3)); | |
97 } | |
98 | |
99 TEST_F(RendererTaskQueueSelectorTest, TestDisableEnable) { | |
100 std::vector<base::PendingTask> tasks = GetTasks(5); | |
101 PushTasks(tasks, std::vector<size_t>{0, 1, 2, 3, 4}); | |
102 selector_.DisableQueue(2); | |
103 selector_.DisableQueue(4); | |
104 EXPECT_THAT(PopTasks(), testing::ElementsAre(0, 1, 3)); | |
105 selector_.EnableQueue(2, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | |
106 EXPECT_THAT(PopTasks(), testing::ElementsAre(2)); | |
107 selector_.EnableQueue(4, RendererTaskQueueSelector::NORMAL_PRIORITY); | |
108 EXPECT_THAT(PopTasks(), testing::ElementsAre(4)); | |
109 } | |
110 | |
111 TEST_F(RendererTaskQueueSelectorTest, TestEmptyQueues) { | |
112 size_t chosen_queue_index = 0; | |
113 EXPECT_FALSE(selector_.SelectWorkQueueToService(&chosen_queue_index)); | |
114 | |
115 // Test only disabled queues. | |
116 std::vector<base::PendingTask> tasks = GetTasks(1); | |
117 PushTasks(tasks, std::vector<size_t>{0}); | |
118 selector_.DisableQueue(0); | |
119 EXPECT_FALSE(selector_.SelectWorkQueueToService(&chosen_queue_index)); | |
120 } | |
121 | |
122 TEST_F(RendererTaskQueueSelectorTest, TestDelay) { | |
123 std::vector<base::PendingTask> tasks = GetTasks(5); | |
124 tasks[0].delayed_run_time = | |
125 base::TimeTicks() + base::TimeDelta::FromMilliseconds(200); | |
126 tasks[3].delayed_run_time = | |
127 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100); | |
128 PushTasks(tasks, std::vector<size_t>{0, 1, 2, 3, 4}); | |
129 EXPECT_THAT(PopTasks(), testing::ElementsAre(1, 2, 4, 3, 0)); | |
130 } | |
131 | |
132 TEST_F(RendererTaskQueueSelectorTest, TestControlStarvesOthers) { | |
133 std::vector<base::PendingTask> tasks = GetTasks(4); | |
134 PushTasks(tasks, std::vector<size_t>{0, 1, 2, 3}); | |
135 selector_.SetQueuePriority(3, RendererTaskQueueSelector::CONTROL_PRIORITY); | |
136 selector_.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY); | |
137 selector_.SetQueuePriority(1, | |
138 RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | |
139 for (int i = 0; i < 100; i++) { | |
140 size_t chosen_queue_index = 0; | |
141 EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_queue_index)); | |
142 EXPECT_EQ(3ul, chosen_queue_index); | |
143 // Don't remove task from queue to simulate all queues still being full. | |
144 } | |
145 } | |
146 | |
147 TEST_F(RendererTaskQueueSelectorTest, TestHighPriorityDoesNotStarveNormal) { | |
148 std::vector<base::PendingTask> tasks = GetTasks(3); | |
149 PushTasks(tasks, std::vector<size_t>{0, 1, 2}); | |
150 selector_.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY); | |
151 selector_.SetQueuePriority(1, | |
152 RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | |
153 std::vector<size_t> counts = {0, 0, 0}; | |
154 for (int i = 0; i < 100; i++) { | |
155 size_t chosen_queue_index = 0; | |
156 EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_queue_index)); | |
157 counts[chosen_queue_index]++; | |
158 // Don't remove task from queue to simulate all queues still being full. | |
159 } | |
160 EXPECT_GT(counts[0], 0ul); // Check high doesn't starve normal. | |
161 EXPECT_GT(counts[2], counts[0]); // Check high gets more chance to run. | |
162 EXPECT_EQ(0ul, counts[1]); // Check best effort is starved. | |
163 } | |
164 | |
165 TEST_F(RendererTaskQueueSelectorTest, TestBestEffortGetsStarved) { | |
166 std::vector<base::PendingTask> tasks = GetTasks(2); | |
167 PushTasks(tasks, std::vector<size_t>{0, 1}); | |
168 selector_.SetQueuePriority(0, | |
169 RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | |
170 selector_.SetQueuePriority(1, RendererTaskQueueSelector::NORMAL_PRIORITY); | |
171 size_t chosen_queue_index = 0; | |
172 for (int i = 0; i < 100; i++) { | |
173 EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_queue_index)); | |
174 EXPECT_EQ(1ul, chosen_queue_index); | |
175 // Don't remove task from queue to simulate all queues still being full. | |
176 } | |
177 selector_.SetQueuePriority(1, RendererTaskQueueSelector::HIGH_PRIORITY); | |
178 for (int i = 0; i < 100; i++) { | |
179 EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_queue_index)); | |
180 EXPECT_EQ(1ul, chosen_queue_index); | |
181 // Don't remove task from queue to simulate all queues still being full. | |
182 } | |
183 selector_.SetQueuePriority(1, RendererTaskQueueSelector::CONTROL_PRIORITY); | |
184 for (int i = 0; i < 100; i++) { | |
185 EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_queue_index)); | |
186 EXPECT_EQ(1ul, chosen_queue_index); | |
187 // Don't remove task from queue to simulate all queues still being full. | |
188 } | |
189 } | |
190 | |
191 } // namespace content | |
OLD | NEW |