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.
5 #include "components/view_manager/animation_runner.h"
7 #include "base/strings/stringprintf.h"
8 #include "components/view_manager/animation_runner_observer.h"
9 #include "components/view_manager/public/interfaces/view_manager_constants.mojom.h"
10 #include "components/view_manager/scheduled_animation_group.h"
11 #include "components/view_manager/server_view.h"
12 #include "components/view_manager/test_server_view_delegate.h"
13 #include "mojo/converters/geometry/geometry_type_converters.h"
14 #include "mojo/converters/transform/transform_type_converters.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 using base::TimeDelta
;
18 using mojo::ANIMATION_PROPERTY_NONE
;
19 using mojo::ANIMATION_PROPERTY_OPACITY
;
20 using mojo::ANIMATION_PROPERTY_TRANSFORM
;
21 using mojo::ANIMATION_TWEEN_TYPE_LINEAR
;
22 using mojo::AnimationElement
;
23 using mojo::AnimationGroup
;
24 using mojo::AnimationProperty
;
25 using mojo::AnimationSequence
;
26 using mojo::AnimationTweenType
;
27 using mojo::AnimationValue
;
28 using mojo::AnimationValuePtr
;
29 using mojo::Transform
;
31 namespace view_manager
{
34 class TestAnimationRunnerObserver
: public AnimationRunnerObserver
{
36 TestAnimationRunnerObserver() {}
37 ~TestAnimationRunnerObserver() override
{}
39 std::vector
<std::string
>* changes() { return &changes_
; }
40 std::vector
<uint32_t>* change_ids() { return &change_ids_
; }
42 void clear_changes() {
47 // AnimationRunnerDelgate:
48 void OnAnimationScheduled(uint32_t id
) override
{
49 change_ids_
.push_back(id
);
50 changes_
.push_back("scheduled");
52 void OnAnimationDone(uint32_t id
) override
{
53 change_ids_
.push_back(id
);
54 changes_
.push_back("done");
56 void OnAnimationInterrupted(uint32_t id
) override
{
57 change_ids_
.push_back(id
);
58 changes_
.push_back("interrupted");
60 void OnAnimationCanceled(uint32_t id
) override
{
61 change_ids_
.push_back(id
);
62 changes_
.push_back("canceled");
66 std::vector
<uint32_t> change_ids_
;
67 std::vector
<std::string
> changes_
;
69 DISALLOW_COPY_AND_ASSIGN(TestAnimationRunnerObserver
);
72 // Creates an AnimationValuePtr from the specified float value.
73 AnimationValuePtr
FloatAnimationValue(float float_value
) {
74 AnimationValuePtr
value(AnimationValue::New());
75 value
->float_value
= float_value
;
79 // Creates an AnimationValuePtr from the specified transform.
80 AnimationValuePtr
TransformAnimationValue(const gfx::Transform
& transform
) {
81 AnimationValuePtr
value(AnimationValue::New());
82 value
->transform
= Transform::From(transform
);
86 // Adds an AnimationElement to |group|s last sequence with the specified value.
87 void AddElement(AnimationGroup
* group
,
89 AnimationValuePtr start_value
,
90 AnimationValuePtr target_value
,
91 AnimationProperty property
,
92 AnimationTweenType tween_type
) {
93 AnimationSequence
& sequence
=
94 *(group
->sequences
[group
->sequences
.size() - 1]);
95 sequence
.elements
.push_back(AnimationElement::New());
96 AnimationElement
& element
=
97 *(sequence
.elements
[sequence
.elements
.size() - 1]);
98 element
.property
= property
;
99 element
.duration
= time
.InMicroseconds();
100 element
.tween_type
= tween_type
;
101 element
.start_value
= start_value
.Pass();
102 element
.target_value
= target_value
.Pass();
105 void AddOpacityElement(AnimationGroup
* group
,
107 AnimationValuePtr start_value
,
108 AnimationValuePtr target_value
) {
109 AddElement(group
, time
, start_value
.Pass(), target_value
.Pass(),
110 ANIMATION_PROPERTY_OPACITY
, ANIMATION_TWEEN_TYPE_LINEAR
);
113 void AddTransformElement(AnimationGroup
* group
,
115 AnimationValuePtr start_value
,
116 AnimationValuePtr target_value
) {
117 AddElement(group
, time
, start_value
.Pass(), target_value
.Pass(),
118 ANIMATION_PROPERTY_TRANSFORM
, ANIMATION_TWEEN_TYPE_LINEAR
);
121 void AddPauseElement(AnimationGroup
* group
, TimeDelta time
) {
122 AddElement(group
, time
, AnimationValuePtr(), AnimationValuePtr(),
123 ANIMATION_PROPERTY_NONE
, ANIMATION_TWEEN_TYPE_LINEAR
);
126 void InitGroupForView(AnimationGroup
* group
,
129 group
->view_id
= ViewIdToTransportId(id
);
130 group
->sequences
.push_back(AnimationSequence::New());
131 group
->sequences
[group
->sequences
.size() - 1]->cycle_count
= cycle_count
;
136 class AnimationRunnerTest
: public testing::Test
{
138 AnimationRunnerTest()
139 : initial_time_(base::TimeTicks::Now()), runner_(initial_time_
) {
140 runner_
.AddObserver(&runner_observer_
);
142 ~AnimationRunnerTest() override
{ runner_
.RemoveObserver(&runner_observer_
); }
145 // Convenience to schedule an animation for a single view/group pair.
146 AnimationRunner::AnimationId
ScheduleForSingleView(
148 const AnimationGroup
* group
,
149 base::TimeTicks now
) {
150 std::vector
<AnimationRunner::ViewAndAnimationPair
> pairs
;
151 pairs
.push_back(std::make_pair(view
, group
));
152 return runner_
.Schedule(pairs
, now
);
155 // If |id| is valid and there is only one view schedule against the animation
156 // it is returned; otherwise returns null.
157 ServerView
* GetSingleViewAnimating(AnimationRunner::AnimationId id
) {
158 std::set
<ServerView
*> views(runner_
.GetViewsAnimating(id
));
159 return views
.size() == 1 ? *views
.begin() : nullptr;
162 const base::TimeTicks initial_time_
;
163 TestAnimationRunnerObserver runner_observer_
;
164 AnimationRunner runner_
;
167 DISALLOW_COPY_AND_ASSIGN(AnimationRunnerTest
);
170 // Opacity from 1 to .5 over 1000.
171 TEST_F(AnimationRunnerTest
, SingleProperty
) {
172 TestServerViewDelegate view_delegate
;
173 ServerView
view(&view_delegate
, ViewId());
175 AnimationGroup group
;
176 InitGroupForView(&group
, view
.id(), 1);
177 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(1000),
178 AnimationValuePtr(), FloatAnimationValue(.5));
180 const uint32_t animation_id
=
181 ScheduleForSingleView(&view
, &group
, initial_time_
);
183 ASSERT_EQ(1u, runner_observer_
.changes()->size());
184 EXPECT_EQ("scheduled", runner_observer_
.changes()->at(0));
185 EXPECT_EQ(animation_id
, runner_observer_
.change_ids()->at(0));
186 runner_observer_
.clear_changes();
188 EXPECT_TRUE(runner_
.HasAnimations());
190 // Opacity should still be 1 (the initial value).
191 EXPECT_EQ(1.f
, view
.opacity());
194 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(500));
196 EXPECT_EQ(.75f
, view
.opacity());
197 EXPECT_TRUE(runner_observer_
.changes()->empty());
199 // Run well past the end. Value should progress to end and delegate should
201 runner_
.Tick(initial_time_
+ TimeDelta::FromSeconds(10));
202 EXPECT_EQ(.5f
, view
.opacity());
204 ASSERT_EQ(1u, runner_observer_
.changes()->size());
205 EXPECT_EQ("done", runner_observer_
.changes()->at(0));
206 EXPECT_EQ(animation_id
, runner_observer_
.change_ids()->at(0));
208 EXPECT_FALSE(runner_
.HasAnimations());
211 // Opacity from 1 to .5, followed by transform from identity to 2x,3x.
212 TEST_F(AnimationRunnerTest
, TwoPropertiesInSequence
) {
213 TestServerViewDelegate view_delegate
;
214 ServerView
view(&view_delegate
, ViewId());
216 AnimationGroup group
;
217 InitGroupForView(&group
, view
.id(), 1);
218 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(1000),
219 AnimationValuePtr(), FloatAnimationValue(.5f
));
221 gfx::Transform done_transform
;
222 done_transform
.Scale(2, 4);
223 AddTransformElement(&group
, TimeDelta::FromMicroseconds(2000),
225 TransformAnimationValue(done_transform
));
227 const uint32_t animation_id
=
228 ScheduleForSingleView(&view
, &group
, initial_time_
);
229 runner_observer_
.clear_changes();
231 // Nothing in the view should have changed yet.
232 EXPECT_EQ(1.f
, view
.opacity());
233 EXPECT_TRUE(view
.transform().IsIdentity());
235 // Animate half way from through opacity animation.
236 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(500));
238 EXPECT_EQ(.75f
, view
.opacity());
239 EXPECT_TRUE(view
.transform().IsIdentity());
241 // Finish first element (opacity).
242 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(1000));
243 EXPECT_EQ(.5f
, view
.opacity());
244 EXPECT_TRUE(view
.transform().IsIdentity());
246 // Half way through second (transform).
247 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(2000));
248 EXPECT_EQ(.5f
, view
.opacity());
249 gfx::Transform half_way_transform
;
250 half_way_transform
.Scale(1.5, 2.5);
251 EXPECT_EQ(half_way_transform
, view
.transform());
253 EXPECT_TRUE(runner_observer_
.changes()->empty());
256 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(3500));
257 EXPECT_EQ(.5f
, view
.opacity());
258 EXPECT_EQ(done_transform
, view
.transform());
260 ASSERT_EQ(1u, runner_observer_
.changes()->size());
261 EXPECT_EQ("done", runner_observer_
.changes()->at(0));
262 EXPECT_EQ(animation_id
, runner_observer_
.change_ids()->at(0));
265 // Opacity from .5 to 1 over 1000, transform to 2x,4x over 500.
266 TEST_F(AnimationRunnerTest
, TwoPropertiesInParallel
) {
267 TestServerViewDelegate view_delegate
;
268 ServerView
view(&view_delegate
, ViewId(1, 1));
270 AnimationGroup group
;
271 InitGroupForView(&group
, view
.id(), 1);
272 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(1000),
273 FloatAnimationValue(.5f
), FloatAnimationValue(1));
275 group
.sequences
.push_back(AnimationSequence::New());
276 group
.sequences
[1]->cycle_count
= 1;
277 gfx::Transform done_transform
;
278 done_transform
.Scale(2, 4);
279 AddTransformElement(&group
, TimeDelta::FromMicroseconds(500),
281 TransformAnimationValue(done_transform
));
283 const uint32_t animation_id
=
284 ScheduleForSingleView(&view
, &group
, initial_time_
);
286 runner_observer_
.clear_changes();
288 // Nothing in the view should have changed yet.
289 EXPECT_EQ(1.f
, view
.opacity());
290 EXPECT_TRUE(view
.transform().IsIdentity());
292 // Animate to 250, which is 1/4 way through opacity and half way through
294 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(250));
296 EXPECT_EQ(.625f
, view
.opacity());
297 gfx::Transform half_way_transform
;
298 half_way_transform
.Scale(1.5, 2.5);
299 EXPECT_EQ(half_way_transform
, view
.transform());
301 // Animate to 500, which is 1/2 way through opacity and transform done.
302 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(500));
303 EXPECT_EQ(.75f
, view
.opacity());
304 EXPECT_EQ(done_transform
, view
.transform());
306 // Animate to 750, which is 3/4 way through opacity and transform done.
307 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(750));
308 EXPECT_EQ(.875f
, view
.opacity());
309 EXPECT_EQ(done_transform
, view
.transform());
311 EXPECT_TRUE(runner_observer_
.changes()->empty());
314 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(3500));
315 EXPECT_EQ(1.f
, view
.opacity());
316 EXPECT_EQ(done_transform
, view
.transform());
318 ASSERT_EQ(1u, runner_observer_
.changes()->size());
319 EXPECT_EQ("done", runner_observer_
.changes()->at(0));
320 EXPECT_EQ(animation_id
, runner_observer_
.change_ids()->at(0));
323 // Opacity from .5 to 1 over 1000, pause for 500, 1 to .5 over 500, with a cycle
325 TEST_F(AnimationRunnerTest
, Cycles
) {
326 TestServerViewDelegate view_delegate
;
327 ServerView
view(&view_delegate
, ViewId(1, 2));
329 view
.SetOpacity(.5f
);
331 AnimationGroup group
;
332 InitGroupForView(&group
, view
.id(), 3);
333 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(1000),
334 AnimationValuePtr(), FloatAnimationValue(1));
335 AddPauseElement(&group
, TimeDelta::FromMicroseconds(500));
336 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(500),
337 AnimationValuePtr(), FloatAnimationValue(.5));
339 ScheduleForSingleView(&view
, &group
, initial_time_
);
340 runner_observer_
.clear_changes();
342 // Nothing in the view should have changed yet.
343 EXPECT_EQ(.5f
, view
.opacity());
345 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(500));
346 EXPECT_EQ(.75f
, view
.opacity());
348 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(1250));
349 EXPECT_EQ(1.f
, view
.opacity());
351 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(1750));
352 EXPECT_EQ(.75f
, view
.opacity());
354 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(2500));
355 EXPECT_EQ(.75f
, view
.opacity());
357 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(3250));
358 EXPECT_EQ(1.f
, view
.opacity());
360 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(3750));
361 EXPECT_EQ(.75f
, view
.opacity());
363 // Animate to the end.
364 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(6500));
365 EXPECT_EQ(.5f
, view
.opacity());
367 ASSERT_EQ(1u, runner_observer_
.changes()->size());
368 EXPECT_EQ("done", runner_observer_
.changes()->at(0));
371 // Verifies scheduling the same view twice sends an interrupt.
372 TEST_F(AnimationRunnerTest
, ScheduleTwice
) {
373 TestServerViewDelegate view_delegate
;
374 ServerView
view(&view_delegate
, ViewId(1, 2));
376 AnimationGroup group
;
377 InitGroupForView(&group
, view
.id(), 1);
378 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(1000),
379 AnimationValuePtr(), FloatAnimationValue(.5));
381 const uint32_t animation_id
=
382 ScheduleForSingleView(&view
, &group
, initial_time_
);
383 runner_observer_
.clear_changes();
386 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(500));
388 EXPECT_EQ(.75f
, view
.opacity());
389 EXPECT_TRUE(runner_observer_
.changes()->empty());
391 // Schedule again. We should get an interrupt, but opacity shouldn't change.
392 const uint32_t animation2_id
= ScheduleForSingleView(
393 &view
, &group
, initial_time_
+ TimeDelta::FromMicroseconds(500));
395 // Id should have changed.
396 EXPECT_NE(animation_id
, animation2_id
);
398 EXPECT_FALSE(runner_
.IsAnimating(animation_id
));
399 EXPECT_EQ(&view
, GetSingleViewAnimating(animation2_id
));
401 EXPECT_EQ(.75f
, view
.opacity());
402 EXPECT_EQ(2u, runner_observer_
.changes()->size());
403 EXPECT_EQ("interrupted", runner_observer_
.changes()->at(0));
404 EXPECT_EQ(animation_id
, runner_observer_
.change_ids()->at(0));
405 EXPECT_EQ("scheduled", runner_observer_
.changes()->at(1));
406 EXPECT_EQ(animation2_id
, runner_observer_
.change_ids()->at(1));
407 runner_observer_
.clear_changes();
409 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(1000));
410 EXPECT_EQ(.625f
, view
.opacity());
411 EXPECT_TRUE(runner_observer_
.changes()->empty());
413 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(2000));
414 EXPECT_EQ(.5f
, view
.opacity());
415 EXPECT_EQ(1u, runner_observer_
.changes()->size());
416 EXPECT_EQ("done", runner_observer_
.changes()->at(0));
417 EXPECT_EQ(animation2_id
, runner_observer_
.change_ids()->at(0));
420 // Verifies Remove() works.
421 TEST_F(AnimationRunnerTest
, CancelAnimationForView
) {
422 // Create an animation and advance it part way.
423 TestServerViewDelegate view_delegate
;
424 ServerView
view(&view_delegate
, ViewId());
425 AnimationGroup group
;
426 InitGroupForView(&group
, view
.id(), 1);
427 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(1000),
428 AnimationValuePtr(), FloatAnimationValue(.5));
430 const uint32_t animation_id
=
431 ScheduleForSingleView(&view
, &group
, initial_time_
);
432 runner_observer_
.clear_changes();
433 EXPECT_EQ(&view
, GetSingleViewAnimating(animation_id
));
435 EXPECT_TRUE(runner_
.HasAnimations());
438 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(500));
439 EXPECT_EQ(.75f
, view
.opacity());
440 EXPECT_TRUE(runner_observer_
.changes()->empty());
442 // Cancel the animation.
443 runner_
.CancelAnimationForView(&view
);
445 EXPECT_FALSE(runner_
.HasAnimations());
446 EXPECT_EQ(nullptr, GetSingleViewAnimating(animation_id
));
448 EXPECT_EQ(.75f
, view
.opacity());
450 EXPECT_EQ(1u, runner_observer_
.changes()->size());
451 EXPECT_EQ("canceled", runner_observer_
.changes()->at(0));
452 EXPECT_EQ(animation_id
, runner_observer_
.change_ids()->at(0));
455 // Verifies a tick with a very large delta and a sequence that repeats forever
456 // doesn't take a long time.
457 TEST_F(AnimationRunnerTest
, InfiniteRepeatWithHugeGap
) {
458 TestServerViewDelegate view_delegate
;
459 ServerView
view(&view_delegate
, ViewId(1, 2));
461 view
.SetOpacity(.5f
);
463 AnimationGroup group
;
464 InitGroupForView(&group
, view
.id(), 0);
465 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(500),
466 AnimationValuePtr(), FloatAnimationValue(1));
467 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(500),
468 AnimationValuePtr(), FloatAnimationValue(.5));
470 ScheduleForSingleView(&view
, &group
, initial_time_
);
471 runner_observer_
.clear_changes();
473 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(1000000000750));
475 EXPECT_EQ(.75f
, view
.opacity());
477 ASSERT_EQ(0u, runner_observer_
.changes()->size());
480 // Verifies a second schedule sets any properties that are no longer animating
481 // to their final value.
482 TEST_F(AnimationRunnerTest
, RescheduleSetsPropertiesToFinalValue
) {
483 TestServerViewDelegate view_delegate
;
484 ServerView
view(&view_delegate
, ViewId());
486 AnimationGroup group
;
487 InitGroupForView(&group
, view
.id(), 1);
488 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(1000),
489 AnimationValuePtr(), FloatAnimationValue(.5));
491 gfx::Transform done_transform
;
492 done_transform
.Scale(2, 4);
493 AddTransformElement(&group
, TimeDelta::FromMicroseconds(500),
495 TransformAnimationValue(done_transform
));
497 ScheduleForSingleView(&view
, &group
, initial_time_
);
499 // Schedule() again, this time without animating opacity.
500 group
.sequences
[0]->elements
[0]->property
= ANIMATION_PROPERTY_NONE
;
501 ScheduleForSingleView(&view
, &group
, initial_time_
);
503 // Opacity should go to final value.
504 EXPECT_EQ(.5f
, view
.opacity());
505 // Transform shouldn't have changed since newly scheduled animation also has
507 EXPECT_TRUE(view
.transform().IsIdentity());
510 // Opacity from 1 to .5 over 1000 of v1 and v2 transform to 2x,4x over 500.
511 TEST_F(AnimationRunnerTest
, TwoViews
) {
512 TestServerViewDelegate view_delegate
;
513 ServerView
view1(&view_delegate
, ViewId());
514 ServerView
view2(&view_delegate
, ViewId(1, 2));
516 AnimationGroup group1
;
517 InitGroupForView(&group1
, view1
.id(), 1);
518 AddOpacityElement(&group1
, TimeDelta::FromMicroseconds(1000),
519 AnimationValuePtr(), FloatAnimationValue(.5));
521 AnimationGroup group2
;
522 InitGroupForView(&group2
, view2
.id(), 1);
523 gfx::Transform done_transform
;
524 done_transform
.Scale(2, 4);
525 AddTransformElement(&group2
, TimeDelta::FromMicroseconds(500),
527 TransformAnimationValue(done_transform
));
529 std::vector
<AnimationRunner::ViewAndAnimationPair
> pairs
;
530 pairs
.push_back(std::make_pair(&view1
, &group1
));
531 pairs
.push_back(std::make_pair(&view2
, &group2
));
533 const uint32_t animation_id
= runner_
.Schedule(pairs
, initial_time_
);
535 ASSERT_EQ(1u, runner_observer_
.changes()->size());
536 EXPECT_EQ("scheduled", runner_observer_
.changes()->at(0));
537 EXPECT_EQ(animation_id
, runner_observer_
.change_ids()->at(0));
538 runner_observer_
.clear_changes();
540 EXPECT_TRUE(runner_
.HasAnimations());
541 EXPECT_TRUE(runner_
.IsAnimating(animation_id
));
543 // Properties should be at the initial value.
544 EXPECT_EQ(1.f
, view1
.opacity());
545 EXPECT_TRUE(view2
.transform().IsIdentity());
547 // Animate 250ms in, which is quarter way for opacity and half way for
549 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(250));
550 EXPECT_EQ(.875f
, view1
.opacity());
551 gfx::Transform half_way_transform
;
552 half_way_transform
.Scale(1.5, 2.5);
553 EXPECT_EQ(half_way_transform
, view2
.transform());
554 std::set
<ServerView
*> views_animating(
555 runner_
.GetViewsAnimating(animation_id
));
556 EXPECT_EQ(2u, views_animating
.size());
557 EXPECT_EQ(1u, views_animating
.count(&view1
));
558 EXPECT_EQ(1u, views_animating
.count(&view2
));
560 // Animate 750ms in, view1 should be done 3/4 done, and view2 done.
561 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(750));
562 EXPECT_EQ(.625, view1
.opacity());
563 EXPECT_EQ(done_transform
, view2
.transform());
564 views_animating
= runner_
.GetViewsAnimating(animation_id
);
565 EXPECT_EQ(1u, views_animating
.size());
566 EXPECT_EQ(1u, views_animating
.count(&view1
));
567 EXPECT_TRUE(runner_
.HasAnimations());
568 EXPECT_TRUE(runner_
.IsAnimating(animation_id
));
571 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(1750));
572 EXPECT_EQ(.5, view1
.opacity());
573 EXPECT_EQ(done_transform
, view2
.transform());
574 views_animating
= runner_
.GetViewsAnimating(animation_id
);
575 EXPECT_TRUE(views_animating
.empty());
576 EXPECT_FALSE(runner_
.HasAnimations());
577 EXPECT_FALSE(runner_
.IsAnimating(animation_id
));
580 TEST_F(AnimationRunnerTest
, Reschedule
) {
581 TestServerViewDelegate view_delegate
;
582 ServerView
view(&view_delegate
, ViewId());
584 // Animation from 1-0 over 1ms and in parallel transform to 2x,4x over 1ms.
585 AnimationGroup group
;
586 InitGroupForView(&group
, view
.id(), 1);
587 AddOpacityElement(&group
, TimeDelta::FromMicroseconds(1000),
588 AnimationValuePtr(), FloatAnimationValue(0));
589 group
.sequences
.push_back(AnimationSequence::New());
590 group
.sequences
[1]->cycle_count
= 1;
591 gfx::Transform done_transform
;
592 done_transform
.Scale(2, 4);
593 AddTransformElement(&group
, TimeDelta::FromMicroseconds(1000),
595 TransformAnimationValue(done_transform
));
596 const uint32_t animation_id1
=
597 ScheduleForSingleView(&view
, &group
, initial_time_
);
599 // Animate half way in.
600 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(500));
601 EXPECT_EQ(.5f
, view
.opacity());
602 gfx::Transform half_way_transform
;
603 half_way_transform
.Scale(1.5, 2.5);
604 EXPECT_EQ(half_way_transform
, view
.transform());
606 runner_observer_
.clear_changes();
608 // Schedule the same view animating opacity to 1.
609 AnimationGroup group2
;
610 InitGroupForView(&group2
, view
.id(), 1);
611 AddOpacityElement(&group2
, TimeDelta::FromMicroseconds(1000),
612 AnimationValuePtr(), FloatAnimationValue(1));
613 const uint32_t animation_id2
= ScheduleForSingleView(
614 &view
, &group2
, initial_time_
+ TimeDelta::FromMicroseconds(500));
616 // Opacity should remain at .5, but transform should go to end state.
617 EXPECT_EQ(.5f
, view
.opacity());
618 EXPECT_EQ(done_transform
, view
.transform());
620 ASSERT_EQ(2u, runner_observer_
.changes()->size());
621 EXPECT_EQ("interrupted", runner_observer_
.changes()->at(0));
622 EXPECT_EQ(animation_id1
, runner_observer_
.change_ids()->at(0));
623 EXPECT_EQ("scheduled", runner_observer_
.changes()->at(1));
624 EXPECT_EQ(animation_id2
, runner_observer_
.change_ids()->at(1));
625 runner_observer_
.clear_changes();
627 // Animate half way through new sequence. Opacity should be the only thing
629 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(1000));
630 EXPECT_EQ(.75f
, view
.opacity());
631 EXPECT_EQ(done_transform
, view
.transform());
632 ASSERT_EQ(0u, runner_observer_
.changes()->size());
635 runner_
.Tick(initial_time_
+ TimeDelta::FromMicroseconds(2000));
636 ASSERT_EQ(1u, runner_observer_
.changes()->size());
637 EXPECT_EQ("done", runner_observer_
.changes()->at(0));
638 EXPECT_EQ(animation_id2
, runner_observer_
.change_ids()->at(0));
641 } // namespace view_manager