// Copyright 2012 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 "cc/trees/layer_tree_host.h"

#include <stdint.h>
#include <climits>

#include "base/bind.h"
#include "cc/animation/animation_curve.h"
#include "cc/animation/animation_host.h"
#include "cc/animation/animation_id_provider.h"
#include "cc/animation/animation_timeline.h"
#include "cc/animation/element_animations.h"
#include "cc/animation/keyframe_effect.h"
#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/animation/scroll_offset_animations.h"
#include "cc/animation/single_keyframe_effect_animation.h"
#include "cc/animation/timing_function.h"
#include "cc/animation/transform_operations.h"
#include "cc/base/completion_event.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/test/animation_test_common.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_picture_layer.h"
#include "cc/test/layer_tree_test.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/transform_node.h"
#include "components/viz/common/quads/compositor_frame.h"

namespace cc {
namespace {

class LayerTreeHostAnimationTest : public LayerTreeTest {
 public:
  LayerTreeHostAnimationTest()
      : timeline_id_(AnimationIdProvider::NextTimelineId()),
        animation_id_(AnimationIdProvider::NextAnimationId()),
        animation_child_id_(AnimationIdProvider::NextAnimationId()) {
    timeline_ = AnimationTimeline::Create(timeline_id_);
    animation_ = SingleKeyframeEffectAnimation::Create(animation_id_);
    animation_child_ =
        SingleKeyframeEffectAnimation::Create(animation_child_id_);

    animation_->set_animation_delegate(this);
  }

  void AttachAnimationsToTimeline() {
    animation_host()->AddAnimationTimeline(timeline_.get());
    layer_tree_host()->SetElementIdsForTesting();
    timeline_->AttachAnimation(animation_.get());
    timeline_->AttachAnimation(animation_child_.get());
  }

  void GetImplTimelineAndAnimationByID(const LayerTreeHostImpl& host_impl) {
    AnimationHost* animation_host_impl = GetImplAnimationHost(&host_impl);
    timeline_impl_ = animation_host_impl->GetTimelineById(timeline_id_);
    EXPECT_TRUE(timeline_impl_);
    animation_impl_ = static_cast<SingleKeyframeEffectAnimation*>(
        timeline_impl_->GetAnimationById(animation_id_));
    EXPECT_TRUE(animation_impl_);
    animation_child_impl_ = static_cast<SingleKeyframeEffectAnimation*>(
        timeline_impl_->GetAnimationById(animation_child_id_));
    EXPECT_TRUE(animation_child_impl_);
  }

  AnimationHost* GetImplAnimationHost(
      const LayerTreeHostImpl* host_impl) const {
    return static_cast<AnimationHost*>(host_impl->mutator_host());
  }

 protected:
  scoped_refptr<AnimationTimeline> timeline_;
  scoped_refptr<SingleKeyframeEffectAnimation> animation_;
  scoped_refptr<SingleKeyframeEffectAnimation> animation_child_;

  scoped_refptr<AnimationTimeline> timeline_impl_;
  scoped_refptr<SingleKeyframeEffectAnimation> animation_impl_;
  scoped_refptr<SingleKeyframeEffectAnimation> animation_child_impl_;

  const int timeline_id_;
  const int animation_id_;
  const int animation_child_id_;
};

// Makes sure that SetNeedsAnimate does not cause the CommitRequested() state to
// be set.
class LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested()
      : num_commits_(0) {}

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    // We skip the first commit because its the commit that populates the
    // impl thread with a tree. After the second commit, the test is done.
    if (num_commits_ != 1)
      return;

    layer_tree_host()->SetNeedsAnimate();
    // Right now, CommitRequested is going to be true, because during
    // BeginFrame, we force CommitRequested to true to prevent requests from
    // hitting the impl thread. But, when the next DidCommit happens, we should
    // verify that CommitRequested has gone back to false.
  }

  void DidCommit() override {
    if (!num_commits_) {
      EXPECT_FALSE(layer_tree_host()->CommitRequested());
      layer_tree_host()->SetNeedsAnimate();
      EXPECT_FALSE(layer_tree_host()->CommitRequested());
    }

    // Verifies that the SetNeedsAnimate we made in ::Animate did not
    // trigger CommitRequested.
    EXPECT_FALSE(layer_tree_host()->CommitRequested());
    EndTest();
    num_commits_++;
  }

  void AfterTest() override {}

 private:
  int num_commits_;
};

MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested);

// Trigger a frame with SetNeedsCommit. Then, inside the resulting animate
// callback, request another frame using SetNeedsAnimate. End the test when
// animate gets called yet-again, indicating that the proxy is correctly
// handling the case where SetNeedsAnimate() is called inside the BeginFrame
// flow.
class LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback()
      : num_begin_frames_(0) {}

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    if (!num_begin_frames_) {
      layer_tree_host()->SetNeedsAnimate();
      num_begin_frames_++;
      return;
    }
    EndTest();
  }

  void AfterTest() override {}

 private:
  int num_begin_frames_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback);

// Add a layer animation and confirm that
// LayerTreeHostImpl::UpdateAnimationState does get called.
class LayerTreeHostAnimationTestAddKeyframeModel
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestAddKeyframeModel()
      : update_animation_state_was_called_(false) {}

  void BeginTest() override {
    AttachAnimationsToTimeline();
    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    PostAddOpacityAnimationToMainThreadInstantly(animation_.get());
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    EXPECT_FALSE(has_unfinished_animation);
    update_animation_state_was_called_ = true;
  }

  void NotifyAnimationStarted(base::TimeTicks monotonic_time,
                              int target_property,
                              int group) override {
    EXPECT_LT(base::TimeTicks(), monotonic_time);

    KeyframeModel* keyframe_model =
        animation_->GetKeyframeModel(TargetProperty::OPACITY);
    if (keyframe_model)
      animation_->RemoveKeyframeModel(keyframe_model->id());

    EndTest();
  }

  void AfterTest() override { EXPECT_TRUE(update_animation_state_was_called_); }

 private:
  bool update_animation_state_was_called_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAddKeyframeModel);

// Add an animation that does not cause damage, followed by an animation that
// does. Confirm that the first animation finishes even though
// enable_early_damage_check should abort draws.
class LayerTreeHostAnimationTestNoDamageAnimation
    : public LayerTreeHostAnimationTest {
  void InitializeSettings(LayerTreeSettings* settings) override {
    settings->using_synchronous_renderer_compositor = true;
    settings->enable_early_damage_check = true;
  }

 public:
  LayerTreeHostAnimationTestNoDamageAnimation()
      : started_animating_(false), finished_animating_(false) {}

  void BeginTest() override {
    AttachAnimationsToTimeline();
    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    PostAddNoDamageAnimationToMainThread(animation_.get());
    PostAddOpacityAnimationToMainThread(animation_.get());
  }

  void AnimateLayers(LayerTreeHostImpl* host_impl,
                     base::TimeTicks monotonic_time) override {
    base::AutoLock auto_lock(lock_);
    started_animating_ = true;
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    base::AutoLock auto_lock(lock_);
    if (started_animating_ && finished_animating_)
      EndTest();
  }

  void NotifyAnimationFinished(base::TimeTicks monotonic_time,
                               int target_property,
                               int group) override {
    base::AutoLock auto_lock(lock_);
    finished_animating_ = true;
  }

  void AfterTest() override {}

 private:
  bool started_animating_;
  bool finished_animating_;
  base::Lock lock_;
};

// This behavior is specific to Android WebView, which only uses
// multi-threaded compositor.
MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestNoDamageAnimation);

// Add a layer animation to a layer, but continually fail to draw. Confirm that
// after a while, we do eventually force a draw.
class LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws()
      : started_animating_(false) {}

  void BeginTest() override {
    AttachAnimationsToTimeline();
    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    PostAddOpacityAnimationToMainThread(animation_.get());
  }

  void AnimateLayers(LayerTreeHostImpl* host_impl,
                     base::TimeTicks monotonic_time) override {
    started_animating_ = true;
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    if (started_animating_)
      EndTest();
  }

  DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                   LayerTreeHostImpl::FrameData* frame,
                                   DrawResult draw_result) override {
    return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
  }

  void AfterTest() override {}

 private:
  bool started_animating_;
};

// Starvation can only be an issue with the MT compositor.
MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws);

