Index: Source/platform/scheduler/SchedulerTest.cpp |
diff --git a/Source/platform/scheduler/SchedulerTest.cpp b/Source/platform/scheduler/SchedulerTest.cpp |
index 557e0386c2b070ffab155b9a6b0ebbdb7b79e976..95057dc6cbf6ed72040226d449f805de6982d353 100644 |
--- a/Source/platform/scheduler/SchedulerTest.cpp |
+++ b/Source/platform/scheduler/SchedulerTest.cpp |
@@ -8,13 +8,17 @@ |
#include "platform/TestingPlatformSupport.h" |
#include "platform/TraceLocation.h" |
#include "public/platform/Platform.h" |
+#include "public/platform/WebBeginFrameArgs.h" |
#include "public/platform/WebThread.h" |
+#include "wtf/CurrentTime.h" |
#include <gmock/gmock.h> |
#include <gtest/gtest.h> |
+#include <queue> |
#include <string> |
#include <vector> |
+using blink::Platform; |
using blink::Scheduler; |
namespace { |
@@ -29,7 +33,8 @@ public: |
virtual void postDelayedTask(Task* task, long long delayMs) OVERRIDE |
{ |
- ASSERT_NOT_REACHED(); |
+ long long deadline = static_cast<long long>(Platform::current()->monotonicallyIncreasingTime() * 1000.0) + delayMs; |
+ m_pendingDelayedTasks.push(DelayedTask(deadline, adoptPtr(task))); |
} |
virtual bool isCurrentThread() const OVERRIDE |
@@ -51,6 +56,12 @@ public: |
{ |
while (!m_pendingTasks.isEmpty()) |
m_pendingTasks.takeFirst()->run(); |
+ |
+ long long timeMs = static_cast<long long>(Platform::current()->monotonicallyIncreasingTime() * 1000.0); |
+ while (!m_pendingDelayedTasks.empty() && m_pendingDelayedTasks.top().m_deadline <= timeMs) { |
+ m_pendingDelayedTasks.top().run(); |
+ m_pendingDelayedTasks.pop(); |
+ } |
} |
size_t numPendingMainThreadTasks() const |
@@ -58,8 +69,43 @@ public: |
return m_pendingTasks.size(); |
} |
+ double nextDelayedTaskDeadlineOrMinusOne() const |
+ { |
+ if (m_pendingDelayedTasks.empty()) |
+ return -1; |
+ |
+ return static_cast<double>(m_pendingDelayedTasks.top().m_deadline) * 0.001; |
+ } |
+ |
private: |
+ class DelayedTask { |
+ public: |
+ DelayedTask(long long deadline, PassOwnPtr<WebThread::Task> task) |
+ : m_deadline(deadline) |
+ , m_task(task.leakPtr()) |
+ { |
+ } |
+ |
+ void run() const |
+ { |
+ m_task->run(); |
+ delete m_task; |
+ } |
+ |
+ bool operator<(const DelayedTask& other) const |
+ { |
+ return m_deadline > other.m_deadline; |
+ } |
+ |
+ long long m_deadline; |
+ |
+ // NOTE we can't use OwnPtr<> here because the std::priority_queue uses the copy constructor |
+ // and c++11 style move semantics are not allowed yet. |
+ WebThread::Task* m_task; |
+ }; |
+ |
WTF::Deque<OwnPtr<Task> > m_pendingTasks; |
+ std::priority_queue<DelayedTask> m_pendingDelayedTasks; |
}; |
class SchedulerTestingPlatformSupport : blink::TestingPlatformSupport { |
@@ -70,6 +116,12 @@ public: |
, m_sharedTimerRunning(false) |
, m_sharedTimerFireInterval(0) |
{ |
+ WTF::setMonotonicallyIncreasingTimeFunction(getDebugTime); |
+ } |
+ |
+ virtual ~SchedulerTestingPlatformSupport() |
+ { |
+ WTF::setMonotonicallyIncreasingTimeFunction(0); |
} |
// blink::Platform implementation. |
@@ -83,6 +135,11 @@ public: |
m_sharedTimerFunction = timerFunction; |
} |
+ virtual double monotonicallyIncreasingTime() OVERRIDE |
+ { |
+ return s_debugTime; |
+ } |
+ |
virtual void setSharedTimerFireInterval(double) |
{ |
m_sharedTimerFireInterval = 0; |
@@ -119,13 +176,31 @@ public: |
return m_mainThread.numPendingMainThreadTasks(); |
} |
+ double nextDelayedTaskDeadlineOrMinusOne() const |
+ { |
+ return m_mainThread.nextDelayedTaskDeadlineOrMinusOne(); |
+ } |
+ |
+ static void setDebugTime(double time) |
+ { |
+ s_debugTime = time; |
+ } |
+ |
private: |
+ static double getDebugTime(void) |
+ { |
+ return s_debugTime; |
+ } |
TestMainThread m_mainThread; |
SharedTimerFunction m_sharedTimerFunction; |
bool m_sharedTimerRunning; |
double m_sharedTimerFireInterval; |
+ |
+ static double s_debugTime; |
}; |
+double SchedulerTestingPlatformSupport::s_debugTime = 0; |
+ |
class SchedulerTest : public testing::Test { |
public: |
SchedulerTest() |
@@ -215,13 +290,16 @@ TEST_F(SchedulerTest, TestPostTask) |
TEST_F(SchedulerTest, TestPostMixedTaskTypes) |
{ |
+ SchedulerTestingPlatformSupport::setDebugTime(1000.0); |
int result = 0; |
m_scheduler->postTask(FROM_HERE, WTF::bind(&unorderedTestTask, 1, &result)); |
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&unorderedTestTask, 2, &result)); |
m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&unorderedTestTask, 4, &result)); |
m_scheduler->postTask(FROM_HERE, WTF::bind(&unorderedTestTask, 8, &result)); |
+ m_scheduler->postIpcTask(FROM_HERE, WTF::bind(&unorderedTestTask, 16, &result)); |
+ SchedulerTestingPlatformSupport::setDebugTime(1001.0); |
runPendingTasks(); |
- EXPECT_EQ(15, result); |
+ EXPECT_EQ(31, result); |
} |
int s_sharedTimerTickCount; |
@@ -262,16 +340,21 @@ TEST_F(SchedulerTest, TestIdleTask) |
TEST_F(SchedulerTest, TestTaskPrioritization) |
{ |
+ SchedulerTestingPlatformSupport::setDebugTime(1000.0); |
+ m_scheduler->postIpcTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("IPC1"))); |
+ m_scheduler->postIpcTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("IPC2"))); |
m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("L1"))); |
m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("L2"))); |
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("I1"))); |
m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("C1"))); |
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("I2"))); |
m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("C2"))); |
+ SchedulerTestingPlatformSupport::setDebugTime(1001.0); |
runPendingTasks(); |
EXPECT_THAT(m_order, testing::ElementsAre( |
- std::string("I1"), std::string("C1"), std::string("I2"), std::string("C2"), std::string("L1"), std::string("L2"))); |
+ std::string("I1"), std::string("C1"), std::string("I2"), std::string("C2"), std::string("L1"), std::string("L2"), |
+ std::string("IPC1"), std::string("IPC2"))); |
} |
TEST_F(SchedulerTest, TestRentrantTask) |
@@ -393,4 +476,49 @@ TEST_F(SchedulerTest, HighPriorityTasksOnlyRunOncePerSharedTimerFiring) |
m_scheduler->setSharedTimerFiredFunction(nullptr); |
} |
+TEST_F(SchedulerTest, TestNextPredictedCompositorStart_initialState) |
+{ |
+ SchedulerTestingPlatformSupport::setDebugTime(1000.0); |
+ EXPECT_EQ(0, m_scheduler->nextPredictedCompositorStart()); |
+} |
+ |
+TEST_F(SchedulerTest, TestNextPredictedCompositorDeadline_initialState) |
+{ |
+ SchedulerTestingPlatformSupport::setDebugTime(1000.0); |
+ EXPECT_EQ(0, m_scheduler->nextPredictedCompositorDeadline()); |
+} |
+ |
+TEST_F(SchedulerTest, TestNextPredictedCompositorStart_afterWillBeginFrame) |
+{ |
+ m_scheduler->willBeginFrame(blink::WebBeginFrameArgs(999.8, 999.9, 0.2)); |
+ |
+ // NOTE nextPredictedCompositorStart attempts to return a time in the future. |
+ SchedulerTestingPlatformSupport::setDebugTime(999.999); |
+ EXPECT_DOUBLE_EQ(1000.0, m_scheduler->nextPredictedCompositorStart()); |
+ |
+ SchedulerTestingPlatformSupport::setDebugTime(1000.0); |
+ EXPECT_DOUBLE_EQ(1000.2, m_scheduler->nextPredictedCompositorStart()); |
+} |
+ |
+TEST_F(SchedulerTest, TestNextPredictedCompositorDeadline_afterWillBeginFrame) |
+{ |
+ m_scheduler->willBeginFrame(blink::WebBeginFrameArgs(999.8, 999.9, 0.2)); |
+ |
+ // NOTE nextPredictedCompositorStart attempts to return a time in the future. |
+ SchedulerTestingPlatformSupport::setDebugTime(1000.0); |
+ EXPECT_DOUBLE_EQ(1000.1, m_scheduler->nextPredictedCompositorDeadline()); |
+ |
+ SchedulerTestingPlatformSupport::setDebugTime(1000.2); |
+ EXPECT_DOUBLE_EQ(1000.3, m_scheduler->nextPredictedCompositorDeadline()); |
+} |
+ |
+TEST_F(SchedulerTest, TestLowPriorityTasksPostedAtNextComposiorDeadline) |
+{ |
+ m_scheduler->willBeginFrame(blink::WebBeginFrameArgs(999.8, 999.9, 0.2)); |
+ SchedulerTestingPlatformSupport::setDebugTime(1000.0); |
+ |
+ m_scheduler->postIpcTask(FROM_HERE, WTF::bind(&dummyTask)); |
+ EXPECT_DOUBLE_EQ(1000.1, m_platformSupport.nextDelayedTaskDeadlineOrMinusOne()); |
+} |
+ |
} // namespace |