int main(int argc, char *argv[]) { le_mem_PoolRef_t idPool, colourPool; idObj_t* idsPtr[ID_POOL_SIZE + NUM_EXTRA_ID] = {NULL}; colourObj_t* coloursPtr[COLOUR_POOL_SIZE] = {NULL}; unsigned int i = 0; unsigned int numRelease = 0; printf("\n"); printf("*** Unit Test for le_mem module. ***\n"); // // Create multiple pools. // idPool = le_mem_CreatePool("ID Pool", sizeof(idObj_t)); colourPool = le_mem_CreatePool("Colour Pool", sizeof(colourObj_t)); printf("Created two memory pools.\n"); // // Expand the pools. // idPool = le_mem_ExpandPool(idPool, ID_POOL_SIZE); colourPool = le_mem_ExpandPool(colourPool, COLOUR_POOL_SIZE); printf("Expanded all pools.\n"); // // Set destructors. // le_mem_SetDestructor(idPool, IdDestructor); // // Spawn child process and perform Assert allocation until failure. // pid_t pID = fork(); if (pID == 0) { // This is the child. // Allocate more than the available objects so the assert will kill the process. for (i = 0; i < ID_POOL_SIZE + 1; i++) { idsPtr[i] = le_mem_AssertAlloc(idPool); } return LE_OK; } else { int status; // wait for the child to terminate. wait(&status); if ( WEXITSTATUS(status) == EXIT_FAILURE ) // Child terminated with an error. { printf("Assert allocation performed correctly.\n"); } else { printf("Assert allocation incorrect: %d", __LINE__); return LE_FAULT; } } // // Allocate all objects. // for (i = 0; i < ID_POOL_SIZE; i++) { idsPtr[i] = le_mem_TryAlloc(idPool); if (idsPtr[i] == NULL) { printf("Allocation error: %d", __LINE__); return LE_FAULT; } idsPtr[i]->id = i; } for (i = 0; i < COLOUR_POOL_SIZE; i++) { coloursPtr[i] = le_mem_TryAlloc(colourPool); if (coloursPtr[i] == NULL) { printf("Allocation error: %d", __LINE__); return LE_FAULT; } coloursPtr[i]->r = i; coloursPtr[i]->g = i + 1; coloursPtr[i]->b = i + 2; } printf("Allocated all objects from all pools.\n"); // // Check objects // for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i]->id != i) { printf("Object error: %d", __LINE__); return LE_FAULT; } } for (i = 0; i < COLOUR_POOL_SIZE; i++) { if ( (coloursPtr[i]->r != i) || (coloursPtr[i]->g != i+1) || (coloursPtr[i]->b != i+2) ) { printf("Object error: %d", __LINE__); return LE_FAULT; } } printf("Checked all objects in pools.\n"); // // Randomly release some objects. // { //seed the random number generator with the clock srand((unsigned int)clock()); idObj_t* objPtr; size_t numNotReleased = 0; NumRelease = 0; for (i = 0; i < ID_POOL_SIZE; i++) { objPtr = idsPtr[i]; if (rand() < REMOVE_THRESHOLD) { // Increase the ref number for these objects. le_mem_AddRef(objPtr); // These objects should not get freed. numNotReleased++; } else { idsPtr[i] = NULL; } // Release all objects but only objects that did not have their ref count increased will be released. le_mem_Release(objPtr); } if (NumRelease != ID_POOL_SIZE - numNotReleased) { printf("Released objects incorrectly: %d", __LINE__); return LE_FAULT; } // Release the rest of the objects. for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i] != NULL) { le_mem_Release(idsPtr[i]); idsPtr[i] = NULL; } } // Check the number of free objects. le_mem_PoolStats_t stats; le_mem_GetStats(idPool, &stats); if (stats.numFree != ID_POOL_SIZE) { printf("Released objects incorrectly: %d", __LINE__); return LE_FAULT; } // Spawn child process and try to release an object that is already released. pid_t pID = fork(); if (pID == 0) { // This is the child. // This allocation should fail and kill the process. le_mem_Release(objPtr); return LE_OK; } else { int status; // wait for the child to terminate. wait(&status); if ( WEXITSTATUS(status) == EXIT_FAILURE ) // Child terminated with an error. { printf("Ref count correct.\n"); } else { printf("Ref count incorrect: %d", __LINE__); return LE_FAULT; } } } printf("Released objects according to ref counts correctly.\n"); printf("Checked that destructors were called correctly.\n"); // // Try allocate until full. // for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i] == NULL) { idsPtr[i] = le_mem_TryAlloc(idPool); if (idsPtr[i] == NULL) { printf("Allocation error: %d.", __LINE__); return LE_FAULT; } } } // The pool should now be empty. if (le_mem_TryAlloc(idPool) != NULL) { printf("Allocation error: %d.", __LINE__); return LE_FAULT; } printf("Tried allocating from empty pool.\n"); // // Force allocate. // le_mem_SetNumObjsToForce(idPool, FORCE_SIZE); for (i = ID_POOL_SIZE; i < ID_POOL_SIZE + NUM_EXTRA_ID; i++) { idsPtr[i] = le_mem_ForceAlloc(idPool); if (idsPtr[i] == NULL) { printf("Allocation error: %d.", __LINE__); return LE_FAULT; } } printf("Forced allocated objects.\n"); // // Get stats. // le_mem_PoolStats_t stats; le_mem_GetStats(idPool, &stats); if ( (stats.numAllocs != ID_POOL_SIZE + NUM_EXTRA_ID + NumRelease) || (stats.numOverflows != (unsigned int)ceil(((1.0*NUM_EXTRA_ID / FORCE_SIZE)))) || (stats.numFree != (stats.numOverflows*FORCE_SIZE) % NUM_EXTRA_ID) ) { printf("Stats are incorrect: %d", __LINE__); return LE_FAULT; } printf("Stats are correct.\n"); // // Get pool size. // if (le_mem_GetTotalNumObjs(idPool) != ID_POOL_SIZE + (stats.numOverflows * FORCE_SIZE)) { printf("Pool size incorrect: %d", __LINE__); return LE_FAULT; } printf("Checked pool size.\n"); // // Get object size. // if (le_mem_GetObjectSize(idPool) != sizeof(idObj_t)) { printf("Object size incorrect: %d", __LINE__); return LE_FAULT; } printf("Checked object size.\n"); // // Reset stats. // { size_t numFree = stats.numFree; le_mem_ResetStats(idPool); le_mem_GetStats(idPool, &stats); if ( (stats.numAllocs != 0) || (stats.numOverflows != 0) || (stats.numFree != numFree) ) { printf("Stats are incorrect: %d", __LINE__); return LE_FAULT; } } printf("Reset stats correctly.\n"); // // Create sub-pool. // // Release some objs from the super-pool in a random manner. numRelease = 0; for (i = 0; i < COLOUR_POOL_SIZE; i++) { if (rand() < REMOVE_THRESHOLD) { le_mem_Release(coloursPtr[i]); coloursPtr[i] = NULL; numRelease++; } } // Create the sub-pool. le_mem_PoolRef_t colourSubPool1 = le_mem_CreateSubPool(colourPool, "Colour sub-pool", numRelease); // // Check sub-pools and super-pool. // if ( (le_mem_GetTotalNumObjs(colourSubPool1) != numRelease) || (le_mem_GetTotalNumObjs(colourPool) != COLOUR_POOL_SIZE) ) { printf("Sub-pool incorrect: %d", __LINE__); return LE_FAULT; } printf("Sub-pool created correctly.\n"); // // Create second sub-pool. // // Release the rest of the objects from the super-pool. for (i = 0; i < COLOUR_POOL_SIZE; i++) { if (coloursPtr[i] != NULL) { le_mem_Release(coloursPtr[i]); coloursPtr[i] = NULL; } } // Create another sub-pool. le_mem_PoolRef_t colourSubPool2 = le_mem_CreateSubPool(colourPool, "Second sub-pool", COLOUR_POOL_SIZE - numRelease); printf("Created second sub-pool.\n"); // // Expand the sub-pool causing the super-pool to expand. // le_mem_ExpandPool(colourSubPool2, NUM_EXPAND_SUB_POOL); // // Allocate from sub-pool. // for (i = 0; i < COLOUR_POOL_SIZE - numRelease; i++) { coloursPtr[i] = le_mem_TryAlloc(colourSubPool2); if (coloursPtr[i] == NULL) { printf("Error allocating from sub-pool: %d", __LINE__); return LE_FAULT; } } // // Check pools. // le_mem_GetStats(colourPool, &stats); if ( (le_mem_GetTotalNumObjs(colourPool) != COLOUR_POOL_SIZE + NUM_EXPAND_SUB_POOL) || (stats.numFree != 0) ) { printf("Error in super-pool: %d", __LINE__); return LE_FAULT; } le_mem_GetStats(colourSubPool1, &stats); if ( (le_mem_GetTotalNumObjs(colourSubPool1) != numRelease) || (stats.numFree != numRelease) ) { printf("Error in sub-pool: %d", __LINE__); return LE_FAULT; } le_mem_GetStats(colourSubPool2, &stats); if ( (le_mem_GetTotalNumObjs(colourSubPool2) != COLOUR_POOL_SIZE - numRelease + NUM_EXPAND_SUB_POOL) || (stats.numFree != NUM_EXPAND_SUB_POOL) ) { printf("Error in sub-pool: %d", __LINE__); return LE_FAULT; } printf("Expanded sub-pool correctly.\n"); printf("Allocated from sub-pools correctly.\n"); // Try Allocating from empty super-pool. if (le_mem_TryAlloc(colourPool) != NULL) { printf("Error in super-pool: %d", __LINE__); return LE_FAULT; } // // Delete sub-pool. // le_mem_DeleteSubPool(colourSubPool1); // Allocate from the super-pool. for (i = 0; i < NUM_ALLOC_SUPER_POOL; i++) { coloursPtr[numRelease] = le_mem_AssertAlloc(colourPool); } // // Check pools. // le_mem_GetStats(colourPool, &stats); if ( (stats.numFree != numRelease - NUM_ALLOC_SUPER_POOL) ) { printf("Error in super-pool: %d", __LINE__); return LE_FAULT; } le_mem_GetStats(colourSubPool2, &stats); if ( (le_mem_GetTotalNumObjs(colourSubPool2) != COLOUR_POOL_SIZE - numRelease + NUM_EXPAND_SUB_POOL) || (stats.numFree != NUM_EXPAND_SUB_POOL) ) { printf("Error in sub-pool: %d", __LINE__); return LE_FAULT; } printf("Deleted sub-pool correctly.\n"); // // Re-create sub-pool causing super pool to expand. // colourSubPool1 = le_mem_CreateSubPool(colourPool, "First sub-pool", numRelease + NUM_EXPAND_SUB_POOL); if ( (le_mem_GetTotalNumObjs(colourSubPool1) != numRelease + NUM_EXPAND_SUB_POOL) || (le_mem_GetTotalNumObjs(colourPool) != COLOUR_POOL_SIZE + 2*NUM_EXPAND_SUB_POOL + NUM_ALLOC_SUPER_POOL) ) { printf("Error re-creating sub-pool: %d", __LINE__); return LE_FAULT; } printf("Successfully recreated sub-pool.\n"); // // Search for pools by name. // if ( (idPool != le_mem_FindPool("ID Pool")) || (colourSubPool1 != le_mem_FindPool("First sub-pool")) ) { printf("Error finding pools by name: %d", __LINE__); return LE_FAULT; } printf("Successfully searched for pools by name.\n"); printf("*** Unit Test for le_mem module passed. ***\n"); printf("\n"); return LE_OK; }
static void TestPools ( le_mem_PoolRef_t idPool, ///< [IN] ID pool le_mem_PoolRef_t colourPool, ///< [IN] Colour pool le_mem_PoolRef_t stringPool ///< [IN] String pool ) { idObj_t* idsPtr[ID_POOL_SIZE + NUM_EXTRA_ID] = {NULL}; colourObj_t* coloursPtr[COLOUR_POOL_SIZE] = {NULL}; char* stringsPtr[4*STRING_POOL_SIZE] = {NULL}; unsigned int i = 0; unsigned int numRelease = 0; LE_TEST_BEGIN_SKIP(!LE_CONFIG_IS_ENABLED(LE_CONFIG_LINUX), 1); #if LE_CONFIG_LINUX // // Spawn child process and perform Assert allocation until failure. // pid_t pID = fork(); if (pID == 0) { // This is the child. // Allocate more than the available objects so the assert will kill the process. for (i = 0; i < ID_POOL_SIZE + 1; i++) { idsPtr[i] = le_mem_AssertAlloc(idPool); } exit(EXIT_SUCCESS); } else { int status; // wait for the child to terminate. wait(&status); LE_TEST_OK(WEXITSTATUS(status) == EXIT_FAILURE, "Assert allocation"); } #endif /* end LE_CONFIG_LINUX */ LE_TEST_END_SKIP(); // // Allocate all objects. // for (i = 0; i < ID_POOL_SIZE; i++) { idsPtr[i] = le_mem_TryAlloc(idPool); LE_TEST_OK(NULL != idsPtr[i], "Allocate id %d", i); if (NULL != idsPtr[i]) { idsPtr[i]->id = i; } } for (i = 0; i < COLOUR_POOL_SIZE; i++) { coloursPtr[i] = le_mem_TryAlloc(colourPool); LE_TEST_OK(NULL != coloursPtr[i], "Allocate color %d", i); if (NULL != idsPtr[i]) { coloursPtr[i]->r = i; coloursPtr[i]->g = i + 1; coloursPtr[i]->b = i + 2; } } // // Check objects // for (i = 0; i < ID_POOL_SIZE; i++) { LE_TEST_OK(idsPtr[i] && (idsPtr[i]->id == i), "Check id %d", i); } for (i = 0; i < COLOUR_POOL_SIZE; i++) { LE_TEST_OK(coloursPtr[i] && ((coloursPtr[i]->r == i) && (coloursPtr[i]->g == i+1) && (coloursPtr[i]->b == i+2)), "Check color %d", i); } // // Randomly release some objects. // { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); //seed the random number generator with the clock srand((unsigned int)(ts.tv_nsec/1000)^ts.tv_sec); idObj_t* objPtr; unsigned int numNotReleased = 0; NumRelease = 0; for (i = 0; i < ID_POOL_SIZE; i++) { objPtr = idsPtr[i]; if (rand() < REMOVE_THRESHOLD) { // Increase the ref number for these objects. le_mem_AddRef(objPtr); // These objects should not get freed. numNotReleased++; } else { idsPtr[i] = NULL; } // Release all objects but only objects that did not have their ref count increased will be released. le_mem_Release(objPtr); } LE_TEST_OK((NumRelease == ID_POOL_SIZE - numNotReleased), "Released %u/%d objects (%u remaining)", NumRelease, ID_POOL_SIZE, numNotReleased); // Release the rest of the objects. for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i] != NULL) { le_mem_Release(idsPtr[i]); idsPtr[i] = NULL; } } // Check the number of free objects. LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND || !LE_CONFIG_IS_ENABLED(LE_CONFIG_MEM_POOL_STATS), 1); le_mem_PoolStats_t stats; le_mem_GetStats(idPool, &stats); LE_TEST_OK((stats.numFree == ID_POOL_SIZE), "Released all objects correctly"); LE_TEST_END_SKIP(); LE_TEST_BEGIN_SKIP(!LE_CONFIG_IS_ENABLED(LE_CONFIG_LINUX), 2); #if LE_CONFIG_LINUX // Spawn child process and try to release an object that is already released. pid_t pID = fork(); if (pID == 0) { // This is the child. // This allocation should fail and kill the process. le_mem_Release(objPtr); exit(EXIT_SUCCESS); } else { int status; // wait for the child to terminate. wait(&status); LE_TEST_OK(( WEXITSTATUS(status) == EXIT_FAILURE ), "Double free terminates process"); // Child terminated with an error. } #endif /* end LE_CONFIG_LINUX */ LE_TEST_END_SKIP(); } // // Try allocate until full. // for (i = 0; i < ID_POOL_SIZE; i++) { if (NULL == idsPtr[i]) { idsPtr[i] = le_mem_TryAlloc(idPool); LE_TEST_OK(NULL != idsPtr[i], "Allocate id %d", i); } } // The pool should now be empty. LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND, 1); LE_TEST_OK (le_mem_TryAlloc(idPool) == NULL, "Allocate from empty pool"); LE_TEST_END_SKIP(); // // Force allocate. // le_mem_SetNumObjsToForce(idPool, FORCE_SIZE); for (i = ID_POOL_SIZE; i < ID_POOL_SIZE + NUM_EXTRA_ID; i++) { idsPtr[i] = le_mem_ForceAlloc(idPool); LE_TEST_OK((NULL != idsPtr[i]), "Force alloc id %d", i); } // // Get stats. // le_mem_PoolStats_t stats; LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND || !LE_CONFIG_IS_ENABLED(LE_CONFIG_MEM_POOL_STATS), 2); le_mem_GetStats(idPool, &stats); LE_TEST_OK(((stats.numAllocs == ID_POOL_SIZE + NUM_EXTRA_ID + NumRelease) && (stats.numOverflows == (unsigned int)ceil(((1.0*NUM_EXTRA_ID / FORCE_SIZE)))) && (stats.numFree == (stats.numOverflows*FORCE_SIZE) % NUM_EXTRA_ID)), "Check stats"); // // Get pool size. // LE_TEST_OK((le_mem_GetObjectCount(idPool) == ID_POOL_SIZE + (stats.numOverflows * FORCE_SIZE)), "Check pool size"); LE_TEST_END_SKIP(); // // Get object size. // LE_TEST_OK((le_mem_GetObjectSize(idPool) == sizeof(idObj_t)), "Check object size"); // // Reset stats. // LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND || !LE_CONFIG_IS_ENABLED(LE_CONFIG_MEM_POOL_STATS), 1); { size_t numFree = stats.numFree; le_mem_ResetStats(idPool); le_mem_GetStats(idPool, &stats); LE_TEST_OK(((stats.numAllocs == 0) && (stats.numOverflows == 0) && (stats.numFree == numFree) ), "Check reset stats"); } LE_TEST_END_SKIP(); // // Create sub-pool. // // Release some objs from the super-pool in a random manner. numRelease = 0; for (i = 0; i < COLOUR_POOL_SIZE; i++) { if (rand() < REMOVE_THRESHOLD) { le_mem_Release(coloursPtr[i]); coloursPtr[i] = NULL; numRelease++; } } // Create the sub-pool. le_mem_PoolRef_t colourSubPool1 = le_mem_CreateSubPool(colourPool, "Colour sub-pool", numRelease); // // Check sub-pools and super-pool. // LE_TEST_OK(NULL != colourSubPool1, "Create sub-pool"); LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND, 1); LE_TEST_OK(( (le_mem_GetObjectCount(colourSubPool1) == numRelease) && (le_mem_GetObjectCount(colourPool) == COLOUR_POOL_SIZE) ), "Check sub-pool size"); LE_TEST_END_SKIP(); // // Create second sub-pool. // // Release the rest of the objects from the super-pool. for (i = 0; i < COLOUR_POOL_SIZE; i++) { if (coloursPtr[i] != NULL) { le_mem_Release(coloursPtr[i]); coloursPtr[i] = NULL; } } // Create another sub-pool. le_mem_PoolRef_t colourSubPool2 = le_mem_CreateSubPool(colourPool, "Second sub-pool", COLOUR_POOL_SIZE - numRelease); LE_TEST_OK(NULL != colourSubPool2, "Create second sub-pool"); // // Expand the sub-pool causing the super-pool to expand. // le_mem_ExpandPool(colourSubPool2, NUM_EXPAND_SUB_POOL); // // Allocate from sub-pool. // for (i = 0; i < COLOUR_POOL_SIZE - numRelease; i++) { coloursPtr[i] = le_mem_TryAlloc(colourSubPool2); LE_TEST_OK(NULL != coloursPtr[i], "Allocate color %d from sub-pool", i); } // // Check pools. // LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND || !LE_CONFIG_IS_ENABLED(LE_CONFIG_MEM_POOL_STATS), 4); le_mem_GetStats(colourPool, &stats); LE_TEST_OK(( (le_mem_GetObjectCount(colourPool) == COLOUR_POOL_SIZE + NUM_EXPAND_SUB_POOL) && (stats.numFree == 0) ), "Check super-pool stats"); le_mem_GetStats(colourSubPool1, &stats); LE_TEST_OK(( (le_mem_GetObjectCount(colourSubPool1) == numRelease) && (stats.numFree == numRelease) ), "Check sub-pool stats"); le_mem_GetStats(colourSubPool2, &stats); LE_TEST_OK(( (le_mem_GetObjectCount(colourSubPool2) == COLOUR_POOL_SIZE - numRelease + NUM_EXPAND_SUB_POOL) && (stats.numFree == NUM_EXPAND_SUB_POOL) ), "Check second sub-pool stats"); // Try Allocating from empty super-pool. LE_TEST_OK(le_mem_TryAlloc(colourPool) == NULL, "Allocate from empty super-pool"); LE_TEST_END_SKIP(); // // Delete sub-pool. // le_mem_DeleteSubPool(colourSubPool1); // Allocate from the super-pool. for (i = 0; i < NUM_ALLOC_SUPER_POOL; i++) { if (COLOUR_POOL_SIZE > numRelease) { coloursPtr[numRelease] = le_mem_TryAlloc(colourPool); LE_TEST_OK(NULL != coloursPtr[numRelease], "Allocate item %d from super-pool", numRelease); } } // // Check pools. // LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND || !LE_CONFIG_IS_ENABLED(LE_CONFIG_MEM_POOL_STATS), 3); le_mem_GetStats(colourPool, &stats); LE_TEST_OK((stats.numFree == numRelease - NUM_ALLOC_SUPER_POOL), "checking super-pool stats after releasing sub-pool"); le_mem_GetStats(colourSubPool2, &stats); LE_TEST_OK(( (le_mem_GetObjectCount(colourSubPool2) == COLOUR_POOL_SIZE - numRelease + NUM_EXPAND_SUB_POOL) && (stats.numFree == NUM_EXPAND_SUB_POOL) ), "checking second sub-pool stats after releasing sub-pool"); // // Re-create sub-pool causing super pool to expand. // colourSubPool1 = le_mem_CreateSubPool(colourPool, "First sub-pool", numRelease + NUM_EXPAND_SUB_POOL); LE_TEST_OK(((le_mem_GetObjectCount(colourSubPool1) == numRelease + NUM_EXPAND_SUB_POOL) && (le_mem_GetObjectCount(colourPool) == COLOUR_POOL_SIZE + 2*NUM_EXPAND_SUB_POOL + NUM_ALLOC_SUPER_POOL)), "recreated sub-pool"); LE_TEST_END_SKIP(); // Create some reduced sub-pools le_mem_PoolRef_t tieredStrPoolMed = le_mem_CreateReducedPool(stringPool, "stringPoolMed", 0, STRING_POOL_MED_BYTES); le_mem_PoolRef_t tieredStrPoolSmall = le_mem_CreateReducedPool(tieredStrPoolMed, "stringPoolSmall", 4, STRING_POOL_SMALL_BYTES); size_t medObjectSize = le_mem_GetObjectSize(tieredStrPoolMed); size_t smallObjectSize = le_mem_GetObjectSize(tieredStrPoolSmall); LE_TEST_OK(STRING_POOL_MED_BYTES <= medObjectSize && medObjectSize < STRING_POOL_BYTES/2, "Check medium pool size (%"PRIuS") is reasonable", medObjectSize); LE_TEST_OK(STRING_POOL_SMALL_BYTES <= smallObjectSize && smallObjectSize < medObjectSize/2, "Check small pool size (%"PRIuS") is reasonable", smallObjectSize); // Try allocating random sized strings int points = STRING_POOL_SIZE*4; for (i = 0; i < 4*STRING_POOL_SIZE && points >= 4; i++) { // Always allocate at least one byte size_t allocSize = (rand() % (STRING_POOL_BYTES-1)) + 1; stringsPtr[i] = le_mem_ForceVarAlloc(tieredStrPoolSmall, allocSize); LE_TEST_OK(stringsPtr[i], "allocate buffer %d (size %"PRIuS")", i, allocSize); memset(stringsPtr[i], 'a', allocSize); if (allocSize <= smallObjectSize) { points -= 1; LE_TEST_OK(le_mem_GetBlockSize(stringsPtr[i]) == smallObjectSize, "got a small object"); } else if (allocSize <= medObjectSize) { points -= 2; LE_TEST_OK(le_mem_GetBlockSize(stringsPtr[i]) == medObjectSize, "got a medium object"); } else { points -= 4; LE_TEST_OK(le_mem_GetBlockSize(stringsPtr[i]) == STRING_POOL_BYTES, "got a large object"); } } // Now try hibernating -- first disable interrupts LE_TEST_BEGIN_SKIP(!LE_CONFIG_IS_ENABLED(LE_CONFIG_RTOS), 3); #if LE_CONFIG_RTOS taskENTER_CRITICAL(); void *beginFree, *endFree; le_mem_Hibernate(&beginFree, &endFree); LE_TEST_OK(endFree - beginFree > 0, "Free %" PRIuS " bytes of memory by hibernating", endFree - beginFree); le_mem_Resume(); taskEXIT_CRITICAL(); #endif /* end LE_CONFIG_RTOS */ LE_TEST_END_SKIP(); // Now finish up by allocating some small strings for(; i < 4*STRING_POOL_SIZE && points >= 0; ++i) { stringsPtr[i] = le_mem_ForceVarAlloc(tieredStrPoolSmall, 1); LE_TEST_OK(stringsPtr[i], "allocate buffer %d (size 1)", i); memset(stringsPtr[i], 'b', 1); LE_TEST_OK(le_mem_GetBlockSize(stringsPtr[i]) == smallObjectSize, "got a small object"); points -= 1; } LE_TEST_INFO("Releasing some buffers"); for (i = 0; i < 4*STRING_POOL_SIZE && stringsPtr[i]; i++) { if (rand() < REMOVE_THRESHOLD) { le_mem_Release(stringsPtr[i]); stringsPtr[i] = NULL; numRelease++; } } LE_TEST_INFO("Re-allocate as small buffers"); for (; i-- > 0; ) { if (!stringsPtr[i]) { stringsPtr[i] = le_mem_ForceVarAlloc(tieredStrPoolSmall, 1); LE_TEST_OK(stringsPtr[i], "allocated a small buffer"); memset(stringsPtr[i], 'c', 1); } } LE_TEST_INFO("Free everything"); for (i = 0; i < 4*STRING_POOL_SIZE && stringsPtr[i]; ++i) { le_mem_Release(stringsPtr[i]); stringsPtr[i] = NULL; } // And delete the sub-pools LE_TEST_INFO("Delete sub-pools"); le_mem_DeleteSubPool(tieredStrPoolSmall); le_mem_DeleteSubPool(tieredStrPoolMed); }