diff --git a/openVulkanoCpp/Data/Containers/RingBuffer.hpp b/openVulkanoCpp/Data/Containers/RingBuffer.hpp index d0dc9df..43dbcc5 100644 --- a/openVulkanoCpp/Data/Containers/RingBuffer.hpp +++ b/openVulkanoCpp/Data/Containers/RingBuffer.hpp @@ -477,6 +477,7 @@ namespace OpenVulkano else return (Parent::head = (Parent::HeadId() + 1) % Capacity()); } + public: ~RingBuffer() { Parent::Clear(); } diff --git a/tests/Data/Containers/RingBufferTest.cpp b/tests/Data/Containers/RingBufferTest.cpp index 27d7d6b..b49864d 100644 --- a/tests/Data/Containers/RingBufferTest.cpp +++ b/tests/Data/Containers/RingBufferTest.cpp @@ -13,167 +13,177 @@ using namespace OpenVulkano; // Helper to track construction/destruction struct Tracked { - static inline int ctorCount = 0; - static inline int dtorCount = 0; - int value; + static inline int ctorCount = 0; + static inline int dtorCount = 0; + int value; - Tracked(int v = 0) : value(v) { ++ctorCount; } - Tracked(const Tracked& other) : value(other.value) { ++ctorCount; } - Tracked(Tracked&& other) noexcept : value(other.value) { ++ctorCount; } - ~Tracked() { ++dtorCount; } + Tracked(int v = 0) : value(v) { ++ctorCount; } + Tracked(const Tracked& other) : value(other.value) { ++ctorCount; } + Tracked(Tracked&& other) noexcept : value(other.value) { ++ctorCount; } + ~Tracked() { ++dtorCount; } - Tracked& operator=(const Tracked&) = default; - Tracked& operator=(Tracked&&) = default; + Tracked& operator=(const Tracked&) = default; + Tracked& operator=(Tracked&&) = default; - friend bool operator==(const Tracked& lhs, const Tracked& rhs) { - return lhs.value == rhs.value; - } + friend bool operator==(const Tracked& lhs, const Tracked& rhs) { + return lhs.value == rhs.value; + } }; void reset_tracking() { - Tracked::ctorCount = 0; - Tracked::dtorCount = 0; + Tracked::ctorCount = 0; + Tracked::dtorCount = 0; } TEST_CASE("RingBuffer Tracking Destruction", "[RingBuffer][Tracked]") { - reset_tracking(); + reset_tracking(); - { - RingBuffer buf; - buf.Push(Tracked(1)); - buf.Push(Tracked(2)); - buf.PopFront(); - buf.Clear(); - } + { + RingBuffer buf; + buf.Push(Tracked(1)); + buf.Push(Tracked(2)); + buf.PopFront(); + buf.Clear(); + } - REQUIRE(Tracked::dtorCount == Tracked::ctorCount); + REQUIRE(Tracked::dtorCount == Tracked::ctorCount); } TEST_CASE("RingBuffer Push and Pop Operations", "[RingBuffer]") { - RingBuffer buf; + RingBuffer buf; - buf.Push(1); - buf.Push(2); - buf.Push(3); + buf.Push(1); + buf.Push(2); + buf.Push(3); - REQUIRE(buf.Count() == 3); - REQUIRE_FALSE(buf.HasFree()); + REQUIRE(buf.Count() == 3); + REQUIRE_FALSE(buf.HasFree()); - SECTION("PopFront/Back correctness") { - REQUIRE(buf.PopBack() == 1); - REQUIRE(buf.PopFront() == 3); - REQUIRE(buf.Count() == 1); - } + SECTION("PopFront/Back correctness") { + REQUIRE(buf.PopBack() == 1); + REQUIRE(buf.PopFront() == 3); + REQUIRE(buf.Count() == 1); + } - SECTION("Clear empties the buffer") { - buf.Clear(); - REQUIRE(buf.IsEmpty()); - REQUIRE(buf.Count() == 0); - } + SECTION("Clear empties the buffer") { + buf.Clear(); + REQUIRE(buf.IsEmpty()); + REQUIRE(buf.Count() == 0); + } } TEST_CASE("PushBack and PushFront Overwrite Logic", "[RingBuffer]") { - RingBuffer buf; - buf.Push(1); - buf.Push(2); + RingBuffer buf; + buf.Push(1); + buf.Push(2); - auto overwrittenFront = buf.PushFront(3); - REQUIRE(overwrittenFront.has_value()); - REQUIRE(overwrittenFront.value() == 1); + auto overwrittenFront = buf.PushFront(3); + REQUIRE(overwrittenFront.has_value()); + REQUIRE(overwrittenFront.value() == 1); - auto overwrittenBack = buf.PushBack(4); - REQUIRE(overwrittenBack.has_value()); - REQUIRE(overwrittenBack.value() == 2); + auto overwrittenBack = buf.PushBack(4); + REQUIRE(overwrittenBack.has_value()); + REQUIRE(overwrittenBack.value() == 2); - REQUIRE(buf.Front() == 3); - REQUIRE(buf.Back() == 4); + REQUIRE(buf.Front() == 3); + REQUIRE(buf.Back() == 4); } TEST_CASE("at() bounds checking", "[RingBuffer]") { - RingBuffer buf; - buf.Push(100); - buf.Push(200); + RingBuffer buf; + buf.Push(100); + buf.Push(200); - REQUIRE(buf.at(0) == 100); - REQUIRE(buf.at(1) == 200); - REQUIRE_THROWS_AS(buf.at(2), std::range_error); + REQUIRE(buf.at(0) == 100); + REQUIRE(buf.at(1) == 200); + REQUIRE_THROWS_AS(buf.at(2), std::range_error); } TEST_CASE("Index-based Access and Wraparound", "[RingBuffer]") { - RingBuffer buf; + RingBuffer buf; - buf.Push(1); - buf.Push(2); - buf.Push(3); - REQUIRE(buf[0] == 1); - REQUIRE(buf[1] == 2); - REQUIRE(buf[2] == 3); + buf.Push(1); + buf.Push(2); + buf.Push(3); + REQUIRE(buf[0] == 1); + REQUIRE(buf[1] == 2); + REQUIRE(buf[2] == 3); - buf.PopBack(); // Remove 1 - buf.Push(4); // Overwrites oldest (2) + buf.PopBack(); + buf.Push(4); - REQUIRE(buf[0] == 2); // Wrap-around behavior depends on ring position + REQUIRE(buf[0] == 2); + REQUIRE(buf[1] == 3); + REQUIRE(buf[2] == 4); + + // Test full wraparound + buf.Push(5); + buf.Push(6); + + REQUIRE(buf[0] == 4); + REQUIRE(buf[1] == 5); + REQUIRE(buf[2] == 6); } TEST_CASE("Emplace and EmplaceBack/Front work correctly", "[RingBuffer]") { - RingBuffer buf; + RingBuffer buf; - buf.Emplace("first"); - buf.EmplaceBack("second"); + buf.Emplace("first"); + buf.EmplaceBack("second"); - REQUIRE(buf.Count() == 2); - REQUIRE(buf[1] == "first"); - REQUIRE(buf[0] == "second"); + REQUIRE(buf.Count() == 2); + REQUIRE(buf[1] == "first"); + REQUIRE(buf[0] == "second"); - auto overwritten = buf.EmplaceFront("new"); - REQUIRE(overwritten.has_value()); - REQUIRE(overwritten.value() == "second"); - REQUIRE(buf.Front() == "new"); + auto overwritten = buf.EmplaceFront("new"); + REQUIRE(overwritten.has_value()); + REQUIRE(overwritten.value() == "second"); + REQUIRE(buf.Front() == "new"); } TEST_CASE("Iterators forward and reverse", "[RingBuffer]") { - RingBuffer buf; - buf.Push(10); - buf.Push(20); - buf.Push(30); + RingBuffer buf; + buf.Push(10); + buf.Push(20); + buf.Push(30); - std::vector forward; - for (int val : buf) forward.push_back(val); - REQUIRE(forward == std::vector{10, 20, 30}); + std::vector forward; + for (int val : buf) forward.push_back(val); + REQUIRE(forward == std::vector{10, 20, 30}); - std::vector reverse; - for (auto it = buf.rbegin(); it != buf.rend(); ++it) - reverse.push_back(*it); - REQUIRE(reverse == std::vector{30, 20, 10}); + std::vector reverse; + for (auto it = buf.rbegin(); it != buf.rend(); ++it) + reverse.push_back(*it); + REQUIRE(reverse == std::vector{30, 20, 10}); } TEST_CASE("Const correctness in iterators", "[RingBuffer][Const]") { - RingBuffer buf; - buf.Push(5); - buf.Push(6); + RingBuffer buf; + buf.Push(5); + buf.Push(6); - const auto& constBuf = buf; + const auto& constBuf = buf; - std::ostringstream oss; - for (auto it = constBuf.cbegin(); it != constBuf.cend(); ++it) { - oss << *it << " "; - } + std::ostringstream oss; + for (auto it = constBuf.cbegin(); it != constBuf.cend(); ++it) { + oss << *it << " "; + } - REQUIRE(oss.str() == "5 6 "); + REQUIRE(oss.str() == "5 6 "); } TEST_CASE("Dynamic RingBuffer behaves like static", "[RingBuffer][Dynamic]") { - RingBuffer buf(5); + RingBuffer buf(5); - for (int i = 0; i < 5; ++i) - buf.Push(i * 10); + for (int i = 0; i < 5; ++i) + buf.Push(i * 10); - REQUIRE(buf.Count() == 5); - REQUIRE_FALSE(buf.HasFree()); - REQUIRE(buf.Front() == 40); - REQUIRE(buf.Back() == 0); + REQUIRE(buf.Count() == 5); + REQUIRE_FALSE(buf.HasFree()); + REQUIRE(buf.Front() == 40); + REQUIRE(buf.Back() == 0); - auto val = buf.PopBack(); - REQUIRE(val == 0); - REQUIRE(buf.Count() == 4); + auto val = buf.PopBack(); + REQUIRE(val == 0); + REQUIRE(buf.Count() == 4); }