#include "memory.hpp" #include #include struct TMemBlock { char *data; size_t size; }; struct TMemBucket { int64_t size; int64_t head; int64_t lostBytes; int64_t allocs; int64_t lastEmptyBlockIndex; int64_t maxBlockCount; TMemBlock *blocks; char *ptr; bool transient; }; class MemoryTest : public ::testing::Test { protected: void SetUp() override { MemBkt_Test = Pke_BeginTransientBucket(1024 * 1024); bkt = reinterpret_cast(MemBkt_Test); }; void TearDown() override { Pke_EndTransientBucket(MemBkt_Test); }; MemBucket *MemBkt_Test = nullptr; TMemBucket *bkt = nullptr; }; /* * Test that memory can be allocated predictably */ TEST_F(MemoryTest, EnsureAllocation001) { // arrange size_t sz = 2; size_t alignment = 1; // act Pke_New(sz, alignment, MemBkt_Test); // assert EXPECT_EQ(-1, bkt->lastEmptyBlockIndex); EXPECT_EQ(sz, bkt->head); }; /* * Test that memory can be freed predictably */ TEST_F(MemoryTest, EnsureFree001) { // arrange size_t sz = 2; size_t alignment = 1; // act void *ptr1 = Pke_New(sz, alignment, MemBkt_Test); Pke_Delete(ptr1, sz, MemBkt_Test); // assert EXPECT_EQ(-1, bkt->lastEmptyBlockIndex); EXPECT_EQ(0, bkt->head); }; /* * Test that memory can be allocated and freed predictably */ class MemoryTestScenario100 : public MemoryTest { void SetUp() override { MemoryTest::SetUp(); for (long i = 0; i < cnt; ++i) { ptrs[i] = Pke_New(sz[i], alignment[i], MemBkt_Test); } } protected: void TestExpectedState() { EXPECT_EQ(2, bkt->lastEmptyBlockIndex); EXPECT_EQ(80, bkt->head); EXPECT_EQ(bkt->ptr + 00, ptrs[0]); EXPECT_EQ(bkt->ptr + 64, ptrs[1]); EXPECT_EQ(bkt->ptr + 16, ptrs[2]); EXPECT_EQ(bkt->ptr + 8, ptrs[3]); } const long cnt = 4; const size_t sz[4] = {2, 16, 16, 4}; const size_t alignment[4] = {1, 64, 16, 8}; void * ptrs[4]; }; /* allocation events * 1st = alignment 01, size 02, move head ( =02 ) * 2nd = alignment 64, size 16, move head ( =80 ) memBlock { +02, 62 } * 3rd = alignment 16, size 16, memBlock { +2, 14 } memBlock { +32, 32 } * 4th = alignment 08, size 04, memBlock { +2, 06 } memBlock { +12, 04 } memBlock { +32, 32 } */ TEST_F(MemoryTestScenario100, EnsureAllocFree0000) { EXPECT_NO_FATAL_FAILURE(this->TestExpectedState()); // arrange // act // assert EXPECT_EQ(bkt->ptr + 2, bkt->blocks[0].data); EXPECT_EQ(6, bkt->blocks[0].size); EXPECT_EQ(bkt->ptr + 12, bkt->blocks[1].data); EXPECT_EQ(4, bkt->blocks[1].size); EXPECT_EQ(bkt->ptr + 32, bkt->blocks[2].data); EXPECT_EQ(32, bkt->blocks[2].size); } TEST_F(MemoryTestScenario100, EnsureAllocFree1000) { EXPECT_NO_FATAL_FAILURE(this->TestExpectedState()); // arrange size_t expectedHead = 80; long freeIndex = 0; // act /* free events * 1st = ptr +00, size 02, memBlock { +00, 08 } */ Pke_Delete(ptrs[freeIndex], sz[freeIndex], MemBkt_Test); // assert EXPECT_EQ(2, bkt->lastEmptyBlockIndex); EXPECT_EQ(expectedHead, bkt->head); EXPECT_EQ(bkt->ptr + 0, bkt->blocks[0].data); EXPECT_EQ(8, bkt->blocks[0].size); EXPECT_EQ(bkt->ptr + 12, bkt->blocks[1].data); EXPECT_EQ(4, bkt->blocks[1].size); EXPECT_EQ(bkt->ptr + 32, bkt->blocks[2].data); EXPECT_EQ(32, bkt->blocks[2].size); }; TEST_F(MemoryTestScenario100, EnsureAllocFree0100) { EXPECT_NO_FATAL_FAILURE(this->TestExpectedState()); // arrange size_t expectedHead = 32; long freeIndex = 1; // act /* free events * 1st = ptr +64, size 16, move head ( =32 ) memBlock { +02, 06 } memBlock { +12, 4 } */ Pke_Delete(ptrs[freeIndex], sz[freeIndex], MemBkt_Test); // assert EXPECT_EQ(1, bkt->lastEmptyBlockIndex); EXPECT_EQ(expectedHead, bkt->head); EXPECT_EQ(bkt->ptr + 2, bkt->blocks[0].data); EXPECT_EQ(6, bkt->blocks[0].size); EXPECT_EQ(bkt->ptr + 12, bkt->blocks[1].data); EXPECT_EQ(4, bkt->blocks[1].size); }; TEST_F(MemoryTestScenario100, EnsureAllocFree0010) { EXPECT_NO_FATAL_FAILURE(this->TestExpectedState()); // arrange size_t expectedHead = 80; long freeIndex = 2; // act /* free events * 1st = ptr +16, size 16, memBlock { +02, 06 } memBlock { +12, 04 } memBlock { +16, 48 } * memBlock { +02, 06 } memBlock { +12, 52 } */ Pke_Delete(ptrs[freeIndex], sz[freeIndex], MemBkt_Test); // assert EXPECT_EQ(1, bkt->lastEmptyBlockIndex); EXPECT_EQ(expectedHead, bkt->head); EXPECT_EQ(bkt->ptr + 2, bkt->blocks[0].data); EXPECT_EQ(6, bkt->blocks[0].size); EXPECT_EQ(bkt->ptr + 12, bkt->blocks[1].data); EXPECT_EQ(52, bkt->blocks[1].size); } TEST_F(MemoryTestScenario100, EnsureAllocFree0001) { EXPECT_NO_FATAL_FAILURE(this->TestExpectedState()); // arrange size_t expectedHead = 80; long freeIndex = 3; // act /* free events * 1st = ptr +08, size 4, memBlock { +02, 06 } memBlock { +08, 08 } memBlock { +32, 32 } * memBlock { +02, 14 } memBlock { +32, 32 } */ Pke_Delete(ptrs[freeIndex], sz[freeIndex], MemBkt_Test); // assert EXPECT_EQ(1, bkt->lastEmptyBlockIndex); EXPECT_EQ(expectedHead, bkt->head); EXPECT_EQ(bkt->ptr + 2, bkt->blocks[0].data); EXPECT_EQ(14, bkt->blocks[0].size); EXPECT_EQ(bkt->ptr + 32, bkt->blocks[1].data); EXPECT_EQ(32, bkt->blocks[1].size); }