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

#include "ui/compositor/layer_animator.h"

#include <memory>
#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.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_sequence.h"
#include "ui/compositor/layer_animator_collection.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/compositor/test/context_factories_for_test.h"
#include "ui/compositor/test/layer_animator_test_controller.h"
#include "ui/compositor/test/test_compositor_host.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/transform.h"

namespace ui {

namespace {

// Converts |color| to a string. Each component of the color is separated by a
// space and the order if A R G B.
std::string ColorToString(SkColor color) {
  return base::StringPrintf("%d %d %d %d", SkColorGetA(color),
                            SkColorGetR(color), SkColorGetG(color),
                            SkColorGetB(color));
}

// 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.
LayerAnimator* CreateDefaultTestAnimator(LayerAnimationDelegate* delegate,
                                         LayerAnimationObserver* observer) {
  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.
LayerAnimator* CreateDefaultTestAnimator(LayerAnimationDelegate* delegate) {
  return CreateDefaultTestAnimator(delegate, nullptr);
}

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

// Creates an implicit animator with timers disabled for test. |delegate| and
// |observer| are attached if non-null.
LayerAnimator* CreateImplicitTestAnimator(LayerAnimationDelegate* delegate,
                                          LayerAnimationObserver* observer) {
  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.
LayerAnimator* CreateImplicitTestAnimator(LayerAnimationDelegate* delegate) {
  return CreateImplicitTestAnimator(delegate, nullptr);
}

// Creates an implicit animator with timers disabled for test.
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) {
  }

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

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

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

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

  bool RequiresNotificationWhenAnimatorDestroyed() const override {
    return notify_when_animator_destructed_;
  }

  bool animations_completed_;
  bool notify_when_animator_destructed_;

  DISALLOW_COPY_AND_ASSIGN(TestImplicitAnimationObserver);
};

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

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

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

  void OnLayerAnimationScheduled(LayerAnimationSequence* sequence) override {}

 private:
  LayerAnimator* animator_;

  DISALLOW_COPY_AND_ASSIGN(DeletingLayerAnimationObserver);
};

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

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

  void OnLayerAnimationEnded(LayerAnimationSequence* sequence) override {}

  void OnLayerAnimationAborted(LayerAnimationSequence* sequence) override {}

  void OnLayerAnimationScheduled(LayerAnimationSequence* sequence) override {}

 private:
  LayerAnimator* animator_;

  DISALLOW_COPY_AND_ASSIGN(AbortAnimationsOnStartedLayerAnimationObserver);
};

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

  void NotifyAnimatorDeleted() {
    animator_deleted_ = true;
  }

  bool IsAnimatorDeleted() {
    return animator_deleted_;
  }

 private:
  bool animator_deleted_;

  DISALLOW_COPY_AND_ASSIGN(LayerAnimatorDestructionObserver);
};

class TestLayerAnimator : public LayerAnimator {
 public:
  TestLayerAnimator() : LayerAnimator(base::TimeDelta::FromSeconds(0)),
      destruction_observer_(NULL) {}

  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:
  LayerAnimatorDestructionObserver* destruction_observer_;

  DISALLOW_COPY_AND_ASSIGN(TestLayerAnimator);
};

// 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() override { (*num_live_instances_)--; }

 private:
  int* num_live_instances_;

  DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationSequence);
};

}  // 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) {}

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

  DISALLOW_COPY_AND_ASSIGN(CountCheckingLayerAnimationObserver);
};

}  // 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::TimeDelta::FromSeconds(1));
  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), 0.5);
}

// 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);
}

// 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);
  delegate.SetBoundsFromAnimation(initial_bounds);
  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::TimeDelta::FromSeconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromMilliseconds(500));

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

  animator->Step(start_time + base::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetOpacityFromAnimation(start_opacity);

  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::TimeDelta::FromSeconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness);
  delegate.SetBoundsFromAnimation(start_bounds);

  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::TimeDelta::FromMilliseconds(500));

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

  animator->Step(start_time + base::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetOpacityFromAnimation(start_opacity);
  delegate.SetBoundsFromAnimation(start_bounds);

  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::TimeDelta::FromSeconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromMilliseconds(500));

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

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

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

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

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

  animator->Step(start_time + base::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale);
  delegate.SetBoundsFromAnimation(start_bounds);

  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::TimeDelta::FromMilliseconds(500));

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

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

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

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

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

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

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

  animator->Step(start_time + base::TimeDelta::FromMilliseconds(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, middle_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::TimeDelta::FromSeconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale);
  delegate.SetBoundsFromAnimation(start_bounds);

  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::TimeDelta::FromMilliseconds(1000));

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

  animator->Step(start_time + base::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromMilliseconds(500));

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

  animator->Step(start_time + base::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetOpacityFromAnimation(start_opacity);

  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::TimeDelta::FromSeconds(1);

  delegate.SetOpacityFromAnimation(start_opacity);

  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::TimeDelta::FromSeconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(1000));

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

  animator->Step(start_time + base::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetOpacityFromAnimation(start_opacity);

  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::TimeDelta::FromSeconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(1000));

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

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

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

  animator->Step(start_time + base::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(1000));

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

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

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

  animator->Step(start_time + base::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale);
  delegate.SetBrightnessFromAnimation(start_brightness);

  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_GT(60.0, delta.InSecondsF());
}

