OLD | NEW |
| (Empty) |
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 "sky/engine/config.h" | |
32 #include "sky/engine/core/animation/AnimationTimeline.h" | |
33 | |
34 #include "sky/engine/core/animation/Animation.h" | |
35 #include "sky/engine/core/animation/AnimationClock.h" | |
36 #include "sky/engine/core/animation/AnimationNode.h" | |
37 #include "sky/engine/core/animation/KeyframeEffectModel.h" | |
38 #include "sky/engine/core/dom/Document.h" | |
39 #include "sky/engine/core/dom/Element.h" | |
40 #include "sky/engine/core/dom/QualifiedName.h" | |
41 #include "sky/engine/platform/weborigin/KURL.h" | |
42 | |
43 #include <gmock/gmock.h> | |
44 #include <gtest/gtest.h> | |
45 | |
46 namespace blink { | |
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 (expectNoMoreAction
s) | |
58 * - cancel the timer and request to be woken on the next frame (expectNext
FrameAction) | |
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 AnimationAnimationTimelineTest : public ::testing::Test { | |
83 protected: | |
84 virtual void SetUp() | |
85 { | |
86 document = Document::create(); | |
87 document->animationClock().resetTimeForTesting(); | |
88 element = Element::create(nullName, document.get()); | |
89 platformTiming = new MockPlatformTiming; | |
90 timeline = AnimationTimeline::create(document.get(), adoptPtr(platformTi
ming)); | |
91 ASSERT_EQ(0, timeline->currentTimeInternal()); | |
92 } | |
93 | |
94 virtual void TearDown() | |
95 { | |
96 document.release(); | |
97 element.release(); | |
98 timeline.release(); | |
99 } | |
100 | |
101 void updateClockAndService(double time) | |
102 { | |
103 document->animationClock().updateTime(time); | |
104 document->compositorPendingAnimations().update(false); | |
105 timeline->serviceAnimations(TimingUpdateForAnimationFrame); | |
106 } | |
107 | |
108 RefPtr<Document> document; | |
109 RefPtr<Element> element; | |
110 RefPtr<AnimationTimeline> timeline; | |
111 Timing timing; | |
112 MockPlatformTiming* platformTiming; | |
113 | |
114 void wake() | |
115 { | |
116 timeline->wake(); | |
117 } | |
118 | |
119 double minimumDelay() | |
120 { | |
121 return AnimationTimeline::s_minimumDelay; | |
122 } | |
123 }; | |
124 | |
125 TEST_F(AnimationAnimationTimelineTest, HasStarted) | |
126 { | |
127 timeline = AnimationTimeline::create(document.get()); | |
128 } | |
129 | |
130 TEST_F(AnimationAnimationTimelineTest, EmptyKeyframeAnimation) | |
131 { | |
132 RefPtr<AnimatableValueKeyframeEffectModel> effect = AnimatableValueKeyframeE
ffectModel::create(AnimatableValueKeyframeVector()); | |
133 RefPtr<Animation> anim = Animation::create(element.get(), effect, timing); | |
134 | |
135 timeline->play(anim.get()); | |
136 | |
137 platformTiming->expectNoMoreActions(); | |
138 updateClockAndService(0); | |
139 EXPECT_FLOAT_EQ(0, timeline->currentTimeInternal()); | |
140 EXPECT_FALSE(anim->isInEffect()); | |
141 | |
142 platformTiming->expectNoMoreActions(); | |
143 updateClockAndService(100); | |
144 EXPECT_FLOAT_EQ(100, timeline->currentTimeInternal()); | |
145 } | |
146 | |
147 TEST_F(AnimationAnimationTimelineTest, EmptyForwardsKeyframeAnimation) | |
148 { | |
149 RefPtr<AnimatableValueKeyframeEffectModel> effect = AnimatableValueKeyframeE
ffectModel::create(AnimatableValueKeyframeVector()); | |
150 timing.fillMode = Timing::FillModeForwards; | |
151 RefPtr<Animation> anim = Animation::create(element.get(), effect, timing); | |
152 | |
153 timeline->play(anim.get()); | |
154 | |
155 platformTiming->expectNoMoreActions(); | |
156 updateClockAndService(0); | |
157 EXPECT_FLOAT_EQ(0, timeline->currentTimeInternal()); | |
158 EXPECT_TRUE(anim->isInEffect()); | |
159 | |
160 platformTiming->expectNoMoreActions(); | |
161 updateClockAndService(100); | |
162 EXPECT_FLOAT_EQ(100, timeline->currentTimeInternal()); | |
163 } | |
164 | |
165 TEST_F(AnimationAnimationTimelineTest, ZeroTime) | |
166 { | |
167 timeline = AnimationTimeline::create(document.get()); | |
168 bool isNull; | |
169 | |
170 document->animationClock().updateTime(100); | |
171 EXPECT_EQ(100, timeline->currentTimeInternal()); | |
172 EXPECT_EQ(100, timeline->currentTimeInternal(isNull)); | |
173 EXPECT_FALSE(isNull); | |
174 | |
175 document->animationClock().updateTime(200); | |
176 EXPECT_EQ(200, timeline->currentTimeInternal()); | |
177 EXPECT_EQ(200, timeline->currentTimeInternal(isNull)); | |
178 EXPECT_FALSE(isNull); | |
179 } | |
180 | |
181 TEST_F(AnimationAnimationTimelineTest, PauseForTesting) | |
182 { | |
183 float seekTime = 1; | |
184 timing.fillMode = Timing::FillModeForwards; | |
185 RefPtr<Animation> anim1 = Animation::create(element.get(), AnimatableValueKe
yframeEffectModel::create(AnimatableValueKeyframeVector()), timing); | |
186 RefPtr<Animation> anim2 = Animation::create(element.get(), AnimatableValueK
eyframeEffectModel::create(AnimatableValueKeyframeVector()), timing); | |
187 AnimationPlayer* player1 = timeline->play(anim1.get()); | |
188 AnimationPlayer* player2 = timeline->play(anim2.get()); | |
189 timeline->pauseAnimationsForTesting(seekTime); | |
190 | |
191 EXPECT_FLOAT_EQ(seekTime, player1->currentTimeInternal()); | |
192 EXPECT_FLOAT_EQ(seekTime, player2->currentTimeInternal()); | |
193 } | |
194 | |
195 TEST_F(AnimationAnimationTimelineTest, DelayBeforeAnimationStart) | |
196 { | |
197 timing.iterationDuration = 2; | |
198 timing.startDelay = 5; | |
199 | |
200 RefPtr<Animation> anim = Animation::create(element.get(), nullptr, timing); | |
201 | |
202 timeline->play(anim.get()); | |
203 | |
204 // TODO: Put the player startTime in the future when we add the capability t
o change player startTime | |
205 platformTiming->expectDelayedAction(timing.startDelay - minimumDelay()); | |
206 updateClockAndService(0); | |
207 | |
208 platformTiming->expectDelayedAction(timing.startDelay - minimumDelay() - 1.5
); | |
209 updateClockAndService(1.5); | |
210 | |
211 EXPECT_CALL(*platformTiming, serviceOnNextFrame()); | |
212 wake(); | |
213 | |
214 platformTiming->expectNextFrameAction(); | |
215 updateClockAndService(4.98); | |
216 } | |
217 | |
218 TEST_F(AnimationAnimationTimelineTest, PlayAfterDocumentDeref) | |
219 { | |
220 timing.iterationDuration = 2; | |
221 timing.startDelay = 5; | |
222 | |
223 timeline = &document->timeline(); | |
224 element = nullptr; | |
225 document = nullptr; | |
226 | |
227 RefPtr<Animation> anim = Animation::create(0, nullptr, timing); | |
228 // Test passes if this does not crash. | |
229 timeline->play(anim.get()); | |
230 } | |
231 | |
232 TEST_F(AnimationAnimationTimelineTest, UseAnimationPlayerAfterTimelineDeref) | |
233 { | |
234 RefPtr<AnimationPlayer> player = timeline->createAnimationPlayer(0); | |
235 timeline.clear(); | |
236 // Test passes if this does not crash. | |
237 player->setStartTime(0); | |
238 } | |
239 | |
240 } | |
OLD | NEW |