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