// Ensures that animations eventually get deleted.
class LayerTreeHostAnimationTestAnimationsGetDeleted
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestAnimationsGetDeleted()
      : started_animating_(false) {}

  void BeginTest() override {
    AttachAnimationsToTimeline();
    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    PostAddOpacityAnimationToMainThread(animation_.get());
  }

  void AnimateLayers(LayerTreeHostImpl* host_impl,
                     base::TimeTicks monotonic_time) override {
    bool have_animations = !GetImplAnimationHost(host_impl)
                                ->ticking_animations_for_testing()
                                .empty();
    if (!started_animating_ && have_animations) {
      started_animating_ = true;
      return;
    }

    if (started_animating_ && !have_animations)
      EndTest();
  }

  void NotifyAnimationFinished(base::TimeTicks monotonic_time,
                               int target_property,
                               int group) override {
    // Animations on the impl-side ElementAnimations only get deleted during
    // a commit, so we need to schedule a commit.
    layer_tree_host()->SetNeedsCommit();
  }

  void AfterTest() override {}

 private:
  bool started_animating_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationsGetDeleted);

// Ensure that an animation's timing function is respected.
class LayerTreeHostAnimationTestAddKeyframeModelWithTimingFunction
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    picture_ = FakePictureLayer::Create(&client_);
    picture_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(picture_->bounds());
    layer_tree_host()->root_layer()->AddChild(picture_);

    AttachAnimationsToTimeline();
    animation_child_->AttachElement(picture_->element_id());
  }

  void BeginTest() override {
    PostAddOpacityAnimationToMainThread(animation_child_.get());
  }

  void AnimateLayers(LayerTreeHostImpl* host_impl,
                     base::TimeTicks monotonic_time) override {
    // TODO(ajuma): This test only checks the active tree. Add checks for
    // pending tree too.
    if (!host_impl->active_tree()->root_layer_for_testing())
      return;

    // Wait for the commit with the animation to happen.
    if (host_impl->active_tree()->source_frame_number() != 0)
      return;

    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<SingleKeyframeEffectAnimation> animation_child_impl =
        static_cast<SingleKeyframeEffectAnimation*>(
            timeline_impl->GetAnimationById(animation_child_id_));

    KeyframeModel* keyframe_model =
        animation_child_impl->GetKeyframeModel(TargetProperty::OPACITY);

    const FloatAnimationCurve* curve =
        keyframe_model->curve()->ToFloatAnimationCurve();
    float start_opacity = curve->GetValue(base::TimeDelta());
    float end_opacity = curve->GetValue(curve->Duration());
    float linearly_interpolated_opacity =
        0.25f * end_opacity + 0.75f * start_opacity;
    base::TimeDelta time = curve->Duration() * 0.25f;
    // If the linear timing function associated with this animation was not
    // picked up, then the linearly interpolated opacity would be different
    // because of the default ease timing function.
    EXPECT_FLOAT_EQ(linearly_interpolated_opacity, curve->GetValue(time));

    EndTest();
  }

  void AfterTest() override {}

  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> picture_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestAddKeyframeModelWithTimingFunction);

// Ensures that main thread animations have their start times synchronized with
// impl thread animations.
class LayerTreeHostAnimationTestSynchronizeAnimationStartTimes
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    picture_ = FakePictureLayer::Create(&client_);
    picture_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(picture_->bounds());

    layer_tree_host()->root_layer()->AddChild(picture_);

    AttachAnimationsToTimeline();
    animation_child_->set_animation_delegate(this);
    animation_child_->AttachElement(picture_->element_id());
  }

  void BeginTest() override {
    PostAddOpacityAnimationToMainThread(animation_child_.get());
  }

  void NotifyAnimationStarted(base::TimeTicks monotonic_time,
                              int target_property,
                              int group) override {
    KeyframeModel* keyframe_model =
        animation_child_->GetKeyframeModel(TargetProperty::OPACITY);
    main_start_time_ = keyframe_model->start_time();
    animation_child_->RemoveKeyframeModel(keyframe_model->id());
    EndTest();
  }

  void UpdateAnimationState(LayerTreeHostImpl* impl_host,
                            bool has_unfinished_animation) override {
    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(impl_host)->GetTimelineById(timeline_id_);
    scoped_refptr<SingleKeyframeEffectAnimation> animation_child_impl =
        static_cast<SingleKeyframeEffectAnimation*>(
            timeline_impl->GetAnimationById(animation_child_id_));

    KeyframeModel* keyframe_model =
        animation_child_impl->GetKeyframeModel(TargetProperty::OPACITY);
    if (!keyframe_model)
      return;

    impl_start_time_ = keyframe_model->start_time();
  }

  void AfterTest() override {
    EXPECT_EQ(impl_start_time_, main_start_time_);
    EXPECT_LT(base::TimeTicks(), impl_start_time_);
  }

 private:
  base::TimeTicks main_start_time_;
  base::TimeTicks impl_start_time_;
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> picture_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestSynchronizeAnimationStartTimes);

// Ensures that notify animation finished is called.
class LayerTreeHostAnimationTestAnimationFinishedEvents
    : public LayerTreeHostAnimationTest {
 public:
  void BeginTest() override {
    AttachAnimationsToTimeline();
    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    PostAddOpacityAnimationToMainThreadInstantly(animation_.get());
  }

  void NotifyAnimationFinished(base::TimeTicks monotonic_time,
                               int target_property,
                               int group) override {
    KeyframeModel* keyframe_model =
        animation_->GetKeyframeModel(TargetProperty::OPACITY);
    if (keyframe_model)
      animation_->RemoveKeyframeModel(keyframe_model->id());
    EndTest();
  }

  void AfterTest() override {}
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestAnimationFinishedEvents);

// Ensures that when opacity is being animated, this value does not cause the
// subtree to be skipped.
class LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity()
      : update_check_layer_() {}

  void SetupTree() override {
    update_check_layer_ = FakePictureLayer::Create(&client_);
    update_check_layer_->SetOpacity(0.f);
    layer_tree_host()->SetRootLayer(update_check_layer_);
    client_.set_bounds(update_check_layer_->bounds());
    LayerTreeHostAnimationTest::SetupTree();

    AttachAnimationsToTimeline();
    animation_->AttachElement(update_check_layer_->element_id());
  }

  void BeginTest() override {
    PostAddOpacityAnimationToMainThread(animation_.get());
  }

  void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<SingleKeyframeEffectAnimation> animation_impl =
        static_cast<SingleKeyframeEffectAnimation*>(
            timeline_impl->GetAnimationById(animation_id_));

    KeyframeModel* keyframe_model_impl =
        animation_impl->GetKeyframeModel(TargetProperty::OPACITY);
    animation_impl->RemoveKeyframeModel(keyframe_model_impl->id());
    EndTest();
  }

  void AfterTest() override {
    // Update() should have been called once, proving that the layer was not
    // skipped.
    EXPECT_EQ(1, update_check_layer_->update_count());

    // clear update_check_layer_ so LayerTreeHost dies.
    update_check_layer_ = nullptr;
  }

 private:
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> update_check_layer_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity);

// Layers added to tree with existing active animations should have the
// animation correctly recognized.
class LayerTreeHostAnimationTestLayerAddedWithAnimation
    : public LayerTreeHostAnimationTest {
 public:
  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      AttachAnimationsToTimeline();

      scoped_refptr<Layer> layer = Layer::Create();
      layer->SetElementId(ElementId(42));
      animation_->AttachElement(layer->element_id());
      animation_->set_animation_delegate(this);

      // Any valid AnimationCurve will do here.
      std::unique_ptr<AnimationCurve> curve(new FakeFloatAnimationCurve());
      std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create(
          std::move(curve), 1, 1, TargetProperty::OPACITY));
      animation_->AddKeyframeModel(std::move(keyframe_model));

      // We add the animation *before* attaching the layer to the tree.
      layer_tree_host()->root_layer()->AddChild(layer);
    }
  }

  void AnimateLayers(LayerTreeHostImpl* impl_host,
                     base::TimeTicks monotonic_time) override {
    EndTest();
  }

  void AfterTest() override {}
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestLayerAddedWithAnimation);

