// 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.

#include "ui/compositor/layer_animator.h"

#include <memory>
#include <vector>

#include "base/compiler_specific.h"
#include "base/memory/raw_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/run_loop.h"
#include "base/test/scoped_mock_clock_override.h"
#include "base/test/task_environment.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/mutator_host.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_delegate.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator_collection.h"
#include "ui/compositor/layer_owner.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/compositor/test/layer_animator_test_controller.h"
#include "ui/compositor/test/test_compositor_host.h"
#include "ui/compositor/test/test_context_factories.h"
#include "ui/compositor/test/test_layer_animation_delegate.h"
#include "ui/compositor/test/test_layer_animation_observer.h"
#include "ui/compositor/test/test_utils.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/transform.h"

namespace ui {

namespace {

// Creates vector with two LayerAnimationSequences, based on |first| and
// |second| layer animation elements.
std::vector<LayerAnimationSequence*> CreateMultiSequence(
    std::unique_ptr<LayerAnimationElement> first,
    std::unique_ptr<LayerAnimationElement> second) {
  LayerAnimationSequence* first_sequence = new LayerAnimationSequence();
  first_sequence->AddElement(std::move(first));
  LayerAnimationSequence* second_sequence = new LayerAnimationSequence();
  second_sequence->AddElement(std::move(second));

  std::vector<ui::LayerAnimationSequence*> animations;
  animations.push_back(first_sequence);
  animations.push_back(second_sequence);
  return animations;
}

// Creates a default animator with timers disabled for test. |delegate| and
// |observer| are attached if non-null.
scoped_refptr<LayerAnimator> CreateDefaultTestAnimator(
    LayerAnimationDelegate* delegate,
    LayerAnimationObserver* observer) {
  scoped_refptr<LayerAnimator> animator =
      LayerAnimator::CreateDefaultAnimator();
  animator->set_disable_timer_for_test(true);
  if (delegate)
    animator->SetDelegate(delegate);
  if (observer)
    animator->AddObserver(observer);
  return animator;
}

// Creates a default animator with timers disabled for test. |delegate| is
// attached if non-null.
scoped_refptr<LayerAnimator> CreateDefaultTestAnimator(
    LayerAnimationDelegate* delegate) {
  return CreateDefaultTestAnimator(delegate, nullptr);
}

// Creates a default animator with timers disabled for test.
scoped_refptr<LayerAnimator> CreateDefaultTestAnimator() {
  return CreateDefaultTestAnimator(nullptr, nullptr);
}

// Creates an implicit animator with timers disabled for test. |delegate| and
// |observer| are attached if non-null.
scoped_refptr<LayerAnimator> CreateImplicitTestAnimator(
    LayerAnimationDelegate* delegate,
    LayerAnimationObserver* observer) {
  scoped_refptr<LayerAnimator> animator =
      LayerAnimator::CreateImplicitAnimator();
  animator->set_disable_timer_for_test(true);
  if (delegate)
    animator->SetDelegate(delegate);
  if (observer)
    animator->AddObserver(observer);
  return animator;
}

// Creates an implicit animator with timers disabled for test. |delegate| is
// attached if non-null.
scoped_refptr<LayerAnimator> CreateImplicitTestAnimator(
    LayerAnimationDelegate* delegate) {
  return CreateImplicitTestAnimator(delegate, nullptr);
}

// Creates an implicit animator with timers disabled for test.
scoped_refptr<LayerAnimator> CreateImplicitTestAnimator() {
  return CreateImplicitTestAnimator(nullptr, nullptr);
}

class TestImplicitAnimationObserver : public ImplicitAnimationObserver {
 public:
  explicit TestImplicitAnimationObserver(bool notify_when_animator_destructed)
    : animations_completed_(false),
      notify_when_animator_destructed_(notify_when_animator_destructed) {
  }

  TestImplicitAnimationObserver(const TestImplicitAnimationObserver&) = delete;
  TestImplicitAnimationObserver& operator=(
      const TestImplicitAnimationObserver&) = delete;

  bool animations_completed() const { return animations_completed_; }
  void set_animations_completed(bool completed) {
    animations_completed_ = completed;
  }

  void SetAnimationsCompletedCallback(base::RepeatingClosure callback) {
    animations_completed_callback_ = std::move(callback);
  }

  bool WasAnimationAbortedForProperty(
      LayerAnimationElement::AnimatableProperty property) const {
    return ImplicitAnimationObserver::WasAnimationAbortedForProperty(property);
  }

  bool WasAnimationCompletedForProperty(
      LayerAnimationElement::AnimatableProperty property) const {
    return ImplicitAnimationObserver::WasAnimationCompletedForProperty(
        property);
  }

  void Wait() {
    if (animations_completed_)
      return;

    base::RunLoop run_loop;
    quit_wait_loop_ = run_loop.QuitClosure();
    run_loop.Run();
  }

 private:
  // ImplicitAnimationObserver implementation
  void OnImplicitAnimationsCompleted() override {
    animations_completed_ = true;

    if (animations_completed_callback_)
      animations_completed_callback_.Run();

    if (quit_wait_loop_)
      std::move(quit_wait_loop_).Run();
  }

  bool RequiresNotificationWhenAnimatorDestroyed() const override {
    return notify_when_animator_destructed_;
  }

  bool animations_completed_;
  bool notify_when_animator_destructed_;
  base::RepeatingClosure animations_completed_callback_;

  base::OnceClosure quit_wait_loop_;
};

// When notified that an animation has ended, stops all other animations.
class DeletingLayerAnimationObserver : public LayerAnimationObserver {
 public:
  explicit DeletingLayerAnimationObserver(LayerAnimator* animator)
      : animator_(animator) {}

  DeletingLayerAnimationObserver(const DeletingLayerAnimationObserver&) =
      delete;
  DeletingLayerAnimationObserver& operator=(
      const DeletingLayerAnimationObserver&) = delete;

  void OnLayerAnimationEnded(LayerAnimationSequence* sequence) override {
    animator_->StopAnimating();
  }

  void OnLayerAnimationAborted(LayerAnimationSequence* sequence) override {
    animator_->StopAnimating();
  }

  void OnLayerAnimationScheduled(LayerAnimationSequence* sequence) override {}

 private:
  raw_ptr<LayerAnimator> animator_;
};

// When notified that an animation has started, aborts all animations.
class AbortAnimationsOnStartedLayerAnimationObserver
    : public LayerAnimationObserver {
 public:
  explicit AbortAnimationsOnStartedLayerAnimationObserver(
      LayerAnimator* animator)
      : animator_(animator) {}

  AbortAnimationsOnStartedLayerAnimationObserver(
      const AbortAnimationsOnStartedLayerAnimationObserver&) = delete;
  AbortAnimationsOnStartedLayerAnimationObserver& operator=(
      const AbortAnimationsOnStartedLayerAnimationObserver&) = delete;

  void OnLayerAnimationStarted(LayerAnimationSequence* sequence) override {
    animator_->AbortAllAnimations();
  }

  void OnLayerAnimationEnded(LayerAnimationSequence* sequence) override {}

  void OnLayerAnimationAborted(LayerAnimationSequence* sequence) override {}

  void OnLayerAnimationScheduled(LayerAnimationSequence* sequence) override {}

 private:
  raw_ptr<LayerAnimator> animator_;
};

class LayerAnimatorDestructionObserver {
 public:
  LayerAnimatorDestructionObserver() : animator_deleted_(false) {}

  LayerAnimatorDestructionObserver(const LayerAnimatorDestructionObserver&) =
      delete;
  LayerAnimatorDestructionObserver& operator=(
      const LayerAnimatorDestructionObserver&) = delete;

  virtual ~LayerAnimatorDestructionObserver() {}

  void NotifyAnimatorDeleted() {
    animator_deleted_ = true;
  }

  bool IsAnimatorDeleted() {
    return animator_deleted_;
  }

 private:
  bool animator_deleted_;
};

class TestLayerAnimator : public LayerAnimator {
 public:
  TestLayerAnimator()
      : LayerAnimator(base::Seconds(0)), destruction_observer_(nullptr) {}

  TestLayerAnimator(const TestLayerAnimator&) = delete;
  TestLayerAnimator& operator=(const TestLayerAnimator&) = delete;

  void SetDestructionObserver(
      LayerAnimatorDestructionObserver* observer) {
    destruction_observer_ = observer;
  }

 protected:
  ~TestLayerAnimator() override {
    if (destruction_observer_) {
      destruction_observer_->NotifyAnimatorDeleted();
    }
  }

  void ProgressAnimation(LayerAnimationSequence* sequence,
                         base::TimeTicks now) override {
    EXPECT_TRUE(HasAnimation(sequence));
    LayerAnimator::ProgressAnimation(sequence, now);
  }

 private:
  raw_ptr<LayerAnimatorDestructionObserver> destruction_observer_;
};

// The test layer animation sequence updates a live instances count when it is
// created and destroyed.
class TestLayerAnimationSequence : public LayerAnimationSequence {
 public:
  TestLayerAnimationSequence(std::unique_ptr<LayerAnimationElement> element,
                             int* num_live_instances)
      : LayerAnimationSequence(std::move(element)),
        num_live_instances_(num_live_instances) {
    (*num_live_instances_)++;
  }

  TestLayerAnimationSequence(const TestLayerAnimationSequence&) = delete;
  TestLayerAnimationSequence& operator=(const TestLayerAnimationSequence&) =
      delete;

  ~TestLayerAnimationSequence() override { (*num_live_instances_)--; }

 private:
  raw_ptr<int> num_live_instances_;
};

}  // namespace

namespace test {

// Tracks the number of calls to the LayerAnimationObserver overrides and fails
// CHECKS if the counts are inconsistent, e.g. the number of started sequences
// is greater than the number of attached sequences.
class CountCheckingLayerAnimationObserver : public LayerAnimationObserver {
 public:
  explicit CountCheckingLayerAnimationObserver(LayerAnimationObserver* observer)
      : observer_(observer) {}

  CountCheckingLayerAnimationObserver(
      const CountCheckingLayerAnimationObserver&) = delete;
  CountCheckingLayerAnimationObserver& operator=(
      const CountCheckingLayerAnimationObserver&) = delete;

  void OnLayerAnimationStarted(LayerAnimationSequence* sequence) override {
    ++started_count_;
    EXPECT_LE(started_count_, attached_sequence_count_);
    EXPECT_LE(started_count_, sequences_scheduled_);
    if (observer_)
      observer_->OnLayerAnimationStarted(sequence);
  }

  void OnLayerAnimationEnded(LayerAnimationSequence* sequence) override {
    ++successful_count_;
    EXPECT_LE(GetNumSequencesCompleted(), sequences_scheduled_)
        << " aborted_count_=" << aborted_count_
        << " successful_count_=" << successful_count_;
    EXPECT_LE(GetNumSequencesCompleted(), attached_sequence_count_)
        << " aborted_count_=" << aborted_count_
        << " successful_count_=" << successful_count_;
    if (observer_)
      observer_->OnLayerAnimationEnded(sequence);
  }

  void OnLayerAnimationAborted(LayerAnimationSequence* sequence) override {
    ++aborted_count_;
    EXPECT_LE(GetNumSequencesCompleted(), sequences_scheduled_)
        << " aborted_count_=" << aborted_count_
        << " successful_count_=" << successful_count_;
    EXPECT_LE(GetNumSequencesCompleted(), attached_sequence_count_)
        << " aborted_count_=" << aborted_count_
        << " successful_count_=" << successful_count_;
    if (observer_)
      observer_->OnLayerAnimationAborted(sequence);
  }

  void OnLayerAnimationScheduled(LayerAnimationSequence* sequence) override {
    ++sequences_scheduled_;
    EXPECT_LE(sequences_scheduled_, attached_sequence_count_);
    if (observer_)
      observer_->OnLayerAnimationScheduled(sequence);
  }

  int GetNumSequencesCompleted() { return aborted_count_ + successful_count_; }

 protected:
  void OnAttachedToSequence(LayerAnimationSequence* sequence) override {
    ++attached_sequence_count_;
    if (observer_)
      observer_->OnAttachedToSequence(sequence);
  }

  void OnDetachedFromSequence(LayerAnimationSequence* sequence) override {
    ++detached_sequence_count_;
    EXPECT_LE(detached_sequence_count_, attached_sequence_count_);
    EXPECT_LE(detached_sequence_count_, GetNumSequencesCompleted())
        << " aborted_count_=" << aborted_count_
        << " successful_count_=" << successful_count_;
    if (observer_)
      observer_->OnDetachedFromSequence(sequence);
  }

 private:
  // Observer to which LayerAnimationObserver calls are delgated.
  raw_ptr<LayerAnimationObserver> observer_;

  // The total number of animation sequences that have been attached.
  int attached_sequence_count_ = 0;

  // The total number of animation sequences that have been detached.
  int detached_sequence_count_ = 0;

  // The total number of animation sequences that have been scheduled.
  int sequences_scheduled_ = 0;

  // The number of animation sequences that have been started.
  int started_count_ = 0;

  // The number of animation sequences that were aborted.
  int aborted_count_ = 0;

  // The number of animation sequences that completed successfully.
  int successful_count_ = 0;
};

}  // namespace test

// Checks that setting a property on an implicit animator causes an animation to
// happen.
TEST(LayerAnimatorTest, ImplicitAnimation) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateImplicitTestAnimator(&delegate);
  base::TimeTicks now = base::TimeTicks::Now();
  animator->SetBrightness(0.5);
  EXPECT_TRUE(animator->is_animating());
  animator->Step(now + base::Seconds(1));
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), 0.5);
  delegate.ExpectLastPropertyChangeReason(PropertyChangeReason::FROM_ANIMATION);
}

// Checks that if the animator is a default animator, that implicit animations
// are not started.
TEST(LayerAnimatorTest, NoImplicitAnimation) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  animator->SetBrightness(0.5);
  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), 0.5);
  delegate.ExpectLastPropertyChangeReason(
      PropertyChangeReason::NOT_FROM_ANIMATION);
}

