Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / scheduler / SchedulerTest.cpp
index 7578940..de1b431 100644 (file)
@@ -5,10 +5,11 @@
 #include "config.h"
 #include "platform/scheduler/Scheduler.h"
 
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/TestingPlatformSupport.h"
 #include "platform/TraceLocation.h"
 #include "public/platform/Platform.h"
-#include "public/platform/WebThread.h"
+#include "public/platform/WebScheduler.h"
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <vector>
 
 using blink::Scheduler;
+using blink::WebScheduler;
+using blink::WebTraceLocation;
 
 namespace {
 
-class SchedulerForTest : public blink::Scheduler {
+class SchedulerForTest : public Scheduler {
 public:
-    static void initializeOnMainThread()
+    SchedulerForTest(WebScheduler* webScheduler):
+        Scheduler(webScheduler)
     {
-        s_sharedScheduler = new SchedulerForTest();
     }
-
-    using Scheduler::Normal;
-    using Scheduler::CompositorPriority;
-    using Scheduler::enterSchedulerPolicy;
-};
-
-class TestMainThread : public blink::WebThread {
-public:
-    // blink::WebThread implementation.
-    virtual void postTask(Task* task) OVERRIDE
-    {
-        m_pendingTasks.append(adoptPtr(task));
-    }
-
-    virtual void postDelayedTask(Task* task, long long delayMs) OVERRIDE
-    {
-        ASSERT_NOT_REACHED();
-    }
-
-    virtual bool isCurrentThread() const OVERRIDE
-    {
-        return true;
-    }
-
-    virtual blink::PlatformThreadId threadId() const OVERRIDE
-    {
-        ASSERT_NOT_REACHED();
-        return 0;
-    }
-
-    virtual void enterRunLoop() OVERRIDE
-    {
-        ASSERT_NOT_REACHED();
-    }
-
-    virtual void exitRunLoop() OVERRIDE
-    {
-        ASSERT_NOT_REACHED();
-    }
-
-    void runPendingTasks()
-    {
-        while (!m_pendingTasks.isEmpty())
-            m_pendingTasks.takeFirst()->run();
-    }
-
-    size_t numPendingMainThreadTasks() const
-    {
-        return m_pendingTasks.size();
-    }
-
-private:
-    WTF::Deque<OwnPtr<Task> > m_pendingTasks;
 };
 
-class SchedulerTestingPlatformSupport : blink::TestingPlatformSupport {
+class WebSchedulerForTest : public WebScheduler {
 public:
-    SchedulerTestingPlatformSupport()
-        : TestingPlatformSupport(TestingPlatformSupport::Config())
-        , m_sharedTimerFunction(nullptr)
-        , m_sharedTimerRunning(false)
-        , m_sharedTimerFireInterval(0)
-        , m_monotonicallyIncreasingTime(0)
+    WebSchedulerForTest()
+        : m_shouldYieldForHighPriorityWork(false)
+        , m_didShutdown(false)
     {
     }
 
-    // blink::Platform implementation.
-    virtual blink::WebThread* currentThread() OVERRIDE
+    // WebScheduler implementation:
+    void shutdown() override
     {
-        return &m_mainThread;
+        m_didShutdown = true;
     }
 
-    virtual void setSharedTimerFiredFunction(SharedTimerFunction timerFunction) OVERRIDE
+    bool shouldYieldForHighPriorityWork() override
     {
-        m_sharedTimerFunction = timerFunction;
+        return m_shouldYieldForHighPriorityWork;
     }
 
-    virtual double monotonicallyIncreasingTime() OVERRIDE
+    void postIdleTask(const WebTraceLocation&, IdleTask* task) override
     {
-        return m_monotonicallyIncreasingTime;
+        m_latestIdleTask = adoptPtr(task);
     }
 
-    virtual void setSharedTimerFireInterval(double)
+    bool didShutdown() const
     {
-        m_sharedTimerFireInterval = 0;
-        m_sharedTimerRunning = true;
+        return m_didShutdown;
     }
 
-    virtual void stopSharedTimer()
+    void setShouldYieldForHighPriorityWork(bool shouldYieldForHighPriorityWork)
     {
-        m_sharedTimerRunning = false;
+        m_shouldYieldForHighPriorityWork = shouldYieldForHighPriorityWork;
     }
 
-    void runPendingTasks()
+    void runLatestIdleTask(double deadlineSeconds)
     {
-        m_mainThread.runPendingTasks();
+        m_latestIdleTask->run(deadlineSeconds);
+        m_latestIdleTask.clear();
     }
 
-    bool sharedTimerRunning() const
-    {
-        return m_sharedTimerRunning;
-    }
-
-    double sharedTimerFireInterval() const
-    {
-        return m_sharedTimerFireInterval;
-    }
-
-    void triggerSharedTimer()
-    {
-        m_sharedTimerFunction();
-    }
-
-    size_t numPendingMainThreadTasks() const
-    {
-        return m_mainThread.numPendingMainThreadTasks();
-    }
-
-    void setMonotonicTimeForTest(double time)
-    {
-        m_monotonicallyIncreasingTime = time;
-    }
+protected:
+    bool m_shouldYieldForHighPriorityWork;
+    bool m_didShutdown;
 
-private:
-    TestMainThread m_mainThread;
-    SharedTimerFunction m_sharedTimerFunction;
-    bool m_sharedTimerRunning;
-    double m_sharedTimerFireInterval;
-    double m_monotonicallyIncreasingTime;
+    OwnPtr<WebScheduler::IdleTask> m_latestIdleTask;
 };
 
 class SchedulerTest : public testing::Test {
 public:
     SchedulerTest()
-        : m_reentrantCount(0)
-        , m_maxRecursion(4)
-    {
-        SchedulerForTest::initializeOnMainThread();
-        m_scheduler = static_cast<SchedulerForTest*>(Scheduler::shared());
-    }
-
-    ~SchedulerTest()
-    {
-        Scheduler::shutdown();
-    }
-
-    virtual void SetUp() OVERRIDE
-    {
-        m_scheduler->enterSchedulerPolicy(SchedulerForTest::Normal);
-    }
-
-    virtual void TearDown() OVERRIDE
     {
-        // If the Scheduler hasn't been shut down then explicitly flush the tasks.
-        if (Scheduler::shared())
-            runPendingTasks();
-    }
-
-    void runPendingTasks()
-    {
-        m_platformSupport.runPendingTasks();
-    }
-
-    void appendToVector(std::string value)
-    {
-        m_order.push_back(value);
-    }
-
-    void appendToVectorReentrantTask()
-    {
-        m_reentrantOrder.push_back(m_reentrantCount++);
-
-        if (m_reentrantCount > m_maxRecursion)
-            return;
-        Scheduler::shared()->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantTask, this));
-    }
-
-    void appendToVectorReentrantInputTask()
-    {
-        m_reentrantOrder.push_back(m_reentrantCount++);
-
-        if (m_reentrantCount > m_maxRecursion)
-            return;
-        m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantInputTask, this));
-    }
-
-    void appendToVectorReentrantCompositorTask()
-    {
-        m_reentrantOrder.push_back(m_reentrantCount++);
-
-        if (m_reentrantCount > m_maxRecursion)
-            return;
-        m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantCompositorTask, this));
+        blink::RuntimeEnabledFeatures::setBlinkSchedulerEnabled(true);
+        m_webScheduler = adoptPtr(new WebSchedulerForTest());
+        m_scheduler = adoptPtr(new SchedulerForTest(m_webScheduler.get()));
     }
 
 protected:
