Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: components/scheduler/child/worker_scheduler_impl_unittest.cc

Issue 2118903002: scheduler: Move the Blink scheduler into Blink (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 "components/scheduler/child/worker_scheduler_impl.h"
6
7 #include "base/callback.h"
8 #include "base/macros.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "cc/test/ordered_simple_task_runner.h"
13 #include "components/scheduler/base/test_time_source.h"
14 #include "components/scheduler/child/scheduler_tqm_delegate_for_test.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using testing::ElementsAreArray;
19
20 namespace scheduler {
21
22 namespace {
23 void NopTask() {
24 }
25
26 int TimeTicksToIntMs(const base::TimeTicks& time) {
27 return static_cast<int>((time - base::TimeTicks()).InMilliseconds());
28 }
29
30 void RecordTimelineTask(std::vector<std::string>* timeline,
31 base::SimpleTestTickClock* clock) {
32 timeline->push_back(base::StringPrintf("run RecordTimelineTask @ %d",
33 TimeTicksToIntMs(clock->NowTicks())));
34 }
35
36 void AppendToVectorTestTask(std::vector<std::string>* vector,
37 std::string value) {
38 vector->push_back(value);
39 }
40
41 void AppendToVectorIdleTestTask(std::vector<std::string>* vector,
42 std::string value,
43 base::TimeTicks deadline) {
44 AppendToVectorTestTask(vector, value);
45 }
46
47 void TimelineIdleTestTask(std::vector<std::string>* timeline,
48 base::TimeTicks deadline) {
49 timeline->push_back(base::StringPrintf("run TimelineIdleTestTask deadline %d",
50 TimeTicksToIntMs(deadline)));
51 }
52
53 }; // namespace
54
55 class WorkerSchedulerImplForTest : public WorkerSchedulerImpl {
56 public:
57 WorkerSchedulerImplForTest(
58 scoped_refptr<SchedulerTqmDelegate> main_task_runner,
59 base::SimpleTestTickClock* clock_)
60 : WorkerSchedulerImpl(main_task_runner),
61 clock_(clock_),
62 timeline_(nullptr) {}
63
64 void RecordTimelineEvents(std::vector<std::string>* timeline) {
65 timeline_ = timeline;
66 }
67
68 private:
69 bool CanEnterLongIdlePeriod(
70 base::TimeTicks now,
71 base::TimeDelta* next_long_idle_period_delay_out) override {
72 if (timeline_) {
73 timeline_->push_back(base::StringPrintf("CanEnterLongIdlePeriod @ %d",
74 TimeTicksToIntMs(now)));
75 }
76 return WorkerSchedulerImpl::CanEnterLongIdlePeriod(
77 now, next_long_idle_period_delay_out);
78 }
79
80 void IsNotQuiescent() override {
81 if (timeline_) {
82 timeline_->push_back(base::StringPrintf(
83 "IsNotQuiescent @ %d", TimeTicksToIntMs(clock_->NowTicks())));
84 }
85 WorkerSchedulerImpl::IsNotQuiescent();
86 }
87
88 base::SimpleTestTickClock* clock_; // NOT OWNED
89 std::vector<std::string>* timeline_; // NOT OWNED
90 };
91
92 class WorkerSchedulerImplTest : public testing::Test {
93 public:
94 WorkerSchedulerImplTest()
95 : clock_(new base::SimpleTestTickClock()),
96 mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_.get(), true)),
97 main_task_runner_(SchedulerTqmDelegateForTest::Create(
98 mock_task_runner_,
99 base::WrapUnique(new TestTimeSource(clock_.get())))),
100 scheduler_(
101 new WorkerSchedulerImplForTest(main_task_runner_, clock_.get())),
102 timeline_(nullptr) {
103 clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
104 }
105
106 ~WorkerSchedulerImplTest() override {}
107
108 void TearDown() override {
109 // Check that all tests stop posting tasks.
110 while (mock_task_runner_->RunUntilIdle()) {
111 }
112 }
113
114 void Init() {
115 scheduler_->Init();
116 default_task_runner_ = scheduler_->DefaultTaskRunner();
117 idle_task_runner_ = scheduler_->IdleTaskRunner();
118 timeline_ = nullptr;
119 }
120
121 void RecordTimelineEvents(std::vector<std::string>* timeline) {
122 timeline_ = timeline;
123 scheduler_->RecordTimelineEvents(timeline);
124 }
125
126 void RunUntilIdle() {
127 if (timeline_) {
128 timeline_->push_back(base::StringPrintf(
129 "RunUntilIdle begin @ %d", TimeTicksToIntMs(clock_->NowTicks())));
130 }
131 mock_task_runner_->RunUntilIdle();
132 if (timeline_) {
133 timeline_->push_back(base::StringPrintf(
134 "RunUntilIdle end @ %d", TimeTicksToIntMs(clock_->NowTicks())));
135 }
136 }
137
138 // Helper for posting several tasks of specific types. |task_descriptor| is a
139 // string with space delimited task identifiers. The first letter of each
140 // task identifier specifies the task type:
141 // - 'D': Default task
142 // - 'I': Idle task
143 void PostTestTasks(std::vector<std::string>* run_order,
144 const std::string& task_descriptor) {
145 std::istringstream stream(task_descriptor);
146 while (!stream.eof()) {
147 std::string task;
148 stream >> task;
149 switch (task[0]) {
150 case 'D':
151 default_task_runner_->PostTask(
152 FROM_HERE, base::Bind(&AppendToVectorTestTask, run_order, task));
153 break;
154 case 'I':
155 idle_task_runner_->PostIdleTask(
156 FROM_HERE,
157 base::Bind(&AppendToVectorIdleTestTask, run_order, task));
158 break;
159 default:
160 NOTREACHED();
161 }
162 }
163 }
164
165 static base::TimeDelta maximum_idle_period_duration() {
166 return base::TimeDelta::FromMilliseconds(
167 IdleHelper::kMaximumIdlePeriodMillis);
168 }
169
170 protected:
171 std::unique_ptr<base::SimpleTestTickClock> clock_;
172 // Only one of mock_task_runner_ or message_loop_ will be set.
173 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
174
175 scoped_refptr<SchedulerTqmDelegate> main_task_runner_;
176 std::unique_ptr<WorkerSchedulerImplForTest> scheduler_;
177 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
178 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
179 std::vector<std::string>* timeline_; // NOT OWNED
180
181 DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerImplTest);
182 };
183
184 TEST_F(WorkerSchedulerImplTest, TestPostDefaultTask) {
185 Init();
186
187 std::vector<std::string> run_order;
188 PostTestTasks(&run_order, "D1 D2 D3 D4");
189
190 RunUntilIdle();
191 EXPECT_THAT(run_order,
192 testing::ElementsAre(std::string("D1"), std::string("D2"),
193 std::string("D3"), std::string("D4")));
194 }
195
196 TEST_F(WorkerSchedulerImplTest, TestPostIdleTask) {
197 Init();
198
199 std::vector<std::string> run_order;
200 PostTestTasks(&run_order, "I1");
201
202 RunUntilIdle();
203 EXPECT_THAT(run_order, testing::ElementsAre(std::string("I1")));
204 }
205
206 TEST_F(WorkerSchedulerImplTest, TestPostDefaultAndIdleTasks) {
207 Init();
208
209 std::vector<std::string> run_order;
210 PostTestTasks(&run_order, "I1 D2 D3 D4");
211
212 RunUntilIdle();
213 EXPECT_THAT(run_order,
214 testing::ElementsAre(std::string("D2"), std::string("D3"),
215 std::string("D4"), std::string("I1")));
216 }
217
218 TEST_F(WorkerSchedulerImplTest, TestPostDefaultDelayedAndIdleTasks) {
219 Init();
220
221 std::vector<std::string> run_order;
222 PostTestTasks(&run_order, "I1 D2 D3 D4");
223
224 default_task_runner_->PostDelayedTask(
225 FROM_HERE, base::Bind(&AppendToVectorTestTask, &run_order, "DELAYED"),
226 base::TimeDelta::FromMilliseconds(1000));
227
228 RunUntilIdle();
229 EXPECT_THAT(run_order,
230 testing::ElementsAre(std::string("D2"), std::string("D3"),
231 std::string("D4"), std::string("I1"),
232 std::string("DELAYED")));
233 }
234
235 TEST_F(WorkerSchedulerImplTest, TestIdleTaskWhenIsNotQuiescent) {
236 std::vector<std::string> timeline;
237 RecordTimelineEvents(&timeline);
238 Init();
239
240 timeline.push_back("Post default task");
241 // Post a delayed task timed to occur mid way during the long idle period.
242 default_task_runner_->PostTask(
243 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
244 base::Unretained(clock_.get())));
245 RunUntilIdle();
246
247 timeline.push_back("Post idle task");
248 idle_task_runner_->PostIdleTask(FROM_HERE,
249 base::Bind(&TimelineIdleTestTask, &timeline));
250
251 RunUntilIdle();
252
253 std::string expected_timeline[] = {"CanEnterLongIdlePeriod @ 5",
254 "Post default task",
255 "run RecordTimelineTask @ 5",
256 "Post idle task",
257 "IsNotQuiescent @ 5",
258 "CanEnterLongIdlePeriod @ 305",
259 "run TimelineIdleTestTask deadline 355"};
260
261 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
262 }
263
264 TEST_F(WorkerSchedulerImplTest, TestIdleDeadlineWithPendingDelayedTask) {
265 std::vector<std::string> timeline;
266 RecordTimelineEvents(&timeline);
267 Init();
268
269 timeline.push_back("Post delayed and idle tasks");
270 // Post a delayed task timed to occur mid way during the long idle period.
271 default_task_runner_->PostDelayedTask(
272 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
273 base::Unretained(clock_.get())),
274 base::TimeDelta::FromMilliseconds(20));
275 idle_task_runner_->PostIdleTask(FROM_HERE,
276 base::Bind(&TimelineIdleTestTask, &timeline));
277
278 RunUntilIdle();
279
280 std::string expected_timeline[] = {
281 "CanEnterLongIdlePeriod @ 5",
282 "Post delayed and idle tasks",
283 "CanEnterLongIdlePeriod @ 5",
284 "run TimelineIdleTestTask deadline 25", // Note the short 20ms deadline.
285 "run RecordTimelineTask @ 25"};
286
287 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
288 }
289
290 TEST_F(WorkerSchedulerImplTest,
291 TestIdleDeadlineWithPendingDelayedTaskFarInTheFuture) {
292 std::vector<std::string> timeline;
293 RecordTimelineEvents(&timeline);
294 Init();
295
296 timeline.push_back("Post delayed and idle tasks");
297 // Post a delayed task timed to occur well after the long idle period.
298 default_task_runner_->PostDelayedTask(
299 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
300 base::Unretained(clock_.get())),
301 base::TimeDelta::FromMilliseconds(500));
302 idle_task_runner_->PostIdleTask(FROM_HERE,
303 base::Bind(&TimelineIdleTestTask, &timeline));
304
305 RunUntilIdle();
306
307 std::string expected_timeline[] = {
308 "CanEnterLongIdlePeriod @ 5",
309 "Post delayed and idle tasks",
310 "CanEnterLongIdlePeriod @ 5",
311 "run TimelineIdleTestTask deadline 55", // Note the full 50ms deadline.
312 "run RecordTimelineTask @ 505"};
313
314 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
315 }
316
317 TEST_F(WorkerSchedulerImplTest, TestPostIdleTaskAfterRunningUntilIdle) {
318 Init();
319
320 default_task_runner_->PostDelayedTask(
321 FROM_HERE, base::Bind(&NopTask), base::TimeDelta::FromMilliseconds(1000));
322 RunUntilIdle();
323
324 std::vector<std::string> run_order;
325 PostTestTasks(&run_order, "I1 I2 D3");
326
327 RunUntilIdle();
328 EXPECT_THAT(run_order,
329 testing::ElementsAre(std::string("D3"), std::string("I1"),
330 std::string("I2")));
331 }
332
333 TEST_F(WorkerSchedulerImplTest, TestLongIdlePeriodTimeline) {
334 Init();
335
336 std::vector<std::string> timeline;
337 RecordTimelineEvents(&timeline);
338
339 // The scheduler should not run the initiate_next_long_idle_period task if
340 // there are no idle tasks and no other task woke up the scheduler, thus
341 // the idle period deadline shouldn't update at the end of the current long
342 // idle period.
343 base::TimeTicks idle_period_deadline =
344 scheduler_->CurrentIdleTaskDeadlineForTesting();
345 clock_->Advance(maximum_idle_period_duration());
346 RunUntilIdle();
347
348 base::TimeTicks new_idle_period_deadline =
349 scheduler_->CurrentIdleTaskDeadlineForTesting();
350 EXPECT_EQ(idle_period_deadline, new_idle_period_deadline);
351
352 // Posting a after-wakeup idle task also shouldn't wake the scheduler or
353 // initiate the next long idle period.
354 timeline.push_back("PostIdleTaskAfterWakeup");
355 idle_task_runner_->PostIdleTaskAfterWakeup(
356 FROM_HERE, base::Bind(&TimelineIdleTestTask, &timeline));
357 RunUntilIdle();
358 new_idle_period_deadline = scheduler_->CurrentIdleTaskDeadlineForTesting();
359
360 // Running a normal task should initiate a new long idle period after waiting
361 // 300ms for quiescence.
362 timeline.push_back("Post RecordTimelineTask");
363 default_task_runner_->PostTask(
364 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
365 base::Unretained(clock_.get())));
366 RunUntilIdle();
367
368 std::string expected_timeline[] = {
369 "RunUntilIdle begin @ 55",
370 "RunUntilIdle end @ 55",
371 "PostIdleTaskAfterWakeup",
372 "RunUntilIdle begin @ 55", // NOTE idle task doesn't run till later.
373 "RunUntilIdle end @ 55",
374 "Post RecordTimelineTask",
375 "RunUntilIdle begin @ 55",
376 "run RecordTimelineTask @ 55",
377 "IsNotQuiescent @ 55", // NOTE we have to wait for quiescence.
378 "CanEnterLongIdlePeriod @ 355",
379 "run TimelineIdleTestTask deadline 405",
380 "RunUntilIdle end @ 355"};
381
382 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
383 }
384
385 } // namespace scheduler
OLDNEW
« no previous file with comments | « components/scheduler/child/worker_scheduler_impl.cc ('k') | components/scheduler/common/scheduler_switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698