Unit test for vector

This commit is contained in:
2026-02-07 22:25:32 -05:00
parent 6f4fc75b66
commit 3edd23996e
11 changed files with 201 additions and 63 deletions

View File

@@ -115,6 +115,7 @@
<CustomBuild Include="src\Core\Application\ApplicationManager.cpp" />
<CustomBuild Include="src\Core\Common\CoreUtils.cpp" />
<CustomBuild Include="src\Core\Common\String.cpp" />
<CustomBuild Include="src\Core\Container\Vector.cpp" />
<CustomBuild Include="src\Core\HAL\Display\Display.cpp" />
<CustomBuild Include="src\Core\HAL\Display\Display_Private.h" />
<CustomBuild Include="src\Core\HAL\Display\DisplayDevice.h" />
@@ -218,9 +219,10 @@
<CustomBuild Include="src\Graphics\Graphics.cpp" />
<CustomBuild Include="src\Graphics\GraphicsDevice.h" />
<CustomBuild Include="src\Graphics\ImGuiRenderer.cpp" />
<CustomBuild Include="src\UnitTest\Container\VectorUnitTest.cpp" />
<CustomBuild Include="src\UnitTest\RunUnitTests.cpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Core\Container\Vector.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{ab9c7e88-6c94-4f93-bc2a-7f5284b7d434}</ProjectGuid>

View File