-    SchedulerTestingPlatformSupport m_platformSupport;
-    SchedulerForTest* m_scheduler;
-    std::vector<std::string> m_order;
-    std::vector<int> m_reentrantOrder;
-    int m_reentrantCount;
-    int m_maxRecursion;
+    OwnPtr<WebSchedulerForTest> m_webScheduler;
+    OwnPtr<SchedulerForTest> m_scheduler;
 };
 
-void orderedTestTask(int value, int* result)
-{
-    *result = (*result << 4) | value;
-}
-
-void unorderedTestTask(int value, int* result)
-{
-    *result += value;
-}
-
-void idleTestTask(int value, int* result, double allottedTime)
-{
-    *result += value;
-}
-
-TEST_F(SchedulerTest, TestPostTask)
-{
-    int result = 0;
-    m_scheduler->postTask(FROM_HERE, WTF::bind(&orderedTestTask, 1, &result));
-    m_scheduler->postTask(FROM_HERE, WTF::bind(&orderedTestTask, 2, &result));
-    m_scheduler->postTask(FROM_HERE, WTF::bind(&orderedTestTask, 3, &result));
-    m_scheduler->postTask(FROM_HERE, WTF::bind(&orderedTestTask, 4, &result));
-    runPendingTasks();
-    EXPECT_EQ(0x1234, result);
-}
-
-TEST_F(SchedulerTest, TestPostMixedTaskTypes)
+TEST_F(SchedulerTest, TestShutdown)
 {
-    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));
-    runPendingTasks();
-    EXPECT_EQ(31, result);
+    EXPECT_FALSE(m_webScheduler->didShutdown());
+    m_scheduler.clear();
+    EXPECT_TRUE(m_webScheduler->didShutdown());
 }
 
