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