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.
6 #include "platform/scheduler/Scheduler.h"
8 #include "platform/TestingPlatformSupport.h"
9 #include "platform/TraceLocation.h"
10 #include "public/platform/Platform.h"
11 #include "public/platform/WebThread.h"
13 #include <gmock/gmock.h>
14 #include <gtest/gtest.h>
18 using blink::Scheduler;
23 class TestMainThread : public blink::WebThread {
25 // blink::WebThread implementation.
26 virtual void postTask(Task* task) OVERRIDE
28 m_pendingTasks.append(adoptPtr(task));
31 virtual void postDelayedTask(Task* task, long long delayMs) OVERRIDE
36 virtual bool isCurrentThread() const OVERRIDE
41 virtual void enterRunLoop() OVERRIDE
46 virtual void exitRunLoop() OVERRIDE
51 void runPendingTasks()
53 while (!m_pendingTasks.isEmpty())
54 m_pendingTasks.takeFirst()->run();
58 WTF::Deque<OwnPtr<Task> > m_pendingTasks;
61 class SchedulerTestingPlatformSupport : blink::TestingPlatformSupport {
63 SchedulerTestingPlatformSupport()
64 : TestingPlatformSupport(TestingPlatformSupport::Config())
65 , m_sharedTimerFunction(nullptr)
66 , m_sharedTimerRunning(false)
67 , m_sharedTimerFireInterval(0)
71 // blink::Platform implementation.
72 virtual blink::WebThread* currentThread() OVERRIDE
77 virtual void setSharedTimerFiredFunction(SharedTimerFunction timerFunction) OVERRIDE
79 m_sharedTimerFunction = timerFunction;
82 virtual void setSharedTimerFireInterval(double)
84 m_sharedTimerFireInterval = 0;
85 m_sharedTimerRunning = true;
88 virtual void stopSharedTimer()
90 m_sharedTimerRunning = false;
93 void runPendingTasks()
95 m_mainThread.runPendingTasks();
98 bool sharedTimerRunning() const
100 return m_sharedTimerRunning;
103 double sharedTimerFireInterval() const
105 return m_sharedTimerFireInterval;
108 void triggerSharedTimer()
110 m_sharedTimerFunction();
114 TestMainThread m_mainThread;
115 SharedTimerFunction m_sharedTimerFunction;
116 bool m_sharedTimerRunning;
117 double m_sharedTimerFireInterval;
120 class SchedulerTest : public testing::Test {
123 : m_reentrantCount(0)
126 Scheduler::initializeOnMainThread();
127 m_scheduler = Scheduler::shared();
132 Scheduler::shutdown();
135 void runPendingTasks()
137 m_platformSupport.runPendingTasks();
140 void appendToVector(string value)
142 m_order.push_back(value);
145 void appendToVectorReentrantTask()
147 m_reentrantOrder.push_back(m_reentrantCount++);
149 if (m_reentrantCount > m_maxRecursion)
151 Scheduler::shared()->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantTask, this));
154 void appendToVectorReentrantInputTask()
156 m_reentrantOrder.push_back(m_reentrantCount++);
158 if (m_reentrantCount > m_maxRecursion)
160 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantInputTask, this));
163 void appendToVectorReentrantCompositorTask()
165 m_reentrantOrder.push_back(m_reentrantCount++);
167 if (m_reentrantCount > m_maxRecursion)
169 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantCompositorTask, this));
173 SchedulerTestingPlatformSupport m_platformSupport;
174 Scheduler* m_scheduler;
175 std::vector<string> m_order;
176 std::vector<int> m_reentrantOrder;
177 int m_reentrantCount;
181 void orderedTestTask(int value, int* result)
183 *result = (*result << 4) | value;
186 void unorderedTestTask(int value, int* result)
191 void idleTestTask(int value, int* result, double allottedTime)
196 TEST_F(SchedulerTest, TestPostTask)
199 m_scheduler->postTask(FROM_HERE, WTF::bind(&orderedTestTask, 1, &result));
200 m_scheduler->postTask(FROM_HERE, WTF::bind(&orderedTestTask, 2, &result));
201 m_scheduler->postTask(FROM_HERE, WTF::bind(&orderedTestTask, 3, &result));
202 m_scheduler->postTask(FROM_HERE, WTF::bind(&orderedTestTask, 4, &result));
204 EXPECT_EQ(0x1234, result);
207 TEST_F(SchedulerTest, TestPostMixedTaskTypes)
210 m_scheduler->postTask(FROM_HERE, WTF::bind(&unorderedTestTask, 1, &result));
211 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&unorderedTestTask, 2, &result));
212 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&unorderedTestTask, 4, &result));
213 m_scheduler->postTask(FROM_HERE, WTF::bind(&unorderedTestTask, 8, &result));
215 EXPECT_EQ(15, result);
218 int s_sharedTimerTickCount;
219 void sharedTimerFunction()
221 s_sharedTimerTickCount++;
224 TEST_F(SchedulerTest, TestSharedTimer)
226 s_sharedTimerTickCount = 0;
227 m_scheduler->setSharedTimerFiredFunction(&sharedTimerFunction);
228 EXPECT_FALSE(m_platformSupport.sharedTimerRunning());
229 m_scheduler->setSharedTimerFireInterval(0);
230 EXPECT_TRUE(m_platformSupport.sharedTimerRunning());
232 m_platformSupport.triggerSharedTimer();
233 EXPECT_EQ(1, s_sharedTimerTickCount);
235 m_scheduler->stopSharedTimer();
236 EXPECT_FALSE(m_platformSupport.sharedTimerRunning());
238 m_scheduler->setSharedTimerFiredFunction(nullptr);
239 EXPECT_FALSE(m_platformSupport.sharedTimerRunning());
242 TEST_F(SchedulerTest, TestIdleTask)
244 // TODO: Check task allottedTime when implemented in the scheduler.
246 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &result));
247 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &result));
248 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &result));
249 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &result));
251 EXPECT_EQ(4, result);
254 TEST_F(SchedulerTest, TestTaskPrioritization)
256 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, string("L1")));
257 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, string("L2")));
258 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, string("I1")));
259 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, string("I2")));
260 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, string("C1")));
261 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, string("C2")));
264 EXPECT_THAT(m_order, testing::ElementsAre(
265 string("I1"), string("I2"), string("C1"), string("C2"), string("L1"), string("L2")));
268 TEST_F(SchedulerTest, TestRentrantTask)
270 m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantTask, this));
273 EXPECT_THAT(m_reentrantOrder, testing::ElementsAre(0, 1, 2, 3, 4));
277 TEST_F(SchedulerTest, TestRentrantInputTaskDuringShutdown)
279 m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantInputTask, this));
280 Scheduler::shutdown();
282 EXPECT_THAT(m_reentrantOrder, testing::ElementsAre(0, 1, 2, 3, 4));
285 TEST_F(SchedulerTest, TestRentrantCompositorTaskDuringShutdown)
287 m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantCompositorTask, this));
288 Scheduler::shutdown();
290 EXPECT_THAT(m_reentrantOrder, testing::ElementsAre(0, 1, 2, 3, 4));