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

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

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

Powered by Google App Engine
This is Rietveld 408576698