//-------------------------------------------------------
// 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::TimeDelta::FromSeconds(1);

  delegate.SetOpacityFromAnimation(start_opacity);
  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromSeconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale);
  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetOpacityFromAnimation(start_opacity);
  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromSeconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale);
  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetGrayscaleFromAnimation(start_grayscale);
  delegate.SetBrightnessFromAnimation(start_brightness);

  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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(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::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetBrightnessFromAnimation(start_brightness);

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

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

  sequence->set_is_cyclic(true);

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

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

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

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

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

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

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

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

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

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

  // Skip ahead by a lot.
  animator->Step(start_time + base::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);

  delegate.SetOpacityFromAnimation(start_opacity);

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

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

  sequence->set_is_cyclic(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::TimeDelta::FromSeconds(1);

  delegate.SetBrightnessFromAnimation(0.0f);

  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::TimeDelta::FromMilliseconds(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 = NULL;

  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::TimeDelta::FromMilliseconds(1000));
  EXPECT_TRUE(observer.animations_completed());
  EXPECT_TRUE(observer.WasAnimationCompletedForProperty(
      LayerAnimationElement::BRIGHTNESS));
  EXPECT_FLOAT_EQ(0.0f, delegate.GetBrightnessForAnimation());
}

// 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::TimeDelta::FromSeconds(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 = NULL;
  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::TimeDelta::FromSeconds(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::TimeDelta::FromMilliseconds(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);

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

  animator->StartAnimation(sequence);

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

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

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

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

  TestImplicitAnimationObserver observer(false);

  delegate.SetBrightnessFromAnimation(0.0f);

  {
    ScopedLayerAnimationSettings setter(animator.get());

    base::TimeDelta delta = base::TimeDelta::FromSeconds(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::TimeDelta::FromMilliseconds(500));

    setter.AddObserver(&observer);

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

    animator->Step(start_time + base::TimeDelta::FromMilliseconds(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);
  base::TimeDelta delta = base::TimeDelta::FromSeconds(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::TimeDelta::FromMilliseconds(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);
  delegate.SetBoundsFromAnimation(start_bounds);

  base::TimeDelta brightness_delta = base::TimeDelta::FromSeconds(1);
  base::TimeDelta halfway_delta = base::TimeDelta::FromSeconds(2);
  base::TimeDelta bounds_delta = base::TimeDelta::FromSeconds(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) override {
      TestLayerAnimationDelegate::SetBoundsFromAnimation(bounds);
      if (bounds.width() > max_width_)
        animator_->StopAnimating();
    }
   private:
    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);

  base::TimeDelta bounds_delta1 = base::TimeDelta::FromMilliseconds(333);
  base::TimeDelta bounds_delta2 = base::TimeDelta::FromMilliseconds(666);
  base::TimeDelta bounds_delta = base::TimeDelta::FromMilliseconds(1000);
  base::TimeDelta final_delta = base::TimeDelta::FromMilliseconds(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::TimeDelta::FromSeconds(1);
  base::TimeDelta bounds_delta = base::TimeDelta::FromSeconds(2);

  delegate.SetBrightnessFromAnimation(start_brightness);
  delegate.SetBoundsFromAnimation(start_bounds);

  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::TimeDelta::FromSeconds(1);

  delegate.SetOpacityFromAnimation(start_opacity);

  std::unique_ptr<LayerAnimationSequence> sequence =
      base::MakeUnique<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);

  {
    // 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::TimeDelta::FromSeconds(1);
  std::unique_ptr<TestLayerAnimationSequence> sequence =
      base::MakeUnique<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);

  {
    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);

  {
    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);

  {
    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));

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

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

  delegate.SetColorFromAnimation(start_color);

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

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

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

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

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

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

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

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


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

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

 private:
  scoped_refptr<LayerAnimator> animator_;

  DISALLOW_COPY_AND_ASSIGN(AnimatorOwner);
};

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() 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_;
  bool* was_deleted_;

  DISALLOW_COPY_AND_ASSIGN(DeletingObserver);
};

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);

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

  delegate.SetBoundsFromAnimation(start_bounds);

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

  delta = base::TimeDelta::FromSeconds(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::TimeDelta::FromMilliseconds(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);

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

  delegate.SetBoundsFromAnimation(start_bounds);

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

  delta = base::TimeDelta::FromSeconds(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);

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

  delegate.SetBoundsFromAnimation(start_bounds);

  std::vector<LayerAnimationSequence*> to_start;

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

  delta = base::TimeDelta::FromSeconds(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);

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

  delegate.SetBoundsFromAnimation(start_bounds);

  std::vector<LayerAnimationSequence*> to_start;

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

  delta = base::TimeDelta::FromSeconds(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);

  ScopedLayerAnimationSettings settings(animator.get());
  settings.SetPreemptionStrategy(
      LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
  settings.SetTransitionDuration(base::TimeDelta::FromSeconds(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::TimeDelta::FromSeconds(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::TimeDelta::FromSeconds(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::TimeDelta::FromSeconds(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) {
  bool enable_pixel_output = false;
  ui::ContextFactory* context_factory = nullptr;
  ui::ContextFactoryPrivate* context_factory_private = nullptr;
  InitializeContextFactoryForTests(enable_pixel_output, &context_factory,
                                   &context_factory_private);
  const gfx::Rect bounds(10, 10, 100, 100);
  std::unique_ptr<TestCompositorHost> host_1(TestCompositorHost::Create(
      bounds, context_factory, context_factory_private));
  std::unique_ptr<TestCompositorHost> host_2(TestCompositorHost::Create(
      bounds, context_factory, context_factory_private));
  host_1->Show();
  host_2->Show();

  Compositor* compositor_1 = host_1->GetCompositor();
  Layer root_1;
  compositor_1->SetRootLayer(&root_1);

  Compositor* compositor_2 = host_2->GetCompositor();
  Layer root_2;
  compositor_2->SetRootLayer(&root_2);

  // 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;
  root_1.Add(&layer);
  LayerAnimator* animator = layer.GetAnimator();
  EXPECT_FALSE(layer.cc_layer_for_testing()->HasTickingAnimationForTesting());

  double target_opacity = 1.0;
  base::TimeDelta time_delta = base::TimeDelta::FromSeconds(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(layer.cc_layer_for_testing()->HasTickingAnimationForTesting());

  root_2.Add(&layer);
  EXPECT_FALSE(compositor_1->layer_animator_collection()->HasActiveAnimators());
  EXPECT_TRUE(compositor_2->layer_animator_collection()->HasActiveAnimators());
  EXPECT_TRUE(layer.cc_layer_for_testing()->HasTickingAnimationForTesting());

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

TEST(LayerAnimatorTest, ThreadedAnimationSurvivesIfLayerRemovedAdded) {
  bool enable_pixel_output = false;
  ui::ContextFactory* context_factory = nullptr;
  ui::ContextFactoryPrivate* context_factory_private = nullptr;
  InitializeContextFactoryForTests(enable_pixel_output, &context_factory,
                                   &context_factory_private);
  const gfx::Rect bounds(10, 10, 100, 100);
  std::unique_ptr<TestCompositorHost> host(TestCompositorHost::Create(
      bounds, context_factory, context_factory_private));
  host->Show();

  Compositor* compositor = host->GetCompositor();

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

  Layer layer;
  root.Add(&layer);

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

  animator->ScheduleAnimation(new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta)));
  EXPECT_TRUE(layer.cc_layer_for_testing()->HasTickingAnimationForTesting());

  root.Remove(&layer);
  EXPECT_FALSE(layer.cc_layer_for_testing()->HasTickingAnimationForTesting());

  root.Add(&layer);
  EXPECT_TRUE(layer.cc_layer_for_testing()->HasTickingAnimationForTesting());

  host.reset();
  TerminateContextFactoryForTests();
}

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

  ~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_;

  DISALLOW_COPY_AND_ASSIGN(LayerOwnerAnimationObserver);
};

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);
  delegate->SetBoundsFromAnimation(start_bounds);

  base::TimeDelta time_delta = base::TimeDelta::FromSeconds(1);
  LayerAnimationSequence* opacity = new LayerAnimationSequence(
      LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta));
  opacity->AddObserver(&observer);
  animator->ScheduleAnimation(opacity);
  time_delta = base::TimeDelta::FromSeconds(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::TimeDelta::FromMilliseconds(500));
  animator->StopAnimating();

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

// Verifies the LayerAnimatorObserver notification order for an animation
// sequence that completes successfully.
TEST(LayerAnimatorObserverNotificationOrderTest,
     SuccessfulCompletionOfSequence) {
  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::TimeDelta::FromSeconds(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_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(), sequence);
  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::TimeDelta::FromSeconds(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_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_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) {
  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::TimeDelta::FromSeconds(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_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_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(), first_sequence);
  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::TimeDelta::FromSeconds(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_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_detached_sequence(), first_sequence);

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

}  // namespace ui
