OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "platform/scheduler/Scheduler.h" | 6 #include "platform/scheduler/Scheduler.h" |
7 | 7 |
8 #include "platform/TestingPlatformSupport.h" | 8 #include "platform/TestingPlatformSupport.h" |
9 #include "platform/TraceLocation.h" | 9 #include "platform/TraceLocation.h" |
10 #include "public/platform/Platform.h" | 10 #include "public/platform/Platform.h" |
11 #include "public/platform/WebThread.h" | 11 #include "public/platform/WebThread.h" |
12 | 12 |
13 #include <gmock/gmock.h> | 13 #include <gmock/gmock.h> |
14 #include <gtest/gtest.h> | 14 #include <gtest/gtest.h> |
15 #include <string> | 15 #include <string> |
16 #include <vector> | 16 #include <vector> |
17 | 17 |
18 using blink::Scheduler; | 18 using blink::Scheduler; |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
| 22 class SchedulerForTest : public blink::Scheduler { |
| 23 public: |
| 24 static void initializeOnMainThread() |
| 25 { |
| 26 s_sharedScheduler = new SchedulerForTest(); |
| 27 } |
| 28 |
| 29 using Scheduler::Normal; |
| 30 using Scheduler::CompositorPriority; |
| 31 using Scheduler::enterSchedulerPolicy; |
| 32 }; |
| 33 |
22 class TestMainThread : public blink::WebThread { | 34 class TestMainThread : public blink::WebThread { |
23 public: | 35 public: |
24 // blink::WebThread implementation. | 36 // blink::WebThread implementation. |
25 virtual void postTask(Task* task) OVERRIDE | 37 virtual void postTask(Task* task) OVERRIDE |
26 { | 38 { |
27 m_pendingTasks.append(adoptPtr(task)); | 39 m_pendingTasks.append(adoptPtr(task)); |
28 } | 40 } |
29 | 41 |
30 virtual void postDelayedTask(Task* task, long long delayMs) OVERRIDE | 42 virtual void postDelayedTask(Task* task, long long delayMs) OVERRIDE |
31 { | 43 { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 WTF::Deque<OwnPtr<Task> > m_pendingTasks; | 80 WTF::Deque<OwnPtr<Task> > m_pendingTasks; |
69 }; | 81 }; |
70 | 82 |
71 class SchedulerTestingPlatformSupport : blink::TestingPlatformSupport { | 83 class SchedulerTestingPlatformSupport : blink::TestingPlatformSupport { |
72 public: | 84 public: |
73 SchedulerTestingPlatformSupport() | 85 SchedulerTestingPlatformSupport() |
74 : TestingPlatformSupport(TestingPlatformSupport::Config()) | 86 : TestingPlatformSupport(TestingPlatformSupport::Config()) |
75 , m_sharedTimerFunction(nullptr) | 87 , m_sharedTimerFunction(nullptr) |
76 , m_sharedTimerRunning(false) | 88 , m_sharedTimerRunning(false) |
77 , m_sharedTimerFireInterval(0) | 89 , m_sharedTimerFireInterval(0) |
| 90 , m_monotonicallyIncreasingTime(0) |
78 { | 91 { |
79 } | 92 } |
80 | 93 |
81 // blink::Platform implementation. | 94 // blink::Platform implementation. |
82 virtual blink::WebThread* currentThread() OVERRIDE | 95 virtual blink::WebThread* currentThread() OVERRIDE |
83 { | 96 { |
84 return &m_mainThread; | 97 return &m_mainThread; |
85 } | 98 } |
86 | 99 |
87 virtual void setSharedTimerFiredFunction(SharedTimerFunction timerFunction)
OVERRIDE | 100 virtual void setSharedTimerFiredFunction(SharedTimerFunction timerFunction)
OVERRIDE |
88 { | 101 { |
89 m_sharedTimerFunction = timerFunction; | 102 m_sharedTimerFunction = timerFunction; |
90 } | 103 } |
91 | 104 |
| 105 virtual double monotonicallyIncreasingTime() OVERRIDE |
| 106 { |
| 107 return m_monotonicallyIncreasingTime; |
| 108 } |
| 109 |
92 virtual void setSharedTimerFireInterval(double) | 110 virtual void setSharedTimerFireInterval(double) |
93 { | 111 { |
94 m_sharedTimerFireInterval = 0; | 112 m_sharedTimerFireInterval = 0; |
95 m_sharedTimerRunning = true; | 113 m_sharedTimerRunning = true; |
96 } | 114 } |
97 | 115 |
98 virtual void stopSharedTimer() | 116 virtual void stopSharedTimer() |
99 { | 117 { |
100 m_sharedTimerRunning = false; | 118 m_sharedTimerRunning = false; |
101 } | 119 } |
(...skipping 16 matching lines...) Expand all Loading... |
118 void triggerSharedTimer() | 136 void triggerSharedTimer() |
119 { | 137 { |
120 m_sharedTimerFunction(); | 138 m_sharedTimerFunction(); |
121 } | 139 } |
122 | 140 |
123 size_t numPendingMainThreadTasks() const | 141 size_t numPendingMainThreadTasks() const |
124 { | 142 { |
125 return m_mainThread.numPendingMainThreadTasks(); | 143 return m_mainThread.numPendingMainThreadTasks(); |
126 } | 144 } |
127 | 145 |
| 146 void setMonotonicTimeForTest(double time) |
| 147 { |
| 148 m_monotonicallyIncreasingTime = time; |
| 149 } |
| 150 |
128 private: | 151 private: |
129 TestMainThread m_mainThread; | 152 TestMainThread m_mainThread; |
130 SharedTimerFunction m_sharedTimerFunction; | 153 SharedTimerFunction m_sharedTimerFunction; |
131 bool m_sharedTimerRunning; | 154 bool m_sharedTimerRunning; |
132 double m_sharedTimerFireInterval; | 155 double m_sharedTimerFireInterval; |
| 156 double m_monotonicallyIncreasingTime; |
133 }; | 157 }; |
134 | 158 |
135 class SchedulerTest : public testing::Test { | 159 class SchedulerTest : public testing::Test { |
136 public: | 160 public: |
137 SchedulerTest() | 161 SchedulerTest() |
138 : m_reentrantCount(0) | 162 : m_reentrantCount(0) |
139 , m_maxRecursion(4) | 163 , m_maxRecursion(4) |
140 { | 164 { |
141 Scheduler::initializeOnMainThread(); | 165 SchedulerForTest::initializeOnMainThread(); |
142 m_scheduler = Scheduler::shared(); | 166 m_scheduler = static_cast<SchedulerForTest*>(Scheduler::shared()); |
143 } | 167 } |
144 | 168 |
145 ~SchedulerTest() | 169 ~SchedulerTest() |
146 { | 170 { |
147 Scheduler::shutdown(); | 171 Scheduler::shutdown(); |
148 } | 172 } |
149 | 173 |
| 174 virtual void SetUp() OVERRIDE |
| 175 { |
| 176 m_scheduler->enterSchedulerPolicy(SchedulerForTest::Normal); |
| 177 } |
| 178 |
150 void runPendingTasks() | 179 void runPendingTasks() |
151 { | 180 { |
152 m_platformSupport.runPendingTasks(); | 181 m_platformSupport.runPendingTasks(); |
153 } | 182 } |
154 | 183 |
155 void appendToVector(std::string value) | 184 void appendToVector(std::string value) |
156 { | 185 { |
157 m_order.push_back(value); | 186 m_order.push_back(value); |
158 } | 187 } |
159 | 188 |
(...skipping 19 matching lines...) Expand all Loading... |
179 { | 208 { |
180 m_reentrantOrder.push_back(m_reentrantCount++); | 209 m_reentrantOrder.push_back(m_reentrantCount++); |
181 | 210 |
182 if (m_reentrantCount > m_maxRecursion) | 211 if (m_reentrantCount > m_maxRecursion) |
183 return; | 212 return; |
184 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::app
endToVectorReentrantCompositorTask, this)); | 213 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::app
endToVectorReentrantCompositorTask, this)); |
185 } | 214 } |
186 | 215 |
187 protected: | 216 protected: |
188 SchedulerTestingPlatformSupport m_platformSupport; | 217 SchedulerTestingPlatformSupport m_platformSupport; |
189 Scheduler* m_scheduler; | 218 SchedulerForTest* m_scheduler; |
190 std::vector<std::string> m_order; | 219 std::vector<std::string> m_order; |
191 std::vector<int> m_reentrantOrder; | 220 std::vector<int> m_reentrantOrder; |
192 int m_reentrantCount; | 221 int m_reentrantCount; |
193 int m_maxRecursion; | 222 int m_maxRecursion; |
194 }; | 223 }; |
195 | 224 |
196 void orderedTestTask(int value, int* result) | 225 void orderedTestTask(int value, int* result) |
197 { | 226 { |
198 *result = (*result << 4) | value; | 227 *result = (*result << 4) | value; |
199 } | 228 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 // TODO: Check task allottedTime when implemented in the scheduler. | 288 // TODO: Check task allottedTime when implemented in the scheduler. |
260 int result = 0; | 289 int result = 0; |
261 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &re
sult)); | 290 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &re
sult)); |
262 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &re
sult)); | 291 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &re
sult)); |
263 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &re
sult)); | 292 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &re
sult)); |
264 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &re
sult)); | 293 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &re
sult)); |
265 runPendingTasks(); | 294 runPendingTasks(); |
266 EXPECT_EQ(4, result); | 295 EXPECT_EQ(4, result); |
267 } | 296 } |
268 | 297 |
269 TEST_F(SchedulerTest, TestTaskPrioritization) | 298 TEST_F(SchedulerTest, TestTaskPrioritization_normalPolicy) |
270 { | 299 { |
271 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, t
his, std::string("L1"))); | 300 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, t
his, std::string("L1"))); |
272 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, t
his, std::string("L2"))); | 301 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, t
his, std::string("L2"))); |
273 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVect
or, this, std::string("I1"))); | 302 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVect
or, this, std::string("I1"))); |
274 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendT
oVector, this, std::string("C1"))); | 303 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendT
oVector, this, std::string("C1"))); |
275 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVect
or, this, std::string("I2"))); | 304 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVect
or, this, std::string("I2"))); |
276 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendT
oVector, this, std::string("C2"))); | 305 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendT
oVector, this, std::string("C2"))); |
277 | 306 |
278 runPendingTasks(); | 307 runPendingTasks(); |
279 EXPECT_THAT(m_order, testing::ElementsAre( | 308 EXPECT_THAT(m_order, testing::ElementsAre( |
| 309 std::string("L1"), std::string("L2"), std::string("I1"), std::string("C1
"), std::string("I2"), std::string("C2"))); |
| 310 } |
| 311 |
| 312 TEST_F(SchedulerTest, TestTaskPrioritization_compositorPriorityPolicy) |
| 313 { |
| 314 m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority); |
| 315 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, t
his, std::string("L1"))); |
| 316 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, t
his, std::string("L2"))); |
| 317 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVect
or, this, std::string("I1"))); |
| 318 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendT
oVector, this, std::string("C1"))); |
| 319 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVect
or, this, std::string("I2"))); |
| 320 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendT
oVector, this, std::string("C2"))); |
| 321 |
| 322 runPendingTasks(); |
| 323 EXPECT_THAT(m_order, testing::ElementsAre( |
280 std::string("I1"), std::string("C1"), std::string("I2"), std::string("C2
"), std::string("L1"), std::string("L2"))); | 324 std::string("I1"), std::string("C1"), std::string("I2"), std::string("C2
"), std::string("L1"), std::string("L2"))); |
281 } | 325 } |
282 | 326 |
283 TEST_F(SchedulerTest, TestRentrantTask) | 327 TEST_F(SchedulerTest, TestRentrantTask) |
284 { | 328 { |
285 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorRee
ntrantTask, this)); | 329 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorRee
ntrantTask, this)); |
286 runPendingTasks(); | 330 runPendingTasks(); |
287 | 331 |
288 EXPECT_THAT(m_reentrantOrder, testing::ElementsAre(0, 1, 2, 3, 4)); | 332 EXPECT_THAT(m_reentrantOrder, testing::ElementsAre(0, 1, 2, 3, 4)); |
289 } | 333 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 | 420 |
377 runPendingTasks(); | 421 runPendingTasks(); |
378 EXPECT_EQ(0U, m_platformSupport.numPendingMainThreadTasks()); | 422 EXPECT_EQ(0U, m_platformSupport.numPendingMainThreadTasks()); |
379 } | 423 } |
380 | 424 |
381 void postDummyInputTask() | 425 void postDummyInputTask() |
382 { | 426 { |
383 Scheduler::shared()->postInputTask(FROM_HERE, WTF::bind(&dummyTask)); | 427 Scheduler::shared()->postInputTask(FROM_HERE, WTF::bind(&dummyTask)); |
384 } | 428 } |
385 | 429 |
386 TEST_F(SchedulerTest, HighPriorityTasksOnlyRunOncePerSharedTimerFiring) | 430 TEST_F(SchedulerTest, HighPriorityTasksOnlyDontRunBecauseOfSharedTimerFiring_InN
ormalMode) |
387 { | 431 { |
388 s_dummyTaskCount = 0; | 432 s_dummyTaskCount = 0; |
389 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask)); | 433 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask)); |
390 // Trigger the posting of an input task during execution of the shared timer
function. | 434 // Trigger the posting of an input task during execution of the shared timer
function. |
391 m_scheduler->setSharedTimerFiredFunction(&postDummyInputTask); | 435 m_scheduler->setSharedTimerFiredFunction(&postDummyInputTask); |
| 436 m_scheduler->setSharedTimerFireInterval(0); |
| 437 m_platformSupport.triggerSharedTimer(); |
| 438 |
| 439 EXPECT_EQ(0, s_dummyTaskCount); |
| 440 |
| 441 // Clean up. |
| 442 m_scheduler->stopSharedTimer(); |
| 443 m_scheduler->setSharedTimerFiredFunction(nullptr); |
| 444 } |
| 445 |
| 446 TEST_F(SchedulerTest, HighPriorityTasksOnlyRunOncePerSharedTimerFiring_InLowSche
dulerPolicy) |
| 447 { |
| 448 s_dummyTaskCount = 0; |
| 449 m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority); |
| 450 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask)); |
| 451 // Trigger the posting of an input task during execution of the shared timer
function. |
| 452 m_scheduler->setSharedTimerFiredFunction(&postDummyInputTask); |
392 m_scheduler->setSharedTimerFireInterval(0); | 453 m_scheduler->setSharedTimerFireInterval(0); |
393 m_platformSupport.triggerSharedTimer(); | 454 m_platformSupport.triggerSharedTimer(); |
394 | 455 |
395 EXPECT_EQ(1, s_dummyTaskCount); | 456 EXPECT_EQ(1, s_dummyTaskCount); |
396 | 457 |
397 // Clean up. | 458 // Clean up. |
398 m_scheduler->stopSharedTimer(); | 459 m_scheduler->stopSharedTimer(); |
399 m_scheduler->setSharedTimerFiredFunction(nullptr); | 460 m_scheduler->setSharedTimerFiredFunction(nullptr); |
400 } | 461 } |
401 | 462 |
| 463 TEST_F(SchedulerTest, TestInputEventDoesNotTriggerShouldYield_InNormalMode) |
| 464 { |
| 465 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask)); |
| 466 |
| 467 EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork()); |
| 468 } |
| 469 |
| 470 TEST_F(SchedulerTest, TestCompositorEventDoesNotTriggerShouldYield_InNormalMode) |
| 471 { |
| 472 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask)); |
| 473 |
| 474 EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork()); |
| 475 } |
| 476 |
| 477 TEST_F(SchedulerTest, TestInputEventDoesTriggerShouldYield_InLowSchedulerPolicy) |
| 478 { |
| 479 m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority); |
| 480 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask)); |
| 481 |
| 482 EXPECT_TRUE(m_scheduler->shouldYieldForHighPriorityWork()); |
| 483 } |
| 484 |
| 485 TEST_F(SchedulerTest, TestCompositorEventDoesTriggerShouldYield_InLowSchedulerPo
licy) |
| 486 { |
| 487 m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority); |
| 488 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask)); |
| 489 |
| 490 EXPECT_TRUE(m_scheduler->shouldYieldForHighPriorityWork()); |
| 491 } |
| 492 |
| 493 TEST_F(SchedulerTest, TestCompositorEvent_LowSchedulerPolicyDoesntLastLong) |
| 494 { |
| 495 m_platformSupport.setMonotonicTimeForTest(1000.0); |
| 496 |
| 497 m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority); |
| 498 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask)); |
| 499 m_platformSupport.setMonotonicTimeForTest(1000.5); |
| 500 runPendingTasks(); |
| 501 |
| 502 ASSERT_FALSE(m_scheduler->shouldYieldForHighPriorityWork()); |
| 503 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask)); |
| 504 |
| 505 EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork()); |
| 506 } |
| 507 |
402 } // namespace | 508 } // namespace |
OLD | NEW |