chromium/cc/trees/layer_tree_host_unittest_scroll.cc

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

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "base/memory/raw_ptr.h"
#include "cc/trees/layer_tree_host.h"

#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "cc/animation/animation_host.h"
#include "cc/base/completion_event.h"
#include "cc/base/features.h"
#include "cc/input/browser_controls_offset_manager.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/input/scroll_elasticity_helper.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/picture_layer.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_picture_layer.h"
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/layer_tree_test.h"
#include "cc/test/test_task_graph_runner.h"
#include "cc/test/test_ukm_recorder_factory.h"
#include "cc/trees/clip_node.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/proxy_impl.h"
#include "cc/trees/scroll_node.h"
#include "cc/trees/single_thread_proxy.h"
#include "cc/trees/transform_node.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/events/types/scroll_input_type.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/test/geometry_util.h"
#include "ui/gfx/geometry/vector2d_conversions.h"

Mock;

ScrollThread;

namespace cc {
namespace {

std::unique_ptr<ScrollState> BeginState(const gfx::Point& point,
                                        const gfx::Vector2dF& delta_hint) {}

ScrollState UpdateState(const gfx::Point& point, const gfx::Vector2dF& delta) {}

class LayerTreeHostScrollTest : public LayerTreeTest, public ScrollCallbacks {};

class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollSimple);

class LayerTreeHostScrollTestScrollMultipleRedraw
    : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollMultipleRedraw);

class LayerTreeHostScrollTestScrollAbortedCommit
    : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollAbortedCommit);

class LayerTreeHostScrollTestFractionalScroll : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(LayerTreeHostScrollTestFractionalScroll);

class LayerTreeHostScrollTestScrollSnapping : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollSnapping);

class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {};

// TODO(crbug.com/41490731): Test is flaky on asan on multiple platforms.
// TODO(crbug.com/345499781): Test is flaky on Linux.
#if defined(ADDRESS_SANITIZER) || defined(IS_LINUX)
#define MAYBE_DeviceScaleFactor1_ScrollChild
#else
#define MAYBE_DeviceScaleFactor1_ScrollChild
#endif
TEST_F(LayerTreeHostScrollTestCaseWithChild,
       MAYBE_DeviceScaleFactor1_ScrollChild) {}

// TODO(crbug.com/41490731): Test is flaky on (at least) Mac and Linux asan.
// TODO(crbug.com/345499781): Test is flaky on Linux.
#if defined(ADDRESS_SANITIZER) || defined(IS_LINUX)
#define MAYBE_DeviceScaleFactor15_ScrollChild
#else
#define MAYBE_DeviceScaleFactor15_ScrollChild
#endif
TEST_F(LayerTreeHostScrollTestCaseWithChild,
       MAYBE_DeviceScaleFactor15_ScrollChild) {}

// TODO(crbug.com/41494888): Test is flaky on asan on multiple platforms.
// TODO(crbug.com/345499781): Test is flaky on Linux.
#if defined(ADDRESS_SANITIZER) || defined(IS_LINUX)
#define MAYBE_DeviceScaleFactor2_ScrollChild
#else
#define MAYBE_DeviceScaleFactor2_ScrollChild
#endif
TEST_F(LayerTreeHostScrollTestCaseWithChild,
       MAYBE_DeviceScaleFactor2_ScrollChild) {}

// TODO(crbug.com/41494364): Test is flaky on asan on multiple platforms.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || \
    defined(ADDRESS_SANITIZER)
#define MAYBE_DeviceScaleFactor1_ScrollRootScrollLayer
#else
#define MAYBE_DeviceScaleFactor1_ScrollRootScrollLayer
#endif
TEST_F(LayerTreeHostScrollTestCaseWithChild,
       MAYBE_DeviceScaleFactor1_ScrollRootScrollLayer) {}

// TODO(crbug.com/41494893): Test is flaky on Win asan.
// TODO(crbug.com/41490731): Test is flaky on Mac asan.
// TODO(crbug.com/345499781): Test is flaky on Linux.
// Test is flaky on asan on multiple platforms.
#if defined(ADDRESS_SANITIZER) || defined(IS_LINUX)
#define MAYBE_DeviceScaleFactor15_ScrollRootScrollLayer
#else
#define MAYBE_DeviceScaleFactor15_ScrollRootScrollLayer
#endif
TEST_F(LayerTreeHostScrollTestCaseWithChild,
       MAYBE_DeviceScaleFactor15_ScrollRootScrollLayer) {}

// TODO(crbug.com/41494746): Fix the flakiness on Mac ASan and re-enable.
// TODO(crbug.com/345499781): Test is flaky on Linux.
// Test is flaky on asan on multiple platforms.
#if defined(ADDRESS_SANITIZER) || defined(IS_LINUX)
#define MAYBE_DeviceScaleFactor2_ScrollRootScrollLayer
#else
#define MAYBE_DeviceScaleFactor2_ScrollRootScrollLayer
#endif
TEST_F(LayerTreeHostScrollTestCaseWithChild,
       MAYBE_DeviceScaleFactor2_ScrollRootScrollLayer) {}

class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest {};

// This tests scrolling on the impl side which is only possible with a thread.
MULTI_THREAD_TEST_F(LayerTreeHostScrollTestSimple);