class LayerTreeHostAnimationTestCancelAnimateCommit
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestCancelAnimateCommit()
      : num_begin_frames_(0), num_commit_calls_(0), num_draw_calls_(0) {}

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    num_begin_frames_++;
    // No-op animate will cancel the commit.
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      EndTest();
      return;
    }
    layer_tree_host()->SetNeedsAnimate();
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
    num_commit_calls_++;
    if (impl->active_tree()->source_frame_number() > 1)
      FAIL() << "Commit should have been canceled.";
  }

  void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
    num_draw_calls_++;
    if (impl->active_tree()->source_frame_number() > 1)
      FAIL() << "Draw should have been canceled.";
  }

  void AfterTest() override {
    EXPECT_EQ(2, num_begin_frames_);
    EXPECT_EQ(1, num_commit_calls_);
    EXPECT_EQ(1, num_draw_calls_);
  }

 private:
  int num_begin_frames_;
  int num_commit_calls_;
  int num_draw_calls_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCancelAnimateCommit);

class LayerTreeHostAnimationTestForceRedraw
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestForceRedraw()
      : num_animate_(0), num_draw_layers_(0) {}

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    if (++num_animate_ < 2)
      layer_tree_host()->SetNeedsAnimate();
  }

  void UpdateLayerTreeHost() override {
    layer_tree_host()->SetNeedsCommitWithForcedRedraw();
  }

  void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
    if (++num_draw_layers_ == 2)
      EndTest();
  }

  void AfterTest() override {
    // The first commit will always draw; make sure the second draw triggered
    // by the animation was not cancelled.
    EXPECT_EQ(2, num_draw_layers_);
    EXPECT_EQ(2, num_animate_);
  }

 private:
  int num_animate_;
  int num_draw_layers_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestForceRedraw);

class LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit()
      : num_animate_(0), num_draw_layers_(0) {}

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    if (++num_animate_ <= 2) {
      layer_tree_host()->SetNeedsCommit();
      layer_tree_host()->SetNeedsAnimate();
    }
  }

  void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
    if (++num_draw_layers_ == 2)
      EndTest();
  }

  void AfterTest() override {
    // The first commit will always draw; make sure the second draw triggered
    // by the SetNeedsCommit was not cancelled.
    EXPECT_EQ(2, num_draw_layers_);
    EXPECT_GE(num_animate_, 2);
  }

 private:
  int num_animate_;
  int num_draw_layers_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit);

// Animations should not be started when frames are being skipped due to
// checkerboard.
class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
    : public LayerTreeHostAnimationTest {
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    picture_ = FakePictureLayer::Create(&client_);
    picture_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(picture_->bounds());
    layer_tree_host()->root_layer()->AddChild(picture_);

    AttachAnimationsToTimeline();
    animation_child_->AttachElement(picture_->element_id());
    animation_child_->set_animation_delegate(this);
  }

  void InitializeSettings(LayerTreeSettings* settings) override {
    // Make sure that drawing many times doesn't cause a checkerboarded
    // animation to start so we avoid flake in this test.
    settings->timeout_and_draw_when_animation_checkerboards = false;
    LayerTreeHostAnimationTest::InitializeSettings(settings);
  }

  void BeginTest() override {
    prevented_draw_ = 0;
    started_times_ = 0;

    PostSetNeedsCommitToMainThread();
  }

  DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                   LayerTreeHostImpl::FrameData* frame_data,
                                   DrawResult draw_result) override {
    // Don't checkerboard when the first animation wants to start.
    if (host_impl->active_tree()->source_frame_number() < 2)
      return draw_result;
    if (TestEnded())
      return draw_result;
    // Act like there is checkerboard when the second animation wants to draw.
    ++prevented_draw_;
    if (prevented_draw_ > 2)
      EndTest();
    return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
  }

  void DidCommitAndDrawFrame() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 1:
        // The animation is longer than 1 BeginFrame interval.
        AddOpacityTransitionToAnimation(animation_child_.get(), 0.1, 0.2f, 0.8f,
                                        false);
        break;
      case 2:
        // This second animation will not be drawn so it should not start.
        AddAnimatedTransformToAnimation(animation_child_.get(), 0.1, 5, 5);
        break;
    }
  }

  void NotifyAnimationStarted(base::TimeTicks monotonic_time,
                              int target_property,
                              int group) override {
    if (TestEnded())
      return;
    started_times_++;
  }

  void AfterTest() override {
    // Make sure we tried to draw the second animation but failed.
    EXPECT_LT(0, prevented_draw_);
    // The first animation should be started, but the second should not because
    // of checkerboard.
    EXPECT_EQ(1, started_times_);
  }

  int prevented_draw_;
  int started_times_;
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> picture_;
};

MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations);

// Verifies that scroll offset animations are only accepted when impl-scrolling
// is supported, and that when scroll offset animations are accepted,
// scroll offset updates are sent back to the main thread.
class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    scroll_layer_ = FakePictureLayer::Create(&client_);
    scroll_layer_->SetScrollable(gfx::Size(100, 100));
    scroll_layer_->SetBounds(gfx::Size(1000, 1000));
    client_.set_bounds(scroll_layer_->bounds());
    scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20));
    layer_tree_host()->root_layer()->AddChild(scroll_layer_);

    AttachAnimationsToTimeline();
    animation_child_->AttachElement(scroll_layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 1: {
        std::unique_ptr<ScrollOffsetAnimationCurve> curve(
            ScrollOffsetAnimationCurve::Create(
                gfx::ScrollOffset(500.f, 550.f),
                CubicBezierTimingFunction::CreatePreset(
                    CubicBezierTimingFunction::EaseType::EASE_IN_OUT)));
        std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create(
            std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET));
        keyframe_model->set_needs_synchronized_start_time(true);
        bool impl_scrolling_supported = proxy()->SupportsImplScrolling();
        if (impl_scrolling_supported)
          animation_child_->AddKeyframeModel(std::move(keyframe_model));
        else
          EndTest();
        break;
      }
      default:
        EXPECT_GE(scroll_layer_->CurrentScrollOffset().x(), 10);
        EXPECT_GE(scroll_layer_->CurrentScrollOffset().y(), 20);
        if (scroll_layer_->CurrentScrollOffset().x() > 10 &&
            scroll_layer_->CurrentScrollOffset().y() > 20)
          EndTest();
    }
  }

  void AfterTest() override {}

 private:
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> scroll_layer_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestScrollOffsetChangesArePropagated);

// Verifies that when a main thread scrolling reason gets added, the
// notification to takover the animation on the main thread gets sent.
class LayerTreeHostAnimationTestScrollOffsetAnimationTakeover
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestScrollOffsetAnimationTakeover() = default;

  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    scroll_layer_ = FakePictureLayer::Create(&client_);
    scroll_layer_->SetBounds(gfx::Size(10000, 10000));
    client_.set_bounds(scroll_layer_->bounds());
    scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20));
    scroll_layer_->SetScrollable(gfx::Size(10, 10));
    layer_tree_host()->root_layer()->AddChild(scroll_layer_);

    AttachAnimationsToTimeline();
    animation_child_->AttachElement(scroll_layer_->element_id());
    // Allows NotifyAnimationTakeover to get called.
    animation_child_->set_animation_delegate(this);
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      // Add an update after the first commit to trigger the animation takeover
      // path.
      animation_host()->scroll_offset_animations().AddTakeoverUpdate(
          scroll_layer_->element_id());
      EXPECT_TRUE(
          animation_host()->scroll_offset_animations().HasUpdatesForTesting());
    }
  }

  void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->sync_tree()->source_frame_number() == 0) {
      GetImplAnimationHost(host_impl)->ImplOnlyScrollAnimationCreate(
          scroll_layer_->element_id(), gfx::ScrollOffset(650.f, 750.f),
          gfx::ScrollOffset(10, 20), base::TimeDelta(), base::TimeDelta());
    }
  }

  void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
                               int target_property,
                               base::TimeTicks animation_start_time,
                               std::unique_ptr<AnimationCurve> curve) override {
    EndTest();
  }

  void AfterTest() override {}

 private:
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> scroll_layer_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationTakeover);

