chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"

#include <memory>
#include <string>
#include <utility>

#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial_params.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/task/common/task_annotator.h"
#include "base/task/sequence_manager/test/fake_task.h"
#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
#include "third_party/blink/public/platform/web_input_event_result.h"
#include "third_party/blink/renderer/platform/scheduler/common/auto_advancing_virtual_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/common/features.h"
#include "third_party/blink/renderer/platform/scheduler/common/task_priority.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_queue_type.h"
#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h"
#include "third_party/blink/renderer/platform/scheduler/test/recording_task_time_observer.h"
#include "third_party/blink/renderer/platform/scheduler/test/web_scheduling_test_helper.h"
#include "v8/include/v8.h"

TaskQueue;

namespace blink {
namespace scheduler {
// To avoid symbol collisions in jumbo builds.
namespace main_thread_scheduler_impl_unittest {

namespace {
Feature;
FakeTask;
FakeTaskTiming;
WebInputEvent;
InSequence;
Mock;
NiceMock;
NotNull;
Return;
ReturnRef;
InputEventState;

constexpr base::TimeDelta kDelayForHighPriorityRendering =;

// This is a wrapper around MainThreadSchedulerImpl::CreatePageScheduler, that
// returns the PageScheduler as a PageSchedulerImpl.
std::unique_ptr<PageSchedulerImpl> CreatePageScheduler(
    PageScheduler::Delegate* page_scheduler_delegate,
    ThreadSchedulerBase* scheduler,
    AgentGroupScheduler& agent_group_scheduler) {}

// This is a wrapper around PageSchedulerImpl::CreateFrameScheduler, that
// returns the FrameScheduler as a FrameSchedulerImpl.
std::unique_ptr<FrameSchedulerImpl> CreateFrameScheduler(
    PageSchedulerImpl* page_scheduler,
    FrameScheduler::Delegate* delegate,
    bool is_in_embedded_frame_tree,
    FrameScheduler::FrameType frame_type) {}

class MockFrameDelegate : public FrameScheduler::Delegate {};

}  // namespace

class FakeInputEvent : public blink::WebInputEvent {};

class FakeTouchEvent : public blink::WebTouchEvent {};

class FakeMouseWheelEvent : public blink::WebMouseWheelEvent {};

void AppendToVectorTestTask(Vector<String>* vector, String value) {}

void AppendToVectorIdleTestTask(Vector<String>* vector,
                                String value,
                                base::TimeTicks deadline) {}

void NullTask() {}

void AppendToVectorReentrantTask(base::SingleThreadTaskRunner* task_runner,
                                 Vector<int>* vector,
                                 int* reentrant_count,
                                 int max_reentrant_count) {}

void IdleTestTask(int* run_count,
                  base::TimeTicks* deadline_out,
                  base::TimeTicks deadline) {}

int g_max_idle_task_reposts =;

void RepostingIdleTestTask(SingleThreadIdleTaskRunner* idle_task_runner,
                           int* run_count,
                           base::TimeTicks deadline) {}

void RepostingUpdateClockIdleTestTask(
    SingleThreadIdleTaskRunner* idle_task_runner,
    int* run_count,
    scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner,
    base::TimeDelta advance_time,
    Vector<base::TimeTicks>* deadlines,
    base::TimeTicks deadline) {}

void WillBeginFrameIdleTask(MainThreadSchedulerImpl* scheduler,
                            uint64_t sequence_number,
                            const base::TickClock* clock,
                            base::TimeTicks deadline) {}

void UpdateClockToDeadlineIdleTestTask(
    scoped_refptr<base::TestMockTimeTaskRunner> task_runner,
    int* run_count,
    base::TimeTicks deadline) {}

void PostingYieldingTestTask(MainThreadSchedulerImpl* scheduler,
                             base::SingleThreadTaskRunner* task_runner,
                             bool simulate_input,
                             bool* should_yield_before,
                             bool* should_yield_after) {}

enum class SimulateInputType {};

class MockPageSchedulerImpl : public PageSchedulerImpl {};

class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl {};

// Lets gtest print human readable Policy values.
::std::ostream& operator<<(::std::ostream& os, const UseCase& use_case) {}

class MainThreadSchedulerImplTest : public testing::Test {};

class
    MainThreadSchedulerImplWithLoadingPhaseBufferTimeAfterFirstMeaningfulPaintTest
    : public MainThreadSchedulerImplTest,
      public ::testing::WithParamInterface<bool> {};

INSTANTIATE_TEST_SUITE_P();

TEST_F(MainThreadSchedulerImplTest, TestPostDefaultTask) {}

TEST_F(MainThreadSchedulerImplTest, TestPostDefaultAndCompositor) {}

TEST_F(MainThreadSchedulerImplTest, TestRentrantTask) {}

TEST_F(MainThreadSchedulerImplTest, TestPostIdleTask) {}

TEST_F(MainThreadSchedulerImplTest, TestRepostingIdleTask) {}

TEST_F(MainThreadSchedulerImplTest, TestIdleTaskExceedsDeadline) {}

TEST_F(MainThreadSchedulerImplTest, TestDelayedEndIdlePeriodCanceled) {}

TEST_F(MainThreadSchedulerImplTest, TestDefaultPolicy) {}

TEST_F(MainThreadSchedulerImplTest, TestDefaultPolicyWithSlowCompositor) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_CompositorHandlesInput_WithTouchHandler) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_MainThreadHandlesInput_WithoutScrollUpdates) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_MainThreadHandlesInput_WithoutPreventDefault) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_CompositorHandlesInput_LongGestureDuration) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_CompositorHandlesInput_WithoutTouchHandler) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_MainThreadHandlesInput_WithTouchHandler) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_MainThreadHandlesInput_WithoutTouchHandler) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_MainThreadHandlesInput_SingleEvent_PreventDefault) {}