// Checks that StopAnimatingProperty stops animation for that property, and also
// skips the stopped animation to the end.
TEST(LayerAnimatorTest, StopAnimatingProperty) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateImplicitTestAnimator(&delegate);
  double target_opacity(0.5);
  gfx::Rect target_bounds(0, 0, 50, 50);
  animator->SetOpacity(target_opacity);
  animator->SetBounds(target_bounds);
  animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5);
  animator->StopAnimatingProperty(LayerAnimationElement::BOUNDS);
  EXPECT_FALSE(animator->is_animating());
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds);
}

// Checks that multiple running animations for separate properties can be
// stopped simultaneously and that all animations are advanced to their target
// values.
TEST(LayerAnimatorTest, StopAnimating) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateImplicitTestAnimator(&delegate);
  double target_opacity(0.5);
  gfx::Rect target_bounds(0, 0, 50, 50);
  animator->SetOpacity(target_opacity);
  animator->SetBounds(target_bounds);
  EXPECT_TRUE(animator->is_animating());
  animator->StopAnimating();
  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds);
}

// Checks that multiple running animations for separate properties can be
// stopped simultaneously and that aborted animations are NOT advanced to their
// target values.
TEST(LayerAnimatorTest, AbortAllAnimations) {
  TestLayerAnimationDelegate delegate;
  double initial_opacity(1.0);
  gfx::Rect initial_bounds(0, 0, 10, 10);
  delegate.SetOpacityFromAnimation(initial_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBoundsFromAnimation(initial_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);
  scoped_refptr<LayerAnimator> animator = CreateImplicitTestAnimator(&delegate);
  double target_opacity(0.5);
  gfx::Rect target_bounds(0, 0, 50, 50);
  animator->SetOpacity(target_opacity);
  animator->SetBounds(target_bounds);
  EXPECT_TRUE(animator->is_animating());
  animator->AbortAllAnimations();
  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(initial_opacity, delegate.GetOpacityForAnimation());
  CheckApproximatelyEqual(initial_bounds, delegate.GetBoundsForAnimation());
}

// Schedule a non-threaded animation that can run immediately. This is the
// trivial case and should result in the animation being started immediately.
TEST(LayerAnimatorTest, ScheduleAnimationThatCanRunImmediately) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_brightness(0.0);
  double middle_brightness(0.5);
  double target_brightness(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->ScheduleAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);
}

// Schedule a threaded animation that can run immediately.
TEST(LayerAnimatorTest, ScheduleThreadedAnimationThatCanRunImmediately) {
  double epsilon = 0.00001;
  TestLayerAnimationDelegate delegate;
  LayerAnimatorTestController test_controller(
      CreateDefaultTestAnimator(&delegate));
  LayerAnimator* animator = test_controller.animator();

  double start_opacity(0.0);
  double target_opacity(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetOpacityFromAnimation(start_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  test_controller.animator()->ScheduleAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateOpacityElement(target_opacity, delta)));

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity);

  base::TimeTicks start_time = test_controller.animator()->last_step_time();
  base::TimeTicks effective_start = start_time + delta;

  test_controller.animator()->OnThreadedAnimationStarted(
      effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  animator->Step(effective_start + delta / 2);

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_NEAR(
      0.5,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)->
          last_progressed_fraction(),
      epsilon);

  animator->Step(effective_start + delta);

  EXPECT_FALSE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity);
}

// Schedule two non-threaded animations on separate properties. Both animations
// should start immediately and should progress in lock step.
TEST(LayerAnimatorTest, ScheduleTwoAnimationsThatCanRunImmediately) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_brightness(0.0);
  double middle_brightness(0.5);
  double target_brightness(1.0);

  gfx::Rect start_bounds, target_bounds, middle_bounds;
  start_bounds = target_bounds = middle_bounds = gfx::Rect(0, 0, 50, 50);
  start_bounds.set_x(-90);
  target_bounds.set_x(90);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->ScheduleAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)));

  animator->ScheduleAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBoundsElement(target_bounds, delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds);

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), middle_bounds);

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds);
}

// Schedule a threaded and a non-threaded animation on separate properties. Both
// animations should progress in lock step.
TEST(LayerAnimatorTest, ScheduleThreadedAndNonThreadedAnimations) {
  double epsilon = 0.00001;
  TestLayerAnimationDelegate delegate;
  LayerAnimatorTestController test_controller(
      CreateDefaultTestAnimator(&delegate));
  LayerAnimator* animator = test_controller.animator();

  double start_opacity(0.0);
  double target_opacity(1.0);

  gfx::Rect start_bounds, target_bounds, middle_bounds;
  start_bounds = target_bounds = middle_bounds = gfx::Rect(0, 0, 50, 50);
  start_bounds.set_x(-90);
  target_bounds.set_x(90);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetOpacityFromAnimation(start_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  std::vector<LayerAnimationSequence*> animations;
  animations.push_back(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateOpacityElement(target_opacity, delta)));

  animations.push_back(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBoundsElement(target_bounds, delta)));

  test_controller.animator()->ScheduleTogether(animations);

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds);

  base::TimeTicks start_time = test_controller.animator()->last_step_time();
  base::TimeTicks effective_start = start_time + delta;

  test_controller.animator()->OnThreadedAnimationStarted(
      effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  animator->Step(effective_start + delta / 2);

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_NEAR(
      0.5,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)->
          last_progressed_fraction(),
      epsilon);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), middle_bounds);

  animator->Step(effective_start + delta);

  EXPECT_FALSE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds);
}

// Schedule two animations on the same property. In this case, the two
// animations should run one after another.
TEST(LayerAnimatorTest, ScheduleTwoAnimationsOnSameProperty) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_brightness(0.0);
  double middle_brightness(0.5);
  double target_brightness(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->ScheduleAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)));

  animator->ScheduleAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);

  animator->Step(start_time + base::Milliseconds(1500));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->Step(start_time + base::Milliseconds(2000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);
}

// Schedule [{g}, {g,b}, {b}] and ensure that {b} doesn't run right away. That
// is, ensure that all animations targetting a particular property are run in
// order.
TEST(LayerAnimatorTest, ScheduleBlockedAnimation) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_grayscale(0.0);
  double middle_grayscale(0.5);
  double target_grayscale(1.0);

  gfx::Rect start_bounds, target_bounds, middle_bounds;
  start_bounds = target_bounds = middle_bounds = gfx::Rect(0, 0, 50, 50);
  start_bounds.set_x(-90);
  target_bounds.set_x(90);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale,
                                     PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->ScheduleAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateGrayscaleElement(target_grayscale,
                                                        delta)));

  std::unique_ptr<LayerAnimationSequence> bounds_and_grayscale(
      new LayerAnimationSequence(LayerAnimationElement::CreateGrayscaleElement(
          start_grayscale, delta)));

  bounds_and_grayscale->AddElement(
      LayerAnimationElement::CreateBoundsElement(target_bounds, delta));

  animator->ScheduleAnimation(bounds_and_grayscale.release());

  animator->ScheduleAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBoundsElement(start_bounds, delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds);

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds);

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), target_grayscale);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds);

  animator->Step(start_time + base::Milliseconds(2000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds);

  animator->Step(start_time + base::Milliseconds(3000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds);

  animator->Step(start_time + base::Milliseconds(4000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds);
}

// Schedule {g} and then schedule {g} and {b} together. In this case, since
// ScheduleTogether is being used, the bounds animation should not start until
// the second grayscale animation starts.
TEST(LayerAnimatorTest, ScheduleTogether) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_grayscale(0.0);
  double target_grayscale(1.0);

  gfx::Rect start_bounds, target_bounds;
  start_bounds = target_bounds = gfx::Rect(0, 0, 50, 50);
  start_bounds.set_x(-90);
  target_bounds.set_x(90);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale,
                                     PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->ScheduleAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateGrayscaleElement(target_grayscale,
                                                        delta)));

  std::vector<LayerAnimationSequence*> sequences;
  sequences.push_back(new LayerAnimationSequence(
      LayerAnimationElement::CreateGrayscaleElement(start_grayscale, delta)));
  sequences.push_back(new LayerAnimationSequence(
      LayerAnimationElement::CreateBoundsElement(target_bounds, delta)));

  animator->ScheduleTogether(sequences);

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds);

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), target_grayscale);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds);

  animator->Step(start_time + base::Milliseconds(2000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds);
}

// Start non-threaded animation (that can run immediately). This is the trivial
// case (see the trival case for ScheduleAnimation).
TEST(LayerAnimatorTest, StartAnimationThatCanRunImmediately) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_brightness(0.0);
  double middle_brightness(0.5);
  double target_brightness(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);
}

// Start threaded animation (that can run immediately).
TEST(LayerAnimatorTest, StartThreadedAnimationThatCanRunImmediately) {
  double epsilon = 0.00001;
  TestLayerAnimationDelegate delegate;
  LayerAnimatorTestController test_controller(
      CreateDefaultTestAnimator(&delegate));
  LayerAnimator* animator = test_controller.animator();

  double start_opacity(0.0);
  double target_opacity(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetOpacityFromAnimation(start_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  test_controller.animator()->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateOpacityElement(target_opacity, delta)));

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity);

  base::TimeTicks start_time = test_controller.animator()->last_step_time();
  base::TimeTicks effective_start = start_time + delta;

  test_controller.animator()->OnThreadedAnimationStarted(
      effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  animator->Step(effective_start + delta / 2);

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_NEAR(
      0.5,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)->
          last_progressed_fraction(),
      epsilon);

  animator->Step(effective_start + delta);
  EXPECT_FALSE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity);
}

// Preempt by immediately setting new target.
TEST(LayerAnimatorTest, PreemptBySettingNewTarget) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_opacity(0.0);
  double target_opacity(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetOpacityFromAnimation(start_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->set_preemption_strategy(LayerAnimator::IMMEDIATELY_SET_NEW_TARGET);

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateOpacityElement(target_opacity, delta)));

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateOpacityElement(start_opacity, delta)));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity);
}

// Preempt by animating to new target, with a non-threaded animation.
TEST(LayerAnimatorTest, PreemptByImmediatelyAnimatingToNewTarget) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_brightness(0.0);
  double middle_brightness(0.5);
  double target_brightness(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->set_preemption_strategy(
      LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)));

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(),
                  0.5 * (start_brightness + middle_brightness));

  animator->Step(start_time + base::Milliseconds(1500));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);
}

// Preempt by animating to new target, with a threaded animation.
TEST(LayerAnimatorTest, PreemptThreadedByImmediatelyAnimatingToNewTarget) {
  double epsilon = 0.00001;
  TestLayerAnimationDelegate delegate;
  LayerAnimatorTestController test_controller(
      CreateDefaultTestAnimator(&delegate));
  LayerAnimator* animator = test_controller.animator();

  double start_opacity(0.0);
  double middle_opacity(0.5);
  double target_opacity(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetOpacityFromAnimation(start_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  test_controller.animator()->set_preemption_strategy(
      LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);

  test_controller.animator()->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateOpacityElement(target_opacity, delta)));

  base::TimeTicks start_time = test_controller.animator()->last_step_time();
  base::TimeTicks effective_start = start_time + delta;

  test_controller.animator()->OnThreadedAnimationStarted(
      effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  animator->Step(effective_start + delta / 2);

  test_controller.animator()->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateOpacityElement(start_opacity, delta)));

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_NEAR(delegate.GetOpacityForAnimation(), middle_opacity, epsilon);

  test_controller.animator()->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateOpacityElement(start_opacity, delta)));

  EXPECT_TRUE(test_controller.animator()->is_animating());

  base::TimeTicks second_effective_start = effective_start + delta;

  test_controller.animator()->OnThreadedAnimationStarted(
      second_effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  animator->Step(second_effective_start + delta / 2);

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_NEAR(
      0.5,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)->
          last_progressed_fraction(),
      epsilon);

  animator->Step(second_effective_start + delta);

  EXPECT_FALSE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity);
}

// Preempt by enqueuing the new animation.
TEST(LayerAnimatorTest, PreemptEnqueueNewAnimation) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_brightness(0.0);
  double middle_brightness(0.5);
  double target_brightness(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION);

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                          delta)));

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  EXPECT_TRUE(animator->is_animating());

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);

  animator->Step(start_time + base::Milliseconds(1500));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->Step(start_time + base::Milliseconds(2000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);
}

// Start an animation when there are sequences waiting in the queue. In this
// case, all pending and running animations should be finished, and the new
// animation started.
TEST(LayerAnimatorTest, PreemptyByReplacingQueuedAnimations) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_brightness(0.0);
  double middle_brightness(0.5);
  double target_brightness(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->set_preemption_strategy(LayerAnimator::REPLACE_QUEUED_ANIMATIONS);

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)));

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(middle_brightness,
                                                         delta)));

  // Queue should now have two animations. Starting a third should replace the
  // second.
  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);

  animator->Step(start_time + base::Milliseconds(1500));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->Step(start_time + base::Milliseconds(2000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);
}

TEST(LayerAnimatorTest, StartTogetherSetsLastStepTime) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_grayscale(0.0);
  double target_grayscale(1.0);
  double start_brightness(0.1);
  double target_brightness(0.9);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale,
                                     PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->set_preemption_strategy(
      LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);

  animator->set_last_step_time(base::TimeTicks());

  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateGrayscaleElement(target_grayscale,
                                                        delta),
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)
      ));

  // If last step time was not set correctly, the resulting delta should be
  // miniscule (fractions of a millisecond). If set correctly, then the delta
  // should be enormous. Arbitrarily choosing 1 minute as the threshold,
  // though a much smaller value would probably have sufficed.
  delta = base::TimeTicks::Now() - animator->last_step_time();
  EXPECT_LT(delta, base::Minutes(1));
}

