dbb4bff98418dab7819a2b7877128abd84a9abf5
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / animation / DocumentTimelineTest.cpp
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/DocumentTimeline.h"
33
34 #include "core/animation/Animation.h"
35 #include "core/animation/AnimationClock.h"
36 #include "core/animation/KeyframeEffectModel.h"
37 #include "core/animation/TimedItem.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 DocumentTimeline::PlatformTiming {
49 public:
50
51     MOCK_METHOD1(wakeAfter, void(double));
52     MOCK_METHOD0(cancelWake, void());
53     MOCK_METHOD0(serviceOnNextFrame, void());
54
55     /**
56      * DocumentTimelines 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
82 class AnimationDocumentTimelineTest : public ::testing::Test {
83 protected:
84     virtual void SetUp()
85     {
86         document = Document::create();
87         document->animationClock().resetTimeForTesting();
88         element = Element::create(nullQName() , document.get());
89         platformTiming = new MockPlatformTiming;
90         timeline = DocumentTimeline::create(document.get(), adoptPtr(platformTiming));
91         timeline->setZeroTime(0);
92         ASSERT_EQ(0, timeline->currentTime());
93     }
94
95     virtual void TearDown()
96     {
97         timeline.release();
98         document.release();
99         element.release();
100     }
101
102     void updateClockAndService(double time)
103     {
104         document->animationClock().updateTime(time);
105         timeline->serviceAnimations();
106     }
107
108     RefPtr<Document> document;
109     RefPtr<Element> element;
110     RefPtr<DocumentTimeline> timeline;
111     Timing timing;
112     MockPlatformTiming* platformTiming;
113
114     void wake()
115     {
116         timeline->wake();
117     }
118
119     double minimumDelay()
120     {
121         return DocumentTimeline::s_minimumDelay;
122     }
123 };
124
125 TEST_F(AnimationDocumentTimelineTest, HasStarted)
126 {
127     timeline = DocumentTimeline::create(document.get());
128     EXPECT_FALSE(timeline->hasStarted());
129     timeline->setZeroTime(0);
130     EXPECT_TRUE(timeline->hasStarted());
131 }
132
133 TEST_F(AnimationDocumentTimelineTest, EmptyKeyframeAnimation)
134 {
135     RefPtr<KeyframeEffectModel> effect = KeyframeEffectModel::create(KeyframeEffectModel::KeyframeVector());
136     RefPtr<Animation> anim = Animation::create(element.get(), effect, timing);
137
138     timeline->play(anim.get());
139
140     platformTiming->expectNoMoreActions();
141     updateClockAndService(0);
142     EXPECT_FLOAT_EQ(0, timeline->currentTime());
143     EXPECT_TRUE(anim->compositableValues()->isEmpty());
144
145     platformTiming->expectNoMoreActions();
146     updateClockAndService(100);
147     EXPECT_FLOAT_EQ(100, timeline->currentTime());
148 }
149
150 TEST_F(AnimationDocumentTimelineTest, EmptyTimelineDoesNotTriggerStyleRecalc)
151 {
152     document->animationClock().updateTime(100);
153     EXPECT_FALSE(timeline->serviceAnimations());
154 }
155
156 TEST_F(AnimationDocumentTimelineTest, EmptyPlayerDoesNotTriggerStyleRecalc)
157 {
158     timeline->play(0);
159     document->animationClock().updateTime(100);
160     EXPECT_FALSE(timeline->serviceAnimations());
161 }
162
163 TEST_F(AnimationDocumentTimelineTest, EmptyTargetDoesNotTriggerStyleRecalc)
164 {
165     timing.iterationDuration = 200;
166     timeline->play(Animation::create(0, KeyframeEffectModel::create(KeyframeEffectModel::KeyframeVector()), timing).get());
167     document->animationClock().updateTime(100);
168     EXPECT_FALSE(timeline->serviceAnimations());
169 }
170
171 TEST_F(AnimationDocumentTimelineTest, EmptyEffectDoesNotTriggerStyleRecalc)
172 {
173     timeline->play(Animation::create(element.get(), 0, timing).get());
174     document->animationClock().updateTime(100);
175     EXPECT_FALSE(timeline->serviceAnimations());
176 }
177
178 TEST_F(AnimationDocumentTimelineTest, TriggerStyleRecalc)
179 {
180     timeline->play(Animation::create(element.get(), KeyframeEffectModel::create(KeyframeEffectModel::KeyframeVector()), timing).get());
181     document->animationClock().updateTime(100);
182     EXPECT_TRUE(timeline->serviceAnimations());
183 }
184
185 TEST_F(AnimationDocumentTimelineTest, ZeroTime)
186 {
187     timeline = DocumentTimeline::create(document.get());
188
189     document->animationClock().updateTime(100);
190     EXPECT_TRUE(isNull(timeline->currentTime()));
191
192     document->animationClock().updateTime(200);
193     EXPECT_TRUE(isNull(timeline->currentTime()));
194
195     timeline->setZeroTime(300);
196     document->animationClock().updateTime(300);
197     EXPECT_EQ(0, timeline->currentTime());
198
199     document->animationClock().updateTime(400);
200     EXPECT_EQ(100, timeline->currentTime());
201 }
202
203 TEST_F(AnimationDocumentTimelineTest, PauseForTesting)
204 {
205     float seekTime = 1;
206     RefPtr<Animation> anim1 = Animation::create(element.get(), KeyframeEffectModel::create(KeyframeEffectModel::KeyframeVector()), timing);
207     RefPtr<Animation> anim2  = Animation::create(element.get(), KeyframeEffectModel::create(KeyframeEffectModel::KeyframeVector()), timing);
208     Player* player1 = timeline->play(anim1.get());
209     Player* player2 = timeline->play(anim2.get());
210     timeline->pauseAnimationsForTesting(seekTime);
211
212     EXPECT_FLOAT_EQ(seekTime, player1->currentTime());
213     EXPECT_FLOAT_EQ(seekTime, player2->currentTime());
214 }
215
216 TEST_F(AnimationDocumentTimelineTest, NumberOfActiveAnimations)
217 {
218     Timing timingForwardFill;
219     timingForwardFill.hasIterationDuration = true;
220     timingForwardFill.iterationDuration = 2;
221
222     Timing timingNoFill;
223     timingNoFill.hasIterationDuration = true;
224     timingNoFill.iterationDuration = 2;
225     timingNoFill.fillMode = Timing::FillModeNone;
226
227     Timing timingBackwardFillDelay;
228     timingBackwardFillDelay.hasIterationDuration = true;
229     timingBackwardFillDelay.iterationDuration = 1;
230     timingBackwardFillDelay.fillMode = Timing::FillModeBackwards;
231     timingBackwardFillDelay.startDelay = 1;
232
233     Timing timingNoFillDelay;
234     timingNoFillDelay.hasIterationDuration = true;
235     timingNoFillDelay.iterationDuration = 1;
236     timingNoFillDelay.fillMode = Timing::FillModeNone;
237     timingNoFillDelay.startDelay = 1;
238
239     RefPtr<Animation> anim1 = Animation::create(element.get(), KeyframeEffectModel::create(KeyframeEffectModel::KeyframeVector()), timingForwardFill);
240     RefPtr<Animation> anim2 = Animation::create(element.get(), KeyframeEffectModel::create(KeyframeEffectModel::KeyframeVector()), timingNoFill);
241     RefPtr<Animation> anim3 = Animation::create(element.get(), KeyframeEffectModel::create(KeyframeEffectModel::KeyframeVector()), timingBackwardFillDelay);
242     RefPtr<Animation> anim4 = Animation::create(element.get(), KeyframeEffectModel::create(KeyframeEffectModel::KeyframeVector()), timingNoFillDelay);
243
244     timeline->play(anim1.get());
245     timeline->play(anim2.get());
246     timeline->play(anim3.get());
247     timeline->play(anim4.get());
248
249     platformTiming->expectNextFrameAction();
250     updateClockAndService(0);
251     EXPECT_EQ(4U, timeline->numberOfActiveAnimationsForTesting());
252     platformTiming->expectNextFrameAction();
253     updateClockAndService(0.5);
254     EXPECT_EQ(4U, timeline->numberOfActiveAnimationsForTesting());
255     platformTiming->expectNextFrameAction();
256     updateClockAndService(1.5);
257     EXPECT_EQ(4U, timeline->numberOfActiveAnimationsForTesting());
258     platformTiming->expectNoMoreActions();
259     updateClockAndService(3);
260     EXPECT_EQ(1U, timeline->numberOfActiveAnimationsForTesting());
261 }
262
263 TEST_F(AnimationDocumentTimelineTest, DelayBeforeAnimationStart)
264 {
265     timing.hasIterationDuration = true;
266     timing.iterationDuration = 2;
267     timing.startDelay = 5;
268
269     RefPtr<Animation> anim = Animation::create(element.get(), 0, timing);
270
271     timeline->play(anim.get());
272
273     // TODO: Put the player startTime in the future when we add the capability to change player startTime
274     platformTiming->expectDelayedAction(timing.startDelay - minimumDelay());
275     updateClockAndService(0);
276
277     platformTiming->expectDelayedAction(timing.startDelay - minimumDelay() - 1.5);
278     updateClockAndService(1.5);
279
280     EXPECT_CALL(*platformTiming, serviceOnNextFrame());
281     wake();
282
283     platformTiming->expectNextFrameAction();
284     updateClockAndService(4.98);
285 }
286
287 }