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/public/interfaces/view_manager/view_manager_constants.mo
jom.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 namespace mojo { |
| 17 namespace service { |
| 18 namespace { |
| 19 |
| 20 class TestAnimationRunnerObserver : public AnimationRunnerObserver { |
| 21 public: |
| 22 TestAnimationRunnerObserver() {} |
| 23 ~TestAnimationRunnerObserver() override {} |
| 24 |
| 25 std::vector<std::string>* changes() { return &changes_; } |
| 26 std::vector<uint32_t>* change_ids() { return &change_ids_; } |
| 27 |
| 28 void clear_changes() { |
| 29 changes_.clear(); |
| 30 change_ids_.clear(); |
| 31 } |
| 32 |
| 33 // AnimationRunnerDelgate: |
| 34 void OnAnimationScheduled(const ServerView* view, uint32_t id) override { |
| 35 change_ids_.push_back(id); |
| 36 changes_.push_back(base::StringPrintf( |
| 37 "scheduled view=%d,%d", view->id().connection_id, view->id().view_id)); |
| 38 } |
| 39 void OnAnimationDone(const ServerView* view, uint32_t id) override { |
| 40 change_ids_.push_back(id); |
| 41 changes_.push_back(base::StringPrintf( |
| 42 "done view=%d,%d", view->id().connection_id, view->id().view_id)); |
| 43 } |
| 44 void OnAnimationInterrupted(const ServerView* view, uint32_t id) override { |
| 45 change_ids_.push_back(id); |
| 46 changes_.push_back(base::StringPrintf( |
| 47 "interruped view=%d,%d", view->id().connection_id, view->id().view_id)); |
| 48 } |
| 49 void OnAnimationCanceled(const ServerView* view, uint32_t id) override { |
| 50 change_ids_.push_back(id); |
| 51 changes_.push_back(base::StringPrintf( |
| 52 "canceled view=%d,%d", view->id().connection_id, view->id().view_id)); |
| 53 } |
| 54 |
| 55 private: |
| 56 std::vector<uint32_t> change_ids_; |
| 57 std::vector<std::string> changes_; |
| 58 |
| 59 DISALLOW_COPY_AND_ASSIGN(TestAnimationRunnerObserver); |
| 60 }; |
| 61 |
| 62 } // namespace |
| 63 |
| 64 class AnimationRunnerTest : public testing::Test { |
| 65 public: |
| 66 AnimationRunnerTest() |
| 67 : initial_time_(base::TimeTicks::Now()), runner_(initial_time_) { |
| 68 runner_.AddObserver(&runner_observer_); |
| 69 } |
| 70 ~AnimationRunnerTest() override { runner_.RemoveObserver(&runner_observer_); } |
| 71 |
| 72 protected: |
| 73 const base::TimeTicks initial_time_; |
| 74 TestAnimationRunnerObserver runner_observer_; |
| 75 AnimationRunner runner_; |
| 76 |
| 77 private: |
| 78 DISALLOW_COPY_AND_ASSIGN(AnimationRunnerTest); |
| 79 }; |
| 80 |
| 81 // Opacity from 1 to .5 over 1000. |
| 82 TEST_F(AnimationRunnerTest, SingleProperty) { |
| 83 TestServerViewDelegate view_delegate; |
| 84 ServerView view(&view_delegate, ViewId()); |
| 85 |
| 86 AnimationGroup group; |
| 87 group.view_id = ViewIdToTransportId(view.id()); |
| 88 group.sequences.push_back(AnimationSequence::New()); |
| 89 AnimationSequence& sequence = *(group.sequences[0]); |
| 90 sequence.cycle_count = 1; |
| 91 sequence.elements.push_back(AnimationElement::New()); |
| 92 AnimationElement& element = *(sequence.elements[0]); |
| 93 element.property = ANIMATION_PROPERTY_OPACITY; |
| 94 element.duration = 1000; |
| 95 element.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 96 element.target_value = AnimationValue::New(); |
| 97 element.target_value->float_value = .5; |
| 98 |
| 99 const uint32_t animation_id = runner_.Schedule(&view, group); |
| 100 |
| 101 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 102 EXPECT_EQ("scheduled view=0,0", runner_observer_.changes()->at(0)); |
| 103 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 104 runner_observer_.clear_changes(); |
| 105 |
| 106 EXPECT_TRUE(runner_.HasAnimations()); |
| 107 |
| 108 // Opacity should still be 1 (the initial value). |
| 109 EXPECT_EQ(1.f, view.opacity()); |
| 110 |
| 111 // Animate half way. |
| 112 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(500)); |
| 113 |
| 114 EXPECT_EQ(.75f, view.opacity()); |
| 115 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 116 |
| 117 // Run well past the end. Value should progress to end and delegate should |
| 118 // be notified. |
| 119 runner_.Tick(initial_time_ + base::TimeDelta::FromSeconds(10)); |
| 120 EXPECT_EQ(.5f, view.opacity()); |
| 121 |
| 122 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 123 EXPECT_EQ("done view=0,0", runner_observer_.changes()->at(0)); |
| 124 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 125 |
| 126 EXPECT_FALSE(runner_.HasAnimations()); |
| 127 } |
| 128 |
| 129 // Opacity from 1 to .5, followed by transform from identity to 2x,3x. |
| 130 TEST_F(AnimationRunnerTest, TwoPropertiesInSequence) { |
| 131 TestServerViewDelegate view_delegate; |
| 132 ServerView view(&view_delegate, ViewId()); |
| 133 |
| 134 AnimationGroup group; |
| 135 group.view_id = ViewIdToTransportId(view.id()); |
| 136 group.sequences.push_back(AnimationSequence::New()); |
| 137 AnimationSequence& sequence = *(group.sequences[0]); |
| 138 sequence.cycle_count = 1; |
| 139 sequence.elements.push_back(AnimationElement::New()); |
| 140 AnimationElement& element = *(sequence.elements[0]); |
| 141 element.property = ANIMATION_PROPERTY_OPACITY; |
| 142 element.duration = 1000; |
| 143 element.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 144 element.target_value = AnimationValue::New(); |
| 145 element.target_value->float_value = .5; |
| 146 sequence.elements.push_back(AnimationElement::New()); |
| 147 AnimationElement& element2 = *(sequence.elements[1]); |
| 148 element2.property = ANIMATION_PROPERTY_TRANSFORM; |
| 149 element2.duration = 2000; |
| 150 element2.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 151 element2.target_value = AnimationValue::New(); |
| 152 gfx::Transform done_transform; |
| 153 done_transform.Scale(2, 4); |
| 154 element2.target_value->transform = Transform::From(done_transform); |
| 155 |
| 156 const uint32_t animation_id = runner_.Schedule(&view, group); |
| 157 runner_observer_.clear_changes(); |
| 158 |
| 159 // Nothing in the view should have changed yet. |
| 160 EXPECT_EQ(1.f, view.opacity()); |
| 161 EXPECT_TRUE(view.transform().IsIdentity()); |
| 162 |
| 163 // Animate half way from through opacity animation. |
| 164 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(500)); |
| 165 |
| 166 EXPECT_EQ(.75f, view.opacity()); |
| 167 EXPECT_TRUE(view.transform().IsIdentity()); |
| 168 |
| 169 // Finish first element (opacity). |
| 170 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(1000)); |
| 171 EXPECT_EQ(.5f, view.opacity()); |
| 172 EXPECT_TRUE(view.transform().IsIdentity()); |
| 173 |
| 174 // Half way through second (transform). |
| 175 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(2000)); |
| 176 EXPECT_EQ(.5f, view.opacity()); |
| 177 gfx::Transform half_way_transform; |
| 178 half_way_transform.Scale(1.5, 2.5); |
| 179 EXPECT_EQ(half_way_transform, view.transform()); |
| 180 |
| 181 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 182 |
| 183 // To end. |
| 184 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(3500)); |
| 185 EXPECT_EQ(.5f, view.opacity()); |
| 186 EXPECT_EQ(done_transform, view.transform()); |
| 187 |
| 188 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 189 EXPECT_EQ("done view=0,0", runner_observer_.changes()->at(0)); |
| 190 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 191 } |
| 192 |
| 193 // Opacity from .5 to 1 over 1000, transform to 2x,3x over 500. |
| 194 TEST_F(AnimationRunnerTest, TwoPropertiesInParallel) { |
| 195 TestServerViewDelegate view_delegate; |
| 196 ServerView view(&view_delegate, ViewId(1, 1)); |
| 197 |
| 198 AnimationGroup group; |
| 199 group.view_id = ViewIdToTransportId(view.id()); |
| 200 group.sequences.push_back(AnimationSequence::New()); |
| 201 AnimationSequence& sequence = *(group.sequences[0]); |
| 202 sequence.cycle_count = 1; |
| 203 sequence.elements.push_back(AnimationElement::New()); |
| 204 AnimationElement& element = *(sequence.elements[0]); |
| 205 element.property = ANIMATION_PROPERTY_OPACITY; |
| 206 element.duration = 1000; |
| 207 element.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 208 element.start_value = AnimationValue::New(); |
| 209 element.start_value->float_value = .5; |
| 210 element.target_value = AnimationValue::New(); |
| 211 element.target_value->float_value = 1; |
| 212 group.sequences.push_back(AnimationSequence::New()); |
| 213 AnimationSequence& sequence2 = *(group.sequences[1]); |
| 214 sequence2.cycle_count = 1; |
| 215 sequence2.elements.push_back(AnimationElement::New()); |
| 216 AnimationElement& element2 = *(sequence2.elements[0]); |
| 217 element2.property = ANIMATION_PROPERTY_TRANSFORM; |
| 218 element2.duration = 500; |
| 219 element2.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 220 element2.target_value = AnimationValue::New(); |
| 221 gfx::Transform done_transform; |
| 222 done_transform.Scale(2, 4); |
| 223 element2.target_value->transform = Transform::From(done_transform); |
| 224 |
| 225 const uint32_t animation_id = runner_.Schedule(&view, group); |
| 226 |
| 227 runner_observer_.clear_changes(); |
| 228 |
| 229 // Nothing in the view should have changed yet. |
| 230 EXPECT_EQ(1.f, view.opacity()); |
| 231 EXPECT_TRUE(view.transform().IsIdentity()); |
| 232 |
| 233 // Animate to 250, which is 1/4 way through opacity and half way through |
| 234 // transform. |
| 235 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(250)); |
| 236 |
| 237 EXPECT_EQ(.625f, view.opacity()); |
| 238 gfx::Transform half_way_transform; |
| 239 half_way_transform.Scale(1.5, 2.5); |
| 240 EXPECT_EQ(half_way_transform, view.transform()); |
| 241 |
| 242 // Animate to 500, which is 1/2 way through opacity and transform done. |
| 243 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(500)); |
| 244 EXPECT_EQ(.75f, view.opacity()); |
| 245 EXPECT_EQ(done_transform, view.transform()); |
| 246 |
| 247 // Animate to 750, which is 3/4 way through opacity and transform done. |
| 248 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(750)); |
| 249 EXPECT_EQ(.875f, view.opacity()); |
| 250 EXPECT_EQ(done_transform, view.transform()); |
| 251 |
| 252 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 253 |
| 254 // To end. |
| 255 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(3500)); |
| 256 EXPECT_EQ(1.f, view.opacity()); |
| 257 EXPECT_EQ(done_transform, view.transform()); |
| 258 |
| 259 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 260 EXPECT_EQ("done view=1,1", runner_observer_.changes()->at(0)); |
| 261 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 262 } |
| 263 |
| 264 // Opacity from .5 to 1 over 1000, pause for 500, 1 to .5 over 500, with a cycle |
| 265 // count of 3. |
| 266 TEST_F(AnimationRunnerTest, Cycles) { |
| 267 TestServerViewDelegate view_delegate; |
| 268 ServerView view(&view_delegate, ViewId(1, 2)); |
| 269 |
| 270 view.SetOpacity(.5f); |
| 271 |
| 272 AnimationGroup group; |
| 273 group.view_id = ViewIdToTransportId(view.id()); |
| 274 group.sequences.push_back(AnimationSequence::New()); |
| 275 AnimationSequence& sequence = *(group.sequences[0]); |
| 276 sequence.cycle_count = 3; |
| 277 sequence.elements.push_back(AnimationElement::New()); |
| 278 AnimationElement& element = *(sequence.elements[0]); |
| 279 element.property = ANIMATION_PROPERTY_OPACITY; |
| 280 element.duration = 1000; |
| 281 element.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 282 element.target_value = AnimationValue::New(); |
| 283 element.target_value->float_value = 1; |
| 284 sequence.elements.push_back(AnimationElement::New()); |
| 285 AnimationElement& element2 = *(sequence.elements[1]); |
| 286 element2.property = ANIMATION_PROPERTY_NONE; |
| 287 element2.duration = 500; |
| 288 sequence.elements.push_back(AnimationElement::New()); |
| 289 AnimationElement& element3 = *(sequence.elements[2]); |
| 290 element3.property = ANIMATION_PROPERTY_OPACITY; |
| 291 element3.duration = 500; |
| 292 element3.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 293 element3.target_value = AnimationValue::New(); |
| 294 element3.target_value->float_value = .5f; |
| 295 |
| 296 runner_.Schedule(&view, group); |
| 297 runner_observer_.clear_changes(); |
| 298 |
| 299 // Nothing in the view should have changed yet. |
| 300 EXPECT_EQ(.5f, view.opacity()); |
| 301 |
| 302 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(500)); |
| 303 EXPECT_EQ(.75f, view.opacity()); |
| 304 |
| 305 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(1250)); |
| 306 EXPECT_EQ(1.f, view.opacity()); |
| 307 |
| 308 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(1750)); |
| 309 EXPECT_EQ(.75f, view.opacity()); |
| 310 |
| 311 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(2500)); |
| 312 EXPECT_EQ(.75f, view.opacity()); |
| 313 |
| 314 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(3250)); |
| 315 EXPECT_EQ(1.f, view.opacity()); |
| 316 |
| 317 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(3750)); |
| 318 EXPECT_EQ(.75f, view.opacity()); |
| 319 |
| 320 // Animate to the end. |
| 321 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(6500)); |
| 322 EXPECT_EQ(.5f, view.opacity()); |
| 323 |
| 324 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 325 EXPECT_EQ("done view=1,2", runner_observer_.changes()->at(0)); |
| 326 } |
| 327 |
| 328 // Verifies scheduling the same view twice sends an interrupt. |
| 329 TEST_F(AnimationRunnerTest, ScheduleTwice) { |
| 330 TestServerViewDelegate view_delegate; |
| 331 ServerView view(&view_delegate, ViewId(1, 2)); |
| 332 |
| 333 AnimationGroup group; |
| 334 group.view_id = ViewIdToTransportId(view.id()); |
| 335 group.sequences.push_back(AnimationSequence::New()); |
| 336 AnimationSequence& sequence = *(group.sequences[0]); |
| 337 sequence.cycle_count = 1; |
| 338 sequence.elements.push_back(AnimationElement::New()); |
| 339 AnimationElement& element = *(sequence.elements[0]); |
| 340 element.property = ANIMATION_PROPERTY_OPACITY; |
| 341 element.duration = 1000; |
| 342 element.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 343 element.target_value = AnimationValue::New(); |
| 344 element.target_value->float_value = .5f; |
| 345 |
| 346 const uint32_t animation_id = runner_.Schedule(&view, group); |
| 347 runner_observer_.clear_changes(); |
| 348 |
| 349 // Animate half way. |
| 350 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(500)); |
| 351 |
| 352 EXPECT_EQ(.75f, view.opacity()); |
| 353 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 354 |
| 355 // Schedule again. We should get an interrupt, but opacity shouldn't change. |
| 356 const uint32_t animation2_id = runner_.Schedule(&view, group); |
| 357 |
| 358 // Id should have changed. |
| 359 EXPECT_NE(animation_id, animation2_id); |
| 360 |
| 361 EXPECT_EQ(nullptr, runner_.GetViewForAnimation(animation_id)); |
| 362 EXPECT_EQ(&view, runner_.GetViewForAnimation(animation2_id)); |
| 363 |
| 364 EXPECT_EQ(.75f, view.opacity()); |
| 365 EXPECT_EQ(2u, runner_observer_.changes()->size()); |
| 366 EXPECT_EQ("interruped view=1,2", runner_observer_.changes()->at(0)); |
| 367 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 368 EXPECT_EQ("scheduled view=1,2", runner_observer_.changes()->at(1)); |
| 369 EXPECT_EQ(animation2_id, runner_observer_.change_ids()->at(1)); |
| 370 runner_observer_.clear_changes(); |
| 371 |
| 372 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(1000)); |
| 373 EXPECT_EQ(.625f, view.opacity()); |
| 374 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 375 |
| 376 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(2000)); |
| 377 EXPECT_EQ(.5f, view.opacity()); |
| 378 EXPECT_EQ(1u, runner_observer_.changes()->size()); |
| 379 EXPECT_EQ("done view=1,2", runner_observer_.changes()->at(0)); |
| 380 EXPECT_EQ(animation2_id, runner_observer_.change_ids()->at(0)); |
| 381 } |
| 382 |
| 383 // Verifies Remove() works. |
| 384 TEST_F(AnimationRunnerTest, CancelAnimationForView) { |
| 385 // Create an animation and advance it part way. |
| 386 TestServerViewDelegate view_delegate; |
| 387 ServerView view(&view_delegate, ViewId()); |
| 388 AnimationGroup group; |
| 389 group.view_id = ViewIdToTransportId(view.id()); |
| 390 group.sequences.push_back(AnimationSequence::New()); |
| 391 AnimationSequence& sequence = *(group.sequences[0]); |
| 392 sequence.cycle_count = 1; |
| 393 sequence.elements.push_back(AnimationElement::New()); |
| 394 AnimationElement& element = *(sequence.elements[0]); |
| 395 element.property = ANIMATION_PROPERTY_OPACITY; |
| 396 element.duration = 1000; |
| 397 element.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 398 element.target_value = AnimationValue::New(); |
| 399 element.target_value->float_value = .5; |
| 400 |
| 401 const uint32_t animation_id = runner_.Schedule(&view, group); |
| 402 runner_observer_.clear_changes(); |
| 403 EXPECT_EQ(&view, runner_.GetViewForAnimation(animation_id)); |
| 404 |
| 405 EXPECT_TRUE(runner_.HasAnimations()); |
| 406 |
| 407 // Animate half way. |
| 408 runner_.Tick(initial_time_ + base::TimeDelta::FromMicroseconds(500)); |
| 409 EXPECT_EQ(.75f, view.opacity()); |
| 410 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 411 |
| 412 // Cancel the animation. |
| 413 runner_.CancelAnimationForView(&view); |
| 414 |
| 415 EXPECT_FALSE(runner_.HasAnimations()); |
| 416 EXPECT_EQ(nullptr, runner_.GetViewForAnimation(animation_id)); |
| 417 |
| 418 EXPECT_EQ(.75f, view.opacity()); |
| 419 |
| 420 EXPECT_EQ(1u, runner_observer_.changes()->size()); |
| 421 EXPECT_EQ("canceled view=0,0", runner_observer_.changes()->at(0)); |
| 422 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 423 } |
| 424 |
| 425 // Verifies a tick with a very large delta and a sequence that repeats forever |
| 426 // doesn't take a long time. |
| 427 TEST_F(AnimationRunnerTest, InfiniteRepeatWithHugeGap) { |
| 428 TestServerViewDelegate view_delegate; |
| 429 ServerView view(&view_delegate, ViewId(1, 2)); |
| 430 |
| 431 view.SetOpacity(.5f); |
| 432 |
| 433 AnimationGroup group; |
| 434 group.view_id = ViewIdToTransportId(view.id()); |
| 435 group.sequences.push_back(AnimationSequence::New()); |
| 436 AnimationSequence& sequence = *(group.sequences[0]); |
| 437 sequence.cycle_count = 0; // Repeats forever. |
| 438 sequence.elements.push_back(AnimationElement::New()); |
| 439 AnimationElement& element = *(sequence.elements[0]); |
| 440 element.property = ANIMATION_PROPERTY_OPACITY; |
| 441 element.duration = 500; |
| 442 element.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 443 element.target_value = AnimationValue::New(); |
| 444 element.target_value->float_value = 1; |
| 445 sequence.elements.push_back(AnimationElement::New()); |
| 446 AnimationElement& element2 = *(sequence.elements[1]); |
| 447 element2.property = ANIMATION_PROPERTY_OPACITY; |
| 448 element2.duration = 500; |
| 449 element2.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 450 element2.target_value = AnimationValue::New(); |
| 451 element2.target_value->float_value = .5f; |
| 452 |
| 453 runner_.Schedule(&view, group); |
| 454 runner_observer_.clear_changes(); |
| 455 |
| 456 runner_.Tick(initial_time_ + |
| 457 base::TimeDelta::FromMicroseconds(1000000000750)); |
| 458 |
| 459 EXPECT_EQ(.75f, view.opacity()); |
| 460 |
| 461 ASSERT_EQ(0u, runner_observer_.changes()->size()); |
| 462 } |
| 463 |
| 464 // Verifies a second schedule sets any properties that are no longer animating |
| 465 // to their final value. |
| 466 TEST_F(AnimationRunnerTest, RescheduleSetsPropertiesToFinalValue) { |
| 467 TestServerViewDelegate view_delegate; |
| 468 ServerView view(&view_delegate, ViewId()); |
| 469 |
| 470 AnimationGroup group; |
| 471 group.view_id = ViewIdToTransportId(view.id()); |
| 472 group.sequences.push_back(AnimationSequence::New()); |
| 473 AnimationSequence& sequence = *(group.sequences[0]); |
| 474 sequence.cycle_count = 1; |
| 475 sequence.elements.push_back(AnimationElement::New()); |
| 476 AnimationElement& element = *(sequence.elements[0]); |
| 477 element.property = ANIMATION_PROPERTY_OPACITY; |
| 478 element.duration = 1000; |
| 479 element.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 480 element.target_value = AnimationValue::New(); |
| 481 element.target_value->float_value = .5; |
| 482 sequence.elements.push_back(AnimationElement::New()); |
| 483 AnimationElement& element2 = *(sequence.elements[1]); |
| 484 element2.property = ANIMATION_PROPERTY_TRANSFORM; |
| 485 element2.duration = 500; |
| 486 element2.tween_type = ANIMATION_TWEEN_TYPE_LINEAR; |
| 487 element2.target_value = AnimationValue::New(); |
| 488 gfx::Transform done_transform; |
| 489 done_transform.Scale(2, 4); |
| 490 element2.target_value->transform = Transform::From(done_transform); |
| 491 runner_.Schedule(&view, group); |
| 492 |
| 493 // Schedule() again, this time without animating opacity. |
| 494 element.property = ANIMATION_PROPERTY_NONE; |
| 495 runner_.Schedule(&view, group); |
| 496 |
| 497 // Opacity should go to final value. |
| 498 EXPECT_EQ(.5f, view.opacity()); |
| 499 // Transform shouldn't have changed since newly scheduled animation also has |
| 500 // transform in it. |
| 501 EXPECT_TRUE(view.transform().IsIdentity()); |
| 502 } |
| 503 |
| 504 } // namespace service |
| 505 } // namespace mojo |
OLD | NEW |