aboutsummaryrefslogtreecommitdiff
path: root/test/source/TestAllocator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/source/TestAllocator.cpp')
-rw-r--r--test/source/TestAllocator.cpp402
1 files changed, 402 insertions, 0 deletions
diff --git a/test/source/TestAllocator.cpp b/test/source/TestAllocator.cpp
new file mode 100644
index 0000000..8cfaadd
--- /dev/null
+++ b/test/source/TestAllocator.cpp
@@ -0,0 +1,402 @@
+/////////////////////////////////////////////////////////////////////////////
+// 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;
+
+ IntList intList1;
+ 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);
+ }
+
+ // 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;
+}
+
+
+
+
+
+
+
+
+
+
+
+