//-------------------------------------------------------
// Preempt by immediately setting new target.
TEST(LayerAnimatorTest, MultiPreemptBySettingNewTarget) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_opacity(0.0);
  double target_opacity(1.0);
  double start_brightness(0.1);
  double target_brightness(0.9);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetOpacityFromAnimation(start_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->set_preemption_strategy(LayerAnimator::IMMEDIATELY_SET_NEW_TARGET);

  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateOpacityElement(target_opacity, delta),
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)
      ));

  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateOpacityElement(start_opacity, delta),
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)
      ));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);
}

// Preempt by animating to new target.
TEST(LayerAnimatorTest, MultiPreemptByImmediatelyAnimatingToNewTarget) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_grayscale(0.0);
  double middle_grayscale(0.5);
  double target_grayscale(1.0);

  double start_brightness(0.1);
  double middle_brightness(0.2);
  double target_brightness(0.3);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale,
                                     PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->set_preemption_strategy(
      LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);

  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateGrayscaleElement(target_grayscale,
                                                        delta),
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)
      ));

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateGrayscaleElement(start_grayscale, delta),
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateGrayscaleElement(start_grayscale, delta),
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(),
                  0.5 * (start_grayscale + middle_grayscale));
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(),
                  0.5 * (start_brightness + middle_brightness));

  animator->Step(start_time + base::Milliseconds(1500));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);
}

// Preempt a threaded animation by animating to new target.
TEST(LayerAnimatorTest, MultiPreemptThreadedByImmediatelyAnimatingToNewTarget) {
  double epsilon = 0.00001;
  TestLayerAnimationDelegate delegate;
  LayerAnimatorTestController test_controller(
      CreateDefaultTestAnimator(&delegate));
  LayerAnimator* animator = test_controller.animator();

  double start_opacity(0.0);
  double middle_opacity(0.5);
  double target_opacity(1.0);

  double start_brightness(0.1);
  double middle_brightness(0.2);
  double target_brightness(0.3);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetOpacityFromAnimation(start_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  test_controller.animator()->set_preemption_strategy(
      LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);

  test_controller.animator()->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateOpacityElement(target_opacity, delta),
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)
      ));

  base::TimeTicks start_time = test_controller.animator()->last_step_time();
  base::TimeTicks effective_start = start_time + delta;

  test_controller.animator()->OnThreadedAnimationStarted(
      effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  animator->Step(effective_start + delta / 2);

  test_controller.animator()->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateOpacityElement(start_opacity, delta),
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_NEAR(delegate.GetOpacityForAnimation(), middle_opacity, epsilon);
  EXPECT_NEAR(delegate.GetBrightnessForAnimation(), middle_brightness, epsilon);

  test_controller.animator()->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateOpacityElement(start_opacity, delta),
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(test_controller.animator()->is_animating());

  base::TimeTicks second_effective_start = effective_start + delta;

  test_controller.animator()->OnThreadedAnimationStarted(
      second_effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  animator->Step(second_effective_start + delta / 2);

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_NEAR(
      0.5,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)->
          last_progressed_fraction(),
      epsilon);
  EXPECT_NEAR(delegate.GetBrightnessForAnimation(),
              0.5 * (start_brightness + middle_brightness),
              epsilon);

  animator->Step(second_effective_start + delta);

  EXPECT_FALSE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);
}

// Preempt by enqueuing the new animation.
TEST(LayerAnimatorTest, MultiPreemptEnqueueNewAnimation) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_grayscale(0.0);
  double middle_grayscale(0.5);
  double target_grayscale(1.0);

  double start_brightness(0.1);
  double middle_brightness(0.2);
  double target_brightness(0.3);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale,
                                     PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION);

  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateGrayscaleElement(target_grayscale,
                                                        delta),
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)));

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateGrayscaleElement(start_grayscale, delta),
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  EXPECT_TRUE(animator->is_animating());

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), target_grayscale);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);

  animator->Step(start_time + base::Milliseconds(1500));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->Step(start_time + base::Milliseconds(2000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);
}

// Start an animation when there are sequences waiting in the queue. In this
// case, all pending and running animations should be finished, and the new
// animation started.
TEST(LayerAnimatorTest, MultiPreemptByReplacingQueuedAnimations) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_grayscale(0.0);
  double middle_grayscale(0.5);
  double target_grayscale(1.0);

  double start_brightness(0.1);
  double middle_brightness(0.2);
  double target_brightness(0.3);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale,
                                     PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->set_preemption_strategy(LayerAnimator::REPLACE_QUEUED_ANIMATIONS);

  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateGrayscaleElement(target_grayscale,
                                                        delta),
          LayerAnimationElement::CreateBrightnessElement(target_brightness,
                                                         delta)));

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateGrayscaleElement(middle_grayscale,
                                                        delta),
          LayerAnimationElement::CreateBrightnessElement(middle_brightness,
                                                         delta)));

  // Queue should now have two animations. Starting a third should replace the
  // second.
  animator->StartTogether(
      CreateMultiSequence(
          LayerAnimationElement::CreateGrayscaleElement(start_grayscale, delta),
          LayerAnimationElement::CreateBrightnessElement(start_brightness,
                                                         delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), target_grayscale);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);

  animator->Step(start_time + base::Milliseconds(1500));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness);

  animator->Step(start_time + base::Milliseconds(2000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale);
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);
}
//-------------------------------------------------------
// Test that non-threaded cyclic sequences continue to animate.
TEST(LayerAnimatorTest, CyclicSequences) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_brightness(0.0);
  double target_brightness(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  std::unique_ptr<LayerAnimationSequence> sequence(
      new LayerAnimationSequence(LayerAnimationElement::CreateBrightnessElement(
          target_brightness, delta)));

  sequence->AddElement(
      LayerAnimationElement::CreateBrightnessElement(start_brightness, delta));

  sequence->set_is_repeating(true);

  animator->StartAnimation(sequence.release());

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);

  animator->Step(start_time + base::Milliseconds(2000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);

  animator->Step(start_time + base::Milliseconds(3000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);

  // Skip ahead by a lot.
  animator->Step(start_time + base::Milliseconds(1000000000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness);

  // Skip ahead by a lot.
  animator->Step(start_time + base::Milliseconds(1000001000));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness);

  animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);

  EXPECT_FALSE(animator->is_animating());
}

// Test that threaded cyclic sequences continue to animate.
TEST(LayerAnimatorTest, ThreadedCyclicSequences) {
  TestLayerAnimationDelegate delegate;
  LayerAnimatorTestController test_controller(
      CreateDefaultTestAnimator(&delegate));
  LayerAnimator* animator = test_controller.animator();

  double start_opacity(0.0);
  double target_opacity(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetOpacityFromAnimation(start_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  std::unique_ptr<LayerAnimationSequence> sequence(new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(target_opacity, delta)));

  sequence->AddElement(
      LayerAnimationElement::CreateOpacityElement(start_opacity, delta));

  sequence->set_is_repeating(true);

  test_controller.animator()->StartAnimation(sequence.release());

  base::TimeTicks start_time = test_controller.animator()->last_step_time();
  base::TimeTicks effective_start = start_time + delta;

  test_controller.animator()->OnThreadedAnimationStarted(
      effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  animator->Step(effective_start + delta);
  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity);

  base::TimeTicks second_effective_start = effective_start + 2 * delta;
  test_controller.animator()->OnThreadedAnimationStarted(
      second_effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  animator->Step(second_effective_start + delta);

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity);

  base::TimeTicks third_effective_start = second_effective_start + 2 * delta;
  test_controller.animator()->OnThreadedAnimationStarted(
      third_effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  animator->Step(third_effective_start + delta);
  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity);

  base::TimeTicks fourth_effective_start = third_effective_start + 2 * delta;
  test_controller.animator()->OnThreadedAnimationStarted(
      fourth_effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  // Skip ahead by a lot.
  animator->Step(fourth_effective_start + 1000 * delta);

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity);

  base::TimeTicks fifth_effective_start = fourth_effective_start + 1001 * delta;
  test_controller.animator()->OnThreadedAnimationStarted(
      fifth_effective_start, cc::TargetProperty::OPACITY,
      test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
          ->animation_group_id());

  // Skip ahead by a lot.
  animator->Step(fifth_effective_start + 999 * delta);

  EXPECT_TRUE(test_controller.animator()->is_animating());
  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity);

  test_controller.animator()->StopAnimatingProperty(
      LayerAnimationElement::OPACITY);

  EXPECT_FALSE(test_controller.animator()->is_animating());
}

TEST(LayerAnimatorTest, AddObserverExplicit) {
  TestLayerAnimationObserver observer;
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator(
      CreateDefaultTestAnimator(&delegate, &observer));
  observer.set_requires_notification_when_animator_destroyed(true);

  EXPECT_TRUE(!observer.last_ended_sequence());

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetBrightnessFromAnimation(0.0f,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  LayerAnimationSequence* sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(1.0f, delta));

  animator->StartAnimation(sequence);

  EXPECT_EQ(observer.last_scheduled_sequence(), sequence);

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_EQ(observer.last_ended_sequence(), sequence);

  // |sequence| has been destroyed. Recreate it to test abort.
  sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(1.0f, delta));

  animator->StartAnimation(sequence);

  animator.reset();

  EXPECT_EQ(observer.last_aborted_sequence(), sequence);
}

// Tests that an observer added to a scoped settings object is still notified
// when the object goes out of scope.
TEST(LayerAnimatorTest, ImplicitAnimationObservers) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  TestImplicitAnimationObserver observer(false);

  EXPECT_FALSE(observer.animations_completed());
  animator->SetBrightness(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.AddObserver(&observer);
    animator->SetBrightness(0.0f);
  }

  EXPECT_FALSE(observer.animations_completed());
  base::TimeTicks start_time = animator->last_step_time();
  animator->Step(start_time + base::Milliseconds(1000));
  EXPECT_TRUE(observer.animations_completed());
  EXPECT_TRUE(observer.WasAnimationCompletedForProperty(
      LayerAnimationElement::BRIGHTNESS));
  EXPECT_FLOAT_EQ(0.0f, delegate.GetBrightnessForAnimation());
}

// Tests that caching render surface added to a scoped settings object is still
// reset when the object goes out of scope.
TEST(LayerAnimatorTest, CacheRenderSurface) {
  ui::Layer layer;
  scoped_refptr<LayerAnimator> animator(layer.GetAnimator());
  animator->set_disable_timer_for_test(true);
  TestImplicitAnimationObserver observer(false);

  EXPECT_FALSE(observer.animations_completed());
  EXPECT_FALSE(layer.cc_layer_for_testing()->cache_render_surface());
  animator->SetOpacity(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.CacheRenderSurface();
    settings.AddObserver(&observer);
    animator->SetOpacity(0.0f);
  }

  EXPECT_FALSE(observer.animations_completed());
  EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
  animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
  EXPECT_TRUE(observer.animations_completed());
  EXPECT_TRUE(observer.WasAnimationCompletedForProperty(
      LayerAnimationElement::OPACITY));
  EXPECT_FLOAT_EQ(0.0f, layer.opacity());
  EXPECT_FALSE(layer.cc_layer_for_testing()->cache_render_surface());
}

// Tests that caching render surface added to a scoped settings object will not
// crash when the layer was destroyed.
TEST(LayerAnimatorTest, CacheRenderSurfaceOnWillBeDestroyedLayer) {
  // Case 1: layer is a pointer.
  auto layer1 = std::make_unique<Layer>();
  scoped_refptr<LayerAnimator> animator(layer1->GetAnimator());
  animator->set_disable_timer_for_test(true);
  TestImplicitAnimationObserver observer1(false);

  EXPECT_FALSE(observer1.animations_completed());
  animator->SetOpacity(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.CacheRenderSurface();
    settings.AddObserver(&observer1);
    animator->SetOpacity(0.0f);
  }

  EXPECT_FALSE(observer1.animations_completed());
  layer1.reset();
  animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
  EXPECT_TRUE(observer1.animations_completed());

  // Case 2: layer is a local variable.
  TestImplicitAnimationObserver observer2(false);
  {
    ui::Layer layer2;
    animator = layer2.GetAnimator();

    EXPECT_FALSE(observer2.animations_completed());
    animator->SetBrightness(1.0f);

    ScopedLayerAnimationSettings settings(animator.get());
    settings.CacheRenderSurface();
    settings.AddObserver(&observer2);
    animator->SetBrightness(0.0f);
  }

  EXPECT_FALSE(observer2.animations_completed());
  animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
  EXPECT_TRUE(observer2.animations_completed());

  // Case 3: Animation finishes before layer is destroyed.
  ui::Layer layer3;
  animator = layer3.GetAnimator();
  TestImplicitAnimationObserver observer3(false);

  EXPECT_FALSE(observer3.animations_completed());
  animator->SetGrayscale(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.CacheRenderSurface();
    settings.AddObserver(&observer3);
    animator->SetGrayscale(0.0f);
  }

  EXPECT_FALSE(observer3.animations_completed());
  animator->StopAnimatingProperty(LayerAnimationElement::GRAYSCALE);
  EXPECT_TRUE(observer3.animations_completed());
}

// Tests that caching render surface added to two scoped settings objects is
// still reset when animation finishes.
TEST(LayerAnimatorTest, CacheRenderSurfaceInTwoAnimations) {
  ui::Layer layer;
  scoped_refptr<LayerAnimator> animator(layer.GetAnimator());
  animator->set_disable_timer_for_test(true);

  // Case 1: the original cache status if false.
  EXPECT_FALSE(layer.cc_layer_for_testing()->cache_render_surface());
  animator->SetBrightness(1.0f);
  animator->SetOpacity(1.0f);

  // Start the brightness animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.CacheRenderSurface();
    animator->SetBrightness(0.0f);
  }
  EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());

  // Start the opacity animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.CacheRenderSurface();
    animator->SetOpacity(0.0f);
  }
  EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());

  // Finish the brightness animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
    EXPECT_FLOAT_EQ(0.0f, layer.layer_brightness());
    EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
  }

  // Finish the opacity animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
    EXPECT_FLOAT_EQ(0.0f, layer.opacity());
    EXPECT_FALSE(layer.cc_layer_for_testing()->cache_render_surface());
  }

  // Case 2: the original cache status if true.
  layer.AddCacheRenderSurfaceRequest();
  EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
  animator->SetBrightness(1.0f);
  animator->SetOpacity(1.0f);

  // Start the brightness animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.CacheRenderSurface();
    animator->SetBrightness(0.0f);
  }
  EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());

  // Start the opacity animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.CacheRenderSurface();
    animator->SetOpacity(0.0f);
  }
  EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());

  // Finish the brightness animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
    EXPECT_FLOAT_EQ(0.0f, layer.layer_brightness());
    EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
  }

  // Finish the opacity animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
    EXPECT_FLOAT_EQ(0.0f, layer.opacity());
    EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
  }
}