// Verifies that an impl-only scroll offset animation gets updated when the
// scroll offset is adjusted on the main thread.
class LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted() = default;

  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    scroll_layer_ = FakePictureLayer::Create(&client_);
    scroll_layer_->SetBounds(gfx::Size(10000, 10000));
    client_.set_bounds(scroll_layer_->bounds());
    scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20));
    scroll_layer_->SetScrollable(gfx::Size(10, 10));
    layer_tree_host()->root_layer()->AddChild(scroll_layer_);

    AttachAnimationsToTimeline();
  }

  KeyframeEffect& ScrollOffsetKeyframeEffect(
      const LayerTreeHostImpl& host_impl,
      scoped_refptr<FakePictureLayer> layer) const {
    scoped_refptr<ElementAnimations> element_animations =
        GetImplAnimationHost(&host_impl)
            ->GetElementAnimationsForElementId(layer->element_id());
    DCHECK(element_animations);
    KeyframeEffect* keyframe_effect =
        &*element_animations->FirstKeyframeEffectForTesting();
    DCHECK(keyframe_effect);
    return *keyframe_effect;
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      // Add an update after the first commit to trigger the animation update
      // path.
      animation_host()->scroll_offset_animations().AddAdjustmentUpdate(
          scroll_layer_->element_id(), gfx::Vector2dF(100.f, 100.f));
      EXPECT_TRUE(
          animation_host()->scroll_offset_animations().HasUpdatesForTesting());
    } else if (layer_tree_host()->SourceFrameNumber() == 2) {
      // Verify that the update queue is cleared after the update is applied.
      EXPECT_FALSE(
          animation_host()->scroll_offset_animations().HasUpdatesForTesting());
    }
  }

  void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
    // Note that the frame number gets incremented after BeginCommitOnThread but
    // before WillCommitCompleteOnThread and CommitCompleteOnThread.
    if (host_impl->sync_tree()->source_frame_number() == 0) {
      GetImplTimelineAndAnimationByID(*host_impl);
      // This happens after the impl-only animation is added in
      // WillCommitCompleteOnThread.
      KeyframeModel* keyframe_model =
          ScrollOffsetKeyframeEffect(*host_impl, scroll_layer_)
              .GetKeyframeModel(TargetProperty::SCROLL_OFFSET);
      DCHECK(keyframe_model);
      ScrollOffsetAnimationCurve* curve =
          keyframe_model->curve()->ToScrollOffsetAnimationCurve();

      // Verifiy the initial and target position before the scroll offset
      // update from MT.
      EXPECT_EQ(gfx::ScrollOffset(10.f, 20.f),
                curve->GetValue(base::TimeDelta()));
      EXPECT_EQ(gfx::ScrollOffset(650.f, 750.f), curve->target_value());
    }
  }

  void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->sync_tree()->source_frame_number() == 0) {
      GetImplAnimationHost(host_impl)->ImplOnlyScrollAnimationCreate(
          scroll_layer_->element_id(), gfx::ScrollOffset(650.f, 750.f),
          gfx::ScrollOffset(10, 20), base::TimeDelta(), base::TimeDelta());
    }
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->sync_tree()->source_frame_number() == 1) {
      KeyframeModel* keyframe_model =
          ScrollOffsetKeyframeEffect(*host_impl, scroll_layer_)
              .GetKeyframeModel(TargetProperty::SCROLL_OFFSET);
      DCHECK(keyframe_model);
      ScrollOffsetAnimationCurve* curve =
          keyframe_model->curve()->ToScrollOffsetAnimationCurve();
      // Verifiy the initial and target position after the scroll offset
      // update from MT
      EXPECT_EQ(KeyframeModel::RunState::STARTING, keyframe_model->run_state());
      EXPECT_EQ(gfx::ScrollOffset(110.f, 120.f),
                curve->GetValue(base::TimeDelta()));
      EXPECT_EQ(gfx::ScrollOffset(750.f, 850.f), curve->target_value());

      EndTest();
    }
  }

  void AfterTest() override {}

 private:
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> scroll_layer_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted);

// Tests that presentation-time requested from the main-thread is attached to
// the correct frame (i.e. activation needs to happen before the
// presentation-request is attached to the frame).
class LayerTreeHostPresentationDuringAnimation
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    scroll_layer_ = FakePictureLayer::Create(&client_);
    scroll_layer_->SetScrollable(gfx::Size(100, 100));
    scroll_layer_->SetBounds(gfx::Size(10000, 10000));
    client_.set_bounds(scroll_layer_->bounds());
    scroll_layer_->SetScrollOffset(gfx::ScrollOffset(100.0, 200.0));
    layer_tree_host()->root_layer()->AddChild(scroll_layer_);

    std::unique_ptr<ScrollOffsetAnimationCurve> curve(
        ScrollOffsetAnimationCurve::Create(
            gfx::ScrollOffset(6500.f, 7500.f),
            CubicBezierTimingFunction::CreatePreset(
                CubicBezierTimingFunction::EaseType::EASE_IN_OUT)));
    std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create(
        std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET));
    keyframe_model->set_needs_synchronized_start_time(true);

    AttachAnimationsToTimeline();
    animation_child_->AttachElement(scroll_layer_->element_id());
    animation_child_->AddKeyframeModel(std::move(keyframe_model));
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    PostSetNeedsCommitToMainThread();
  }

  void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->active_tree()->source_frame_number() == 1) {
      request_token_ = host_impl->next_frame_token();
      layer_tree_host()->RequestPresentationTimeForNextFrame(base::BindOnce(
          &LayerTreeHostPresentationDuringAnimation::OnPresentation,
          base::Unretained(this)));
      host_impl->BlockNotifyReadyToActivateForTesting(true);
    }
  }

  void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
                                  const viz::BeginFrameArgs& args) override {
    if (host_impl->next_frame_token() >= 5)
      host_impl->BlockNotifyReadyToActivateForTesting(false);
  }

  void DisplayReceivedCompositorFrameOnThread(
      const viz::CompositorFrame& frame) override {
    received_token_ = frame.metadata.frame_token;
  }

  void AfterTest() override {
    EXPECT_GT(request_token_, 0u);
    EXPECT_GT(received_token_, request_token_);
    EXPECT_GE(received_token_, 5u);
  }

 private:
  void OnPresentation(const gfx::PresentationFeedback& feedback) { EndTest(); }

  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> scroll_layer_;
  uint32_t request_token_ = 0;
  uint32_t received_token_ = 0;
};

MULTI_THREAD_TEST_F(LayerTreeHostPresentationDuringAnimation);

// Verifies that when the main thread removes a scroll animation and sets a new
// scroll position, the active tree takes on exactly this new scroll position
// after activation, and the main thread doesn't receive a spurious scroll
// delta.
class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestScrollOffsetAnimationRemoval()
      : final_postion_(50.0, 100.0) {}

  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    scroll_layer_ = FakePictureLayer::Create(&client_);
    scroll_layer_->SetScrollable(gfx::Size(100, 100));
    scroll_layer_->SetBounds(gfx::Size(10000, 10000));
    client_.set_bounds(scroll_layer_->bounds());
    scroll_layer_->SetScrollOffset(gfx::ScrollOffset(100.0, 200.0));
    layer_tree_host()->root_layer()->AddChild(scroll_layer_);

    std::unique_ptr<ScrollOffsetAnimationCurve> curve(
        ScrollOffsetAnimationCurve::Create(
            gfx::ScrollOffset(6500.f, 7500.f),
            CubicBezierTimingFunction::CreatePreset(
                CubicBezierTimingFunction::EaseType::EASE_IN_OUT)));
    std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create(
        std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET));
    keyframe_model->set_needs_synchronized_start_time(true);

    AttachAnimationsToTimeline();
    animation_child_->AttachElement(scroll_layer_->element_id());
    animation_child_->AddKeyframeModel(std::move(keyframe_model));
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 0:
        EXPECT_EQ(scroll_layer_->CurrentScrollOffset().x(), 100);
        EXPECT_EQ(scroll_layer_->CurrentScrollOffset().y(), 200);
        break;
      case 1: {
        EXPECT_GE(scroll_layer_->CurrentScrollOffset().x(), 100);
        EXPECT_GE(scroll_layer_->CurrentScrollOffset().y(), 200);
        KeyframeModel* keyframe_model =
            animation_child_->GetKeyframeModel(TargetProperty::SCROLL_OFFSET);
        animation_child_->RemoveKeyframeModel(keyframe_model->id());
        scroll_layer_->SetScrollOffset(final_postion_);
        break;
      }
      default:
        EXPECT_EQ(final_postion_, scroll_layer_->CurrentScrollOffset());
    }
  }

  void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
    host_impl->BlockNotifyReadyToActivateForTesting(
        ShouldBlockActivation(host_impl));
  }

  void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
                                  const viz::BeginFrameArgs& args) override {
    host_impl->BlockNotifyReadyToActivateForTesting(
        ShouldBlockActivation(host_impl));
  }

  void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->pending_tree()->source_frame_number() != 1)
      return;
    LayerImpl* scroll_layer_impl =
        host_impl->pending_tree()->LayerById(scroll_layer_->id());
    EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset());
  }

  void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->active_tree()->source_frame_number() != 1)
      return;
    LayerImpl* scroll_layer_impl =
        host_impl->active_tree()->LayerById(scroll_layer_->id());
    EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset());
    EndTest();
  }

  void AfterTest() override {
    EXPECT_EQ(final_postion_, scroll_layer_->CurrentScrollOffset());
  }

 private:
  bool ShouldBlockActivation(LayerTreeHostImpl* host_impl) {
    if (!host_impl->pending_tree())
      return false;

    if (!host_impl->active_tree()->root_layer_for_testing())
      return false;

    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<SingleKeyframeEffectAnimation> animation_impl =
        static_cast<SingleKeyframeEffectAnimation*>(
            timeline_impl->GetAnimationById(animation_child_id_));

    LayerImpl* scroll_layer_impl =
        host_impl->active_tree()->LayerById(scroll_layer_->id());
    KeyframeModel* keyframe_model =
        animation_impl->GetKeyframeModel(TargetProperty::SCROLL_OFFSET);

    if (!keyframe_model ||
        keyframe_model->run_state() != KeyframeModel::RUNNING)
      return false;

    // Block activation until the running animation has a chance to produce a
    // scroll delta.
    gfx::Vector2dF scroll_delta = ScrollDelta(scroll_layer_impl);
    if (scroll_delta.x() > 0.f || scroll_delta.y() > 0.f)
      return false;

    return true;
  }

  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> scroll_layer_;
  const gfx::ScrollOffset final_postion_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationRemoval);

