1#include "gtest/gtest.h" 2 3#include "chre/util/memory_pool.h" 4 5#include <random> 6#include <vector> 7 8using chre::MemoryPool; 9 10TEST(MemoryPool, ExhaustPool) { 11 MemoryPool<int, 3> memoryPool; 12 ASSERT_NE(memoryPool.allocate(), nullptr); 13 ASSERT_NE(memoryPool.allocate(), nullptr); 14 ASSERT_NE(memoryPool.allocate(), nullptr); 15 ASSERT_EQ(memoryPool.allocate(), nullptr); 16} 17 18TEST(MemoryPool, ExhaustPoolThenDeallocateOneAndAllocateOne) { 19 MemoryPool<int, 3> memoryPool; 20 21 // Exhaust the pool. 22 int *element1 = memoryPool.allocate(); 23 int *element2 = memoryPool.allocate(); 24 int *element3 = memoryPool.allocate(); 25 26 // Perform some simple assignments. There is a chance we crash here if things 27 // are not implemented correctly. 28 *element1 = 0xcafe; 29 *element2 = 0xbeef; 30 *element3 = 0xface; 31 32 // Free one element and then allocate another. 33 memoryPool.deallocate(element1); 34 element1 = memoryPool.allocate(); 35 ASSERT_NE(element1, nullptr); 36 37 // Ensure that the pool remains exhausted. 38 ASSERT_EQ(memoryPool.allocate(), nullptr); 39 40 // Perform another simple assignment. There is a hope that this can crash if 41 // the pointer returned is very bad (like nullptr). 42 *element1 = 0xfade; 43 44 // Verify that the values stored were not corrupted by the deallocate 45 // allocate cycle. 46 ASSERT_EQ(*element1, 0xfade); 47 ASSERT_EQ(*element2, 0xbeef); 48 ASSERT_EQ(*element3, 0xface); 49} 50 51/* 52 * Pair an allocated pointer with the expected value that should be stored in 53 * that location. 54 */ 55struct AllocationExpectedValuePair { 56 size_t *allocation; 57 size_t expectedValue; 58}; 59 60TEST(MemoryPool, ExhaustPoolThenRandomDeallocate) { 61 // The number of times to allocate and deallocate in random order. 62 const size_t kStressTestCount = 64; 63 64 // Construct a memory pool and a vector to maintain a list of all allocations. 65 const size_t kMemoryPoolSize = 64; 66 MemoryPool<size_t, kMemoryPoolSize> memoryPool; 67 std::vector<AllocationExpectedValuePair> allocations; 68 69 for (size_t i = 0; i < kStressTestCount; i++) { 70 // Exhaust the memory pool. 71 for (size_t j = 0; j < kMemoryPoolSize; j++) { 72 AllocationExpectedValuePair allocation = { 73 .allocation = memoryPool.allocate(), 74 .expectedValue = j, 75 }; 76 77 *allocation.allocation = j; 78 allocations.push_back(allocation); 79 } 80 81 // Seed a random number generator with the loop iteration so that order is 82 // preserved across test runs. 83 std::mt19937 randomGenerator(i); 84 85 while (!allocations.empty()) { 86 // Generate a number with a uniform distribution between zero and the number 87 // of allocations remaining. 88 std::uniform_int_distribution<> distribution(0, allocations.size() - 1); 89 size_t deallocateIndex = distribution(randomGenerator); 90 91 // Verify the expected value and free the allocation. 92 ASSERT_EQ(*allocations[deallocateIndex].allocation, 93 allocations[deallocateIndex].expectedValue); 94 memoryPool.deallocate(allocations[deallocateIndex].allocation); 95 96 // Remove the freed allocation from the allocation list. 97 allocations.erase(allocations.begin() + deallocateIndex); 98 } 99 } 100} 101 102