@@ -192,6 +192,9 @@
<CustomBuild Include="src\Core\Common\String.cpp">
<Filter>src\Core\Common</Filter>
</CustomBuild>
<CustomBuild Include="src\Core\Container\Vector.cpp">
<Filter>src\Core\Container</Filter>
</CustomBuild>
<CustomBuild Include="src\Core\HAL\Display\Display.cpp">
<Filter>src\Core\HAL\Display</Filter>
</CustomBuild>
@@ -501,6 +504,12 @@
<CustomBuild Include="src\Graphics\ImGuiRenderer.cpp">
<Filter>src\Graphics</Filter>
</CustomBuild>
<CustomBuild Include="src\UnitTest\Container\VectorUnitTest.cpp">
<Filter>src\UnitTest\Container</Filter>
</CustomBuild>
<CustomBuild Include="src\UnitTest\RunUnitTests.cpp">
<Filter>src\UnitTest</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<Filter Include="include\Core\Application">
@@ -642,6 +651,11 @@
<UniqueIdentifier>{f763d340-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Filter Include="src\Core\Container">
<UniqueIdentifier>{3e286bee-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Filter Include="src\Core\HAL\Display">
<UniqueIdentifier>{82da0982-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
@@ -772,4 +786,14 @@
<UniqueIdentifier>{0fd13bb0-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Filter Include="src\UnitTest\Container">
<UniqueIdentifier>{3fba0971-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Filter Include="src\UnitTest">
<UniqueIdentifier>{a650fa16-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@@ -14,17 +14,62 @@ namespace Juliet
#define global static
// 1. Stringify helpers
#define JULIET_STR(x) #x
#define JULIET_TOSTRING(x) JULIET_STR(x)
// 2. Define the pragma operator based on compiler
#if defined(__clang__) || defined(__GNUC__)
#define JULIET_PRAGMA(x) _Pragma(#x)
#define JULIET_SUPPRESS_MSVC(id)
#define JULIET_SUPPRESS_CLANG(str) JULIET_PRAGMA(clang diagnostic ignored str)
#elif defined(_MSC_VER)
#define JULIET_PRAGMA(x) __pragma(x)
#define JULIET_SUPPRESS_MSVC(id) JULIET_PRAGMA(warning(disable : id))
#define JULIET_SUPPRESS_CLANG(str)
#else
#define JULIET_PRAGMA(x)
#define JULIET_SUPPRESS_MSVC(id)
#define JULIET_SUPPRESS_CLANG(str)
#endif
// 3. The Agnostic "Push/Pop"
#if defined(__clang__)
#define JULIET_WARNING_PUSH JULIET_PRAGMA(clang diagnostic push)
#define JULIET_WARNING_POP JULIET_PRAGMA(clang diagnostic pop)
#elif defined(_MSC_VER)
#define JULIET_WARNING_PUSH JULIET_PRAGMA(warning(push))
#define JULIET_WARNING_POP JULIET_PRAGMA(warning(pop))
#else
#define JULIET_WARNING_PUSH
#define JULIET_WARNING_POP
#endif
#if defined(_MSC_VER)
// MSVC specific intrinsic
#define JULIET_PLATFORM_BREAK() (__nop(), __debugbreak())
#elif defined(__clang__) || defined(__GNUC__)
// Clang/GCC specific intrinsic
#define JULIET_PLATFORM_BREAK() __builtin_trap()
#else
#include <signal.h>
#define JULIET_PLATFORM_BREAK() raise(SIGTRAP)
#endif
#if JULIET_DEBUG
#define JULIET_ASSERT_INTERNAL(expression, message) \
__pragma(warning(push)) __pragma(warning(disable : 4127)) __pragma(warning(disable : 4548)) do \
JULIET_WARNING_PUSH \
JULIET_SUPPRESS_CLANG("-Wextra-semi-stmt") \
JULIET_SUPPRESS_MSVC(4127) \
JULIET_SUPPRESS_MSVC(4548) \
{ \
if (!(expression)) \
if (!(expression)) [[unlikely]] \
{ \
Juliet::JulietAssert(#expression, message); \
} \
} \
while (0) \
__pragma(warning(pop))
JULIET_WARNING_POP \
static_assert(true, "")
#define AssertHR(hr_expression, message) \
do \
@@ -117,11 +162,11 @@ namespace Juliet
return (x + alignment - 1) & ~(alignment - 1);
}
inline void Swap(auto* Restrict& a, auto* Restrict& b)
inline void Swap(auto* Restrict a, auto* Restrict b)
{
auto* temp = a;
a = b;
b = temp;
auto temp = *a;
*a = *b;
*b = temp;
}
// Move to another file dedicated to those

View File

@@ -10,6 +10,7 @@ namespace Juliet
template <typename Type>
struct VectorArena
{
public:
VectorArena()
: First(nullptr)
, Count(0)
@@ -39,12 +40,13 @@ namespace Juliet
Assert(index < Count);
Assert(Count > 0);
Type* baseAdr = First;
Type* elementAdr = First + index;
// Swap Last and element
Swap(Last, elementAdr);
--Last;
--Count;
ArenaPop(Arena, Stride);
}
void Clear()

View File

@@ -12,9 +12,7 @@ namespace Juliet
Log(LogLevel::Error, LogCategory::Core, "--- ASSERTION FAILED ---");
Log(LogLevel::Error, LogCategory::Core, "Expression: %s", expression);
Log(LogLevel::Error, LogCategory::Core, "Message: %s", message);
Log(LogLevel::Error, LogCategory::Core, "Location: %s(%u): %s",
location.file_name(),
location.line(),
Log(LogLevel::Error, LogCategory::Core, "Location: %s(%u): %s", location.file_name(), location.line(),
location.function_name());
if (handleResult < 0)
@@ -26,14 +24,7 @@ namespace Juliet
Log(LogLevel::Error, LogCategory::Core, "-------------------------");
if (IsDebuggerPresent())
{
__debugbreak();
}
else
{
exit(1);
}
JULIET_PLATFORM_BREAK();
}
void Free(ByteBuffer& buffer)

View File

@@ -89,8 +89,8 @@ namespace Juliet::UnitTest
Assert(reservedSizePreBigArray == testArena->Current->BasePosition);
// TODO Get page size from os kernel call (dwPageSize)
constexpr uint64 k_PageSize = Kilobytes(4);
size_t reserve_sizeAlignToPage = AlignPow2(reserve_size, k_PageSize);
constexpr uint64 k_PageSizeUnitTest = Kilobytes(4);
size_t reserve_sizeAlignToPage = AlignPow2(reserve_size, k_PageSizeUnitTest);
bool isReserveSizeSame = testArena->Current->Reserved == reserve_sizeAlignToPage;
Assert(isReserveSizeSame);

View File

@@ -17,9 +17,9 @@
namespace Juliet
{
#ifdef JULIET_DEBUG
#if JULIET_DEBUG
extern void RunUnitTests();
#endif
#endif
namespace
{
@@ -136,9 +136,9 @@ namespace Juliet
InitializeLogManager();
MemoryArenasInit();
#ifdef JULIET_DEBUG
#if JULIET_DEBUG
RunUnitTests();
#endif
#endif
InitFilesystem();

View File

@@ -1,57 +1,117 @@
#ifdef JULIET_DEBUG
#if JULIET_DEBUG
#include <Core/Container/Vector.h>
#include <Core/Common/CoreUtils.h>
#include <Core/Container/Vector.h>
namespace Juliet
{
void VectorUnitTest()
{
// Basic usage test
// Test 1: Integer VectorArena - Basic PushBack and Access
{
Vector<int> vec;
Assert(vec.empty());
Assert(vec.size() == 0);
VectorArena<int> vec;
Assert(vec.Size() == 0);
Assert(vec.begin() == vec.end());
vec.push_back(10);
Assert(!vec.empty());
Assert(vec.size() == 1);
vec.PushBack(10);
Assert(vec.Size() == 1);
Assert(vec[0] == 10);
Assert(*vec.begin() == 10);
vec.push_back(20);
Assert(vec.size() == 2);
vec.PushBack(20);
Assert(vec.Size() == 2);
Assert(vec[0] == 10);
Assert(vec[1] == 20);
// Test iteration (std::vector iterator compatibility)
vec.PushBack(30);
Assert(vec.Size() == 3);
Assert(vec[2] == 30);
// Test Iteration
int sum = 0;
for (int val : vec)
{
sum += val;
}
Assert(sum == 30);
vec.clear();
Assert(vec.empty());
Assert(vec.size() == 0);
Assert(sum == 60);
}
// Test with complex types (std::string) to ensure proper construction/destruction
// Note: Vector.h currently inherits from std::vector, so this tests std::vector really.
// Test 2: RemoveAtFast
{
struct TestStruct
VectorArena<int> vec;
vec.PushBack(10);
vec.PushBack(20);
vec.PushBack(30);
// Initial: [10, 20, 30]
// Remove index 0 (value 10). Should swap with Last (30) and pop last.
// Expected: [30, 20]
vec.RemoveAtFast(0);
Assert(vec.Size() == 2);
Assert(vec[0] == 30);
Assert(vec[1] == 20);
// Remove index 1 (value 20). Last is 20. Swap 20 with 20.
// Expected: [30]
vec.RemoveAtFast(1);
Assert(vec.Size() == 1);
Assert(vec[0] == 30);
// Remove remaining element
vec.RemoveAtFast(0);
Assert(vec.Size() == 0);
}
// Test 3: Clear and Reuse
{
VectorArena<int> vec;
vec.PushBack(100);
vec.PushBack(200);
Assert(vec.Size() == 2);
vec.Clear();
Assert(vec.Size() == 0);
Assert(vec.begin() == vec.end());
// Should be able to push again
vec.PushBack(300);
Assert(vec.Size() == 1);
Assert(vec[0] == 300);
}
// Test 4: Struct VectorArena (Testing Move Semantics and Complex Types)
{
struct TestItem
{
int Value;
bool Active;
int A;
float B;
bool operator==(const TestItem& other) const
{
float diff = B - other.B;
return A == other.A && (diff > -0.0001f && diff < 0.0001f);
}
};
Vector<TestStruct> structVec;
structVec.push_back({ 42, true });
VectorArena<TestItem> vec;
vec.PushBack({ 1, 1.0f });
vec.PushBack({ 2, 2.0f });
vec.PushBack({ 3, 3.0f });
Assert(structVec.size() == 1);
Assert(structVec[0].Value == 42);
Assert(structVec[0].Active == true);
Assert(vec.Size() == 3);
Assert(vec[0].A == 1);
Assert(vec[1].A == 2);
// Remove middle element (index 1, value {2, 2.0f})
// Should swap with last ({3, 3.0f})
// Result: [{1, 1.0f}, {3, 3.0f}]
vec.RemoveAtFast(1);
Assert(vec.Size() == 2);
// Use operator== to verify entire struct including float
Assert(vec[0] == (TestItem{ 1, 1.0f }));
Assert(vec[1] == (TestItem{ 3, 3.0f }));
}
}
}
} // namespace Juliet
#endif

View File

@@ -1,9 +1,8 @@
#ifdef JULIET_DEBUG
#if JULIET_DEBUG
#include <Core/Common/CoreUtils.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Common/CoreUtils.h>
namespace Juliet
{
@@ -18,6 +17,6 @@ namespace Juliet
LogMessage(LogCategory::Core, "Unit Tests Completed Successfully.");
}
}
} // namespace Juliet
#endif

0
current_run.log Normal file
View File

15
test.txt Normal file
View File

@@ -0,0 +1,15 @@
--- Launching JulietApp.exe ---
Platform: x64Clang
Config: Debug
Running Paged Memory Arena Tests...
[2026-02-08 02:56:49.1217020] Allocating from W:\Classified\Juliet\Juliet\src\Core\Memory\MemoryArenaTests.cpp : 23l
[2026-02-08 02:56:49.1220553] Allocating from W:\Classified\Juliet\Juliet\src\Core\Memory\MemoryArena.cpp : 99l
[Success] Arena Pop
All Paged MemoryArena tests passed.
[2026-02-08 02:56:49.1319769] Starting Unit Tests...
[2026-02-08 02:56:49.1320761] Allocating from Juliet/include\Core/Container/Vector.h : 19l
[2026-02-08 02:56:49.1321474] --- ASSERTION FAILED ---
[2026-02-08 02:56:49.1321999] Expression: vec[0] == 30
[2026-02-08 02:56:49.1322519] Message: No additional information provided.
[2026-02-08 02:56:49.1323083] Location: W:\Classified\Juliet\Juliet\src\UnitTest\Container\VectorUnitTest.cpp(45): void __cdecl Juliet::VectorUnitTest(void)
[2026-02-08 02:56:49.1323588] -------------------------