diff --git a/Juliet/Juliet.vcxproj b/Juliet/Juliet.vcxproj index 1a25475..de66553 100644 --- a/Juliet/Juliet.vcxproj +++ b/Juliet/Juliet.vcxproj @@ -115,6 +115,7 @@ + @@ -218,9 +219,10 @@ + + - {ab9c7e88-6c94-4f93-bc2a-7f5284b7d434} diff --git a/Juliet/Juliet.vcxproj.filters b/Juliet/Juliet.vcxproj.filters index 863a7bf..9f1d957 100644 --- a/Juliet/Juliet.vcxproj.filters +++ b/Juliet/Juliet.vcxproj.filters @@ -192,6 +192,9 @@ src\Core\Common + + src\Core\Container + src\Core\HAL\Display @@ -501,6 +504,12 @@ src\Graphics + + src\UnitTest\Container + + + src\UnitTest + @@ -642,6 +651,11 @@ {f763d340-6c94-4f93-bc2a-7f5284b7d434} + + + {3e286bee-6c94-4f93-bc2a-7f5284b7d434} + + {82da0982-6c94-4f93-bc2a-7f5284b7d434} @@ -772,4 +786,14 @@ {0fd13bb0-6c94-4f93-bc2a-7f5284b7d434} + + + {3fba0971-6c94-4f93-bc2a-7f5284b7d434} + + + + + {a650fa16-6c94-4f93-bc2a-7f5284b7d434} + + \ No newline at end of file diff --git a/Juliet/include/Core/Common/CoreUtils.h b/Juliet/include/Core/Common/CoreUtils.h index 58edf80..4da2dba 100644 --- a/Juliet/include/Core/Common/CoreUtils.h +++ b/Juliet/include/Core/Common/CoreUtils.h @@ -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 +#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 diff --git a/Juliet/include/Core/Container/Vector.h b/Juliet/include/Core/Container/Vector.h index f542b5d..c3cc240 100644 --- a/Juliet/include/Core/Container/Vector.h +++ b/Juliet/include/Core/Container/Vector.h @@ -10,6 +10,7 @@ namespace Juliet template 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() diff --git a/Juliet/src/Core/Common/CoreUtils.cpp b/Juliet/src/Core/Common/CoreUtils.cpp index a2605ed..cecff81 100644 --- a/Juliet/src/Core/Common/CoreUtils.cpp +++ b/Juliet/src/Core/Common/CoreUtils.cpp @@ -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) diff --git a/Juliet/src/Core/Memory/MemoryArenaTests.cpp b/Juliet/src/Core/Memory/MemoryArenaTests.cpp index bf9a4bc..cc630e8 100644 --- a/Juliet/src/Core/Memory/MemoryArenaTests.cpp +++ b/Juliet/src/Core/Memory/MemoryArenaTests.cpp @@ -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); diff --git a/Juliet/src/Engine/Engine.cpp b/Juliet/src/Engine/Engine.cpp index 7c3b72a..6d1f90b 100644 --- a/Juliet/src/Engine/Engine.cpp +++ b/Juliet/src/Engine/Engine.cpp @@ -17,9 +17,9 @@ namespace Juliet { - #ifdef JULIET_DEBUG +#if JULIET_DEBUG extern void RunUnitTests(); - #endif +#endif namespace { @@ -135,10 +135,10 @@ namespace Juliet { InitializeLogManager(); MemoryArenasInit(); - - #ifdef JULIET_DEBUG + +#if JULIET_DEBUG RunUnitTests(); - #endif +#endif InitFilesystem(); diff --git a/Juliet/src/UnitTest/Container/VectorUnitTest.cpp b/Juliet/src/UnitTest/Container/VectorUnitTest.cpp index dc69046..3ee8450 100644 --- a/Juliet/src/UnitTest/Container/VectorUnitTest.cpp +++ b/Juliet/src/UnitTest/Container/VectorUnitTest.cpp @@ -1,57 +1,117 @@ -#ifdef JULIET_DEBUG +#if JULIET_DEBUG -#include #include +#include namespace Juliet { void VectorUnitTest() { - // Basic usage test + // Test 1: Integer VectorArena - Basic PushBack and Access { - Vector vec; - Assert(vec.empty()); - Assert(vec.size() == 0); + VectorArena 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 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 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 structVec; - structVec.push_back({ 42, true }); - - Assert(structVec.size() == 1); - Assert(structVec[0].Value == 42); - Assert(structVec[0].Active == true); + VectorArena vec; + vec.PushBack({ 1, 1.0f }); + vec.PushBack({ 2, 2.0f }); + vec.PushBack({ 3, 3.0f }); + + 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 \ No newline at end of file +#endif diff --git a/Juliet/src/UnitTest/RunUnitTests.cpp b/Juliet/src/UnitTest/RunUnitTests.cpp index eb342c6..537cc02 100644 --- a/Juliet/src/UnitTest/RunUnitTests.cpp +++ b/Juliet/src/UnitTest/RunUnitTests.cpp @@ -1,9 +1,8 @@ -#ifdef JULIET_DEBUG +#if JULIET_DEBUG +#include #include #include -#include - namespace Juliet { @@ -18,6 +17,6 @@ namespace Juliet LogMessage(LogCategory::Core, "Unit Tests Completed Successfully."); } -} +} // namespace Juliet -#endif \ No newline at end of file +#endif diff --git a/current_run.log b/current_run.log new file mode 100644 index 0000000..e69de29 diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..5669239 --- /dev/null +++ b/test.txt @@ -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] -------------------------