TEST_F(
    MainThreadSchedulerImplTest,
    TestCompositorPolicy_MainThreadHandlesInput_SingleEvent_NoPreventDefault) {}

TEST_F(MainThreadSchedulerImplTest, Navigation_ResetsTaskCostEstimations) {}

TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicy_Compositor) {}

TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicy_MainThread) {}

TEST_P(
    MainThreadSchedulerImplWithLoadingPhaseBufferTimeAfterFirstMeaningfulPaintTest,
    InitiallyInEarlyLoadingUseCase) {}

TEST_P(
    MainThreadSchedulerImplWithLoadingPhaseBufferTimeAfterFirstMeaningfulPaintTest,
    NonOrdinaryPageDoesNotTriggerLoadingUseCase) {}

TEST_F(MainThreadSchedulerImplTest,
       EventConsumedOnCompositorThread_IgnoresMouseMove_WhenMouseUp) {}

TEST_F(MainThreadSchedulerImplTest,
       EventForwardedToMainThread_IgnoresMouseMove_WhenMouseUp) {}

TEST_F(MainThreadSchedulerImplTest,
       EventConsumedOnCompositorThread_MouseMove_WhenMouseDown) {}

TEST_F(MainThreadSchedulerImplTest,
       EventForwardedToMainThread_MouseMove_WhenMouseDown) {}

TEST_F(MainThreadSchedulerImplTest,
       EventForwardedToMainThread_MouseMove_WhenMouseDown_AfterMouseWheel) {}

TEST_F(MainThreadSchedulerImplTest, EventForwardedToMainThread_MouseClick) {}

TEST_F(MainThreadSchedulerImplTest,
       EventConsumedOnCompositorThread_MouseWheel) {}

TEST_F(MainThreadSchedulerImplTest,
       EventForwardedToMainThread_MouseWheel_PreventDefault) {}

TEST_F(MainThreadSchedulerImplTest,
       EventForwardedToMainThread_NoPreventDefault) {}

TEST_F(
    MainThreadSchedulerImplTest,
    EventForwardedToMainThreadAndBackToCompositor_MouseWheel_NoPreventDefault) {}

TEST_F(MainThreadSchedulerImplTest,
       EventConsumedOnCompositorThread_IgnoresKeyboardEvents) {}

