pcsx-redux/third_party/EASTL/test/source/TestAllocator.cpp
Nicolas 'Pixel' Noble d63f87a7f4 Adding EASTL.
2022-06-29 19:37:35 -07:00

403 lines
9.7 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Copyright (c) Electronic Arts Inc. All rights reserved.
/////////////////////////////////////////////////////////////////////////////
#include "EASTLTest.h"
#include <EASTL/allocator.h>
#include <EASTL/allocator_malloc.h>
#include <EASTL/fixed_allocator.h>
#include <EASTL/core_allocator_adapter.h>
#include <EASTL/list.h>
#include <EAStdC/EAString.h>
#include <EAStdC/EAAlignment.h>
///////////////////////////////////////////////////////////////////////////////
// fixed_pool_reference
//
struct fixed_pool_reference
{
public:
fixed_pool_reference(const char* = NULL)
{
mpFixedPool = NULL;
}
fixed_pool_reference(eastl::fixed_pool& fixedPool)
{
mpFixedPool = &fixedPool;
}
fixed_pool_reference(const fixed_pool_reference& x)
{
mpFixedPool = x.mpFixedPool;
}
fixed_pool_reference& operator=(const fixed_pool_reference& x)
{
mpFixedPool = x.mpFixedPool;
return *this;
}
void* allocate(size_t /*n*/, int /*flags*/ = 0)
{
return mpFixedPool->allocate();
}
void* allocate(size_t /*n*/, size_t /*alignment*/, size_t /*offset*/, int /*flags*/ = 0)
{
return mpFixedPool->allocate();
}
void deallocate(void* p, size_t /*n*/)
{
return mpFixedPool->deallocate(p);
}
const char* get_name() const
{
return "fixed_pool_reference";
}
void set_name(const char* /*pName*/)
{
}
protected:
friend bool operator==(const fixed_pool_reference& a, const fixed_pool_reference& b);
friend bool operator!=(const fixed_pool_reference& a, const fixed_pool_reference& b);
eastl::fixed_pool* mpFixedPool;
};
inline bool operator==(const fixed_pool_reference& a, const fixed_pool_reference& b)
{
return (a.mpFixedPool == b.mpFixedPool);
}
inline bool operator!=(const fixed_pool_reference& a, const fixed_pool_reference& b)
{
return (a.mpFixedPool != b.mpFixedPool);
}
///////////////////////////////////////////////////////////////////////////////
// TestFixedAllocator
//
EA_DISABLE_VC_WARNING(6262)
static int TestFixedAllocator()
{
using namespace eastl;
int nErrorCount = 0;
{ // fixed_allocator
typedef eastl::list<int, fixed_allocator> IntList;
typedef IntList::node_type IntListNode;
const size_t kBufferCount = 200;
IntListNode buffer1[kBufferCount];
IntList intList1;
const size_t kAlignOfIntListNode = EA_ALIGN_OF(IntListNode);
intList1.get_allocator().init(buffer1, sizeof(buffer1), sizeof(IntListNode), kAlignOfIntListNode);
for(size_t i = 0; i < kBufferCount; i++)
intList1.push_back(0);
EATEST_VERIFY(intList1.size() == kBufferCount);
// Try making a copy.
IntListNode buffer2[kBufferCount];
IntList intList2;
intList2.get_allocator().init(buffer2, sizeof(buffer2), sizeof(IntListNode), kAlignOfIntListNode);
intList2 = intList1;
EATEST_VERIFY(intList2.size() == kBufferCount);
}
// fixed_allocator_with_overflow, ensure allocations are coming from fixed buffer. This is to
// prevent a reported user regression where all allocations were being routed to the overflow
// allocator.
{
const int DEFAULT_VALUE = 0xbaadf00d;
const int TEST_VALUE = 0x12345689;
const size_t kBufferCount = 10;
typedef eastl::list<int, fixed_allocator_with_overflow> IntList;
typedef IntList::node_type IntListNode;
const size_t kAlignOfIntListNode = EA_ALIGN_OF(IntListNode);
// ensure the fixed buffer contains the default value that will be replaced
IntListNode buffer1[kBufferCount];
for (int i = 0; i < kBufferCount; i++)
{
buffer1[i].mValue = DEFAULT_VALUE;
EATEST_VERIFY(buffer1[i].mValue == DEFAULT_VALUE);
}
IntList intList1;
// replace all the values in the local buffer with the test value
intList1.get_allocator().init(buffer1, sizeof(buffer1), sizeof(IntListNode), kAlignOfIntListNode);
for (size_t i = 0; i < kBufferCount; i++)
intList1.push_back(TEST_VALUE);
// ensure the local buffer has been altered with the contents of the list::push_back
for (int i = 0; i < kBufferCount; i++)
{
EATEST_VERIFY(buffer1[i].mValue == TEST_VALUE);
}
}
{ // fixed_allocator_with_overflow
typedef eastl::list<int, fixed_allocator_with_overflow> IntList;
typedef IntList::node_type IntListNode;
const size_t kBufferCount = 200;
IntListNode buffer1[kBufferCount];
IntList intList1;
const size_t kAlignOfIntListNode = EA_ALIGN_OF(IntListNode);
intList1.get_allocator().init(buffer1, sizeof(buffer1), sizeof(IntListNode), kAlignOfIntListNode);
for(size_t i = 0; i < kBufferCount * 2; i++)
intList1.push_back(0);
EATEST_VERIFY(intList1.size() == (kBufferCount * 2));
// Try making a copy.
IntListNode buffer2[kBufferCount];
IntList intList2;
intList2.get_allocator().init(buffer2, sizeof(buffer2), sizeof(IntListNode), kAlignOfIntListNode);
intList2 = intList1;
EATEST_VERIFY(intList2.size() == (kBufferCount * 2));
}
{
// fixed_pool_reference
typedef eastl::list<int, fixed_pool_reference> WidgetList;
WidgetList::node_type buffer[16];
eastl::fixed_pool myPool(buffer, sizeof(buffer), sizeof(WidgetList::node_type), 16);
WidgetList myList1(myPool);
WidgetList myList2(myPool);
myList1.push_back(1);
myList2.push_back(1);
EATEST_VERIFY(myList1 == myList2);
myList1.push_back(2);
myList1.sort();
myList2.push_front(2);
myList2.sort();
EATEST_VERIFY(myList1 == myList2);
}
return nErrorCount;
}
EA_RESTORE_VC_WARNING()
///////////////////////////////////////////////////////////////////////////////
// TestAllocatorMalloc
//
static int TestAllocatorMalloc()
{
int nErrorCount = 0;
{
typedef eastl::list<int, eastl::allocator_malloc> WidgetList;
WidgetList myList1;
WidgetList myList2;
myList1.push_back(1);
myList2.push_back(1);
EATEST_VERIFY(myList1 == myList2);
myList1.push_back(2);
myList1.sort();
myList2.push_front(2);
myList2.sort();
EATEST_VERIFY(myList1 == myList2);
#if EASTL_ALIGNED_MALLOC_AVAILABLE
#endif
}
return nErrorCount;
}
#if EASTL_DLL
void* operator new[](size_t size, const char* pName, int flags, unsigned debugFlags, const char* file, int line);
void* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line);
#endif
struct EASTLTestCoreAllocator
{
public:
void* Alloc(size_t size, const char* name, unsigned int flags)
{
return ::operator new[](size, name, flags, 0, __FILE__, __LINE__);
}
void* Alloc(size_t size, const char* name, unsigned int flags,
unsigned int alignment, unsigned int alignOffset = 0)
{
return ::operator new[](size, alignment, alignOffset, name, flags, 0, __FILE__, __LINE__);
}
void Free(void* p, size_t /*size*/ = 0)
{
::operator delete((char*)p);
}
static EASTLTestCoreAllocator* GetDefaultAllocator();
};
EASTLTestCoreAllocator gEASTLTestCoreAllocator;
EASTLTestCoreAllocator* EASTLTestCoreAllocator::GetDefaultAllocator()
{
return &gEASTLTestCoreAllocator;
}
struct TestClass
{
mutable int mX;
TestClass() : mX(37) { }
void Increment()
{ mX++; }
void IncrementConst() const
{ mX++; }
int MultiplyBy(int x)
{ return mX * x; }
int MultiplyByConst(int x) const
{ return mX * x; }
};
///////////////////////////////////////////////////////////////////////////////
// TestCoreAllocatorAdapter
//
static int TestCoreAllocatorAdapter()
{
int nErrorCount = 0;
#if EASTL_CORE_ALLOCATOR_ENABLED
typedef EA::Allocator::CoreAllocatorAdapter<EASTLTestCoreAllocator> Adapter;
eastl::list<TestClass, Adapter> widgetList(Adapter("UI/WidgetList", &gEASTLTestCoreAllocator));
widgetList.push_back(TestClass());
EATEST_VERIFY(widgetList.size() == 1);
eastl::vector<TestClass, Adapter> widgetVector(100, Adapter("UI/WidgetVector", &gEASTLTestCoreAllocator));
widgetVector.push_back(TestClass());
EATEST_VERIFY(widgetVector.size() == 101);
eastl::vector<TestClass, Adapter> widgetVector2(widgetVector);
widgetVector2.resize(400);
EATEST_VERIFY(widgetVector2.size() == 400);
#endif
return nErrorCount;
}
///////////////////////////////////////////////////////////////////////////////
// TestSwapAllocator
//
static int TestSwapAllocator()
{
int nErrorCount = 0;
{
InstanceAllocator a(nullptr, (uint8_t)111), b(nullptr, (uint8_t)222);
eastl::swap(a, b);
EATEST_VERIFY(a.mInstanceId == 222);
EATEST_VERIFY(b.mInstanceId == 111);
EATEST_VERIFY(EA::StdC::Strcmp(a.get_name(), "InstanceAllocator 222") == 0);
EATEST_VERIFY(EA::StdC::Strcmp(b.get_name(), "InstanceAllocator 111") == 0);
}
return nErrorCount;
}
static int TestAllocationOffsetAndAlignment()
{
int nErrorCount = 0;
auto testAllocatorAlignment = [&nErrorCount](int requestedSize, int requestedAlignment, int requestedOffset)
{
CountingAllocator::resetCount();
CountingAllocator a;
void* p = allocate_memory(a, requestedSize, requestedAlignment, requestedOffset);
EATEST_VERIFY(p != nullptr);
EATEST_VERIFY(EA::StdC::IsAligned(p, requestedAlignment));
a.deallocate(p, requestedSize);
EATEST_VERIFY(CountingAllocator::getActiveAllocationSize() == 0);
};
testAllocatorAlignment(100, 1, 0);
testAllocatorAlignment(100, 2, 0);
testAllocatorAlignment(100, 4, 0);
testAllocatorAlignment(100, 8, 0);
testAllocatorAlignment(100, 16, 0);
testAllocatorAlignment(100, 1, 16);
testAllocatorAlignment(100, 2, 16);
testAllocatorAlignment(100, 4, 16);
testAllocatorAlignment(100, 8, 16);
testAllocatorAlignment(100, 16, 16);
return nErrorCount;
}
///////////////////////////////////////////////////////////////////////////////
// TestAllocator
//
int TestAllocator()
{
int nErrorCount = 0;
nErrorCount += TestAllocationOffsetAndAlignment();
nErrorCount += TestFixedAllocator();
nErrorCount += TestAllocatorMalloc();
nErrorCount += TestCoreAllocatorAdapter();
nErrorCount += TestSwapAllocator();
return nErrorCount;
}