Files
klubhaus-doorbell/libraries/FastLED/tests/test_allocator.cpp
2026-02-12 00:45:31 -08:00

162 lines
4.8 KiB
C++

// Unit tests for general allocator functionality and integration tests
#include "test.h"
#include "fl/allocator.h"
#include "fl/vector.h"
using namespace fl;
// Test struct for general allocator testing
struct TestObject {
int data[4]; // 16 bytes to make it larger than pointer size
TestObject() {
for (int i = 0; i < 4; ++i) {
data[i] = 0;
}
}
};
TEST_CASE("Allocator - Integration tests") {
SUBCASE("Different allocator types comparison") {
// Test basic functionality across different allocator types
// SlabAllocator
SlabAllocator<int, 8> slab_alloc;
int* slab_ptr = slab_alloc.allocate();
REQUIRE(slab_ptr != nullptr);
*slab_ptr = 100;
CHECK_EQ(*slab_ptr, 100);
slab_alloc.deallocate(slab_ptr);
// allocator_inlined
fl::allocator_inlined<int, 3> inlined_alloc;
int* inlined_ptr = inlined_alloc.allocate(1);
REQUIRE(inlined_ptr != nullptr);
*inlined_ptr = 200;
CHECK_EQ(*inlined_ptr, 200);
inlined_alloc.deallocate(inlined_ptr, 1);
// allocator_inlined_slab
fl::allocator_inlined_slab<int, 3> inlined_slab_alloc;
int* inlined_slab_ptr = inlined_slab_alloc.allocate(1);
REQUIRE(inlined_slab_ptr != nullptr);
*inlined_slab_ptr = 300;
CHECK_EQ(*inlined_slab_ptr, 300);
inlined_slab_alloc.deallocate(inlined_slab_ptr, 1);
}
}
TEST_CASE("Allocator - Multi-allocation support") {
SUBCASE("SlabAllocator multi-allocation") {
SlabAllocator<int, 8> allocator;
// Test single allocation
int* single_ptr = allocator.allocate(1);
REQUIRE(single_ptr != nullptr);
*single_ptr = 42;
CHECK_EQ(*single_ptr, 42);
allocator.deallocate(single_ptr, 1);
// Test multi-allocation (should work with our bitset implementation)
int* multi_ptr = allocator.allocate(3);
REQUIRE(multi_ptr != nullptr);
// Initialize the multi-allocation
for (int i = 0; i < 3; ++i) {
multi_ptr[i] = i + 100;
}
// Verify the values
for (int i = 0; i < 3; ++i) {
CHECK_EQ(multi_ptr[i], i + 100);
}
allocator.deallocate(multi_ptr, 3);
}
}
TEST_CASE("Allocator - Copy and move semantics") {
SUBCASE("allocator_inlined copy constructor") {
fl::allocator_inlined<int, 3> allocator1;
// Allocate some memory in the first allocator
int* ptr1 = allocator1.allocate(1);
REQUIRE(ptr1 != nullptr);
*ptr1 = 42;
// Copy constructor
fl::allocator_inlined<int, 3> allocator2(allocator1);
// Original allocation should still be valid
CHECK_EQ(*ptr1, 42);
// New allocator should be independent
int* ptr2 = allocator2.allocate(1);
REQUIRE(ptr2 != nullptr);
*ptr2 = 84;
CHECK_EQ(*ptr2, 84);
// Cleanup
allocator1.deallocate(ptr1, 1);
allocator2.deallocate(ptr2, 1);
}
SUBCASE("allocator_inlined_slab copy constructor") {
fl::allocator_inlined_slab<int, 3> allocator1;
// Allocate some memory in the first allocator
int* ptr1 = allocator1.allocate(1);
REQUIRE(ptr1 != nullptr);
*ptr1 = 42;
// Copy constructor
fl::allocator_inlined_slab<int, 3> allocator2(allocator1);
// Original allocation should still be valid
CHECK_EQ(*ptr1, 42);
// New allocator should be independent
int* ptr2 = allocator2.allocate(1);
REQUIRE(ptr2 != nullptr);
*ptr2 = 84;
CHECK_EQ(*ptr2, 84);
// Cleanup
allocator1.deallocate(ptr1, 1);
allocator2.deallocate(ptr2, 1);
}
}
TEST_CASE("Allocator - Performance and stress tests") {
SUBCASE("SlabAllocator performance") {
SlabAllocator<TestObject, 16> allocator;
fl::vector<TestObject*> ptrs;
const size_t num_allocs = 32; // More than one slab
// Allocate
for (size_t i = 0; i < num_allocs; ++i) {
TestObject* ptr = allocator.allocate();
REQUIRE(ptr != nullptr);
// Initialize data
for (int j = 0; j < 4; ++j) {
ptr->data[j] = static_cast<int>(i * 10 + j);
}
ptrs.push_back(ptr);
}
// Verify data integrity
for (size_t i = 0; i < ptrs.size(); ++i) {
for (int j = 0; j < 4; ++j) {
CHECK_EQ(ptrs[i]->data[j], static_cast<int>(i * 10 + j));
}
}
// Cleanup
for (TestObject* ptr : ptrs) {
allocator.deallocate(ptr);
}
}
}