• 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.h>
16 #include <gtest/gtest.h>
17 
18 #include <meta/api/make_callback.h>
19 #include <meta/api/object.h>
20 #include <meta/ext/object_fwd.h>
21 #include <meta/interface/intf_recyclable.h>
22 #include <meta/interface/loaders/intf_file_content_loader.h>
23 #include <meta/interface/model/intf_object_provider.h>
24 
25 #include "TestRunner.h"
26 #include "helpers/serialisation_utils.h"
27 #include "helpers/testing_objects.h"
28 
29 
30 using namespace testing;
31 using namespace testing::ext;
32 
META_BEGIN_NAMESPACE()33 META_BEGIN_NAMESPACE()
34 
35 static IDataModel::Ptr CreateTestDataModel(size_t size, size_t startNum = 0)
36 {
37     auto model = GetObjectRegistry().Create<IContainer>(META_NS::ClassId::ContainerDataModel);
38     for (int i = 0; i != size; ++i) {
39         auto p = CreateTestType();
40         p->First()->SetValue(startNum + i);
41         model->Add(p);
42     }
43     return interface_pointer_cast<IDataModel>(model);
44 }
45 
46 META_REGISTER_CLASS(CustomDataItemView, "4a3bd491-3333-4a9a-bcad-92530493be09", ObjectCategoryBits::NO_CATEGORY)
47 
48 class CustomDataItemView : public IntroduceInterfaces<ObjectFwd, IRecyclable> {
49     META_OBJECT(CustomDataItemView, ClassId::CustomDataItemView, IntroduceInterfaces)
50 public:
ReBuild(const IMetadata::Ptr & data)51     bool ReBuild(const IMetadata::Ptr& data) override
52     {
53         if (auto p = data->GetProperty("First")) {
54             auto prop = DuplicatePropertyType(META_NS::GetObjectRegistry(), p, "MyFirst");
55             PropertyLock l { prop };
56             l->SetBind(p);
57             AddProperty(prop);
58             return true;
59         }
60         return false;
61     }
Dispose()62     void Dispose() override
63     {
64         if (auto p = GetProperty("MyFirst")) {
65             RemoveProperty(p);
66         }
67     }
68 };
69 
70 namespace {
71 struct TestDefinition {
72     ClassInfo obj {};
73     BASE_NS::string propName;
74 };
75 } // namespace
76 
77 class InstantiatingObjectProviderTest : public ::testing::TestWithParam<std::tuple<TestDefinition, int>> {
78 public:
SetUpTestSuite()79     static void SetUpTestSuite()
80     {
81         SetTest();
82     }
TearDownTestSuite()83     static void TearDownTestSuite()
84     {
85         TearDownTest();
86     }
SetUp()87     void SetUp() override
88     {
89         RegisterObjectType<CustomDataItemView>();
90         auto v = std::get<0>(GetParam());
91         instObj_ = v.obj;
92         propName_ = v.propName;
93         cacheHint_ = std::get<1>(GetParam());
94 
95         auto instprov =
96             GetObjectRegistry().Create<IInstantiatingObjectProvider>(META_NS::ClassId::InstantiatingObjectProvider);
97         ASSERT_TRUE(instprov);
98 
99         auto model = CreateTestDataModel(10); // 10: param
100         cont_ = interface_pointer_cast<IContainer>(model);
101         instprov->SetObjectClassId(instObj_.Id());
102 
103         prov_ = interface_pointer_cast<IModelObjectProvider>(instprov);
104         ASSERT_TRUE(prov_);
105         prov_->SetDataModel(model);
106         prov_->CacheHint()->SetValue(cacheHint_);
107 
108         EXPECT_EQ(prov_->GetObjectCount(), 10); // 10: param
109     }
110 
TearDown()111     void TearDown() override
112     {
113         UnregisterObjectType<CustomDataItemView>();
114     }
115 
116 protected:
117     ClassInfo instObj_;
118     BASE_NS::string propName_;
119     size_t cacheHint_ {};
120     IModelObjectProvider::Ptr prov_;
121     IContainer::Ptr cont_;
122 };
123 
124 HWTEST_P(InstantiatingObjectProviderTest, CreateAndDispose, TestSize.Level1)
125 {
126     BASE_NS::vector<IObject::Ptr> objs;
127 
128     for (std::size_t i = 0; i != 10; ++i) {
129         objs.push_back(prov_->CreateObject(DataModelIndex { i }));
130         auto d = interface_cast<IMetadata>(objs.back());
131         ASSERT_TRUE(d);
132         auto p = d->GetProperty<int>(propName_);
133         ASSERT_TRUE(p);
134         EXPECT_EQ(p->GetValue(), i);
135     }
136 
137     for (std::size_t i = 0; i != 10; ++i) {
138         EXPECT_EQ(prov_->DisposeObject(objs.front()), i < cacheHint_);
139         auto d = interface_cast<IMetadata>(objs.front());
140         ASSERT_TRUE(d);
141         if (interface_cast<IRecyclable>(d)) {
142             ASSERT_FALSE(d->GetProperty(propName_));
143         } else {
144             auto p = d->GetProperty<int>(propName_);
145             ASSERT_TRUE(p);
146             EXPECT_FALSE(p->GetBind());
147         }
148     }
149 }
150 
151 HWTEST_P(InstantiatingObjectProviderTest, AddRemoveMove, TestSize.Level1)
152 {
153     size_t addIndex = -1;
154     size_t RemoveIndex = -1;
155     size_t moveFromIndex = -1;
156     size_t moveToIndex = -1;
157 
158     prov_->OnDataAdded()->AddHandler(
__anonc3b022e20202(auto index, auto count) 159         MakeCallback<IOnDataAdded>([&](auto index, auto count) { addIndex = index.Index(); }));
160     prov_->OnDataRemoved()->AddHandler(
__anonc3b022e20302(auto index, auto count) 161         MakeCallback<IOnDataRemoved>([&](auto index, auto count) { RemoveIndex = index.Index(); }));
__anonc3b022e20402(auto from, auto count, auto to) 162     prov_->OnDataMoved()->AddHandler(MakeCallback<IOnDataMoved>([&](auto from, auto count, auto to) {
163         moveFromIndex = from.Index();
164         moveToIndex = to.Index();
165     }));
166 
167     auto o1 = CreateTestType<IObject>();
168     cont_->Add(o1);
169 
170     EXPECT_EQ(prov_->GetObjectCount(), 11);
171     EXPECT_EQ(addIndex, 10);
172 
173     EXPECT_TRUE(prov_->CreateObject(DataModelIndex { 10 }));
174 
175     cont_->Remove(cont_->GetAt(0));
176 
177     EXPECT_EQ(prov_->GetObjectCount(), 10);
178     EXPECT_EQ(RemoveIndex, 0);
179 
180     cont_->Move(1, 8);
181     EXPECT_EQ(prov_->GetObjectCount(), 10);
182     EXPECT_EQ(moveFromIndex, 1);
183     EXPECT_EQ(moveToIndex, 8);
184 }
185 
BuildTestName(const testing::TestParamInfo<InstantiatingObjectProviderTest::ParamType> & info)186 static std::string BuildTestName(const testing::TestParamInfo<InstantiatingObjectProviderTest::ParamType>& info)
187 {
188     auto name = std::get<0>(info.param).obj.Name();
189     auto test =
190         std::string(name.data(), name.size()) + std::string("_CacheHint_") + std::to_string(std::get<1>(info.param));
191     return test;
192 }
193 
194 INSTANTIATE_TEST_SUITE_P(InstantiatingObjectProviderTests, InstantiatingObjectProviderTest,
195     testing::Combine(testing::Values(TestDefinition { META_NS::ClassId::Object, "Model.First" },
196                          TestDefinition { ClassId::CustomDataItemView, "MyFirst" }),
197         testing::Range(0, 10, 4)),
198     BuildTestName);
199 
200 class CompositeObjectProviderTest : public ::testing::Test {
201 protected:
SetUpTestSuite()202     static void SetUpTestSuite()
203     {
204         SetTest();
205     }
TearDownTestSuite()206     static void TearDownTestSuite()
207     {
208         TearDownTest();
209     }
CreateProvider(size_t size,size_t startNum)210     IObjectProvider::Ptr CreateProvider(size_t size, size_t startNum)
211     {
212         auto instprov =
213             GetObjectRegistry().Create<IInstantiatingObjectProvider>(META_NS::ClassId::InstantiatingObjectProvider);
214         if (!instprov) {
215             return nullptr;
216         }
217 
218         auto p = interface_pointer_cast<IModelObjectProvider>(instprov);
219 
220         p->SetDataModel(CreateTestDataModel(size, startNum));
221         instprov->SetObjectClassId(META_NS::ClassId::Object.Id());
222 
223         return p;
224     }
225 
SetUp()226     void SetUp() override
227     {
228         p1_ = CreateProvider(5, 0); // 5: param
229         ASSERT_TRUE(p1_);
230         c1_ = interface_cast<IContainer>(interface_cast<IModelObjectProvider>(p1_)->GetDataModel());
231         p2_ = CreateProvider(0, 5); // 5: param
232         ASSERT_TRUE(p2_);
233         c2_ = interface_cast<IContainer>(interface_cast<IModelObjectProvider>(p2_)->GetDataModel());
234         p3_ = CreateProvider(1, 5); // 5: param
235         ASSERT_TRUE(p3_);
236         c3_ = interface_cast<IContainer>(interface_cast<IModelObjectProvider>(p3_)->GetDataModel());
237         p4_ = CreateProvider(10, 6); // 10: param  6: param
238         ASSERT_TRUE(p4_);
239         c4_ = interface_cast<IContainer>(interface_cast<IModelObjectProvider>(p4_)->GetDataModel());
240 
241         auto p = GetObjectRegistry().Create<IContainer>(META_NS::ClassId::CompositeObjectProvider);
242         p->Add(p1_);
243         p->Add(p2_);
244         p->Add(p3_);
245         p->Add(p4_);
246 
247         prov_ = interface_pointer_cast<IObjectProvider>(p);
248 
249         size_ = c1_->GetSize() + c2_->GetSize() + c3_->GetSize() + c4_->GetSize();
250     }
251 
TearDown()252     void TearDown() override {}
253 
254     IObjectProvider::Ptr p1_;
255     IContainer* c1_;
256     IObjectProvider::Ptr p2_;
257     IContainer* c2_;
258     IObjectProvider::Ptr p3_;
259     IContainer* c3_;
260     IObjectProvider::Ptr p4_;
261     IContainer* c4_;
262 
263     IObjectProvider::Ptr prov_;
264 
265     size_t size_;
266 };
267 
268 HWTEST_F(CompositeObjectProviderTest, CreateAndDispose, TestSize.Level1)
269 {
270     BASE_NS::vector<IObject::Ptr> objs;
271 
272     EXPECT_EQ(prov_->GetObjectCount(), size_);
273 
274     for (std::size_t i = 0; i != size_; ++i) {
275         objs.push_back(prov_->CreateObject(DataModelIndex { i }));
276         auto d = interface_cast<IMetadata>(objs.back());
277         ASSERT_TRUE(d);
278         auto p = d->GetProperty<int>("Model.First");
279         ASSERT_TRUE(p);
280         EXPECT_EQ(p->GetValue(), i);
281     }
282 
283     for (std::size_t i = 0; i != size_; ++i) {
284         prov_->DisposeObject(objs.front());
285         auto d = interface_cast<IMetadata>(objs.front());
286         ASSERT_TRUE(d);
287 
288         auto p = d->GetProperty<int>("Model.First");
289         ASSERT_TRUE(p);
290         EXPECT_FALSE(p->GetBind());
291     }
292 }
293 
294 HWTEST_F(CompositeObjectProviderTest, AddRemoveMove, TestSize.Level1)
295 {
296     size_t addIndex = -1;
297     size_t RemoveIndex = -1;
298     size_t moveFromIndex = -1;
299     size_t moveToIndex = -1;
300 
301     prov_->OnDataAdded()->AddHandler(
__anonc3b022e20502(auto index, auto count) 302         MakeCallback<IOnDataAdded>([&](auto index, auto count) { addIndex = index.Index(); }));
303     prov_->OnDataRemoved()->AddHandler(
__anonc3b022e20602(auto index, auto count) 304         MakeCallback<IOnDataRemoved>([&](auto index, auto count) { RemoveIndex = index.Index(); }));
__anonc3b022e20702(auto from, auto count, auto to) 305     prov_->OnDataMoved()->AddHandler(MakeCallback<IOnDataMoved>([&](auto from, auto count, auto to) {
306         moveFromIndex = from.Index();
307         moveToIndex = to.Index();
308     }));
309 
310     c3_->Add(CreateTestType<IObject>());
311 
312     EXPECT_EQ(prov_->GetObjectCount(), ++size_);
313     EXPECT_EQ(addIndex, 6);
314 
315     c2_->Add(CreateTestType<IObject>());
316 
317     EXPECT_EQ(prov_->GetObjectCount(), ++size_);
318     EXPECT_EQ(addIndex, 5);
319 
320     c4_->Remove(c4_->GetAt(0));
321 
322     EXPECT_EQ(prov_->GetObjectCount(), --size_);
323     EXPECT_EQ(RemoveIndex, 8);
324 
325     c4_->Move(1, 6);
326     EXPECT_EQ(prov_->GetObjectCount(), size_);
327     EXPECT_EQ(moveFromIndex, 9);
328     EXPECT_EQ(moveToIndex, 14);
329 }
330 
331 HWTEST_F(CompositeObjectProviderTest, AddProviders, TestSize.Level1)
332 {
333     size_t index = -1;
334     size_t count = 0;
335 
__anonc3b022e20802(auto i, auto c) 336     prov_->OnDataAdded()->AddHandler(MakeCallback<IOnDataAdded>([&](auto i, auto c) {
337         index = i.Index();
338         count = c;
339     }));
340 
341     auto cont = interface_cast<IContainer>(prov_);
342 
343     cont->Add(CreateProvider(2, 0));
344     EXPECT_EQ(prov_->GetObjectCount(), size_ + 2);
345     EXPECT_EQ(index, size_);
346     EXPECT_EQ(count, 2);
347 
348     cont->Insert(1, CreateProvider(4, 0));
349     EXPECT_EQ(prov_->GetObjectCount(), size_ + 2 + 4);
350     EXPECT_EQ(index, 5);
351     EXPECT_EQ(count, 4);
352 }
353 
354 HWTEST_F(CompositeObjectProviderTest, RemoveProviders, TestSize.Level1)
355 {
356     size_t index = -1;
357     size_t count = -1;
358 
__anonc3b022e20902(auto i, auto c) 359     prov_->OnDataRemoved()->AddHandler(MakeCallback<IOnDataRemoved>([&](auto i, auto c) {
360         index = i.Index();
361         count = c;
362     }));
363 
364     auto cont = interface_cast<IContainer>(prov_);
365 
366     cont->Remove(cont->GetAt(1));
367     EXPECT_EQ(prov_->GetObjectCount(), size_);
368     EXPECT_EQ(index, -1);
369     EXPECT_EQ(count, -1);
370 
371     cont->Remove(cont->GetAt(1));
372     EXPECT_EQ(prov_->GetObjectCount(), size_ - 1);
373     EXPECT_EQ(index, 5);
374     EXPECT_EQ(count, 1);
375 
376     cont->Remove(cont->GetAt(cont->GetSize() - 1));
377     EXPECT_EQ(prov_->GetObjectCount(), size_ - 1 - 10);
378     EXPECT_EQ(index, 5);
379     EXPECT_EQ(count, 10);
380 }
381 
382 HWTEST_F(CompositeObjectProviderTest, MoveProviders, TestSize.Level1)
383 {
384     size_t from = -1;
385     size_t to = -1;
386     size_t count = -1;
387 
__anonc3b022e20a02(auto f, auto c, auto t) 388     prov_->OnDataMoved()->AddHandler(MakeCallback<IOnDataMoved>([&](auto f, auto c, auto t) {
389         from = f.Index();
390         to = t.Index();
391         count = c;
392     }));
393 
394     auto cont = interface_cast<IContainer>(prov_);
395 
396     cont->Move(1, 4);
397     EXPECT_EQ(prov_->GetObjectCount(), size_);
398     EXPECT_EQ(from, -1);
399     EXPECT_EQ(to, -1);
400     EXPECT_EQ(count, -1);
401     // move it back
402     cont->Move(3, 1);
403 
404     cont->Move(0, 4);
405     EXPECT_EQ(prov_->GetObjectCount(), size_);
406     EXPECT_EQ(from, 0);
407     EXPECT_EQ(to, 16);
408     EXPECT_EQ(count, 5);
409 
410     cont->Move(3, 0);
411     EXPECT_EQ(prov_->GetObjectCount(), size_);
412     EXPECT_EQ(from, 11);
413     EXPECT_EQ(to, 0);
414     EXPECT_EQ(count, 5);
415 
416     cont->Move(2, 3);
417     EXPECT_EQ(prov_->GetObjectCount(), size_);
418     EXPECT_EQ(from, 5);
419     EXPECT_EQ(to, 16);
420     EXPECT_EQ(count, 1);
421 }
422 
423 class ContentLoaderObjectProviderTest : public ::testing::TestWithParam<int> {
424 public:
SetUpTestSuite()425     static void SetUpTestSuite()
426     {
427         SetTest();
428     }
TearDownTestSuite()429     static void TearDownTestSuite()
430     {
431         TearDownTest();
432     }
SetUp()433     void SetUp() override
434     {
435         cacheHint_ = GetParam();
436 
437         prov_ = GetObjectRegistry().Create<IModelObjectProvider>(META_NS::ClassId::ContentLoaderObjectProvider);
438         ASSERT_TRUE(prov_);
439 
440         auto model = CreateTestDataModel(20, 10); // 20: param  10: param
441         cont_ = interface_pointer_cast<IContainer>(model);
442 
443         prov_->SetDataModel(model);
444         prov_->CacheHint()->SetValue(cacheHint_);
445 
446         EXPECT_EQ(prov_->GetObjectCount(), 20); // 20: param
447     }
448 
SetJsonLoader(CORE_NS::IFile::Ptr file)449     void SetJsonLoader(CORE_NS::IFile::Ptr file)
450     {
451         if (auto p = interface_cast<IContentLoaderObjectProvider>(prov_)) {
452             auto loader = GetObjectRegistry().Create<IFileContentLoader>(META_NS::ClassId::JsonContentLoader);
453             ASSERT_TRUE(loader);
454             loader->SetFile(BASE_NS::move(file));
455             p->SetContentLoader(loader);
456         }
457     }
458 
TearDown()459     void TearDown() override
460     {
461         UnregisterObjectType<CustomDataItemView>();
462     }
463 
464 protected:
465     size_t cacheHint_ {};
466     IModelObjectProvider::Ptr prov_;
467     IContainer::Ptr cont_;
468 };
469 
CreateTestFileWithoutProperty()470 static CORE_NS::IFile::Ptr CreateTestFileWithoutProperty()
471 {
472     TestSerialiser ser;
473     ser.Export(CreateInstance(META_NS::ClassId::Object));
474     return CORE_NS::IFile::Ptr(new MemFile(ser.GetData()));
475 }
476 
477 HWTEST_P(ContentLoaderObjectProviderTest, JsonWithoutProperty, TestSize.Level1)
478 {
479     SetJsonLoader(CreateTestFileWithoutProperty());
480 
481     BASE_NS::vector<IObject::Ptr> objs;
482     for (size_t i = 0; i != 10; ++i) {
483         auto obj = prov_->CreateObject(DataModelIndex(i));
484         ASSERT_TRUE(obj);
485         auto p = interface_cast<IMetadata>(obj)->GetProperty<int>("Model.First");
486         ASSERT_TRUE(p);
487         EXPECT_EQ(p->GetValue(), i + 10);
488         objs.push_back(obj);
489     }
490     for (size_t i = 0; i != 10; ++i) {
491         auto o = objs.back();
492         objs.pop_back();
493         prov_->DisposeObject(o);
494     }
495     for (size_t i = 10; i != 20; ++i) {
496         auto obj = prov_->CreateObject(DataModelIndex(i));
497         ASSERT_TRUE(obj);
498         auto p = interface_cast<IMetadata>(obj)->GetProperty<int>("Model.First");
499         ASSERT_TRUE(p);
500         EXPECT_EQ(p->GetValue(), i + 10);
501     }
502 }
503 
CreateTestFileWithProperty()504 static CORE_NS::IFile::Ptr CreateTestFileWithProperty()
505 {
506     TestSerialiser ser;
507     Metadata object(CreateInstance(META_NS::ClassId::Object));
508     object.AddProperty<int>("Model.First", 0);
509     ser.Export(object.GetPtr<META_NS::IObject>());
510     return CORE_NS::IFile::Ptr(new MemFile(ser.GetData()));
511 }
512 
513 HWTEST_P(ContentLoaderObjectProviderTest, JsonWithProperty, TestSize.Level1)
514 {
515     SetJsonLoader(CreateTestFileWithProperty());
516 
517     BASE_NS::vector<IObject::Ptr> objs;
518     for (size_t i = 0; i != 10; ++i) {
519         auto obj = prov_->CreateObject(DataModelIndex(i));
520         ASSERT_TRUE(obj);
521         auto p = interface_cast<IMetadata>(obj)->GetProperty<int>("Model.First");
522         ASSERT_TRUE(p);
523         EXPECT_EQ(p->GetValue(), i + 10);
524         objs.push_back(obj);
525     }
526     for (size_t i = 0; i != 10; ++i) {
527         auto o = objs.back();
528         objs.pop_back();
529         prov_->DisposeObject(o);
530     }
531     for (size_t i = 10; i != 20; ++i) {
532         auto obj = prov_->CreateObject(DataModelIndex(i));
533         ASSERT_TRUE(obj);
534         auto p = interface_cast<IMetadata>(obj)->GetProperty<int>("Model.First");
535         ASSERT_TRUE(p);
536         EXPECT_EQ(p->GetValue(), i + 10);
537     }
538 }
539 
BuildContentLoaderTestName(const testing::TestParamInfo<ContentLoaderObjectProviderTest::ParamType> & info)540 static std::string BuildContentLoaderTestName(
541     const testing::TestParamInfo<ContentLoaderObjectProviderTest::ParamType>& info)
542 {
543     return std::string("CacheHint_") + std::to_string(info.param);
544 }
545 
546 INSTANTIATE_TEST_SUITE_P(ContentLoaderObjectProviderTests, ContentLoaderObjectProviderTest,
547     testing::Range(0, 10, 4), BuildContentLoaderTestName);
548 
549 
550 META_END_NAMESPACE()
551