Capacity was incorrectly 2x larger than needed. Added unit test to ensure it stays correct.
389 lines
11 KiB
C++
389 lines
11 KiB
C++
// Copyright (c) Wojciech Figat. All rights reserved.
|
|
|
|
#include "Engine/Core/RandomStream.h"
|
|
#include "Engine/Core/Collections/Array.h"
|
|
#include "Engine/Core/Collections/BitArray.h"
|
|
#include "Engine/Core/Collections/HashSet.h"
|
|
#include "Engine/Core/Collections/Dictionary.h"
|
|
#include <ThirdParty/catch2/catch.hpp>
|
|
|
|
const bool TestBits[] = { true, false, true, false };
|
|
|
|
template<typename AllocationType = HeapAllocation>
|
|
void InitBitArray(BitArray<AllocationType>& array)
|
|
{
|
|
array.Add(TestBits, ARRAY_COUNT(TestBits));
|
|
}
|
|
|
|
template<typename AllocationType = HeapAllocation>
|
|
void CheckBitArray(const BitArray<AllocationType>& array)
|
|
{
|
|
CHECK(array.Count() == ARRAY_COUNT(TestBits));
|
|
for (int32 i = 0; i < ARRAY_COUNT(TestBits); i++)
|
|
{
|
|
CHECK(array[i] == TestBits[i]);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Array")
|
|
{
|
|
SECTION("Test Capacity")
|
|
{
|
|
// Ensure correct collections capacity growing to meet proper memory usage vs safe slack
|
|
CHECK(AllocationUtils::CalculateCapacityGrow(1, 0) == 8);
|
|
CHECK(AllocationUtils::CalculateCapacityGrow(7, 0) == 8);
|
|
CHECK(AllocationUtils::CalculateCapacityGrow(1, 16) == 16);
|
|
CHECK(AllocationUtils::CalculateCapacityGrow(31, 0) == 32);
|
|
CHECK(AllocationUtils::CalculateCapacityGrow(32, 0) == 32);
|
|
CHECK(AllocationUtils::CalculateCapacityGrow(1000, 0) == 1024);
|
|
CHECK(AllocationUtils::CalculateCapacityGrow(1024, 0) == 1024);
|
|
CHECK(AllocationUtils::CalculateCapacityGrow(1025, 0) == 2048);
|
|
}
|
|
|
|
SECTION("Test Allocators")
|
|
{
|
|
Array<int32> a1;
|
|
Array<int32, InlinedAllocation<8>> a2;
|
|
Array<int32, FixedAllocation<8>> a3;
|
|
for (int32 i = 0; i < 7; i++)
|
|
{
|
|
a1.Add(i);
|
|
a2.Add(i);
|
|
a3.Add(i);
|
|
}
|
|
CHECK(a1.Count() == 7);
|
|
CHECK(a2.Count() == 7);
|
|
CHECK(a3.Count() == 7);
|
|
for (int32 i = 0; i < 7; i++)
|
|
{
|
|
CHECK(a1[i] == i);
|
|
CHECK(a2[i] == i);
|
|
CHECK(a3[i] == i);
|
|
}
|
|
}
|
|
|
|
// Generate some random data for testing
|
|
Array<uint32> testData;
|
|
testData.Resize(32);
|
|
RandomStream rand(101);
|
|
for (int32 i = 0; i < testData.Count(); i++)
|
|
testData[i] = rand.GetUnsignedInt();
|
|
|
|
SECTION("Test Copy Constructor")
|
|
{
|
|
const Array<uint32> a1(testData);
|
|
const Array<uint32, InlinedAllocation<8>> a2(testData);
|
|
const Array<uint32, InlinedAllocation<64>> a3(testData);
|
|
const Array<uint32, FixedAllocation<64>> a4(testData);
|
|
CHECK(a1 == testData);
|
|
CHECK(a2 == testData);
|
|
CHECK(a3 == testData);
|
|
CHECK(a4 == testData);
|
|
}
|
|
|
|
SECTION("Test Copy Operator")
|
|
{
|
|
Array<uint32> a1;
|
|
a1 = testData;
|
|
CHECK(a1 == testData);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("BitArray")
|
|
{
|
|
SECTION("Test Access")
|
|
{
|
|
BitArray<> a1;
|
|
CHECK(a1.Count() == 0);
|
|
for (int32 i = 0; i < 310; i++)
|
|
{
|
|
a1.Add(false);
|
|
}
|
|
CHECK(a1.Count() == 310);
|
|
a1.Resize(300);
|
|
CHECK(a1.Count() == 300);
|
|
CHECK(a1.Capacity() >= 300);
|
|
a1.SetAll(true);
|
|
a1.SetAll(false);
|
|
for (int32 i = 0; i < 300; i++)
|
|
{
|
|
a1.Set(i, true);
|
|
for (int32 j = 0; j < 300; j++)
|
|
{
|
|
bool expected = j == i;
|
|
CHECK(a1.Get(j) == expected);
|
|
}
|
|
a1.Set(i, false);
|
|
}
|
|
}
|
|
|
|
SECTION("Test Allocators")
|
|
{
|
|
BitArray<> a1;
|
|
BitArray<InlinedAllocation<8>> a2;
|
|
BitArray<FixedAllocation<8>> a3;
|
|
for (int32 i = 0; i < 7; i++)
|
|
{
|
|
const bool v = i & 2;
|
|
a1.Add(v);
|
|
a2.Add(v);
|
|
a3.Add(v);
|
|
}
|
|
CHECK(a1.Count() == 7);
|
|
CHECK(a2.Count() == 7);
|
|
CHECK(a3.Count() == 7);
|
|
for (int32 i = 0; i < 7; i++)
|
|
{
|
|
const bool v = i & 2;
|
|
CHECK(a1.Get(i) == v);
|
|
CHECK(a2.Get(i) == v);
|
|
CHECK(a3.Get(i) == v);
|
|
}
|
|
}
|
|
|
|
SECTION("Test Move/Copy")
|
|
{
|
|
BitArray<> array1;
|
|
BitArray<FixedAllocation<4>> array2;
|
|
BitArray<InlinedAllocation<4>> array3;
|
|
BitArray<InlinedAllocation<2>> array4;
|
|
|
|
InitBitArray(array1);
|
|
InitBitArray(array2);
|
|
InitBitArray(array3);
|
|
InitBitArray(array4);
|
|
|
|
CheckBitArray(array1);
|
|
CheckBitArray(array2);
|
|
CheckBitArray(array3);
|
|
CheckBitArray(array4);
|
|
|
|
BitArray<> arrayClone1 = array1;
|
|
BitArray<FixedAllocation<4>> arrayClone2(array1);
|
|
BitArray<FixedAllocation<4>> arrayClone3(MoveTemp(array1));
|
|
BitArray<> arrayClone4(MoveTemp(array1));
|
|
BitArray<FixedAllocation<4>> arrayClone5 = MoveTemp(array2);
|
|
BitArray<InlinedAllocation<4>> arrayClone6 = MoveTemp(array3);
|
|
BitArray<InlinedAllocation<2>> arrayClone7 = MoveTemp(array4);
|
|
|
|
CheckBitArray(arrayClone1);
|
|
CheckBitArray(arrayClone2);
|
|
CheckBitArray(arrayClone4);
|
|
CheckBitArray(arrayClone5);
|
|
CheckBitArray(arrayClone6);
|
|
CheckBitArray(arrayClone7);
|
|
|
|
CHECK(array1.Count() == 0);
|
|
CHECK(array2.Count() == 0);
|
|
CHECK(array3.Count() == 0);
|
|
CHECK(array4.Count() == 0);
|
|
}
|
|
|
|
// Generate some random data for testing
|
|
BitArray<> testData;
|
|
testData.Resize(128);
|
|
RandomStream rand(101);
|
|
for (int32 i = 0; i < testData.Count(); i++)
|
|
testData.Set(i, rand.GetBool());
|
|
|
|
SECTION("Test Copy Constructor")
|
|
{
|
|
const BitArray<> a1(testData);
|
|
const BitArray<InlinedAllocation<8>> a2(testData);
|
|
const BitArray<InlinedAllocation<256>> a3(testData);
|
|
const BitArray<FixedAllocation<256>> a4(testData);
|
|
CHECK(a1 == testData);
|
|
CHECK(a2 == testData);
|
|
CHECK(a3 == testData);
|
|
CHECK(a4 == testData);
|
|
}
|
|
|
|
SECTION("Test Copy Operator")
|
|
{
|
|
BitArray<> a1;
|
|
a1 = testData;
|
|
CHECK(a1 == testData);
|
|
}
|
|
|
|
SECTION("Test Set All")
|
|
{
|
|
BitArray<> a1;
|
|
a1.Resize(9);
|
|
CHECK(a1.Count() == 9);
|
|
a1.SetAll(true);
|
|
for (int32 i = 0; i < a1.Count(); i++)
|
|
CHECK(a1[i] == true);
|
|
a1.SetAll(false);
|
|
for (int32 i = 0; i < a1.Count(); i++)
|
|
CHECK(a1[i] == false);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("HashSet")
|
|
{
|
|
SECTION("Test Allocators")
|
|
{
|
|
HashSet<int32> a1;
|
|
HashSet<int32, InlinedAllocation<HASH_SET_DEFAULT_CAPACITY>> a2;
|
|
HashSet<int32, FixedAllocation<HASH_SET_DEFAULT_CAPACITY>> a3;
|
|
for (int32 i = 0; i < 7; i++)
|
|
{
|
|
a1.Add(i);
|
|
a2.Add(i);
|
|
a3.Add(i);
|
|
}
|
|
CHECK(a1.Count() == 7);
|
|
CHECK(a2.Count() == 7);
|
|
CHECK(a3.Count() == 7);
|
|
for (int32 i = 0; i < 7; i++)
|
|
{
|
|
CHECK(a1.Contains(i));
|
|
CHECK(a2.Contains(i));
|
|
CHECK(a3.Contains(i));
|
|
}
|
|
}
|
|
|
|
SECTION("Test Resizing")
|
|
{
|
|
HashSet<int32> a1;
|
|
for (int32 i = 0; i < 4000; i++)
|
|
a1.Add(i);
|
|
CHECK(a1.Count() == 4000);
|
|
int32 capacity = a1.Capacity();
|
|
for (int32 i = 0; i < 4000; i++)
|
|
{
|
|
CHECK(a1.Contains(i));
|
|
}
|
|
a1.Clear();
|
|
CHECK(a1.Count() == 0);
|
|
CHECK(a1.Capacity() == capacity);
|
|
for (int32 i = 0; i < 4000; i++)
|
|
a1.Add(i);
|
|
CHECK(a1.Count() == 4000);
|
|
CHECK(a1.Capacity() == capacity);
|
|
for (int32 i = 0; i < 4000; i++)
|
|
a1.Remove(i);
|
|
CHECK(a1.Count() == 0);
|
|
CHECK(a1.Capacity() == capacity);
|
|
for (int32 i = 0; i < 4000; i++)
|
|
a1.Add(i);
|
|
CHECK(a1.Count() == 4000);
|
|
CHECK(a1.Capacity() == capacity);
|
|
}
|
|
|
|
SECTION("Test Default Capacity")
|
|
{
|
|
HashSet<int32> a1;
|
|
a1.Add(1);
|
|
CHECK(a1.Capacity() <= HASH_SET_DEFAULT_CAPACITY);
|
|
}
|
|
|
|
SECTION("Test Add/Remove")
|
|
{
|
|
HashSet<int32> a1;
|
|
for (int32 i = 0; i < 4000; i++)
|
|
{
|
|
a1.Add(i);
|
|
a1.Remove(i);
|
|
}
|
|
CHECK(a1.Count() == 0);
|
|
CHECK(a1.Capacity() <= HASH_SET_DEFAULT_CAPACITY);
|
|
a1.Clear();
|
|
for (int32 i = 1; i <= 10; i++)
|
|
a1.Add(-i);
|
|
for (int32 i = 0; i < 4000; i++)
|
|
{
|
|
a1.Add(i);
|
|
a1.Remove(i);
|
|
}
|
|
CHECK(a1.Count() == 10);
|
|
CHECK(a1.Capacity() <= HASH_SET_DEFAULT_CAPACITY);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Dictionary")
|
|
{
|
|
SECTION("Test Allocators")
|
|
{
|
|
Dictionary<int32, int32> a1;
|
|
Dictionary<int32, int32, InlinedAllocation<HASH_SET_DEFAULT_CAPACITY>> a2;
|
|
Dictionary<int32, int32, FixedAllocation<HASH_SET_DEFAULT_CAPACITY>> a3;
|
|
for (int32 i = 0; i < 7; i++)
|
|
{
|
|
a1.Add(i, i);
|
|
a2.Add(i, i);
|
|
a3.Add(i, i);
|
|
}
|
|
CHECK(a1.Count() == 7);
|
|
CHECK(a2.Count() == 7);
|
|
CHECK(a3.Count() == 7);
|
|
for (int32 i = 0; i < 7; i++)
|
|
{
|
|
CHECK(a1.ContainsKey(i));
|
|
CHECK(a2.ContainsKey(i));
|
|
CHECK(a3.ContainsKey(i));
|
|
CHECK(a1.ContainsValue(i));
|
|
CHECK(a2.ContainsValue(i));
|
|
CHECK(a3.ContainsValue(i));
|
|
}
|
|
}
|
|
|
|
SECTION("Test Resizing")
|
|
{
|
|
Dictionary<int32, int32> a1;
|
|
for (int32 i = 0; i < 4000; i++)
|
|
a1.Add(i, i);
|
|
CHECK(a1.Count() == 4000);
|
|
int32 capacity = a1.Capacity();
|
|
for (int32 i = 0; i < 4000; i++)
|
|
{
|
|
CHECK(a1.ContainsKey(i));
|
|
CHECK(a1.ContainsValue(i));
|
|
}
|
|
a1.Clear();
|
|
CHECK(a1.Count() == 0);
|
|
CHECK(a1.Capacity() == capacity);
|
|
for (int32 i = 0; i < 4000; i++)
|
|
a1.Add(i, i);
|
|
CHECK(a1.Count() == 4000);
|
|
CHECK(a1.Capacity() == capacity);
|
|
for (int32 i = 0; i < 4000; i++)
|
|
a1.Remove(i);
|
|
CHECK(a1.Count() == 0);
|
|
CHECK(a1.Capacity() == capacity);
|
|
for (int32 i = 0; i < 4000; i++)
|
|
a1.Add(i, i);
|
|
CHECK(a1.Count() == 4000);
|
|
CHECK(a1.Capacity() == capacity);
|
|
}
|
|
|
|
SECTION("Test Default Capacity")
|
|
{
|
|
Dictionary<int32, int32> a1;
|
|
a1.Add(1, 1);
|
|
CHECK(a1.Capacity() <= HASH_SET_DEFAULT_CAPACITY);
|
|
}
|
|
|
|
SECTION("Test Add/Remove")
|
|
{
|
|
Dictionary<int32, int32> a1;
|
|
for (int32 i = 0; i < 4000; i++)
|
|
{
|
|
a1.Add(i, i);
|
|
a1.Remove(i);
|
|
}
|
|
CHECK(a1.Count() == 0);
|
|
CHECK(a1.Capacity() <= HASH_SET_DEFAULT_CAPACITY);
|
|
a1.Clear();
|
|
for (int32 i = 1; i <= 10; i++)
|
|
a1.Add(-i, -i);
|
|
for (int32 i = 0; i < 4000; i++)
|
|
{
|
|
a1.Add(i, i);
|
|
a1.Remove(i);
|
|
}
|
|
CHECK(a1.Count() == 10);
|
|
CHECK(a1.Capacity() <= HASH_SET_DEFAULT_CAPACITY);
|
|
}
|
|
}
|