Home | History | Annotate | Download | only in animation
      1 /*
      2  * Copyright (c) 2013, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "core/animation/AnimationTimeline.h"
     33 
     34 #include "core/animation/Animation.h"
     35 #include "core/animation/AnimationClock.h"
     36 #include "core/animation/AnimationNode.h"
     37 #include "core/animation/KeyframeEffectModel.h"
     38 #include "core/dom/Document.h"
     39 #include "core/dom/Element.h"
     40 #include "core/dom/QualifiedName.h"
     41 #include "platform/weborigin/KURL.h"
     42 
     43 #include <gmock/gmock.h>
     44 #include <gtest/gtest.h>
     45 
     46 namespace WebCore {
     47 
     48 class MockPlatformTiming : public AnimationTimeline::PlatformTiming {
     49 public:
     50 
     51     MOCK_METHOD1(wakeAfter, void(double));
     52     MOCK_METHOD0(cancelWake, void());
     53     MOCK_METHOD0(serviceOnNextFrame, void());
     54 
     55     /**
     56      * AnimationTimelines should do one of the following things after servicing animations:
     57      *  - cancel the timer and not request to be woken again (expectNoMoreActions)
     58      *  - cancel the timer and request to be woken on the next frame (expectNextFrameAction)
     59      *  - cancel the timer and request to be woken at some point in the future (expectDelayedAction)
     60      */
     61 
     62     void expectNoMoreActions()
     63     {
     64         EXPECT_CALL(*this, cancelWake());
     65     }
     66 
     67     void expectNextFrameAction()
     68     {
     69         ::testing::Sequence sequence;
     70         EXPECT_CALL(*this, cancelWake()).InSequence(sequence);
     71         EXPECT_CALL(*this, serviceOnNextFrame()).InSequence(sequence);
     72     }
     73 
     74     void expectDelayedAction(double when)
     75     {
     76         ::testing::Sequence sequence;
     77         EXPECT_CALL(*this, cancelWake()).InSequence(sequence);
     78         EXPECT_CALL(*this, wakeAfter(when)).InSequence(sequence);
     79     }
     80 
     81     void trace(Visitor* visitor)
     82     {
     83         AnimationTimeline::PlatformTiming::trace(visitor);
     84     }
     85 };
     86 
     87 class AnimationAnimationTimelineTest : public ::testing::Test {
     88 protected:
     89     virtual void SetUp()
     90     {
     91         document = Document::create();
     92         document->animationClock().resetTimeForTesting();
     93         element = Element::create(QualifiedName::null() , document.get());
     94         platformTiming = new MockPlatformTiming;
     95         timeline = AnimationTimeline::create(document.get(), adoptPtrWillBeNoop(platformTiming));
     96         ASSERT_EQ(0, timeline->currentTimeInternal());
     97     }
     98 
     99     virtual void TearDown()
    100     {
    101         document.release();
    102         element.release();
    103         timeline.release();
    104     }
    105 
    106     void updateClockAndService(double time)
    107     {
    108         document->animationClock().updateTime(time);
    109         timeline->serviceAnimations(TimingUpdateForAnimationFrame);
    110     }
    111 
    112     RefPtrWillBePersistent<Document> document;
    113     RefPtrWillBePersistent<Element> element;
    114     RefPtrWillBePersistent<AnimationTimeline> timeline;
    115     Timing timing;
    116     MockPlatformTiming* platformTiming;
    117 
    118     void wake()
    119     {
    120         timeline->wake();
    121     }
    122 
    123     double minimumDelay()
    124     {
    125         return AnimationTimeline::s_minimumDelay;
    126     }
    127 };
    128 
    129 TEST_F(AnimationAnimationTimelineTest, HasStarted)
    130 {
    131     timeline = AnimationTimeline::create(document.get());
    132 }
    133 
    134 TEST_F(AnimationAnimationTimelineTest, EmptyKeyframeAnimation)
    135 {
    136     RefPtrWillBeRawPtr<AnimatableValueKeyframeEffectModel> effect = AnimatableValueKeyframeEffectModel::create(AnimatableValueKeyframeVector());
    137     RefPtrWillBeRawPtr<Animation> anim = Animation::create(element.get(), effect, timing);
    138 
    139     timeline->play(anim.get());
    140 
    141     platformTiming->expectNoMoreActions();
    142     updateClockAndService(0);
    143     EXPECT_FLOAT_EQ(0, timeline->currentTimeInternal());
    144     EXPECT_FALSE(anim->isInEffect());
    145 
    146     platformTiming->expectNoMoreActions();
    147     updateClockAndService(100);
    148     EXPECT_FLOAT_EQ(100, timeline->currentTimeInternal());
    149 }
    150 
    151 TEST_F(AnimationAnimationTimelineTest, EmptyForwardsKeyframeAnimation)
    152 {
    153     RefPtrWillBeRawPtr<AnimatableValueKeyframeEffectModel> effect = AnimatableValueKeyframeEffectModel::create(AnimatableValueKeyframeVector());
    154     timing.fillMode = Timing::FillModeForwards;
    155     RefPtrWillBeRawPtr<Animation> anim = Animation::create(element.get(), effect, timing);
    156 
    157     timeline->play(anim.get());
    158 
    159     platformTiming->expectNoMoreActions();
    160     updateClockAndService(0);
    161     EXPECT_FLOAT_EQ(0, timeline->currentTimeInternal());
    162     EXPECT_TRUE(anim->isInEffect());
    163 
    164     platformTiming->expectNoMoreActions();
    165     updateClockAndService(100);
    166     EXPECT_FLOAT_EQ(100, timeline->currentTimeInternal());
    167 }
    168 
    169 TEST_F(AnimationAnimationTimelineTest, ZeroTime)
    170 {
    171     timeline = AnimationTimeline::create(document.get());
    172     bool isNull;
    173 
    174     document->animationClock().updateTime(100);
    175     EXPECT_EQ(100, timeline->currentTimeInternal());
    176     EXPECT_EQ(100, timeline->currentTimeInternal(isNull));
    177     EXPECT_FALSE(isNull);
    178 
    179     document->animationClock().updateTime(200);
    180     EXPECT_EQ(200, timeline->currentTimeInternal());
    181     EXPECT_EQ(200, timeline->currentTimeInternal(isNull));
    182     EXPECT_FALSE(isNull);
    183 }
    184 
    185 TEST_F(AnimationAnimationTimelineTest, PauseForTesting)
    186 {
    187     float seekTime = 1;
    188     timing.fillMode = Timing::FillModeForwards;
    189     RefPtrWillBeRawPtr<Animation> anim1 = Animation::create(element.get(), AnimatableValueKeyframeEffectModel::create(AnimatableValueKeyframeVector()), timing);
    190     RefPtrWillBeRawPtr<Animation> anim2  = Animation::create(element.get(), AnimatableValueKeyframeEffectModel::create(AnimatableValueKeyframeVector()), timing);
    191     AnimationPlayer* player1 = timeline->play(anim1.get());
    192     AnimationPlayer* player2 = timeline->play(anim2.get());
    193     timeline->pauseAnimationsForTesting(seekTime);
    194 
    195     EXPECT_FLOAT_EQ(seekTime, player1->currentTimeInternal());
    196     EXPECT_FLOAT_EQ(seekTime, player2->currentTimeInternal());
    197 }
    198 
    199 TEST_F(AnimationAnimationTimelineTest, NumberOfActiveAnimations)
    200 {
    201     Timing timingForwardFill;
    202     timingForwardFill.iterationDuration = 2;
    203     timingForwardFill.fillMode = Timing::FillModeForwards;
    204 
    205     Timing timingNoFill;
    206     timingNoFill.iterationDuration = 2;
    207     timingNoFill.fillMode = Timing::FillModeNone;
    208 
    209     Timing timingBackwardFillDelay;
    210     timingBackwardFillDelay.iterationDuration = 1;
    211     timingBackwardFillDelay.fillMode = Timing::FillModeBackwards;
    212     timingBackwardFillDelay.startDelay = 1;
    213 
    214     Timing timingNoFillDelay;
    215     timingNoFillDelay.iterationDuration = 1;
    216     timingNoFillDelay.fillMode = Timing::FillModeNone;
    217     timingNoFillDelay.startDelay = 1;
    218 
    219     Timing timingAutoFill;
    220     timingAutoFill.iterationDuration = 2;
    221 
    222     RefPtrWillBeRawPtr<Animation> anim1 = Animation::create(element.get(), AnimatableValueKeyframeEffectModel::create(AnimatableValueKeyframeVector()), timingForwardFill);
    223     RefPtrWillBeRawPtr<Animation> anim2 = Animation::create(element.get(), AnimatableValueKeyframeEffectModel::create(AnimatableValueKeyframeVector()), timingNoFill);
    224     RefPtrWillBeRawPtr<Animation> anim3 = Animation::create(element.get(), AnimatableValueKeyframeEffectModel::create(AnimatableValueKeyframeVector()), timingBackwardFillDelay);
    225     RefPtrWillBeRawPtr<Animation> anim4 = Animation::create(element.get(), AnimatableValueKeyframeEffectModel::create(AnimatableValueKeyframeVector()), timingNoFillDelay);
    226     RefPtrWillBeRawPtr<Animation> anim5 = Animation::create(element.get(), AnimatableValueKeyframeEffectModel::create(AnimatableValueKeyframeVector()), timingAutoFill);
    227 
    228     timeline->play(anim1.get());
    229     timeline->play(anim2.get());
    230     timeline->play(anim3.get());
    231     timeline->play(anim4.get());
    232     timeline->play(anim5.get());
    233 
    234     platformTiming->expectNextFrameAction();
    235     updateClockAndService(0);
    236     EXPECT_EQ(5U, timeline->numberOfActiveAnimationsForTesting());
    237     platformTiming->expectNextFrameAction();
    238     updateClockAndService(0.5);
    239     EXPECT_EQ(5U, timeline->numberOfActiveAnimationsForTesting());
    240     platformTiming->expectNextFrameAction();
    241     updateClockAndService(1.5);
    242     EXPECT_EQ(5U, timeline->numberOfActiveAnimationsForTesting());
    243     platformTiming->expectNoMoreActions();
    244     updateClockAndService(3);
    245     EXPECT_EQ(0U, timeline->numberOfActiveAnimationsForTesting());
    246 }
    247 
    248 TEST_F(AnimationAnimationTimelineTest, DelayBeforeAnimationStart)
    249 {
    250     timing.iterationDuration = 2;
    251     timing.startDelay = 5;
    252 
    253     RefPtrWillBeRawPtr<Animation> anim = Animation::create(element.get(), nullptr, timing);
    254 
    255     timeline->play(anim.get());
    256 
    257     // TODO: Put the player startTime in the future when we add the capability to change player startTime
    258     platformTiming->expectDelayedAction(timing.startDelay - minimumDelay());
    259     updateClockAndService(0);
    260 
    261     platformTiming->expectDelayedAction(timing.startDelay - minimumDelay() - 1.5);
    262     updateClockAndService(1.5);
    263 
    264     EXPECT_CALL(*platformTiming, serviceOnNextFrame());
    265     wake();
    266 
    267     platformTiming->expectNextFrameAction();
    268     updateClockAndService(4.98);
    269 }
    270 
    271 TEST_F(AnimationAnimationTimelineTest, PlayAfterDocumentDeref)
    272 {
    273     timing.iterationDuration = 2;
    274     timing.startDelay = 5;
    275 
    276     timeline = &document->timeline();
    277     element = nullptr;
    278     document = nullptr;
    279 
    280     RefPtrWillBeRawPtr<Animation> anim = Animation::create(0, nullptr, timing);
    281     // Test passes if this does not crash.
    282     timeline->play(anim.get());
    283 }
    284 
    285 TEST_F(AnimationAnimationTimelineTest, UseAnimationPlayerAfterTimelineDeref)
    286 {
    287     RefPtrWillBeRawPtr<AnimationPlayer> player = timeline->createAnimationPlayer(0);
    288     timeline.clear();
    289     // Test passes if this does not crash.
    290     player->setStartTime(0);
    291 }
    292 
    293 }
    294