diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp | |
parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
download | qtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz |
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp')
-rw-r--r-- | Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp | 519 |
1 files changed, 480 insertions, 39 deletions
diff --git a/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp b/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp index c4f103a3c..fa95a2ac5 100644 --- a/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp +++ b/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp @@ -56,7 +56,8 @@ PassOwnPtr<CCActiveAnimation> createActiveAnimation(PassOwnPtr<CCAnimationCurve> TEST(CCLayerAnimationControllerTest, createOpacityAnimation) { - OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy)); const double duration = 1; WebCore::KeyframeValueList values(AnimatedPropertyOpacity); values.insert(new FloatAnimationValue(0, 0)); @@ -85,9 +86,37 @@ TEST(CCLayerAnimationControllerTest, createOpacityAnimation) EXPECT_EQ(1, curve->getValue(duration)); } +TEST(CCLayerAnimationControllerTest, ignoreUnsupportedAnimationDirections) +{ + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy)); + const double duration = 1; + WebCore::KeyframeValueList values(AnimatedPropertyOpacity); + values.insert(new FloatAnimationValue(0, 0)); + values.insert(new FloatAnimationValue(duration, 1)); + + RefPtr<Animation> animation = Animation::create(); + animation->setDuration(duration); + + IntSize boxSize; + + animation->setDirection(Animation::AnimationDirectionAlternate); + EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0)); + + animation->setDirection(Animation::AnimationDirectionAlternateReverse); + EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0)); + + animation->setDirection(Animation::AnimationDirectionReverse); + EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0)); + + animation->setDirection(Animation::AnimationDirectionNormal); + EXPECT_TRUE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0)); +} + TEST(CCLayerAnimationControllerTest, createTransformAnimation) { - OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy)); const double duration = 1; WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); @@ -124,92 +153,504 @@ TEST(CCLayerAnimationControllerTest, createTransformAnimation) TEST(CCLayerAnimationControllerTest, syncNewAnimation) { - FakeLayerAnimationControllerImplClient dummy; - OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy)); - OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + FakeLayerAnimationControllerClient dummyImpl; + OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy)); EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); - addOpacityTransitionToController(*controller, 1, 0, 1); + addOpacityTransitionToController(*controller, 1, 0, 1, false); - controller->synchronizeAnimations(controllerImpl.get()); + controller->pushAnimationUpdatesTo(controllerImpl.get()); EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); } -TEST(CCLayerAnimationControllerTest, syncAnimationProperties) +// If an animation is started on the impl thread before it is ticked on the main +// thread, we must be sure to respect the synchronized start time. +TEST(CCLayerAnimationControllerTest, doNotClobberStartTimes) { - FakeLayerAnimationControllerImplClient dummy; - OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy)); - OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + FakeLayerAnimationControllerClient dummyImpl; + OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy)); EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); - addOpacityTransitionToController(*controller, 1, 0, 1); + addOpacityTransitionToController(*controller, 1, 0, 1, false); - controller->synchronizeAnimations(controllerImpl.get()); + controller->pushAnimationUpdatesTo(controllerImpl.get()); EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); - // Push an animation property change to the impl thread (should not cause an animation to be added). - controller->pauseAnimation(0, 0); - controller->synchronizeAnimations(controllerImpl.get()); + CCAnimationEventsVector events; + controllerImpl->animate(1, &events); - EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); - EXPECT_EQ(CCActiveAnimation::Paused, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); + // Synchronize the start times. + EXPECT_EQ(1u, events.size()); + controller->notifyAnimationStarted(events[0]); + EXPECT_EQ(controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime(), controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime()); + + // Start the animation on the main thread. Should not affect the start time. + controller->animate(1.5, 0); + EXPECT_EQ(controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime(), controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime()); } -TEST(CCLayerAnimationControllerTest, syncAbortedAnimation) +TEST(CCLayerAnimationControllerTest, syncPauseAndResume) { - FakeLayerAnimationControllerImplClient dummy; - OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy)); - OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + FakeLayerAnimationControllerClient dummyImpl; + OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy)); EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); - addOpacityTransitionToController(*controller, 1, 0, 1); + addOpacityTransitionToController(*controller, 1, 0, 1, false); - controller->synchronizeAnimations(controllerImpl.get()); + controller->pushAnimationUpdatesTo(controllerImpl.get()); EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); - controller->removeAnimation(0); + // Start the animations on each controller. + CCAnimationEventsVector events; + controllerImpl->animate(0, &events); + controller->animate(0, 0); + EXPECT_EQ(CCActiveAnimation::Running, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); + EXPECT_EQ(CCActiveAnimation::Running, controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); - // Abort an animation from the main thread. - controller->synchronizeAnimations(controllerImpl.get()); + // Pause the main-thread animation. + controller->suspendAnimations(1); + EXPECT_EQ(CCActiveAnimation::Paused, controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); - EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + // The pause run state change should make it to the impl thread controller. + controller->pushAnimationUpdatesTo(controllerImpl.get()); + EXPECT_EQ(CCActiveAnimation::Paused, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); + + // Resume the main-thread animation. + controller->resumeAnimations(2); + EXPECT_EQ(CCActiveAnimation::Running, controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); + + // The pause run state change should make it to the impl thread controller. + controller->pushAnimationUpdatesTo(controllerImpl.get()); + EXPECT_EQ(CCActiveAnimation::Running, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); } -TEST(CCLayerAnimationControllerTest, syncCompletedAnimation) + +TEST(CCLayerAnimationControllerTest, doNotSyncFinishedAnimation) { - FakeLayerAnimationControllerImplClient dummy; - OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy)); - OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + FakeLayerAnimationControllerClient dummyImpl; + OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy)); EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); - addOpacityTransitionToController(*controller, 1, 0, 1); + addOpacityTransitionToController(*controller, 1, 0, 1, false); - controller->synchronizeAnimations(controllerImpl.get()); + controller->pushAnimationUpdatesTo(controllerImpl.get()); EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); - // Step through the animation until it is finished. At the next sync, the main thread's animation should be cleared. - OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); - controllerImpl->animate(0, *events); - controllerImpl->animate(2, *events); + // Notify main thread controller that the animation has started. + CCAnimationEvent animationStartedEvent(CCAnimationEvent::Started, 0, 0, CCActiveAnimation::Opacity, 0); + controller->notifyAnimationStarted(animationStartedEvent); + + // Force animation to complete on impl thread. + controllerImpl->removeAnimation(0); EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + + controller->pushAnimationUpdatesTo(controllerImpl.get()); + + // Even though the main thread has a 'new' animation, it should not be pushed because the animation has already completed on the impl thread. + EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); +} + +// Tests that transitioning opacity from 0 to 1 works as expected. +TEST(CCLayerAnimationControllerTest, TrivialTransition) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + + controller->add(toAdd.release()); + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(1, events.get()); + EXPECT_EQ(1, dummy.opacity()); + EXPECT_FALSE(controller->hasActiveAnimation()); +} + +// Tests animations that are waiting for a synchronized start time do not finish. +TEST(CCLayerAnimationControllerTest, AnimationsWaitingForStartTimeDoNotFinishIfTheyWaitLongerToStartThanTheirDuration) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + toAdd->setNeedsSynchronizedStartTime(true); + + // We should pause at the first keyframe indefinitely waiting for that animation to start. + controller->add(toAdd.release()); + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(1, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(2, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + + // Send the synchronized start time. + controller->notifyAnimationStarted(CCAnimationEvent(CCAnimationEvent::Started, 0, 1, CCActiveAnimation::Opacity, 2)); + controller->animate(5, events.get()); + EXPECT_EQ(1, dummy.opacity()); + EXPECT_FALSE(controller->hasActiveAnimation()); +} + +// Tests that two queued animations affecting the same property run in sequence. +TEST(CCLayerAnimationControllerTest, TrivialQueuing) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity)); + + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(1, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(1, dummy.opacity()); + controller->animate(2, events.get()); + EXPECT_EQ(0.5, dummy.opacity()); + EXPECT_FALSE(controller->hasActiveAnimation()); +} + +// Tests interrupting a transition with another transition. +TEST(CCLayerAnimationControllerTest, Interrupt) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity)); + toAdd->setRunState(CCActiveAnimation::WaitingForNextTick, 0); + controller->add(toAdd.release()); + + // Since the animation was in the WaitingForNextTick state, it should start right in + // this call to animate. + controller->animate(0.5, events.get()); EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(1, dummy.opacity()); + controller->animate(1.5, events.get()); + EXPECT_EQ(0.5, dummy.opacity()); + EXPECT_FALSE(controller->hasActiveAnimation()); +} + +// Tests scheduling two animations to run together when only one property is free. +TEST(CCLayerAnimationControllerTest, ScheduleTogetherWhenAPropertyIsBlocked) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); - controller->synchronizeAnimations(controllerImpl.get()); + controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform)); + controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, CCActiveAnimation::Opacity)); + controller->animate(0, events.get()); + EXPECT_EQ(0, dummy.opacity()); + EXPECT_TRUE(controller->hasActiveAnimation()); + controller->animate(1, events.get()); + // Should not have started the float transition yet. + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + // The float animation should have started at time 1 and should be done. + controller->animate(2, events.get()); + EXPECT_EQ(1, dummy.opacity()); EXPECT_FALSE(controller->hasActiveAnimation()); } +// Tests scheduling two animations to run together with different lengths and another +// animation queued to start when the shorter animation finishes (should wait +// for both to finish). +TEST(CCLayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity)); + + // Animations with id 1 should both start now. + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + // The opacity animation should have finished at time 1, but the group + // of animations with id 1 don't finish until time 2 because of the length + // of the transform animation. + controller->animate(2, events.get()); + // Should not have started the float transition yet. + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(1, dummy.opacity()); + + // The second opacity animation should start at time 2 and should be done by time 3 + controller->animate(3, events.get()); + EXPECT_EQ(0.5, dummy.opacity()); + EXPECT_FALSE(controller->hasActiveAnimation()); +} + +// Tests scheduling an animation to start in the future. +TEST(CCLayerAnimationControllerTest, ScheduleAnimation) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0); + toAdd->setStartTime(1); + controller->add(toAdd.release()); + + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(1, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(2, events.get()); + EXPECT_EQ(1, dummy.opacity()); + EXPECT_FALSE(controller->hasActiveAnimation()); +} + +// Tests scheduling an animation to start in the future that's interrupting a running animation. +TEST(CCLayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimation) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity)); + + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0.5, 0)), 2, CCActiveAnimation::Opacity)); + toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0); + toAdd->setStartTime(1); + controller->add(toAdd.release()); + + // First 2s opacity transition should start immediately. + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(0.5, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.25, dummy.opacity()); + controller->animate(1, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.5, dummy.opacity()); + controller->animate(2, events.get()); + EXPECT_EQ(0, dummy.opacity()); + EXPECT_FALSE(controller->hasActiveAnimation()); +} + +// Tests scheduling an animation to start in the future that interrupts a running animation +// and there is yet another animation queued to start later. +TEST(CCLayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity)); + + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0.5, 0)), 2, CCActiveAnimation::Opacity)); + toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0); + toAdd->setStartTime(1); + controller->add(toAdd.release()); + + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 0.75)), 3, CCActiveAnimation::Opacity)); + + // First 2s opacity transition should start immediately. + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(0.5, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.25, dummy.opacity()); + EXPECT_TRUE(controller->hasActiveAnimation()); + controller->animate(1, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.5, dummy.opacity()); + controller->animate(3, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(4, events.get()); + EXPECT_EQ(0.75, dummy.opacity()); + EXPECT_FALSE(controller->hasActiveAnimation()); +} + +// Test that a looping animation loops and for the correct number of iterations. +TEST(CCLayerAnimationControllerTest, TrivialLooping) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + toAdd->setIterations(3); + controller->add(toAdd.release()); + + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(1.25, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.25, dummy.opacity()); + controller->animate(1.75, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.75, dummy.opacity()); + controller->animate(2.25, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.25, dummy.opacity()); + controller->animate(2.75, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.75, dummy.opacity()); + controller->animate(3, events.get()); + EXPECT_FALSE(controller->hasActiveAnimation()); + EXPECT_EQ(1, dummy.opacity()); + + // Just be extra sure. + controller->animate(4, events.get()); + EXPECT_EQ(1, dummy.opacity()); +} + +// Test that an infinitely looping animation does indeed go until aborted. +TEST(CCLayerAnimationControllerTest, InfiniteLooping) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + const int id = 1; + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity)); + toAdd->setIterations(-1); + controller->add(toAdd.release()); + + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(1.25, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.25, dummy.opacity()); + controller->animate(1.75, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.75, dummy.opacity()); + + controller->animate(1073741824.25, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.25, dummy.opacity()); + controller->animate(1073741824.75, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.75, dummy.opacity()); + + EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity)); + controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 0.75); + EXPECT_FALSE(controller->hasActiveAnimation()); + EXPECT_EQ(0.75, dummy.opacity()); +} + +// Test that pausing and resuming work as expected. +TEST(CCLayerAnimationControllerTest, PauseResume) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + const int id = 1; + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity)); + + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(0.5, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.5, dummy.opacity()); + + EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity)); + controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Paused, 0.5); + + controller->animate(1024, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.5, dummy.opacity()); + + EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity)); + controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Running, 1024); + + controller->animate(1024.25, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.75, dummy.opacity()); + controller->animate(1024.5, events.get()); + EXPECT_FALSE(controller->hasActiveAnimation()); + EXPECT_EQ(1, dummy.opacity()); +} + +TEST(CCLayerAnimationControllerTest, AbortAGroupedAnimation) +{ + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerClient dummy; + OwnPtr<CCLayerAnimationController> controller( + CCLayerAnimationController::create(&dummy)); + + const int id = 1; + controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.75)), 2, CCActiveAnimation::Opacity)); + + controller->animate(0, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0, dummy.opacity()); + controller->animate(1, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(0.5, dummy.opacity()); + + EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity)); + controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 1); + controller->animate(1, events.get()); + EXPECT_TRUE(controller->hasActiveAnimation()); + EXPECT_EQ(1, dummy.opacity()); + controller->animate(2, events.get()); + EXPECT_TRUE(!controller->hasActiveAnimation()); + EXPECT_EQ(0.75, dummy.opacity()); +} + } // namespace |