// Tests that deferred painting request added to a scoped settings object is
// still reset when the object goes out of scope.
TEST(LayerAnimatorTest, DeferredPaint) {
  ui::Layer layer;
  scoped_refptr<LayerAnimator> animator(layer.GetAnimator());
  animator->set_disable_timer_for_test(true);
  TestImplicitAnimationObserver observer(false);

  EXPECT_FALSE(observer.animations_completed());
  EXPECT_FALSE(layer.IsPaintDeferredForTesting());
  animator->SetOpacity(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.DeferPaint();
    settings.AddObserver(&observer);
    animator->SetOpacity(0.0f);
  }

  EXPECT_FALSE(observer.animations_completed());
  EXPECT_TRUE(layer.IsPaintDeferredForTesting());
  animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
  EXPECT_TRUE(observer.animations_completed());
  EXPECT_TRUE(observer.WasAnimationCompletedForProperty(
      LayerAnimationElement::OPACITY));
  EXPECT_FLOAT_EQ(0.0f, layer.opacity());
  EXPECT_FALSE(layer.IsPaintDeferredForTesting());
}

// Tests that deferred painting request is added to child layers and will be
// removed even the child layer was reparented.
TEST(LayerAnimatorTest, DeferredPaintOnChildLayer) {
  ui::Layer layer;
  ui::Layer child_layer1;
  ui::Layer child_layer2;
  layer.Add(&child_layer1);
  layer.Add(&child_layer2);

  scoped_refptr<LayerAnimator> animator(layer.GetAnimator());
  animator->set_disable_timer_for_test(true);
  TestImplicitAnimationObserver observer(false);

  EXPECT_FALSE(observer.animations_completed());
  EXPECT_FALSE(layer.IsPaintDeferredForTesting());
  EXPECT_FALSE(child_layer1.IsPaintDeferredForTesting());
  EXPECT_FALSE(child_layer2.IsPaintDeferredForTesting());
  animator->SetOpacity(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.DeferPaint();
    settings.AddObserver(&observer);
    animator->SetOpacity(0.0f);
  }

  EXPECT_FALSE(observer.animations_completed());
  EXPECT_TRUE(layer.IsPaintDeferredForTesting());
  EXPECT_TRUE(child_layer1.IsPaintDeferredForTesting());
  EXPECT_TRUE(child_layer2.IsPaintDeferredForTesting());

  // Reparent child_layer2.
  ui::Layer new_parent_layer;
  new_parent_layer.Add(&child_layer2);
  EXPECT_TRUE(child_layer2.IsPaintDeferredForTesting());

  animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
  EXPECT_TRUE(observer.animations_completed());
  EXPECT_TRUE(observer.WasAnimationCompletedForProperty(
      LayerAnimationElement::OPACITY));
  EXPECT_FLOAT_EQ(0.0f, layer.opacity());
  EXPECT_FALSE(layer.IsPaintDeferredForTesting());
  EXPECT_FALSE(child_layer1.IsPaintDeferredForTesting());
  EXPECT_FALSE(child_layer2.IsPaintDeferredForTesting());
}

// Tests that deffered paint request added to two scoped settings objects is
// still reset when animation finishes.
TEST(LayerAnimatorTest, DeferredPaintInTwoAnimations) {
  ui::Layer layer;
  scoped_refptr<LayerAnimator> animator(layer.GetAnimator());
  animator->set_disable_timer_for_test(true);

  // Case 1: the original deferred paint status if false.
  EXPECT_FALSE(layer.IsPaintDeferredForTesting());
  animator->SetBrightness(1.0f);
  animator->SetOpacity(1.0f);

  // Start the brightness animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.DeferPaint();
    animator->SetBrightness(0.0f);
  }
  EXPECT_TRUE(layer.IsPaintDeferredForTesting());

  // Start the opacity animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.DeferPaint();
    animator->SetOpacity(0.0f);
  }
  EXPECT_TRUE(layer.IsPaintDeferredForTesting());

  // Finish the brightness animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
    EXPECT_FLOAT_EQ(0.0f, layer.layer_brightness());
    EXPECT_TRUE(layer.IsPaintDeferredForTesting());
  }

  // Finish the opacity animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
    EXPECT_FLOAT_EQ(0.0f, layer.opacity());
    EXPECT_FALSE(layer.IsPaintDeferredForTesting());
  }

  // Case 2: the original cache status if true.
  layer.AddDeferredPaintRequest();
  EXPECT_TRUE(layer.IsPaintDeferredForTesting());
  animator->SetBrightness(1.0f);
  animator->SetOpacity(1.0f);

  // Start the brightness animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.DeferPaint();
    animator->SetBrightness(0.0f);
  }
  EXPECT_TRUE(layer.IsPaintDeferredForTesting());

  // Start the opacity animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.DeferPaint();
    animator->SetOpacity(0.0f);
  }
  EXPECT_TRUE(layer.IsPaintDeferredForTesting());

  // Finish the brightness animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
    EXPECT_FLOAT_EQ(0.0f, layer.layer_brightness());
    EXPECT_TRUE(layer.IsPaintDeferredForTesting());
  }

  // Finish the opacity animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
    EXPECT_FLOAT_EQ(0.0f, layer.opacity());
    EXPECT_TRUE(layer.IsPaintDeferredForTesting());
  }
}

// Tests that deferred paint request added to a scoped settings object will
// not crash when the layer was destroyed.
TEST(LayerAnimatorTest, DeferredPaintOnWillBeDestroyedLayer) {
  // Case 1: layer is a pointer.
  auto layer1 = std::make_unique<Layer>();
  scoped_refptr<LayerAnimator> animator(layer1->GetAnimator());
  animator->set_disable_timer_for_test(true);
  TestImplicitAnimationObserver observer1(false);

  EXPECT_FALSE(observer1.animations_completed());
  animator->SetOpacity(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.DeferPaint();
    settings.AddObserver(&observer1);
    animator->SetOpacity(0.0f);
  }

  EXPECT_FALSE(observer1.animations_completed());
  layer1.reset();
  animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
  EXPECT_TRUE(observer1.animations_completed());

  // Case 2: layer is a local variable.
  TestImplicitAnimationObserver observer2(false);
  {
    ui::Layer layer2;
    animator = layer2.GetAnimator();

    EXPECT_FALSE(observer2.animations_completed());
    animator->SetBrightness(1.0f);

    ScopedLayerAnimationSettings settings(animator.get());
    settings.DeferPaint();
    settings.AddObserver(&observer2);
    animator->SetBrightness(0.0f);
  }

  EXPECT_FALSE(observer2.animations_completed());
  animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
  EXPECT_TRUE(observer2.animations_completed());

  // Case 3: Animation finishes before layer is destroyed.
  ui::Layer layer3;
  animator = layer3.GetAnimator();
  TestImplicitAnimationObserver observer3(false);

  EXPECT_FALSE(observer3.animations_completed());
  animator->SetGrayscale(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.DeferPaint();
    settings.AddObserver(&observer3);
    animator->SetGrayscale(0.0f);
  }

  EXPECT_FALSE(observer3.animations_completed());
  animator->StopAnimatingProperty(LayerAnimationElement::GRAYSCALE);
  EXPECT_TRUE(observer3.animations_completed());
}

// Tests that trilinear filtering request added to a scoped settings object is
// still reset when the object goes out of scope.
TEST(LayerAnimatorTest, TrilinearFiltering) {
  ui::Layer layer;
  scoped_refptr<LayerAnimator> animator(layer.GetAnimator());
  animator->set_disable_timer_for_test(true);
  TestImplicitAnimationObserver observer(false);

  EXPECT_FALSE(observer.animations_completed());
  EXPECT_FALSE(layer.cc_layer_for_testing()->trilinear_filtering());
  animator->SetOpacity(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.TrilinearFiltering();
    settings.AddObserver(&observer);
    animator->SetOpacity(0.0f);
  }

  EXPECT_FALSE(observer.animations_completed());
  EXPECT_TRUE(layer.cc_layer_for_testing()->trilinear_filtering());
  animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
  EXPECT_TRUE(observer.animations_completed());
  EXPECT_TRUE(observer.WasAnimationCompletedForProperty(
      LayerAnimationElement::OPACITY));
  EXPECT_FLOAT_EQ(0.0f, layer.opacity());
  EXPECT_FALSE(layer.cc_layer_for_testing()->trilinear_filtering());
}

// Tests that trilinear filtering request added to a scoped settings object will
// not crash when the layer was destroyed.
TEST(LayerAnimatorTest, TrilinearFilteringOnWillBeDestroyedLayer) {
  // Case 1: layer is a pointer.
  auto layer1 = std::make_unique<Layer>();
  scoped_refptr<LayerAnimator> animator(layer1->GetAnimator());
  animator->set_disable_timer_for_test(true);
  TestImplicitAnimationObserver observer1(false);

  EXPECT_FALSE(observer1.animations_completed());
  animator->SetOpacity(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.TrilinearFiltering();
    settings.AddObserver(&observer1);
    animator->SetOpacity(0.0f);
  }

  EXPECT_FALSE(observer1.animations_completed());
  layer1.reset();
  animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
  EXPECT_TRUE(observer1.animations_completed());

  // Case 2: layer is a local variable.
  TestImplicitAnimationObserver observer2(false);
  {
    ui::Layer layer2;
    animator = layer2.GetAnimator();

    EXPECT_FALSE(observer2.animations_completed());
    animator->SetBrightness(1.0f);

    ScopedLayerAnimationSettings settings(animator.get());
    settings.TrilinearFiltering();
    settings.AddObserver(&observer2);
    animator->SetBrightness(0.0f);
  }

  EXPECT_FALSE(observer2.animations_completed());
  animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
  EXPECT_TRUE(observer2.animations_completed());

  // Case 3: Animation finishes before layer is destroyed.
  ui::Layer layer3;
  animator = layer3.GetAnimator();
  TestImplicitAnimationObserver observer3(false);

  EXPECT_FALSE(observer3.animations_completed());
  animator->SetGrayscale(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.TrilinearFiltering();
    settings.AddObserver(&observer3);
    animator->SetGrayscale(0.0f);
  }

  EXPECT_FALSE(observer3.animations_completed());
  animator->StopAnimatingProperty(LayerAnimationElement::GRAYSCALE);
  EXPECT_TRUE(observer3.animations_completed());
}

// Tests that trilinear filtering request added to two scoped settings objects
// is still reset when animation finishes.
TEST(LayerAnimatorTest, TrilinearFilteringInTwoAnimations) {
  ui::Layer layer;
  scoped_refptr<LayerAnimator> animator(layer.GetAnimator());
  animator->set_disable_timer_for_test(true);

  // Case 1: the original trilinear filtering status if false.
  EXPECT_FALSE(layer.cc_layer_for_testing()->trilinear_filtering());
  animator->SetBrightness(1.0f);
  animator->SetOpacity(1.0f);

  // Start the brightness animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.TrilinearFiltering();
    animator->SetBrightness(0.0f);
  }
  EXPECT_TRUE(layer.cc_layer_for_testing()->trilinear_filtering());

  // Start the opacity animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.TrilinearFiltering();
    animator->SetOpacity(0.0f);
  }
  EXPECT_TRUE(layer.cc_layer_for_testing()->trilinear_filtering());

  // Finish the brightness animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
    EXPECT_FLOAT_EQ(0.0f, layer.layer_brightness());
    EXPECT_TRUE(layer.cc_layer_for_testing()->trilinear_filtering());
  }

  // Finish the opacity animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
    EXPECT_FLOAT_EQ(0.0f, layer.opacity());
    EXPECT_FALSE(layer.cc_layer_for_testing()->trilinear_filtering());
  }

  // Case 2: the original original trilinear status if true.
  layer.AddTrilinearFilteringRequest();
  EXPECT_TRUE(layer.cc_layer_for_testing()->trilinear_filtering());
  animator->SetBrightness(1.0f);
  animator->SetOpacity(1.0f);

  // Start the brightness animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.TrilinearFiltering();
    animator->SetBrightness(0.0f);
  }
  EXPECT_TRUE(layer.cc_layer_for_testing()->trilinear_filtering());

  // Start the opacity animation.
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.TrilinearFiltering();
    animator->SetOpacity(0.0f);
  }
  EXPECT_TRUE(layer.cc_layer_for_testing()->trilinear_filtering());

  // Finish the brightness animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
    EXPECT_FLOAT_EQ(0.0f, layer.layer_brightness());
    EXPECT_TRUE(layer.cc_layer_for_testing()->trilinear_filtering());
  }

  // Finish the opacity animation.
  {
    animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
    EXPECT_FLOAT_EQ(0.0f, layer.opacity());
    EXPECT_TRUE(layer.cc_layer_for_testing()->trilinear_filtering());
  }
}

