Index: Source/platform/TimerTest.cpp |
diff --git a/Source/platform/TimerTest.cpp b/Source/platform/TimerTest.cpp |
index 4773cd6ddc1ea71ef48c980781dbd57b29b89f3a..439e71e0e8eaeab5fe14f830daeaca172ca61ee4 100644 |
--- a/Source/platform/TimerTest.cpp |
+++ b/Source/platform/TimerTest.cpp |
@@ -23,9 +23,58 @@ double currentTime() |
return gCurrentTimeSecs; |
} |
+// This class exists because gcc doesn't know how to move an OwnPtr. |
+class RefCountedTaskContainer : public RefCounted<RefCountedTaskContainer> { |
+public: |
+ explicit RefCountedTaskContainer(WebThread::Task* task) : m_task(adoptPtr(task)) { } |
+ |
+ ~RefCountedTaskContainer() { } |
+ |
+ void run() |
+ { |
+ m_task->run(); |
+ } |
+ |
+private: |
+ OwnPtr<WebThread::Task> m_task; |
+}; |
+ |
+class DelayedTask { |
+public: |
+ DelayedTask(WebThread::Task* task, long long delayMs) |
+ : m_task(adoptRef(new RefCountedTaskContainer(task))) |
+ , m_runTimeSecs(monotonicallyIncreasingTime() + 0.001 * static_cast<double>(delayMs)) |
+ , m_delayMs(delayMs) { } |
+ |
+ bool operator<(const DelayedTask& other) const |
+ { |
+ return m_runTimeSecs > other.m_runTimeSecs; |
+ } |
+ |
+ void run() const |
+ { |
+ m_task->run(); |
+ } |
+ |
+ double runTimeSecs() const |
+ { |
+ return m_runTimeSecs; |
+ } |
+ |
+ long long delayMs() const |
+ { |
+ return m_delayMs; |
+ } |
+ |
+private: |
+ RefPtr<RefCountedTaskContainer> m_task; |
+ double m_runTimeSecs; |
+ long long m_delayMs; |
+}; |
+ |
class MockWebScheduler : public WebScheduler { |
public: |
- explicit MockWebScheduler() { } |
+ MockWebScheduler() { } |
~MockWebScheduler() override { } |
bool shouldYieldForHighPriorityWork() override |
@@ -56,12 +105,49 @@ public: |
void postTimerTask(const WebTraceLocation&, WebThread::Task* task, long long delayMs) override |
{ |
+ m_timerTasks.push(DelayedTask(task, delayMs)); |
+ } |
+ |
+ void runUntilIdle() |
+ { |
+ while (!m_timerTasks.empty()) { |
+ gCurrentTimeSecs = m_timerTasks.top().runTimeSecs(); |
+ m_timerTasks.top().run(); |
+ m_timerTasks.pop(); |
+ } |
+ } |
+ |
+ void runUntilIdleOrDeadlinePassed(double deadline) |
+ { |
+ while (!m_timerTasks.empty()) { |
+ if (m_timerTasks.top().runTimeSecs() > deadline) { |
+ gCurrentTimeSecs = deadline; |
+ break; |
+ } |
+ gCurrentTimeSecs = m_timerTasks.top().runTimeSecs(); |
+ m_timerTasks.top().run(); |
+ m_timerTasks.pop(); |
+ } |
+ } |
+ |
+ bool hasOneTimerTask() const |
+ { |
+ return m_timerTasks.size() == 1; |
} |
+ |
+ long nextTimerTaskDelayMillis() const |
+ { |
+ ASSERT(hasOneTimerTask()); |
+ return m_timerTasks.top().delayMs(); |
+ } |
+ |
+private: |
+ std::priority_queue<DelayedTask> m_timerTasks; |
}; |
class FakeWebThread : public WebThread { |
public: |
- explicit FakeWebThread(WebScheduler* webScheduler) : m_webScheduler(webScheduler) { } |
+ FakeWebThread() : m_webScheduler(adoptPtr(new MockWebScheduler())) { } |
~FakeWebThread() override { } |
// WebThread implementation: |
@@ -89,7 +175,7 @@ public: |
WebScheduler* scheduler() const override |
{ |
- return m_webScheduler; |
+ return m_webScheduler.get(); |
} |
virtual void enterRunLoop() |
@@ -103,19 +189,18 @@ public: |
} |
private: |
- WebScheduler* m_webScheduler; |
+ OwnPtr<MockWebScheduler> m_webScheduler; |
}; |
class TimerTestPlatform : public Platform { |
public: |
- explicit TimerTestPlatform(WebThread* webThread) |
- : m_webThread(webThread) |
- , m_timerInterval(-1) { } |
+ TimerTestPlatform() |
+ : m_webThread(adoptPtr(new FakeWebThread())) { } |
~TimerTestPlatform() override { } |
WebThread* currentThread() override |
{ |
- return m_webThread; |
+ return m_webThread.get(); |
} |
void cryptographicallyRandomValues(unsigned char*, size_t) override |
@@ -129,71 +214,40 @@ public: |
return enabled; |
} |
- void setSharedTimerFiredFunction(SharedTimerFunction timerFunction) override |
- { |
- s_timerFunction = timerFunction; |
- } |
- |
- void setSharedTimerFireInterval(double interval) override |
- { |
- m_timerInterval = interval; |
- } |
- |
- virtual void stopSharedTimer() override |
- { |
- m_timerInterval = -1; |
- } |
- |
void runUntilIdle() |
{ |
- while (hasOneTimerTask()) { |
- gCurrentTimeSecs += m_timerInterval; |
- s_timerFunction(); |
- } |
+ mockScheduler()->runUntilIdle(); |
} |
void runUntilIdleOrDeadlinePassed(double deadline) |
{ |
- while (hasOneTimerTask()) { |
- double newTime = gCurrentTimeSecs + m_timerInterval; |
- if (newTime >= deadline) { |
- gCurrentTimeSecs = deadline; |
- break; |
- } |
- gCurrentTimeSecs = newTime; |
- s_timerFunction(); |
- } |
+ mockScheduler()->runUntilIdleOrDeadlinePassed(deadline); |
} |
bool hasOneTimerTask() const |
{ |
- return s_timerFunction && m_timerInterval >= 0; |
+ return mockScheduler()->hasOneTimerTask(); |
} |
long nextTimerTaskDelayMillis() const |
{ |
- ASSERT(hasOneTimerTask()); |
- return static_cast<long>(m_timerInterval * 1000); |
+ return mockScheduler()->nextTimerTaskDelayMillis(); |
} |
private: |
- WebThread* m_webThread; |
- double m_timerInterval; |
+ MockWebScheduler* mockScheduler() const |
+ { |
+ return static_cast<MockWebScheduler*>(m_webThread->scheduler()); |
+ } |
- // This needs to be static because the callback is registered only once by |
- // PlatformThreadData. |
- static SharedTimerFunction s_timerFunction; |
+ OwnPtr<FakeWebThread> m_webThread; |
}; |
-Platform::SharedTimerFunction TimerTestPlatform::s_timerFunction; |
- |
class TimerTest : public testing::Test { |
public: |
void SetUp() override |
{ |
- m_mockWebScheduler = adoptPtr(new MockWebScheduler()); |
- m_fakeWebThread = adoptPtr(new FakeWebThread(m_mockWebScheduler.get())); |
- m_platform = adoptPtr(new TimerTestPlatform(m_fakeWebThread.get())); |
+ m_platform = adoptPtr(new TimerTestPlatform()); |
m_oldPlatform = Platform::current(); |
Platform::initialize(m_platform.get()); |
WTF::setMonotonicallyIncreasingTimeFunction(currentTime); |
@@ -243,8 +297,6 @@ protected: |
std::vector<double> m_runTimes; |
private: |
- OwnPtr<MockWebScheduler> m_mockWebScheduler; |
- OwnPtr<FakeWebThread> m_fakeWebThread; |
OwnPtr<TimerTestPlatform> m_platform; |
Platform* m_oldPlatform; |
}; |
@@ -672,7 +724,7 @@ TEST_F(TimerTest, DidChangeAlignmentInterval) |
EXPECT_FLOAT_EQ(m_startTime, timer.lastFireTime()); |
timer.setAlignedFireTime(m_startTime); |
- timer.didChangeAlignmentInterval(); |
+ timer.didChangeAlignmentInterval(monotonicallyIncreasingTime()); |
EXPECT_FLOAT_EQ(0.0, timer.nextFireInterval()); |
EXPECT_FLOAT_EQ(0.0, timer.nextUnalignedFireInterval()); |