TEST_F(MainThreadSchedulerImplTest,
       EventForwardedToMainThread_IgnoresKeyboardEvents) {}

TEST_F(MainThreadSchedulerImplTest,
       TestMainthreadScrollingUseCaseDoesNotStarveDefaultTasks) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicyEnds_CompositorHandlesInput) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicyEnds_MainThreadHandlesInput) {}

TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicyEndsAfterTimeout) {}

TEST_F(MainThreadSchedulerImplTest,
       TestTouchstartPolicyEndsAfterConsecutiveTouchmoves) {}

TEST_F(MainThreadSchedulerImplTest, TestShouldYield) {}

TEST_F(MainThreadSchedulerImplTest, TestShouldYield_TouchStart) {}

TEST_F(MainThreadSchedulerImplTest, SlowMainThreadInputEvent) {}

TEST_F(MainThreadSchedulerImplTest, OnlyOnePendingUrgentPolicyUpdate) {}

TEST_F(MainThreadSchedulerImplTest, OnePendingDelayedAndOneUrgentUpdatePolicy) {}

TEST_F(MainThreadSchedulerImplTest, OneUrgentAndOnePendingDelayedUpdatePolicy) {}

TEST_F(MainThreadSchedulerImplTest, UpdatePolicyCountTriggeredByOneInputEvent) {}

TEST_F(MainThreadSchedulerImplTest,
       UpdatePolicyCountTriggeredByThreeInputEvents) {}

TEST_F(MainThreadSchedulerImplTest,
       UpdatePolicyCountTriggeredByTwoInputEventsWithALongSeparatingDelay) {}

TEST_F(MainThreadSchedulerImplTest, EnsureUpdatePolicyNotTriggeredTooOften) {}

TEST_F(MainThreadSchedulerImplTest,
       BlockingInputExpectedSoonWhenBlockInputEventSeen) {}

TEST_F(MainThreadSchedulerImplTest,
       BlockingInputNotExpectedSoonWhenNoBlockInputEventSeen) {}

TEST_F(MainThreadSchedulerImplTest, TestBeginMainFrameNotExpectedUntil) {}

TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriod) {}

TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodWithPendingDelayedTask) {}

TEST_F(MainThreadSchedulerImplTest,
       TestLongIdlePeriodWithLatePendingDelayedTask) {}

TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodRepeating) {}

TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodInTouchStartPolicy) {}

TEST_F(MainThreadSchedulerImplTest, TestRendererHiddenIdlePeriod) {}

TEST_F(MainThreadSchedulerImplTest, ThrottleableQueueEnabledByDefault) {}

TEST_F(MainThreadSchedulerImplTest, StopAndResumeRenderer) {}

TEST_F(MainThreadSchedulerImplTest, StopAndThrottleThrottleableQueue) {}

TEST_F(MainThreadSchedulerImplTest, MultipleStopsNeedMultipleResumes) {}

TEST_F(MainThreadSchedulerImplTest, PauseRenderer) {}

TEST_F(MainThreadSchedulerImplTest, UseCaseToString) {}

TEST_F(MainThreadSchedulerImplTest, MismatchedDidHandleInputEventOnMainThread) {}

TEST_F(MainThreadSchedulerImplTest, BeginMainFrameOnCriticalPath) {}

TEST_F(MainThreadSchedulerImplTest, ShutdownPreventsPostingOfNewTasks) {}

namespace {
void SlowCountingTask(
    size_t* count,
    scoped_refptr<base::TestMockTimeTaskRunner> task_runner,
    int task_duration,
    scoped_refptr<base::SingleThreadTaskRunner> throttleable_queue) {}
}  // namespace

TEST_F(
    MainThreadSchedulerImplTest,
    SYNCHRONIZED_GESTURE_ThrottleableTaskThrottling_ThrottleableQueuesStopped) {}

TEST_F(MainThreadSchedulerImplTest,
       SYNCHRONIZED_GESTURE_ThrottleableTaskThrottling_task_not_expensive) {}