// Tests that an observer added to a scoped settings object is still notified
// when the object goes out of scope due to the animation being interrupted.
TEST(LayerAnimatorTest, InterruptedImplicitAnimationObservers) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  TestImplicitAnimationObserver observer(false);

  EXPECT_FALSE(observer.animations_completed());
  animator->SetBrightness(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.AddObserver(&observer);
    animator->SetBrightness(0.0f);
  }

  EXPECT_FALSE(observer.animations_completed());
  // This should interrupt the implicit animation causing the observer to be
  // notified immediately.
  animator->SetBrightness(1.0f);
  EXPECT_TRUE(observer.animations_completed());
  EXPECT_TRUE(observer.WasAnimationCompletedForProperty(
      LayerAnimationElement::BRIGHTNESS));
  EXPECT_FLOAT_EQ(1.0f, delegate.GetBrightnessForAnimation());
}

// Tests that LayerAnimator is not deleted after the animation completes as long
// as there is a live ScopedLayerAnimationSettings object wrapped around it.
TEST(LayerAnimatorTest, AnimatorKeptAliveBySettings) {
  // Note we are using a raw pointer unlike in other tests.
  TestLayerAnimator* animator = new TestLayerAnimator();
  LayerAnimatorDestructionObserver destruction_observer;
  animator->SetDestructionObserver(&destruction_observer);
  animator->set_disable_timer_for_test(true);
  TestLayerAnimationDelegate delegate;
  animator->SetDelegate(&delegate);
  {
    // ScopedLayerAnimationSettings should keep the Animator alive as long as
    // it is alive, even beyond the end of the animation.
    ScopedLayerAnimationSettings settings(animator);
    base::TimeTicks now = base::TimeTicks::Now();
    animator->SetBrightness(0.5);
    animator->Step(now + base::Seconds(1));
    EXPECT_FALSE(destruction_observer.IsAnimatorDeleted());
  }
  // ScopedLayerAnimationSettings was destroyed, so Animator should be deleted.
  EXPECT_TRUE(destruction_observer.IsAnimatorDeleted());
}

// Tests that an observer added to a scoped settings object is not notified
// when the animator is destroyed unless explicitly requested.
TEST(LayerAnimatorTest, ImplicitObserversAtAnimatorDestruction) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  TestImplicitAnimationObserver observer_notify(true);
  TestImplicitAnimationObserver observer_do_not_notify(false);

  EXPECT_FALSE(observer_notify.animations_completed());
  EXPECT_FALSE(observer_do_not_notify.animations_completed());

  animator->SetBrightness(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.AddObserver(&observer_notify);
    settings.AddObserver(&observer_do_not_notify);
    animator->SetBrightness(0.0f);
  }

  EXPECT_FALSE(observer_notify.animations_completed());
  EXPECT_FALSE(observer_do_not_notify.animations_completed());
  animator.reset();
  EXPECT_TRUE(observer_notify.animations_completed());
  EXPECT_TRUE(observer_notify.WasAnimationAbortedForProperty(
      LayerAnimationElement::BRIGHTNESS));
  EXPECT_FALSE(observer_do_not_notify.animations_completed());
}

TEST(LayerAnimatorTest, AbortedAnimationStatusInImplicitObservers) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  TestImplicitAnimationObserver observer(false);

  EXPECT_FALSE(observer.animations_completed());
  animator->SetBrightness(1.0f);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.AddObserver(&observer);
    animator->SetBrightness(0.0f);
  }
  EXPECT_FALSE(observer.animations_completed());

  animator->AbortAllAnimations();
  EXPECT_TRUE(observer.animations_completed());
  EXPECT_TRUE(observer.WasAnimationAbortedForProperty(
      LayerAnimationElement::BRIGHTNESS));
  EXPECT_FALSE(observer.WasAnimationAbortedForProperty(
      LayerAnimationElement::OPACITY));

  observer.set_animations_completed(false);
  {
    ScopedLayerAnimationSettings settings(animator.get());
    settings.AddObserver(&observer);
    animator->SetOpacity(0.0f);
  }
  EXPECT_FALSE(observer.animations_completed());

  animator->AbortAllAnimations();
  EXPECT_TRUE(observer.animations_completed());
  EXPECT_TRUE(observer.WasAnimationAbortedForProperty(
      LayerAnimationElement::BRIGHTNESS));
  EXPECT_TRUE(observer.WasAnimationAbortedForProperty(
      LayerAnimationElement::OPACITY));
}

TEST(LayerAnimatorTest, RemoveObserverShouldRemoveFromSequences) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  TestLayerAnimationObserver observer;
  TestLayerAnimationObserver removed_observer;

  base::TimeDelta delta = base::Seconds(1);

  LayerAnimationSequence* sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(1.0f, delta));

  sequence->AddObserver(&observer);
  sequence->AddObserver(&removed_observer);

  animator->StartAnimation(sequence);

  EXPECT_EQ(observer.last_scheduled_sequence(), sequence);
  EXPECT_TRUE(!observer.last_ended_sequence());
  EXPECT_EQ(removed_observer.last_scheduled_sequence(), sequence);
  EXPECT_TRUE(!removed_observer.last_ended_sequence());

  // This should stop the observer from observing sequence.
  animator->RemoveObserver(&removed_observer);

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_EQ(observer.last_ended_sequence(), sequence);
  EXPECT_TRUE(!removed_observer.last_ended_sequence());
}

TEST(LayerAnimatorTest, ObserverReleasedBeforeAnimationSequenceEnds) {
  TestLayerAnimationDelegate delegate;
  std::unique_ptr<TestLayerAnimationObserver> observer(
      new TestLayerAnimationObserver);
  scoped_refptr<LayerAnimator> animator(
      CreateDefaultTestAnimator(&delegate, observer.get()));

  delegate.SetOpacityFromAnimation(0.0f,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  base::TimeDelta delta = base::Seconds(1);
  LayerAnimationSequence* sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(1.0f, delta));

  animator->StartAnimation(sequence);

  // |observer| should be attached to |sequence|.
  EXPECT_TRUE(!sequence->observers_.empty());

  // Now, release |observer|
  observer.reset();

  // And |sequence| should no longer be attached to |observer|.
  EXPECT_FALSE(!sequence->observers_.empty());
}

TEST(LayerAnimatorTest, ObserverAttachedAfterAnimationStarted) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  TestImplicitAnimationObserver observer(false);

  delegate.SetBrightnessFromAnimation(0.0f,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  {
    ScopedLayerAnimationSettings setter(animator.get());

    base::TimeDelta delta = base::Seconds(1);
    LayerAnimationSequence* sequence = new LayerAnimationSequence(
        LayerAnimationElement::CreateBrightnessElement(1.0f, delta));

    animator->StartAnimation(sequence);
    base::TimeTicks start_time = animator->last_step_time();
    animator->Step(start_time + base::Milliseconds(500));

    setter.AddObserver(&observer);

    // Start observing an in-flight animation.
    sequence->AddObserver(&observer);

    animator->Step(start_time + base::Milliseconds(1000));
  }

  EXPECT_TRUE(observer.animations_completed());
  EXPECT_TRUE(observer.WasAnimationCompletedForProperty(
                  LayerAnimationElement::BRIGHTNESS));
}

TEST(LayerAnimatorTest, ObserverDetachedBeforeAnimationFinished) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  TestImplicitAnimationObserver observer(false);

  delegate.SetBrightnessFromAnimation(0.0f,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);
  base::TimeDelta delta = base::Seconds(1);
  LayerAnimationSequence* sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(1.0f, delta));

  {
    ScopedLayerAnimationSettings setter(animator.get());
    setter.AddObserver(&observer);

    animator->StartAnimation(sequence);
    base::TimeTicks start_time = animator->last_step_time();
    animator->Step(start_time + base::Milliseconds(500));
  }

  EXPECT_FALSE(observer.animations_completed());

  // Stop observing an in-flight animation.
  sequence->RemoveObserver(&observer);

  EXPECT_TRUE(observer.animations_completed());

  // The animation didn't complete, and neither was it aborted.
  EXPECT_FALSE(observer.WasAnimationCompletedForProperty(
                  LayerAnimationElement::BRIGHTNESS));
  EXPECT_FALSE(observer.WasAnimationAbortedForProperty(
                  LayerAnimationElement::BRIGHTNESS));
}

// This checks that if an animation is deleted due to a callback, that the
// animator does not try to use the deleted animation. For example, if we have
// two running animations, and the first finishes and the resulting callback
// causes the second to be deleted, we should not attempt to animate the second
// animation.
TEST(LayerAnimatorTest, ObserverDeletesAnimationsOnEnd) {
  ScopedAnimationDurationScaleMode normal_duration_mode(
      ScopedAnimationDurationScaleMode::NORMAL_DURATION);
  scoped_refptr<LayerAnimator> animator(new TestLayerAnimator());
  animator->set_disable_timer_for_test(true);
  TestLayerAnimationDelegate delegate;
  animator->SetDelegate(&delegate);

  double start_brightness(0.0);
  double target_brightness(1.0);

  gfx::Rect start_bounds(0, 0, 50, 50);
  gfx::Rect target_bounds(5, 5, 5, 5);

  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  base::TimeDelta brightness_delta = base::Seconds(1);
  base::TimeDelta halfway_delta = base::Seconds(2);
  base::TimeDelta bounds_delta = base::Seconds(3);

  std::unique_ptr<DeletingLayerAnimationObserver> observer(
      new DeletingLayerAnimationObserver(animator.get()));

  animator->AddObserver(observer.get());

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(
              target_brightness, brightness_delta)));

  animator->StartAnimation(new LayerAnimationSequence(
      LayerAnimationElement::CreateBoundsElement(
          target_bounds, bounds_delta)));
  ASSERT_TRUE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));

  base::TimeTicks start_time = animator->last_step_time();
  animator->Step(start_time + halfway_delta);

  // Completing the brightness animation should have stopped the bounds
  // animation.
  ASSERT_FALSE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));

  animator->RemoveObserver(observer.get());
}

// Ensure that stopping animation in a bounds change does not crash and that
// animation gets stopped correctly.
// This scenario is possible when animation is restarted from inside a
// callback triggered by the animation progress.
TEST(LayerAnimatorTest, CallbackDeletesAnimationInProgress) {

  class TestLayerAnimationDeletingDelegate : public TestLayerAnimationDelegate {
   public:
    TestLayerAnimationDeletingDelegate(LayerAnimator* animator, int max_width)
      : animator_(animator),
        max_width_(max_width) {
    }

    void SetBoundsFromAnimation(const gfx::Rect& bounds,
                                PropertyChangeReason reason) override {
      TestLayerAnimationDelegate::SetBoundsFromAnimation(bounds, reason);
      if (bounds.width() > max_width_)
        animator_->StopAnimating();
    }
   private:
    raw_ptr<LayerAnimator> animator_;
    int max_width_;
    // Allow copy and assign.
  };

  ScopedAnimationDurationScaleMode normal_duration_mode(
      ScopedAnimationDurationScaleMode::NORMAL_DURATION);
  scoped_refptr<LayerAnimator> animator(new TestLayerAnimator());
  animator->set_disable_timer_for_test(true);
  TestLayerAnimationDeletingDelegate delegate(animator.get(), 30);
  animator->SetDelegate(&delegate);

  gfx::Rect start_bounds(0, 0, 0, 0);
  gfx::Rect target_bounds(5, 5, 50, 50);

  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  base::TimeDelta bounds_delta1 = base::Milliseconds(333);
  base::TimeDelta bounds_delta2 = base::Milliseconds(666);
  base::TimeDelta bounds_delta = base::Milliseconds(1000);
  base::TimeDelta final_delta = base::Milliseconds(1500);

  animator->StartAnimation(new LayerAnimationSequence(
      LayerAnimationElement::CreateBoundsElement(
          target_bounds, bounds_delta)));
  ASSERT_TRUE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));

  base::TimeTicks start_time = animator->last_step_time();
  ASSERT_NO_FATAL_FAILURE(animator->Step(start_time + bounds_delta1));
  ASSERT_TRUE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));

  // The next step should change the animated bounds past the threshold and
  // cause the animaton to stop.
  ASSERT_NO_FATAL_FAILURE(animator->Step(start_time + bounds_delta2));
  ASSERT_FALSE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));
  ASSERT_NO_FATAL_FAILURE(animator->Step(start_time + final_delta));

  // Completing the animation should have stopped the bounds
  // animation.
  ASSERT_FALSE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));
}

// Similar to the ObserverDeletesAnimationsOnEnd test above except that it
// tests the behavior when the OnLayerAnimationAborted() callback causes
// all of the animator's other animations to be deleted.
TEST(LayerAnimatorTest, ObserverDeletesAnimationsOnAbort) {
  ScopedAnimationDurationScaleMode test_duration_mode(
      ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
  scoped_refptr<LayerAnimator> animator(new TestLayerAnimator());
  animator->set_disable_timer_for_test(true);
  TestLayerAnimationDelegate delegate;
  animator->SetDelegate(&delegate);

  double start_brightness(0.0);
  double target_brightness(1.0);
  gfx::Rect start_bounds(0, 0, 50, 50);
  gfx::Rect target_bounds(5, 5, 5, 5);
  base::TimeDelta brightness_delta = base::Seconds(1);
  base::TimeDelta bounds_delta = base::Seconds(2);

  delegate.SetBrightnessFromAnimation(start_brightness,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  std::unique_ptr<DeletingLayerAnimationObserver> observer(
      new DeletingLayerAnimationObserver(animator.get()));
  animator->AddObserver(observer.get());

  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(
              target_brightness, brightness_delta)));
  animator->StartAnimation(new LayerAnimationSequence(
      LayerAnimationElement::CreateBoundsElement(
          target_bounds, bounds_delta)));
  ASSERT_TRUE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));

  animator->set_preemption_strategy(
      LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
  animator->StartAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateBrightnessElement(
              target_brightness, brightness_delta)));

  // Starting the second brightness animation should have aborted the initial
  // brightness animation. |observer| should have stopped the bounds animation
  // as a result.
  ASSERT_FALSE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));

  animator->RemoveObserver(observer.get());
}

