• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/animation/intf_animation_controller.h>
20 #include <meta/interface/property/construct_property.h>
21 #include <meta/interface/property/property.h>
22 
23 #include "TestRunner.h"
24 #include "helpers/animation_test_base.h"
25 #include "helpers/serialisation_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 AnimationTest : public AnimationTestBase {
34 protected:
SetUpTestSuite()35     static void SetUpTestSuite()
36     {
37         SetTest();
38     }
TearDownTestSuite()39     static void TearDownTestSuite()
40     {
41         TearDownTest();
42     }
CreateAnimation(const META_NS::ClassInfo & classId)43     IPropertyAnimation::Ptr CreateAnimation(const META_NS::ClassInfo& classId)
44     {
45         auto pani = GetObjectRegistry().Create<IPropertyAnimation>(classId);
46         if (auto ani = interface_cast<IAnimation>(pani)) {
47             ani->OnStarted()->AddHandler(MakeCallback<IOnChanged>([this]() { startedCalled_++; }));
48             ani->OnFinished()->AddHandler(MakeCallback<IOnChanged>([this]() { finishedCalled_++; }));
49         }
50         return pani;
51     }
52 
GetStartedCalledCount() const53     auto GetStartedCalledCount() const
54     {
55         return startedCalled_;
56     }
GetFinishedCalledCount() const57     auto GetFinishedCalledCount() const
58     {
59         return finishedCalled_;
60     }
61 
62 private:
63     size_t startedCalled_ {};
64     size_t finishedCalled_ {};
65 };
66 
67 HWTEST_F(AnimationTest, KeyframeAnimation, TestSize.Level1)
68 {
69     auto p = ConstructProperty<int>("test");
70     auto pani = CreateAnimation(ClassId::KeyframeAnimation);
71     ASSERT_TRUE(pani);
72     auto pp = pani->Property();
73     ASSERT_TRUE(pp);
74     pp->SetValue(p);
75 
76     auto ani = interface_pointer_cast<IKeyframeAnimation>(pani);
77     ASSERT_TRUE(ani);
78     ani->From()->SetValue(IAny::Ptr(new Any<int>(0)));
79     ani->To()->SetValue(IAny::Ptr(new Any<int>(10)));
80     ani->Duration()->SetValue(TimeSpan::Milliseconds(100));
81 
82     auto st = interface_pointer_cast<IStartableAnimation>(pani);
83 
84     st->Start();
85 
86     EXPECT_EQ(GetStartedCalledCount(), 1);
87     EXPECT_EQ(GetFinishedCalledCount(), 0);
88 
89     EXPECT_TRUE(ani->Running()->GetValue());
90 
__anon50d39ff20302(uint32_t frame) 91     this->RunFrames(11, [&](uint32_t frame) {
92         auto f = frame - 1;
93         EXPECT_EQ(f, p->GetValue());
94         EXPECT_EQ(ani->Running()->GetValue(), f < 10);
95         EXPECT_FLOAT_EQ(ani->Progress()->GetValue(), f / 10.f);
96     });
97 
98     EXPECT_FALSE(ani->Running()->GetValue());
99 
100     EXPECT_EQ(GetStartedCalledCount(), 1);
101     EXPECT_EQ(GetFinishedCalledCount(), 1);
102 }
103 
104 HWTEST_F(AnimationTest, KeyframeAnimationSerialization, TestSize.Level1)
105 {
106     TestSerialiser ser;
107     {
108         auto p = ConstructProperty<int>("test");
109         auto pani = CreateAnimation(ClassId::KeyframeAnimation);
110         ASSERT_TRUE(pani);
111         auto pp = pani->Property();
112         ASSERT_TRUE(pp);
113         pp->SetValue(p);
114 
115         auto ani = interface_pointer_cast<IKeyframeAnimation>(pani);
116         ASSERT_TRUE(ani);
117         ani->From()->SetValue(IAny::Ptr(new Any<int>(0)));
118         ani->To()->SetValue(IAny::Ptr(new Any<int>(10)));
119         ani->Duration()->SetValue(TimeSpan::Milliseconds(100));
120 
121         Object obj(CreateInstance(ClassId::Object));
122         Metadata(obj).AddProperty(p);
123         AttachmentContainer(obj).Attach(pani);
124         ASSERT_TRUE(ser.Export(obj));
125         ser.Dump("app://test.json");
126     }
127 
128     auto obj = ser.Import<IMetadata>();
129     ASSERT_TRUE(obj);
130     auto p = obj->GetProperty<int>("test");
131     ASSERT_TRUE(p);
132 
133     auto att = interface_cast<IAttach>(obj);
134     ASSERT_TRUE(att);
135     auto attvec = att->GetAttachments<IKeyframeAnimation>();
136     ASSERT_EQ(attvec.size(), 1);
137 
138     auto pani = interface_pointer_cast<IPropertyAnimation>(attvec.front());
139     auto st = interface_pointer_cast<IStartableAnimation>(pani);
140     auto ani = interface_pointer_cast<IKeyframeAnimation>(pani);
141     ASSERT_TRUE(ani);
142     ASSERT_EQ(pani->Property()->GetValue().lock(), p.GetProperty());
143     ASSERT_TRUE(ani->Valid()->GetValue());
144 
145     st->Start();
146 
147     EXPECT_TRUE(ani->Running()->GetValue());
148 
__anon50d39ff20402(uint32_t frame) 149     this->RunFrames(11, [&](uint32_t frame) {
150         auto f = frame - 1;
151         EXPECT_EQ(f, p->GetValue());
152         EXPECT_EQ(ani->Running()->GetValue(), f < 10);
153         EXPECT_FLOAT_EQ(ani->Progress()->GetValue(), f / 10.f);
154     });
155 
156     EXPECT_FALSE(ani->Running()->GetValue());
157 }
158 
159 HWTEST_F(AnimationTest, ImplicitAnimation, TestSize.Level1)
160 {
161     auto p = ConstructProperty<int>("test");
162     auto pani = CreateAnimation(ClassId::PropertyAnimation);
163     auto ani = interface_pointer_cast<ITimedAnimation>(pani);
164     ASSERT_TRUE(ani && pani);
165 
166     EXPECT_TRUE(p->SetValue(10));
167     EXPECT_EQ(p->GetValue(), 10);
168 
169     EXPECT_TRUE(p->SetValue(0));
170     EXPECT_EQ(p->GetValue(), 0);
171 
172     EXPECT_TRUE(pani->Property()->SetValue(p));
173     EXPECT_TRUE(ani->Duration()->SetValue(TimeSpan::Milliseconds(100)));
174 
175     EXPECT_EQ(p->GetValue(), 0);
176 
177     // Set the value, it should not immediately change but rather start animating as we
178     // run some frames
179     EXPECT_TRUE(p->SetValue(10));
180 
181     EXPECT_TRUE(ani->Running()->GetValue());
182     EXPECT_EQ(p->GetValue(), 0);
183     EXPECT_EQ(GetStartedCalledCount(), 1);
184     EXPECT_EQ(GetFinishedCalledCount(), 0);
185 
186     // Check that property value changes to target gradually
__anon50d39ff20502(uint32_t frame) 187     this->RunFrames(11, [&](uint32_t frame) {
188         auto f = frame - 1;
189         EXPECT_EQ(f, p->GetValue());
190         EXPECT_EQ(ani->Running()->GetValue(), f < 10);
191         EXPECT_FLOAT_EQ(ani->Progress()->GetValue(), f / 10.f);
192     });
193 
194     EXPECT_EQ(GetStartedCalledCount(), 1);
195     EXPECT_EQ(GetFinishedCalledCount(), 1);
196 
197     EXPECT_FALSE(ani->Running()->GetValue());
198     EXPECT_EQ(p->GetValue(), 10);
199 
200     // Change the value again and verify that it still changes gradually
201     EXPECT_TRUE(p->SetValue(0));
202     EXPECT_TRUE(ani->Running()->GetValue());
203     EXPECT_EQ(p->GetValue(), 10);
204 
205     EXPECT_EQ(GetStartedCalledCount(), 2);
206     EXPECT_EQ(GetFinishedCalledCount(), 1);
207 
__anon50d39ff20602(uint32_t frame) 208     this->RunFrames(11, [&](uint32_t frame) {
209         auto f = frame - 1;
210         EXPECT_FLOAT_EQ(11 - frame, p->GetValue()) << "Frame: " << frame;
211         EXPECT_EQ(ani->Running()->GetValue(), f < 10) << "Frame: " << frame;
212         EXPECT_FLOAT_EQ(ani->Progress()->GetValue(), f / 10.f) << "Frame: " << frame;
213     });
214 
215     EXPECT_FALSE(ani->Running()->GetValue());
216     EXPECT_EQ(p->GetValue(), 0);
217 
218     EXPECT_EQ(GetStartedCalledCount(), 2);
219     EXPECT_EQ(GetFinishedCalledCount(), 2);
220 
221     // Remove target property, now any changes to property value should be immediate
222     pani->Property()->SetValue({});
223 
224     EXPECT_TRUE(p->SetValue(10));
225     EXPECT_FALSE(ani->Running()->GetValue());
226     EXPECT_EQ(p->GetValue(), 10);
227 
228     EXPECT_EQ(GetStartedCalledCount(), 2);
229     EXPECT_EQ(GetFinishedCalledCount(), 2);
230 }
231 
232 HWTEST_F(AnimationTest, ImplicitAnimationNoEvaluate, TestSize.Level1)
233 {
234     auto p = ConstructProperty<int>("test");
235     auto pani = CreateAnimation(ClassId::PropertyAnimation);
236     auto ani = interface_pointer_cast<ITimedAnimation>(pani);
237     ASSERT_TRUE(ani && pani);
238 
239     EXPECT_TRUE(pani->Property()->SetValue(p));
240     EXPECT_TRUE(ani->Duration()->SetValue(TimeSpan::Milliseconds(100)));
241 
242     // Set the value, it should not immediately change but rather start animating as we
243     // run some frames
244     EXPECT_TRUE(p->SetValue(10));
245 
246     EXPECT_TRUE(ani->Running()->GetValue());
247 
__anon50d39ff20702(uint32_t frame) 248     this->RunFrames(11, [&](uint32_t frame) {
249         auto f = frame - 1;
250         EXPECT_EQ(ani->Running()->GetValue(), f < 10);
251         EXPECT_FLOAT_EQ(ani->Progress()->GetValue(), f / 10.f);
252     });
253 
254     EXPECT_TRUE(p->SetValue(0));
255     EXPECT_EQ(p->GetValue(), 10);
256 }
257 
258 HWTEST_F(AnimationTest, ImplicitAnimationSerialization, TestSize.Level1)
259 {
260     TestSerialiser ser;
261     {
262         auto p = ConstructProperty<int>("test");
263         auto pani = CreateAnimation(ClassId::PropertyAnimation);
264         auto ani = interface_pointer_cast<ITimedAnimation>(pani);
265         ASSERT_TRUE(ani && pani);
266 
267         EXPECT_TRUE(pani->Property()->SetValue(p));
268         EXPECT_TRUE(ani->Duration()->SetValue(TimeSpan::Milliseconds(100)));
269 
270         Object obj(CreateInstance(ClassId::Object));
271         Metadata(obj).AddProperty(p);
272         ASSERT_TRUE(ser.Export(obj));
273         ser.Dump("app://test.json");
274     }
275 
276     auto obj = ser.Import<IMetadata>();
277     ASSERT_TRUE(obj);
278     auto p = obj->GetProperty<int>("test");
279     ASSERT_TRUE(p);
280 
281     auto vec = p->GetModifiers<ITimedAnimation>();
282     ASSERT_EQ(vec.size(), 1);
283     auto ani = vec.front();
284     ASSERT_TRUE(ani);
285     auto pani = interface_pointer_cast<IPropertyAnimation>(ani);
286     ASSERT_TRUE(pani);
287 
288     EXPECT_EQ(ani->Duration()->GetValue(), TimeSpan::Milliseconds(100));
289     EXPECT_EQ(pani->Property()->GetValue().lock(), p.GetProperty());
290 
291     // Set the value, it should not immediately change but rather start animating as we
292     // run some frames
293     EXPECT_TRUE(p->SetValue(10));
294 
295     EXPECT_TRUE(ani->Running()->GetValue());
296     EXPECT_EQ(p->GetValue(), 0);
297 
298     // Check that property value changes to target gradually
__anon50d39ff20802(uint32_t frame) 299     this->RunFrames(11, [&](uint32_t frame) {
300         auto f = frame - 1;
301         EXPECT_EQ(f, p->GetValue());
302         EXPECT_EQ(ani->Running()->GetValue(), f < 10);
303         EXPECT_FLOAT_EQ(ani->Progress()->GetValue(), f / 10.f);
304     });
305 
306     EXPECT_FALSE(ani->Running()->GetValue());
307     EXPECT_EQ(p->GetValue(), 10);
308 }
309 
310 HWTEST_F(AnimationTest, ImplicitAnimationSerializationWithAttachment, TestSize.Level1)
311 {
312     TestSerialiser ser;
313     {
314         auto p = ConstructProperty<int>("test");
315         auto pani = CreateAnimation(ClassId::PropertyAnimation);
316         auto ani = interface_pointer_cast<ITimedAnimation>(pani);
317         ASSERT_TRUE(ani && pani);
318 
319         EXPECT_TRUE(pani->Property()->SetValue(p));
320         EXPECT_TRUE(ani->Duration()->SetValue(TimeSpan::Milliseconds(100)));
321 
322         Object obj(CreateInstance(ClassId::Object));
323         Metadata(obj).AddProperty(p);
324         AttachmentContainer(obj).Attach(interface_pointer_cast<IAttachment>(pani));
325         ASSERT_TRUE(ser.Export(obj));
326         ser.Dump("file://./test.json");
327     }
328 
329     auto obj = ser.Import<IMetadata>();
330     ASSERT_TRUE(obj);
331     auto p = obj->GetProperty<int>("test");
332     ASSERT_TRUE(p);
333 
334     auto att = interface_cast<IAttach>(obj);
335     ASSERT_TRUE(att);
336     auto attvec = att->GetAttachments<IPropertyAnimation>();
337     EXPECT_EQ(attvec.size(), 1);
338 
339     auto vec = p->GetModifiers<ITimedAnimation>();
340     ASSERT_EQ(vec.size(), 1);
341     auto ani = vec.front();
342     ASSERT_TRUE(ani);
343     auto pani = interface_pointer_cast<IPropertyAnimation>(ani);
344     ASSERT_TRUE(pani);
345 
346     EXPECT_EQ(ani->Duration()->GetValue(), TimeSpan::Milliseconds(100));
347     EXPECT_EQ(pani->Property()->GetValue().lock(), p.GetProperty());
348 
349     // Set the value, it should not immediately change but rather start animating as we
350     // run some frames
351     EXPECT_TRUE(p->SetValue(10));
352 
353     EXPECT_TRUE(ani->Running()->GetValue());
354     EXPECT_EQ(p->GetValue(), 0);
355 
356     // Check that property value changes to target gradually
__anon50d39ff20902(uint32_t frame) 357     this->RunFrames(11, [&](uint32_t frame) {
358         auto f = frame - 1;
359         EXPECT_EQ(f, p->GetValue());
360         EXPECT_EQ(ani->Running()->GetValue(), f < 10);
361         EXPECT_FLOAT_EQ(ani->Progress()->GetValue(), f / 10.f);
362     });
363 
364     EXPECT_FALSE(ani->Running()->GetValue());
365     EXPECT_EQ(p->GetValue(), 10);
366 }
367 
368 /**
369  * @tc.name: ImplicitAnimationOnChanged
370  * @tc.desc: test ImplicitAnimationOnChanged
371  * @tc.type: FUNC
372  */
373 HWTEST_F(AnimationTest, ImplicitAnimationOnChanged, TestSize.Level1)
374 {
375     auto p = ConstructProperty<int>("test");
376     auto pani = CreateAnimation(ClassId::PropertyAnimation);
377     auto ani = interface_pointer_cast<ITimedAnimation>(pani);
378     ASSERT_TRUE(ani && pani);
379 
380     int count = 0;
__anon50d39ff20a02null381     p->OnChanged()->AddHandler(MakeCallback<IOnChanged>([&] {
382         ++count;
383         p->GetValue();
384     }));
385 
386     EXPECT_TRUE(pani->Property()->SetValue(p));
387     EXPECT_TRUE(ani->Duration()->SetValue(TimeSpan::Milliseconds(100)));
388 
389     // Set the value, it should not immediately change but rather start animating as we
390     // run some frames
391     EXPECT_TRUE(p->SetValue(10));
392 
393     EXPECT_TRUE(ani->Running()->GetValue());
394     EXPECT_EQ(p->GetValue(), 0);
395     EXPECT_EQ(GetStartedCalledCount(), 1);
396     EXPECT_EQ(GetFinishedCalledCount(), 0);
397 
398     // Check that property value changes to target gradually
__anon50d39ff20b02(uint32_t frame) 399     this->RunFrames(11, [&](uint32_t frame) {
400         auto f = frame - 1;
401         EXPECT_EQ(f, p->GetValue());
402         EXPECT_EQ(ani->Running()->GetValue(), f < 10);
403         EXPECT_FLOAT_EQ(ani->Progress()->GetValue(), f / 10.f);
404     });
405 
406     EXPECT_EQ(GetStartedCalledCount(), 1);
407     EXPECT_EQ(GetFinishedCalledCount(), 1);
408 
409     EXPECT_FALSE(ani->Running()->GetValue());
410     EXPECT_EQ(p->GetValue(), 10);
411     EXPECT_TRUE(count >= 10);
412 }
413 META_END_NAMESPACE()
414