[Sync] Fix invalidations on Android.
[chromium-blink-merge.git] / mojo / services / view_manager / animation_runner_unittest.cc
blobc43f0b1ece739f4b812efb41edc94b6a05fd2672
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 "mojo/services/view_manager/animation_runner.h"
7 #include "base/strings/stringprintf.h"
8 #include "mojo/converters/geometry/geometry_type_converters.h"
9 #include "mojo/converters/transform/transform_type_converters.h"
10 #include "mojo/services/view_manager/animation_runner_observer.h"
11 #include "mojo/services/view_manager/scheduled_animation_group.h"
12 #include "mojo/services/view_manager/server_view.h"
13 #include "mojo/services/view_manager/test_server_view_delegate.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager_constants.mojom.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 {
32 namespace {
34 class TestAnimationRunnerObserver : public AnimationRunnerObserver {
35 public:
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() {
43 changes_.clear();
44 change_ids_.clear();
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");
65 private:
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;
76 return value.Pass();
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);
83 return value.Pass();
86 // Adds an AnimationElement to |group|s last sequence with the specified value.
87 void AddElement(AnimationGroup* group,
88 TimeDelta time,
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,
106 TimeDelta time,
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,
114 TimeDelta time,
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,
127 const ViewId& id,
128 int cycle_count) {
129 group->view_id = ViewIdToTransportId(id);
130 group->sequences.push_back(AnimationSequence::New());
131 group->sequences[group->sequences.size() - 1]->cycle_count = cycle_count;
134 } // namespace
136 class AnimationRunnerTest : public testing::Test {
137 public:
138 AnimationRunnerTest()
139 : initial_time_(base::TimeTicks::Now()), runner_(initial_time_) {
140 runner_.AddObserver(&runner_observer_);
142 ~AnimationRunnerTest() override { runner_.RemoveObserver(&runner_observer_); }
144 protected:
145 // Convenience to schedule an animation for a single view/group pair.
146 AnimationRunner::AnimationId ScheduleForSingleView(
147 ServerView* view,
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_;
166 private:
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());
193 // Animate half way.
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
200 // be notified.
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),
224 AnimationValuePtr(),
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());
255 // To end.
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),
280 AnimationValuePtr(),
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
293 // transform.
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());
313 // To end.
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
324 // count of 3.
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();
385 // Animate half way.
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());
437 // Animate half way.
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),
494 AnimationValuePtr(),
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
506 // transform in it.
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),
526 AnimationValuePtr(),
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
548 // transform.
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));
570 // Animate to end.
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),
594 AnimationValuePtr(),
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
628 // changing.
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());
634 // Animate to end.
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