// Check that setting a property during an animation with a default animator
// cancels the original animation.
TEST(LayerAnimatorTest, SettingPropertyDuringAnAnimation) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  double start_opacity(0.0);
  double target_opacity(1.0);

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetOpacityFromAnimation(start_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  std::unique_ptr<LayerAnimationSequence> sequence =
      std::make_unique<LayerAnimationSequence>(
          LayerAnimationElement::CreateOpacityElement(target_opacity, delta));

  animator->StartAnimation(sequence.release());

  animator->SetOpacity(0.5);

  EXPECT_FALSE(animator->is_animating());
  EXPECT_EQ(0.5, animator->GetTargetOpacity());
}

// Tests that the preemption mode IMMEDIATELY_SET_NEW_TARGET, doesn't cause the
// second sequence to be leaked.
TEST(LayerAnimatorTest, ImmediatelySettingNewTargetDoesNotLeak) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  animator->set_preemption_strategy(LayerAnimator::IMMEDIATELY_SET_NEW_TARGET);

  gfx::Rect start_bounds(0, 0, 50, 50);
  gfx::Rect middle_bounds(10, 10, 100, 100);
  gfx::Rect target_bounds(5, 5, 5, 5);

  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  {
    // start an implicit bounds animation.
    ScopedLayerAnimationSettings settings(animator.get());
    animator->SetBounds(middle_bounds);
  }

  EXPECT_TRUE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));

  int num_live_instances = 0;
  base::TimeDelta delta = base::Seconds(1);
  std::unique_ptr<TestLayerAnimationSequence> sequence =
      std::make_unique<TestLayerAnimationSequence>(
          LayerAnimationElement::CreateBoundsElement(target_bounds, delta),
          &num_live_instances);

  EXPECT_EQ(1, num_live_instances);

  // This should interrupt the running sequence causing us to immediately set
  // the target value. The sequence should alse be destructed.
  animator->StartAnimation(sequence.release());

  EXPECT_FALSE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));
  EXPECT_EQ(0, num_live_instances);
  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds);
}

// Verifies GetTargetOpacity() works when multiple sequences are scheduled.
TEST(LayerAnimatorTest, GetTargetOpacity) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION);

  delegate.SetOpacityFromAnimation(0.0,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    animator->SetOpacity(0.5);
    EXPECT_EQ(0.5, animator->GetTargetOpacity());

    // Because the strategy is ENQUEUE_NEW_ANIMATION the target should now be 1.
    animator->SetOpacity(1.0);
    EXPECT_EQ(1.0, animator->GetTargetOpacity());
  }
}

// Verifies GetTargetBrightness() works when multiple sequences are scheduled.
TEST(LayerAnimatorTest, GetTargetBrightness) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION);

  delegate.SetBrightnessFromAnimation(0.0,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    animator->SetBrightness(0.5);
    EXPECT_EQ(0.5, animator->GetTargetBrightness());

    // Because the strategy is ENQUEUE_NEW_ANIMATION the target should now be 1.
    animator->SetBrightness(1.0);
    EXPECT_EQ(1.0, animator->GetTargetBrightness());
  }
}

// Verifies GetTargetGrayscale() works when multiple sequences are scheduled.
TEST(LayerAnimatorTest, GetTargetGrayscale) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION);

  delegate.SetGrayscaleFromAnimation(0.0,
                                     PropertyChangeReason::NOT_FROM_ANIMATION);

  {
    ScopedLayerAnimationSettings settings(animator.get());
    animator->SetGrayscale(0.5);
    EXPECT_EQ(0.5, animator->GetTargetGrayscale());

    // Because the strategy is ENQUEUE_NEW_ANIMATION the target should now be 1.
    animator->SetGrayscale(1.0);
    EXPECT_EQ(1.0, animator->GetTargetGrayscale());
  }
}

// Verifies color property is modified appropriately.
TEST(LayerAnimatorTest, Color) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  SkColor4f start_color = SkColor4f::FromColor(SkColorSetARGB(64, 20, 40, 60));
  SkColor4f middle_color =
      SkColor4f::FromColor(SkColorSetARGB(128, 35, 70, 120));
  SkColor4f target_color =
      SkColor4f::FromColor(SkColorSetARGB(192, 40, 80, 140));

  base::TimeDelta delta = base::Seconds(1);

  delegate.SetColorFromAnimation(start_color,
                                 PropertyChangeReason::NOT_FROM_ANIMATION);

  animator->ScheduleAnimation(
      new LayerAnimationSequence(
          LayerAnimationElement::CreateColorElement(target_color, delta)));

  EXPECT_TRUE(animator->is_animating());
  EXPECT_EQ(start_color, delegate.GetColorForAnimation());

  base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + base::Milliseconds(500));

  EXPECT_TRUE(animator->is_animating());
  // The color is not exactly middle_color because of the round errors.
  EXPECT_EQ(middle_color.toSkColor(),
            delegate.GetColorForAnimation().toSkColor());

  animator->Step(start_time + base::Milliseconds(1000));

  EXPECT_FALSE(animator->is_animating());
  EXPECT_EQ(target_color, delegate.GetColorForAnimation());
}

// Verifies SchedulePauseForProperties().
TEST(LayerAnimatorTest, SchedulePauseForProperties) {
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator();
  animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION);
  animator->SchedulePauseForProperties(
      base::Milliseconds(100),
      LayerAnimationElement::TRANSFORM | LayerAnimationElement::BOUNDS);
  EXPECT_TRUE(animator->IsAnimatingProperty(LayerAnimationElement::TRANSFORM));
  EXPECT_TRUE(animator->IsAnimatingProperty(LayerAnimationElement::BOUNDS));
  EXPECT_FALSE(animator->IsAnimatingProperty(LayerAnimationElement::OPACITY));
}

// Verifies that IsAnimatingOnePropertyOf() returns true iff at least one of the
// input properties is animated.
TEST(LayerAnimatorTest, IsAnimatingOnePropertyOf) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateImplicitTestAnimator(&delegate);
  animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION);
  animator->SetBrightness(0.5f);
  animator->SetGrayscale(0.5f);
  EXPECT_TRUE(animator->IsAnimatingOnePropertyOf(
      LayerAnimationElement::LayerAnimationElement::BRIGHTNESS));
  EXPECT_TRUE(animator->IsAnimatingOnePropertyOf(
      LayerAnimationElement::LayerAnimationElement::GRAYSCALE));
  EXPECT_TRUE(animator->IsAnimatingOnePropertyOf(
      LayerAnimationElement::LayerAnimationElement::BRIGHTNESS |
      LayerAnimationElement::LayerAnimationElement::GRAYSCALE));
  EXPECT_TRUE(animator->IsAnimatingOnePropertyOf(
      LayerAnimationElement::LayerAnimationElement::BRIGHTNESS));
  EXPECT_FALSE(animator->IsAnimatingOnePropertyOf(
      LayerAnimationElement::LayerAnimationElement::BOUNDS));
}

class AnimatorOwner {
 public:
  AnimatorOwner() : animator_(CreateDefaultTestAnimator()) {}

  AnimatorOwner(const AnimatorOwner&) = delete;
  AnimatorOwner& operator=(const AnimatorOwner&) = delete;

  LayerAnimator* animator() { return animator_.get(); }

 private:
  scoped_refptr<LayerAnimator> animator_;
};

class DeletingObserver : public LayerAnimationObserver {
 public:
  explicit DeletingObserver(bool* was_deleted)
      : animator_owner_(new AnimatorOwner),
        delete_on_animation_ended_(false),
        delete_on_animation_aborted_(false),
        delete_on_animation_scheduled_(false),
        was_deleted_(was_deleted) {
    animator()->AddObserver(this);
  }

  DeletingObserver(const DeletingObserver&) = delete;
  DeletingObserver& operator=(const DeletingObserver&) = delete;

  ~DeletingObserver() override {
    animator()->RemoveObserver(this);
    *was_deleted_ = true;
  }

  LayerAnimator* animator() { return animator_owner_->animator(); }

  bool delete_on_animation_ended() const {
    return delete_on_animation_ended_;
  }
  void set_delete_on_animation_ended(bool enabled) {
    delete_on_animation_ended_ = enabled;
  }

  bool delete_on_animation_aborted() const {
    return delete_on_animation_aborted_;
  }
  void set_delete_on_animation_aborted(bool enabled) {
    delete_on_animation_aborted_ = enabled;
  }

  bool delete_on_animation_scheduled() const {
    return delete_on_animation_scheduled_;
  }
  void set_delete_on_animation_scheduled(bool enabled) {
    delete_on_animation_scheduled_ = enabled;
  }

  // LayerAnimationObserver implementation.
  void OnLayerAnimationEnded(LayerAnimationSequence* sequence) override {
    if (delete_on_animation_ended_)
      delete this;
  }

  void OnLayerAnimationAborted(LayerAnimationSequence* sequence) override {
    if (delete_on_animation_aborted_)
      delete this;
  }

  void OnLayerAnimationScheduled(LayerAnimationSequence* sequence) override {
    if (delete_on_animation_scheduled_)
      delete this;
  }

 private:
  std::unique_ptr<AnimatorOwner> animator_owner_;
  bool delete_on_animation_ended_;
  bool delete_on_animation_aborted_;
  bool delete_on_animation_scheduled_;
  raw_ptr<bool> was_deleted_;
};

TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterFinishingAnimation) {
  bool observer_was_deleted = false;
  DeletingObserver* observer = new DeletingObserver(&observer_was_deleted);
  observer->set_delete_on_animation_ended(true);
  observer->set_delete_on_animation_aborted(true);
  LayerAnimator* animator = observer->animator();
  TestLayerAnimationDelegate delegate;
  animator->SetDelegate(&delegate);

  delegate.SetBrightnessFromAnimation(0.0f,
                                      PropertyChangeReason::NOT_FROM_ANIMATION);

  gfx::Rect start_bounds(0, 0, 50, 50);
  gfx::Rect target_bounds(10, 10, 100, 100);

  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  base::TimeDelta delta = base::Seconds(1);
  LayerAnimationSequence* brightness_sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(1.0f, delta));
  animator->StartAnimation(brightness_sequence);

  delta = base::Seconds(2);
  LayerAnimationSequence* bounds_sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBoundsElement(target_bounds, delta));
  animator->StartAnimation(bounds_sequence);

  base::TimeTicks start_time = animator->last_step_time();
  animator->Step(start_time + base::Milliseconds(1500));

  EXPECT_TRUE(observer_was_deleted);
}

TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterStoppingAnimating) {
  bool observer_was_deleted = false;
  DeletingObserver* observer = new DeletingObserver(&observer_was_deleted);
  observer->set_delete_on_animation_ended(true);
  observer->set_delete_on_animation_aborted(true);
  LayerAnimator* animator = observer->animator();
  TestLayerAnimationDelegate delegate;
  animator->SetDelegate(&delegate);

  delegate.SetOpacityFromAnimation(0.0f,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  gfx::Rect start_bounds(0, 0, 50, 50);
  gfx::Rect target_bounds(10, 10, 100, 100);

  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  base::TimeDelta delta = base::Seconds(1);
  LayerAnimationSequence* opacity_sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(1.0f, delta));
  animator->StartAnimation(opacity_sequence);

  delta = base::Seconds(2);
  LayerAnimationSequence* bounds_sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBoundsElement(target_bounds, delta));
  animator->StartAnimation(bounds_sequence);

  animator->StopAnimating();

  EXPECT_TRUE(observer_was_deleted);
}

TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterScheduling) {
  bool observer_was_deleted = false;
  TestLayerAnimationDelegate delegate;
  DeletingObserver* observer = new DeletingObserver(&observer_was_deleted);
  observer->set_delete_on_animation_scheduled(true);
  LayerAnimator* animator = observer->animator();
  animator->SetDelegate(&delegate);

  delegate.SetOpacityFromAnimation(0.0f,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  gfx::Rect start_bounds(0, 0, 50, 50);
  gfx::Rect target_bounds(10, 10, 100, 100);

  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  std::vector<LayerAnimationSequence*> to_start;

  base::TimeDelta delta = base::Seconds(1);
  to_start.push_back(new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(1.0f, delta)));

  delta = base::Seconds(2);
  to_start.push_back(new LayerAnimationSequence(
      LayerAnimationElement::CreateBoundsElement(target_bounds, delta)));

  animator->ScheduleTogether(to_start);

  EXPECT_TRUE(observer_was_deleted);
}

TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterAborted) {
  bool observer_was_deleted = false;
  DeletingObserver* observer = new DeletingObserver(&observer_was_deleted);
  TestLayerAnimationDelegate delegate;
  observer->set_delete_on_animation_aborted(true);
  LayerAnimator* animator = observer->animator();
  animator->set_preemption_strategy(
      LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
  animator->SetDelegate(&delegate);

  delegate.SetOpacityFromAnimation(0.0f,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  gfx::Rect start_bounds(0, 0, 50, 50);
  gfx::Rect target_bounds(10, 10, 100, 100);

  delegate.SetBoundsFromAnimation(start_bounds,
                                  PropertyChangeReason::NOT_FROM_ANIMATION);

  std::vector<LayerAnimationSequence*> to_start;

  base::TimeDelta delta = base::Seconds(1);
  to_start.push_back(new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(1.0f, delta)));

  delta = base::Seconds(2);
  to_start.push_back(new LayerAnimationSequence(
      LayerAnimationElement::CreateBoundsElement(target_bounds, delta)));

  animator->ScheduleTogether(to_start);

  EXPECT_FALSE(observer_was_deleted);

  animator->StartAnimation(new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(1.0f, delta)));

  EXPECT_TRUE(observer_was_deleted);
}