// When animations are simultaneously added to an existing layer and to a new
// layer, they should start at the same time, even when there's already a
// running animation on the existing layer.
class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers()
      : frame_count_with_pending_tree_(0) {}

  void BeginTest() override {
    AttachAnimationsToTimeline();
    PostSetNeedsCommitToMainThread();
  }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
      AddAnimatedTransformToAnimation(animation_.get(), 4, 1, 1);
    } else if (layer_tree_host()->SourceFrameNumber() == 2) {
      AddOpacityTransitionToAnimation(animation_.get(), 1, 0.f, 0.5f, true);

      scoped_refptr<Layer> layer = Layer::Create();
      layer_tree_host()->root_layer()->AddChild(layer);

      layer_tree_host()->SetElementIdsForTesting();
      layer->SetBounds(gfx::Size(4, 4));

      animation_child_->AttachElement(layer->element_id());
      animation_child_->set_animation_delegate(this);
      AddOpacityTransitionToAnimation(animation_child_.get(), 1, 0.f, 0.5f,
                                      true);
    }
  }

  void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
    host_impl->BlockNotifyReadyToActivateForTesting(true);
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    // For the commit that added animations to new and existing layers, keep
    // blocking activation. We want to verify that even with activation blocked,
    // the animation on the layer that's already in the active tree won't get a
    // head start.
    if (host_impl->pending_tree()->source_frame_number() != 2) {
      host_impl->BlockNotifyReadyToActivateForTesting(false);
    }
  }

  void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
                                  const viz::BeginFrameArgs& args) override {
    if (!host_impl->pending_tree() ||
        host_impl->pending_tree()->source_frame_number() != 2)
      return;

    frame_count_with_pending_tree_++;
    if (frame_count_with_pending_tree_ == 2) {
      host_impl->BlockNotifyReadyToActivateForTesting(false);
    }
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<SingleKeyframeEffectAnimation> animation_impl =
        static_cast<SingleKeyframeEffectAnimation*>(
            timeline_impl->GetAnimationById(animation_id_));
    scoped_refptr<SingleKeyframeEffectAnimation> animation_child_impl =
        static_cast<SingleKeyframeEffectAnimation*>(
            timeline_impl->GetAnimationById(animation_child_id_));

    // wait for tree activation.
    if (!animation_impl->keyframe_effect()->element_animations())
      return;

    KeyframeModel* root_keyframe_model =
        animation_impl->GetKeyframeModel(TargetProperty::OPACITY);
    if (!root_keyframe_model ||
        root_keyframe_model->run_state() != KeyframeModel::RUNNING)
      return;

    KeyframeModel* child_keyframe_model =
        animation_child_impl->GetKeyframeModel(TargetProperty::OPACITY);
    EXPECT_EQ(KeyframeModel::RUNNING, child_keyframe_model->run_state());
    EXPECT_EQ(root_keyframe_model->start_time(),
              child_keyframe_model->start_time());
    animation_impl->AbortKeyframeModelsWithProperty(TargetProperty::OPACITY,
                                                    false);
    animation_impl->AbortKeyframeModelsWithProperty(TargetProperty::TRANSFORM,
                                                    false);
    animation_child_impl->AbortKeyframeModelsWithProperty(
        TargetProperty::OPACITY, false);
    EndTest();
  }

  void AfterTest() override {}

 private:
  int frame_count_with_pending_tree_;
};

// This test blocks activation which is not supported for single thread mode.
MULTI_THREAD_BLOCKNOTIFY_TEST_F(
    LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers);

class LayerTreeHostAnimationTestPendingTreeAnimatesFirstCommit
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(2, 2));
    client_.set_bounds(layer_->bounds());
    // Transform the layer to 4,4 to start.
    gfx::Transform start_transform;
    start_transform.Translate(4.0, 4.0);
    layer_->SetTransform(start_transform);

    layer_tree_host()->root_layer()->AddChild(layer_);
    layer_tree_host()->SetElementIdsForTesting();

    animation_->AttachElement(layer_->element_id());

    AttachAnimationsToTimeline();
  }

  void BeginTest() override {
    // Add a translate from 6,7 to 8,9.
    TransformOperations start;
    start.AppendTranslate(6.f, 7.f, 0.f);
    TransformOperations end;
    end.AppendTranslate(8.f, 9.f, 0.f);
    AddAnimatedTransformToAnimation(animation_.get(), 4.0, start, end);

    PostSetNeedsCommitToMainThread();
  }

  void WillPrepareTilesOnThread(LayerTreeHostImpl* host_impl) override {
    // After activating the sync tree PrepareTiles will be called
    // again (which races with the test exiting).
    LayerTreeImpl* sync_tree = host_impl->sync_tree();
    if (!sync_tree || TestEnded())
      return;

    if (sync_tree->source_frame_number() != 0)
      return;

    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<SingleKeyframeEffectAnimation> animation_impl =
        static_cast<SingleKeyframeEffectAnimation*>(
            timeline_impl->GetAnimationById(animation_id_));

    LayerImpl* child = sync_tree->LayerById(layer_->id());
    KeyframeModel* keyframe_model =
        animation_impl->GetKeyframeModel(TargetProperty::TRANSFORM);

    // The animation should be starting for the first frame.
    EXPECT_EQ(KeyframeModel::STARTING, keyframe_model->run_state());

    // And the transform should be propogated to the sync tree layer, at its
    // starting state which is 6,7.
    gfx::Transform expected_transform;
    expected_transform.Translate(6.0, 7.0);
    EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, child->DrawTransform());
    // And the sync tree layer should know it is animating.
    EXPECT_TRUE(child->screen_space_transform_is_animating());

    animation_impl->AbortKeyframeModelsWithProperty(TargetProperty::TRANSFORM,
                                                    false);
    EndTest();
  }

  void AfterTest() override {}

  FakeContentLayerClient client_;
  scoped_refptr<Layer> layer_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestPendingTreeAnimatesFirstCommit);

// When a layer with an animation is removed from the tree and later re-added,
// the animation should resume.
class LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = Layer::Create();
    layer_->SetBounds(gfx::Size(4, 4));
    layer_tree_host()->root_layer()->AddChild(layer_);

    layer_tree_host()->SetElementIdsForTesting();

    animation_host()->AddAnimationTimeline(timeline_.get());
    timeline_->AttachAnimation(animation_.get());
    animation_->AttachElement(layer_->element_id());
    DCHECK(animation_->keyframe_effect()->element_animations());

    AddOpacityTransitionToAnimation(animation_.get(), 10000.0, 0.1f, 0.9f,
                                    true);
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 0:
        EXPECT_TRUE(animation_->keyframe_effect()
                        ->element_animations()
                        ->has_element_in_active_list());
        EXPECT_FALSE(animation_->keyframe_effect()
                         ->element_animations()
                         ->has_element_in_pending_list());
        EXPECT_TRUE(animation_host()->NeedsTickAnimations());
        break;
      case 1:
        layer_->RemoveFromParent();
        EXPECT_FALSE(animation_->keyframe_effect()
                         ->element_animations()
                         ->has_element_in_active_list());
        EXPECT_FALSE(animation_->keyframe_effect()
                         ->element_animations()
                         ->has_element_in_pending_list());
        // Animations still need one more tick to deliver finished event.
        EXPECT_TRUE(animation_host()->NeedsTickAnimations());
        break;
      case 2:
        EXPECT_FALSE(animation_host()->NeedsTickAnimations());
        layer_tree_host()->root_layer()->AddChild(layer_);
        EXPECT_TRUE(animation_->keyframe_effect()
                        ->element_animations()
                        ->has_element_in_active_list());
        EXPECT_FALSE(animation_->keyframe_effect()
                         ->element_animations()
                         ->has_element_in_pending_list());
        EXPECT_TRUE(animation_host()->NeedsTickAnimations());
        break;
    }
  }

  void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<SingleKeyframeEffectAnimation> animation_impl =
        static_cast<SingleKeyframeEffectAnimation*>(
            timeline_impl->GetAnimationById(animation_id_));

    switch (host_impl->active_tree()->source_frame_number()) {
      case 0:
        EXPECT_TRUE(animation_impl->keyframe_effect()
                        ->element_animations()
                        ->has_element_in_active_list());
        EXPECT_TRUE(GetImplAnimationHost(host_impl)->NeedsTickAnimations());
        break;
      case 1:
        EXPECT_FALSE(animation_impl->keyframe_effect()
                         ->element_animations()
                         ->has_element_in_active_list());
        // Having updated state on the host_impl during the commit, we no longer
        // need to tick animations.
        EXPECT_FALSE(GetImplAnimationHost(host_impl)->NeedsTickAnimations());
        break;
      case 2:
        EXPECT_TRUE(animation_impl->keyframe_effect()
                        ->element_animations()
                        ->has_element_in_active_list());
        EXPECT_TRUE(GetImplAnimationHost(host_impl)->NeedsTickAnimations());
        EndTest();
        break;
    }
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded);

class LayerTreeHostAnimationTestAddKeyframeModelAfterAnimating
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = Layer::Create();
    layer_->SetBounds(gfx::Size(4, 4));
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachAnimationsToTimeline();

    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    animation_child_->AttachElement(layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 1:
        // First frame: add an animation to the root layer.
        AddAnimatedTransformToAnimation(animation_.get(), 0.1, 5, 5);
        break;
      case 2:
        // Second frame: add an animation to the content layer. The root layer
        // animation has caused us to animate already during this frame.
        AddOpacityTransitionToAnimation(animation_child_.get(), 0.1, 5, 5,
                                        false);
        break;
    }
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    // After both animations have started, verify that they have valid
    // start times.
    if (host_impl->active_tree()->source_frame_number() < 2)
      return;

    // Animation state is updated after drawing. Only do this once.
    if (!TestEnded()) {
      ImplThreadTaskRunner()->PostTask(
          FROM_HERE,
          base::BindOnce(
              &LayerTreeHostAnimationTestAddKeyframeModelAfterAnimating::
                  CheckAnimations,
              base::Unretained(this), host_impl));
    }
  }

  void CheckAnimations(LayerTreeHostImpl* host_impl) {
    GetImplTimelineAndAnimationByID(*host_impl);

    EXPECT_EQ(2u, GetImplAnimationHost(host_impl)
                      ->ticking_animations_for_testing()
                      .size());

    KeyframeModel* root_anim =
        animation_impl_->GetKeyframeModel(TargetProperty::TRANSFORM);
    EXPECT_LT(base::TimeTicks(), root_anim->start_time());

    KeyframeModel* anim =
        animation_child_impl_->GetKeyframeModel(TargetProperty::OPACITY);
    EXPECT_LT(base::TimeTicks(), anim->start_time());

    EndTest();
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestAddKeyframeModelAfterAnimating);

class LayerTreeHostAnimationTestRemoveKeyframeModel
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachAnimationsToTimeline();

    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    animation_child_->AttachElement(layer_->element_id());
  }

  void BeginTest() override {
    animation_stopped_ = false;
    last_frame_number_ = INT_MAX;
    PostSetNeedsCommitToMainThread();
  }

  void DidCommit() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 1:
        AddAnimatedTransformToAnimation(animation_child_.get(), 1.0, 5, 5);
        break;
      case 2:
        KeyframeModel* keyframe_model =
            animation_child_->GetKeyframeModel(TargetProperty::TRANSFORM);
        animation_child_->RemoveKeyframeModel(keyframe_model->id());
        gfx::Transform transform;
        transform.Translate(10.f, 10.f);
        layer_->SetTransform(transform);

        // Do something that causes property trees to get rebuilt. This is
        // intended to simulate the conditions that caused the bug whose fix
        // this is testing (the test will pass without it but won't test what
        // we want it to). We were updating the wrong transform node at the end
        // of an animation (we were assuming the layer with the finished
        // animation still had its own transform node). But nodes can only get
        // added/deleted when something triggers a rebuild. Adding a layer
        // triggers a rebuild, and since the layer that had an animation before
        // no longer has one, it doesn't get a transform node in the rebuild.
        layer_->AddChild(Layer::Create());
        break;
    }
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    GetImplTimelineAndAnimationByID(*host_impl);
    LayerImpl* child = host_impl->active_tree()->LayerById(layer_->id());
    switch (host_impl->active_tree()->source_frame_number()) {
      case 0:
        // No animation yet.
        break;
      case 1:
        // Animation is started.
        EXPECT_TRUE(child->screen_space_transform_is_animating());
        break;
      case 2: {
        // The animation is stopped, the transform that was set afterward is
        // applied.
        gfx::Transform expected_transform;
        expected_transform.Translate(10.f, 10.f);
        EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform,
                                        child->DrawTransform());
        EXPECT_FALSE(child->screen_space_transform_is_animating());
        animation_stopped_ = true;
        PostSetNeedsCommitToMainThread();
        break;
      }
    }
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->sync_tree()->source_frame_number() >= last_frame_number_) {
      // Check that eventually the animation is removed.
      EXPECT_FALSE(
          animation_child_impl_->keyframe_effect()->has_any_keyframe_model());
      EndTest();
    }
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    // Non impl only animations are removed during commit. After the animation
    // is fully stopped on compositor thread, make sure another commit happens.
    if (animation_stopped_ && !has_unfinished_animation) {
      last_frame_number_ =
          std::min(last_frame_number_,
                   host_impl->active_tree()->source_frame_number() + 1);
      PostSetNeedsCommitToMainThread();
    }
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;

  int last_frame_number_;
  bool animation_stopped_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestRemoveKeyframeModel);

class LayerTreeHostAnimationTestIsAnimating
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachAnimationsToTimeline();
    animation_->AttachElement(layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 1:
        AddAnimatedTransformToAnimation(animation_.get(), 1.0, 5, 5);
        break;
      case 2:
        KeyframeModel* keyframe_model =
            animation_->GetKeyframeModel(TargetProperty::TRANSFORM);
        animation_->RemoveKeyframeModel(keyframe_model->id());
        break;
    }
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    LayerImpl* child = host_impl->sync_tree()->LayerById(layer_->id());
    switch (host_impl->sync_tree()->source_frame_number()) {
      case 0:
        // No animation yet.
        break;
      case 1:
        // Animation is started.
        EXPECT_TRUE(child->screen_space_transform_is_animating());
        break;
      case 2:
        // The animation is removed/stopped.
        EXPECT_FALSE(child->screen_space_transform_is_animating());
        EndTest();
        break;
      default:
        NOTREACHED();
    }
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    LayerImpl* child = host_impl->active_tree()->LayerById(layer_->id());
    switch (host_impl->active_tree()->source_frame_number()) {
      case 0:
        // No animation yet.
        break;
      case 1:
        // Animation is started.
        EXPECT_TRUE(child->screen_space_transform_is_animating());
        break;
      case 2:
        // The animation is removed/stopped.
        EXPECT_FALSE(child->screen_space_transform_is_animating());
        EndTest();
        break;
      default:
        NOTREACHED();
    }
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestIsAnimating);

