Add Internal::IndexedMap
[platform/core/uifw/dali-core.git] / automated-tests / src / dali-internal / utc-Dali-Internal-IndexedIntegerMap.cpp
1 /*
2  * Copyright (c) 2022 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 #include <dali-test-suite-utils.h>
19
20 #include <stdlib.h>
21 #include <string>
22
23 #include <dali/internal/common/indexed-integer-map.h>
24
25 using namespace Dali;
26 using Dali::Internal::IndexedIntegerMap;
27
28 void utc_dali_indexed_integer_map_startup(void)
29 {
30   test_return_value = TET_UNDEF;
31 }
32
33 void utc_dali_indexed_integer_map_cleanup(void)
34 {
35   test_return_value = TET_PASS;
36 }
37
38 int UtcDaliIndexedIntegerMap(void)
39 {
40   IndexedIntegerMap<int> indexedMap;
41   const std::uint32_t    keyFirst  = 111111u;
42   const std::uint32_t    keySecond = 222222u;
43   const std::uint32_t    keyThird  = 333333u;
44   const std::uint32_t    keyFourth = 444444u;
45
46   auto IndexedMapGetValueTest = [](const IndexedIntegerMap<int>& indexedMap, std::uint32_t key, bool registered, int element, const char* location) {
47     const auto& iter = indexedMap.Get(key);
48     DALI_TEST_EQUALS(!(iter == indexedMap.end()), registered, location);
49     if(registered)
50     {
51       DALI_TEST_EQUALS(iter->second, element, location);
52     }
53   };
54
55   // Check. empty state
56   DALI_TEST_EQUALS(0u, indexedMap.Count(), TEST_LOCATION);
57   DALI_TEST_CHECK(indexedMap.Begin() == indexedMap.End());
58   DALI_TEST_CHECK(indexedMap.Empty());
59   DALI_TEST_EQUALS(0u, indexedMap.size(), TEST_LOCATION);
60   DALI_TEST_CHECK(indexedMap.begin() == indexedMap.end());
61   DALI_TEST_CHECK(indexedMap.empty());
62
63   // phase 1 - Regist two element
64   DALI_TEST_CHECK(indexedMap.Register(keyFirst, 1));
65   DALI_TEST_CHECK(indexedMap.Register(keySecond, 2));
66
67   // Get data by key
68   DALI_TEST_EQUALS(2u, indexedMap.Count(), TEST_LOCATION);
69   DALI_TEST_CHECK(!indexedMap.Empty());
70   IndexedMapGetValueTest(indexedMap, keyFirst, true, 1, TEST_LOCATION);
71   IndexedMapGetValueTest(indexedMap, keySecond, true, 2, TEST_LOCATION);
72   IndexedMapGetValueTest(indexedMap, keyThird, false, 0, TEST_LOCATION);
73   IndexedMapGetValueTest(indexedMap, keyFourth, false, 0, TEST_LOCATION);
74
75   // Get data by index
76   DALI_TEST_EQUALS(indexedMap[keyFirst], 1, TEST_LOCATION);
77   DALI_TEST_EQUALS(indexedMap[keySecond], 2, TEST_LOCATION);
78   DALI_TEST_EQUALS(indexedMap.GetElementByIndex(0), 1, TEST_LOCATION);
79   DALI_TEST_EQUALS(indexedMap.GetElementByIndex(1), 2, TEST_LOCATION);
80   DALI_TEST_EQUALS(indexedMap.GetKeyByIndex(0), keyFirst, TEST_LOCATION);
81   DALI_TEST_EQUALS(indexedMap.GetKeyByIndex(1), keySecond, TEST_LOCATION);
82   DALI_TEST_CHECK(indexedMap.GetKeyElementPairByIndex(0) == IndexedIntegerMap<int>::KeyElementPairType(keyFirst, 1));
83   DALI_TEST_CHECK(indexedMap.GetKeyElementPairByIndex(1) == IndexedIntegerMap<int>::KeyElementPairType(keySecond, 2));
84
85   // Const iteration check
86   for(const auto& elem : indexedMap)
87   {
88     if(elem.first == keyFirst)
89     {
90       DALI_TEST_EQUALS(elem.second, 1, TEST_LOCATION);
91     }
92     else if(elem.first == keySecond)
93     {
94       DALI_TEST_EQUALS(elem.second, 2, TEST_LOCATION);
95     }
96     else
97     {
98       DALI_TEST_CHECK(false); // Should not get here
99     }
100   }
101
102   // Iteration and fix data check
103   for(auto&& elem : indexedMap)
104   {
105     if(elem.first == keyFirst)
106     {
107       elem.second += 110;
108     }
109   }
110   // operator[] fix data check
111   indexedMap[keySecond] += 220;
112
113   // Get data by key
114   DALI_TEST_EQUALS(2u, indexedMap.Count(), TEST_LOCATION);
115   IndexedMapGetValueTest(indexedMap, keyFirst, true, 111, TEST_LOCATION);
116   IndexedMapGetValueTest(indexedMap, keySecond, true, 222, TEST_LOCATION);
117   IndexedMapGetValueTest(indexedMap, keyThird, false, 0, TEST_LOCATION);
118   IndexedMapGetValueTest(indexedMap, keyFourth, false, 0, TEST_LOCATION);
119
120   // Get data by index
121   DALI_TEST_EQUALS(indexedMap[keyFirst], 111, TEST_LOCATION);
122   DALI_TEST_EQUALS(indexedMap[keySecond], 222, TEST_LOCATION);
123   DALI_TEST_EQUALS(indexedMap.GetElementByIndex(0), 111, TEST_LOCATION);
124   DALI_TEST_EQUALS(indexedMap.GetElementByIndex(1), 222, TEST_LOCATION);
125   DALI_TEST_EQUALS(indexedMap.GetKeyByIndex(0), keyFirst, TEST_LOCATION);
126   DALI_TEST_EQUALS(indexedMap.GetKeyByIndex(1), keySecond, TEST_LOCATION);
127   DALI_TEST_CHECK(indexedMap.GetKeyElementPairByIndex(0) == IndexedIntegerMap<int>::KeyElementPairType(keyFirst, 111));
128   DALI_TEST_CHECK(indexedMap.GetKeyElementPairByIndex(1) == IndexedIntegerMap<int>::KeyElementPairType(keySecond, 222));
129
130   // Const iteration check
131   for(const auto& elem : indexedMap)
132   {
133     if(elem.first == keyFirst)
134     {
135       DALI_TEST_EQUALS(elem.second, 111, TEST_LOCATION);
136     }
137     else if(elem.first == keySecond)
138     {
139       DALI_TEST_EQUALS(elem.second, 222, TEST_LOCATION);
140     }
141     else
142     {
143       DALI_TEST_CHECK(false); // Should not get here
144     }
145   }
146
147   // phase 2 - Regist two more element
148   DALI_TEST_CHECK(!indexedMap.Register(keyFirst, 11));  // Register failed when we try to insert data with same key
149   DALI_TEST_CHECK(!indexedMap.Register(keySecond, 22)); // Register failed when we try to insert data with same key
150   DALI_TEST_CHECK(indexedMap.Register(keyThird, 3));
151   DALI_TEST_CHECK(indexedMap.Register(keyFourth, 4));
152
153   // Get data by key
154   DALI_TEST_EQUALS(4, indexedMap.Count(), TEST_LOCATION);
155   IndexedMapGetValueTest(indexedMap, keyFirst, true, 111, TEST_LOCATION);
156   IndexedMapGetValueTest(indexedMap, keySecond, true, 222, TEST_LOCATION);
157   IndexedMapGetValueTest(indexedMap, keyThird, true, 3, TEST_LOCATION);
158   IndexedMapGetValueTest(indexedMap, keyFourth, true, 4, TEST_LOCATION);
159
160   // Get elemnt as l-value
161   {
162     auto iter = indexedMap.Get(keyFourth);
163     DALI_TEST_CHECK(iter != indexedMap.end())
164     {
165       iter->second = 444;
166     }
167   }
168
169   // Get data by index
170   DALI_TEST_EQUALS(indexedMap[keyFirst], 111, TEST_LOCATION);
171   DALI_TEST_EQUALS(indexedMap[keySecond], 222, TEST_LOCATION);
172   DALI_TEST_EQUALS(indexedMap[keyThird], 3, TEST_LOCATION);
173   DALI_TEST_EQUALS(indexedMap[keyFourth], 444, TEST_LOCATION);
174   DALI_TEST_EQUALS(indexedMap.GetElementByIndex(0), 111, TEST_LOCATION);
175   DALI_TEST_EQUALS(indexedMap.GetElementByIndex(1), 222, TEST_LOCATION);
176   DALI_TEST_EQUALS(indexedMap.GetElementByIndex(2), 3, TEST_LOCATION);
177   DALI_TEST_EQUALS(indexedMap.GetElementByIndex(3), 444, TEST_LOCATION);
178   DALI_TEST_EQUALS(indexedMap.GetKeyByIndex(0), keyFirst, TEST_LOCATION);
179   DALI_TEST_EQUALS(indexedMap.GetKeyByIndex(1), keySecond, TEST_LOCATION);
180   DALI_TEST_EQUALS(indexedMap.GetKeyByIndex(2), keyThird, TEST_LOCATION);
181   DALI_TEST_EQUALS(indexedMap.GetKeyByIndex(3), keyFourth, TEST_LOCATION);
182   DALI_TEST_CHECK(indexedMap.GetKeyElementPairByIndex(0) == IndexedIntegerMap<int>::KeyElementPairType(keyFirst, 111));
183   DALI_TEST_CHECK(indexedMap.GetKeyElementPairByIndex(1) == IndexedIntegerMap<int>::KeyElementPairType(keySecond, 222));
184   DALI_TEST_CHECK(indexedMap.GetKeyElementPairByIndex(2) == IndexedIntegerMap<int>::KeyElementPairType(keyThird, 3));
185   DALI_TEST_CHECK(indexedMap.GetKeyElementPairByIndex(3) == IndexedIntegerMap<int>::KeyElementPairType(keyFourth, 444));
186
187   // For coverage
188   DALI_TEST_EQUALS(const_cast<const IndexedIntegerMap<int>&>(indexedMap)[keyFirst], 111, TEST_LOCATION);
189
190   // Clear check
191   DALI_TEST_CHECK(!indexedMap.Empty());
192   indexedMap.Clear();
193   DALI_TEST_CHECK(indexedMap.Empty());
194   DALI_TEST_EQUALS(0u, indexedMap.Count(), TEST_LOCATION);
195   IndexedMapGetValueTest(indexedMap, keyFirst, false, 1, TEST_LOCATION);
196   IndexedMapGetValueTest(indexedMap, keySecond, false, 2, TEST_LOCATION);
197   IndexedMapGetValueTest(indexedMap, keyThird, false, 3, TEST_LOCATION);
198   IndexedMapGetValueTest(indexedMap, keyFourth, false, 4, TEST_LOCATION);
199   END_TEST;
200 }
201
202 int UtcDaliIndexedIntegerMapNegative(void)
203 {
204   tet_infoline("Negative test when IndexedIntegerMap access non-exist elements.");
205
206   IndexedIntegerMap<int> indexedMap;
207
208   auto IndexedMapAssertTestWithIndex = [](IndexedIntegerMap<int>& indexedMap, int testIndex) {
209     tet_printf("operator[] test");
210     // Assert when try to access as const operator[] input with not registered key.
211     try
212     {
213       const auto& elem = const_cast<const IndexedIntegerMap<int>&>(indexedMap)[333];
214       if(elem == 0) // Avoid build warning
215       {
216         DALI_TEST_CHECK(false); // Should not get here
217       }
218       DALI_TEST_CHECK(false); // Should not get here
219     }
220     catch(...)
221     {
222       DALI_TEST_CHECK(true); // Asserted
223     }
224     // Assert when try to access as operator[] input with not registered key.
225     try
226     {
227       indexedMap[333] = 0;
228       DALI_TEST_CHECK(false); // Should not get here
229     }
230     catch(...)
231     {
232       DALI_TEST_CHECK(true); // Asserted
233     }
234
235     tet_printf("GetElementByIndex test");
236     // Assert when try to access as GetElementByIndex input with not registered index.
237     try
238     {
239       const auto& elem = indexedMap.GetElementByIndex(testIndex);
240       if(elem == 0) // Avoid build warning
241       {
242         DALI_TEST_CHECK(false); // Should not get here
243       }
244       DALI_TEST_CHECK(false); // Should not get here
245     }
246     catch(...)
247     {
248       DALI_TEST_CHECK(true); // Asserted
249     }
250
251     tet_printf("GetKeyByIndex test");
252     // Assert when try to access as GetKeyByIndex input with not registered index.
253     try
254     {
255       const auto& elem = indexedMap.GetKeyByIndex(testIndex);
256       if(elem == 0) // Avoid build warning
257       {
258         DALI_TEST_CHECK(false); // Should not get here
259       }
260       DALI_TEST_CHECK(false); // Should not get here
261     }
262     catch(...)
263     {
264       DALI_TEST_CHECK(true); // Asserted
265     }
266
267     tet_printf("GetKeyElementPairByIndex test");
268     // Assert when try to access as GetKeyByIndex input with not registered index.
269     try
270     {
271       const auto& elem = indexedMap.GetKeyElementPairByIndex(testIndex);
272       if(elem == IndexedIntegerMap<int>::KeyElementPairType(0, 0)) // Avoid build warning
273       {
274         DALI_TEST_CHECK(false); // Should not get here
275       }
276       DALI_TEST_CHECK(false); // Should not get here
277     }
278     catch(...)
279     {
280       DALI_TEST_CHECK(true); // Asserted
281     }
282   };
283   // Assert test with empty indexedMap.
284   DALI_TEST_CHECK(indexedMap.Empty());
285   IndexedMapAssertTestWithIndex(indexedMap, 0);
286
287   // Register 2 data
288   DALI_TEST_CHECK(indexedMap.Register(111, 1));
289   DALI_TEST_CHECK(indexedMap.Register(222, 2));
290   DALI_TEST_EQUALS(2u, indexedMap.Count(), TEST_LOCATION);
291   IndexedMapAssertTestWithIndex(indexedMap, 2);
292
293   // Test with always-invalid index like -1
294   IndexedMapAssertTestWithIndex(indexedMap, -1);
295
296   END_TEST;
297 }
298
299 int UtcDaliIndexedIntegerMapStressTest(void)
300 {
301   IndexedIntegerMap<int> indexedMap;
302
303   std::vector<std::uint32_t> keyList(2 * (256 + 2));
304
305   // Add 256 kind keys and +- 1
306   for(std::uint32_t i = 0; i < 256 + 2; i++)
307   {
308     // Intention overflow here
309     keyList[i]           = i - 1;
310     keyList[i + 256 + 2] = ((i - 1) << 24) + (((i - 1) >> 8) & 15);
311     if(i == 1)
312     {
313       //To avoid same Key
314       keyList[i + 256 + 2] = 0x0f0f0f0f;
315     }
316     if(i == 257)
317     {
318       //To avoid same Key
319       keyList[i + 256 + 2] = 0xf0f0f0f0;
320     }
321   }
322
323   auto IndexedMapGetValueTest = [](const IndexedIntegerMap<int>& indexedMap, std::uint32_t key, bool registered, int element) {
324     const auto& iter = indexedMap.Get(key);
325     DALI_TEST_CHECK(!(iter == indexedMap.end()) == registered);
326     if(registered)
327     {
328       DALI_TEST_CHECK(iter->second == element);
329     }
330   };
331
332   for(std::size_t i = 0; i < keyList.size(); i++)
333   {
334     // We don't need to check whole key. Just compare near 0 and 256+2
335     for(std::size_t j = 0; j < i && j < 4; j++)
336     {
337       DALI_TEST_CHECK(!indexedMap.Register(keyList[j], -j - 1));
338     }
339     for(std::size_t j = 256; j < i && j < 256 + 6; j++)
340     {
341       DALI_TEST_CHECK(!indexedMap.Register(keyList[j], -j - 1));
342     }
343
344     // Regist i'th keylist
345     DALI_TEST_CHECK(indexedMap.Register(keyList[i], i));
346
347     // We don't need to check whole key. Just compare near 0 and 256+2 and end and i
348     for(std::size_t j = 0; j < keyList.size() && j < 20; j++)
349     {
350       IndexedMapGetValueTest(indexedMap, keyList[j], j <= i, j);
351     }
352     for(std::size_t j = 256 - 18; j < keyList.size() && j < 256 + 22; j++)
353     {
354       IndexedMapGetValueTest(indexedMap, keyList[j], j <= i, j);
355     }
356     for(std::size_t j = keyList.size() - 20; j < keyList.size(); j++)
357     {
358       IndexedMapGetValueTest(indexedMap, keyList[j], j <= i, j);
359     }
360     // When i < 20 overflow occured, but dont care.
361     for(std::size_t j = i - 20; j < keyList.size() && j < i + 20; j++)
362     {
363       IndexedMapGetValueTest(indexedMap, keyList[j], j <= i, j);
364     }
365
366     // Keylist have over 500 kind of keys. Print debug rarely.
367     if(i % 50 == 0)
368     {
369       tet_printf("%u / %u pass\n", i, keyList.size());
370     }
371   }
372
373   END_TEST;
374 }