TEST(LayerAnimatorTest, TestSetterRespectEnqueueStrategy) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  float start_opacity = 0.0f;
  float target_opacity = 1.0f;
  float magic_opacity = 0.123f;

  delegate.SetOpacityFromAnimation(start_opacity,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  ScopedLayerAnimationSettings settings(animator.get());
  settings.SetPreemptionStrategy(
      LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
  settings.SetTransitionDuration(base::Seconds(1));
  animator->SetOpacity(target_opacity);

  EXPECT_EQ(start_opacity, delegate.GetOpacityForAnimation());

  settings.SetPreemptionStrategy(
      LayerAnimator::ENQUEUE_NEW_ANIMATION);
  settings.SetTransitionDuration(base::TimeDelta());
  animator->SetOpacity(magic_opacity);

  EXPECT_EQ(start_opacity, delegate.GetOpacityForAnimation());
}

class CollectionLayerAnimationDelegate : public TestLayerAnimationDelegate {
 public:
  CollectionLayerAnimationDelegate() : collection(NULL) {}
  ~CollectionLayerAnimationDelegate() override {}

  // LayerAnimationDelegate:
  LayerAnimatorCollection* GetLayerAnimatorCollection() override {
    return &collection;
  }

 private:
  LayerAnimatorCollection collection;
};

TEST(LayerAnimatorTest, LayerAnimatorCollectionTickTime) {
  Layer layer;
  LayerAnimator* animator = layer.GetAnimator();
  CollectionLayerAnimationDelegate delegate;
  animator->SetDelegate(&delegate);

  LayerAnimatorCollection* collection = delegate.GetLayerAnimatorCollection();
  base::TimeTicks null;
  collection->OnAnimationStep(null);
  EXPECT_TRUE(collection->last_tick_time().is_null());

  // Adding an animator to the collection should update the last tick time.
  collection->StartAnimator(layer.GetAnimator());
  EXPECT_TRUE(collection->HasActiveAnimators());
  EXPECT_FALSE(collection->last_tick_time().is_null());

  collection->StopAnimator(layer.GetAnimator());
  EXPECT_FALSE(collection->HasActiveAnimators());

  animator->SetDelegate(nullptr);
}

// Verifies that sequences are removed from the animation queue prior to be
// notified of being started. This will allow observers to abort animations in
// the OnLayerAnimationStarted() callback without triggering a sequence to be
// started a second time.
TEST(LayerAnimatorTest,
     SequencesAreRemovedFromQueueBeforeBeingNotifiedOfStarted) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);

  AbortAnimationsOnStartedLayerAnimationObserver aborting_observer(
      animator.get());
  test::CountCheckingLayerAnimationObserver counting_observer(
      &aborting_observer);

  const base::TimeDelta sequence_duration = base::Seconds(1);

  animator->ScheduleAnimation(new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(1.f, sequence_duration)));

  LayerAnimationSequence* observed_sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(0.f, sequence_duration));
  observed_sequence->AddObserver(&counting_observer);
  animator->ScheduleAnimation(observed_sequence);

  EXPECT_TRUE(animator->is_animating());
  const base::TimeTicks start_time = animator->last_step_time();

  animator->Step(start_time + sequence_duration * 3);
  EXPECT_FALSE(animator->is_animating());
}

TEST(LayerAnimatorTest, AnimatorStartedCorrectly) {
  Layer layer;
  LayerAnimatorTestController test_controller(layer.GetAnimator());
  LayerAnimator* animator = test_controller.animator();
  ASSERT_FALSE(animator->is_started_);

  TestLayerAnimationDelegate test_delegate;
  animator->SetDelegate(&test_delegate);
  double target_opacity = 1.0;
  base::TimeDelta time_delta = base::Seconds(1);
  animator->ScheduleAnimation(new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta)));
  EXPECT_FALSE(animator->is_started_);

  CollectionLayerAnimationDelegate collection_delegate;
  animator->SetDelegate(&collection_delegate);
  animator->UpdateAnimationState();
  EXPECT_TRUE(animator->is_started_);
  animator->SetDelegate(NULL);
}

TEST(LayerAnimatorTest, AnimatorRemovedFromCollectionWhenLayerIsDestroyed) {
  std::unique_ptr<Layer> layer(new Layer(LAYER_TEXTURED));
  LayerAnimatorTestController test_controller(layer->GetAnimator());
  scoped_refptr<LayerAnimator> animator = test_controller.animator();
  CollectionLayerAnimationDelegate collection_delegate;
  animator->SetDelegate(&collection_delegate);

  double target_opacity = 1.0;
  base::TimeDelta time_delta = base::Seconds(1);
  animator->ScheduleAnimation(new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta)));

  EXPECT_TRUE(
      collection_delegate.GetLayerAnimatorCollection()->HasActiveAnimators());

  layer.reset();
  EXPECT_EQ(NULL, animator->delegate());
  EXPECT_FALSE(
      collection_delegate.GetLayerAnimatorCollection()->HasActiveAnimators());
}

TEST(LayerAnimatorTest, LayerMovedBetweenCompositorsDuringAnimation) {
  base::test::TaskEnvironment task_environment_(
      base::test::TaskEnvironment::MainThreadType::UI);
  const bool enable_pixel_output = false;
  TestContextFactories context_factories(enable_pixel_output);
  const gfx::Rect bounds(10, 10, 100, 100);
  std::unique_ptr<TestCompositorHost> host_1(TestCompositorHost::Create(
      bounds, context_factories.GetContextFactory()));
  std::unique_ptr<TestCompositorHost> host_2(TestCompositorHost::Create(
      bounds, context_factories.GetContextFactory()));
  host_1->Show();
  host_2->Show();

  Compositor* compositor_1 = host_1->GetCompositor();
  Layer root_1;
  compositor_1->SetRootLayer(&root_1);
  cc::MutatorHost* mutator_host_1 =
      root_1.cc_layer_for_testing()->layer_tree_host()->mutator_host();

  Compositor* compositor_2 = host_2->GetCompositor();
  Layer root_2;
  compositor_2->SetRootLayer(&root_2);
  cc::MutatorHost* mutator_host_2 =
      root_2.cc_layer_for_testing()->layer_tree_host()->mutator_host();

  // Verify that neither compositor has active animators.
  EXPECT_FALSE(compositor_1->layer_animator_collection()->HasActiveAnimators());
  EXPECT_FALSE(compositor_2->layer_animator_collection()->HasActiveAnimators());

  Layer layer;
  layer.SetOpacity(0.5f);
  root_1.Add(&layer);
  EXPECT_FALSE(
      mutator_host_1->HasTickingKeyframeModelForTesting(layer.element_id()));
  EXPECT_FALSE(
      mutator_host_2->HasTickingKeyframeModelForTesting(layer.element_id()));

  LayerAnimator* animator = layer.GetAnimator();
  double target_opacity = 1.0;
  base::TimeDelta time_delta = base::Seconds(1);

  animator->ScheduleAnimation(new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta)));
  EXPECT_TRUE(compositor_1->layer_animator_collection()->HasActiveAnimators());
  EXPECT_FALSE(compositor_2->layer_animator_collection()->HasActiveAnimators());
  EXPECT_TRUE(
      mutator_host_1->HasTickingKeyframeModelForTesting(layer.element_id()));
  EXPECT_FALSE(
      mutator_host_2->HasTickingKeyframeModelForTesting(layer.element_id()));

  root_2.Add(&layer);
  EXPECT_FALSE(compositor_1->layer_animator_collection()->HasActiveAnimators());
  EXPECT_TRUE(compositor_2->layer_animator_collection()->HasActiveAnimators());
  EXPECT_FALSE(
      mutator_host_1->HasTickingKeyframeModelForTesting(layer.element_id()));
  EXPECT_TRUE(
      mutator_host_2->HasTickingKeyframeModelForTesting(layer.element_id()));

  host_2.reset();
  host_1.reset();
}

TEST(LayerAnimatorTest, ThreadedAnimationSurvivesIfLayerRemovedAdded) {
  base::test::TaskEnvironment task_environment_(
      base::test::TaskEnvironment::MainThreadType::UI);
  const bool enable_pixel_output = false;
  TestContextFactories context_factories(enable_pixel_output);
  const gfx::Rect bounds(10, 10, 100, 100);
  std::unique_ptr<TestCompositorHost> host(TestCompositorHost::Create(
      bounds, context_factories.GetContextFactory()));
  host->Show();

  Compositor* compositor = host->GetCompositor();

  Layer root;
  compositor->SetRootLayer(&root);

  Layer layer;
  layer.SetOpacity(0.5f);
  root.Add(&layer);

  LayerAnimator* animator = layer.GetAnimator();
  double target_opacity = 1.0;
  base::TimeDelta time_delta = base::Seconds(1);

  animator->ScheduleAnimation(new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta)));

  cc::MutatorHost* mutator =
      layer.cc_layer_for_testing()->layer_tree_host()->mutator_host();
  EXPECT_TRUE(mutator->HasTickingKeyframeModelForTesting(layer.element_id()));

  root.Remove(&layer);

  root.Add(&layer);

  mutator = layer.cc_layer_for_testing()->layer_tree_host()->mutator_host();
  EXPECT_TRUE(mutator->HasTickingKeyframeModelForTesting(layer.element_id()));

  host.reset();
}

class LayerOwnerAnimationObserver : public LayerAnimationObserver {
 public:
  explicit LayerOwnerAnimationObserver(LayerAnimator* animator)
      : animator_layer_(new Layer(LAYER_TEXTURED)) {
    animator_layer_->SetAnimator(animator);
  }

  LayerOwnerAnimationObserver(const LayerOwnerAnimationObserver&) = delete;
  LayerOwnerAnimationObserver& operator=(const LayerOwnerAnimationObserver&) =
      delete;

  ~LayerOwnerAnimationObserver() override {}

  void OnLayerAnimationEnded(LayerAnimationSequence* sequence) override {
    ASSERT_TRUE(sequence);
    animator_layer_.reset();
  }

  void OnLayerAnimationAborted(LayerAnimationSequence* sequence) override {
    ASSERT_TRUE(sequence);
    animator_layer_.reset();
  }

  LayerAnimationDelegate* animator_layer() {
    return animator_layer_.get();
  }

  void OnLayerAnimationScheduled(LayerAnimationSequence* sequence) override {}

 private:
  std::unique_ptr<Layer> animator_layer_;
};

TEST(LayerAnimatorTest, ObserverDeletesLayerInStopAnimating) {
  scoped_refptr<LayerAnimator> animator = CreateImplicitTestAnimator();
  LayerOwnerAnimationObserver observer(animator.get());
  LayerAnimationDelegate* delegate = observer.animator_layer();

  const gfx::Rect start_bounds(0, 0, 50, 50);
  const gfx::Rect target_bounds(10, 10, 100, 100);
  const double target_opacity = 1.0;

  delegate->SetOpacityFromAnimation(0.0f,
                                    PropertyChangeReason::NOT_FROM_ANIMATION);
  delegate->SetBoundsFromAnimation(start_bounds,
                                   PropertyChangeReason::NOT_FROM_ANIMATION);

  base::TimeDelta time_delta = base::Seconds(1);
  LayerAnimationSequence* opacity = new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta));
  opacity->AddObserver(&observer);
  animator->ScheduleAnimation(opacity);
  time_delta = base::Seconds(2);
  LayerAnimationSequence* move = new LayerAnimationSequence(
      LayerAnimationElement::CreateBoundsElement(target_bounds, time_delta));
  animator->ScheduleAnimation(move);
  EXPECT_TRUE(animator->is_animating());
  animator->Step(animator->last_step_time() + base::Milliseconds(500));
  animator->StopAnimating();

  EXPECT_EQ(nullptr, observer.animator_layer());
  EXPECT_TRUE(animator->is_animating());
}

TEST(LayerAnimatorTest,
     SetPropertyWithObserverThatDeletesLayerInStopAnimating) {
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator();
  LayerOwnerAnimationObserver observer(animator.get());
  LayerAnimationDelegate* delegate = observer.animator_layer();

  const double target_opacity = 1.0;
  delegate->SetOpacityFromAnimation(0.0f,
                                    PropertyChangeReason::NOT_FROM_ANIMATION);

  base::TimeDelta time_delta = base::Seconds(1);
  LayerAnimationSequence* opacity = new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta));
  opacity->AddObserver(&observer);
  animator->ScheduleAnimation(opacity);
  animator->Step(animator->last_step_time() + base::Milliseconds(500));
  EXPECT_TRUE(animator->is_animating());

  animator->SetOpacity(1.0f);
  EXPECT_EQ(nullptr, observer.animator_layer());
  EXPECT_FALSE(animator->is_animating());
}

TEST(LayerAnimatorTest,
     SetPropertyWithObserverThatDeletesLayerOnImplicitAnimationCompletion) {
  LayerOwner layer_owner(std::make_unique<Layer>(LAYER_SOLID_COLOR));

  // Create observer which deletes layer on implicit animation completion.
  TestImplicitAnimationObserver layer_animation_observer(true);
  layer_animation_observer.SetAnimationsCompletedCallback(
      base::BindRepeating(base::IgnoreResult(&LayerOwner::ReleaseLayer),
                          base::Unretained(&layer_owner)));

  {
    // Kick off and observe a property animation.
    ScopedLayerAnimationSettings settings(layer_owner.layer()->GetAnimator());
    settings.SetTransitionDuration(base::Seconds(1));
    settings.AddObserver(&layer_animation_observer);
    layer_owner.layer()->SetOpacity(1.f);
  }

  // Set the same property which will result in implicit completion of the
  // running animation which, in turn, will result in layer deletion.
  layer_owner.layer()->SetOpacity(0.f);
  EXPECT_FALSE(layer_owner.layer());
}

class CountCyclesObserver : public LayerAnimationObserver {
 public:
  explicit CountCyclesObserver(ui::LayerAnimator* animator)
      : animator_(animator) {
    animator_->AddObserver(this);
  }
  ~CountCyclesObserver() override { animator_->RemoveObserver(this); }
  CountCyclesObserver(const CountCyclesObserver&) = delete;
  CountCyclesObserver& operator=(const CountCyclesObserver&) = delete;

  void OnLayerAnimationEnded(LayerAnimationSequence* sequence) override {}

  void OnLayerAnimationAborted(LayerAnimationSequence* sequence) override {}

  void OnLayerAnimationWillRepeat(LayerAnimationSequence* sequence) override {
    cycles_count_++;
  }

