| 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
|
| deleted file mode 100644
|
| index 0ee313bdbbd73785781337d97ac016771caa882d..0000000000000000000000000000000000000000
|
| --- a/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc
|
| +++ /dev/null
|
| @@ -1,3448 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "components/scheduler/renderer/renderer_scheduler_impl.h"
|
| -
|
| -#include <utility>
|
| -
|
| -#include "base/callback.h"
|
| -#include "base/macros.h"
|
| -#include "base/memory/ptr_util.h"
|
| -#include "base/run_loop.h"
|
| -#include "base/test/simple_test_tick_clock.h"
|
| -#include "cc/output/begin_frame_args.h"
|
| -#include "cc/test/ordered_simple_task_runner.h"
|
| -#include "components/scheduler/base/test_time_source.h"
|
| -#include "components/scheduler/child/scheduler_tqm_delegate_for_test.h"
|
| -#include "components/scheduler/child/scheduler_tqm_delegate_impl.h"
|
| -#include "components/scheduler/renderer/auto_advancing_virtual_time_domain.h"
|
| -#include "testing/gmock/include/gmock/gmock.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -namespace scheduler {
|
| -
|
| -namespace {
|
| -class FakeInputEvent : public blink::WebInputEvent {
|
| - public:
|
| - explicit FakeInputEvent(blink::WebInputEvent::Type event_type)
|
| - : WebInputEvent(sizeof(FakeInputEvent)) {
|
| - type = event_type;
|
| - }
|
| -
|
| - FakeInputEvent(blink::WebInputEvent::Type event_type, int event_modifiers)
|
| - : WebInputEvent(sizeof(FakeInputEvent)) {
|
| - type = event_type;
|
| - modifiers = event_modifiers;
|
| - }
|
| -};
|
| -
|
| -void AppendToVectorTestTask(std::vector<std::string>* vector,
|
| - std::string value) {
|
| - vector->push_back(value);
|
| -}
|
| -
|
| -void AppendToVectorIdleTestTask(std::vector<std::string>* vector,
|
| - std::string value,
|
| - base::TimeTicks deadline) {
|
| - AppendToVectorTestTask(vector, value);
|
| -}
|
| -
|
| -void NullTask() {
|
| -}
|
| -
|
| -void AppendToVectorReentrantTask(base::SingleThreadTaskRunner* task_runner,
|
| - std::vector<int>* vector,
|
| - int* reentrant_count,
|
| - int max_reentrant_count) {
|
| - vector->push_back((*reentrant_count)++);
|
| - if (*reentrant_count < max_reentrant_count) {
|
| - task_runner->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(AppendToVectorReentrantTask, base::Unretained(task_runner),
|
| - vector, reentrant_count, max_reentrant_count));
|
| - }
|
| -}
|
| -
|
| -void IdleTestTask(int* run_count,
|
| - base::TimeTicks* deadline_out,
|
| - base::TimeTicks deadline) {
|
| - (*run_count)++;
|
| - *deadline_out = deadline;
|
| -}
|
| -
|
| -int max_idle_task_reposts = 2;
|
| -
|
| -void RepostingIdleTestTask(SingleThreadIdleTaskRunner* idle_task_runner,
|
| - int* run_count,
|
| - base::TimeTicks deadline) {
|
| - if ((*run_count + 1) < max_idle_task_reposts) {
|
| - idle_task_runner->PostIdleTask(
|
| - FROM_HERE, base::Bind(&RepostingIdleTestTask,
|
| - base::Unretained(idle_task_runner), run_count));
|
| - }
|
| - (*run_count)++;
|
| -}
|
| -
|
| -void RepostingUpdateClockIdleTestTask(
|
| - SingleThreadIdleTaskRunner* idle_task_runner,
|
| - int* run_count,
|
| - base::SimpleTestTickClock* clock,
|
| - base::TimeDelta advance_time,
|
| - std::vector<base::TimeTicks>* deadlines,
|
| - base::TimeTicks deadline) {
|
| - if ((*run_count + 1) < max_idle_task_reposts) {
|
| - idle_task_runner->PostIdleTask(
|
| - FROM_HERE, base::Bind(&RepostingUpdateClockIdleTestTask,
|
| - base::Unretained(idle_task_runner), run_count,
|
| - clock, advance_time, deadlines));
|
| - }
|
| - deadlines->push_back(deadline);
|
| - (*run_count)++;
|
| - clock->Advance(advance_time);
|
| -}
|
| -
|
| -void WillBeginFrameIdleTask(RendererScheduler* scheduler,
|
| - base::SimpleTestTickClock* clock,
|
| - base::TimeTicks deadline) {
|
| - scheduler->WillBeginFrame(cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
|
| -}
|
| -
|
| -void UpdateClockToDeadlineIdleTestTask(base::SimpleTestTickClock* clock,
|
| - int* run_count,
|
| - base::TimeTicks deadline) {
|
| - clock->Advance(deadline - clock->NowTicks());
|
| - (*run_count)++;
|
| -}
|
| -
|
| -void PostingYieldingTestTask(RendererSchedulerImpl* scheduler,
|
| - base::SingleThreadTaskRunner* task_runner,
|
| - bool simulate_input,
|
| - bool* should_yield_before,
|
| - bool* should_yield_after) {
|
| - *should_yield_before = scheduler->ShouldYieldForHighPriorityWork();
|
| - task_runner->PostTask(FROM_HERE, base::Bind(NullTask));
|
| - if (simulate_input) {
|
| - scheduler->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - }
|
| - *should_yield_after = scheduler->ShouldYieldForHighPriorityWork();
|
| -}
|
| -
|
| -enum class SimulateInputType {
|
| - None,
|
| - TouchStart,
|
| - TouchEnd,
|
| - GestureScrollBegin,
|
| - GestureScrollEnd
|
| -};
|
| -
|
| -void AnticipationTestTask(RendererSchedulerImpl* scheduler,
|
| - SimulateInputType simulate_input,
|
| - bool* is_anticipated_before,
|
| - bool* is_anticipated_after) {
|
| - *is_anticipated_before = scheduler->IsHighPriorityWorkAnticipated();
|
| - 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;
|
| -
|
| - case SimulateInputType::GestureScrollBegin:
|
| - scheduler->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollBegin),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - break;
|
| -
|
| - case SimulateInputType::GestureScrollEnd:
|
| - scheduler->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollEnd),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - break;
|
| - }
|
| - *is_anticipated_after = scheduler->IsHighPriorityWorkAnticipated();
|
| -}
|
| -
|
| -}; // namespace
|
| -
|
| -class RendererSchedulerImplForTest : public RendererSchedulerImpl {
|
| - public:
|
| - using RendererSchedulerImpl::OnIdlePeriodEnded;
|
| - using RendererSchedulerImpl::OnIdlePeriodStarted;
|
| - using RendererSchedulerImpl::EstimateLongestJankFreeTaskDuration;
|
| -
|
| - RendererSchedulerImplForTest(
|
| - scoped_refptr<SchedulerTqmDelegate> main_task_runner)
|
| - : RendererSchedulerImpl(main_task_runner), update_policy_count_(0) {}
|
| -
|
| - void UpdatePolicyLocked(UpdateType update_type) override {
|
| - update_policy_count_++;
|
| - RendererSchedulerImpl::UpdatePolicyLocked(update_type);
|
| -
|
| - std::string use_case = RendererSchedulerImpl::UseCaseToString(
|
| - MainThreadOnly().current_use_case);
|
| - if (MainThreadOnly().touchstart_expected_soon) {
|
| - use_cases_.push_back(use_case + " touchstart expected");
|
| - } else {
|
| - use_cases_.push_back(use_case);
|
| - }
|
| - }
|
| -
|
| - void EnsureUrgentPolicyUpdatePostedOnMainThread() {
|
| - base::AutoLock lock(any_thread_lock_);
|
| - RendererSchedulerImpl::EnsureUrgentPolicyUpdatePostedOnMainThread(
|
| - FROM_HERE);
|
| - }
|
| -
|
| - void ScheduleDelayedPolicyUpdate(base::TimeTicks now, base::TimeDelta delay) {
|
| - delayed_update_policy_runner_.SetDeadline(FROM_HERE, delay, now);
|
| - }
|
| -
|
| - bool BeginMainFrameOnCriticalPath() {
|
| - base::AutoLock lock(any_thread_lock_);
|
| - return AnyThread().begin_main_frame_on_critical_path;
|
| - }
|
| -
|
| - int update_policy_count_;
|
| - std::vector<std::string> use_cases_;
|
| -};
|
| -
|
| -// Lets gtest print human readable Policy values.
|
| -::std::ostream& operator<<(::std::ostream& os,
|
| - const RendererSchedulerImpl::UseCase& use_case) {
|
| - return os << RendererSchedulerImpl::UseCaseToString(use_case);
|
| -}
|
| -
|
| -class RendererSchedulerImplTest : public testing::Test {
|
| - public:
|
| - using UseCase = RendererSchedulerImpl::UseCase;
|
| -
|
| - RendererSchedulerImplTest() : clock_(new base::SimpleTestTickClock()) {
|
| - clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
|
| - }
|
| -
|
| - RendererSchedulerImplTest(base::MessageLoop* message_loop)
|
| - : clock_(new base::SimpleTestTickClock()), message_loop_(message_loop) {
|
| - clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
|
| - }
|
| -
|
| - ~RendererSchedulerImplTest() override {}
|
| -
|
| - void SetUp() override {
|
| - if (message_loop_) {
|
| - main_task_runner_ = SchedulerTqmDelegateImpl::Create(
|
| - message_loop_.get(),
|
| - base::WrapUnique(new TestTimeSource(clock_.get())));
|
| - } else {
|
| - mock_task_runner_ = make_scoped_refptr(
|
| - new cc::OrderedSimpleTaskRunner(clock_.get(), false));
|
| - main_task_runner_ = SchedulerTqmDelegateForTest::Create(
|
| - mock_task_runner_,
|
| - base::WrapUnique(new TestTimeSource(clock_.get())));
|
| - }
|
| - Initialize(
|
| - base::WrapUnique(new RendererSchedulerImplForTest(main_task_runner_)));
|
| - }
|
| -
|
| - void Initialize(std::unique_ptr<RendererSchedulerImplForTest> scheduler) {
|
| - scheduler_ = std::move(scheduler);
|
| - default_task_runner_ = scheduler_->DefaultTaskRunner();
|
| - compositor_task_runner_ = scheduler_->CompositorTaskRunner();
|
| - loading_task_runner_ = scheduler_->LoadingTaskRunner();
|
| - idle_task_runner_ = scheduler_->IdleTaskRunner();
|
| - timer_task_runner_ = scheduler_->TimerTaskRunner();
|
| - }
|
| -
|
| - void TearDown() override {
|
| - DCHECK(!mock_task_runner_.get() || !message_loop_.get());
|
| - scheduler_->Shutdown();
|
| - if (mock_task_runner_.get()) {
|
| - // Check that all tests stop posting tasks.
|
| - mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
|
| - while (mock_task_runner_->RunUntilIdle()) {
|
| - }
|
| - } else {
|
| - base::RunLoop().RunUntilIdle();
|
| - }
|
| - scheduler_.reset();
|
| - }
|
| -
|
| - void RunUntilIdle() {
|
| - // Only one of mock_task_runner_ or message_loop_ should be set.
|
| - DCHECK(!mock_task_runner_.get() || !message_loop_.get());
|
| - if (mock_task_runner_.get())
|
| - mock_task_runner_->RunUntilIdle();
|
| - else
|
| - base::RunLoop().RunUntilIdle();
|
| - }
|
| -
|
| - void DoMainFrame() {
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = false;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - scheduler_->DidCommitFrameToCompositor();
|
| - }
|
| -
|
| - void DoMainFrameOnCriticalPath() {
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - }
|
| -
|
| - void ForceTouchStartToBeExpectedSoon() {
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollUpdate),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollEnd),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - clock_->Advance(priority_escalation_after_input_duration() * 2);
|
| - scheduler_->ForceUpdatePolicy();
|
| - }
|
| -
|
| - void SimulateExpensiveTasks(
|
| - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
|
| - // RunUntilIdle won't actually run all of the SimpleTestTickClock::Advance
|
| - // tasks unless we set AutoAdvanceNow to true :/
|
| - mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
|
| -
|
| - // Simulate a bunch of expensive tasks
|
| - for (int i = 0; i < 10; i++) {
|
| - task_runner->PostTask(FROM_HERE,
|
| - base::Bind(&base::SimpleTestTickClock::Advance,
|
| - base::Unretained(clock_.get()),
|
| - base::TimeDelta::FromMilliseconds(500)));
|
| - }
|
| -
|
| - RunUntilIdle();
|
| -
|
| - // Switch back to not auto-advancing because we want to be in control of
|
| - // when time advances.
|
| - mock_task_runner_->SetAutoAdvanceNowToPendingTasks(false);
|
| - }
|
| -
|
| - enum class TouchEventPolicy {
|
| - SEND_TOUCH_START,
|
| - DONT_SEND_TOUCH_START,
|
| - };
|
| -
|
| - void SimulateCompositorGestureStart(TouchEventPolicy touch_event_policy) {
|
| - if (touch_event_policy == TouchEventPolicy::SEND_TOUCH_START) {
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - }
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollBegin),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollUpdate),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - }
|
| -
|
| - // Simulate a gesture where there is an active compositor scroll, but no
|
| - // scroll updates are generated. Instead, the main thread handles
|
| - // non-canceleable touch events, making this an effectively main thread
|
| - // driven gesture.
|
| - void SimulateMainThreadGestureWithoutScrollUpdates() {
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollBegin),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - }
|
| -
|
| - // Simulate a gesture where the main thread handles touch events but does not
|
| - // preventDefault(), allowing the gesture to turn into a compositor driven
|
| - // gesture. This function also verifies the necessary policy updates are
|
| - // scheduled.
|
| - void SimulateMainThreadGestureWithoutPreventDefault() {
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| -
|
| - // Touchstart policy update.
|
| - EXPECT_TRUE(scheduler_->PolicyNeedsUpdateForTesting());
|
| - EXPECT_EQ(UseCase::TOUCHSTART, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_FALSE(scheduler_->PolicyNeedsUpdateForTesting());
|
| -
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureTapCancel),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollBegin),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| -
|
| - // Main thread gesture policy update.
|
| - EXPECT_TRUE(scheduler_->PolicyNeedsUpdateForTesting());
|
| - EXPECT_EQ(UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_FALSE(scheduler_->PolicyNeedsUpdateForTesting());
|
| -
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollUpdate),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchScrollStarted),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| -
|
| - // Compositor thread gesture policy update.
|
| - EXPECT_TRUE(scheduler_->PolicyNeedsUpdateForTesting());
|
| - EXPECT_EQ(UseCase::COMPOSITOR_GESTURE,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_FALSE(scheduler_->PolicyNeedsUpdateForTesting());
|
| - }
|
| -
|
| - void SimulateMainThreadGestureStart(TouchEventPolicy touch_event_policy,
|
| - blink::WebInputEvent::Type gesture_type) {
|
| - if (touch_event_policy == TouchEventPolicy::SEND_TOUCH_START) {
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart));
|
| -
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove));
|
| -
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove));
|
| - }
|
| - if (gesture_type != blink::WebInputEvent::Undefined) {
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(gesture_type),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnMainThread(FakeInputEvent(gesture_type));
|
| - }
|
| - }
|
| -
|
| - void SimulateMainThreadInputHandlingCompositorTask(
|
| - base::TimeDelta begin_main_frame_duration) {
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - clock_->Advance(begin_main_frame_duration);
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove));
|
| - scheduler_->DidCommitFrameToCompositor();
|
| - }
|
| -
|
| - void SimulateMainThreadCompositorTask(
|
| - base::TimeDelta begin_main_frame_duration) {
|
| - clock_->Advance(begin_main_frame_duration);
|
| - scheduler_->DidCommitFrameToCompositor();
|
| - simulate_compositor_task_ran_ = true;
|
| - }
|
| -
|
| - bool SimulatedCompositorTaskPending() const {
|
| - return !simulate_compositor_task_ran_;
|
| - }
|
| -
|
| - void SimulateTimerTask(base::TimeDelta duration) {
|
| - clock_->Advance(duration);
|
| - simulate_timer_task_ran_ = true;
|
| - }
|
| -
|
| - void EnableIdleTasks() { DoMainFrame(); }
|
| -
|
| - UseCase CurrentUseCase() {
|
| - return scheduler_->MainThreadOnly().current_use_case;
|
| - }
|
| -
|
| - UseCase ForceUpdatePolicyAndGetCurrentUseCase() {
|
| - scheduler_->ForceUpdatePolicy();
|
| - return scheduler_->MainThreadOnly().current_use_case;
|
| - }
|
| -
|
| - v8::RAILMode RAILMode() {
|
| - return scheduler_->MainThreadOnly().current_policy.rail_mode;
|
| - }
|
| -
|
| - bool BeginFrameNotExpectedSoon() {
|
| - return scheduler_->MainThreadOnly().begin_frame_not_expected_soon;
|
| - }
|
| -
|
| - bool TouchStartExpectedSoon() {
|
| - return scheduler_->MainThreadOnly().touchstart_expected_soon;
|
| - }
|
| -
|
| - bool HaveSeenABeginMainframe() {
|
| - return scheduler_->MainThreadOnly().have_seen_a_begin_main_frame;
|
| - }
|
| -
|
| - bool LoadingTasksSeemExpensive() {
|
| - return scheduler_->MainThreadOnly().loading_tasks_seem_expensive;
|
| - }
|
| -
|
| - bool TimerTasksSeemExpensive() {
|
| - return scheduler_->MainThreadOnly().timer_tasks_seem_expensive;
|
| - }
|
| -
|
| - base::TimeTicks EstimatedNextFrameBegin() {
|
| - return scheduler_->MainThreadOnly().estimated_next_frame_begin;
|
| - }
|
| -
|
| - int NavigationTaskExpectedCount() {
|
| - return scheduler_->MainThreadOnly().navigation_task_expected_count;
|
| - }
|
| -
|
| - // Helper for posting several tasks of specific types. |task_descriptor| is a
|
| - // string with space delimited task identifiers. The first letter of each
|
| - // task identifier specifies the task type:
|
| - // - 'D': Default task
|
| - // - 'C': Compositor task
|
| - // - 'L': Loading task
|
| - // - 'I': Idle task
|
| - // - 'T': Timer task
|
| - void PostTestTasks(std::vector<std::string>* run_order,
|
| - const std::string& task_descriptor) {
|
| - std::istringstream stream(task_descriptor);
|
| - while (!stream.eof()) {
|
| - std::string task;
|
| - stream >> task;
|
| - switch (task[0]) {
|
| - case 'D':
|
| - default_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&AppendToVectorTestTask, run_order, task));
|
| - break;
|
| - case 'C':
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&AppendToVectorTestTask, run_order, task));
|
| - break;
|
| - case 'L':
|
| - loading_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&AppendToVectorTestTask, run_order, task));
|
| - break;
|
| - case 'I':
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE,
|
| - base::Bind(&AppendToVectorIdleTestTask, run_order, task));
|
| - break;
|
| - case 'T':
|
| - timer_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&AppendToVectorTestTask, run_order, task));
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - }
|
| - }
|
| - }
|
| -
|
| - protected:
|
| - static base::TimeDelta priority_escalation_after_input_duration() {
|
| - return base::TimeDelta::FromMilliseconds(
|
| - UserModel::kGestureEstimationLimitMillis);
|
| - }
|
| -
|
| - static base::TimeDelta subsequent_input_expected_after_input_duration() {
|
| - return base::TimeDelta::FromMilliseconds(
|
| - UserModel::kExpectSubsequentGestureMillis);
|
| - }
|
| -
|
| - static base::TimeDelta maximum_idle_period_duration() {
|
| - return base::TimeDelta::FromMilliseconds(
|
| - IdleHelper::kMaximumIdlePeriodMillis);
|
| - }
|
| -
|
| - static base::TimeDelta end_idle_when_hidden_delay() {
|
| - return base::TimeDelta::FromMilliseconds(
|
| - RendererSchedulerImpl::kEndIdleWhenHiddenDelayMillis);
|
| - }
|
| -
|
| - static base::TimeDelta idle_period_starvation_threshold() {
|
| - return base::TimeDelta::FromMilliseconds(
|
| - RendererSchedulerImpl::kIdlePeriodStarvationThresholdMillis);
|
| - }
|
| -
|
| - static base::TimeDelta suspend_timers_when_backgrounded_delay() {
|
| - return base::TimeDelta::FromMilliseconds(
|
| - RendererSchedulerImpl::kSuspendTimersWhenBackgroundedDelayMillis);
|
| - }
|
| -
|
| - static base::TimeDelta rails_response_time() {
|
| - return base::TimeDelta::FromMilliseconds(
|
| - RendererSchedulerImpl::kRailsResponseTimeMillis);
|
| - }
|
| -
|
| - template <typename E>
|
| - static void CallForEachEnumValue(E first,
|
| - E last,
|
| - const char* (*function)(E)) {
|
| - for (E val = first; val < last;
|
| - val = static_cast<E>(static_cast<int>(val) + 1)) {
|
| - (*function)(val);
|
| - }
|
| - }
|
| -
|
| - static void CheckAllUseCaseToString() {
|
| - CallForEachEnumValue<RendererSchedulerImpl::UseCase>(
|
| - RendererSchedulerImpl::UseCase::FIRST_USE_CASE,
|
| - RendererSchedulerImpl::UseCase::USE_CASE_COUNT,
|
| - &RendererSchedulerImpl::UseCaseToString);
|
| - }
|
| -
|
| - std::unique_ptr<base::SimpleTestTickClock> clock_;
|
| - // Only one of mock_task_runner_ or message_loop_ will be set.
|
| - scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
|
| - std::unique_ptr<base::MessageLoop> message_loop_;
|
| -
|
| - scoped_refptr<SchedulerTqmDelegate> main_task_runner_;
|
| - std::unique_ptr<RendererSchedulerImplForTest> scheduler_;
|
| - scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
|
| - scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
|
| - scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_;
|
| - scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
|
| - scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner_;
|
| - bool simulate_timer_task_ran_;
|
| - bool simulate_compositor_task_ran_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest);
|
| -};
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestPostDefaultTask) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "D1 D2 D3 D4");
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("D1"), std::string("D2"),
|
| - std::string("D3"), std::string("D4")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestPostDefaultAndCompositor) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "D1 C1");
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order, testing::Contains("D1"));
|
| - EXPECT_THAT(run_order, testing::Contains("C1"));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestRentrantTask) {
|
| - int count = 0;
|
| - std::vector<int> run_order;
|
| - default_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(AppendToVectorReentrantTask,
|
| - base::RetainedRef(default_task_runner_), &run_order,
|
| - &count, 5));
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_THAT(run_order, testing::ElementsAre(0, 1, 2, 3, 4));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestPostIdleTask) {
|
| - int run_count = 0;
|
| - base::TimeTicks expected_deadline =
|
| - clock_->NowTicks() + base::TimeDelta::FromMilliseconds(2300);
|
| - base::TimeTicks deadline_in_task;
|
| -
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(100));
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_EQ(0, run_count); // Shouldn't run yet as no WillBeginFrame.
|
| -
|
| - scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
|
| - RunUntilIdle();
|
| - EXPECT_EQ(0, run_count); // Shouldn't run as no DidCommitFrameToCompositor.
|
| -
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(1200));
|
| - scheduler_->DidCommitFrameToCompositor();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(0, run_count); // We missed the deadline.
|
| -
|
| - scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(800));
|
| - scheduler_->DidCommitFrameToCompositor();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(1, run_count);
|
| - EXPECT_EQ(expected_deadline, deadline_in_task);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestRepostingIdleTask) {
|
| - int run_count = 0;
|
| -
|
| - max_idle_task_reposts = 2;
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&RepostingIdleTestTask,
|
| - base::RetainedRef(idle_task_runner_), &run_count));
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(1, run_count);
|
| -
|
| - // Reposted tasks shouldn't run until next idle period.
|
| - RunUntilIdle();
|
| - EXPECT_EQ(1, run_count);
|
| -
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(2, run_count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestIdleTaskExceedsDeadline) {
|
| - mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
|
| - int run_count = 0;
|
| -
|
| - // Post two UpdateClockToDeadlineIdleTestTask tasks.
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE,
|
| - base::Bind(&UpdateClockToDeadlineIdleTestTask, clock_.get(), &run_count));
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE,
|
| - base::Bind(&UpdateClockToDeadlineIdleTestTask, clock_.get(), &run_count));
|
| -
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - // Only the first idle task should execute since it's used up the deadline.
|
| - EXPECT_EQ(1, run_count);
|
| -
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - // Second task should be run on the next idle period.
|
| - EXPECT_EQ(2, run_count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestPostIdleTaskAfterWakeup) {
|
| - base::TimeTicks deadline_in_task;
|
| - int run_count = 0;
|
| -
|
| - idle_task_runner_->PostIdleTaskAfterWakeup(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| -
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - // Shouldn't run yet as no other task woke up the scheduler.
|
| - EXPECT_EQ(0, run_count);
|
| -
|
| - idle_task_runner_->PostIdleTaskAfterWakeup(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| -
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - // Another after wakeup idle task shouldn't wake the scheduler.
|
| - EXPECT_EQ(0, run_count);
|
| -
|
| - default_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask));
|
| -
|
| - RunUntilIdle();
|
| - EnableIdleTasks(); // Must start a new idle period before idle task runs.
|
| - RunUntilIdle();
|
| - // Execution of default task queue task should trigger execution of idle task.
|
| - EXPECT_EQ(2, run_count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestPostIdleTaskAfterWakeupWhileAwake) {
|
| - base::TimeTicks deadline_in_task;
|
| - int run_count = 0;
|
| -
|
| - idle_task_runner_->PostIdleTaskAfterWakeup(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| - default_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask));
|
| -
|
| - RunUntilIdle();
|
| - EnableIdleTasks(); // Must start a new idle period before idle task runs.
|
| - RunUntilIdle();
|
| - // Should run as the scheduler was already awakened by the normal task.
|
| - EXPECT_EQ(1, run_count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestPostIdleTaskWakesAfterWakeupIdleTask) {
|
| - base::TimeTicks deadline_in_task;
|
| - int run_count = 0;
|
| -
|
| - idle_task_runner_->PostIdleTaskAfterWakeup(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| -
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - // Must start a new idle period before after-wakeup idle task runs.
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - // Normal idle task should wake up after-wakeup idle task.
|
| - EXPECT_EQ(2, run_count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestDelayedEndIdlePeriodCanceled) {
|
| - int run_count = 0;
|
| -
|
| - base::TimeTicks deadline_in_task;
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| -
|
| - // Trigger the beginning of an idle period for 1000ms.
|
| - scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
|
| - DoMainFrame();
|
| -
|
| - // End the idle period early (after 500ms), and send a WillBeginFrame which
|
| - // specifies that the next idle period should end 1000ms from now.
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(500));
|
| - scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_EQ(0, run_count); // Not currently in an idle period.
|
| -
|
| - // Trigger the start of the idle period before the task to end the previous
|
| - // idle period has been triggered.
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(400));
|
| - scheduler_->DidCommitFrameToCompositor();
|
| -
|
| - // Post a task which simulates running until after the previous end idle
|
| - // period delayed task was scheduled for
|
| - scheduler_->DefaultTaskRunner()->PostTask(FROM_HERE, base::Bind(NullTask));
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(300));
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_EQ(1, run_count); // We should still be in the new idle period.
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestDefaultPolicy) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
|
| -
|
| - 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")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestCompositorPolicy_CompositorHandlesInput_WithTouchHandler) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - EnableIdleTasks();
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("D1"),
|
| - std::string("D2"), std::string("I1"),
|
| - std::string("C1"), std::string("C2")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
|
| - CurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestCompositorPolicy_MainThreadHandlesInput_WithoutScrollUpdates) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - EnableIdleTasks();
|
| - SimulateMainThreadGestureWithoutScrollUpdates();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("C2"),
|
| - std::string("L1"), std::string("D1"),
|
| - std::string("D2"), std::string("I1")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - CurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestCompositorPolicy_MainThreadHandlesInput_WithoutPreventDefault) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - EnableIdleTasks();
|
| - SimulateMainThreadGestureWithoutPreventDefault();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("D1"),
|
| - std::string("D2"), std::string("I1"),
|
| - std::string("C1"), std::string("C2")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
|
| - CurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestCompositorPolicy_CompositorHandlesInput_LongGestureDuration) {
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - EnableIdleTasks();
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| -
|
| - base::TimeTicks loop_end_time =
|
| - clock_->NowTicks() + base::TimeDelta::FromMilliseconds(
|
| - UserModel::kMedianGestureDurationMillis * 2);
|
| -
|
| - // The UseCase::COMPOSITOR_GESTURE usecase initially deprioritizes compositor
|
| - // tasks (see TestCompositorPolicy_CompositorHandlesInput_WithTouchHandler)
|
| - // but if the gesture is long enough, compositor tasks get prioritized again.
|
| - while (clock_->NowTicks() < loop_end_time) {
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(16));
|
| - RunUntilIdle();
|
| - }
|
| -
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("C2"),
|
| - std::string("L1"), std::string("D1"),
|
| - std::string("D2")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
|
| - CurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestCompositorPolicy_CompositorHandlesInput_WithoutTouchHandler) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
|
| -
|
| - EnableIdleTasks();
|
| - SimulateCompositorGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START);
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("D1"),
|
| - std::string("D2"), std::string("I1"),
|
| - std::string("C1"), std::string("C2")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
|
| - CurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestCompositorPolicy_MainThreadHandlesInput_WithTouchHandler) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - EnableIdleTasks();
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollBegin);
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("C2"),
|
| - std::string("L1"), std::string("D1"),
|
| - std::string("D2"), std::string("I1")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - CurrentUseCase());
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureFlingStart));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestCompositorPolicy_MainThreadHandlesInput_WithoutTouchHandler) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
|
| -
|
| - EnableIdleTasks();
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollBegin);
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("C2"),
|
| - std::string("L1"), std::string("D1"),
|
| - std::string("D2"), std::string("I1")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - CurrentUseCase());
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureFlingStart));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestCompositorPolicy_DidAnimateForInput) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - scheduler_->DidAnimateForInputOnCompositorThread();
|
| - // Note DidAnimateForInputOnCompositorThread does not by itself trigger a
|
| - // policy update.
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("D1"), std::string("D2"),
|
| - std::string("I1"), std::string("C1"),
|
| - std::string("C2")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
|
| - CurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, Navigation_ResetsTaskCostEstimations) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - scheduler_->OnNavigationStarted();
|
| - PostTestTasks(&run_order, "C1 T1");
|
| -
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollBegin);
|
| - scheduler_->DidCommitFrameToCompositor(); // Starts Idle Period
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("T1")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveTimersDontRunWhenMainThreadScrolling) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - DoMainFrame();
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollUpdate);
|
| -
|
| - PostTestTasks(&run_order, "C1 T1");
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_FALSE(TouchStartExpectedSoon());
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_GESTURE,
|
| - CurrentUseCase());
|
| -
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("C1")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveTimersDoRunWhenMainThreadInputHandling) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - DoMainFrame();
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
|
| - blink::WebInputEvent::Undefined);
|
| -
|
| - PostTestTasks(&run_order, "C1 T1");
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_FALSE(TouchStartExpectedSoon());
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - CurrentUseCase());
|
| -
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("T1")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveTimersDoRunWhenMainThreadScrolling_AndOnCriticalPath) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - DoMainFrameOnCriticalPath();
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollBegin);
|
| -
|
| - PostTestTasks(&run_order, "C1 T1");
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_FALSE(TouchStartExpectedSoon());
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - CurrentUseCase());
|
| -
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("T1")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestTouchstartPolicy_Compositor) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 D1 C1 D2 C2 T1 T2");
|
| -
|
| - // Observation of touchstart should defer execution of timer, idle and loading
|
| - // tasks.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("C2"),
|
| - std::string("D1"), std::string("D2")));
|
| -
|
| - // Animation or meta events like TapDown/FlingCancel shouldn't affect the
|
| - // priority.
|
| - run_order.clear();
|
| - scheduler_->DidAnimateForInputOnCompositorThread();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureFlingCancel),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureTapDown),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -
|
| - // Action events like ScrollBegin will kick us back into compositor priority,
|
| - // allowing service of the timer, loading and idle queues.
|
| - run_order.clear();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollBegin),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("T1"),
|
| - std::string("T2")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestTouchstartPolicy_MainThread) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 D1 C1 D2 C2 T1 T2");
|
| -
|
| - // Observation of touchstart should defer execution of timer, idle and loading
|
| - // tasks.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart));
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("C2"),
|
| - std::string("D1"), std::string("D2")));
|
| -
|
| - // Meta events like TapDown/FlingCancel shouldn't affect the priority.
|
| - run_order.clear();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureFlingCancel),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureFlingCancel));
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureTapDown),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureTapDown));
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -
|
| - // Action events like ScrollBegin will kick us back into compositor priority,
|
| - // allowing service of the timer, loading and idle queues.
|
| - run_order.clear();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollBegin),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollBegin));
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("T1"),
|
| - std::string("T2")));
|
| -}
|
| -
|
| -// TODO(alexclarke): Reenable once we've reinstaed the Loading UseCase.
|
| -TEST_F(RendererSchedulerImplTest, DISABLED_LoadingUseCase) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2");
|
| -
|
| - scheduler_->OnNavigationStarted();
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| -
|
| - // In loading policy, loading tasks are prioritized other others.
|
| - std::string loading_policy_expected[] = {
|
| - std::string("D1"), std::string("L1"), std::string("D2"),
|
| - std::string("L2"), std::string("C1"), std::string("T1"),
|
| - std::string("C2"), std::string("T2"), std::string("I1")};
|
| - EXPECT_THAT(run_order, testing::ElementsAreArray(loading_policy_expected));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::LOADING, CurrentUseCase());
|
| -
|
| - // Advance 15s and try again, the loading policy should have ended and the
|
| - // task order should return to the NONE use case where loading tasks are no
|
| - // longer prioritized.
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(150000));
|
| - run_order.clear();
|
| - PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2");
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| -
|
| - std::string default_order_expected[] = {
|
| - std::string("D1"), std::string("C1"), std::string("T1"),
|
| - std::string("L1"), std::string("D2"), std::string("C2"),
|
| - std::string("T2"), std::string("L2"), std::string("I1")};
|
| - EXPECT_THAT(run_order, testing::ElementsAreArray(default_order_expected));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - EventConsumedOnCompositorThread_IgnoresMouseMove_WhenMouseUp) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
|
| -
|
| - EnableIdleTasks();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::MouseMove),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - RunUntilIdle();
|
| - // Note compositor tasks are not prioritized.
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase());
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("D1"), std::string("C1"),
|
| - std::string("D2"), std::string("C2"),
|
| - std::string("I1")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - EventForwardedToMainThread_IgnoresMouseMove_WhenMouseUp) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
|
| -
|
| - EnableIdleTasks();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::MouseMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - RunUntilIdle();
|
| - // Note compositor tasks are not prioritized.
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase());
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("D1"), std::string("C1"),
|
| - std::string("D2"), std::string("C2"),
|
| - std::string("I1")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - EventConsumedOnCompositorThread_MouseMove_WhenMouseDown) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
|
| -
|
| - EnableIdleTasks();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::MouseMove,
|
| - blink::WebInputEvent::LeftButtonDown),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - RunUntilIdle();
|
| - // Note compositor tasks are prioritized.
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("C2"),
|
| - std::string("D1"), std::string("D2"),
|
| - std::string("I1")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - EventForwardedToMainThread_MouseMove_WhenMouseDown) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
|
| -
|
| - EnableIdleTasks();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::MouseMove,
|
| - blink::WebInputEvent::LeftButtonDown),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - RunUntilIdle();
|
| - // Note compositor tasks are prioritized.
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("C2"),
|
| - std::string("D1"), std::string("D2"),
|
| - std::string("I1")));
|
| - scheduler_->DidHandleInputEventOnMainThread(FakeInputEvent(
|
| - blink::WebInputEvent::MouseMove, blink::WebInputEvent::LeftButtonDown));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, EventConsumedOnCompositorThread_MouseWheel) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
|
| -
|
| - EnableIdleTasks();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::MouseWheel),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - RunUntilIdle();
|
| - // Note compositor tasks are prioritized.
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("C2"),
|
| - std::string("D1"), std::string("D2"),
|
| - std::string("I1")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, EventForwardedToMainThread_MouseWheel) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
|
| -
|
| - EnableIdleTasks();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::MouseWheel),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - RunUntilIdle();
|
| - // Note compositor tasks are prioritized.
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("C2"),
|
| - std::string("D1"), std::string("D2"),
|
| - std::string("I1")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - CurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - EventConsumedOnCompositorThread_IgnoresKeyboardEvents) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
|
| -
|
| - EnableIdleTasks();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::KeyDown),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - RunUntilIdle();
|
| - // Note compositor tasks are not prioritized.
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("D1"), std::string("C1"),
|
| - std::string("D2"), std::string("C2"),
|
| - std::string("I1")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - EventForwardedToMainThread_IgnoresKeyboardEvents) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
|
| -
|
| - EnableIdleTasks();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::KeyDown),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - RunUntilIdle();
|
| - // Note compositor tasks are not prioritized.
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("D1"), std::string("C1"),
|
| - std::string("D2"), std::string("C2"),
|
| - std::string("I1")));
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase());
|
| - // Note compositor tasks are not prioritized.
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::KeyDown));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestMainthreadScrollingUseCaseDoesNotStarveDefaultTasks) {
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollBegin);
|
| - EnableIdleTasks();
|
| -
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "D1 C1");
|
| -
|
| - for (int i = 0; i < 20; i++) {
|
| - compositor_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask));
|
| - }
|
| - PostTestTasks(&run_order, "C2");
|
| -
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureFlingStart),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - RunUntilIdle();
|
| - // Ensure that the default D1 task gets to run at some point before the final
|
| - // C2 compositor task.
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("D1"),
|
| - std::string("C2")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestCompositorPolicyEnds_CompositorHandlesInput) {
|
| - SimulateCompositorGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START);
|
| - EXPECT_EQ(UseCase::COMPOSITOR_GESTURE,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| -
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestCompositorPolicyEnds_MainThreadHandlesInput) {
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollBegin);
|
| - EXPECT_EQ(UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| -
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestTouchstartPolicyEndsAfterTimeout) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 D1 C1 D2 C2");
|
| -
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - 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")));
|
| -
|
| - run_order.clear();
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
|
| -
|
| - // Don't post any compositor tasks to simulate a very long running event
|
| - // handler.
|
| - PostTestTasks(&run_order, "D1 D2");
|
| -
|
| - // Touchstart policy mode should have ended now that the clock has advanced.
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("D1"),
|
| - std::string("D2")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestTouchstartPolicyEndsAfterConsecutiveTouchmoves) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "L1 D1 C1 D2 C2");
|
| -
|
| - // Observation of touchstart should defer execution of idle and loading tasks.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - 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")));
|
| -
|
| - // Receiving the first touchmove will not affect scheduler priority.
|
| - run_order.clear();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -
|
| - // Receiving the second touchmove will kick us back into compositor priority.
|
| - run_order.clear();
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("L1")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestIsHighPriorityWorkAnticipated) {
|
| - bool is_anticipated_before = false;
|
| - bool is_anticipated_after = false;
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - default_task_runner_->PostTask(
|
| - 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);
|
| -
|
| - default_task_runner_->PostTask(
|
| - 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));
|
| - default_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&AnticipationTestTask, scheduler_.get(),
|
| - SimulateInputType::GestureScrollBegin, &dummy, &dummy));
|
| - default_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&AnticipationTestTask, scheduler_.get(),
|
| - SimulateInputType::GestureScrollEnd, &dummy, &dummy));
|
| -
|
| - RunUntilIdle();
|
| - // When input is received, the scheduler should indicate that high-priority
|
| - // work is anticipated.
|
| - EXPECT_FALSE(is_anticipated_before);
|
| - EXPECT_TRUE(is_anticipated_after);
|
| -
|
| - clock_->Advance(priority_escalation_after_input_duration() * 2);
|
| - default_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(),
|
| - SimulateInputType::None, &is_anticipated_before,
|
| - &is_anticipated_after));
|
| - RunUntilIdle();
|
| - // Without additional input, the scheduler should go into NONE
|
| - // use case but with scrolling expected where high-priority work is still
|
| - // anticipated.
|
| - EXPECT_EQ(UseCase::NONE, CurrentUseCase());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - 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::NONE, CurrentUseCase());
|
| - EXPECT_FALSE(TouchStartExpectedSoon());
|
| - EXPECT_FALSE(is_anticipated_before);
|
| - EXPECT_FALSE(is_anticipated_after);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestShouldYield) {
|
| - bool should_yield_before = false;
|
| - bool should_yield_after = false;
|
| -
|
| - default_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&PostingYieldingTestTask, scheduler_.get(),
|
| - base::RetainedRef(default_task_runner_), false,
|
| - &should_yield_before, &should_yield_after));
|
| - RunUntilIdle();
|
| - // Posting to default runner shouldn't cause yielding.
|
| - EXPECT_FALSE(should_yield_before);
|
| - EXPECT_FALSE(should_yield_after);
|
| -
|
| - default_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&PostingYieldingTestTask, scheduler_.get(),
|
| - base::RetainedRef(compositor_task_runner_), false,
|
| - &should_yield_before, &should_yield_after));
|
| - RunUntilIdle();
|
| - // Posting while not mainthread scrolling shouldn't cause yielding.
|
| - EXPECT_FALSE(should_yield_before);
|
| - EXPECT_FALSE(should_yield_after);
|
| -
|
| - default_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&PostingYieldingTestTask, scheduler_.get(),
|
| - base::RetainedRef(compositor_task_runner_), true,
|
| - &should_yield_before, &should_yield_after));
|
| - RunUntilIdle();
|
| - // We should be able to switch to compositor priority mid-task.
|
| - EXPECT_FALSE(should_yield_before);
|
| - EXPECT_TRUE(should_yield_after);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestShouldYield_TouchStart) {
|
| - // Receiving a touchstart should immediately trigger yielding, even if
|
| - // there's no immediately pending work in the compositor queue.
|
| - EXPECT_FALSE(scheduler_->ShouldYieldForHighPriorityWork());
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - EXPECT_TRUE(scheduler_->ShouldYieldForHighPriorityWork());
|
| - RunUntilIdle();
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, SlowMainThreadInputEvent) {
|
| - EXPECT_EQ(UseCase::NONE, 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(UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING, CurrentUseCase());
|
| -
|
| - // Simulate the input event being queued for a very long time. The compositor
|
| - // task we post here represents the enqueued input task.
|
| - clock_->Advance(priority_escalation_after_input_duration() * 2);
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureFlingStart));
|
| - RunUntilIdle();
|
| -
|
| - // Even though we exceeded the input priority escalation period, we should
|
| - // still be in main thread gesture since the input remains queued.
|
| - EXPECT_EQ(UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING, CurrentUseCase());
|
| -
|
| - // After the escalation period ends we should go back into normal mode.
|
| - clock_->Advance(priority_escalation_after_input_duration() * 2);
|
| - RunUntilIdle();
|
| - EXPECT_EQ(UseCase::NONE, CurrentUseCase());
|
| -}
|
| -
|
| -class RendererSchedulerImplWithMockSchedulerTest
|
| - : public RendererSchedulerImplTest {
|
| - public:
|
| - void SetUp() override {
|
| - mock_task_runner_ = make_scoped_refptr(
|
| - new cc::OrderedSimpleTaskRunner(clock_.get(), false));
|
| - main_task_runner_ = SchedulerTqmDelegateForTest::Create(
|
| - mock_task_runner_, base::WrapUnique(new TestTimeSource(clock_.get())));
|
| - mock_scheduler_ = new RendererSchedulerImplForTest(main_task_runner_);
|
| - Initialize(base::WrapUnique(mock_scheduler_));
|
| - }
|
| -
|
| - protected:
|
| - RendererSchedulerImplForTest* mock_scheduler_;
|
| -};
|
| -
|
| -TEST_F(RendererSchedulerImplWithMockSchedulerTest,
|
| - OnlyOnePendingUrgentPolicyUpdatey) {
|
| - mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
|
| - mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
|
| - mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
|
| - mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
|
| -
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplWithMockSchedulerTest,
|
| - OnePendingDelayedAndOneUrgentUpdatePolicy) {
|
| - mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
|
| -
|
| - mock_scheduler_->ScheduleDelayedPolicyUpdate(
|
| - clock_->NowTicks(), base::TimeDelta::FromMilliseconds(1));
|
| - mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
|
| -
|
| - RunUntilIdle();
|
| -
|
| - // We expect both the urgent and the delayed updates to run.
|
| - EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplWithMockSchedulerTest,
|
| - OneUrgentAndOnePendingDelayedUpdatePolicy) {
|
| - mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
|
| -
|
| - mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
|
| - mock_scheduler_->ScheduleDelayedPolicyUpdate(
|
| - clock_->NowTicks(), base::TimeDelta::FromMilliseconds(1));
|
| -
|
| - RunUntilIdle();
|
| -
|
| - // We expect both the urgent and the delayed updates to run.
|
| - EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplWithMockSchedulerTest,
|
| - UpdatePolicyCountTriggeredByOneInputEvent) {
|
| - // We expect DidHandleInputEventOnCompositorThread to post an urgent policy
|
| - // update.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - EXPECT_EQ(0, mock_scheduler_->update_policy_count_);
|
| - mock_task_runner_->RunPendingTasks();
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| -
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart));
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| -
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
|
| - RunUntilIdle();
|
| -
|
| - // We finally expect a delayed policy update 100ms later.
|
| - EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplWithMockSchedulerTest,
|
| - UpdatePolicyCountTriggeredByThreeInputEvents) {
|
| - // We expect DidHandleInputEventOnCompositorThread to post an urgent policy
|
| - // update.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - EXPECT_EQ(0, mock_scheduler_->update_policy_count_);
|
| - mock_task_runner_->RunPendingTasks();
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| -
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart));
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| -
|
| - // The second call to DidHandleInputEventOnCompositorThread should not post a
|
| - // policy update because we are already in compositor priority.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - mock_task_runner_->RunPendingTasks();
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| -
|
| - // We expect DidHandleInputEvent to trigger a policy update.
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove));
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| -
|
| - // The third call to DidHandleInputEventOnCompositorThread should post a
|
| - // policy update because the awaiting_touch_start_response_ flag changed.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| - mock_task_runner_->RunPendingTasks();
|
| - EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
|
| -
|
| - // We expect DidHandleInputEvent to trigger a policy update.
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove));
|
| - EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
|
| -
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
|
| - RunUntilIdle();
|
| -
|
| - // We finally expect a delayed policy update.
|
| - EXPECT_EQ(3, mock_scheduler_->update_policy_count_);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplWithMockSchedulerTest,
|
| - UpdatePolicyCountTriggeredByTwoInputEventsWithALongSeparatingDelay) {
|
| - // We expect DidHandleInputEventOnCompositorThread to post an urgent policy
|
| - // update.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - EXPECT_EQ(0, mock_scheduler_->update_policy_count_);
|
| - mock_task_runner_->RunPendingTasks();
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| -
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart));
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| -
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
|
| - RunUntilIdle();
|
| - // We expect a delayed policy update.
|
| - EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
|
| -
|
| - // We expect the second call to DidHandleInputEventOnCompositorThread to post
|
| - // an urgent policy update because we are no longer in compositor priority.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
|
| - mock_task_runner_->RunPendingTasks();
|
| - EXPECT_EQ(3, mock_scheduler_->update_policy_count_);
|
| -
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove));
|
| - EXPECT_EQ(3, mock_scheduler_->update_policy_count_);
|
| -
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
|
| - RunUntilIdle();
|
| -
|
| - // We finally expect a delayed policy update.
|
| - EXPECT_EQ(4, mock_scheduler_->update_policy_count_);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplWithMockSchedulerTest,
|
| - EnsureUpdatePolicyNotTriggeredTooOften) {
|
| - mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
|
| -
|
| - EXPECT_EQ(0, mock_scheduler_->update_policy_count_);
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| -
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| -
|
| - // We expect the first call to IsHighPriorityWorkAnticipated to be called
|
| - // after receiving an input event (but before the UpdateTask was processed) to
|
| - // call UpdatePolicy.
|
| - EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
|
| - scheduler_->IsHighPriorityWorkAnticipated();
|
| - EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
|
| - // Subsequent calls should not call UpdatePolicy.
|
| - scheduler_->IsHighPriorityWorkAnticipated();
|
| - scheduler_->IsHighPriorityWorkAnticipated();
|
| - scheduler_->IsHighPriorityWorkAnticipated();
|
| - scheduler_->ShouldYieldForHighPriorityWork();
|
| - scheduler_->ShouldYieldForHighPriorityWork();
|
| - scheduler_->ShouldYieldForHighPriorityWork();
|
| - scheduler_->ShouldYieldForHighPriorityWork();
|
| -
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollEnd),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchEnd),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| -
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart));
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove));
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove));
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchEnd));
|
| -
|
| - EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
|
| -
|
| - // We expect both the urgent and the delayed updates to run in addition to the
|
| - // earlier updated cause by IsHighPriorityWorkAnticipated, a final update
|
| - // transitions from 'not_scrolling touchstart expected' to 'not_scrolling'.
|
| - RunUntilIdle();
|
| - EXPECT_THAT(
|
| - mock_scheduler_->use_cases_,
|
| - testing::ElementsAre(
|
| - std::string("none"), std::string("compositor_gesture"),
|
| - std::string("compositor_gesture touchstart expected"),
|
| - std::string("none touchstart expected"), std::string("none")));
|
| -}
|
| -
|
| -class RendererSchedulerImplWithMessageLoopTest
|
| - : public RendererSchedulerImplTest {
|
| - public:
|
| - RendererSchedulerImplWithMessageLoopTest()
|
| - : RendererSchedulerImplTest(new base::MessageLoop()) {}
|
| - ~RendererSchedulerImplWithMessageLoopTest() override {}
|
| -
|
| - void PostFromNestedRunloop(std::vector<
|
| - std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>>* tasks) {
|
| - base::MessageLoop::ScopedNestableTaskAllower allow(message_loop_.get());
|
| - for (std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>& pair : *tasks) {
|
| - if (pair.second) {
|
| - idle_task_runner_->PostIdleTask(FROM_HERE, pair.first);
|
| - } else {
|
| - idle_task_runner_->PostNonNestableIdleTask(FROM_HERE, pair.first);
|
| - }
|
| - }
|
| - EnableIdleTasks();
|
| - base::RunLoop().RunUntilIdle();
|
| - }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplWithMessageLoopTest);
|
| -};
|
| -
|
| -TEST_F(RendererSchedulerImplWithMessageLoopTest,
|
| - NonNestableIdleTaskDoesntExecuteInNestedLoop) {
|
| - std::vector<std::string> order;
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE,
|
| - base::Bind(&AppendToVectorIdleTestTask, &order, std::string("1")));
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE,
|
| - base::Bind(&AppendToVectorIdleTestTask, &order, std::string("2")));
|
| -
|
| - std::vector<std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>>
|
| - tasks_to_post_from_nested_loop;
|
| - tasks_to_post_from_nested_loop.push_back(std::make_pair(
|
| - base::Bind(&AppendToVectorIdleTestTask, &order, std::string("3")),
|
| - false));
|
| - tasks_to_post_from_nested_loop.push_back(std::make_pair(
|
| - base::Bind(&AppendToVectorIdleTestTask, &order, std::string("4")), true));
|
| - tasks_to_post_from_nested_loop.push_back(std::make_pair(
|
| - base::Bind(&AppendToVectorIdleTestTask, &order, std::string("5")), true));
|
| -
|
| - default_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(
|
| - &RendererSchedulerImplWithMessageLoopTest::PostFromNestedRunloop,
|
| - base::Unretained(this),
|
| - base::Unretained(&tasks_to_post_from_nested_loop)));
|
| -
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - // Note we expect task 3 to run last because it's non-nestable.
|
| - EXPECT_THAT(order, testing::ElementsAre(std::string("1"), std::string("2"),
|
| - std::string("4"), std::string("5"),
|
| - std::string("3")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestLongIdlePeriod) {
|
| - base::TimeTicks expected_deadline =
|
| - clock_->NowTicks() + maximum_idle_period_duration();
|
| - base::TimeTicks deadline_in_task;
|
| - int run_count = 0;
|
| -
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_EQ(0, run_count); // Shouldn't run yet as no idle period.
|
| -
|
| - scheduler_->BeginFrameNotExpectedSoon();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(1, run_count); // Should have run in a long idle time.
|
| - EXPECT_EQ(expected_deadline, deadline_in_task);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestLongIdlePeriodWithPendingDelayedTask) {
|
| - base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(30);
|
| - base::TimeTicks expected_deadline = clock_->NowTicks() + pending_task_delay;
|
| - base::TimeTicks deadline_in_task;
|
| - int run_count = 0;
|
| -
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| - default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask),
|
| - pending_task_delay);
|
| -
|
| - scheduler_->BeginFrameNotExpectedSoon();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(1, run_count); // Should have run in a long idle time.
|
| - EXPECT_EQ(expected_deadline, deadline_in_task);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - TestLongIdlePeriodWithLatePendingDelayedTask) {
|
| - base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(10);
|
| - base::TimeTicks deadline_in_task;
|
| - int run_count = 0;
|
| -
|
| - default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask),
|
| - pending_task_delay);
|
| -
|
| - // Advance clock until after delayed task was meant to be run.
|
| - clock_->Advance(base::TimeDelta::FromMilliseconds(20));
|
| -
|
| - // Post an idle task and BeginFrameNotExpectedSoon to initiate a long idle
|
| - // period. Since there is a late pending delayed task this shouldn't actually
|
| - // start an idle period.
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| - scheduler_->BeginFrameNotExpectedSoon();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(0, run_count);
|
| -
|
| - // After the delayed task has been run we should trigger an idle period.
|
| - clock_->Advance(maximum_idle_period_duration());
|
| - RunUntilIdle();
|
| - EXPECT_EQ(1, run_count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestLongIdlePeriodRepeating) {
|
| - mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
|
| - std::vector<base::TimeTicks> actual_deadlines;
|
| - int run_count = 0;
|
| -
|
| - max_idle_task_reposts = 3;
|
| - base::TimeTicks clock_before(clock_->NowTicks());
|
| - base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE,
|
| - base::Bind(&RepostingUpdateClockIdleTestTask,
|
| - base::RetainedRef(idle_task_runner_), &run_count, clock_.get(),
|
| - idle_task_runtime, &actual_deadlines));
|
| - scheduler_->BeginFrameNotExpectedSoon();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(3, run_count);
|
| - EXPECT_THAT(
|
| - actual_deadlines,
|
| - testing::ElementsAre(
|
| - clock_before + maximum_idle_period_duration(),
|
| - clock_before + idle_task_runtime + maximum_idle_period_duration(),
|
| - clock_before + (2 * idle_task_runtime) +
|
| - maximum_idle_period_duration()));
|
| -
|
| - // Check that idle tasks don't run after the idle period ends with a
|
| - // new BeginMainFrame.
|
| - max_idle_task_reposts = 5;
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE,
|
| - base::Bind(&RepostingUpdateClockIdleTestTask,
|
| - base::RetainedRef(idle_task_runner_), &run_count, clock_.get(),
|
| - idle_task_runtime, &actual_deadlines));
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&WillBeginFrameIdleTask,
|
| - base::Unretained(scheduler_.get()), clock_.get()));
|
| - RunUntilIdle();
|
| - EXPECT_EQ(4, run_count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestLongIdlePeriodDoesNotWakeScheduler) {
|
| - base::TimeTicks deadline_in_task;
|
| - int run_count = 0;
|
| -
|
| - // Start a long idle period and get the time it should end.
|
| - scheduler_->BeginFrameNotExpectedSoon();
|
| - // The scheduler should not run the initiate_next_long_idle_period task if
|
| - // there are no idle tasks and no other task woke up the scheduler, thus
|
| - // the idle period deadline shouldn't update at the end of the current long
|
| - // idle period.
|
| - base::TimeTicks idle_period_deadline =
|
| - scheduler_->CurrentIdleTaskDeadlineForTesting();
|
| - clock_->Advance(maximum_idle_period_duration());
|
| - RunUntilIdle();
|
| -
|
| - base::TimeTicks new_idle_period_deadline =
|
| - scheduler_->CurrentIdleTaskDeadlineForTesting();
|
| - EXPECT_EQ(idle_period_deadline, new_idle_period_deadline);
|
| -
|
| - // Posting a after-wakeup idle task also shouldn't wake the scheduler or
|
| - // initiate the next long idle period.
|
| - idle_task_runner_->PostIdleTaskAfterWakeup(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| - RunUntilIdle();
|
| - new_idle_period_deadline = scheduler_->CurrentIdleTaskDeadlineForTesting();
|
| - EXPECT_EQ(idle_period_deadline, new_idle_period_deadline);
|
| - EXPECT_EQ(0, run_count);
|
| -
|
| - // Running a normal task should initiate a new long idle period though.
|
| - default_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask));
|
| - RunUntilIdle();
|
| - new_idle_period_deadline = scheduler_->CurrentIdleTaskDeadlineForTesting();
|
| - EXPECT_EQ(idle_period_deadline + maximum_idle_period_duration(),
|
| - new_idle_period_deadline);
|
| -
|
| - EXPECT_EQ(1, run_count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestLongIdlePeriodInTouchStartPolicy) {
|
| - base::TimeTicks deadline_in_task;
|
| - int run_count = 0;
|
| -
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
|
| -
|
| - // Observation of touchstart should defer the start of the long idle period.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - scheduler_->BeginFrameNotExpectedSoon();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(0, run_count);
|
| -
|
| - // The long idle period should start after the touchstart policy has finished.
|
| - clock_->Advance(priority_escalation_after_input_duration());
|
| - RunUntilIdle();
|
| - EXPECT_EQ(1, run_count);
|
| -}
|
| -
|
| -void TestCanExceedIdleDeadlineIfRequiredTask(RendererScheduler* scheduler,
|
| - bool* can_exceed_idle_deadline_out,
|
| - int* run_count,
|
| - base::TimeTicks deadline) {
|
| - *can_exceed_idle_deadline_out = scheduler->CanExceedIdleDeadlineIfRequired();
|
| - (*run_count)++;
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, CanExceedIdleDeadlineIfRequired) {
|
| - int run_count = 0;
|
| - bool can_exceed_idle_deadline = false;
|
| -
|
| - // Should return false if not in an idle period.
|
| - EXPECT_FALSE(scheduler_->CanExceedIdleDeadlineIfRequired());
|
| -
|
| - // Should return false for short idle periods.
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE,
|
| - base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask, scheduler_.get(),
|
| - &can_exceed_idle_deadline, &run_count));
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(1, run_count);
|
| - EXPECT_FALSE(can_exceed_idle_deadline);
|
| -
|
| - // Should return false for a long idle period which is shortened due to a
|
| - // pending delayed task.
|
| - default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask),
|
| - base::TimeDelta::FromMilliseconds(10));
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE,
|
| - base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask, scheduler_.get(),
|
| - &can_exceed_idle_deadline, &run_count));
|
| - scheduler_->BeginFrameNotExpectedSoon();
|
| - RunUntilIdle();
|
| - EXPECT_EQ(2, run_count);
|
| - EXPECT_FALSE(can_exceed_idle_deadline);
|
| -
|
| - // Next long idle period will be for the maximum time, so
|
| - // CanExceedIdleDeadlineIfRequired should return true.
|
| - clock_->Advance(maximum_idle_period_duration());
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE,
|
| - base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask, scheduler_.get(),
|
| - &can_exceed_idle_deadline, &run_count));
|
| - RunUntilIdle();
|
| - EXPECT_EQ(3, run_count);
|
| - EXPECT_TRUE(can_exceed_idle_deadline);
|
| -
|
| - // Next long idle period will be for the maximum time, so
|
| - // CanExceedIdleDeadlineIfRequired should return true.
|
| - scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
|
| - EXPECT_FALSE(scheduler_->CanExceedIdleDeadlineIfRequired());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestRendererHiddenIdlePeriod) {
|
| - int run_count = 0;
|
| -
|
| - max_idle_task_reposts = 2;
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&RepostingIdleTestTask,
|
| - base::RetainedRef(idle_task_runner_), &run_count));
|
| -
|
| - // Renderer should start in visible state.
|
| - RunUntilIdle();
|
| - EXPECT_EQ(0, run_count);
|
| -
|
| - // When we hide the renderer it should start a max deadline idle period, which
|
| - // will run an idle task and then immediately start a new idle period, which
|
| - // runs the second idle task.
|
| - scheduler_->SetAllRenderWidgetsHidden(true);
|
| - RunUntilIdle();
|
| - EXPECT_EQ(2, run_count);
|
| -
|
| - // Advance time by amount of time by the maximum amount of time we execute
|
| - // idle tasks when hidden (plus some slack) - idle period should have ended.
|
| - max_idle_task_reposts = 3;
|
| - idle_task_runner_->PostIdleTask(
|
| - FROM_HERE, base::Bind(&RepostingIdleTestTask,
|
| - base::RetainedRef(idle_task_runner_), &run_count));
|
| - clock_->Advance(end_idle_when_hidden_delay() +
|
| - base::TimeDelta::FromMilliseconds(10));
|
| - RunUntilIdle();
|
| - EXPECT_EQ(2, run_count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TimerQueueEnabledByDefault) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("T1"), std::string("T2")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, SuspendAndResumeTimerQueue) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| -
|
| - scheduler_->SuspendTimerQueue();
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -
|
| - scheduler_->ResumeTimerQueue();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("T1"), std::string("T2")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, SuspendAndThrottleTimerQueue) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| -
|
| - scheduler_->SuspendTimerQueue();
|
| - RunUntilIdle();
|
| - scheduler_->throttling_helper()->IncreaseThrottleRefCount(
|
| - static_cast<TaskQueue*>(timer_task_runner_.get()));
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, ThrottleAndSuspendTimerQueue) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| -
|
| - scheduler_->throttling_helper()->IncreaseThrottleRefCount(
|
| - static_cast<TaskQueue*>(timer_task_runner_.get()));
|
| - RunUntilIdle();
|
| - scheduler_->SuspendTimerQueue();
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, MultipleSuspendsNeedMultipleResumes) {
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| -
|
| - scheduler_->SuspendTimerQueue();
|
| - scheduler_->SuspendTimerQueue();
|
| - scheduler_->SuspendTimerQueue();
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -
|
| - scheduler_->ResumeTimerQueue();
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -
|
| - scheduler_->ResumeTimerQueue();
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -
|
| - scheduler_->ResumeTimerQueue();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("T1"), std::string("T2")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, SuspendRenderer) {
|
| - // Assume that the renderer is backgrounded.
|
| - scheduler_->OnRendererBackgrounded();
|
| -
|
| - // Tasks in some queues don't fire when the renderer is suspended.
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "D1 C1 L1 I1 T1");
|
| - scheduler_->SuspendRenderer();
|
| - EnableIdleTasks();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("D1"), std::string("C1"),
|
| - std::string("I1")));
|
| -
|
| - // The rest queued tasks fire when the tab goes foregrounded.
|
| - run_order.clear();
|
| - scheduler_->OnRendererForegrounded();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("T1")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, UseCaseToString) {
|
| - CheckAllUseCaseToString();
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, MismatchedDidHandleInputEventOnMainThread) {
|
| - // This should not DCHECK because there was no corresponding compositor side
|
| - // call to DidHandleInputEventOnCompositorThread with
|
| - // INPUT_EVENT_ACK_STATE_NOT_CONSUMED. There are legitimate reasons for the
|
| - // compositor to not be there and we don't want to make debugging impossible.
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureFlingStart));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, BeginMainFrameOnCriticalPath) {
|
| - ASSERT_FALSE(scheduler_->BeginMainFrameOnCriticalPath());
|
| -
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL);
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - ASSERT_TRUE(scheduler_->BeginMainFrameOnCriticalPath());
|
| -
|
| - begin_frame_args.on_critical_path = false;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - ASSERT_FALSE(scheduler_->BeginMainFrameOnCriticalPath());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, ShutdownPreventsPostingOfNewTasks) {
|
| - scheduler_->Shutdown();
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "D1 C1");
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestRendererBackgroundedTimerSuspension) {
|
| - scheduler_->SetTimerQueueSuspensionWhenBackgroundedEnabled(true);
|
| -
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| -
|
| - // The background signal will not immediately suspend the timer queue.
|
| - scheduler_->OnRendererBackgrounded();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("T1"), std::string("T2")));
|
| -
|
| - run_order.clear();
|
| - PostTestTasks(&run_order, "T3");
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("T3")));
|
| -
|
| - // Advance the time until after the scheduled timer queue suspension.
|
| - run_order.clear();
|
| - clock_->Advance(suspend_timers_when_backgrounded_delay() +
|
| - base::TimeDelta::FromMilliseconds(10));
|
| - RunUntilIdle();
|
| - ASSERT_TRUE(run_order.empty());
|
| -
|
| - // Timer tasks should be suspended until the foregrounded signal.
|
| - PostTestTasks(&run_order, "T4 T5");
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(run_order.empty());
|
| -
|
| - scheduler_->OnRendererForegrounded();
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("T4"), std::string("T5")));
|
| -
|
| - // Subsequent timer tasks should fire as usual.
|
| - run_order.clear();
|
| - PostTestTasks(&run_order, "T6");
|
| - RunUntilIdle();
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("T6")));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveLoadingTasksNotBlockedTillFirstBeginMainFrame) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - SimulateExpensiveTasks(loading_task_runner_);
|
| - ForceTouchStartToBeExpectedSoon();
|
| - PostTestTasks(&run_order, "L1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_FALSE(HaveSeenABeginMainframe());
|
| - EXPECT_TRUE(LoadingTasksSeemExpensive());
|
| - EXPECT_FALSE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("D1")));
|
| -
|
| - // Emit a BeginMainFrame, and the loading task should get blocked.
|
| - DoMainFrame();
|
| - run_order.clear();
|
| -
|
| - PostTestTasks(&run_order, "L1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_TRUE(LoadingTasksSeemExpensive());
|
| - EXPECT_FALSE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_RESPONSE, RAILMode());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveLoadingTasksNotBlockedIfNoTouchHandler) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(false);
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(loading_task_runner_);
|
| - ForceTouchStartToBeExpectedSoon();
|
| - PostTestTasks(&run_order, "L1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_TRUE(LoadingTasksSeemExpensive());
|
| - EXPECT_FALSE(TimerTasksSeemExpensive());
|
| - EXPECT_FALSE(TouchStartExpectedSoon());
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("D1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_ANIMATION, RAILMode());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveTimerTaskBlocked_UseCase_NONE_PreviousCompositorGesture) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - ForceTouchStartToBeExpectedSoon();
|
| -
|
| - PostTestTasks(&run_order, "T1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_FALSE(LoadingTasksSeemExpensive());
|
| - EXPECT_TRUE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_RESPONSE, RAILMode());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveTimerTaskNotBlocked_UseCase_NONE_PreviousMainThreadGesture) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| -
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollBegin);
|
| - EXPECT_EQ(UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| -
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchEnd),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - scheduler_->DidHandleInputEventOnMainThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchEnd));
|
| -
|
| - clock_->Advance(priority_escalation_after_input_duration() * 2);
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| -
|
| - PostTestTasks(&run_order, "T1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_FALSE(LoadingTasksSeemExpensive());
|
| - EXPECT_TRUE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("T1"), std::string("D1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_ANIMATION, RAILMode());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveTimerTaskBlocked_UseCase_COMPOSITOR_GESTURE) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - ForceTouchStartToBeExpectedSoon();
|
| - scheduler_->DidAnimateForInputOnCompositorThread();
|
| -
|
| - PostTestTasks(&run_order, "T1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(UseCase::COMPOSITOR_GESTURE,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_FALSE(LoadingTasksSeemExpensive());
|
| - EXPECT_TRUE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_RESPONSE, RAILMode());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveTimerTaskNotBlockedIfDisallowed_UseCase_COMPOSITOR_GESTURE) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - scheduler_->SetExpensiveTaskBlockingAllowed(false);
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - ForceTouchStartToBeExpectedSoon();
|
| - scheduler_->DidAnimateForInputOnCompositorThread();
|
| -
|
| - PostTestTasks(&run_order, "T1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(UseCase::COMPOSITOR_GESTURE,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_FALSE(LoadingTasksSeemExpensive());
|
| - EXPECT_TRUE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("T1"),
|
| - std::string("D1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_RESPONSE, RAILMode());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveTimerTaskBlocked_EvenIfBeginMainFrameNotExpectedSoon) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - ForceTouchStartToBeExpectedSoon();
|
| - scheduler_->BeginFrameNotExpectedSoon();
|
| -
|
| - PostTestTasks(&run_order, "T1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_FALSE(LoadingTasksSeemExpensive());
|
| - EXPECT_TRUE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_RESPONSE, RAILMode());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveLoadingTasksBlockedIfChildFrameNavigationExpected) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - DoMainFrame();
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - SimulateExpensiveTasks(loading_task_runner_);
|
| - ForceTouchStartToBeExpectedSoon();
|
| - scheduler_->AddPendingNavigation(
|
| - blink::WebScheduler::NavigatingFrameType::kChildFrame);
|
| -
|
| - PostTestTasks(&run_order, "L1 D1");
|
| - RunUntilIdle();
|
| -
|
| - // The expensive loading task gets blocked.
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_RESPONSE, RAILMode());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveLoadingTasksNotBlockedIfMainFrameNavigationExpected) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - DoMainFrame();
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - SimulateExpensiveTasks(loading_task_runner_);
|
| - ForceTouchStartToBeExpectedSoon();
|
| - scheduler_->AddPendingNavigation(
|
| - blink::WebScheduler::NavigatingFrameType::kMainFrame);
|
| -
|
| - PostTestTasks(&run_order, "L1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_TRUE(LoadingTasksSeemExpensive());
|
| - EXPECT_FALSE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_EQ(1, NavigationTaskExpectedCount());
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("D1")));
|
| -
|
| - // After the nagigation has been cancelled, the expensive loading tasks should
|
| - // get blocked.
|
| - scheduler_->RemovePendingNavigation(
|
| - blink::WebScheduler::NavigatingFrameType::kMainFrame);
|
| - run_order.clear();
|
| -
|
| - PostTestTasks(&run_order, "L1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_TRUE(LoadingTasksSeemExpensive());
|
| - EXPECT_FALSE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_EQ(0, NavigationTaskExpectedCount());
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_RESPONSE, RAILMode());
|
| -}
|
| -
|
| -TEST_F(
|
| - RendererSchedulerImplTest,
|
| - ExpensiveLoadingTasksNotBlockedIfMainFrameNavigationExpected_Multiple) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - DoMainFrame();
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - SimulateExpensiveTasks(loading_task_runner_);
|
| - ForceTouchStartToBeExpectedSoon();
|
| - scheduler_->AddPendingNavigation(
|
| - blink::WebScheduler::NavigatingFrameType::kMainFrame);
|
| - scheduler_->AddPendingNavigation(
|
| - blink::WebScheduler::NavigatingFrameType::kMainFrame);
|
| -
|
| - PostTestTasks(&run_order, "L1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_TRUE(LoadingTasksSeemExpensive());
|
| - EXPECT_FALSE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_EQ(2, NavigationTaskExpectedCount());
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("D1")));
|
| -
|
| -
|
| - run_order.clear();
|
| - scheduler_->RemovePendingNavigation(
|
| - blink::WebScheduler::NavigatingFrameType::kMainFrame);
|
| - // Navigation task expected ref count non-zero so expensive tasks still not
|
| - // blocked.
|
| - PostTestTasks(&run_order, "L1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_TRUE(LoadingTasksSeemExpensive());
|
| - EXPECT_FALSE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_EQ(1, NavigationTaskExpectedCount());
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("L1"), std::string("D1")));
|
| -
|
| -
|
| - run_order.clear();
|
| - scheduler_->RemovePendingNavigation(
|
| - blink::WebScheduler::NavigatingFrameType::kMainFrame);
|
| - // Navigation task expected ref count is now zero, the expensive loading tasks
|
| - // should get blocked.
|
| - PostTestTasks(&run_order, "L1 D1");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase());
|
| - EXPECT_TRUE(HaveSeenABeginMainframe());
|
| - EXPECT_TRUE(LoadingTasksSeemExpensive());
|
| - EXPECT_FALSE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_EQ(0, NavigationTaskExpectedCount());
|
| - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_RESPONSE, RAILMode());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveLoadingTasksNotBlockedDuringMainThreadGestures) {
|
| - std::vector<std::string> run_order;
|
| -
|
| - SimulateExpensiveTasks(loading_task_runner_);
|
| -
|
| - // Loading tasks should not be disabled during main thread user interactions.
|
| - PostTestTasks(&run_order, "C1 L1");
|
| -
|
| - // Trigger main_thread_gesture UseCase
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollBegin);
|
| - RunUntilIdle();
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - CurrentUseCase());
|
| -
|
| - EXPECT_TRUE(LoadingTasksSeemExpensive());
|
| - EXPECT_FALSE(TimerTasksSeemExpensive());
|
| - EXPECT_THAT(run_order,
|
| - testing::ElementsAre(std::string("C1"), std::string("L1")));
|
| - EXPECT_EQ(v8::PERFORMANCE_ANIMATION, RAILMode());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, ModeratelyExpensiveTimer_NotBlocked) {
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
|
| - blink::WebInputEvent::TouchMove);
|
| - RunUntilIdle();
|
| - for (int i = 0; i < 20; i++) {
|
| - simulate_timer_task_ran_ = false;
|
| -
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = false;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| -
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&RendererSchedulerImplTest::
|
| - SimulateMainThreadInputHandlingCompositorTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(8)));
|
| - timer_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&RendererSchedulerImplTest::SimulateTimerTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(4)));
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(simulate_timer_task_ran_) << " i = " << i;
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - CurrentUseCase())
|
| - << " i = " << i;
|
| - EXPECT_FALSE(LoadingTasksSeemExpensive()) << " i = " << i;
|
| - EXPECT_FALSE(TimerTasksSeemExpensive()) << " i = " << i;
|
| -
|
| - base::TimeDelta time_till_next_frame =
|
| - EstimatedNextFrameBegin() - clock_->NowTicks();
|
| - if (time_till_next_frame > base::TimeDelta())
|
| - clock_->Advance(time_till_next_frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - FourtyMsTimer_NotBlocked_CompositorScrolling) {
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - RunUntilIdle();
|
| - for (int i = 0; i < 20; i++) {
|
| - simulate_timer_task_ran_ = false;
|
| -
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = false;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - scheduler_->DidAnimateForInputOnCompositorThread();
|
| -
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::SimulateMainThreadCompositorTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(8)));
|
| - timer_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&RendererSchedulerImplTest::SimulateTimerTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(40)));
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(simulate_timer_task_ran_) << " i = " << i;
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
|
| - CurrentUseCase())
|
| - << " i = " << i;
|
| - EXPECT_FALSE(LoadingTasksSeemExpensive()) << " i = " << i;
|
| - EXPECT_FALSE(TimerTasksSeemExpensive()) << " i = " << i;
|
| -
|
| - base::TimeDelta time_till_next_frame =
|
| - EstimatedNextFrameBegin() - clock_->NowTicks();
|
| - if (time_till_next_frame > base::TimeDelta())
|
| - clock_->Advance(time_till_next_frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveTimer_NotBlocked_UseCase_MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
|
| - blink::WebInputEvent::TouchMove);
|
| - RunUntilIdle();
|
| - for (int i = 0; i < 20; i++) {
|
| - simulate_timer_task_ran_ = false;
|
| -
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = false;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| -
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&RendererSchedulerImplTest::
|
| - SimulateMainThreadInputHandlingCompositorTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(8)));
|
| - timer_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&RendererSchedulerImplTest::SimulateTimerTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(10)));
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
|
| - CurrentUseCase())
|
| - << " i = " << i;
|
| - EXPECT_FALSE(LoadingTasksSeemExpensive()) << " i = " << i;
|
| - if (i == 0) {
|
| - EXPECT_FALSE(TimerTasksSeemExpensive()) << " i = " << i;
|
| - } else {
|
| - EXPECT_TRUE(TimerTasksSeemExpensive()) << " i = " << i;
|
| - }
|
| - EXPECT_TRUE(simulate_timer_task_ran_) << " i = " << i;
|
| -
|
| - base::TimeDelta time_till_next_frame =
|
| - EstimatedNextFrameBegin() - clock_->NowTicks();
|
| - if (time_till_next_frame > base::TimeDelta())
|
| - clock_->Advance(time_till_next_frame);
|
| - }
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - EstimateLongestJankFreeTaskDuration_UseCase_NONE) {
|
| - EXPECT_EQ(UseCase::NONE, CurrentUseCase());
|
| - EXPECT_EQ(rails_response_time(),
|
| - scheduler_->EstimateLongestJankFreeTaskDuration());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - EstimateLongestJankFreeTaskDuration_UseCase_COMPOSITOR_GESTURE) {
|
| - SimulateCompositorGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START);
|
| - EXPECT_EQ(UseCase::COMPOSITOR_GESTURE,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_EQ(rails_response_time(),
|
| - scheduler_->EstimateLongestJankFreeTaskDuration());
|
| -}
|
| -
|
| -// TODO(alexclarke): Reenable once we've reinstaed the Loading UseCase.
|
| -TEST_F(RendererSchedulerImplTest,
|
| - DISABLED_EstimateLongestJankFreeTaskDuration_UseCase_) {
|
| - scheduler_->OnNavigationStarted();
|
| - EXPECT_EQ(UseCase::LOADING, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_EQ(rails_response_time(),
|
| - scheduler_->EstimateLongestJankFreeTaskDuration());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - EstimateLongestJankFreeTaskDuration_UseCase_MAIN_THREAD_GESTURE) {
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollUpdate);
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = false;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| -
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::
|
| - SimulateMainThreadInputHandlingCompositorTask,
|
| - base::Unretained(this), base::TimeDelta::FromMilliseconds(5)));
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_EQ(UseCase::MAIN_THREAD_GESTURE, CurrentUseCase());
|
| -
|
| - // 16ms frame - 5ms compositor work = 11ms for other stuff.
|
| - EXPECT_EQ(base::TimeDelta::FromMilliseconds(11),
|
| - scheduler_->EstimateLongestJankFreeTaskDuration());
|
| -}
|
| -
|
| -TEST_F(
|
| - RendererSchedulerImplTest,
|
| - EstimateLongestJankFreeTaskDuration_UseCase_MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = false;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| -
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::
|
| - SimulateMainThreadInputHandlingCompositorTask,
|
| - base::Unretained(this), base::TimeDelta::FromMilliseconds(5)));
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_EQ(UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING, CurrentUseCase());
|
| -
|
| - // 16ms frame - 5ms compositor work = 11ms for other stuff.
|
| - EXPECT_EQ(base::TimeDelta::FromMilliseconds(11),
|
| - scheduler_->EstimateLongestJankFreeTaskDuration());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - EstimateLongestJankFreeTaskDuration_UseCase_SYNCHRONIZED_GESTURE) {
|
| - SimulateCompositorGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START);
|
| -
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| -
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::SimulateMainThreadCompositorTask,
|
| - base::Unretained(this), base::TimeDelta::FromMilliseconds(5)));
|
| -
|
| - RunUntilIdle();
|
| - EXPECT_EQ(UseCase::SYNCHRONIZED_GESTURE, CurrentUseCase());
|
| -
|
| - // 16ms frame - 5ms compositor work = 11ms for other stuff.
|
| - EXPECT_EQ(base::TimeDelta::FromMilliseconds(11),
|
| - scheduler_->EstimateLongestJankFreeTaskDuration());
|
| -}
|
| -
|
| -class WebViewSchedulerImplForTest : public WebViewSchedulerImpl {
|
| - public:
|
| - WebViewSchedulerImplForTest(RendererSchedulerImpl* scheduler)
|
| - : WebViewSchedulerImpl(nullptr, scheduler, false) {}
|
| - ~WebViewSchedulerImplForTest() override {}
|
| -
|
| - void AddConsoleWarning(const std::string& message) override {
|
| - console_warnings_.push_back(message);
|
| - }
|
| -
|
| - const std::vector<std::string>& console_warnings() const {
|
| - return console_warnings_;
|
| - }
|
| -
|
| - private:
|
| - std::vector<std::string> console_warnings_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(WebViewSchedulerImplForTest);
|
| -};
|
| -
|
| -TEST_F(RendererSchedulerImplTest, BlockedTimerNotification) {
|
| - // Make sure we see one (and just one) console warning about an expensive
|
| - // timer being deferred.
|
| - WebViewSchedulerImplForTest web_view_scheduler(scheduler_.get());
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - scheduler_->SetExpensiveTaskBlockingAllowed(true);
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| - ForceTouchStartToBeExpectedSoon();
|
| -
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(0u, run_order.size());
|
| - EXPECT_EQ(1u, web_view_scheduler.console_warnings().size());
|
| - EXPECT_NE(std::string::npos,
|
| - web_view_scheduler.console_warnings()[0].find("crbug.com/574343"));
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - BlockedTimerNotification_ExpensiveTaskBlockingNotAllowed) {
|
| - // Make sure we don't report warnings about blocked tasks when expensive task
|
| - // blocking is not allowed.
|
| - WebViewSchedulerImplForTest web_view_scheduler(scheduler_.get());
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - scheduler_->SetExpensiveTaskBlockingAllowed(false);
|
| - scheduler_->SuspendTimerQueue();
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| - ForceTouchStartToBeExpectedSoon();
|
| -
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(0u, run_order.size());
|
| - EXPECT_EQ(0u, web_view_scheduler.console_warnings().size());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, BlockedTimerNotification_TimersSuspended) {
|
| - // Make sure we don't report warnings about blocked tasks when timers are
|
| - // being blocked for other reasons.
|
| - WebViewSchedulerImplForTest web_view_scheduler(scheduler_.get());
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - scheduler_->SetExpensiveTaskBlockingAllowed(true);
|
| - scheduler_->SuspendTimerQueue();
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| - ForceTouchStartToBeExpectedSoon();
|
| -
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(0u, run_order.size());
|
| - EXPECT_EQ(0u, web_view_scheduler.console_warnings().size());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, BlockedTimerNotification_TOUCHSTART) {
|
| - // Make sure we don't report warnings about blocked tasks during TOUCHSTART.
|
| - WebViewSchedulerImplForTest web_view_scheduler(scheduler_.get());
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - EXPECT_EQ(UseCase::TOUCHSTART, ForceUpdatePolicyAndGetCurrentUseCase());
|
| -
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(0u, run_order.size());
|
| - EXPECT_EQ(0u, web_view_scheduler.console_warnings().size());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - BlockedTimerNotification_SYNCHRONIZED_GESTURE) {
|
| - // Make sure we only report warnings during a high blocking threshold.
|
| - WebViewSchedulerImplForTest web_view_scheduler(scheduler_.get());
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - DoMainFrame();
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - SimulateCompositorGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START);
|
| -
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| -
|
| - EXPECT_EQ(UseCase::SYNCHRONIZED_GESTURE,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| -
|
| - std::vector<std::string> run_order;
|
| - PostTestTasks(&run_order, "T1 T2");
|
| - RunUntilIdle();
|
| -
|
| - EXPECT_EQ(0u, run_order.size());
|
| - EXPECT_EQ(0u, web_view_scheduler.console_warnings().size());
|
| -}
|
| -
|
| -namespace {
|
| -void SlowCountingTask(size_t* count,
|
| - base::SimpleTestTickClock* clock,
|
| - int task_duration,
|
| - scoped_refptr<base::SingleThreadTaskRunner> timer_queue) {
|
| - clock->Advance(base::TimeDelta::FromMilliseconds(task_duration));
|
| - if (++(*count) < 500) {
|
| - timer_queue->PostTask(FROM_HERE, base::Bind(SlowCountingTask, count, clock,
|
| - task_duration, timer_queue));
|
| - }
|
| -}
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - SYNCHRONIZED_GESTURE_TimerTaskThrottling_task_expensive) {
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| -
|
| - base::TimeTicks first_throttled_run_time =
|
| - ThrottlingHelper::ThrottledRunTime(clock_->NowTicks());
|
| -
|
| - size_t count = 0;
|
| - // With the compositor task taking 10ms, there is not enough time to run this
|
| - // 7ms timer task in the 16ms frame.
|
| - scheduler_->TimerTaskRunner()->PostTask(
|
| - FROM_HERE, base::Bind(SlowCountingTask, &count, clock_.get(), 7,
|
| - scheduler_->TimerTaskRunner()));
|
| -
|
| - for (int i = 0; i < 1000; i++) {
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollUpdate),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| -
|
| - simulate_compositor_task_ran_ = false;
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::SimulateMainThreadCompositorTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(10)));
|
| -
|
| - mock_task_runner_->RunTasksWhile(
|
| - base::Bind(&RendererSchedulerImplTest::SimulatedCompositorTaskPending,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(UseCase::SYNCHRONIZED_GESTURE, CurrentUseCase()) << "i = " << i;
|
| -
|
| - // Before the policy is updated the queue will be enabled. Subsequently it
|
| - // will be disabled until the throttled queue is pumped.
|
| - bool expect_queue_enabled =
|
| - (i == 0) || (clock_->NowTicks() > first_throttled_run_time);
|
| - EXPECT_EQ(expect_queue_enabled,
|
| - scheduler_->TimerTaskRunner()->IsQueueEnabled())
|
| - << "i = " << i;
|
| - }
|
| -
|
| - // Task is throttled but not completely blocked.
|
| - EXPECT_EQ(12u, count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - SYNCHRONIZED_GESTURE_TimerTaskThrottling_TimersSuspended) {
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| -
|
| - base::TimeTicks first_throttled_run_time =
|
| - ThrottlingHelper::ThrottledRunTime(clock_->NowTicks());
|
| -
|
| - size_t count = 0;
|
| - // With the compositor task taking 10ms, there is not enough time to run this
|
| - // 7ms timer task in the 16ms frame.
|
| - scheduler_->TimerTaskRunner()->PostTask(
|
| - FROM_HERE, base::Bind(SlowCountingTask, &count, clock_.get(), 7,
|
| - scheduler_->TimerTaskRunner()));
|
| -
|
| - bool suspended = false;
|
| - for (int i = 0; i < 1000; i++) {
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollUpdate),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| -
|
| - simulate_compositor_task_ran_ = false;
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::SimulateMainThreadCompositorTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(10)));
|
| -
|
| - mock_task_runner_->RunTasksWhile(
|
| - base::Bind(&RendererSchedulerImplTest::SimulatedCompositorTaskPending,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(UseCase::SYNCHRONIZED_GESTURE, CurrentUseCase()) << "i = " << i;
|
| -
|
| - // Before the policy is updated the queue will be enabled. Subsequently it
|
| - // will be disabled until the throttled queue is pumped.
|
| - bool expect_queue_enabled =
|
| - (i == 0) || (clock_->NowTicks() > first_throttled_run_time);
|
| - if (suspended)
|
| - expect_queue_enabled = false;
|
| - EXPECT_EQ(expect_queue_enabled,
|
| - scheduler_->TimerTaskRunner()->IsQueueEnabled())
|
| - << "i = " << i;
|
| -
|
| - // After we've run any expensive tasks suspend the queue. The throttling
|
| - // helper should /not/ re-enable this queue under any circumstances while
|
| - // timers are suspended.
|
| - if (count > 0 && !suspended) {
|
| - EXPECT_EQ(2u, count);
|
| - scheduler_->SuspendTimerQueue();
|
| - suspended = true;
|
| - }
|
| - }
|
| -
|
| - // Make sure the timer queue stayed suspended!
|
| - EXPECT_EQ(2u, count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - SYNCHRONIZED_GESTURE_TimerTaskThrottling_task_not_expensive) {
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| -
|
| - size_t count = 0;
|
| - // With the compositor task taking 10ms, there is enough time to run this 6ms
|
| - // timer task in the 16ms frame.
|
| - scheduler_->TimerTaskRunner()->PostTask(
|
| - FROM_HERE, base::Bind(SlowCountingTask, &count, clock_.get(), 6,
|
| - scheduler_->TimerTaskRunner()));
|
| -
|
| - for (int i = 0; i < 1000; i++) {
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollUpdate),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| -
|
| - simulate_compositor_task_ran_ = false;
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::SimulateMainThreadCompositorTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(10)));
|
| -
|
| - mock_task_runner_->RunTasksWhile(
|
| - base::Bind(&RendererSchedulerImplTest::SimulatedCompositorTaskPending,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(UseCase::SYNCHRONIZED_GESTURE, CurrentUseCase()) << "i = " << i;
|
| - EXPECT_TRUE(scheduler_->TimerTaskRunner()->IsQueueEnabled()) << "i = " << i;
|
| - }
|
| -
|
| - // Task is not throttled.
|
| - EXPECT_EQ(500u, count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest,
|
| - ExpensiveTimerTaskBlocked_SYNCHRONIZED_GESTURE_TouchStartExpected) {
|
| - SimulateExpensiveTasks(timer_task_runner_);
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - ForceTouchStartToBeExpectedSoon();
|
| -
|
| - // Bump us into SYNCHRONIZED_GESTURE.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollUpdate),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| -
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| -
|
| - EXPECT_EQ(UseCase::SYNCHRONIZED_GESTURE,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| -
|
| - EXPECT_TRUE(TimerTasksSeemExpensive());
|
| - EXPECT_TRUE(TouchStartExpectedSoon());
|
| - EXPECT_FALSE(scheduler_->TimerTaskRunner()->IsQueueEnabled());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, DenyLongIdleDuringTouchStart) {
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| - EXPECT_EQ(UseCase::TOUCHSTART, ForceUpdatePolicyAndGetCurrentUseCase());
|
| -
|
| - // First check that long idle is denied during the TOUCHSTART use case.
|
| - IdleHelper::Delegate* idle_delegate = scheduler_.get();
|
| - base::TimeTicks now;
|
| - base::TimeDelta next_time_to_check;
|
| - EXPECT_FALSE(idle_delegate->CanEnterLongIdlePeriod(now, &next_time_to_check));
|
| - EXPECT_GE(next_time_to_check, base::TimeDelta());
|
| -
|
| - // Check again at a time past the TOUCHSTART expiration. We should still get a
|
| - // non-negative delay to when to check again.
|
| - now += base::TimeDelta::FromMilliseconds(500);
|
| - EXPECT_FALSE(idle_delegate->CanEnterLongIdlePeriod(now, &next_time_to_check));
|
| - EXPECT_GE(next_time_to_check, base::TimeDelta());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestCompositorPolicy_TouchStartDuringFling) {
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - scheduler_->DidAnimateForInputOnCompositorThread();
|
| - // Note DidAnimateForInputOnCompositorThread does not by itself trigger a
|
| - // policy update.
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| -
|
| - // Make sure TouchStart causes a policy change.
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchStart),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| - EXPECT_EQ(RendererSchedulerImpl::UseCase::TOUCHSTART,
|
| - ForceUpdatePolicyAndGetCurrentUseCase());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, SYNCHRONIZED_GESTURE_CompositingExpensive) {
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| -
|
| - // With the compositor task taking 20ms, there is not enough time to run
|
| - // other tasks in the same 16ms frame. To avoid starvation, compositing tasks
|
| - // should therefore not get prioritized.
|
| - std::vector<std::string> run_order;
|
| - for (int i = 0; i < 1000; i++)
|
| - PostTestTasks(&run_order, "T1");
|
| -
|
| - for (int i = 0; i < 100; i++) {
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollUpdate),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| -
|
| - simulate_compositor_task_ran_ = false;
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::SimulateMainThreadCompositorTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(20)));
|
| -
|
| - mock_task_runner_->RunTasksWhile(
|
| - base::Bind(&RendererSchedulerImplTest::SimulatedCompositorTaskPending,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(UseCase::SYNCHRONIZED_GESTURE, CurrentUseCase()) << "i = " << i;
|
| - }
|
| -
|
| - // Timer tasks should not have been starved by the expensive compositor
|
| - // tasks.
|
| - EXPECT_EQ(TaskQueue::NORMAL_PRIORITY,
|
| - scheduler_->CompositorTaskRunner()->GetQueuePriority());
|
| - EXPECT_EQ(1000u, run_order.size());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollBegin);
|
| -
|
| - // With the compositor task taking 20ms, there is not enough time to run
|
| - // other tasks in the same 16ms frame. To avoid starvation, compositing tasks
|
| - // should therefore not get prioritized.
|
| - std::vector<std::string> run_order;
|
| - for (int i = 0; i < 1000; i++)
|
| - PostTestTasks(&run_order, "T1");
|
| -
|
| - for (int i = 0; i < 100; i++) {
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::TouchMove),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| -
|
| - simulate_compositor_task_ran_ = false;
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::SimulateMainThreadCompositorTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(20)));
|
| -
|
| - mock_task_runner_->RunTasksWhile(
|
| - base::Bind(&RendererSchedulerImplTest::SimulatedCompositorTaskPending,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING, CurrentUseCase())
|
| - << "i = " << i;
|
| - }
|
| -
|
| - // Timer tasks should not have been starved by the expensive compositor
|
| - // tasks.
|
| - EXPECT_EQ(TaskQueue::NORMAL_PRIORITY,
|
| - scheduler_->CompositorTaskRunner()->GetQueuePriority());
|
| - EXPECT_EQ(1000u, run_order.size());
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, MAIN_THREAD_GESTURE) {
|
| - SimulateMainThreadGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START,
|
| - blink::WebInputEvent::GestureScrollBegin);
|
| -
|
| - // With the compositor task taking 20ms, there is not enough time to run
|
| - // other tasks in the same 16ms frame. However because this is a main thread
|
| - // gesture instead of custom main thread input handling, we allow the timer
|
| - // tasks to be starved.
|
| - std::vector<std::string> run_order;
|
| - for (int i = 0; i < 1000; i++)
|
| - PostTestTasks(&run_order, "T1");
|
| -
|
| - for (int i = 0; i < 100; i++) {
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollUpdate),
|
| - RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
|
| -
|
| - simulate_compositor_task_ran_ = false;
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::SimulateMainThreadCompositorTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(20)));
|
| -
|
| - mock_task_runner_->RunTasksWhile(
|
| - base::Bind(&RendererSchedulerImplTest::SimulatedCompositorTaskPending,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(UseCase::MAIN_THREAD_GESTURE, CurrentUseCase()) << "i = " << i;
|
| - }
|
| -
|
| - EXPECT_EQ(TaskQueue::HIGH_PRIORITY,
|
| - scheduler_->CompositorTaskRunner()->GetQueuePriority());
|
| - EXPECT_EQ(279u, run_order.size());
|
| -}
|
| -
|
| -class MockRAILModeObserver : public RendererScheduler::RAILModeObserver {
|
| - public:
|
| - MOCK_METHOD1(OnRAILModeChanged, void(v8::RAILMode rail_mode));
|
| -};
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestResponseRAILMode) {
|
| - MockRAILModeObserver observer;
|
| - scheduler_->SetRAILModeObserver(&observer);
|
| - EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_RESPONSE));
|
| -
|
| - scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
|
| - ForceTouchStartToBeExpectedSoon();
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_EQ(v8::PERFORMANCE_RESPONSE, RAILMode());
|
| - scheduler_->SetRAILModeObserver(nullptr);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestAnimateRAILMode) {
|
| - MockRAILModeObserver observer;
|
| - scheduler_->SetRAILModeObserver(&observer);
|
| - EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_ANIMATION)).Times(0);
|
| -
|
| - EXPECT_FALSE(BeginFrameNotExpectedSoon());
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_EQ(v8::PERFORMANCE_ANIMATION, RAILMode());
|
| - scheduler_->SetRAILModeObserver(nullptr);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, TestIdleRAILMode) {
|
| - MockRAILModeObserver observer;
|
| - scheduler_->SetRAILModeObserver(&observer);
|
| - EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_ANIMATION));
|
| - EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_IDLE));
|
| -
|
| - scheduler_->SetAllRenderWidgetsHidden(true);
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_EQ(v8::PERFORMANCE_IDLE, RAILMode());
|
| - scheduler_->SetAllRenderWidgetsHidden(false);
|
| - EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
|
| - EXPECT_EQ(v8::PERFORMANCE_ANIMATION, RAILMode());
|
| - scheduler_->SetRAILModeObserver(nullptr);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, UnthrottledTaskRunner) {
|
| - // Ensure neither suspension nor timer task throttling affects an unthrottled
|
| - // task runner.
|
| - SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START);
|
| - scoped_refptr<TaskQueue> unthrottled_task_runner =
|
| - scheduler_->NewUnthrottledTaskRunner("unthrottled_tq");
|
| -
|
| - size_t timer_count = 0;
|
| - size_t unthrottled_count = 0;
|
| - scheduler_->TimerTaskRunner()->PostTask(
|
| - FROM_HERE, base::Bind(SlowCountingTask, &timer_count, clock_.get(), 7,
|
| - scheduler_->TimerTaskRunner()));
|
| - unthrottled_task_runner->PostTask(
|
| - FROM_HERE, base::Bind(SlowCountingTask, &unthrottled_count, clock_.get(),
|
| - 7, unthrottled_task_runner));
|
| - scheduler_->SuspendTimerQueue();
|
| -
|
| - for (int i = 0; i < 1000; i++) {
|
| - cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
|
| - BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
|
| - base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
|
| - begin_frame_args.on_critical_path = true;
|
| - scheduler_->WillBeginFrame(begin_frame_args);
|
| - scheduler_->DidHandleInputEventOnCompositorThread(
|
| - FakeInputEvent(blink::WebInputEvent::GestureScrollUpdate),
|
| - RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
|
| -
|
| - simulate_compositor_task_ran_ = false;
|
| - compositor_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererSchedulerImplTest::SimulateMainThreadCompositorTask,
|
| - base::Unretained(this),
|
| - base::TimeDelta::FromMilliseconds(10)));
|
| -
|
| - mock_task_runner_->RunTasksWhile(
|
| - base::Bind(&RendererSchedulerImplTest::SimulatedCompositorTaskPending,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(UseCase::SYNCHRONIZED_GESTURE, CurrentUseCase()) << "i = " << i;
|
| - }
|
| -
|
| - EXPECT_EQ(0u, timer_count);
|
| - EXPECT_EQ(500u, unthrottled_count);
|
| -}
|
| -
|
| -TEST_F(RendererSchedulerImplTest, EnableVirtualTime) {
|
| - scheduler_->EnableVirtualTime();
|
| -
|
| - scoped_refptr<TaskQueue> loading_tq =
|
| - scheduler_->NewLoadingTaskRunner("test");
|
| - scoped_refptr<TaskQueue> timer_tq = scheduler_->NewTimerTaskRunner("test");
|
| - scoped_refptr<TaskQueue> unthrottled_tq =
|
| - scheduler_->NewUnthrottledTaskRunner("test");
|
| -
|
| - EXPECT_EQ(scheduler_->DefaultTaskRunner()->GetTimeDomain(),
|
| - scheduler_->GetVirtualTimeDomain());
|
| - EXPECT_EQ(scheduler_->CompositorTaskRunner()->GetTimeDomain(),
|
| - scheduler_->GetVirtualTimeDomain());
|
| - EXPECT_EQ(scheduler_->LoadingTaskRunner()->GetTimeDomain(),
|
| - scheduler_->GetVirtualTimeDomain());
|
| - EXPECT_EQ(scheduler_->TimerTaskRunner()->GetTimeDomain(),
|
| - scheduler_->GetVirtualTimeDomain());
|
| -
|
| - EXPECT_EQ(loading_tq->GetTimeDomain(), scheduler_->GetVirtualTimeDomain());
|
| - EXPECT_EQ(timer_tq->GetTimeDomain(), scheduler_->GetVirtualTimeDomain());
|
| - EXPECT_EQ(unthrottled_tq->GetTimeDomain(),
|
| - scheduler_->GetVirtualTimeDomain());
|
| -
|
| - EXPECT_EQ(scheduler_->NewLoadingTaskRunner("test")->GetTimeDomain(),
|
| - scheduler_->GetVirtualTimeDomain());
|
| - EXPECT_EQ(scheduler_->NewTimerTaskRunner("test")->GetTimeDomain(),
|
| - scheduler_->GetVirtualTimeDomain());
|
| - EXPECT_EQ(scheduler_->NewUnthrottledTaskRunner("test")->GetTimeDomain(),
|
| - scheduler_->GetVirtualTimeDomain());
|
| -}
|
| -
|
| -} // namespace scheduler
|
|
|