class LayerTreeHostAnimationTestAnimationFinishesDuringCommit
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestAnimationFinishesDuringCommit()
      : signalled_(false) {}

  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachAnimationsToTimeline();

    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    animation_child_->AttachElement(layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1)
      AddAnimatedTransformToAnimation(animation_child_.get(), 0.04, 5, 5);
  }

  void WillCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 2) {
      // Block until the animation finishes on the compositor thread. Since
      // animations have already been ticked on the main thread, when the commit
      // happens the state on the main thread will be consistent with having a
      // running animation but the state on the compositor thread will be
      // consistent with having only a finished animation.
      completion_.Wait();
    }
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    switch (host_impl->sync_tree()->source_frame_number()) {
      case 1:
        PostSetNeedsCommitToMainThread();
        break;
      case 2:
        gfx::Transform expected_transform;
        expected_transform.Translate(5.f, 5.f);
        LayerImpl* layer_impl = host_impl->sync_tree()->LayerById(layer_->id());
        EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform,
                                        layer_impl->DrawTransform());
        EndTest();
        break;
    }
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    if (host_impl->active_tree()->source_frame_number() == 1 &&
        !has_unfinished_animation && !signalled_) {
      // The animation has finished, so allow the main thread to commit.
      completion_.Signal();
      signalled_ = true;
    }
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;
  CompletionEvent completion_;
  bool signalled_;
};

// An animation finishing during commit can only happen when we have a separate
// compositor thread.
MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationFinishesDuringCommit);

class LayerTreeHostAnimationTestImplSideInvalidation
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachAnimationsToTimeline();

    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    animation_child_->AttachElement(layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1)
      AddAnimatedTransformToAnimation(animation_child_.get(), 0.04, 5, 5);
  }

  void WillCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 2) {
      // Block until the animation finishes on the compositor thread. Since
      // animations have already been ticked on the main thread, when the commit
      // happens the state on the main thread will be consistent with having a
      // running animation but the state on the compositor thread will be
      // consistent with having only a finished animation.
      completion_.Wait();
    }
  }

  void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) override {
    DCHECK(did_request_impl_side_invalidation_);
    completion_.Signal();
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    if (host_impl->active_tree()->source_frame_number() == 1 &&
        !has_unfinished_animation && !did_request_impl_side_invalidation_) {
      // The animation on the active tree has finished, now request an impl-side
      // invalidation and make sure it finishes before the main thread is
      // released.
      did_request_impl_side_invalidation_ = true;
      host_impl->RequestImplSideInvalidationForCheckerImagedTiles();
    }
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    switch (host_impl->sync_tree()->source_frame_number()) {
      case 1:
        PostSetNeedsCommitToMainThread();
        break;
      case 2:
        gfx::Transform expected_transform;
        expected_transform.Translate(5.f, 5.f);
        LayerImpl* layer_impl = host_impl->sync_tree()->LayerById(layer_->id());
        EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform,
                                        layer_impl->DrawTransform());
        EndTest();
        break;
    }
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;
  CompletionEvent completion_;
  bool did_request_impl_side_invalidation_ = false;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestImplSideInvalidation);

class LayerTreeHostAnimationTestImplSideInvalidationWithoutCommit
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);
    AttachAnimationsToTimeline();
    animation_child_->AttachElement(layer_->element_id());
    num_draws_ = 0;
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    if (!has_unfinished_animation && !did_request_impl_side_invalidation_) {
      // The animation on the active tree has finished, now request an impl-side
      // invalidation and verify that the final value on an impl-side pending
      // tree is correct.
      did_request_impl_side_invalidation_ = true;
      host_impl->RequestImplSideInvalidationForCheckerImagedTiles();
    }
  }

  void AfterTest() override {}

 protected:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;
  bool did_request_impl_side_invalidation_ = false;
  int num_draws_;
};

class ImplSideInvalidationWithoutCommitTestOpacity
    : public LayerTreeHostAnimationTestImplSideInvalidationWithoutCommit {
 public:
  void BeginTest() override {
    AddOpacityTransitionToAnimation(animation_child_.get(), 0.04, 0.2f, 0.8f,
                                    false);
    PostSetNeedsCommitToMainThread();
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    if (num_draws_++ > 0)
      return;
    EXPECT_EQ(0, host_impl->active_tree()->source_frame_number());
    LayerImpl* layer_impl = host_impl->active_tree()->LayerById(layer_->id());
    EXPECT_FLOAT_EQ(0.2f, layer_impl->Opacity());
  }

  void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) override {
    ASSERT_TRUE(did_request_impl_side_invalidation_);
    EXPECT_EQ(0, host_impl->sync_tree()->source_frame_number());
    const float expected_opacity = 0.8f;
    LayerImpl* layer_impl = host_impl->sync_tree()->LayerById(layer_->id());
    EXPECT_FLOAT_EQ(expected_opacity, layer_impl->Opacity());
    EndTest();
  }
};

MULTI_THREAD_TEST_F(ImplSideInvalidationWithoutCommitTestOpacity);

class ImplSideInvalidationWithoutCommitTestTransform
    : public LayerTreeHostAnimationTestImplSideInvalidationWithoutCommit {
 public:
  void BeginTest() override {
    AddAnimatedTransformToAnimation(animation_child_.get(), 0.04, 5, 5);
    PostSetNeedsCommitToMainThread();
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    if (num_draws_++ > 0)
      return;
    EXPECT_EQ(0, host_impl->active_tree()->source_frame_number());
    LayerImpl* layer_impl = host_impl->active_tree()->LayerById(layer_->id());
    EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(),
                                    layer_impl->DrawTransform());
  }

  void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) override {
    ASSERT_TRUE(did_request_impl_side_invalidation_);
    EXPECT_EQ(0, host_impl->sync_tree()->source_frame_number());
    gfx::Transform expected_transform;
    expected_transform.Translate(5.f, 5.f);
    LayerImpl* layer_impl = host_impl->sync_tree()->LayerById(layer_->id());
    EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform,
                                    layer_impl->DrawTransform());
    EndTest();
  }
};

MULTI_THREAD_TEST_F(ImplSideInvalidationWithoutCommitTestTransform);

class ImplSideInvalidationWithoutCommitTestFilter
    : public LayerTreeHostAnimationTestImplSideInvalidationWithoutCommit {
 public:
  void BeginTest() override {
    AddAnimatedFilterToAnimation(animation_child_.get(), 0.04, 0.f, 1.f);
    PostSetNeedsCommitToMainThread();
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    if (num_draws_++ > 0)
      return;
    EXPECT_EQ(0, host_impl->active_tree()->source_frame_number());
    EXPECT_EQ(
        std::string("{\"FilterOperations\":[{\"type\":5,\"amount\":0.0}]}"),
        host_impl->active_tree()
            ->property_trees()
            ->effect_tree.FindNodeFromElementId(layer_->element_id())
            ->filters.ToString());
  }

  void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) override {
    ASSERT_TRUE(did_request_impl_side_invalidation_);
    EXPECT_EQ(0, host_impl->sync_tree()->source_frame_number());
    // AddAnimatedFilterToAnimation adds brightness filter which is type 5.
    EXPECT_EQ(
        std::string("{\"FilterOperations\":[{\"type\":5,\"amount\":1.0}]}"),
        host_impl->sync_tree()
            ->property_trees()
            ->effect_tree.FindNodeFromElementId(layer_->element_id())
            ->filters.ToString());
    EndTest();
  }
};

MULTI_THREAD_TEST_F(ImplSideInvalidationWithoutCommitTestFilter);