  void OnLayerAnimationScheduled(LayerAnimationSequence* sequence) override {}

  int cycles_count() { return cycles_count_; }

 private:
  raw_ptr<ui::LayerAnimator> animator_;
  int cycles_count_ = 0;
};

// Verifies that an observer is notified each time a LayerAnimationSequence's
// cycle has ended.
TEST(LayerAnimatorTest, ObserverGetsNotifiedOnCycleEnded) {
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator = CreateDefaultTestAnimator(&delegate);
  CountCyclesObserver observer(animator.get());

  constexpr base::TimeDelta kAnimationDuration = base::Seconds(1);
  LayerAnimationSequence* sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(1.0f, kAnimationDuration));
  sequence->set_is_repeating(true);
  animator->StartAnimation(sequence);

  for (int i = 0; i < 3; i++) {
    EXPECT_EQ(observer.cycles_count(), i);
    const base::TimeTicks last_time = animator->last_step_time();
    animator->Step(last_time + kAnimationDuration);
  }
}

// Verifies the LayerAnimatorObserver notification order for an animation
// sequence that completes successfully.
TEST(LayerAnimatorObserverNotificationOrderTest,
     SuccessfulCompletionOfSequence) {
  for (int is_cyclic = 0; is_cyclic <= 0; is_cyclic++) {
    TestLayerAnimationObserver observer;
    TestLayerAnimationDelegate delegate;
    scoped_refptr<LayerAnimator> animator(
        CreateDefaultTestAnimator(&delegate, &observer));
    observer.set_requires_notification_when_animator_destroyed(true);

    const base::TimeDelta animation_duration = base::Seconds(100);

    LayerAnimationSequence* sequence = new LayerAnimationSequence(
        LayerAnimationElement::CreateBrightnessElement(1.0f,
                                                       animation_duration));
    sequence->set_is_repeating(is_cyclic);

    EXPECT_TRUE(observer.NoEventsObserved());

    animator->StartAnimation(sequence);

    EXPECT_EQ(observer.last_attached_sequence(), sequence);
    EXPECT_EQ(observer.last_scheduled_sequence(), sequence);
    EXPECT_EQ(observer.last_started_sequence(), sequence);
    EXPECT_EQ(observer.last_aborted_sequence(), nullptr);
    EXPECT_EQ(observer.last_ended_sequence(), nullptr);
    EXPECT_EQ(observer.last_repetition_ended_sequence(), nullptr);
    EXPECT_EQ(observer.last_detached_sequence(), nullptr);

    EXPECT_TRUE(observer.AttachedEpochIsBeforeScheduledEpoch());
    EXPECT_TRUE(observer.ScheduledEpochIsBeforeStartedEpoch());

    observer.ResetLayerAnimationObserverations();

    const base::TimeTicks start_time = animator->last_step_time();

    animator->Step(start_time + animation_duration);

    EXPECT_EQ(observer.last_attached_sequence(), nullptr);
    EXPECT_EQ(observer.last_scheduled_sequence(), nullptr);
    EXPECT_EQ(observer.last_started_sequence(), nullptr);
    EXPECT_EQ(observer.last_aborted_sequence(), nullptr);
    EXPECT_EQ(observer.last_ended_sequence(), is_cyclic ? nullptr : sequence);
    EXPECT_EQ(observer.last_repetition_ended_sequence(),
              is_cyclic ? sequence : nullptr);
    EXPECT_EQ(observer.last_detached_sequence(), sequence);

    EXPECT_TRUE(observer.EndedEpochIsBeforeDetachedEpoch());
  }
}

// Verifies the LayerAnimatorObserver notification order for an animation
// sequence that is aborted after being scheduled.
TEST(LayerAnimatorObserverNotificationOrderTest, AbortingAScheduledSequence) {
  TestLayerAnimationObserver observer;
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator(
      CreateDefaultTestAnimator(&delegate, &observer));
  observer.set_requires_notification_when_animator_destroyed(true);

  const base::TimeDelta animation_duration = base::Seconds(100);

  LayerAnimationSequence* sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(1.0f, animation_duration));

  EXPECT_TRUE(observer.NoEventsObserved());

  animator->StartAnimation(sequence);

  EXPECT_EQ(observer.last_attached_sequence(), sequence);
  EXPECT_EQ(observer.last_scheduled_sequence(), sequence);
  EXPECT_EQ(observer.last_started_sequence(), sequence);
  EXPECT_EQ(observer.last_aborted_sequence(), nullptr);
  EXPECT_EQ(observer.last_ended_sequence(), nullptr);
  EXPECT_EQ(observer.last_repetition_ended_sequence(), nullptr);
  EXPECT_EQ(observer.last_detached_sequence(), nullptr);

  EXPECT_TRUE(observer.AttachedEpochIsBeforeScheduledEpoch());
  EXPECT_TRUE(observer.ScheduledEpochIsBeforeStartedEpoch());

  observer.ResetLayerAnimationObserverations();

  animator->AbortAllAnimations();

  EXPECT_EQ(observer.last_attached_sequence(), nullptr);
  EXPECT_EQ(observer.last_scheduled_sequence(), nullptr);
  EXPECT_EQ(observer.last_started_sequence(), nullptr);
  EXPECT_EQ(observer.last_aborted_sequence(), sequence);
  EXPECT_EQ(observer.last_ended_sequence(), nullptr);
  EXPECT_EQ(observer.last_repetition_ended_sequence(), nullptr);
  EXPECT_EQ(observer.last_detached_sequence(), sequence);

  EXPECT_TRUE(observer.AbortedEpochIsBeforeDetachedEpoch());
}

// Verifies the LayerAnimatorObserver notification order for an animation
// sequence that is queued up after another sequence that
// completes successfully.
TEST(LayerAnimatorObserverNotificationOrderTest,
     RunningASequenceThatIsQueuedForLaterStartTime) {
  for (int is_cyclic = 0; is_cyclic <= 0; is_cyclic++) {
    TestLayerAnimationObserver observer;
    TestLayerAnimationDelegate delegate;
    scoped_refptr<LayerAnimator> animator(
        CreateDefaultTestAnimator(&delegate, &observer));
    observer.set_requires_notification_when_animator_destroyed(true);

    const base::TimeDelta animation_duration = base::Seconds(100);

    LayerAnimationSequence* first_sequence = new LayerAnimationSequence(
        LayerAnimationElement::CreateBrightnessElement(1.0f,
                                                       animation_duration));
    first_sequence->set_is_repeating(is_cyclic);

    LayerAnimationSequence* queued_sequence = new LayerAnimationSequence(
        LayerAnimationElement::CreateBrightnessElement(1.0f,
                                                       animation_duration));
    queued_sequence->set_is_repeating(is_cyclic);

    EXPECT_TRUE(observer.NoEventsObserved());

    animator->StartAnimation(first_sequence);

    EXPECT_EQ(observer.last_attached_sequence(), first_sequence);
    EXPECT_EQ(observer.last_scheduled_sequence(), first_sequence);
    EXPECT_EQ(observer.last_started_sequence(), first_sequence);
    EXPECT_EQ(observer.last_aborted_sequence(), nullptr);
    EXPECT_EQ(observer.last_ended_sequence(), nullptr);
    EXPECT_EQ(observer.last_repetition_ended_sequence(), nullptr);
    EXPECT_EQ(observer.last_detached_sequence(), nullptr);

    EXPECT_TRUE(observer.AttachedEpochIsBeforeScheduledEpoch());
    EXPECT_TRUE(observer.ScheduledEpochIsBeforeStartedEpoch());

    observer.ResetLayerAnimationObserverations();

    animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION);
    animator->StartAnimation(queued_sequence);

    EXPECT_EQ(observer.last_attached_sequence(), queued_sequence);
    EXPECT_EQ(observer.last_scheduled_sequence(), queued_sequence);
    EXPECT_EQ(observer.last_started_sequence(), nullptr);
    EXPECT_EQ(observer.last_aborted_sequence(), nullptr);
    EXPECT_EQ(observer.last_ended_sequence(), nullptr);
    EXPECT_EQ(observer.last_repetition_ended_sequence(), nullptr);
    EXPECT_EQ(observer.last_detached_sequence(), nullptr);

    EXPECT_TRUE(observer.AttachedEpochIsBeforeScheduledEpoch());

    observer.ResetLayerAnimationObserverations();

    base::TimeTicks start_time = animator->last_step_time();

    animator->Step(start_time + animation_duration);

    EXPECT_EQ(observer.last_attached_sequence(), nullptr);
    EXPECT_EQ(observer.last_scheduled_sequence(), nullptr);
    EXPECT_EQ(observer.last_started_sequence(), queued_sequence);
    EXPECT_EQ(observer.last_aborted_sequence(), nullptr);
    EXPECT_EQ(observer.last_ended_sequence(),
              is_cyclic ? nullptr : first_sequence);
    EXPECT_EQ(observer.last_repetition_ended_sequence(),
              is_cyclic ? first_sequence : nullptr);
    EXPECT_EQ(observer.last_detached_sequence(), first_sequence);

    EXPECT_TRUE(observer.EndedEpochIsBeforeDetachedEpoch());
    EXPECT_TRUE(observer.EndedEpochIsBeforeStartedEpoch());
  }
}

// Verifies the LayerAnimatorObserver notification order for an animation
// sequence that pre-empts another sequence.
TEST(LayerAnimatorObserverNotificationOrderTest,
     RunningASequenceThatPreEmptsAnotherSequence) {
  TestLayerAnimationObserver observer;
  TestLayerAnimationDelegate delegate;
  scoped_refptr<LayerAnimator> animator(
      CreateDefaultTestAnimator(&delegate, &observer));
  observer.set_requires_notification_when_animator_destroyed(true);

  const base::TimeDelta animation_duration = base::Seconds(100);

  LayerAnimationSequence* first_sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(1.0f, animation_duration));

  LayerAnimationSequence* queued_sequence = new LayerAnimationSequence(
      LayerAnimationElement::CreateBrightnessElement(1.0f, animation_duration));

  EXPECT_TRUE(observer.NoEventsObserved());

  animator->StartAnimation(first_sequence);

  EXPECT_EQ(observer.last_attached_sequence(), first_sequence);
  EXPECT_EQ(observer.last_scheduled_sequence(), first_sequence);
  EXPECT_EQ(observer.last_started_sequence(), first_sequence);
  EXPECT_EQ(observer.last_aborted_sequence(), nullptr);
  EXPECT_EQ(observer.last_ended_sequence(), nullptr);
  EXPECT_EQ(observer.last_repetition_ended_sequence(), nullptr);
  EXPECT_EQ(observer.last_detached_sequence(), nullptr);

  EXPECT_TRUE(observer.AttachedEpochIsBeforeScheduledEpoch());
  EXPECT_TRUE(observer.ScheduledEpochIsBeforeStartedEpoch());

  observer.ResetLayerAnimationObserverations();

  animator->set_preemption_strategy(
      LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
  animator->StartAnimation(queued_sequence);

  EXPECT_EQ(observer.last_attached_sequence(), queued_sequence);
  EXPECT_EQ(observer.last_scheduled_sequence(), queued_sequence);
  EXPECT_EQ(observer.last_started_sequence(), queued_sequence);
  EXPECT_EQ(observer.last_aborted_sequence(), first_sequence);
  EXPECT_EQ(observer.last_ended_sequence(), nullptr);
  EXPECT_EQ(observer.last_repetition_ended_sequence(), nullptr);
  EXPECT_EQ(observer.last_detached_sequence(), first_sequence);

  EXPECT_TRUE(observer.AbortedEpochIsBeforeDetachedEpoch());
  EXPECT_TRUE(observer.AbortedEpochIsBeforeStartedEpoch());
  EXPECT_TRUE(observer.AttachedEpochIsBeforeScheduledEpoch());
  EXPECT_TRUE(observer.ScheduledEpochIsBeforeStartedEpoch());
}

// Verifies that an observer can be attached to a LayerAnimationSequence that
// has already been scheduled.
TEST(LayerAnimatorObserverNotificationOrderTest,
     ObserverAddedAfterAnimationStarts) {
  for (int is_cyclic = 0; is_cyclic <= 0; is_cyclic++) {
    TestLayerAnimationDelegate delegate;
    scoped_refptr<LayerAnimator> animator =
        CreateDefaultTestAnimator(&delegate);

    constexpr base::TimeDelta kAnimationDuration = base::Seconds(1);
    LayerAnimationSequence* sequence = new LayerAnimationSequence(
        LayerAnimationElement::CreateBrightnessElement(1.0f,
                                                       kAnimationDuration));
    sequence->set_is_repeating(is_cyclic);
    animator->StartAnimation(sequence);

    TestLayerAnimationObserver observer;
    observer.set_requires_notification_when_animator_destroyed(true);
    animator->AddObserver(&observer);

    EXPECT_EQ(observer.last_attached_sequence(), sequence);
    EXPECT_EQ(observer.last_scheduled_sequence(), nullptr);
    EXPECT_EQ(observer.last_started_sequence(), nullptr);
    EXPECT_EQ(observer.last_aborted_sequence(), nullptr);
    EXPECT_EQ(observer.last_ended_sequence(), nullptr);
    EXPECT_EQ(observer.last_repetition_ended_sequence(), nullptr);
    EXPECT_EQ(observer.last_detached_sequence(), nullptr);

    animator->StopAnimating();

    EXPECT_EQ(observer.last_attached_sequence(), sequence);
    EXPECT_EQ(observer.last_scheduled_sequence(), nullptr);
    EXPECT_EQ(observer.last_started_sequence(), nullptr);
    EXPECT_EQ(observer.last_aborted_sequence(), nullptr);
    EXPECT_EQ(observer.last_ended_sequence(), is_cyclic ? nullptr : sequence);
    EXPECT_EQ(observer.last_repetition_ended_sequence(),
              is_cyclic ? sequence : nullptr);
    EXPECT_EQ(observer.last_detached_sequence(), sequence);

    animator->RemoveObserver(&observer);
  }
}

}  // namespace ui
