1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <gmock/gmock-matchers.h>
16 #include <gtest/gtest.h>
17
18 #include <meta/api/animation.h>
19 #include <meta/interface/property/construct_property.h>
20 #include <meta/interface/property/property.h>
21
22 #include "TestRunner.h"
23 #include "helpers/animation_test_base.h"
24 #include "helpers/serialisation_utils.h"
25 #include "helpers/test_utils.h"
26 #include "helpers/testing_objects.h"
27
28 using namespace testing;
29 using namespace testing::ext;
30
31 META_BEGIN_NAMESPACE()
32
33 class AnimationModifierTestBase;
34
35 namespace {
36 struct TestDefinition {
37 std::string name;
38 std::function<IAnimation::Ptr(AnimationModifierTestBase&)> constructor;
__anonab38eef20202__anonab38eef20111::TestDefinition39 std::function<IAnimation::Ptr(AnimationModifierTestBase& test, IAnimation::Ptr)> transform = [](auto&, auto p) {
40 return p;
41 };
42 };
43
44 } // namespace
45
46 class AnimationModifierTestBase : public AnimationTestBase,
47 public ::testing::WithParamInterface<std::tuple<TestDefinition, int>> {
48 public:
SetUpTestSuite()49 static void SetUpTestSuite()
50 {
51 SetTest();
52 }
TearDownTestSuite()53 static void TearDownTestSuite()
54 {
55 TearDownTest();
56 }
SetUp()57 void SetUp() override
58 {
59 AnimationTestBase::SetUp();
60 }
61
TearDown()62 void TearDown() override
63 {
64 keepAliveProperties.clear();
65 AnimationTestBase::TearDown();
66 }
67
GetAnimation()68 IAnimation::Ptr GetAnimation()
69 {
70 return std::get<0>(GetParam()).constructor(*this);
71 }
72
Transform(IAnimation::Ptr p)73 IAnimation::Ptr Transform(IAnimation::Ptr p)
74 {
75 return std::get<0>(GetParam()).transform(*this, p);
76 }
77
78 BASE_NS::vector<META_NS::IProperty::Ptr> keepAliveProperties;
79 };
80
81 /**
82 * @tc.name: ReverseImplicitAnimation
83 * @tc.desc: test ReverseImplicitAnimation
84 * @tc.type: FUNC
85 */
86 HWTEST_F(AnimationModifierTestBase, ReverseImplicitAnimation, TestSize.Level1)
87 {
88 auto animation = META_NS::PropertyAnimation(CreateInstance(ClassId::PropertyAnimation));
89 constexpr auto start = 10.0f;
90 constexpr auto to = 20.0f;
91
92 auto property = META_NS::ConstructProperty<float>("test", start);
93
94 animation.SetProperty(property);
95 animation.SetDuration(META_NS::TimeSpan::Milliseconds(100));
96 animation.AddModifier(META_NS::AnimationModifiers::Reverse(CreateInstance(ClassId::ReverseAnimationModifier)));
97
98 property->SetValue(to);
99
100 EXPECT_TRUE(animation.GetRunning());
101 animation.Step(GetTestClock());
102
103 bool finished = false;
__anonab38eef20302null104 animation.OnFinished()->AddHandler(MakeCallback<IOnChanged>([&] { finished = true; }));
105
__anonab38eef20402(uint32_t frame) 106 StepAnimations({ animation }, 10, [&](uint32_t frame) {
107 auto progress = animation.GetProgress();
108 EXPECT_EQ(progress, frame / 10.f) << "Frame: " << frame;
109
110 auto value = GetValue(property);
111 EXPECT_EQ(value, start + (1.f - progress) * (to - start)) << "Frame: " << frame;
112 });
113
114 EXPECT_FALSE(animation.GetRunning());
115 EXPECT_EQ(animation.GetProgress(), 1.f);
116 EXPECT_TRUE(finished);
117 }
118
119 class LoopAnimationModifierTest : public AnimationModifierTestBase {
120 public:
SetUpTestSuite()121 static void SetUpTestSuite()
122 {
123 SetTest();
124 }
TearDownTestSuite()125 static void TearDownTestSuite()
126 {
127 TearDownTest();
128 }
GetLoopCount()129 int GetLoopCount()
130 {
131 return std::get<1>(GetParam());
132 }
133 };
134
135 class SpeedAnimationModifierTest : public AnimationModifierTestBase {
136 public:
SetUpTestSuite()137 static void SetUpTestSuite()
138 {
139 SetTest();
140 }
TearDownTestSuite()141 static void TearDownTestSuite()
142 {
143 TearDownTest();
144 }
GetSpeedFactor()145 float GetSpeedFactor()
146 {
147 return std::get<1>(GetParam()) / 10.f;
148 }
149 };
150
StartOrSetPropertyValue(IAnimation::Ptr anim)151 static void StartOrSetPropertyValue(IAnimation::Ptr anim)
152 {
153 if (auto startable = interface_cast<IStartableAnimation>(anim)) {
154 startable->Start();
155 } else if (auto p = interface_cast<IPropertyAnimation>(anim)) {
156 Property<float> prop(p->Property()->GetValue().lock());
157 if (prop) {
158 prop->SetValue(20.0f);
159 }
160 }
161 }
162
163 class ReverseAnimationModifierTest : public AnimationModifierTestBase {
164 public:
SetUpTestSuite()165 static void SetUpTestSuite()
166 {
167 SetTest();
168 }
TearDownTestSuite()169 static void TearDownTestSuite()
170 {
171 TearDownTest();
172 }
GetFrameCount() const173 int GetFrameCount() const
174 {
175 return std::get<1>(GetParam());
176 }
177
CollectFrames(const META_NS::IAnimation::Ptr & anim)178 BASE_NS::vector<BASE_NS::vector<float>> CollectFrames(const META_NS::IAnimation::Ptr& anim)
179 {
180 const auto frames = GetFrameCount();
181 const auto millisPerFrame = GetValue(anim->TotalDuration()).ToMilliseconds() / frames;
182 BASE_NS::vector<BASE_NS::vector<float>> propsValues(keepAliveProperties.size(), {});
183
184 auto recordFrame = [this](BASE_NS::vector<BASE_NS::vector<float>>& out) {
185 int i = 0;
186 for (const auto& prop : keepAliveProperties) {
187 out[i++].push_back(GetValue<float>(prop));
188 }
189 };
190
191 if (auto startable = interface_cast<IStartableAnimation>(anim)) {
192 startable->Restart();
193 }
194 anim->Step(GetTestClock());
195 recordFrame(propsValues);
196 StepAnimations(
197 { anim },
198 frames,
199 millisPerFrame,
200 [&propsValues, recordFrame](int frame) {
201 recordFrame(propsValues);
202 });
203
204 return propsValues;
205 }
206 };
207
BuildTestName(const testing::TestParamInfo<LoopAnimationModifierTest::ParamType> & info)208 std::string BuildTestName(const testing::TestParamInfo<LoopAnimationModifierTest::ParamType>& info)
209 {
210 return std::get<0>(info.param).name + "Animation" + std::to_string(info.index);
211 }
212
CreateKeyFrameAnimation(AnimationModifierTestBase & test)213 IAnimation::Ptr CreateKeyFrameAnimation(AnimationModifierTestBase& test)
214 {
215 KeyframeAnimation<float> animation(CreateInstance(ClassId::KeyframeAnimation));
216
217 auto start = 10.0f;
218 float to = 20.0f;
219
220 auto property = ConstructProperty<float>("test", 5.0f);
221 test.keepAliveProperties.push_back(property);
222
223 animation.SetFrom(start);
224 animation.SetTo(to);
225 animation.SetDuration(TimeSpan::Milliseconds(1000)); // 1000: param
226 animation.SetProperty(property);
227
228 return animation;
229 }
230
CreatePropertyAnimation(AnimationModifierTestBase & test)231 IAnimation::Ptr CreatePropertyAnimation(AnimationModifierTestBase& test)
232 {
233 auto animation = PropertyAnimation(CreateInstance(ClassId::PropertyAnimation));
234 auto start = 10.0f;
235 float to = 20.0f;
236
237 auto property = ConstructProperty<float>("test", start);
238 test.keepAliveProperties.push_back(property);
239
240 animation.SetProperty(property);
241 animation.SetDuration(TimeSpan::Milliseconds(1000)); // 1000: param
242
243 return animation;
244 }
245
CreateTrackAnimation(AnimationModifierTestBase & test)246 IAnimation::Ptr CreateTrackAnimation(AnimationModifierTestBase& test)
247 {
248 BASE_NS::vector<float> timestamps = { 0.1f, 0.3f, 0.8f, 1.f };
249 BASE_NS::vector<float> keyframes = { 50.0f, 100.0f, 170.0f, 190.0f };
250 const float initialValue = 10.0f;
251
252 auto property = ConstructProperty<float>("Prop", initialValue);
253 test.keepAliveProperties.push_back(property);
254
255 BASE_NS::array_view<float> kf = keyframes;
256
257 auto animation = TrackAnimation<float>(CreateInstance(ClassId::TrackAnimation))
258 .SetKeyframes(keyframes)
259 .SetTimestamps(timestamps)
260 .SetProperty(property)
261 .SetDuration(TimeSpan::Milliseconds(1000));
262
263 return animation;
264 }
265
CreateParallelAnimation(AnimationModifierTestBase & test)266 IAnimation::Ptr CreateParallelAnimation(AnimationModifierTestBase& test)
267 {
268 auto anim1 = CreateKeyFrameAnimation(test);
269 auto anim2 = CreateTrackAnimation(test);
270
271 auto staggered = ParallelAnimation(CreateInstance(ClassId::ParallelAnimation)).Add(anim1).Add(anim2);
272
273 return staggered;
274 }
275
CreateSequentialAnimation(AnimationModifierTestBase & test)276 IAnimation::Ptr CreateSequentialAnimation(AnimationModifierTestBase& test)
277 {
278 auto anim1 = CreateKeyFrameAnimation(test);
279 auto anim2 = CreateTrackAnimation(test);
280
281 auto staggered = SequentialAnimation(CreateInstance(ClassId::SequentialAnimation)).Add(anim1).Add(anim2);
282
283 return staggered;
284 }
285
Serialize(AnimationModifierTestBase & test,IAnimation::Ptr anim)286 IAnimation::Ptr Serialize(AnimationModifierTestBase& test, IAnimation::Ptr anim)
287 {
288 TestSerialiser ser;
289
290 {
291 Object obj(CreateInstance(ClassId::Object));
292 AttachmentContainer(obj).Attach(interface_pointer_cast<IAttachment>(anim));
293
294 for (auto&& v : test.keepAliveProperties) {
295 Metadata(obj).AddProperty(v);
296 }
297
298 ser.Export(obj);
299 }
300 test.keepAliveProperties.clear();
301
302 auto meta = ser.Import<IMetadata>();
303 for (auto& p : meta->GetProperties()) {
304 test.keepAliveProperties.push_back(p);
305 }
306 if (auto att = interface_pointer_cast<IAttach>(meta)) {
307 auto vec = att->GetAttachments<IAnimation>();
308 return vec.empty() ? nullptr : vec[0];
309 }
310 return nullptr;
311 }
312
313 /**
314 * @tc.name: ReversedAnimationIsPlayedBackward
315 * @tc.desc: test ReversedAnimationIsPlayedBackward
316 * @tc.type: FUNC
317 */
318 HWTEST_P(ReverseAnimationModifierTest, ReversedAnimationIsPlayedBackward, TestSize.Level1)
319 {
320 using ::testing::FloatNear;
321 using ::testing::Pointwise;
322
323 auto anim = GetAnimation();
324 const auto forwardFrames = CollectFrames(anim);
325 {
326 auto reverse = AnimationModifiers::Reverse(CreateInstance(ClassId::ReverseAnimationModifier));
327 auto attach = interface_pointer_cast<IAttach>(anim);
328 attach->Attach(interface_pointer_cast<IObject>(reverse));
329 }
330 anim = Transform(anim);
331 ASSERT_TRUE(anim);
332
333 const auto reverseFrames = CollectFrames(anim);
334
335 for (decltype(forwardFrames.size()) i = 0, end = forwardFrames.size(); i < end; ++i) {
336 EXPECT_THAT(
337 reverseFrames[i], Pointwise(FloatNear(0.001),
338 decltype(forwardFrames[i]) { forwardFrames[i].rbegin(), forwardFrames[i].rend() }))
339 << "i: " << i;
340 }
341 }
342
GetAnimAttachment(IAnimation::Ptr anim)343 static IObject::Ptr GetAnimAttachment(IAnimation::Ptr anim)
344 {
345 auto attach = interface_pointer_cast<IAttach>(anim);
346 auto vec = attach->GetAttachments<IAnimationModifier>();
347 return vec.empty() ? nullptr : interface_pointer_cast<IObject>(vec[0]);
348 }
349
350 /**
351 * @tc.name: LoopCountModifiesDuration
352 * @tc.desc: test LoopCountModifiesDuration
353 * @tc.type: FUNC
354 */
355 HWTEST_P(LoopAnimationModifierTest, LoopCountModifiesDuration, TestSize.Level1)
356 {
357 auto anim = GetAnimation();
358 int loopCount = GetLoopCount();
359 auto originalDuration = GetValue(anim->TotalDuration());
360
361 {
362 auto loop = AnimationModifiers::Loop(CreateInstance(ClassId::LoopAnimationModifier)).SetLoopCount(loopCount);
363 auto attach = interface_pointer_cast<IAttach>(anim);
364 EXPECT_TRUE(attach->Attach(interface_pointer_cast<IObject>(loop)));
365 }
366
367 anim = Transform(anim);
368 ASSERT_TRUE(anim);
369 AnimationModifiers::Loop loop(GetAnimAttachment(anim));
370 ASSERT_TRUE(loop);
371
372 EXPECT_EQ(GetValue(anim->TotalDuration()), loopCount * originalDuration);
373 loop.SetLoopCount(loopCount * 2);
374 EXPECT_EQ(GetValue(anim->TotalDuration()), loopCount * 2 * originalDuration);
375 loop.SetLoopCount(loopCount);
376 EXPECT_EQ(GetValue(anim->TotalDuration()), loopCount * originalDuration);
377
378 loop.SetLoopCount(-1);
379 EXPECT_EQ(GetValue(anim->TotalDuration()), TimeSpan::Infinite());
380 }
381
382 /**
383 * @tc.name: AnimationIsLoopingRegardlessOfSpeedModificator
384 * @tc.desc: test AnimationIsLoopingRegardlessOfSpeedModificator
385 * @tc.type: FUNC
386 */
387 HWTEST_P(LoopAnimationModifierTest, AnimationIsLoopingRegardlessOfSpeedModificator, TestSize.Level1)
388 {
389 static constexpr int64_t frameStepMs = 10;
390 static constexpr float speedFactor = 2.7;
391 const auto expectedLoops = GetLoopCount();
392 auto anim = GetAnimation();
393 const auto animPlayTime = (static_cast<float>(GetValue(anim->TotalDuration()).ToMilliseconds()) / speedFactor) *
394 static_cast<float>(expectedLoops);
395 const auto animTotalFrames = static_cast<int64_t>(animPlayTime) / frameStepMs;
396
397 {
398 const auto attach = interface_pointer_cast<META_NS::IAttach>(anim);
399 attach->Attach(META_NS::AnimationModifiers::Loop(CreateNew).LoopIndefinitely().GetPtr());
400 attach->Attach(META_NS::AnimationModifiers::Speed(CreateNew).SetSpeedFactor(speedFactor).GetPtr());
401 }
402 anim = Transform(anim);
403 ASSERT_TRUE(anim);
404
405 uint32_t actualLoops = 0;
406 auto previousProgress = GetValue(anim->Progress());
407 StartOrSetPropertyValue(anim);
__anonab38eef20702(uint32_t frame) 408 StepAnimations({ anim }, animTotalFrames, frameStepMs, [&](uint32_t frame) {
409 actualLoops = actualLoops == 0 ? 1 : actualLoops;
410 const auto currentProgress = GetValue(anim->Progress());
411 if (previousProgress > currentProgress) {
412 ++actualLoops;
413 }
414 previousProgress = currentProgress;
415 });
416
417 EXPECT_EQ(actualLoops, expectedLoops);
418 }
419
420 /**
421 * @tc.name: AnimationIslooping
422 * @tc.desc: test AnimationIslooping
423 * @tc.type: FUNC
424 */
425 HWTEST_P(LoopAnimationModifierTest, AnimationIslooping, TestSize.Level1)
426 {
427 auto anim = GetAnimation();
428 int loopCount = GetLoopCount();
429 auto originalDuration = GetValue(anim->TotalDuration());
430
431 // Don't test zero loopcount
432 if (loopCount == 0) {
433 return;
434 }
435
436 // round up
437 const int frames = (originalDuration.ToMilliseconds() + 9) / 10;
438 const int totalFrames = frames * loopCount;
439
440 EXPECT_TRUE(GetValue(anim->Valid()));
441 {
442 auto loop =
443 META_NS::AnimationModifiers::Loop(CreateInstance(ClassId::LoopAnimationModifier)).SetLoopCount(loopCount);
444 auto attach = interface_pointer_cast<META_NS::IAttach>(anim);
445 attach->Attach(loop.GetPtr());
446 }
447
448 anim = Transform(anim);
449 ASSERT_TRUE(anim);
450
451 EXPECT_TRUE(GetValue(anim->Valid()));
452
453 StartOrSetPropertyValue(anim);
454 anim->Step(GetTestClock());
455
456 EXPECT_TRUE(GetValue(anim->Valid()));
457 EXPECT_TRUE(GetValue(anim->Running()));
458
459 for (int i = 0; i < loopCount; ++i) {
460 const int frameOffset = i * 10;
461 EXPECT_TRUE(GetValue(anim->Running()));
462 auto previousProgress = 0.f;
463
__anonab38eef20802(int frame) 464 StepAnimations({ anim }, frames, [&](int frame) {
465 frame = i * frames + frame;
466 auto progress = GetValue(anim->Progress());
467 if (i == (loopCount - 1) && frame == totalFrames) {
468 // Last frame
469 ASSERT_FALSE(GetValue(anim->Running())) << "Frame " << frame;
470 } else {
471 ASSERT_TRUE(GetValue(anim->Running())) << "Frame " << frame;
472 ASSERT_GT(progress, previousProgress) << "Frame " << frame;
473 }
474
475 previousProgress = progress;
476 });
477 }
478
479 ASSERT_FALSE(GetValue(anim->Running()));
480
481 // Animation is stopped, it should not advance any further
482 for (int i = 0; i < 10; ++i) {
483 IncrementClockTime(META_NS::TimeSpan::Milliseconds(10));
484 anim->Step(GetTestClock());
485
486 EXPECT_FALSE(GetValue(anim->Running()));
487 EXPECT_FLOAT_EQ(1.0f, GetValue(anim->Progress()));
488 }
489 }
490
491 /**
492 * @tc.name: DuplicateProperties
493 * @tc.desc: test DuplicateProperties
494 * @tc.type: FUNC
495 */
496 HWTEST_P(LoopAnimationModifierTest, DuplicateProperties, TestSize.Level1)
497 {
498 auto animation = GetAnimation();
499 animation = Transform(animation);
500
501 auto meta = interface_pointer_cast<META_NS::IMetadata>(animation);
502
503 for (const auto& prop : meta->GetProperties()) {
504 for (const auto& rhs : meta->GetProperties()) {
505 if (prop == rhs) {
506 continue;
507 }
508
509 ASSERT_NE(prop->GetName(), rhs->GetName());
510 }
511 }
512 }
513
514 /**
515 * @tc.name: SpeedFactorModifiesDuration
516 * @tc.desc: test SpeedFactorModifiesDuration
517 * @tc.type: FUNC
518 */
519 HWTEST_P(SpeedAnimationModifierTest, SpeedFactorModifiesDuration, TestSize.Level1)
520 {
521 auto anim = GetAnimation();
522 float speedFactor = GetSpeedFactor();
523 auto originalDuration = GetValue(anim->TotalDuration());
524 auto expectedDuration = originalDuration / BASE_NS::Math::abs(speedFactor);
525
526 {
527 auto speedModifier = META_NS::AnimationModifiers::Speed(CreateNew).SetSpeedFactor(speedFactor);
528 auto attach = interface_pointer_cast<META_NS::IAttach>(anim);
529 ASSERT_TRUE(attach->Attach(speedModifier.GetPtr()));
530 }
531 anim = Transform(anim);
532 ASSERT_TRUE(anim);
533 META_NS::AnimationModifiers::Speed speedModifier(GetAnimAttachment(anim));
534 ASSERT_TRUE(speedModifier);
535
536 EXPECT_TRUE(GetValue(anim->Valid()));
537
538 EXPECT_EQ(GetValue(anim->TotalDuration()), expectedDuration);
539
540 // Change speed factor, total duration should follow
541 speedModifier.SetSpeedFactor(speedFactor * 2);
542 EXPECT_EQ(GetValue(anim->TotalDuration()).ToMilliseconds(), (expectedDuration / 2).ToMilliseconds());
543 speedModifier.SetSpeedFactor(speedFactor);
544 EXPECT_EQ(GetValue(anim->TotalDuration()), expectedDuration);
545
546 speedModifier.SetSpeedFactor(-speedFactor * 2);
547 EXPECT_EQ(GetValue(anim->TotalDuration()).ToMilliseconds(), (expectedDuration / 2).ToMilliseconds());
548 speedModifier.SetSpeedFactor(-speedFactor);
549 EXPECT_EQ(GetValue(anim->TotalDuration()), expectedDuration);
550
551 speedModifier.SetSpeedFactor(0);
552 EXPECT_EQ(GetValue(anim->TotalDuration()), TimeSpan::Infinite());
553 }
554
555 /**
556 * @tc.name: SpeedFactorAffectsPlayback
557 * @tc.desc: test SpeedFactorAffectsPlayback
558 * @tc.type: FUNC
559 */
560 HWTEST_P(SpeedAnimationModifierTest, SpeedFactorAffectsPlayback, TestSize.Level1)
561 {
562 auto anim = GetAnimation();
563 const float speedFactor = GetSpeedFactor();
564 if (speedFactor == 0.f) {
565 return;
566 }
567
568 auto originalDuration = GetValue(anim->TotalDuration());
569 auto expectedDuration = originalDuration / BASE_NS::Math::abs(speedFactor);
570
571 {
572 auto speedModifier = META_NS::AnimationModifiers::Speed(CreateInstance(ClassId::SpeedAnimationModifier))
573 .SetSpeedFactor(speedFactor);
574
575 auto attach = interface_pointer_cast<META_NS::IAttach>(anim);
576 ASSERT_NE(attach, nullptr);
577 attach->Attach(speedModifier.GetPtr());
578 }
579 anim = Transform(anim);
580 ASSERT_TRUE(anim);
581 META_NS::AnimationModifiers::Speed speedModifier(GetAnimAttachment(anim));
582 ASSERT_TRUE(speedModifier);
583
584 EXPECT_TRUE(GetValue(anim->Valid()));
585
586 StartOrSetPropertyValue(anim);
587
588 EXPECT_TRUE(GetValue(anim->Valid()));
589 EXPECT_TRUE(GetValue(anim->Running()));
590 anim->Step(GetTestClock());
591
592 if (speedFactor == 0.f) {
593 EXPECT_EQ(GetValue(anim->TotalDuration()), META_NS::TimeSpan::Infinite());
594 EXPECT_EQ(GetValue(anim->Progress()), 0);
595 return;
596 }
597 // Figure out how many milliseconds we must progress at each frame
598 // to cover the whole animation in 10 frames
599 int64_t millisPerFrame =
600 BASE_NS::Math::round(static_cast<float>(GetValue(anim->TotalDuration()).ToMilliseconds()) / 10.f);
601 EXPECT_EQ(millisPerFrame, (expectedDuration / 10).ToMilliseconds());
602
603 float previousProgress = GetValue(anim->Progress());
604 EXPECT_EQ(previousProgress, 0);
605
__anonab38eef20902(int frame) 606 StepAnimations({ anim }, 10, millisPerFrame, [millisPerFrame, &anim, &previousProgress](int frame) {
607 float progress = GetValue(anim->Progress());
608 EXPECT_GT(progress, previousProgress);
609 EXPECT_NEAR(progress, frame / 10.f, 0.05);
610 previousProgress = progress;
611 });
612
613 // Animation is stopped, it should not advance any further
__anonab38eef20a02(int frame) 614 StepAnimations({ anim }, 10, millisPerFrame, [millisPerFrame, &anim, &previousProgress](int frame) {
615 EXPECT_FALSE(GetValue(anim->Running()));
616 EXPECT_FLOAT_EQ(1.0f, GetValue(anim->Progress()));
617 });
618 }
619
620 INSTANTIATE_TEST_SUITE_P(LoopAnimationModifierSuite, LoopAnimationModifierTest,
621 testing::Combine(
622 testing::Values(TestDefinition { "Keyframe", CreateKeyFrameAnimation },
623 TestDefinition { "Track", CreateTrackAnimation }, TestDefinition { "Parallel", CreateParallelAnimation },
624 TestDefinition { "Sequential", CreateSequentialAnimation },
625 TestDefinition { "Property", CreatePropertyAnimation },
626 TestDefinition { "KeyframeSerialize", CreateKeyFrameAnimation, Serialize },
627 TestDefinition { "TrackSerialize", CreateTrackAnimation, Serialize },
628 TestDefinition { "ParallelSerialize", CreateParallelAnimation, Serialize },
629 TestDefinition { "SequentialSerialize", CreateSequentialAnimation, Serialize },
630 TestDefinition { "PropertySerialize", CreatePropertyAnimation, Serialize }),
631 testing::Range(1, 10)),
632 BuildTestName);
633
634 INSTANTIATE_TEST_SUITE_P(SpeedAnimationModifierSuite, SpeedAnimationModifierTest,
635 testing::Combine(
636 testing::Values(TestDefinition { "Keyframe", CreateKeyFrameAnimation },
637 TestDefinition { "Track", CreateTrackAnimation }, TestDefinition { "Parallel", CreateParallelAnimation },
638 TestDefinition { "Sequential", CreateSequentialAnimation },
639 TestDefinition { "Property", CreatePropertyAnimation },
640 TestDefinition { "KeyframeSerialize", CreateKeyFrameAnimation, Serialize },
641 TestDefinition { "TrackSerialize", CreateTrackAnimation, Serialize },
642 TestDefinition { "ParallelSerialize", CreateParallelAnimation, Serialize },
643 TestDefinition { "SequentialSerialize", CreateSequentialAnimation, Serialize },
644 TestDefinition { "PropertySerialize", CreatePropertyAnimation, Serialize }),
645 testing::Range(-20, 20, 5)),
646 BuildTestName);
647
648 INSTANTIATE_TEST_SUITE_P(ReverseAnimationModifierSuite, ReverseAnimationModifierTest,
649 testing::Combine(
650 testing::Values(TestDefinition { "Keyframe", CreateKeyFrameAnimation },
651 TestDefinition { "Track", CreateTrackAnimation }, TestDefinition { "Parallel", CreateParallelAnimation },
652 TestDefinition { "KeyframeSerialize", CreateKeyFrameAnimation, Serialize },
653 TestDefinition { "TrackSerialize", CreateTrackAnimation, Serialize },
654 TestDefinition { "ParallelSerialize", CreateParallelAnimation, Serialize }),
655 testing::Range(10, 20, 10)),
656 BuildTestName);
657
658 META_END_NAMESPACE()
659