TEST_F(MainThreadSchedulerImplTest, DenyLongIdleDuringTouchStart) {}

TEST_F(MainThreadSchedulerImplTest, SYNCHRONIZED_GESTURE_CompositingExpensive) {}

TEST_F(MainThreadSchedulerImplTest, MAIN_THREAD_CUSTOM_INPUT_HANDLING) {}

TEST_F(MainThreadSchedulerImplTest, MAIN_THREAD_GESTURE) {}

class MockRAILModeObserver : public RAILModeObserver {};

TEST_F(MainThreadSchedulerImplTest, TestResponseRAILMode) {}

TEST_F(MainThreadSchedulerImplTest, TestAnimateRAILMode) {}

TEST_F(MainThreadSchedulerImplTest, TestIdleRAILMode) {}

TEST_P(
    MainThreadSchedulerImplWithLoadingPhaseBufferTimeAfterFirstMeaningfulPaintTest,
    TestLoadRAILMode) {}

TEST_P(
    MainThreadSchedulerImplWithLoadingPhaseBufferTimeAfterFirstMeaningfulPaintTest,
    InputTerminatesLoadRAILMode) {}

TEST_F(MainThreadSchedulerImplTest, UnthrottledTaskRunner) {}

TEST_F(MainThreadSchedulerImplTest, EnableVirtualTime) {}

TEST_F(MainThreadSchedulerImplTest, DisableVirtualTimeForTesting) {}

TEST_F(MainThreadSchedulerImplTest, VirtualTimePauser) {}

TEST_F(MainThreadSchedulerImplTest, VirtualTimePauserNonInstantTask) {}

TEST_F(MainThreadSchedulerImplTest, VirtualTimeWithOneQueueWithoutVirtualTime) {}

TEST_F(MainThreadSchedulerImplTest, Tracing) {}

TEST_F(MainThreadSchedulerImplTest,
       LogIpcsPostedToDocumentsInBackForwardCache) {}

void RecordingTimeTestTask(
    Vector<base::TimeTicks>* run_times,
    scoped_refptr<base::TestMockTimeTaskRunner> task_runner) {}

TEST_F(MainThreadSchedulerImplTest, LoadingControlTasks) {}

TEST_F(MainThreadSchedulerImplTest, RequestBeginMainFrameNotExpected) {}

TEST_F(MainThreadSchedulerImplTest,
       RequestBeginMainFrameNotExpected_MultipleCalls) {}

#if BUILDFLAG(IS_ANDROID)
TEST_F(MainThreadSchedulerImplTest, PauseTimersForAndroidWebView) {
  // Tasks in some queues don't fire when the throttleable queues are paused.
  Vector<String> run_order;
  PostTestTasks(&run_order, "D1 C1 L1 I1 T1");
  scheduler_->PauseTimersForAndroidWebView();
  EnableIdleTasks();
  test_task_runner_->FastForwardUntilNoTasksRemain();
  EXPECT_THAT(run_order, testing::ElementsAre("D1", "C1", "L1", "I1"));
  // The rest queued tasks fire when the throttleable queues are resumed.
  run_order.clear();
  scheduler_->ResumeTimersForAndroidWebView();
  test_task_runner_->FastForwardUntilNoTasksRemain();
  EXPECT_THAT(run_order, testing::ElementsAre("T1"));
}
#endif  // BUILDFLAG(IS_ANDROID)

TEST_F(MainThreadSchedulerImplTest, FreezesCompositorQueueWhenAllPagesFrozen) {}

class MainThreadSchedulerImplWithInitalVirtualTimeTest
    : public MainThreadSchedulerImplTest {};

TEST_F(MainThreadSchedulerImplWithInitalVirtualTimeTest, VirtualTimeOverride) {}

TEST_F(MainThreadSchedulerImplTest, CompositingAfterInput) {}

TEST_F(MainThreadSchedulerImplTest,
       CompositorNotPrioritizedAfterContinuousInput) {}

TEST_F(MainThreadSchedulerImplTest, TaskQueueReferenceClearedOnShutdown) {}

