Chromium Code Reviews| Index: ash/test/test_session_state_animator.cc |
| diff --git a/ash/test/test_session_state_animator.cc b/ash/test/test_session_state_animator.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e41dcdb995d32d4c422d8de95a27377f5f1100cf |
| --- /dev/null |
| +++ b/ash/test/test_session_state_animator.cc |
| @@ -0,0 +1,304 @@ |
| +// Copyright 2014 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 "ash/test/test_session_state_animator.h" |
| + |
| +#include <vector> |
| + |
| +#include "base/bind.h" |
| + |
| +namespace ash { |
| +namespace test { |
| + |
| +namespace { |
| +// A no-op callback that can be used when managing an animation that didn't |
| +// actually have a callback given. |
| +void DummyCallback() {} |
| +} |
| + |
| +const SessionStateAnimator::Container |
| + TestSessionStateAnimator::kAllContainers[] = { |
| + SessionStateAnimator::DESKTOP_BACKGROUND, |
| + SessionStateAnimator::LAUNCHER, |
| + SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, |
| + SessionStateAnimator::LOCK_SCREEN_BACKGROUND, |
| + SessionStateAnimator::LOCK_SCREEN_CONTAINERS, |
| + SessionStateAnimator::LOCK_SCREEN_RELATED_CONTAINERS, |
| + SessionStateAnimator::ROOT_CONTAINER |
| + }; |
|
Daniel Erat
2014/09/12 15:50:14
nit: i'm not sure what the rules are here, but i t
bruthig
2014/09/12 16:01:52
Whoops, that's what I meant to do, not sure how I
|
| + |
| +// A simple SessionStateAnimator::AnimationSequence that tracks the number of |
| +// attached sequences. The callback will be invoked if all animations complete |
| +// successfully. |
| +class TestSessionStateAnimator::AnimationSequence |
| + : public SessionStateAnimator::AnimationSequence { |
| + public: |
| + AnimationSequence(base::Closure callback, TestSessionStateAnimator* animator) |
| + : SessionStateAnimator::AnimationSequence(callback), |
| + sequence_count_(0), |
| + sequence_aborted_(false), |
| + animator_(animator) { |
| + } |
| + |
| + virtual ~AnimationSequence() {} |
| + |
| + virtual void SequenceAttached() { |
| + ++sequence_count_; |
| + } |
| + |
| + // Notify the sequence that is has completed. |
| + virtual void SequenceFinished(bool successfully) { |
| + DCHECK_GT(sequence_count_, 0); |
| + --sequence_count_; |
| + sequence_aborted_ |= !successfully; |
| + if (sequence_count_ == 0) { |
| + if (sequence_aborted_) |
| + OnAnimationAborted(); |
| + else |
| + OnAnimationCompleted(); |
| + } |
| + } |
| + |
| + // ash::SessionStateAnimator::AnimationSequence: |
| + virtual void StartAnimation(int container_mask, |
| + AnimationType type, |
| + AnimationSpeed speed) OVERRIDE { |
| + animator_->StartAnimationInSequence(container_mask, type, speed, this); |
| + } |
| + |
| + private: |
| + // Tracks the number of contained animations. |
| + int sequence_count_; |
| + |
| + // True if the sequence was aborted. |
| + bool sequence_aborted_; |
| + |
| + // The TestSessionAnimator that created this. Not owned. |
| + TestSessionStateAnimator* animator_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(AnimationSequence); |
| +}; |
| + |
| +TestSessionStateAnimator::ActiveAnimation::ActiveAnimation( |
| + int animation_epoch, |
| + base::TimeDelta duration, |
| + SessionStateAnimator::Container container, |
| + AnimationType type, |
| + AnimationSpeed speed, |
| + base::Closure success_callback, |
| + base::Closure failed_callback) |
| + : animation_epoch(animation_epoch), |
| + remaining_duration(duration), |
| + container(container), |
| + type(type), |
| + speed(speed), |
| + success_callback(success_callback), |
| + failed_callback(failed_callback) { |
| +} |
| + |
| +TestSessionStateAnimator::ActiveAnimation::~ActiveAnimation() { |
| +} |
| + |
| +TestSessionStateAnimator::TestSessionStateAnimator() |
| + : last_animation_epoch_(0), |
| + is_background_hidden_(false) { |
| +} |
| + |
| +TestSessionStateAnimator::~TestSessionStateAnimator() { |
| + CompleteAllAnimations(false); |
| +} |
| + |
| +void TestSessionStateAnimator::ResetAnimationEpoch() { |
| + CompleteAllAnimations(false); |
| + last_animation_epoch_ = 0; |
| +} |
| + |
| +void TestSessionStateAnimator::Advance(const base::TimeDelta& duration) { |
| + for (ActiveAnimationsMap::iterator container_iter = |
| + active_animations_.begin(); |
| + container_iter != active_animations_.end(); |
| + ++container_iter) { |
| + AnimationList::iterator animation_iter = (*container_iter).second.begin(); |
| + while (animation_iter != (*container_iter).second.end()) { |
| + ActiveAnimation& active_animation = *animation_iter; |
| + active_animation.remaining_duration -= duration; |
| + if (active_animation.remaining_duration <= base::TimeDelta()) { |
| + active_animation.success_callback.Run(); |
| + animation_iter = (*container_iter).second.erase(animation_iter); |
| + } else { |
| + ++animation_iter; |
| + } |
| + } |
| + } |
| +} |
| + |
| +void TestSessionStateAnimator::CompleteAnimations(int animation_epoch, |
| + bool completed_successfully) { |
| + for (ActiveAnimationsMap::iterator container_iter = |
| + active_animations_.begin(); |
| + container_iter != active_animations_.end(); |
| + ++container_iter) { |
| + AnimationList::iterator animation_iter = (*container_iter).second.begin(); |
| + while (animation_iter != (*container_iter).second.end()) { |
| + ActiveAnimation active_animation = *animation_iter; |
| + if (active_animation.animation_epoch <= animation_epoch) { |
| + if (completed_successfully) |
| + active_animation.success_callback.Run(); |
| + else |
| + active_animation.failed_callback.Run(); |
| + animation_iter = (*container_iter).second.erase(animation_iter); |
| + } else { |
| + ++animation_iter; |
| + } |
| + } |
| + } |
| +} |
| + |
| +void TestSessionStateAnimator::CompleteAllAnimations( |
| + bool completed_successfully) { |
| + CompleteAnimations(last_animation_epoch_, completed_successfully); |
| +} |
| + |
| +bool TestSessionStateAnimator::IsContainerAnimated( |
| + SessionStateAnimator::Container container, |
| + SessionStateAnimator::AnimationType type) const { |
| + ActiveAnimationsMap::const_iterator container_iter = |
| + active_animations_.find(container); |
| + if (container_iter != active_animations_.end()) { |
| + for (AnimationList::const_iterator animation_iter = |
| + (*container_iter).second.begin(); |
| + animation_iter != (*container_iter).second.end(); |
| + ++animation_iter) { |
| + const ActiveAnimation& active_animation = *animation_iter; |
| + if (active_animation.type == type) |
| + return true; |
| + } |
| + } |
| + return false; |
| +} |
| + |
| +bool TestSessionStateAnimator::AreContainersAnimated( |
| + int container_mask, SessionStateAnimator::AnimationType type) const { |
| + for (size_t i = 0; i < arraysize(kAllContainers); ++i) { |
| + if (container_mask & kAllContainers[i] && |
| + !IsContainerAnimated(kAllContainers[i], type)) { |
| + return false; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +size_t TestSessionStateAnimator::GetAnimationCount() const { |
| + size_t count = 0; |
| + for (ActiveAnimationsMap::const_iterator container_iter = |
| + active_animations_.begin(); |
| + container_iter != active_animations_.end(); |
| + ++container_iter) { |
| + count += (*container_iter).second.size(); |
| + } |
| + return count; |
| +} |
| + |
| +void TestSessionStateAnimator::StartAnimation(int container_mask, |
| + AnimationType type, |
| + AnimationSpeed speed) { |
| + ++last_animation_epoch_; |
| + for (size_t i = 0; i < arraysize(kAllContainers); ++i) { |
| + if (container_mask & kAllContainers[i]) { |
| + // Use a dummy no-op callback because one isn't required by the client |
| + // but one is required when completing or aborting animations. |
| + base::Closure callback = base::Bind(&DummyCallback); |
| + AddAnimation(kAllContainers[i], type, speed, callback, callback); |
| + } |
| + } |
| +} |
| + |
| +void TestSessionStateAnimator::StartAnimationWithCallback( |
| + int container_mask, |
| + AnimationType type, |
| + AnimationSpeed speed, |
| + base::Closure callback) { |
| + ++last_animation_epoch_; |
| + for (size_t i = 0; i < arraysize(kAllContainers); ++i) |
| + if (container_mask & kAllContainers[i]) { |
| + // ash::SessionStateAnimatorImpl invokes the callback whether or not the |
| + // animation was completed successfully or not. |
| + AddAnimation(kAllContainers[i], type, speed, callback, callback); |
| + } |
| +} |
| + |
| +ash::SessionStateAnimator::AnimationSequence* |
| + TestSessionStateAnimator::BeginAnimationSequence(base::Closure callback) { |
| + return new AnimationSequence(callback, this); |
| +} |
| + |
| +bool TestSessionStateAnimator::IsBackgroundHidden() const { |
| + return is_background_hidden_; |
| +} |
| + |
| +void TestSessionStateAnimator::ShowBackground() { |
| + is_background_hidden_ = false; |
| +} |
| + |
| +void TestSessionStateAnimator::HideBackground() { |
| + is_background_hidden_ = true; |
| +} |
| + |
| +void TestSessionStateAnimator::StartAnimationInSequence( |
| + int container_mask, |
| + AnimationType type, |
| + AnimationSpeed speed, |
| + AnimationSequence* animation_sequence) { |
| + ++last_animation_epoch_; |
| + for (size_t i = 0; i < arraysize(kAllContainers); ++i) { |
| + if (container_mask & kAllContainers[i]) { |
| + base::Closure success_callback = |
| + base::Bind(&AnimationSequence::SequenceFinished, |
| + base::Unretained(animation_sequence), true); |
| + base::Closure failed_callback = |
| + base::Bind(&AnimationSequence::SequenceFinished, |
| + base::Unretained(animation_sequence), false); |
| + animation_sequence->SequenceAttached(); |
| + AddAnimation(kAllContainers[i], type, speed, success_callback, |
| + failed_callback); |
| + } |
| + } |
| +} |
| + |
| +void TestSessionStateAnimator::AddAnimation( |
| + SessionStateAnimator::Container container, |
| + AnimationType type, |
| + AnimationSpeed speed, |
| + base::Closure success_callback, |
| + base::Closure failed_callback) { |
| + base::TimeDelta duration = GetDuration(speed); |
| + ActiveAnimation active_animation(last_animation_epoch_, |
| + duration, |
| + container, |
| + type, |
| + speed, |
| + success_callback, |
| + failed_callback); |
| + // This test double is limited to only have one animation active for a given |
| + // container at a time. |
| + AbortAnimation(container); |
| + active_animations_[container].push_back(active_animation); |
| +} |
| + |
| +void TestSessionStateAnimator::AbortAnimation( |
| + SessionStateAnimator::Container container) { |
| + ActiveAnimationsMap::iterator container_iter = |
| + active_animations_.find(container); |
| + if (container_iter != active_animations_.end()) { |
| + AnimationList::iterator animation_iter = (*container_iter).second.begin(); |
| + while (animation_iter != (*container_iter).second.end()) { |
| + ActiveAnimation active_animation = *animation_iter; |
| + active_animation.failed_callback.Run(); |
| + animation_iter = (*container_iter).second.erase(animation_iter); |
| + } |
| + } |
| +} |
| + |
| +} // namespace test |
| +} // namespace ash |