Index: components/scheduler/renderer/renderer_scheduler_impl_unittest.cc |
diff --git a/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc |
index c651486d18c9315d3783c1992daac11d200eeaa6..8538896ba2ca06770780dbd6ef7fa6ab7ccfbe46 100644 |
--- a/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc |
+++ b/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc |
@@ -126,15 +126,28 @@ void PostingYieldingTestTask(RendererSchedulerImpl* scheduler, |
*should_yield_after = scheduler->ShouldYieldForHighPriorityWork(); |
} |
+enum class SimulateInputType { None, TouchStart, TouchEnd }; |
+ |
void AnticipationTestTask(RendererSchedulerImpl* scheduler, |
- bool simulate_input, |
+ SimulateInputType simulate_input, |
bool* is_anticipated_before, |
bool* is_anticipated_after) { |
*is_anticipated_before = scheduler->IsHighPriorityWorkAnticipated(); |
- if (simulate_input) { |
- scheduler->DidHandleInputEventOnCompositorThread( |
- FakeInputEvent(blink::WebInputEvent::GestureFlingStart), |
- RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); |
+ switch (simulate_input) { |
+ case SimulateInputType::None: |
+ break; |
+ |
+ case SimulateInputType::TouchStart: |
+ scheduler->DidHandleInputEventOnCompositorThread( |
+ FakeInputEvent(blink::WebInputEvent::TouchStart), |
+ RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); |
+ break; |
+ |
+ case SimulateInputType::TouchEnd: |
+ scheduler->DidHandleInputEventOnCompositorThread( |
+ FakeInputEvent(blink::WebInputEvent::TouchEnd), |
+ RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); |
+ break; |
} |
*is_anticipated_after = scheduler->IsHighPriorityWorkAnticipated(); |
} |
@@ -145,8 +158,8 @@ class RendererSchedulerImplForTest : public RendererSchedulerImpl { |
public: |
using RendererSchedulerImpl::OnIdlePeriodEnded; |
using RendererSchedulerImpl::OnIdlePeriodStarted; |
- using RendererSchedulerImpl::Policy; |
- using RendererSchedulerImpl::PolicyToString; |
+ using RendererSchedulerImpl::UseCase; |
+ using RendererSchedulerImpl::UseCaseToString; |
RendererSchedulerImplForTest( |
scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner) |
@@ -155,6 +168,14 @@ class RendererSchedulerImplForTest : public RendererSchedulerImpl { |
void UpdatePolicyLocked(UpdateType update_type) override { |
update_policy_count_++; |
RendererSchedulerImpl::UpdatePolicyLocked(update_type); |
+ |
+ std::string use_case = RendererSchedulerImplForTest::UseCaseToString( |
+ MainThreadOnly().current_use_case_); |
+ if (MainThreadOnly().scroll_expected_soon_) { |
+ use_cases_.push_back(use_case + " scroll expected"); |
+ } else { |
+ use_cases_.push_back(use_case); |
+ } |
} |
void EnsureUrgentPolicyUpdatePostedOnMainThread() { |
@@ -173,17 +194,19 @@ class RendererSchedulerImplForTest : public RendererSchedulerImpl { |
} |
int update_policy_count_; |
+ std::vector<std::string> use_cases_; |
}; |
// Lets gtest print human readable Policy values. |
-::std::ostream& operator<<(::std::ostream& os, |
- const RendererSchedulerImplForTest::Policy& policy) { |
- return os << RendererSchedulerImplForTest::PolicyToString(policy); |
+::std::ostream& operator<<( |
+ ::std::ostream& os, |
+ const RendererSchedulerImplForTest::UseCase& use_case) { |
+ return os << RendererSchedulerImplForTest::UseCaseToString(use_case); |
} |
class RendererSchedulerImplTest : public testing::Test { |
public: |
- using Policy = RendererSchedulerImpl::Policy; |
+ using UseCase = RendererSchedulerImpl::UseCase; |
RendererSchedulerImplTest() : clock_(new base::SimpleTestTickClock()) { |
clock_->Advance(base::TimeDelta::FromMicroseconds(5000)); |
@@ -255,10 +278,27 @@ class RendererSchedulerImplTest : public testing::Test { |
scheduler_->DidCommitFrameToCompositor(); |
} |
+ void ForceMainthreadScrollingUseCase() { |
+ cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create( |
+ BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(), |
+ base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL); |
+ begin_frame_args.on_critical_path = true; |
+ scheduler_->WillBeginFrame(begin_frame_args); |
+ } |
+ |
void EnableIdleTasks() { DoMainFrame(); } |
- Policy CurrentPolicy() { |
- return scheduler_->MainThreadOnly().current_policy_; |
+ UseCase CurrentUseCase() { |
+ return scheduler_->MainThreadOnly().current_use_case_; |
+ } |
+ |
+ UseCase ForceUpdatePolicyAndGetCurrentUseCase() { |
+ scheduler_->ForceUpdatePolicy(); |
+ return scheduler_->MainThreadOnly().current_use_case_; |
+ } |
+ |
+ bool ScrollExpectedSoon() { |
+ return scheduler_->MainThreadOnly().scroll_expected_soon_; |
} |
// Helper for posting several tasks of specific types. |task_descriptor| is a |
@@ -309,6 +349,11 @@ class RendererSchedulerImplTest : public testing::Test { |
RendererSchedulerImpl::kPriorityEscalationAfterInputMillis); |
} |
+ static base::TimeDelta subsequent_input_expected_after_input_duration() { |
+ return base::TimeDelta::FromMilliseconds( |
+ RendererSchedulerImpl::kExpectSubsequentInputMillis); |
+ } |
+ |
static base::TimeDelta maximum_idle_period_duration() { |
return base::TimeDelta::FromMilliseconds( |
IdleHelper::kMaximumIdlePeriodMillis); |
@@ -334,11 +379,11 @@ class RendererSchedulerImplTest : public testing::Test { |
} |
} |
- static void CheckAllPolicyToString() { |
- CallForEachEnumValue<RendererSchedulerImpl::Policy>( |
- RendererSchedulerImpl::Policy::FIRST_POLICY, |
- RendererSchedulerImpl::Policy::POLICY_COUNT, |
- &RendererSchedulerImpl::PolicyToString); |
+ static void CheckAllUseCaseToString() { |
+ CallForEachEnumValue<RendererSchedulerImpl::UseCase>( |
+ RendererSchedulerImpl::UseCase::FIRST_USE_CASE, |
+ RendererSchedulerImpl::UseCase::USE_CASE_COUNT, |
+ &RendererSchedulerImpl::UseCaseToString); |
} |
scoped_ptr<base::SimpleTestTickClock> clock_; |
@@ -637,9 +682,12 @@ TEST_F( |
PostTestTasks(&run_order, "C1 T1"); |
scheduler_->DidAnimateForInputOnCompositorThread(); |
- scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create( |
+ cc::BeginFrameArgs begin_frame_args1 = cc::BeginFrameArgs::Create( |
BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(), |
- base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL)); |
+ base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL); |
+ begin_frame_args1.on_critical_path = true; |
+ scheduler_->WillBeginFrame(begin_frame_args1); |
+ scheduler_->DidCommitFrameToCompositor(); // Starts Idle Period |
RunUntilIdle(); |
EXPECT_THAT(run_order, testing::ElementsAre(std::string("C1"))); |
@@ -793,28 +841,32 @@ TEST_F(RendererSchedulerImplTest, TestTouchstartPolicy_MainThread) { |
TEST_F(RendererSchedulerImplTest, LoadingPriorityPolicy) { |
std::vector<std::string> run_order; |
- PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2"); |
+ PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2"); |
scheduler_->OnPageLoadStarted(); |
EnableIdleTasks(); |
RunUntilIdle(); |
- // In loading policy compositor tasks are best effort and should be run last. |
- EXPECT_THAT(run_order, |
- testing::ElementsAre(std::string("L1"), std::string("D1"), |
- std::string("D2"), std::string("I1"), |
- std::string("C1"), std::string("C2"))); |
+ |
+ // In loading policy, loading and timer tasks are prioritized other others. |
+ std::string loading_policy_expected[] = { |
+ std::string("T1"), std::string("L1"), std::string("T2"), |
+ std::string("L2"), std::string("D1"), std::string("C1"), |
+ std::string("D2"), std::string("C2"), std::string("I1")}; |
+ EXPECT_THAT(run_order, testing::ElementsAreArray(loading_policy_expected)); |
// Advance 1.5s and try again, the loading policy should have ended and the |
- // task order should return to normal. |
+ // task order should return to the NOT_SCROLLING use case where loading tasks |
+ // are prioritized. |
clock_->Advance(base::TimeDelta::FromMilliseconds(1500)); |
run_order.clear(); |
- PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2"); |
+ PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2"); |
EnableIdleTasks(); |
RunUntilIdle(); |
- EXPECT_THAT(run_order, |
- testing::ElementsAre(std::string("L1"), std::string("D1"), |
- std::string("C1"), std::string("D2"), |
- std::string("C2"), std::string("I1"))); |
+ std::string default_order_expected[] = { |
+ std::string("L1"), std::string("L2"), std::string("D1"), |
+ std::string("C1"), std::string("T1"), std::string("D2"), |
+ std::string("C2"), std::string("T2"), std::string("I1")}; |
+ EXPECT_THAT(run_order, testing::ElementsAreArray(default_order_expected)); |
} |
TEST_F(RendererSchedulerImplTest, |
@@ -962,7 +1014,9 @@ TEST_F(RendererSchedulerImplTest, |
} |
TEST_F(RendererSchedulerImplTest, |
- TestCompositorPolicyDoesNotStarveDefaultTasks) { |
+ TestMainthreadScrollingUseCaseDoesNotStarveDefaultTasks) { |
+ ForceMainthreadScrollingUseCase(); |
+ |
std::vector<std::string> run_order; |
PostTestTasks(&run_order, "D1 C1"); |
@@ -984,52 +1038,28 @@ TEST_F(RendererSchedulerImplTest, |
TEST_F(RendererSchedulerImplTest, |
TestCompositorPolicyEnds_CompositorHandlesInput) { |
- std::vector<std::string> run_order; |
- PostTestTasks(&run_order, "D1 C1 D2 C2"); |
- |
scheduler_->DidHandleInputEventOnCompositorThread( |
FakeInputEvent(blink::WebInputEvent::GestureFlingStart), |
RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); |
- RunUntilIdle(); |
- EXPECT_THAT(run_order, |
- testing::ElementsAre(std::string("C1"), std::string("C2"), |
- std::string("D1"), std::string("D2"))); |
+ EXPECT_EQ(UseCase::COMPOSITOR_SCROLLING, |
+ ForceUpdatePolicyAndGetCurrentUseCase()); |
- run_order.clear(); |
clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); |
- PostTestTasks(&run_order, "D1 C1 D2 C2"); |
- |
- // Compositor policy mode should have ended now that the clock has advanced. |
- RunUntilIdle(); |
- EXPECT_THAT(run_order, |
- testing::ElementsAre(std::string("D1"), std::string("C1"), |
- std::string("D2"), std::string("C2"))); |
+ EXPECT_EQ(UseCase::NOT_SCROLLING, ForceUpdatePolicyAndGetCurrentUseCase()); |
} |
TEST_F(RendererSchedulerImplTest, |
TestCompositorPolicyEnds_MainThreadHandlesInput) { |
- std::vector<std::string> run_order; |
- PostTestTasks(&run_order, "D1 C1 D2 C2"); |
- |
scheduler_->DidHandleInputEventOnCompositorThread( |
FakeInputEvent(blink::WebInputEvent::GestureFlingStart), |
RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD); |
scheduler_->DidHandleInputEventOnMainThread( |
FakeInputEvent(blink::WebInputEvent::GestureFlingStart)); |
- RunUntilIdle(); |
- EXPECT_THAT(run_order, |
- testing::ElementsAre(std::string("C1"), std::string("C2"), |
- std::string("D1"), std::string("D2"))); |
+ EXPECT_EQ(UseCase::COMPOSITOR_SCROLLING, |
+ ForceUpdatePolicyAndGetCurrentUseCase()); |
- run_order.clear(); |
clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); |
- PostTestTasks(&run_order, "D1 C1 D2 C2"); |
- |
- // Compositor policy mode should have ended now that the clock has advanced. |
- RunUntilIdle(); |
- EXPECT_THAT(run_order, |
- testing::ElementsAre(std::string("D1"), std::string("C1"), |
- std::string("D2"), std::string("C2"))); |
+ EXPECT_EQ(UseCase::NOT_SCROLLING, ForceUpdatePolicyAndGetCurrentUseCase()); |
} |
TEST_F(RendererSchedulerImplTest, TestTouchstartPolicyEndsAfterTimeout) { |
@@ -1093,22 +1123,25 @@ TEST_F(RendererSchedulerImplTest, TestIsHighPriorityWorkAnticipated) { |
bool is_anticipated_before = false; |
bool is_anticipated_after = false; |
- bool simulate_input = false; |
default_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&AnticipationTestTask, scheduler_.get(), simulate_input, |
- &is_anticipated_before, &is_anticipated_after)); |
+ FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(), |
+ SimulateInputType::None, &is_anticipated_before, |
+ &is_anticipated_after)); |
RunUntilIdle(); |
// In its default state, without input receipt, the scheduler should indicate |
// that no high-priority is anticipated. |
EXPECT_FALSE(is_anticipated_before); |
EXPECT_FALSE(is_anticipated_after); |
- simulate_input = true; |
default_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&AnticipationTestTask, scheduler_.get(), simulate_input, |
- &is_anticipated_before, &is_anticipated_after)); |
+ FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(), |
+ SimulateInputType::TouchStart, |
+ &is_anticipated_before, &is_anticipated_after)); |
+ bool dummy; |
+ default_task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(), |
+ SimulateInputType::TouchEnd, &dummy, &dummy)); |
+ |
RunUntilIdle(); |
// When input is received, the scheduler should indicate that high-priority |
// work is anticipated. |
@@ -1116,14 +1149,29 @@ TEST_F(RendererSchedulerImplTest, TestIsHighPriorityWorkAnticipated) { |
EXPECT_TRUE(is_anticipated_after); |
clock_->Advance(priority_escalation_after_input_duration() * 2); |
- simulate_input = false; |
default_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&AnticipationTestTask, scheduler_.get(), simulate_input, |
- &is_anticipated_before, &is_anticipated_after)); |
- RunUntilIdle(); |
- // Without additional input, the scheduler should indicate that high-priority |
- // work is no longer anticipated. |
+ FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(), |
+ SimulateInputType::None, &is_anticipated_before, |
+ &is_anticipated_after)); |
+ RunUntilIdle(); |
+ // Without additional input, the scheduler should go into NOT_SCROLLING |
+ // use case but with scrolling expected where high-priority work is still |
+ // anticipated. |
+ EXPECT_EQ(UseCase::NOT_SCROLLING, CurrentUseCase()); |
+ EXPECT_TRUE(ScrollExpectedSoon()); |
+ EXPECT_TRUE(is_anticipated_before); |
+ EXPECT_TRUE(is_anticipated_after); |
+ |
+ clock_->Advance(subsequent_input_expected_after_input_duration() * 2); |
+ default_task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(), |
+ SimulateInputType::None, &is_anticipated_before, |
+ &is_anticipated_after)); |
+ RunUntilIdle(); |
+ // Eventually the scheduler should go into the default use case where |
+ // high-priority work is no longer anticipated. |
+ EXPECT_EQ(UseCase::NOT_SCROLLING, CurrentUseCase()); |
+ EXPECT_FALSE(ScrollExpectedSoon()); |
EXPECT_FALSE(is_anticipated_before); |
EXPECT_FALSE(is_anticipated_after); |
} |
@@ -1132,6 +1180,8 @@ TEST_F(RendererSchedulerImplTest, TestShouldYield) { |
bool should_yield_before = false; |
bool should_yield_after = false; |
+ ForceMainthreadScrollingUseCase(); |
+ |
default_task_runner_->PostTask( |
FROM_HERE, base::Bind(&PostingYieldingTestTask, scheduler_.get(), |
default_task_runner_, false, &should_yield_before, |
@@ -1146,7 +1196,7 @@ TEST_F(RendererSchedulerImplTest, TestShouldYield) { |
compositor_task_runner_, false, |
&should_yield_before, &should_yield_after)); |
RunUntilIdle(); |
- // Posting while not in compositor priority shouldn't cause yielding. |
+ // Posting while not mainthread scrolling shouldn't cause yielding. |
EXPECT_FALSE(should_yield_before); |
EXPECT_FALSE(should_yield_after); |
@@ -1170,14 +1220,14 @@ TEST_F(RendererSchedulerImplTest, TestShouldYield) { |
} |
TEST_F(RendererSchedulerImplTest, SlowMainThreadInputEvent) { |
- EXPECT_EQ(Policy::NORMAL, CurrentPolicy()); |
+ EXPECT_EQ(UseCase::NOT_SCROLLING, CurrentUseCase()); |
// An input event should bump us into input priority. |
scheduler_->DidHandleInputEventOnCompositorThread( |
FakeInputEvent(blink::WebInputEvent::GestureFlingStart), |
RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD); |
RunUntilIdle(); |
- EXPECT_EQ(Policy::COMPOSITOR_PRIORITY, CurrentPolicy()); |
+ EXPECT_EQ(UseCase::COMPOSITOR_SCROLLING, CurrentUseCase()); |
// Simulate the input event being queued for a very long time. The compositor |
// task we post here represents the enqueued input task. |
@@ -1188,12 +1238,12 @@ TEST_F(RendererSchedulerImplTest, SlowMainThreadInputEvent) { |
// Even though we exceeded the input priority escalation period, we should |
// still be in compositor priority since the input remains queued. |
- EXPECT_EQ(Policy::COMPOSITOR_PRIORITY, CurrentPolicy()); |
+ EXPECT_EQ(UseCase::COMPOSITOR_SCROLLING, CurrentUseCase()); |
// After the escalation period ends we should go back into normal mode. |
clock_->Advance(priority_escalation_after_input_duration() * 2); |
RunUntilIdle(); |
- EXPECT_EQ(Policy::NORMAL, CurrentPolicy()); |
+ EXPECT_EQ(UseCase::NOT_SCROLLING, CurrentUseCase()); |
} |
class RendererSchedulerImplWithMockSchedulerTest |
@@ -1396,10 +1446,15 @@ TEST_F(RendererSchedulerImplWithMockSchedulerTest, |
EXPECT_EQ(1, mock_scheduler_->update_policy_count_); |
- RunUntilIdle(); |
// We expect both the urgent and the delayed updates to run in addition to the |
- // earlier updated cause by IsHighPriorityWorkAnticipated. |
- EXPECT_EQ(3, mock_scheduler_->update_policy_count_); |
+ // earlier updated cause by IsHighPriorityWorkAnticipated, a final update |
+ // transitions from 'not_scrolling scroll expected' to 'not_scrolling'. |
+ RunUntilIdle(); |
+ EXPECT_THAT( |
+ mock_scheduler_->use_cases_, |
+ testing::ElementsAre(std::string("touchstart"), std::string("touchstart"), |
+ std::string("not_scrolling scroll expected"), |
+ std::string("not_scrolling"))); |
} |
class RendererSchedulerImplWithMessageLoopTest |
@@ -1754,8 +1809,8 @@ TEST_F(RendererSchedulerImplTest, MultipleSuspendsNeedMultipleResumes) { |
testing::ElementsAre(std::string("T1"), std::string("T2"))); |
} |
-TEST_F(RendererSchedulerImplTest, PolicyToString) { |
- CheckAllPolicyToString(); |
+TEST_F(RendererSchedulerImplTest, UseCaseToString) { |
+ CheckAllUseCaseToString(); |
} |
TEST_F(RendererSchedulerImplTest, MismatchedDidHandleInputEventOnMainThread) { |