From 2e6f761458960dbf2d6aff9dc0f82db1bc243526 Mon Sep 17 00:00:00 2001 From: ylavic Date: Sat, 13 Mar 2021 02:11:17 +0100 Subject: [PATCH] Tests for StdAllocator. --- test/unittest/allocatorstest.cpp | 166 ++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/test/unittest/allocatorstest.cpp b/test/unittest/allocatorstest.cpp index c541f04..b8a2191 100644 --- a/test/unittest/allocatorstest.cpp +++ b/test/unittest/allocatorstest.cpp @@ -16,6 +16,9 @@ #include "rapidjson/allocators.h" +#include +#include + using namespace rapidjson; template @@ -47,19 +50,180 @@ void TestAllocator(Allocator& a) { EXPECT_TRUE(a.Realloc(a.Malloc(1), 1, 0) == 0); } +struct TestStdAllocatorData { + TestStdAllocatorData(int &constructions, int &destructions) : + constructions_(&constructions), + destructions_(&destructions) + { + ++*constructions_; + } + TestStdAllocatorData(const TestStdAllocatorData& rhs) : + constructions_(rhs.constructions_), + destructions_(rhs.destructions_) + { + ++*constructions_; + } + TestStdAllocatorData& operator=(const TestStdAllocatorData& rhs) + { + this->~TestStdAllocatorData(); + constructions_ = rhs.constructions_; + destructions_ = rhs.destructions_; + ++*constructions_; + return *this; + } + ~TestStdAllocatorData() + { + ++*destructions_; + } +private: + TestStdAllocatorData(); + int *constructions_, + *destructions_; +}; + +template +void TestStdAllocator(const Allocator& a) { + typedef StdAllocator VoidAllocator; + typedef typename VoidAllocator::template rebind::other BoolAllocator; + BoolAllocator ba(a), ba2(a); + EXPECT_TRUE(ba == ba2); + EXPECT_FALSE(ba!= ba2); + ba.deallocate(ba.allocate()); + EXPECT_TRUE(ba == ba2); + EXPECT_FALSE(ba != ba2); + + unsigned long long ll = 0, *llp = ≪ + const unsigned long long cll = 0, *cllp = &cll; + StdAllocator lla(a); + EXPECT_EQ(lla.address(ll), llp); + EXPECT_EQ(lla.address(cll), cllp); + EXPECT_TRUE(lla.max_size() > 0 && lla.max_size() <= SIZE_MAX / sizeof(unsigned long long)); + + int *arr; + StdAllocator ia(a); + arr = ia.allocate(10 * sizeof(int)); + EXPECT_TRUE(arr != 0); + for (int i = 0; i < 10; ++i) { + arr[i] = 0x0f0f0f0f; + } + ia.deallocate(arr, 10); + arr = (int *)ia.Malloc(10 * sizeof(int)); + EXPECT_TRUE(arr != 0); + for (int i = 0; i < 10; ++i) { + arr[i] = 0x0f0f0f0f; + } + arr = (int *)ia.Realloc(arr, 10 * sizeof(int), 20 * sizeof(int)); + EXPECT_TRUE(arr != 0); + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(arr[i], 0x0f0f0f0f); + } + for (int i = 10; i < 20; i++) { + arr[i] = 0x0f0f0f0f; + } + ia.Free(arr); + + int cons = 0, dest = 0; + StdAllocator da(a); + for (int i = 1; i < 10; i++) { + TestStdAllocatorData *d = da.allocate(); + EXPECT_TRUE(d != 0); + + da.destroy(new(d) TestStdAllocatorData(cons, dest)); + EXPECT_EQ(cons, i); + EXPECT_EQ(dest, i); + + da.deallocate(d); + } + + typedef StdAllocator CharAllocator; + typedef std::basic_string, CharAllocator> String; + CharAllocator ca(a); + String s(ca); + for (int i = 0; i < 26; i++) { + s.push_back(static_cast('A' + i)); + } + EXPECT_TRUE(s == "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); +} + TEST(Allocator, CrtAllocator) { CrtAllocator a; + TestAllocator(a); + TestStdAllocator(a); + + CrtAllocator a2; + EXPECT_TRUE(a == a2); + EXPECT_FALSE(a != a2); + a2.Free(a2.Malloc(1)); + EXPECT_TRUE(a == a2); + EXPECT_FALSE(a != a2); } TEST(Allocator, MemoryPoolAllocator) { - MemoryPoolAllocator<> a; + const size_t capacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; + MemoryPoolAllocator<> a(capacity); + + a.Clear(); // noop + EXPECT_EQ(a.Size(), 0u); + EXPECT_EQ(a.Capacity(), 0u); + EXPECT_EQ(a.Shared(), false); + { + MemoryPoolAllocator<> a2(a); + EXPECT_EQ(a2.Shared(), true); + EXPECT_EQ(a.Shared(), true); + EXPECT_TRUE(a == a2); + EXPECT_FALSE(a != a2); + a2.Free(a2.Malloc(1)); + EXPECT_TRUE(a == a2); + EXPECT_FALSE(a != a2); + } + EXPECT_EQ(a.Shared(), false); + EXPECT_EQ(a.Capacity(), capacity); + EXPECT_EQ(a.Size(), 8u); // aligned + a.Clear(); + EXPECT_EQ(a.Capacity(), 0u); + EXPECT_EQ(a.Size(), 0u); + TestAllocator(a); + TestStdAllocator(a); for (size_t i = 1; i < 1000; i++) { EXPECT_TRUE(a.Malloc(i) != 0); EXPECT_LE(a.Size(), a.Capacity()); } + + CrtAllocator baseAllocator; + a = MemoryPoolAllocator<>(capacity, &baseAllocator); + EXPECT_EQ(a.Capacity(), 0u); + EXPECT_EQ(a.Size(), 0u); + a.Free(a.Malloc(1)); + EXPECT_EQ(a.Capacity(), capacity); + EXPECT_EQ(a.Size(), 8u); // aligned + + { + a.Clear(); + const size_t bufSize = 1024; + char *buffer = (char *)a.Malloc(bufSize); + MemoryPoolAllocator<> aligned_a(buffer, bufSize); + EXPECT_TRUE(aligned_a.Capacity() > 0 && aligned_a.Capacity() <= bufSize); + EXPECT_EQ(aligned_a.Size(), 0u); + aligned_a.Free(aligned_a.Malloc(1)); + EXPECT_TRUE(aligned_a.Capacity() > 0 && aligned_a.Capacity() <= bufSize); + EXPECT_EQ(aligned_a.Size(), 8u); // aligned + } + + { + a.Clear(); + const size_t bufSize = 1024; + char *buffer = (char *)a.Malloc(bufSize); + RAPIDJSON_ASSERT(bufSize % sizeof(void*) == 0); + MemoryPoolAllocator<> unaligned_a(buffer + 1, bufSize - 1); + EXPECT_TRUE(unaligned_a.Capacity() > 0 && unaligned_a.Capacity() <= bufSize - sizeof(void*)); + EXPECT_EQ(unaligned_a.Size(), 0u); + unaligned_a.Free(unaligned_a.Malloc(1)); + EXPECT_TRUE(unaligned_a.Capacity() > 0 && unaligned_a.Capacity() <= bufSize - sizeof(void*)); + EXPECT_EQ(unaligned_a.Size(), 8u); // aligned + } } TEST(Allocator, Alignment) {