| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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/Timer.h" | 6 #include "platform/Timer.h" |
| 7 | 7 |
| 8 #include "public/platform/Platform.h" | 8 #include "public/platform/Platform.h" |
| 9 #include "public/platform/WebScheduler.h" | 9 #include "public/platform/WebScheduler.h" |
| 10 #include "public/platform/WebThread.h" | 10 #include "public/platform/WebThread.h" |
| 11 #include <gmock/gmock.h> | 11 #include <gmock/gmock.h> |
| 12 #include <gtest/gtest.h> | 12 #include <gtest/gtest.h> |
| 13 #include <queue> | 13 #include <queue> |
| 14 | 14 |
| 15 using testing::ElementsAre; | 15 using testing::ElementsAre; |
| 16 | 16 |
| 17 namespace blink { | 17 namespace blink { |
| 18 namespace { | 18 namespace { |
| 19 double gCurrentTimeSecs = 0.0; | 19 double gCurrentTimeSecs = 0.0; |
| 20 | 20 |
| 21 double currentTime() | 21 double currentTime() |
| 22 { | 22 { |
| 23 return gCurrentTimeSecs; | 23 return gCurrentTimeSecs; |
| 24 } | 24 } |
| 25 | 25 |
| 26 // This class exists because gcc doesn't know how to move an OwnPtr. | |
| 27 class RefCountedTaskContainer : public RefCounted<RefCountedTaskContainer> { | |
| 28 public: | |
| 29 explicit RefCountedTaskContainer(WebThread::Task* task) : m_task(adoptPtr(ta
sk)) { } | |
| 30 | |
| 31 ~RefCountedTaskContainer() { } | |
| 32 | |
| 33 void run() | |
| 34 { | |
| 35 m_task->run(); | |
| 36 } | |
| 37 | |
| 38 private: | |
| 39 OwnPtr<WebThread::Task> m_task; | |
| 40 }; | |
| 41 | |
| 42 class DelayedTask { | |
| 43 public: | |
| 44 DelayedTask(WebThread::Task* task, long long delayMs) | |
| 45 : m_task(adoptRef(new RefCountedTaskContainer(task))) | |
| 46 , m_runTimeSecs(monotonicallyIncreasingTime() + 0.001 * static_cast<doub
le>(delayMs)) | |
| 47 , m_delayMs(delayMs) { } | |
| 48 | |
| 49 bool operator<(const DelayedTask& other) const | |
| 50 { | |
| 51 return m_runTimeSecs > other.m_runTimeSecs; | |
| 52 } | |
| 53 | |
| 54 void run() const | |
| 55 { | |
| 56 m_task->run(); | |
| 57 } | |
| 58 | |
| 59 double runTimeSecs() const | |
| 60 { | |
| 61 return m_runTimeSecs; | |
| 62 } | |
| 63 | |
| 64 long long delayMs() const | |
| 65 { | |
| 66 return m_delayMs; | |
| 67 } | |
| 68 | |
| 69 private: | |
| 70 RefPtr<RefCountedTaskContainer> m_task; | |
| 71 double m_runTimeSecs; | |
| 72 long long m_delayMs; | |
| 73 }; | |
| 74 | |
| 75 class MockWebScheduler : public WebScheduler { | 26 class MockWebScheduler : public WebScheduler { |
| 76 public: | 27 public: |
| 77 MockWebScheduler() { } | 28 explicit MockWebScheduler() { } |
| 78 ~MockWebScheduler() override { } | 29 ~MockWebScheduler() override { } |
| 79 | 30 |
| 80 bool shouldYieldForHighPriorityWork() override | 31 bool shouldYieldForHighPriorityWork() override |
| 81 { | 32 { |
| 82 return false; | 33 return false; |
| 83 } | 34 } |
| 84 | 35 |
| 85 bool canExceedIdleDeadlineIfRequired() override | 36 bool canExceedIdleDeadlineIfRequired() override |
| 86 { | 37 { |
| 87 return false; | 38 return false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 98 void postIdleTaskAfterWakeup(const WebTraceLocation&, WebThread::IdleTask*)
override | 49 void postIdleTaskAfterWakeup(const WebTraceLocation&, WebThread::IdleTask*)
override |
| 99 { | 50 { |
| 100 } | 51 } |
| 101 | 52 |
| 102 void postLoadingTask(const WebTraceLocation&, WebThread::Task*) override | 53 void postLoadingTask(const WebTraceLocation&, WebThread::Task*) override |
| 103 { | 54 { |
| 104 } | 55 } |
| 105 | 56 |
| 106 void postTimerTask(const WebTraceLocation&, WebThread::Task* task, long long
delayMs) override | 57 void postTimerTask(const WebTraceLocation&, WebThread::Task* task, long long
delayMs) override |
| 107 { | 58 { |
| 108 m_timerTasks.push(DelayedTask(task, delayMs)); | |
| 109 } | 59 } |
| 110 | |
| 111 void runUntilIdle() | |
| 112 { | |
| 113 while (!m_timerTasks.empty()) { | |
| 114 gCurrentTimeSecs = m_timerTasks.top().runTimeSecs(); | |
| 115 m_timerTasks.top().run(); | |
| 116 m_timerTasks.pop(); | |
| 117 } | |
| 118 } | |
| 119 | |
| 120 void runUntilIdleOrDeadlinePassed(double deadline) | |
| 121 { | |
| 122 while (!m_timerTasks.empty()) { | |
| 123 if (m_timerTasks.top().runTimeSecs() > deadline) { | |
| 124 gCurrentTimeSecs = deadline; | |
| 125 break; | |
| 126 } | |
| 127 gCurrentTimeSecs = m_timerTasks.top().runTimeSecs(); | |
| 128 m_timerTasks.top().run(); | |
| 129 m_timerTasks.pop(); | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 bool hasOneTimerTask() const | |
| 134 { | |
| 135 return m_timerTasks.size() == 1; | |
| 136 } | |
| 137 | |
| 138 long nextTimerTaskDelayMillis() const | |
| 139 { | |
| 140 ASSERT(hasOneTimerTask()); | |
| 141 return m_timerTasks.top().delayMs(); | |
| 142 } | |
| 143 | |
| 144 private: | |
| 145 std::priority_queue<DelayedTask> m_timerTasks; | |
| 146 }; | 60 }; |
| 147 | 61 |
| 148 class FakeWebThread : public WebThread { | 62 class FakeWebThread : public WebThread { |
| 149 public: | 63 public: |
| 150 FakeWebThread() : m_webScheduler(adoptPtr(new MockWebScheduler())) { } | 64 explicit FakeWebThread(WebScheduler* webScheduler) : m_webScheduler(webSched
uler) { } |
| 151 ~FakeWebThread() override { } | 65 ~FakeWebThread() override { } |
| 152 | 66 |
| 153 // WebThread implementation: | 67 // WebThread implementation: |
| 154 void postTask(const WebTraceLocation&, Task*) | 68 void postTask(const WebTraceLocation&, Task*) |
| 155 { | 69 { |
| 156 ASSERT_NOT_REACHED(); | 70 ASSERT_NOT_REACHED(); |
| 157 } | 71 } |
| 158 | 72 |
| 159 virtual void postDelayedTask(const WebTraceLocation&, Task*, long long) | 73 virtual void postDelayedTask(const WebTraceLocation&, Task*, long long) |
| 160 { | 74 { |
| 161 ASSERT_NOT_REACHED(); | 75 ASSERT_NOT_REACHED(); |
| 162 } | 76 } |
| 163 | 77 |
| 164 virtual bool isCurrentThread() const | 78 virtual bool isCurrentThread() const |
| 165 { | 79 { |
| 166 ASSERT_NOT_REACHED(); | 80 ASSERT_NOT_REACHED(); |
| 167 return true; | 81 return true; |
| 168 } | 82 } |
| 169 | 83 |
| 170 virtual PlatformThreadId threadId() const | 84 virtual PlatformThreadId threadId() const |
| 171 { | 85 { |
| 172 ASSERT_NOT_REACHED(); | 86 ASSERT_NOT_REACHED(); |
| 173 return 0; | 87 return 0; |
| 174 } | 88 } |
| 175 | 89 |
| 176 WebScheduler* scheduler() const override | 90 WebScheduler* scheduler() const override |
| 177 { | 91 { |
| 178 return m_webScheduler.get(); | 92 return m_webScheduler; |
| 179 } | 93 } |
| 180 | 94 |
| 181 virtual void enterRunLoop() | 95 virtual void enterRunLoop() |
| 182 { | 96 { |
| 183 ASSERT_NOT_REACHED(); | 97 ASSERT_NOT_REACHED(); |
| 184 } | 98 } |
| 185 | 99 |
| 186 virtual void exitRunLoop() | 100 virtual void exitRunLoop() |
| 187 { | 101 { |
| 188 ASSERT_NOT_REACHED(); | 102 ASSERT_NOT_REACHED(); |
| 189 } | 103 } |
| 190 | 104 |
| 191 private: | 105 private: |
| 192 OwnPtr<MockWebScheduler> m_webScheduler; | 106 WebScheduler* m_webScheduler; |
| 193 }; | 107 }; |
| 194 | 108 |
| 195 class TimerTestPlatform : public Platform { | 109 class TimerTestPlatform : public Platform { |
| 196 public: | 110 public: |
| 197 TimerTestPlatform() | 111 explicit TimerTestPlatform(WebThread* webThread) |
| 198 : m_webThread(adoptPtr(new FakeWebThread())) { } | 112 : m_webThread(webThread) |
| 113 , m_timerInterval(-1) { } |
| 199 ~TimerTestPlatform() override { } | 114 ~TimerTestPlatform() override { } |
| 200 | 115 |
| 201 WebThread* currentThread() override | 116 WebThread* currentThread() override |
| 202 { | 117 { |
| 203 return m_webThread.get(); | 118 return m_webThread; |
| 204 } | 119 } |
| 205 | 120 |
| 206 void cryptographicallyRandomValues(unsigned char*, size_t) override | 121 void cryptographicallyRandomValues(unsigned char*, size_t) override |
| 207 { | 122 { |
| 208 ASSERT_NOT_REACHED(); | 123 ASSERT_NOT_REACHED(); |
| 209 } | 124 } |
| 210 | 125 |
| 211 const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) o
verride | 126 const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) o
verride |
| 212 { | 127 { |
| 213 static const unsigned char enabled[] = {0}; | 128 static const unsigned char enabled[] = {0}; |
| 214 return enabled; | 129 return enabled; |
| 215 } | 130 } |
| 216 | 131 |
| 132 void setSharedTimerFiredFunction(SharedTimerFunction timerFunction) override |
| 133 { |
| 134 s_timerFunction = timerFunction; |
| 135 } |
| 136 |
| 137 void setSharedTimerFireInterval(double interval) override |
| 138 { |
| 139 m_timerInterval = interval; |
| 140 } |
| 141 |
| 142 virtual void stopSharedTimer() override |
| 143 { |
| 144 m_timerInterval = -1; |
| 145 } |
| 146 |
| 217 void runUntilIdle() | 147 void runUntilIdle() |
| 218 { | 148 { |
| 219 mockScheduler()->runUntilIdle(); | 149 while (hasOneTimerTask()) { |
| 150 gCurrentTimeSecs += m_timerInterval; |
| 151 s_timerFunction(); |
| 152 } |
| 220 } | 153 } |
| 221 | 154 |
| 222 void runUntilIdleOrDeadlinePassed(double deadline) | 155 void runUntilIdleOrDeadlinePassed(double deadline) |
| 223 { | 156 { |
| 224 mockScheduler()->runUntilIdleOrDeadlinePassed(deadline); | 157 while (hasOneTimerTask()) { |
| 158 double newTime = gCurrentTimeSecs + m_timerInterval; |
| 159 if (newTime >= deadline) { |
| 160 gCurrentTimeSecs = deadline; |
| 161 break; |
| 162 } |
| 163 gCurrentTimeSecs = newTime; |
| 164 s_timerFunction(); |
| 165 } |
| 225 } | 166 } |
| 226 | 167 |
| 227 bool hasOneTimerTask() const | 168 bool hasOneTimerTask() const |
| 228 { | 169 { |
| 229 return mockScheduler()->hasOneTimerTask(); | 170 return s_timerFunction && m_timerInterval >= 0; |
| 230 } | 171 } |
| 231 | 172 |
| 232 long nextTimerTaskDelayMillis() const | 173 long nextTimerTaskDelayMillis() const |
| 233 { | 174 { |
| 234 return mockScheduler()->nextTimerTaskDelayMillis(); | 175 ASSERT(hasOneTimerTask()); |
| 176 return static_cast<long>(m_timerInterval * 1000); |
| 235 } | 177 } |
| 236 | 178 |
| 237 private: | 179 private: |
| 238 MockWebScheduler* mockScheduler() const | 180 WebThread* m_webThread; |
| 239 { | 181 double m_timerInterval; |
| 240 return static_cast<MockWebScheduler*>(m_webThread->scheduler()); | |
| 241 } | |
| 242 | 182 |
| 243 OwnPtr<FakeWebThread> m_webThread; | 183 // This needs to be static because the callback is registered only once by |
| 184 // PlatformThreadData. |
| 185 static SharedTimerFunction s_timerFunction; |
| 244 }; | 186 }; |
| 245 | 187 |
| 188 Platform::SharedTimerFunction TimerTestPlatform::s_timerFunction; |
| 189 |
| 246 class TimerTest : public testing::Test { | 190 class TimerTest : public testing::Test { |
| 247 public: | 191 public: |
| 248 void SetUp() override | 192 void SetUp() override |
| 249 { | 193 { |
| 250 m_platform = adoptPtr(new TimerTestPlatform()); | 194 m_mockWebScheduler = adoptPtr(new MockWebScheduler()); |
| 195 m_fakeWebThread = adoptPtr(new FakeWebThread(m_mockWebScheduler.get())); |
| 196 m_platform = adoptPtr(new TimerTestPlatform(m_fakeWebThread.get())); |
| 251 m_oldPlatform = Platform::current(); | 197 m_oldPlatform = Platform::current(); |
| 252 Platform::initialize(m_platform.get()); | 198 Platform::initialize(m_platform.get()); |
| 253 WTF::setMonotonicallyIncreasingTimeFunction(currentTime); | 199 WTF::setMonotonicallyIncreasingTimeFunction(currentTime); |
| 254 | 200 |
| 255 m_runTimes.clear(); | 201 m_runTimes.clear(); |
| 256 gCurrentTimeSecs = 10.0; | 202 gCurrentTimeSecs = 10.0; |
| 257 m_startTime = gCurrentTimeSecs; | 203 m_startTime = gCurrentTimeSecs; |
| 258 } | 204 } |
| 259 | 205 |
| 260 void TearDown() override | 206 void TearDown() override |
| (...skipping 29 matching lines...) Expand all Loading... |
| 290 long nextTimerTaskDelayMillis() const | 236 long nextTimerTaskDelayMillis() const |
| 291 { | 237 { |
| 292 return m_platform->nextTimerTaskDelayMillis(); | 238 return m_platform->nextTimerTaskDelayMillis(); |
| 293 } | 239 } |
| 294 | 240 |
| 295 protected: | 241 protected: |
| 296 double m_startTime; | 242 double m_startTime; |
| 297 std::vector<double> m_runTimes; | 243 std::vector<double> m_runTimes; |
| 298 | 244 |
| 299 private: | 245 private: |
| 246 OwnPtr<MockWebScheduler> m_mockWebScheduler; |
| 247 OwnPtr<FakeWebThread> m_fakeWebThread; |
| 300 OwnPtr<TimerTestPlatform> m_platform; | 248 OwnPtr<TimerTestPlatform> m_platform; |
| 301 Platform* m_oldPlatform; | 249 Platform* m_oldPlatform; |
| 302 }; | 250 }; |
| 303 | 251 |
| 304 TEST_F(TimerTest, StartOneShot_Zero) | 252 TEST_F(TimerTest, StartOneShot_Zero) |
| 305 { | 253 { |
| 306 Timer<TimerTest> timer(this, &TimerTest::countingTask); | 254 Timer<TimerTest> timer(this, &TimerTest::countingTask); |
| 307 timer.startOneShot(0, FROM_HERE); | 255 timer.startOneShot(0, FROM_HERE); |
| 308 | 256 |
| 309 ASSERT(hasOneTimerTask()); | 257 ASSERT(hasOneTimerTask()); |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 MockTimerWithAlignment timer; | 665 MockTimerWithAlignment timer; |
| 718 timer.setAlignedFireTime(m_startTime + 1.0); | 666 timer.setAlignedFireTime(m_startTime + 1.0); |
| 719 | 667 |
| 720 timer.start(0.0, 0.0, FROM_HERE); | 668 timer.start(0.0, 0.0, FROM_HERE); |
| 721 | 669 |
| 722 EXPECT_FLOAT_EQ(1.0, timer.nextFireInterval()); | 670 EXPECT_FLOAT_EQ(1.0, timer.nextFireInterval()); |
| 723 EXPECT_FLOAT_EQ(0.0, timer.nextUnalignedFireInterval()); | 671 EXPECT_FLOAT_EQ(0.0, timer.nextUnalignedFireInterval()); |
| 724 EXPECT_FLOAT_EQ(m_startTime, timer.lastFireTime()); | 672 EXPECT_FLOAT_EQ(m_startTime, timer.lastFireTime()); |
| 725 | 673 |
| 726 timer.setAlignedFireTime(m_startTime); | 674 timer.setAlignedFireTime(m_startTime); |
| 727 timer.didChangeAlignmentInterval(monotonicallyIncreasingTime()); | 675 timer.didChangeAlignmentInterval(); |
| 728 | 676 |
| 729 EXPECT_FLOAT_EQ(0.0, timer.nextFireInterval()); | 677 EXPECT_FLOAT_EQ(0.0, timer.nextFireInterval()); |
| 730 EXPECT_FLOAT_EQ(0.0, timer.nextUnalignedFireInterval()); | 678 EXPECT_FLOAT_EQ(0.0, timer.nextUnalignedFireInterval()); |
| 731 EXPECT_FLOAT_EQ(m_startTime, timer.lastFireTime()); | 679 EXPECT_FLOAT_EQ(m_startTime, timer.lastFireTime()); |
| 732 } | 680 } |
| 733 | 681 |
| 734 | 682 |
| 735 } // namespace | 683 } // namespace |
| 736 } // namespace blink | 684 } // namespace blink |
| OLD | NEW |