-int s_sharedTimerTickCount;
-void sharedTimerFunction()
+TEST_F(SchedulerTest, TestShouldYield)
 {
-    s_sharedTimerTickCount++;
-}
-
-TEST_F(SchedulerTest, TestSharedTimer)
-{
-    s_sharedTimerTickCount = 0;
-    m_scheduler->setSharedTimerFiredFunction(&sharedTimerFunction);
-    EXPECT_FALSE(m_platformSupport.sharedTimerRunning());
-    m_scheduler->setSharedTimerFireInterval(0);
-    EXPECT_TRUE(m_platformSupport.sharedTimerRunning());
-
-    m_platformSupport.triggerSharedTimer();
-    EXPECT_EQ(1, s_sharedTimerTickCount);
-
-    m_scheduler->stopSharedTimer();
-    EXPECT_FALSE(m_platformSupport.sharedTimerRunning());
-
-    m_scheduler->setSharedTimerFiredFunction(nullptr);
-    EXPECT_FALSE(m_platformSupport.sharedTimerRunning());
-}
-
-TEST_F(SchedulerTest, TestIdleTask)
-{
-    // TODO: Check task allottedTime when implemented in the scheduler.
-    int result = 0;
-    m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &result));
-    m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &result));
-    m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &result));
-    m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, 1, &result));
-    runPendingTasks();
-    EXPECT_EQ(4, result);
-}
-
-TEST_F(SchedulerTest, TestTaskPrioritization_normalPolicy)
-{
-    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")));
-    m_scheduler->postIpcTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("IPC")));
-
-    runPendingTasks();
-    EXPECT_THAT(m_order, testing::ElementsAre(
-        std::string("L1"), std::string("L2"), std::string("I1"), std::string("C1"), std::string("I2"), std::string("C2"),
-        std::string("IPC")));
-}
-
-TEST_F(SchedulerTest, TestTaskPrioritization_compositorPriorityPolicy)
-{
-    m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority);
-    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")));
-    m_scheduler->postIpcTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("IPC")));
-
-    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("IPC")));
-}
-
-TEST_F(SchedulerTest, TestRentrantTask)
-{
-    m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantTask, this));
-    runPendingTasks();
-
-    EXPECT_THAT(m_reentrantOrder, testing::ElementsAre(0, 1, 2, 3, 4));
-}
-
-
-TEST_F(SchedulerTest, TestRentrantInputTaskDuringShutdown)
-{
-    m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantInputTask, this));
-    Scheduler::shutdown();
-
-    EXPECT_THAT(m_reentrantOrder, testing::ElementsAre(0, 1, 2, 3, 4));
-}
-
-TEST_F(SchedulerTest, TestRentrantCompositorTaskDuringShutdown)
-{
-    m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVectorReentrantCompositorTask, this));
-    Scheduler::shutdown();
-
-    EXPECT_THAT(m_reentrantOrder, testing::ElementsAre(0, 1, 2, 3, 4));
-}
-
-bool s_shouldContinue;
-void reentrantInputTask(Scheduler* scheduler)
-{
-    if (s_shouldContinue)
-        scheduler->postInputTask(FROM_HERE, WTF::bind(&reentrantInputTask, scheduler));
-}
-
-void reentrantCompositorTask(Scheduler* scheduler)
-{
-    if (s_shouldContinue)
-        scheduler->postCompositorTask(FROM_HERE, WTF::bind(&reentrantCompositorTask, scheduler));
-}
-
-void stopReentrantTask()
-{
-    s_shouldContinue = false;
-}
-
-TEST_F(SchedulerTest, TestRentrantInputTaskDoesNotStarveOutLowPriorityTask)
-{
-    s_shouldContinue = true;
-    m_scheduler->postInputTask(FROM_HERE, WTF::bind(&reentrantInputTask, m_scheduler));
-    m_scheduler->postTask(FROM_HERE, WTF::bind(&stopReentrantTask));
-
-    // If starvation occurs then this will never exit.
-    runPendingTasks();
-}
-
-TEST_F(SchedulerTest, TestRentrantCompositorTaskDoesNotStarveOutLowPriorityTask)
-{
-    s_shouldContinue = true;
-    m_scheduler->postInputTask(FROM_HERE, WTF::bind(&reentrantCompositorTask, m_scheduler));
-    m_scheduler->postTask(FROM_HERE, WTF::bind(&stopReentrantTask));
-
-    // If starvation occurs then this will never exit.
-    runPendingTasks();
-}
-
-int s_dummyTaskCount;
-void dummyTask()
-{
-    s_dummyTaskCount++;
-}
-
-TEST_F(SchedulerTest, TestMultipleCallsToPostInputOrCompositorTaskResultsInOnlyOneMainThreadTask)
-{
-    EXPECT_EQ(0U, m_platformSupport.numPendingMainThreadTasks());
-
-    for (int i = 0; i < 10; i++) {
-        m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
-        m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask));
-    }
-
-    EXPECT_EQ(1U, m_platformSupport.numPendingMainThreadTasks());
-}
-
-TEST_F(SchedulerTest, TestMainThreadTaskLifeCycle)
-{
-    EXPECT_EQ(0U, m_platformSupport.numPendingMainThreadTasks());
-
-    m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
-    EXPECT_EQ(1U, m_platformSupport.numPendingMainThreadTasks());
-
-    runPendingTasks();
-    EXPECT_EQ(0U, m_platformSupport.numPendingMainThreadTasks());
-
-    m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask));
-    EXPECT_EQ(1U, m_platformSupport.numPendingMainThreadTasks());
-
-    runPendingTasks();
-    EXPECT_EQ(0U, m_platformSupport.numPendingMainThreadTasks());
-}
-
-void postDummyInputTask()
-{
-    Scheduler::shared()->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
-}
-
-TEST_F(SchedulerTest, HighPriorityTasksOnlyDontRunBecauseOfSharedTimerFiring_InNormalMode)
-{
-    s_dummyTaskCount = 0;
-    m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
-    // Trigger the posting of an input task during execution of the shared timer function.
-    m_scheduler->setSharedTimerFiredFunction(&postDummyInputTask);
-    m_scheduler->setSharedTimerFireInterval(0);
-    m_platformSupport.triggerSharedTimer();
-
-    EXPECT_EQ(0, s_dummyTaskCount);
-
-    // Clean up.
-    m_scheduler->stopSharedTimer();
-    m_scheduler->setSharedTimerFiredFunction(nullptr);
-}
-
-TEST_F(SchedulerTest, HighPriorityTasksOnlyRunOncePerSharedTimerFiring_InLowSchedulerPolicy)
-{
-    s_dummyTaskCount = 0;
-    m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority);
-    m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
-    // Trigger the posting of an input task during execution of the shared timer function.
-    m_scheduler->setSharedTimerFiredFunction(&postDummyInputTask);
-    m_scheduler->setSharedTimerFireInterval(0);
-    m_platformSupport.triggerSharedTimer();
-
-    EXPECT_EQ(1, s_dummyTaskCount);
-
-    // Clean up.
-    m_scheduler->stopSharedTimer();
-    m_scheduler->setSharedTimerFiredFunction(nullptr);
-}
-
-TEST_F(SchedulerTest, TestInputEventDoesNotTriggerShouldYield_InNormalMode)
-{
-    m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
-
     EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
-}
-
-TEST_F(SchedulerTest, TestDidReceiveInputEventDoesNotTriggerShouldYield)
-{
-    m_scheduler->didReceiveInputEvent();
-
-    EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
-}
-
-TEST_F(SchedulerTest, TestCompositorTaskDoesNotTriggerShouldYield_InNormalMode)
-{
-    m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask));
-
-    EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
-}
-
-TEST_F(SchedulerTest, TestIpcTaskDoesNotTriggerShouldYield_InNormalMode)
-{
-    m_scheduler->postIpcTask(FROM_HERE, WTF::bind(&dummyTask));
-
-    EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
-}
-
-TEST_F(SchedulerTest, TestCompositorTaskDoesTriggerShouldYieldAfterDidReceiveInputEvent)
-{
-    m_scheduler->didReceiveInputEvent();
-
-    ASSERT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
-    m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask));
-
-    EXPECT_TRUE(m_scheduler->shouldYieldForHighPriorityWork());
-}
-
-TEST_F(SchedulerTest, TestInputTaskDoesTriggerShouldYield_InCompositorPriorityMode)
-{
-    m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority);
-    m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
-
+    m_webScheduler->setShouldYieldForHighPriorityWork(true);
     EXPECT_TRUE(m_scheduler->shouldYieldForHighPriorityWork());
 }
 
