2 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <dali-test-suite-utils.h>
19 #include <dali/public-api/dali-core.h>
21 // Internal headers are allowed here
22 #include <dali/internal/common/fixed-size-memory-pool.h>
26 void utc_dali_internal_fixedsizememorypool_startup(void)
28 test_return_value = TET_UNDEF;
31 void utc_dali_internal_fixedsizememorypool_cleanup(void)
33 test_return_value = TET_PASS;
38 unsigned int gTestObjectConstructed = 0;
39 unsigned int gTestObjectDestructed = 0;
40 unsigned int gTestObjectMethod = 0;
41 unsigned int gTestObjectDataAccess = 0;
50 gTestObjectConstructed++;
55 gTestObjectDestructed++;
68 gTestObjectDataAccess++;
78 int UtcDaliFixedSizeMemoryPoolCreate(void)
80 gTestObjectConstructed = 0;
81 gTestObjectDestructed = 0;
82 gTestObjectMethod = 0;
83 gTestObjectDataAccess = 0;
85 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size);
87 TestObject* testObject1 = new(memoryPool.Allocate()) TestObject();
88 DALI_TEST_CHECK(testObject1);
89 DALI_TEST_EQUALS(gTestObjectConstructed, 1U, TEST_LOCATION);
91 testObject1->Method();
92 DALI_TEST_EQUALS(gTestObjectMethod, 1U, TEST_LOCATION);
94 testObject1->DataAccess();
95 DALI_TEST_EQUALS(gTestObjectDataAccess, 1U, TEST_LOCATION);
97 testObject1->~TestObject();
98 memoryPool.Free(testObject1);
99 DALI_TEST_EQUALS(gTestObjectDestructed, 1U, TEST_LOCATION);
104 int UtcDaliFixedSizeMemoryPoolStressTest01(void)
106 gTestObjectConstructed = 0;
107 gTestObjectDestructed = 0;
108 gTestObjectMethod = 0;
109 gTestObjectDataAccess = 0;
111 const size_t initialCapacity = 32;
112 const unsigned int numObjects = 7 * 1024 * 1024;
114 // Don't specify key layout
115 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size, initialCapacity /*, default max cap(1M) */);
117 Dali::Vector<TestObject*> objects;
118 objects.Reserve(numObjects);
120 for(unsigned int i = 0; i < numObjects; ++i)
122 TestObject* testObject = new(memoryPool.Allocate()) TestObject();
123 DALI_TEST_CHECK(testObject);
125 objects.PushBack(testObject);
127 uint32_t key = memoryPool.GetKeyFromPtr(testObject);
128 DALI_TEST_EQUALS(key, i, TEST_LOCATION);
129 void* ptr = memoryPool.GetPtrFromKey(key);
130 DALI_TEST_EQUALS(static_cast<void*>(testObject), ptr, TEST_LOCATION);
133 DALI_TEST_EQUALS(gTestObjectConstructed, numObjects, TEST_LOCATION);
135 for(unsigned int i = 0; i < numObjects; ++i)
137 objects[i]->~TestObject();
138 memoryPool.Free(objects[i]);
141 DALI_TEST_EQUALS(gTestObjectDestructed, numObjects, TEST_LOCATION);
146 int UtcDaliFixedSizeMemoryPoolStressTest02(void)
148 gTestObjectConstructed = 0;
149 gTestObjectDestructed = 0;
150 gTestObjectMethod = 0;
151 gTestObjectDataAccess = 0;
153 const size_t initialCapacity = 32;
154 const unsigned int numObjects = 7 * 1024 * 1024;
156 // Maxing the number of blocks and providing key layout.
157 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size, initialCapacity, 4194304, 27);
159 Dali::Vector<TestObject*> objects;
160 objects.Reserve(numObjects);
162 uint32_t blockSizes[] = {32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304};
163 unsigned int curBlock = 0;
164 unsigned int curBlockStartIndex = 0;
165 for(unsigned int i = 0; i < numObjects; ++i)
167 TestObject* testObject = new(memoryPool.Allocate()) TestObject();
168 DALI_TEST_CHECK(testObject);
170 objects.PushBack(testObject);
172 if(i == curBlockStartIndex + blockSizes[curBlock])
174 curBlockStartIndex += blockSizes[curBlock++];
175 tet_printf("Next Block [%d] size %d\n", curBlock, blockSizes[curBlock]);
176 tet_printf(" StartIdx [%d]\n", curBlockStartIndex);
178 uint32_t key = memoryPool.GetKeyFromPtr(testObject);
179 DALI_TEST_EQUALS((key & 0xf8000000) >> 27, curBlock, TEST_LOCATION);
180 DALI_TEST_EQUALS((key & 0x07ffffff), i - curBlockStartIndex, TEST_LOCATION);
181 void* ptr = memoryPool.GetPtrFromKey(key);
182 DALI_TEST_EQUALS(static_cast<void*>(testObject), ptr, TEST_LOCATION);
185 DALI_TEST_EQUALS(gTestObjectConstructed, numObjects, TEST_LOCATION);
187 for(unsigned int i = 0; i < numObjects; ++i)
189 objects[i]->~TestObject();
190 memoryPool.Free(objects[i]);
193 DALI_TEST_EQUALS(gTestObjectDestructed, numObjects, TEST_LOCATION);
198 int UtcDaliFixedSizeMemoryPoolStressTest03(void)
200 gTestObjectConstructed = 0;
201 gTestObjectDestructed = 0;
202 gTestObjectMethod = 0;
203 gTestObjectDataAccess = 0;
205 const size_t initialCapacity = 32;
206 const size_t maximumCapacity = 1024; // @todo smaller max cap means higher number of blocks, and bit width should change accordingly.
208 const unsigned int numObjects = 1024 * 1024;
210 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size, initialCapacity, maximumCapacity);
212 Dali::Vector<TestObject*> objects;
213 objects.Reserve(numObjects);
215 for(unsigned int i = 0; i < numObjects; ++i)
217 TestObject* testObject = new(memoryPool.Allocate()) TestObject();
218 DALI_TEST_CHECK(testObject);
220 uint32_t key = memoryPool.GetKeyFromPtr(testObject);
221 DALI_TEST_EQUALS(key, i, TEST_LOCATION);
222 DALI_TEST_EQUALS((void*)testObject, (void*)memoryPool.GetPtrFromKey(i), TEST_LOCATION);
223 objects.PushBack(testObject);
226 DALI_TEST_EQUALS(gTestObjectConstructed, numObjects, TEST_LOCATION);
228 for(unsigned int i = 0; i < numObjects; ++i)
230 objects[i]->~TestObject();
231 memoryPool.Free(objects[i]);
234 DALI_TEST_EQUALS(gTestObjectDestructed, numObjects, TEST_LOCATION);
239 int UtcDaliFixedSizeMemoryPoolPtrFromKeyP01(void)
241 gTestObjectConstructed = 0;
242 gTestObjectDestructed = 0;
243 gTestObjectMethod = 0;
244 gTestObjectDataAccess = 0;
246 const size_t initialCapacity = 32;
247 const unsigned int numObjects = 1024;
249 // Maxing the number of blocks and providing key layout.
250 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size, initialCapacity, 4194304, 27);
252 Dali::Vector<TestObject*> objects;
253 objects.Reserve(numObjects);
255 uint32_t blockSizes[] = {32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304};
256 unsigned int curBlock = 0;
257 unsigned int curBlockStartIndex = 0;
258 for(unsigned int i = 0; i < numObjects; ++i)
260 TestObject* testObject = new(memoryPool.Allocate()) TestObject();
261 DALI_TEST_CHECK(testObject);
263 objects.PushBack(testObject);
265 if(i == curBlockStartIndex + blockSizes[curBlock])
267 curBlockStartIndex += blockSizes[curBlock++];
268 tet_printf("Next Block [%d] size %d\n", curBlock, blockSizes[curBlock]);
269 tet_printf(" StartIdx [%d]\n", curBlockStartIndex);
271 uint32_t key = memoryPool.GetKeyFromPtr(testObject);
272 DALI_TEST_EQUALS((key & 0xf8000000) >> 27, curBlock, TEST_LOCATION);
273 DALI_TEST_EQUALS((key & 0x07ffffff), i - curBlockStartIndex, TEST_LOCATION);
274 void* ptr = memoryPool.GetPtrFromKey(key);
275 DALI_TEST_EQUALS(static_cast<void*>(testObject), ptr, TEST_LOCATION);
278 DALI_TEST_EQUALS(gTestObjectConstructed, numObjects, TEST_LOCATION);
282 int UtcDaliFixedSizeMemoryPoolKeyFromPtrN01(void)
284 gTestObjectConstructed = 0;
285 gTestObjectDestructed = 0;
286 gTestObjectMethod = 0;
287 gTestObjectDataAccess = 0;
289 const size_t initialCapacity = 32;
290 const unsigned int numObjects = 1024;
292 // Maxing the number of blocks and providing key layout.
293 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size, initialCapacity, 4194304, 27);
295 Dali::Vector<TestObject*> objects;
296 objects.Reserve(numObjects);
298 TestObject* testObject = nullptr;
299 for(unsigned int i = 0; i < numObjects; ++i)
301 testObject = new(memoryPool.Allocate()) TestObject();
302 objects.PushBack(testObject);
305 uint32_t key = memoryPool.GetKeyFromPtr(nullptr);
306 DALI_TEST_EQUALS(key, (uint32_t)-1, TEST_LOCATION);
308 testObject += 1500; // Ensure it's outside block
309 key = memoryPool.GetKeyFromPtr(testObject);
310 DALI_TEST_EQUALS(key, (uint32_t)-1, TEST_LOCATION);
315 int UtcDaliFixedSizeMemoryPoolPtrFromKeyN01(void)
317 gTestObjectConstructed = 0;
318 gTestObjectDestructed = 0;
319 gTestObjectMethod = 0;
320 gTestObjectDataAccess = 0;
322 const size_t initialCapacity = 32;
323 const unsigned int numObjects = 1024;
325 // Maxing the number of blocks and providing key layout.
326 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size, initialCapacity, 4194304, 27);
328 Dali::Vector<TestObject*> objects;
329 objects.Reserve(numObjects);
331 TestObject* testObject = nullptr;
332 for(unsigned int i = 0; i < numObjects; ++i)
334 testObject = new(memoryPool.Allocate()) TestObject();
335 objects.PushBack(testObject);
338 void* object = memoryPool.GetPtrFromKey((uint32_t)-1);
339 DALI_TEST_CHECK(object == nullptr);
341 uint32_t key = (8 << 27) | 33; // Index 33 in block 8 should be out of range
343 object = memoryPool.GetPtrFromKey(key);
344 DALI_TEST_CHECK(object == nullptr);
349 int UtcDaliFixedSizeMemoryPoolKeyFromPtrP02(void)
351 gTestObjectConstructed = 0;
352 gTestObjectDestructed = 0;
353 gTestObjectMethod = 0;
354 gTestObjectDataAccess = 0;
356 const size_t initialCapacity = 32;
357 const size_t maximumCapacity = 1024;
358 const unsigned int numObjects = 1024;
360 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size, initialCapacity, maximumCapacity, 0xffffffff /*No block limit*/);
362 Dali::Vector<TestObject*> objects;
363 objects.Reserve(numObjects);
365 TestObject* testObject;
366 TestObject* firstObject;
368 for(unsigned int i = 0; i < numObjects; ++i)
370 testObject = new(memoryPool.Allocate()) TestObject();
373 firstObject = testObject;
376 objects.PushBack(testObject);
379 uint32_t key = memoryPool.GetKeyFromPtr(testObject);
380 // Check key == index with no block id
381 DALI_TEST_EQUALS(key, 1023, TEST_LOCATION);
383 key = memoryPool.GetKeyFromPtr(firstObject);
384 // Check key == index with no block id
385 DALI_TEST_EQUALS(key, 0, TEST_LOCATION);
390 int UtcDaliFixedSizeMemoryPoolKeyFromPtrN02(void)
392 gTestObjectConstructed = 0;
393 gTestObjectDestructed = 0;
394 gTestObjectMethod = 0;
395 gTestObjectDataAccess = 0;
397 const size_t initialCapacity = 32;
398 const size_t maximumCapacity = 512;
399 const unsigned int numObjects = 1024;
401 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size, initialCapacity, maximumCapacity, 0xffffffff /*No block limit*/);
403 Dali::Vector<TestObject*> objects;
404 objects.Reserve(numObjects);
406 TestObject* testObject;
407 TestObject* firstObject;
409 for(unsigned int i = 0; i < numObjects; ++i)
411 testObject = new(memoryPool.Allocate()) TestObject();
414 firstObject = testObject;
417 objects.PushBack(testObject);
421 uint32_t key = memoryPool.GetKeyFromPtr(firstObject);
422 DALI_TEST_EQUALS(key, (uint32_t)-1, TEST_LOCATION);
424 testObject += 1024; // Ensure it's outside the block
425 key = memoryPool.GetKeyFromPtr(testObject);
426 DALI_TEST_EQUALS(key, (uint32_t)-1, TEST_LOCATION);
428 key = memoryPool.GetKeyFromPtr(nullptr);
429 DALI_TEST_EQUALS(key, (uint32_t)-1, TEST_LOCATION);
434 int UtcDaliFixedSizeMemoryPoolPtrFromKeyP02(void)
436 gTestObjectConstructed = 0;
437 gTestObjectDestructed = 0;
438 gTestObjectMethod = 0;
439 gTestObjectDataAccess = 0;
441 const size_t initialCapacity = 32;
442 const size_t maximumCapacity = 1024;
443 const unsigned int numObjects = 1024;
445 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size, initialCapacity, maximumCapacity, 0xffffffff /*No block limit*/);
447 Dali::Vector<TestObject*> objects;
448 objects.Reserve(numObjects);
450 TestObject* testObject;
451 TestObject* firstObject;
453 for(unsigned int i = 0; i < numObjects; ++i)
455 testObject = new(memoryPool.Allocate()) TestObject();
458 firstObject = testObject;
461 objects.PushBack(testObject);
464 void* ptr = memoryPool.GetPtrFromKey(0);
465 DALI_TEST_EQUALS(ptr, (void*)firstObject, TEST_LOCATION);
467 ptr = memoryPool.GetPtrFromKey(1023);
468 DALI_TEST_EQUALS(ptr, (void*)(testObject), TEST_LOCATION);
473 int UtcDaliFixedSizeMemoryPoolPtrFromKeyN02(void)
475 tet_infoline("Negative Test of PtrFromKey in a memory pool with unlimited blocks");
477 gTestObjectConstructed = 0;
478 gTestObjectDestructed = 0;
479 gTestObjectMethod = 0;
480 gTestObjectDataAccess = 0;
482 const size_t initialCapacity = 32;
483 const size_t maximumCapacity = 1024;
484 const unsigned int numObjects = 1024;
486 Internal::FixedSizeMemoryPool memoryPool(Internal::TypeSizeWithAlignment<TestObject>::size, initialCapacity, maximumCapacity, 0xffffffff /*No block limit*/);
488 Dali::Vector<TestObject*> objects;
489 objects.Reserve(numObjects);
491 TestObject* testObject;
493 // There is always 1 block allocated, so testing indices in this range won't fail
494 void* ptr = memoryPool.GetPtrFromKey(33);
495 DALI_TEST_CHECK(ptr == nullptr);
497 for(unsigned int i = 0; i < numObjects; ++i)
499 testObject = new(memoryPool.Allocate()) TestObject();
500 objects.PushBack(testObject);
503 ptr = memoryPool.GetPtrFromKey(1024);
504 DALI_TEST_CHECK(ptr != nullptr); // this key successfully finds a block, even though
505 // it's not been alloc'd.
507 ptr = memoryPool.GetPtrFromKey(204029); // Check a key outside the allocd range.
508 DALI_TEST_CHECK(ptr == nullptr);