Use OrderedSet so remove useless iteration for some singletone
[platform/core/uifw/dali-core.git] / automated-tests / src / dali-internal / utc-Dali-Internal-OrderedSet.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // EXTERNAL INCLUDES
19 #include <utility>
20
21 // INTERNAL INCLUDES
22 #include <dali-test-suite-utils.h>
23 #include <dali/internal/common/ordered-set.h>
24
25 using namespace Dali::Internal;
26
27 void utc_dali_internal_owner_set_startup(void)
28 {
29   test_return_value = TET_UNDEF;
30 }
31
32 void utc_dali_internal_owner_set_cleanup(void)
33 {
34   test_return_value = TET_PASS;
35 }
36
37 ///////////////////////////////////////////////////////////////////////////////
38 namespace
39 {
40 /// Takes in a reference to a bool which is set to true when the destructor is called
41 class OwnedClass
42 {
43 public:
44   OwnedClass(bool& destructorCalled)
45   : mDestructorCalled(destructorCalled)
46   {
47     mDestructorCalled = false;
48   }
49
50   ~OwnedClass()
51   {
52     mDestructorCalled = true;
53   }
54
55 private:
56   bool& mDestructorCalled;
57 };
58
59 /// Just a simple class with a member value and global refcount.
60 class ClassWithId
61 {
62 public:
63   ClassWithId(int id)
64   : mId(id)
65   {
66     ++gRefCount;
67   }
68   ~ClassWithId()
69   {
70     --gRefCount;
71   }
72
73   static int gRefCount;
74   int        mId{};
75 };
76 int ClassWithId::gRefCount = 0;
77
78 } // namespace
79
80 ///////////////////////////////////////////////////////////////////////////////
81
82 int UtcDaliOrderedSetEnsureDeletion(void)
83 {
84   // Ensure that the object owned by the OrderedSet is deleted.
85
86   bool deleted = false;
87
88   {
89     OrderedSet<OwnedClass> set;
90     set.PushBack(new OwnedClass(deleted));
91     DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
92   }
93
94   // OrderedSet out-of-scope, object should be deleted.
95
96   DALI_TEST_EQUALS(deleted, true, TEST_LOCATION);
97
98   END_TEST;
99 }
100
101 int UtcDaliOrderedSetFalseEnsureNotDeletionWhen(void)
102 {
103   // Ensure that the object owned by the OrderedSET is deleted.
104
105   bool deleted = false;
106
107   OwnedClass* ptr;
108
109   {
110     // Create OrderedSet without ownership. It will not delete automatically.
111     OrderedSet<OwnedClass, false> set;
112     ptr = new OwnedClass(deleted);
113     set.PushBack(ptr);
114     DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
115   }
116
117   // OrderedSet out-of-scope, but, object should not be deleted.
118
119   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
120
121   delete ptr;
122   DALI_TEST_EQUALS(deleted, true, TEST_LOCATION);
123
124   END_TEST;
125 }
126
127 int UtcDaliOrderedSetDefaultConstructor(void)
128 {
129   // Ensure the default constructor is created as expected.
130
131   OrderedSet<OwnedClass> set;
132   DALI_TEST_CHECK(set.Count() == 0u);
133
134   END_TEST;
135 }
136
137 int UtcDaliOrderedSetFalseDefaultConstructor(void)
138 {
139   // Ensure the default constructor is created as expected.
140
141   OrderedSet<OwnedClass, false> set;
142   DALI_TEST_CHECK(set.Count() == 0u);
143
144   END_TEST;
145 }
146
147 int UtcDaliOrderedSetReserve(void)
148 {
149   OrderedSet<OwnedClass> set;
150   set.Reserve(100u);
151
152   // Reserve function didn't change the count.
153   DALI_TEST_CHECK(set.Count() == 0u);
154
155   OrderedSet<OwnedClass> set2;
156   set2.Reserve(100u);
157
158   // Reserve function didn't change the count.
159   DALI_TEST_CHECK(set2.Count() == 0u);
160
161   END_TEST;
162 }
163
164 int UtcDaliOrderedSetMove(void)
165 {
166   // Call move constructor and move assignment operator
167
168   bool        deleted = false;
169   OwnedClass* owned   = new OwnedClass(deleted);
170
171   OrderedSet<OwnedClass> first;
172   DALI_TEST_CHECK(first.Find(owned) == first.End());
173   first.PushBack(owned);
174   DALI_TEST_CHECK(first.Find(owned) != first.End());
175
176   {
177     // Move constructor, first should have a nullptr now, no object deletion
178     OrderedSet<OwnedClass> second(std::move(first));
179     DALI_TEST_CHECK(first.Find(owned) == first.End());
180     DALI_TEST_CHECK(second.Find(owned) != second.End());
181     DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
182
183     // Assign second to first, no deletion, second should have a nullptr now
184     first = std::move(second);
185     DALI_TEST_CHECK(first.Find(owned) != first.End());
186     DALI_TEST_CHECK(second.Find(owned) == second.End());
187     DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
188   }
189
190   // second is out-of-scope now, no object deletion
191   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
192
193   // Assign to an empty pointer, owned object should be deleted
194   OrderedSet<OwnedClass> empty;
195   first = std::move(empty);
196   DALI_TEST_EQUALS(deleted, true, TEST_LOCATION);
197   DALI_TEST_CHECK(first.Find(owned) == first.End());
198   DALI_TEST_CHECK(empty.Find(owned) == empty.End());
199
200   END_TEST;
201 }
202
203 int UtcDaliOrderedSetFalseMove(void)
204 {
205   // Call move constructor and move assignment operator
206
207   bool        deleted = false;
208   OwnedClass* owned   = new OwnedClass(deleted);
209
210   OrderedSet<OwnedClass, false> first;
211   DALI_TEST_CHECK(first.Find(owned) == first.End());
212   first.PushBack(owned);
213   DALI_TEST_CHECK(first.Find(owned) != first.End());
214
215   {
216     // Move constructor, first should have a nullptr now, no object deletion
217     OrderedSet<OwnedClass, false> second(std::move(first));
218     DALI_TEST_CHECK(first.Find(owned) == first.End());
219     DALI_TEST_CHECK(second.Find(owned) != second.End());
220     DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
221
222     // Assign second to first, no deletion, second should have a nullptr now
223     first = std::move(second);
224     DALI_TEST_CHECK(first.Find(owned) != first.End());
225     DALI_TEST_CHECK(second.Find(owned) == second.End());
226     DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
227   }
228
229   // second is out-of-scope now, no object deletion
230   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
231
232   // Assign to an empty pointer, but owned object should not be deleted
233   OrderedSet<OwnedClass, false> empty;
234   first = std::move(empty);
235   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
236   DALI_TEST_CHECK(first.Find(owned) == first.End());
237   DALI_TEST_CHECK(empty.Find(owned) == empty.End());
238
239   delete owned;
240   DALI_TEST_EQUALS(deleted, true, TEST_LOCATION);
241
242   END_TEST;
243 }
244
245 int UtcDaliOrderedSetErase(void)
246 {
247   // Ensure that calling Reset deletes the object and sets the owner-pointer to NULL
248
249   bool        deleted = false;
250   OwnedClass* owned   = new OwnedClass(deleted);
251
252   OrderedSet<OwnedClass> set;
253   set.PushBack(owned);
254   DALI_TEST_EQUALS(set.Count(), 1u, TEST_LOCATION);
255   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
256   set.EraseObject(owned);
257   DALI_TEST_EQUALS(deleted, true, TEST_LOCATION);
258
259   END_TEST;
260 }
261
262 int UtcDaliOrderedSetFalseErase(void)
263 {
264   // Ensure that calling Reset not deletes the object and sets the owner-pointer to NULL
265
266   bool        deleted = false;
267   OwnedClass* owned   = new OwnedClass(deleted);
268
269   OrderedSet<OwnedClass, false> set;
270   set.PushBack(owned);
271   DALI_TEST_EQUALS(set.Count(), 1u, TEST_LOCATION);
272   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
273   set.EraseObject(owned);
274   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
275
276   delete owned;
277   DALI_TEST_EQUALS(deleted, true, TEST_LOCATION);
278
279   END_TEST;
280 }
281
282 int UtcDaliOrderedSetClear(void)
283 {
284   // Ensure that calling Reset deletes the object and sets the owner-pointer to NULL
285
286   bool        deleted = false;
287   OwnedClass* owned   = new OwnedClass(deleted);
288
289   OrderedSet<OwnedClass> set;
290   set.PushBack(owned);
291   DALI_TEST_EQUALS(set.Count(), 1u, TEST_LOCATION);
292   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
293
294   set.Clear();
295   DALI_TEST_EQUALS(set.Count(), 0u, TEST_LOCATION);
296   DALI_TEST_EQUALS(deleted, true, TEST_LOCATION);
297
298   END_TEST;
299 }
300
301 int UtcDaliOrderedSetFalseClear(void)
302 {
303   // Ensure that calling Reset deletes the object and sets the owner-pointer to NULL
304
305   bool        deleted = false;
306   OwnedClass* owned   = new OwnedClass(deleted);
307
308   OrderedSet<OwnedClass, false> set;
309   set.PushBack(owned);
310   DALI_TEST_EQUALS(set.Count(), 1u, TEST_LOCATION);
311   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
312
313   set.Clear();
314   DALI_TEST_EQUALS(set.Count(), 0u, TEST_LOCATION);
315   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
316
317   delete owned;
318   DALI_TEST_EQUALS(deleted, true, TEST_LOCATION);
319
320   END_TEST;
321 }
322
323 int UtcDaliOrderedSetRelease(void)
324 {
325   // Ensure that calling Release does NOT delete the object but still sets the owner-pointer to NULL
326
327   bool        deleted = false;
328   OwnedClass* owned   = new OwnedClass(deleted);
329
330   OrderedSet<OwnedClass> set;
331   set.PushBack(owned);
332   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
333
334   auto iter = set.Find(owned);
335   DALI_TEST_CHECK(iter != set.End());
336   DALI_TEST_EQUALS(set.Count(), 1u, TEST_LOCATION);
337
338   OwnedClass* released = set.Release(iter);
339   DALI_TEST_EQUALS(deleted, false, TEST_LOCATION);
340   DALI_TEST_CHECK(set.Find(owned) == set.End());
341   DALI_TEST_CHECK(set.Find(released) == set.End());
342   DALI_TEST_EQUALS(set.Count(), 0u, TEST_LOCATION);
343
344   delete released;
345   DALI_TEST_EQUALS(deleted, true, TEST_LOCATION);
346
347   END_TEST;
348 }
349
350 int UtcDaliOrderedSetIteratorOrderCheck(void)
351 {
352   // Ensure that order of iterator is equal with Order of Insertion.
353
354   // Reset refcount of class
355   ClassWithId::gRefCount = 0;
356
357   // To avoid lucky pass, run this test multiple time.
358   int tryCnt = 3;
359   while(tryCnt--)
360   {
361     int baseId = tryCnt; // random id
362     int id     = baseId;
363     int n      = 10 + 5 * (tryCnt + 1); // random count
364
365     OrderedSet<ClassWithId> set;
366
367     for(int i = 0; i < n; ++i)
368     {
369       ClassWithId* object = new ClassWithId(id++);
370       set.PushBack(object);
371     }
372
373     int expectId;
374     // Check by for iteration
375     expectId = baseId;
376     for(auto iter = set.Begin(), iterEnd = set.End(); iter != iterEnd; ++iter)
377     {
378       DALI_TEST_EQUALS(expectId++, (*iter)->mId, TEST_LOCATION);
379     }
380     DALI_TEST_EQUALS(expectId, id, TEST_LOCATION);
381
382     // Check by range referenced iteration
383     expectId = baseId;
384     for(auto&& iter : set)
385     {
386       DALI_TEST_EQUALS(expectId++, iter->mId, TEST_LOCATION);
387       // Change iter's value.
388       ++(iter->mId);
389     }
390     DALI_TEST_EQUALS(expectId, id, TEST_LOCATION);
391
392     // Check by range iteration. Note that class value changed.
393     expectId = baseId + 1;
394     for(const auto& iter : set)
395     {
396       DALI_TEST_EQUALS(expectId++, iter->mId, TEST_LOCATION);
397     }
398     DALI_TEST_EQUALS(expectId, id + 1, TEST_LOCATION);
399   }
400
401   // Check whether leak exist.
402   DALI_TEST_EQUALS(ClassWithId::gRefCount, 0, TEST_LOCATION);
403
404   END_TEST;
405 }
406
407 int UtcDaliOrderedSetFalseIteratorOrderCheck(void)
408 {
409   // Ensure that order of iterator is equal with Order of Insertion.
410
411   // Reset refcount of class
412   ClassWithId::gRefCount = 0;
413
414   // Container of ownered class, to release memories after test finished.
415   std::vector<ClassWithId*> objectList;
416
417   // To avoid lucky pass, run this test multiple time.
418   int tryCnt = 3;
419   while(tryCnt--)
420   {
421     int baseId = tryCnt; // random id
422     int id     = baseId;
423     int n      = 10 + 5 * (tryCnt + 1); // random count
424
425     OrderedSet<ClassWithId, false> set;
426
427     for(int i = 0; i < n; ++i)
428     {
429       ClassWithId* object = new ClassWithId(id++);
430       objectList.push_back(object);
431       set.PushBack(object);
432     }
433
434     int expectId;
435     // Check by for iteration
436     expectId = baseId;
437     for(auto iter = set.Begin(), iterEnd = set.End(); iter != iterEnd; ++iter)
438     {
439       DALI_TEST_EQUALS(expectId++, (*iter)->mId, TEST_LOCATION);
440     }
441     DALI_TEST_EQUALS(expectId, id, TEST_LOCATION);
442
443     // Check by range referenced iteration
444     expectId = baseId;
445     for(auto&& iter : set)
446     {
447       DALI_TEST_EQUALS(expectId++, iter->mId, TEST_LOCATION);
448       // Change iter's value.
449       ++(iter->mId);
450     }
451     DALI_TEST_EQUALS(expectId, id, TEST_LOCATION);
452
453     // Check by range iteration. Note that class value changed.
454     expectId = baseId + 1;
455     for(const auto& iter : set)
456     {
457       DALI_TEST_EQUALS(expectId++, iter->mId, TEST_LOCATION);
458     }
459     DALI_TEST_EQUALS(expectId, id + 1, TEST_LOCATION);
460   }
461
462   // Check whether leak exist.
463   DALI_TEST_EQUALS(ClassWithId::gRefCount, objectList.size(), TEST_LOCATION);
464
465   // Release memory now.
466   for(auto&& iter : objectList)
467   {
468     delete iter;
469   }
470   objectList.clear();
471   DALI_TEST_EQUALS(ClassWithId::gRefCount, 0, TEST_LOCATION);
472
473   END_TEST;
474 }