OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "services/view_manager/animation_runner.h" | |
6 | |
7 #include "base/strings/stringprintf.h" | |
8 #include "mojo/converters/geometry/geometry_type_converters.h" | |
9 #include "mojo/services/view_manager/interfaces/view_manager_constants.mojom.h" | |
10 #include "services/view_manager/animation_runner_observer.h" | |
11 #include "services/view_manager/scheduled_animation_group.h" | |
12 #include "services/view_manager/server_view.h" | |
13 #include "services/view_manager/test_server_view_delegate.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 using base::TimeDelta; | |
17 using mojo::AnimationElement; | |
18 using mojo::AnimationGroup; | |
19 using mojo::AnimationProperty; | |
20 using mojo::AnimationSequence; | |
21 using mojo::AnimationTweenType; | |
22 using mojo::AnimationValue; | |
23 using mojo::AnimationValuePtr; | |
24 using mojo::Transform; | |
25 | |
26 namespace view_manager { | |
27 namespace { | |
28 | |
29 class TestAnimationRunnerObserver : public AnimationRunnerObserver { | |
30 public: | |
31 TestAnimationRunnerObserver() {} | |
32 ~TestAnimationRunnerObserver() override {} | |
33 | |
34 std::vector<std::string>* changes() { return &changes_; } | |
35 std::vector<uint32_t>* change_ids() { return &change_ids_; } | |
36 | |
37 void clear_changes() { | |
38 changes_.clear(); | |
39 change_ids_.clear(); | |
40 } | |
41 | |
42 // AnimationRunnerDelgate: | |
43 void OnAnimationScheduled(uint32_t id) override { | |
44 change_ids_.push_back(id); | |
45 changes_.push_back("scheduled"); | |
46 } | |
47 void OnAnimationDone(uint32_t id) override { | |
48 change_ids_.push_back(id); | |
49 changes_.push_back("done"); | |
50 } | |
51 void OnAnimationInterrupted(uint32_t id) override { | |
52 change_ids_.push_back(id); | |
53 changes_.push_back("interrupted"); | |
54 } | |
55 void OnAnimationCanceled(uint32_t id) override { | |
56 change_ids_.push_back(id); | |
57 changes_.push_back("canceled"); | |
58 } | |
59 | |
60 private: | |
61 std::vector<uint32_t> change_ids_; | |
62 std::vector<std::string> changes_; | |
63 | |
64 DISALLOW_COPY_AND_ASSIGN(TestAnimationRunnerObserver); | |
65 }; | |
66 | |
67 // Creates an AnimationValuePtr from the specified float value. | |
68 AnimationValuePtr FloatAnimationValue(float float_value) { | |
69 AnimationValuePtr value(AnimationValue::New()); | |
70 value->float_value = float_value; | |
71 return value; | |
72 } | |
73 | |
74 // Creates an AnimationValuePtr from the specified transform. | |
75 AnimationValuePtr TransformAnimationValue(const gfx::Transform& transform) { | |
76 AnimationValuePtr value(AnimationValue::New()); | |
77 value->transform = Transform::From(transform); | |
78 return value; | |
79 } | |
80 | |
81 // Adds an AnimationElement to |group|s last sequence with the specified value. | |
82 void AddElement(AnimationGroup* group, | |
83 TimeDelta time, | |
84 AnimationValuePtr start_value, | |
85 AnimationValuePtr target_value, | |
86 AnimationProperty property, | |
87 AnimationTweenType tween_type) { | |
88 AnimationSequence& sequence = | |
89 *(group->sequences[group->sequences.size() - 1]); | |
90 sequence.elements.push_back(AnimationElement::New()); | |
91 AnimationElement& element = | |
92 *(sequence.elements[sequence.elements.size() - 1]); | |
93 element.property = property; | |
94 element.duration = time.InMicroseconds(); | |
95 element.tween_type = tween_type; | |
96 element.start_value = start_value.Pass(); | |
97 element.target_value = target_value.Pass(); | |
98 } | |
99 | |
100 void AddOpacityElement(AnimationGroup* group, | |
101 TimeDelta time, | |
102 AnimationValuePtr start_value, | |
103 AnimationValuePtr target_value) { | |
104 AddElement(group, time, start_value.Pass(), target_value.Pass(), | |
105 AnimationProperty::OPACITY, AnimationTweenType::LINEAR); | |
106 } | |
107 | |
108 void AddTransformElement(AnimationGroup* group, | |
109 TimeDelta time, | |
110 AnimationValuePtr start_value, | |
111 AnimationValuePtr target_value) { | |
112 AddElement(group, time, start_value.Pass(), target_value.Pass(), | |
113 AnimationProperty::TRANSFORM, AnimationTweenType::LINEAR); | |
114 } | |
115 | |
116 void AddPauseElement(AnimationGroup* group, TimeDelta time) { | |
117 AddElement(group, time, AnimationValuePtr(), AnimationValuePtr(), | |
118 AnimationProperty::NONE, AnimationTweenType::LINEAR); | |
119 } | |
120 | |
121 void InitGroupForView(AnimationGroup* group, | |
122 const ViewId& id, | |
123 int cycle_count) { | |
124 group->view_id = ViewIdToTransportId(id); | |
125 group->sequences.push_back(AnimationSequence::New()); | |
126 group->sequences[group->sequences.size() - 1]->cycle_count = cycle_count; | |
127 } | |
128 | |
129 } // namespace | |
130 | |
131 class AnimationRunnerTest : public testing::Test { | |
132 public: | |
133 AnimationRunnerTest() | |
134 : initial_time_(base::TimeTicks::Now()), runner_(initial_time_) { | |
135 runner_.AddObserver(&runner_observer_); | |
136 } | |
137 ~AnimationRunnerTest() override { runner_.RemoveObserver(&runner_observer_); } | |
138 | |
139 protected: | |
140 // Convenience to schedule an animation for a single view/group pair. | |
141 AnimationRunner::AnimationId ScheduleForSingleView( | |
142 ServerView* view, | |
143 const AnimationGroup* group, | |
144 base::TimeTicks now) { | |
145 std::vector<AnimationRunner::ViewAndAnimationPair> pairs; | |
146 pairs.push_back(std::make_pair(view, group)); | |
147 return runner_.Schedule(pairs, now); | |
148 } | |
149 | |
150 // If |id| is valid and there is only one view schedule against the animation | |
151 // it is returned; otherwise returns null. | |
152 ServerView* GetSingleViewAnimating(AnimationRunner::AnimationId id) { | |
153 std::set<ServerView*> views(runner_.GetViewsAnimating(id)); | |
154 return views.size() == 1 ? *views.begin() : nullptr; | |
155 } | |
156 | |
157 const base::TimeTicks initial_time_; | |
158 TestAnimationRunnerObserver runner_observer_; | |
159 AnimationRunner runner_; | |
160 | |
161 private: | |
162 DISALLOW_COPY_AND_ASSIGN(AnimationRunnerTest); | |
163 }; | |
164 | |
165 // Opacity from 1 to .5 over 1000. | |
166 TEST_F(AnimationRunnerTest, SingleProperty) { | |
167 TestServerViewDelegate view_delegate; | |
168 ServerView view(&view_delegate, ViewId()); | |
169 | |
170 AnimationGroup group; | |
171 InitGroupForView(&group, view.id(), 1); | |
172 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
173 AnimationValuePtr(), FloatAnimationValue(.5)); | |
174 | |
175 const uint32_t animation_id = | |
176 ScheduleForSingleView(&view, &group, initial_time_); | |
177 | |
178 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
179 EXPECT_EQ("scheduled", runner_observer_.changes()->at(0)); | |
180 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
181 runner_observer_.clear_changes(); | |
182 | |
183 EXPECT_TRUE(runner_.HasAnimations()); | |
184 | |
185 // Opacity should still be 1 (the initial value). | |
186 EXPECT_EQ(1.f, view.opacity()); | |
187 | |
188 // Animate half way. | |
189 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
190 | |
191 EXPECT_EQ(.75f, view.opacity()); | |
192 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
193 | |
194 // Run well past the end. Value should progress to end and delegate should | |
195 // be notified. | |
196 runner_.Tick(initial_time_ + TimeDelta::FromSeconds(10)); | |
197 EXPECT_EQ(.5f, view.opacity()); | |
198 | |
199 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
200 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
201 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
202 | |
203 EXPECT_FALSE(runner_.HasAnimations()); | |
204 } | |
205 | |
206 // Opacity from 1 to .5, followed by transform from identity to 2x,3x. | |
207 TEST_F(AnimationRunnerTest, TwoPropertiesInSequence) { | |
208 TestServerViewDelegate view_delegate; | |
209 ServerView view(&view_delegate, ViewId()); | |
210 | |
211 AnimationGroup group; | |
212 InitGroupForView(&group, view.id(), 1); | |
213 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
214 AnimationValuePtr(), FloatAnimationValue(.5f)); | |
215 | |
216 gfx::Transform done_transform; | |
217 done_transform.Scale(2, 4); | |
218 AddTransformElement(&group, TimeDelta::FromMicroseconds(2000), | |
219 AnimationValuePtr(), | |
220 TransformAnimationValue(done_transform)); | |
221 | |
222 const uint32_t animation_id = | |
223 ScheduleForSingleView(&view, &group, initial_time_); | |
224 runner_observer_.clear_changes(); | |
225 | |
226 // Nothing in the view should have changed yet. | |
227 EXPECT_EQ(1.f, view.opacity()); | |
228 EXPECT_TRUE(view.transform().IsIdentity()); | |
229 | |
230 // Animate half way from through opacity animation. | |
231 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
232 | |
233 EXPECT_EQ(.75f, view.opacity()); | |
234 EXPECT_TRUE(view.transform().IsIdentity()); | |
235 | |
236 // Finish first element (opacity). | |
237 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000)); | |
238 EXPECT_EQ(.5f, view.opacity()); | |
239 EXPECT_TRUE(view.transform().IsIdentity()); | |
240 | |
241 // Half way through second (transform). | |
242 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2000)); | |
243 EXPECT_EQ(.5f, view.opacity()); | |
244 gfx::Transform half_way_transform; | |
245 half_way_transform.Scale(1.5, 2.5); | |
246 EXPECT_EQ(half_way_transform, view.transform()); | |
247 | |
248 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
249 | |
250 // To end. | |
251 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3500)); | |
252 EXPECT_EQ(.5f, view.opacity()); | |
253 EXPECT_EQ(done_transform, view.transform()); | |
254 | |
255 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
256 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
257 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
258 } | |
259 | |
260 // Opacity from .5 to 1 over 1000, transform to 2x,4x over 500. | |
261 TEST_F(AnimationRunnerTest, TwoPropertiesInParallel) { | |
262 TestServerViewDelegate view_delegate; | |
263 ServerView view(&view_delegate, ViewId(1, 1)); | |
264 | |
265 AnimationGroup group; | |
266 InitGroupForView(&group, view.id(), 1); | |
267 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
268 FloatAnimationValue(.5f), FloatAnimationValue(1)); | |
269 | |
270 group.sequences.push_back(AnimationSequence::New()); | |
271 group.sequences[1]->cycle_count = 1; | |
272 gfx::Transform done_transform; | |
273 done_transform.Scale(2, 4); | |
274 AddTransformElement(&group, TimeDelta::FromMicroseconds(500), | |
275 AnimationValuePtr(), | |
276 TransformAnimationValue(done_transform)); | |
277 | |
278 const uint32_t animation_id = | |
279 ScheduleForSingleView(&view, &group, initial_time_); | |
280 | |
281 runner_observer_.clear_changes(); | |
282 | |
283 // Nothing in the view should have changed yet. | |
284 EXPECT_EQ(1.f, view.opacity()); | |
285 EXPECT_TRUE(view.transform().IsIdentity()); | |
286 | |
287 // Animate to 250, which is 1/4 way through opacity and half way through | |
288 // transform. | |
289 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(250)); | |
290 | |
291 EXPECT_EQ(.625f, view.opacity()); | |
292 gfx::Transform half_way_transform; | |
293 half_way_transform.Scale(1.5, 2.5); | |
294 EXPECT_EQ(half_way_transform, view.transform()); | |
295 | |
296 // Animate to 500, which is 1/2 way through opacity and transform done. | |
297 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
298 EXPECT_EQ(.75f, view.opacity()); | |
299 EXPECT_EQ(done_transform, view.transform()); | |
300 | |
301 // Animate to 750, which is 3/4 way through opacity and transform done. | |
302 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(750)); | |
303 EXPECT_EQ(.875f, view.opacity()); | |
304 EXPECT_EQ(done_transform, view.transform()); | |
305 | |
306 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
307 | |
308 // To end. | |
309 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3500)); | |
310 EXPECT_EQ(1.f, view.opacity()); | |
311 EXPECT_EQ(done_transform, view.transform()); | |
312 | |
313 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
314 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
315 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
316 } | |
317 | |
318 // Opacity from .5 to 1 over 1000, pause for 500, 1 to .5 over 500, with a cycle | |
319 // count of 3. | |
320 TEST_F(AnimationRunnerTest, Cycles) { | |
321 TestServerViewDelegate view_delegate; | |
322 ServerView view(&view_delegate, ViewId(1, 2)); | |
323 | |
324 view.SetOpacity(.5f); | |
325 | |
326 AnimationGroup group; | |
327 InitGroupForView(&group, view.id(), 3); | |
328 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
329 AnimationValuePtr(), FloatAnimationValue(1)); | |
330 AddPauseElement(&group, TimeDelta::FromMicroseconds(500)); | |
331 AddOpacityElement(&group, TimeDelta::FromMicroseconds(500), | |
332 AnimationValuePtr(), FloatAnimationValue(.5)); | |
333 | |
334 ScheduleForSingleView(&view, &group, initial_time_); | |
335 runner_observer_.clear_changes(); | |
336 | |
337 // Nothing in the view should have changed yet. | |
338 EXPECT_EQ(.5f, view.opacity()); | |
339 | |
340 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
341 EXPECT_EQ(.75f, view.opacity()); | |
342 | |
343 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1250)); | |
344 EXPECT_EQ(1.f, view.opacity()); | |
345 | |
346 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1750)); | |
347 EXPECT_EQ(.75f, view.opacity()); | |
348 | |
349 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2500)); | |
350 EXPECT_EQ(.75f, view.opacity()); | |
351 | |
352 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3250)); | |
353 EXPECT_EQ(1.f, view.opacity()); | |
354 | |
355 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3750)); | |
356 EXPECT_EQ(.75f, view.opacity()); | |
357 | |
358 // Animate to the end. | |
359 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(6500)); | |
360 EXPECT_EQ(.5f, view.opacity()); | |
361 | |
362 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
363 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
364 } | |
365 | |
366 // Verifies scheduling the same view twice sends an interrupt. | |
367 TEST_F(AnimationRunnerTest, ScheduleTwice) { | |
368 TestServerViewDelegate view_delegate; | |
369 ServerView view(&view_delegate, ViewId(1, 2)); | |
370 | |
371 AnimationGroup group; | |
372 InitGroupForView(&group, view.id(), 1); | |
373 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
374 AnimationValuePtr(), FloatAnimationValue(.5)); | |
375 | |
376 const uint32_t animation_id = | |
377 ScheduleForSingleView(&view, &group, initial_time_); | |
378 runner_observer_.clear_changes(); | |
379 | |
380 // Animate half way. | |
381 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
382 | |
383 EXPECT_EQ(.75f, view.opacity()); | |
384 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
385 | |
386 // Schedule again. We should get an interrupt, but opacity shouldn't change. | |
387 const uint32_t animation2_id = ScheduleForSingleView( | |
388 &view, &group, initial_time_ + TimeDelta::FromMicroseconds(500)); | |
389 | |
390 // Id should have changed. | |
391 EXPECT_NE(animation_id, animation2_id); | |
392 | |
393 EXPECT_FALSE(runner_.IsAnimating(animation_id)); | |
394 EXPECT_EQ(&view, GetSingleViewAnimating(animation2_id)); | |
395 | |
396 EXPECT_EQ(.75f, view.opacity()); | |
397 EXPECT_EQ(2u, runner_observer_.changes()->size()); | |
398 EXPECT_EQ("interrupted", runner_observer_.changes()->at(0)); | |
399 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
400 EXPECT_EQ("scheduled", runner_observer_.changes()->at(1)); | |
401 EXPECT_EQ(animation2_id, runner_observer_.change_ids()->at(1)); | |
402 runner_observer_.clear_changes(); | |
403 | |
404 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000)); | |
405 EXPECT_EQ(.625f, view.opacity()); | |
406 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
407 | |
408 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2000)); | |
409 EXPECT_EQ(.5f, view.opacity()); | |
410 EXPECT_EQ(1u, runner_observer_.changes()->size()); | |
411 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
412 EXPECT_EQ(animation2_id, runner_observer_.change_ids()->at(0)); | |
413 } | |
414 | |
415 // Verifies Remove() works. | |
416 TEST_F(AnimationRunnerTest, CancelAnimationForView) { | |
417 // Create an animation and advance it part way. | |
418 TestServerViewDelegate view_delegate; | |
419 ServerView view(&view_delegate, ViewId()); | |
420 AnimationGroup group; | |
421 InitGroupForView(&group, view.id(), 1); | |
422 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
423 AnimationValuePtr(), FloatAnimationValue(.5)); | |
424 | |
425 const uint32_t animation_id = | |
426 ScheduleForSingleView(&view, &group, initial_time_); | |
427 runner_observer_.clear_changes(); | |
428 EXPECT_EQ(&view, GetSingleViewAnimating(animation_id)); | |
429 | |
430 EXPECT_TRUE(runner_.HasAnimations()); | |
431 | |
432 // Animate half way. | |
433 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
434 EXPECT_EQ(.75f, view.opacity()); | |
435 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
436 | |
437 // Cancel the animation. | |
438 runner_.CancelAnimationForView(&view); | |
439 | |
440 EXPECT_FALSE(runner_.HasAnimations()); | |
441 EXPECT_EQ(nullptr, GetSingleViewAnimating(animation_id)); | |
442 | |
443 EXPECT_EQ(.75f, view.opacity()); | |
444 | |
445 EXPECT_EQ(1u, runner_observer_.changes()->size()); | |
446 EXPECT_EQ("canceled", runner_observer_.changes()->at(0)); | |
447 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
448 } | |
449 | |
450 // Verifies a tick with a very large delta and a sequence that repeats forever | |
451 // doesn't take a long time. | |
452 TEST_F(AnimationRunnerTest, InfiniteRepeatWithHugeGap) { | |
453 TestServerViewDelegate view_delegate; | |
454 ServerView view(&view_delegate, ViewId(1, 2)); | |
455 | |
456 view.SetOpacity(.5f); | |
457 | |
458 AnimationGroup group; | |
459 InitGroupForView(&group, view.id(), 0); | |
460 AddOpacityElement(&group, TimeDelta::FromMicroseconds(500), | |
461 AnimationValuePtr(), FloatAnimationValue(1)); | |
462 AddOpacityElement(&group, TimeDelta::FromMicroseconds(500), | |
463 AnimationValuePtr(), FloatAnimationValue(.5)); | |
464 | |
465 ScheduleForSingleView(&view, &group, initial_time_); | |
466 runner_observer_.clear_changes(); | |
467 | |
468 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000000000750)); | |
469 | |
470 EXPECT_EQ(.75f, view.opacity()); | |
471 | |
472 ASSERT_EQ(0u, runner_observer_.changes()->size()); | |
473 } | |
474 | |
475 // Verifies a second schedule sets any properties that are no longer animating | |
476 // to their final value. | |
477 TEST_F(AnimationRunnerTest, RescheduleSetsPropertiesToFinalValue) { | |
478 TestServerViewDelegate view_delegate; | |
479 ServerView view(&view_delegate, ViewId()); | |
480 | |
481 AnimationGroup group; | |
482 InitGroupForView(&group, view.id(), 1); | |
483 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
484 AnimationValuePtr(), FloatAnimationValue(.5)); | |
485 | |
486 gfx::Transform done_transform; | |
487 done_transform.Scale(2, 4); | |
488 AddTransformElement(&group, TimeDelta::FromMicroseconds(500), | |
489 AnimationValuePtr(), | |
490 TransformAnimationValue(done_transform)); | |
491 | |
492 ScheduleForSingleView(&view, &group, initial_time_); | |
493 | |
494 // Schedule() again, this time without animating opacity. | |
495 group.sequences[0]->elements[0]->property = AnimationProperty::NONE; | |
496 ScheduleForSingleView(&view, &group, initial_time_); | |
497 | |
498 // Opacity should go to final value. | |
499 EXPECT_EQ(.5f, view.opacity()); | |
500 // Transform shouldn't have changed since newly scheduled animation also has | |
501 // transform in it. | |
502 EXPECT_TRUE(view.transform().IsIdentity()); | |
503 } | |
504 | |
505 // Opacity from 1 to .5 over 1000 of v1 and v2 transform to 2x,4x over 500. | |
506 TEST_F(AnimationRunnerTest, TwoViews) { | |
507 TestServerViewDelegate view_delegate; | |
508 ServerView view1(&view_delegate, ViewId()); | |
509 ServerView view2(&view_delegate, ViewId(1, 2)); | |
510 | |
511 AnimationGroup group1; | |
512 InitGroupForView(&group1, view1.id(), 1); | |
513 AddOpacityElement(&group1, TimeDelta::FromMicroseconds(1000), | |
514 AnimationValuePtr(), FloatAnimationValue(.5)); | |
515 | |
516 AnimationGroup group2; | |
517 InitGroupForView(&group2, view2.id(), 1); | |
518 gfx::Transform done_transform; | |
519 done_transform.Scale(2, 4); | |
520 AddTransformElement(&group2, TimeDelta::FromMicroseconds(500), | |
521 AnimationValuePtr(), | |
522 TransformAnimationValue(done_transform)); | |
523 | |
524 std::vector<AnimationRunner::ViewAndAnimationPair> pairs; | |
525 pairs.push_back(std::make_pair(&view1, &group1)); | |
526 pairs.push_back(std::make_pair(&view2, &group2)); | |
527 | |
528 const uint32_t animation_id = runner_.Schedule(pairs, initial_time_); | |
529 | |
530 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
531 EXPECT_EQ("scheduled", runner_observer_.changes()->at(0)); | |
532 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
533 runner_observer_.clear_changes(); | |
534 | |
535 EXPECT_TRUE(runner_.HasAnimations()); | |
536 EXPECT_TRUE(runner_.IsAnimating(animation_id)); | |
537 | |
538 // Properties should be at the initial value. | |
539 EXPECT_EQ(1.f, view1.opacity()); | |
540 EXPECT_TRUE(view2.transform().IsIdentity()); | |
541 | |
542 // Animate 250ms in, which is quarter way for opacity and half way for | |
543 // transform. | |
544 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(250)); | |
545 EXPECT_EQ(.875f, view1.opacity()); | |
546 gfx::Transform half_way_transform; | |
547 half_way_transform.Scale(1.5, 2.5); | |
548 EXPECT_EQ(half_way_transform, view2.transform()); | |
549 std::set<ServerView*> views_animating( | |
550 runner_.GetViewsAnimating(animation_id)); | |
551 EXPECT_EQ(2u, views_animating.size()); | |
552 EXPECT_EQ(1u, views_animating.count(&view1)); | |
553 EXPECT_EQ(1u, views_animating.count(&view2)); | |
554 | |
555 // Animate 750ms in, view1 should be done 3/4 done, and view2 done. | |
556 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(750)); | |
557 EXPECT_EQ(.625, view1.opacity()); | |
558 EXPECT_EQ(done_transform, view2.transform()); | |
559 views_animating = runner_.GetViewsAnimating(animation_id); | |
560 EXPECT_EQ(1u, views_animating.size()); | |
561 EXPECT_EQ(1u, views_animating.count(&view1)); | |
562 EXPECT_TRUE(runner_.HasAnimations()); | |
563 EXPECT_TRUE(runner_.IsAnimating(animation_id)); | |
564 | |
565 // Animate to end. | |
566 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1750)); | |
567 EXPECT_EQ(.5, view1.opacity()); | |
568 EXPECT_EQ(done_transform, view2.transform()); | |
569 views_animating = runner_.GetViewsAnimating(animation_id); | |
570 EXPECT_TRUE(views_animating.empty()); | |
571 EXPECT_FALSE(runner_.HasAnimations()); | |
572 EXPECT_FALSE(runner_.IsAnimating(animation_id)); | |
573 } | |
574 | |
575 TEST_F(AnimationRunnerTest, Reschedule) { | |
576 TestServerViewDelegate view_delegate; | |
577 ServerView view(&view_delegate, ViewId()); | |
578 | |
579 // Animation from 1-0 over 1ms and in parallel transform to 2x,4x over 1ms. | |
580 AnimationGroup group; | |
581 InitGroupForView(&group, view.id(), 1); | |
582 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
583 AnimationValuePtr(), FloatAnimationValue(0)); | |
584 group.sequences.push_back(AnimationSequence::New()); | |
585 group.sequences[1]->cycle_count = 1; | |
586 gfx::Transform done_transform; | |
587 done_transform.Scale(2, 4); | |
588 AddTransformElement(&group, TimeDelta::FromMicroseconds(1000), | |
589 AnimationValuePtr(), | |
590 TransformAnimationValue(done_transform)); | |
591 const uint32_t animation_id1 = | |
592 ScheduleForSingleView(&view, &group, initial_time_); | |
593 | |
594 // Animate half way in. | |
595 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
596 EXPECT_EQ(.5f, view.opacity()); | |
597 gfx::Transform half_way_transform; | |
598 half_way_transform.Scale(1.5, 2.5); | |
599 EXPECT_EQ(half_way_transform, view.transform()); | |
600 | |
601 runner_observer_.clear_changes(); | |
602 | |
603 // Schedule the same view animating opacity to 1. | |
604 AnimationGroup group2; | |
605 InitGroupForView(&group2, view.id(), 1); | |
606 AddOpacityElement(&group2, TimeDelta::FromMicroseconds(1000), | |
607 AnimationValuePtr(), FloatAnimationValue(1)); | |
608 const uint32_t animation_id2 = ScheduleForSingleView( | |
609 &view, &group2, initial_time_ + TimeDelta::FromMicroseconds(500)); | |
610 | |
611 // Opacity should remain at .5, but transform should go to end state. | |
612 EXPECT_EQ(.5f, view.opacity()); | |
613 EXPECT_EQ(done_transform, view.transform()); | |
614 | |
615 ASSERT_EQ(2u, runner_observer_.changes()->size()); | |
616 EXPECT_EQ("interrupted", runner_observer_.changes()->at(0)); | |
617 EXPECT_EQ(animation_id1, runner_observer_.change_ids()->at(0)); | |
618 EXPECT_EQ("scheduled", runner_observer_.changes()->at(1)); | |
619 EXPECT_EQ(animation_id2, runner_observer_.change_ids()->at(1)); | |
620 runner_observer_.clear_changes(); | |
621 | |
622 // Animate half way through new sequence. Opacity should be the only thing | |
623 // changing. | |
624 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000)); | |
625 EXPECT_EQ(.75f, view.opacity()); | |
626 EXPECT_EQ(done_transform, view.transform()); | |
627 ASSERT_EQ(0u, runner_observer_.changes()->size()); | |
628 | |
629 // Animate to end. | |
630 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2000)); | |
631 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
632 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
633 EXPECT_EQ(animation_id2, runner_observer_.change_ids()->at(0)); | |
634 } | |
635 | |
636 } // namespace view_manager | |
OLD | NEW |