TEST_F(MainThreadSchedulerImplTest, MicrotaskCheckpointTiming) {}

TEST_F(MainThreadSchedulerImplTest, NonWakingTaskQueue) {}

class BestEffortPriorityForFindInPageExperimentTest
    : public MainThreadSchedulerImplTest {};

TEST_F(BestEffortPriorityForFindInPageExperimentTest,
       FindInPageTasksAreBestEffortPriorityUnderExperiment) {}

TEST_F(MainThreadSchedulerImplTest, FindInPageTasksAreVeryHighPriority) {}

TEST_F(MainThreadSchedulerImplTest, FindInPageTasksChangeToNormalPriority) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_CompositorStaysAtNormalPriority) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_FirstCompositorTaskSetToVeryHighPriority) {}

TEST_F(MainThreadSchedulerImplTest,
       TestCompositorPolicy_FirstCompositorTaskStaysAtNormalPriority) {}

TEST_F(MainThreadSchedulerImplTest, ThrottleHandleThrottlesQueue) {}

class PrioritizeCompositingAfterDelayTest : public MainThreadSchedulerImplTest {};

TEST_F(PrioritizeCompositingAfterDelayTest, PreFCP) {}

TEST_F(PrioritizeCompositingAfterDelayTest, PostFCP) {}

TEST_F(PrioritizeCompositingAfterDelayTest, DuringCompositorGesture) {}

struct CompositorTQPolicyDuringThreadedScrollTestParam {};

class CompositorTQPolicyDuringThreadedScrollTest
    : public MainThreadSchedulerImplTest,
      public ::testing::WithParamInterface<
          CompositorTQPolicyDuringThreadedScrollTestParam> {};

TEST_P(CompositorTQPolicyDuringThreadedScrollTest, CompositorPriority) {}

INSTANTIATE_TEST_SUITE_P();

TEST_F(MainThreadSchedulerImplTest, RenderBlockingTaskPriority) {}

TEST_F(MainThreadSchedulerImplTest, RenderBlockingAndDiscreteInput) {}

TEST_F(MainThreadSchedulerImplTest, RenderBlockingStarvationPrevention) {}

TEST_F(MainThreadSchedulerImplTest, DetachRunningTaskQueue) {}

class UrgentMessageSchedulingPolicyTest : public MainThreadSchedulerImplTest {};

TEST_F(UrgentMessageSchedulingPolicyTest, PrioritizeIPCTasks) {}

TEST_F(UrgentMessageSchedulingPolicyTest, UrgentMessageAndCompositorPriority) {}

class DeferRendererTasksAfterInputTest
    : public MainThreadSchedulerImplTest,
      public ::testing::WithParamInterface<features::TaskDeferralPolicy>,
      public WebSchedulingTestHelper::Delegate {};

TEST_P(DeferRendererTasksAfterInputTest, TaskDeferral) {}

TEST_P(DeferRendererTasksAfterInputTest, DynamicPriorityTaskDeferral) {}

TEST_P(DeferRendererTasksAfterInputTest, TaskDeferralTimeout) {}

TEST_P(DeferRendererTasksAfterInputTest,
       DiscreteInputUseCaseDependsOnFrameRequested) {}

TEST_P(DeferRendererTasksAfterInputTest,
       DiscreteInputUseCaseIgnoresContinuous) {}

TEST_P(DeferRendererTasksAfterInputTest, UseCaseTimeout) {}

TEST_P(DeferRendererTasksAfterInputTest, TouchStartAndDiscreteInput) {}

TEST_P(DeferRendererTasksAfterInputTest, DiscreteInputDuringContinuousGesture) {}

INSTANTIATE_TEST_SUITE_P();

class DiscreteInputMatchesResponsivenessMetricsTest
    : public MainThreadSchedulerImplTest,
      public ::testing::WithParamInterface<bool> {};

TEST_P(DiscreteInputMatchesResponsivenessMetricsTest, TestPolicy) {}

INSTANTIATE_TEST_SUITE_P();

}  // namespace main_thread_scheduler_impl_unittest
}  // namespace scheduler
}  // namespace blink