class ImplSideInvalidationWithoutCommitTestScroll
    : public LayerTreeHostAnimationTestImplSideInvalidationWithoutCommit {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTestImplSideInvalidationWithoutCommit::SetupTree();

    layer_->SetScrollable(gfx::Size(100, 100));
    layer_->SetBounds(gfx::Size(1000, 1000));
    client_.set_bounds(layer_->bounds());
    layer_->SetScrollOffset(gfx::ScrollOffset(10.f, 20.f));
  }

  void BeginTest() override {
    std::unique_ptr<ScrollOffsetAnimationCurve> curve(
        ScrollOffsetAnimationCurve::Create(
            gfx::ScrollOffset(500.f, 550.f),
            CubicBezierTimingFunction::CreatePreset(
                CubicBezierTimingFunction::EaseType::EASE_IN_OUT)));
    std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create(
        std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET));
    keyframe_model->set_needs_synchronized_start_time(true);
    ASSERT_TRUE(proxy()->SupportsImplScrolling());
    animation_child_->AddKeyframeModel(std::move(keyframe_model));
    PostSetNeedsCommitToMainThread();
  }

  void WillCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      // Block until the invalidation is done after animation finishes on the
      // compositor thread. We need to make sure the pending tree has valid
      // information based on invalidation only.
      completion_.Wait();
    }
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    if (num_draws_++ > 0)
      return;
    EXPECT_EQ(0, host_impl->active_tree()->source_frame_number());
    LayerImpl* layer_impl = host_impl->active_tree()->LayerById(layer_->id());
    EXPECT_VECTOR2DF_EQ(gfx::ScrollOffset(10.f, 20.f),
                        layer_impl->CurrentScrollOffset());
  }

  void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) override {
    ASSERT_TRUE(did_request_impl_side_invalidation_);
    EXPECT_EQ(0, host_impl->sync_tree()->source_frame_number());
    LayerImpl* layer_impl = host_impl->pending_tree()->LayerById(layer_->id());
    EXPECT_VECTOR2DF_EQ(gfx::ScrollOffset(500.f, 550.f),
                        layer_impl->CurrentScrollOffset());
    completion_.Signal();
    EndTest();
  }

 private:
  CompletionEvent completion_;
};

MULTI_THREAD_TEST_F(ImplSideInvalidationWithoutCommitTestScroll);

class LayerTreeHostAnimationTestNotifyAnimationFinished
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestNotifyAnimationFinished()
      : called_animation_started_(false), called_animation_finished_(false) {}

  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    picture_ = FakePictureLayer::Create(&client_);
    picture_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(picture_->bounds());
    layer_tree_host()->root_layer()->AddChild(picture_);

    AttachAnimationsToTimeline();
    animation_->AttachElement(picture_->element_id());
    animation_->set_animation_delegate(this);
  }

  void BeginTest() override {
    PostAddOpacityAnimationToMainThreadDelayed(animation_.get());
  }

  void NotifyAnimationStarted(base::TimeTicks monotonic_time,
                              int target_property,
                              int group) override {
    called_animation_started_ = true;
    layer_tree_host()->AnimateLayers(base::TimeTicks::Max());
    PostSetNeedsCommitToMainThread();
  }

  void NotifyAnimationFinished(base::TimeTicks monotonic_time,
                               int target_property,
                               int group) override {
    called_animation_finished_ = true;
    EndTest();
  }

  void AfterTest() override {
    EXPECT_TRUE(called_animation_started_);
    EXPECT_TRUE(called_animation_finished_);
  }

 private:
  bool called_animation_started_;
  bool called_animation_finished_;
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> picture_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestNotifyAnimationFinished);

// Check that transform sync happens correctly at commit when we remove and add
// a different animation animation to an element.
class LayerTreeHostAnimationTestChangeSingleKeyframeEffectAnimation
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    AttachAnimationsToTimeline();
    timeline_->DetachAnimation(animation_child_.get());
    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());

    TransformOperations start;
    start.AppendTranslate(5.f, 5.f, 0.f);
    TransformOperations end;
    end.AppendTranslate(5.f, 5.f, 0.f);
    AddAnimatedTransformToAnimation(animation_.get(), 1.0, start, end);
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    PropertyTrees* property_trees = host_impl->sync_tree()->property_trees();
    TransformNode* node =
        property_trees->transform_tree.Node(host_impl->sync_tree()
                                                ->root_layer_for_testing()
                                                ->transform_tree_index());
    gfx::Transform translate;
    translate.Translate(5, 5);
    switch (host_impl->sync_tree()->source_frame_number()) {
      case 2:
        EXPECT_TRANSFORMATION_MATRIX_EQ(node->local, translate);
        EndTest();
        break;
      default:
        break;
    }
  }

  void DidCommit() override { PostSetNeedsCommitToMainThread(); }

  void WillBeginMainFrame() override {
    if (layer_tree_host()->SourceFrameNumber() == 2) {
      // Destroy animation.
      timeline_->DetachAnimation(animation_.get());
      animation_ = nullptr;
      timeline_->AttachAnimation(animation_child_.get());
      animation_child_->AttachElement(
          layer_tree_host()->root_layer()->element_id());
      AddAnimatedTransformToAnimation(animation_child_.get(), 1.0, 10, 10);
      KeyframeModel* keyframe_model =
          animation_child_->GetKeyframeModel(TargetProperty::TRANSFORM);
      keyframe_model->set_start_time(base::TimeTicks::Now() +
                                     base::TimeDelta::FromSecondsD(1000));
      keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE);
    }
  }

  void AfterTest() override {}
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestChangeSingleKeyframeEffectAnimation);

// Check that SetTransformIsPotentiallyAnimatingChanged is called
// if we destroy ElementAnimations.
class LayerTreeHostAnimationTestSetPotentiallyAnimatingOnLacDestruction
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    prev_screen_space_transform_is_animating_ = true;
    screen_space_transform_animation_stopped_ = false;

    LayerTreeHostAnimationTest::SetupTree();
    AttachAnimationsToTimeline();
    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    AddAnimatedTransformToAnimation(animation_.get(), 1.0, 5, 5);
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->pending_tree()->source_frame_number() <= 1) {
      EXPECT_TRUE(host_impl->pending_tree()
                      ->root_layer_for_testing()
                      ->screen_space_transform_is_animating());
    } else {
      EXPECT_FALSE(host_impl->pending_tree()
                       ->root_layer_for_testing()
                       ->screen_space_transform_is_animating());
    }
  }

  void DidCommit() override { PostSetNeedsCommitToMainThread(); }

  void UpdateLayerTreeHost() override {
    if (layer_tree_host()->SourceFrameNumber() == 2) {
      // Destroy animation.
      timeline_->DetachAnimation(animation_.get());
      animation_ = nullptr;
    }
  }

  DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                   LayerTreeHostImpl::FrameData* frame_data,
                                   DrawResult draw_result) override {
    const bool screen_space_transform_is_animating =
        host_impl->active_tree()
            ->root_layer_for_testing()
            ->screen_space_transform_is_animating();

    // Check that screen_space_transform_is_animating changes only once.
    if (screen_space_transform_is_animating &&
        prev_screen_space_transform_is_animating_)
      EXPECT_FALSE(screen_space_transform_animation_stopped_);
    if (!screen_space_transform_is_animating &&
        prev_screen_space_transform_is_animating_) {
      EXPECT_FALSE(screen_space_transform_animation_stopped_);
      screen_space_transform_animation_stopped_ = true;
    }
    if (!screen_space_transform_is_animating &&
        !prev_screen_space_transform_is_animating_)
      EXPECT_TRUE(screen_space_transform_animation_stopped_);

    prev_screen_space_transform_is_animating_ =
        screen_space_transform_is_animating;

    return draw_result;
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->active_tree()->source_frame_number() >= 2)
      EndTest();
  }

  void AfterTest() override {
    EXPECT_TRUE(screen_space_transform_animation_stopped_);
  }

  bool prev_screen_space_transform_is_animating_;
  bool screen_space_transform_animation_stopped_;
};

MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestSetPotentiallyAnimatingOnLacDestruction);

// Check that we invalidate property trees on
// SingleKeyframeEffectAnimation::SetNeedsCommit.
class LayerTreeHostAnimationTestRebuildPropertyTreesOnAnimationSetNeedsCommit
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachAnimationsToTimeline();

    animation_->AttachElement(layer_tree_host()->root_layer()->element_id());
    animation_child_->AttachElement(layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1 ||
        layer_tree_host()->SourceFrameNumber() == 2)
      PostSetNeedsCommitToMainThread();
  }

  void UpdateLayerTreeHost() override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      EXPECT_FALSE(layer_tree_host()->property_trees()->needs_rebuild);
      AddAnimatedTransformToAnimation(animation_child_.get(), 1.0, 5, 5);
    }

    EXPECT_TRUE(layer_tree_host()->property_trees()->needs_rebuild);
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->active_tree()->source_frame_number() >= 2)
      EndTest();
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;
};

MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestRebuildPropertyTreesOnAnimationSetNeedsCommit);

}  // namespace
}  // namespace cc
