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.h> 16 #include <gtest/gtest.h> 17 18 #include <meta/api/animation.h> 19 #include <meta/api/property/property_event_handler.h> 20 #include <meta/api/util.h> 21 #include <meta/base/namespace.h> 22 #include <meta/interface/animation/builtin_animations.h> 23 #include <meta/interface/animation/intf_animation_controller.h> 24 #include <meta/interface/property/construct_property.h> 25 26 #include "TestRunner.h" 27 #include "helpers/animation_test_base.h" 28 #include "helpers/serialisation_utils.h" 29 #include "helpers/testing_objects.h" 30 31 using namespace testing; 32 using namespace testing::ext; 33 34 META_BEGIN_NAMESPACE() 35 36 class AnimationControllerTest : public AnimationTestBase { 37 public: SetUpTestSuite()38 static void SetUpTestSuite() 39 { 40 SetTest(); 41 } TearDownTestSuite()42 static void TearDownTestSuite() 43 { 44 TearDownTest(); 45 } SetUp()46 void SetUp() override 47 { 48 AnimationTestBase::SetUp(); 49 50 property_ = META_NS::ConstructProperty<float>("prop", 0.f); 51 sutAnimationCtrl_ = META_NS::GetAnimationController(); 52 ASSERT_THAT(sutAnimationCtrl_, testing::NotNull()); 53 } 54 TearDown()55 void TearDown() override 56 { 57 auto count = GetValue(sutAnimationCtrl_->Count()); 58 59 sutAnimationCtrl_->Clear(); 60 61 count = GetValue(sutAnimationCtrl_->Count()); 62 63 ASSERT_EQ(sutAnimationCtrl_->GetRunning().size(), 0); 64 AnimationTestBase::TearDown(); 65 } 66 CreateAnimation()67 META_NS::KeyframeAnimation<float> CreateAnimation() 68 { 69 auto animation = META_NS::KeyframeAnimation<float>(CreateInstance(ClassId::KeyframeAnimation)); 70 animation.SetProperty(property_); 71 animation.SetFrom(0.f); 72 animation.SetTo(10.f); 73 animation.SetDuration(ANIMATION_LENGTH); 74 animation.SetController(sutAnimationCtrl_); 75 return animation; 76 } 77 78 static constexpr auto ANIMATION_LENGTH = TimeSpan::Milliseconds(100); 79 80 META_NS::Property<float> property_; 81 META_NS::IAnimationController::Ptr sutAnimationCtrl_; 82 }; 83 84 /** 85 * @tc.name: RunningAnimationListContainsStartedAnimations 86 * @tc.desc: test RunningAnimationListContainsStartedAnimations 87 * @tc.type: FUNC 88 */ 89 HWTEST_F(AnimationControllerTest, RunningAnimationListContainsStartedAnimations, TestSize.Level1) 90 { 91 // given 92 auto anim = CreateAnimation(); 93 94 // when 95 anim.Start(); 96 97 // expected 98 ASSERT_EQ(anim.GetRunning(), true); 99 const auto runningAnimations = sutAnimationCtrl_->GetRunning(); 100 ASSERT_THAT(runningAnimations.size(), testing::Eq(1)); 101 EXPECT_THAT(runningAnimations[0].lock(), testing::Eq(anim)); 102 } 103 104 /** 105 * @tc.name: RunningAnimationListIsEmptyWhenAllAnimationsWereStopped 106 * @tc.desc: test RunningAnimationListIsEmptyWhenAllAnimationsWereStopped 107 * @tc.type: FUNC 108 */ 109 HWTEST_F(AnimationControllerTest, RunningAnimationListIsEmptyWhenAllAnimationsWereStopped, TestSize.Level1) 110 { 111 // given 112 auto anim = CreateAnimation(); 113 114 // when 115 anim.Start(); 116 anim.Stop(); 117 118 // expected 119 ASSERT_EQ(anim.GetRunning(), false); 120 EXPECT_TRUE(sutAnimationCtrl_->GetRunning().empty()); 121 } 122 123 /** 124 * @tc.name: RunningAnimationListContainsResumedAnimations 125 * @tc.desc: test RunningAnimationListContainsResumedAnimations 126 * @tc.type: FUNC 127 */ 128 HWTEST_F(AnimationControllerTest, RunningAnimationListContainsResumedAnimations, TestSize.Level1) 129 { 130 // given 131 auto anim = CreateAnimation(); 132 133 // when 134 anim.Start(); 135 anim.Pause(); 136 anim.Start(); 137 138 // expected 139 ASSERT_EQ(anim.GetRunning(), true); 140 const auto runningAnimations = sutAnimationCtrl_->GetRunning(); 141 ASSERT_THAT(runningAnimations.size(), testing::Eq(1)); 142 EXPECT_THAT(runningAnimations[0].lock(), testing::Eq(anim)); 143 } 144 145 /** 146 * @tc.name: RunningAnimationListIsEmptyWhenAllAnimationsWereFinished 147 * @tc.desc: test RunningAnimationListIsEmptyWhenAllAnimationsWereFinished 148 * @tc.type: FUNC 149 */ 150 HWTEST_F(AnimationControllerTest, RunningAnimationListIsEmptyWhenAllAnimationsWereFinished, TestSize.Level1) 151 { 152 // given 153 auto anim = CreateAnimation(); 154 155 // when 156 anim.Start(); 157 StepAnimationController(0); 158 StepAnimationController(ANIMATION_LENGTH.ToMilliseconds()); 159 160 // expected 161 ASSERT_EQ(anim.GetRunning(), false); 162 ASSERT_EQ(anim.GetProgress(), 1.f); 163 EXPECT_TRUE(sutAnimationCtrl_->GetRunning().empty()); 164 } 165 166 /** 167 * @tc.name: AnimationControllerUpdatesControllerPropOfAddedAnimation 168 * @tc.desc: test AnimationControllerUpdatesControllerPropOfAddedAnimation 169 * @tc.type: FUNC 170 */ 171 HWTEST_F(AnimationControllerTest, AnimationControllerUpdatesControllerPropOfAddedAnimation, TestSize.Level1) 172 { 173 // given 174 auto anim = CreateAnimation(); 175 anim.SetController({}); 176 ASSERT_TRUE(anim.GetController().expired()); 177 178 // when 179 sutAnimationCtrl_->AddAnimation(anim); 180 181 // expected 182 ASSERT_FALSE(anim.GetController().expired()); 183 EXPECT_THAT(anim.GetController().lock(), testing::Eq(sutAnimationCtrl_)); 184 } 185 186 /** 187 * @tc.name: Serialization 188 * @tc.desc: test Serialization 189 * @tc.type: FUNC 190 */ 191 HWTEST_F(AnimationControllerTest, Serialization, TestSize.Level1) 192 { 193 TestSerialiser ser; 194 static constexpr auto implicitPropertyName = "ImplicitProperty"; 195 static constexpr auto keyframePropertyName = "KeyframeProperty"; 196 197 { 198 auto controller = GetObjectRegistry().Create<IAnimationController>(META_NS::ClassId::AnimationController); 199 200 auto implicitProp = ConstructProperty<float>(implicitPropertyName, 0); 201 auto keyframeProp = ConstructProperty<float>(keyframePropertyName, 0); 202 203 Object object(CreateInstance(ClassId::Object)); 204 Metadata(object).AddProperty(implicitProp); 205 Metadata(object).AddProperty(keyframeProp); 206 207 auto implicitAnim = PropertyAnimation(CreateInstance(ClassId::PropertyAnimation)) 208 .SetProperty(implicitProp) 209 .SetController(controller); 210 auto keyframeAnim = SequentialAnimation(CreateInstance(ClassId::SequentialAnimation)); 211 keyframeAnim.SetController(controller); 212 keyframeAnim.Add(KeyframeAnimation<float>(CreateInstance(ClassId::KeyframeAnimation)) 213 .SetFrom(0) 214 .SetTo(10) 215 .SetProperty(keyframeProp) 216 .SetDuration(TimeSpan::Milliseconds(100))); 217 keyframeAnim.Add(KeyframeAnimation<float>(CreateInstance(ClassId::KeyframeAnimation)) 218 .SetFrom(10) 219 .SetTo(0) 220 .SetProperty(keyframeProp) 221 .SetDuration(TimeSpan::Milliseconds(100))); 222 223 AttachmentContainer(object).Attach(implicitAnim); 224 AttachmentContainer(object).Attach(keyframeAnim); 225 AttachmentContainer(object).Attach(controller); 226 227 ASSERT_TRUE(ser.Export(object)); 228 ser.Dump("app://animation_ser.ui"); 229 } 230 231 auto obj = ser.Import(); 232 ASSERT_TRUE(obj); 233 Object imported(obj); 234 ASSERT_TRUE(imported); 235 236 auto controllers = 237 AttachmentContainer(imported).GetAttachments({ TypeId(META_NS::InterfaceId::IAnimationController) }); 238 ASSERT_EQ(controllers.size(), 1); 239 240 auto importedController = interface_pointer_cast<IAnimationController>(controllers[0]); 241 EXPECT_EQ(importedController->Count()->GetValue(), 2); 242 243 auto animations = importedController->GetAnimations(); 244 ASSERT_EQ(animations.size(), 2); 245 246 for (const auto& anim : animations) { 247 auto animation = anim.lock(); 248 ASSERT_TRUE(animation); 249 auto controller = animation->Controller()->GetValue().lock(); 250 EXPECT_EQ(controller, importedController); 251 } 252 253 // Check that we got the same animation hierarchy back 254 PropertyAnimation implicitAnim(animations[0].lock()); 255 SequentialAnimation seqAnim(animations[1].lock()); 256 ASSERT_TRUE(implicitAnim); 257 ASSERT_TRUE(seqAnim); 258 auto children = seqAnim.GetAnimations(); 259 ASSERT_EQ(children.size(), 2); 260 KeyframeAnimation<float> segment1(children[0]); 261 ASSERT_TRUE(segment1); 262 EXPECT_TRUE(segment1.GetValid()); 263 264 // Start the sequential animation and check that it works 265 seqAnim.Start(); 266 importedController->Step(GetTestClock()); 267 268 EXPECT_TRUE(seqAnim.GetRunning()); 269 EXPECT_EQ(seqAnim.GetProgress(), 0); 270 auto progress = seqAnim.GetProgress(); 271 272 for (auto i = 0; i < 5; i++) { 273 IncrementClockTime(TimeSpan::Milliseconds(10)); 274 importedController->Step(GetTestClock()); 275 auto current = seqAnim.GetProgress(); 276 EXPECT_GT(current, progress); 277 progress = current; 278 } 279 } 280 281 META_END_NAMESPACE() 282