-
-TEST_F(SchedulerTest, TestCompositorTaskDoesTriggerShouldYield_InCompositorPriorityMode)
-{
-    m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority);
-    m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask));
-
-    EXPECT_TRUE(m_scheduler->shouldYieldForHighPriorityWork());
-}
-
-TEST_F(SchedulerTest, TestIpcTaskDoesNotTriggerShouldYield_InCompositorPriorityMode)
+void idleTestTask(double expectedDeadline, double deadlineSeconds)
 {
-    m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority);
-    m_scheduler->postIpcTask(FROM_HERE, WTF::bind(&dummyTask));
-
-    EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
+    EXPECT_EQ(expectedDeadline, deadlineSeconds);
 }
 
-TEST_F(SchedulerTest, testDidReceiveInputEvent_DoesntTriggerLowLatencyModeForLong)
+TEST_F(SchedulerTest, TestIdleTasks)
 {
-    m_platformSupport.setMonotonicTimeForTest(1000.0);
-
-    // Note the latency mode gets reset by executeHighPriorityTasks, so we need a dummy task here
-    // to make sure runPendingTasks triggers executeHighPriorityTasks.
-    m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask));
-    m_scheduler->didReceiveInputEvent();
-    m_platformSupport.setMonotonicTimeForTest(1000.5);
-    runPendingTasks();
-
-    ASSERT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
-    m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask));
-
-    EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
+    double deadline = 1.1;
+    m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&idleTestTask, deadline));
+    m_webScheduler->runLatestIdleTask(deadline);
 }
 
 } // namespace