// This test makes sure that layers pick up scrolls that occur between
// beginning a commit and finishing a commit (aka scroll deltas not
// included in sent scroll delta) still apply to layers that don't
// push properties.
class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest {};

// This tests scrolling on the impl side which is only possible with a thread.
MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplOnlyScroll);

// TODO(crbug.com/40451005): Mac currently doesn't support smooth scrolling
// wheel events.
#if !BUILDFLAG(IS_MAC)
// This test simulates scrolling on the impl thread such that it starts a scroll
// animation. It ensures that RequestScrollAnimationEndNotification() correctly
// notifies the callback after the animation ends.
class SmoothScrollAnimationEndNotification : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(SmoothScrollAnimationEndNotification);
#endif  // !BUILDFLAG(IS_MAC)

void DoGestureScroll(LayerTreeHostImpl* host_impl,
                     const scoped_refptr<Layer>& scroller,
                     gfx::Vector2dF offset,
                     ElementId scroller_element_id) {}

// This test simulates scrolling on the impl thread such that snapping occurs
// and ensures that the target snap area element ids are sent back to the main
// thread.
class LayerTreeHostScrollTestImplOnlyScrollSnap
    : public LayerTreeHostScrollTest {};

// TODO(crbug.com/40762489): Flaky on Fuchsia, ChromeOS, and Linux.
// TODO(crbug.com/41495136): Flaky on Windows ASAN.
// TODO(crbug.com/342502558): Flaky on Mac ASAN.
#if !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_CHROMEOS) && \
    !BUILDFLAG(IS_LINUX) &&                              \
    !((BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)) && defined(ADDRESS_SANITIZER))
MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplOnlyScrollSnap);
#endif

// This test simulates scrolling on the impl thread such that 2 impl-only
// scrolls occur between main frames. It ensures that the snap target ids will
// be synced from impl to main for both snapped scrolling nodes.
class LayerTreeHostScrollTestImplOnlyMultipleScrollSnap
    : public LayerTreeHostScrollTest {};

// TODO(crbug.com/40787490): Test is flaky on Chrome OS (both Ash and Lacros).
#if !BUILDFLAG(IS_CHROMEOS)
MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplOnlyMultipleScrollSnap);
#endif

class LayerTreeHostScrollTestScrollZeroMaxScrollOffset
    : public LayerTreeHostScrollTest {};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostScrollTestScrollZeroMaxScrollOffset);

class LayerTreeHostScrollTestScrollNonDrawnLayer
    : public LayerTreeHostScrollTest {};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollNonDrawnLayer);

class LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent
    : public LayerTreeHostScrollTest {};

// This test is flaky in the single threaded configuration, only on the
// chromeos-amd64-generic-rel bot. https://crbug.com/1093078.
#if BUILDFLAG(IS_CHROMEOS)
// SINGLE_THREAD_TEST_F(
//    LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent);
MULTI_THREAD_TEST_F(
    LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent);
#else
SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent);
#endif

class ThreadCheckingInputHandlerClient : public InputHandlerClient {};

class LayerTreeHostScrollTestLayerStructureChange
    : public LayerTreeHostScrollTest {};

TEST_F(LayerTreeHostScrollTestLayerStructureChange, ScrollDestroyLayer) {}

TEST_F(LayerTreeHostScrollTestLayerStructureChange, ScrollDestroyWholeTree) {}

class LayerTreeHostScrollTestScrollMFBA : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollMFBA);

class LayerTreeHostScrollTestScrollAbortedCommitMFBA
    : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollAbortedCommitMFBA);

class MockInputHandlerClient : public InputHandlerClient {};

// This is a regression test, see crbug.com/639046.
class LayerTreeHostScrollTestElasticOverscroll
    : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(LayerTreeHostScrollTestElasticOverscroll);

class LayerTreeHostScrollTestPropertyTreeUpdate
    : public LayerTreeHostScrollTest {};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostScrollTestPropertyTreeUpdate);

class LayerTreeHostScrollTestImplSideInvalidation
    : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplSideInvalidation);

class LayerTreeHostRasterPriorityTest : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(LayerTreeHostRasterPriorityTest);

class NonScrollingMainThreadScrollHitTestRegion
    : public LayerTreeHostScrollTest {};

SINGLE_THREAD_TEST_F(NonScrollingMainThreadScrollHitTestRegion);

// This test verifies that scrolling in non layer list mode (used by UI
// compositor) is always "compositor scrolled", i.e. property trees are mutated
// and the updated layers redrawn.  This test intentionally doesn't inherit
// from LayerTreeHostScrollTest since that enables LayerLists.
class UnifiedScrollingRepaintOnScroll : public LayerTreeTest {};

MULTI_THREAD_TEST_F(UnifiedScrollingRepaintOnScroll);

// Regression test for crbug.com/1248211 where the viewport was not updated
// when the browser controls were changed on an aborted commit.
//
class LayerTreeHostScrollTestViewportAbortedCommit
    : public LayerTreeHostScrollTest {};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostScrollTestViewportAbortedCommit);

class PreventRecreatingTilingDuringScroll : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(PreventRecreatingTilingDuringScroll);

class CommitWithoutSynchronizingScrollOffsets : public LayerTreeHostScrollTest {};

MULTI_THREAD_TEST_F(CommitWithoutSynchronizingScrollOffsets);

}  // namespace
}  // namespace cc