From 378f4923b747f7709666af39727cbd5f1c26867e Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Tue, 13 May 2025 19:31:46 +0200 Subject: [PATCH] Fix some warnings --- openVulkanoCpp/Data/Containers/RingBuffer.hpp | 4 +- tests/Data/Containers/RingBufferTest.cpp | 931 +++++++++--------- 2 files changed, 468 insertions(+), 467 deletions(-) diff --git a/openVulkanoCpp/Data/Containers/RingBuffer.hpp b/openVulkanoCpp/Data/Containers/RingBuffer.hpp index 84a941a..90d7997 100644 --- a/openVulkanoCpp/Data/Containers/RingBuffer.hpp +++ b/openVulkanoCpp/Data/Containers/RingBuffer.hpp @@ -459,7 +459,7 @@ namespace OpenVulkano return (Parent::HeadId() + 1 + Capacity() - Parent::Count()) % Capacity(); } - [[nodiscard]] size_t IncrementHead() + size_t IncrementHead() { if (Parent::IsEmpty()) [[unlikely]] return Parent::head; return (Parent::head = (Parent::HeadId() + 1) % Capacity()); @@ -504,7 +504,7 @@ namespace OpenVulkano return (Parent::HeadId() + 1 + Capacity() - Parent::Count()) % Capacity(); } - [[nodiscard]] size_t IncrementHead() + size_t IncrementHead() { if (Parent::IsEmpty()) [[unlikely]] return Parent::head; if constexpr (POW2) diff --git a/tests/Data/Containers/RingBufferTest.cpp b/tests/Data/Containers/RingBufferTest.cpp index ac59c61..5e01357 100644 --- a/tests/Data/Containers/RingBufferTest.cpp +++ b/tests/Data/Containers/RingBufferTest.cpp @@ -16,553 +16,554 @@ using namespace OpenVulkano; // Helper to track construction/destruction struct Tracked { - static inline int ctorCount = 0; - static inline int dtorCount = 0; - static inline int moveCount = 0; - static inline int copyCount = 0; - int value; + static inline int ctorCount = 0; + static inline int dtorCount = 0; + static inline int moveCount = 0; + static inline int copyCount = 0; + int value; - Tracked(int v = 0) : value(v) { ++ctorCount; } - Tracked(const Tracked& other) : value(other.value) { ++ctorCount; ++copyCount; } - Tracked(Tracked&& other) noexcept : value(other.value) { ++ctorCount; ++moveCount; } - ~Tracked() { ++dtorCount; } + Tracked(int v = 0) : value(v) { ++ctorCount; } + Tracked(const Tracked& other) : value(other.value) { ++ctorCount; ++copyCount; } + Tracked(Tracked&& other) noexcept : value(other.value) { ++ctorCount; ++moveCount; } + ~Tracked() { ++dtorCount; } - Tracked& operator=(const Tracked& other) { - value = other.value; - ++copyCount; - return *this; - } - - Tracked& operator=(Tracked&& other) noexcept { - value = other.value; - ++moveCount; - return *this; - } + Tracked& operator=(const Tracked& other) { + value = other.value; + ++copyCount; + return *this; + } + + Tracked& operator=(Tracked&& other) noexcept { + value = other.value; + ++moveCount; + return *this; + } - 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::moveCount = 0; - Tracked::copyCount = 0; + Tracked::ctorCount = 0; + Tracked::dtorCount = 0; + Tracked::moveCount = 0; + Tracked::copyCount = 0; } TEST_CASE("RingBuffer Basic Construction", "[RingBuffer]") { - SECTION("Static buffer construction") { - RingBuffer buf; - REQUIRE(buf.Capacity() == 5); - REQUIRE(buf.IsEmpty()); - REQUIRE(buf.Count() == 0); - REQUIRE(buf.HasFree()); - } - - SECTION("Dynamic buffer construction") { - RingBuffer buf(10); - REQUIRE(buf.Capacity() == 10); - REQUIRE(buf.IsEmpty()); - REQUIRE(buf.Count() == 0); - REQUIRE(buf.HasFree()); - } + SECTION("Static buffer construction") { + RingBuffer buf; + REQUIRE(buf.Capacity() == 5); + REQUIRE(buf.IsEmpty()); + REQUIRE(buf.Count() == 0); + REQUIRE(buf.HasFree()); + } + + SECTION("Dynamic buffer construction") { + RingBuffer buf(10); + REQUIRE(buf.Capacity() == 10); + REQUIRE(buf.IsEmpty()); + REQUIRE(buf.Count() == 0); + REQUIRE(buf.HasFree()); + } } 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 Move and Copy Semantics", "[RingBuffer][Tracked]") { - reset_tracking(); - - { - RingBuffer buf; - - SECTION("Push with move") { - Tracked t(42); - buf.Push(std::move(t)); - REQUIRE(Tracked::moveCount >= 1); - REQUIRE(buf.Front().value == 42); - } - - SECTION("Push with copy") { - Tracked t(42); - buf.Push(t); - REQUIRE(Tracked::copyCount >= 1); - REQUIRE(buf.Front().value == 42); - } - - SECTION("Emplace constructs in-place") { - int initialCtors = Tracked::ctorCount; - buf.Emplace(99); - REQUIRE(Tracked::ctorCount == initialCtors + 1); - REQUIRE(buf.Front().value == 99); - } - } - - REQUIRE(Tracked::dtorCount == Tracked::ctorCount); + reset_tracking(); + + { + RingBuffer buf; + + SECTION("Push with move") { + Tracked t(42); + buf.Push(std::move(t)); + REQUIRE(Tracked::moveCount >= 1); + REQUIRE(buf.Front().value == 42); + } + + SECTION("Push with copy") { + Tracked t(42); + buf.Push(t); + REQUIRE(Tracked::copyCount >= 1); + REQUIRE(buf.Front().value == 42); + } + + SECTION("Emplace constructs in-place") { + int initialCtors = Tracked::ctorCount; + buf.Emplace(99); + REQUIRE(Tracked::ctorCount == initialCtors + 1); + REQUIRE(buf.Front().value == 99); + } + } + + 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); - REQUIRE(buf.PopFront() == 2); - REQUIRE(buf.IsEmpty()); - REQUIRE_THROWS_AS(buf.PopFront(), std::underflow_error); - REQUIRE_THROWS_AS(buf.PopBack(), std::underflow_error); - } + SECTION("PopFront/Back correctness") { + REQUIRE(buf.PopBack() == 1); + REQUIRE(buf.PopFront() == 3); + REQUIRE(buf.Count() == 1); + REQUIRE(buf.PopFront() == 2); + REQUIRE(buf.IsEmpty()); + REQUIRE_THROWS_AS(buf.PopFront(), std::underflow_error); + REQUIRE_THROWS_AS(buf.PopBack(), std::underflow_error); + } - SECTION("Clear empties the buffer") { - buf.Clear(); - REQUIRE(buf.IsEmpty()); - REQUIRE(buf.Count() == 0); - } - - SECTION("Front and Back access") { - REQUIRE(buf.Front() == 3); - REQUIRE(buf.Back() == 1); - - buf.PopFront(); - REQUIRE(buf.Front() == 2); - REQUIRE(buf.Back() == 1); - - buf.PopBack(); - REQUIRE(buf.Front() == 2); - REQUIRE(buf.Back() == 2); - } + SECTION("Clear empties the buffer") { + buf.Clear(); + REQUIRE(buf.IsEmpty()); + REQUIRE(buf.Count() == 0); + } + + SECTION("Front and Back access") { + REQUIRE(buf.Front() == 3); + REQUIRE(buf.Back() == 1); + + buf.PopFront(); + REQUIRE(buf.Front() == 2); + REQUIRE(buf.Back() == 1); + + buf.PopBack(); + REQUIRE(buf.Front() == 2); + REQUIRE(buf.Back() == 2); + } } TEST_CASE("RingBuffer PushNoOverwrite operation", "[RingBuffer]") { - RingBuffer buf; - - buf.PushNoOverwrite(1); - buf.PushNoOverwrite(2); - REQUIRE_THROWS_AS(buf.PushNoOverwrite(3), std::overflow_error); - - SECTION("EmplaceNoOverwrite") { - RingBuffer strBuf; - strBuf.EmplaceNoOverwrite("first"); - strBuf.EmplaceNoOverwrite("second"); - REQUIRE_THROWS_AS(strBuf.EmplaceNoOverwrite("third"), std::overflow_error); - } + RingBuffer buf; + + buf.PushNoOverwrite(1); + buf.PushNoOverwrite(2); + REQUIRE_THROWS_AS(buf.PushNoOverwrite(3), std::overflow_error); + + SECTION("EmplaceNoOverwrite") { + RingBuffer strBuf; + strBuf.EmplaceNoOverwrite("first"); + strBuf.EmplaceNoOverwrite("second"); + REQUIRE_THROWS_AS(strBuf.EmplaceNoOverwrite("third"), std::overflow_error); + } } TEST_CASE("RingBuffer PushAndOverwrite operation", "[RingBuffer]") { - RingBuffer buf; - - SECTION("Cannot use PushAndOverwrite when buffer not full") { - buf.Push(1); - REQUIRE_THROWS_AS(buf.PushAndOverwrite(5), std::runtime_error); - } - - SECTION("PushAndOverwrite returns overwritten value") { - buf.Fill(42); - REQUIRE(buf.Count() == 2); - - int overwritten = buf.PushAndOverwrite(99); - REQUIRE(overwritten == 42); - REQUIRE(buf.Front() == 99); - REQUIRE(buf.Back() == 42); - } + RingBuffer buf; + + SECTION("Cannot use PushAndOverwrite when buffer not full") { + buf.Push(1); + REQUIRE_THROWS_AS(buf.PushAndOverwrite(5), std::runtime_error); + } + + SECTION("PushAndOverwrite returns overwritten value") { + buf.Fill(42); + REQUIRE(buf.Count() == 2); + + int overwritten = buf.PushAndOverwrite(99); + REQUIRE(overwritten == 42); + REQUIRE(buf.Front() == 99); + REQUIRE(buf.Back() == 42); + } } TEST_CASE("PushBack and PushFront Overwrite Logic", "[RingBuffer]") { - RingBuffer buf; - buf.Push(1); - buf.Push(2); + RingBuffer buf; + buf.Push(1); + buf.Push(2); - SECTION("PushFront overwrites correctly") { - auto overwrittenFront = buf.PushFront(3); - REQUIRE(overwrittenFront.has_value()); - REQUIRE(overwrittenFront.value() == 1); - REQUIRE(buf.Front() == 3); - REQUIRE(buf.Back() == 2); - } + SECTION("PushFront overwrites correctly") { + auto overwrittenFront = buf.PushFront(3); + REQUIRE(overwrittenFront.has_value()); + REQUIRE(overwrittenFront.value() == 1); + REQUIRE(buf.Front() == 3); + REQUIRE(buf.Back() == 2); + } - SECTION("PushBack overwrites correctly") { - auto overwrittenBack = buf.PushBack(4); - REQUIRE(overwrittenBack.has_value()); - REQUIRE(overwrittenBack.value() == 1); - REQUIRE(buf.Front() == 2); - REQUIRE(buf.Back() == 4); - } - - SECTION("PushFront with available space doesn't overwrite") { - RingBuffer buf2; - buf2.Push(10); - - auto result = buf2.PushFront(20); - REQUIRE_FALSE(result.has_value()); - REQUIRE(buf2.Count() == 2); - REQUIRE(buf2.Front() == 20); - REQUIRE(buf2.Back() == 10); - } - - SECTION("PushBack with available space doesn't overwrite") { - RingBuffer buf2; - buf2.Push(10); - - auto result = buf2.PushBack(20); - REQUIRE_FALSE(result.has_value()); - REQUIRE(buf2.Count() == 2); - REQUIRE(buf2.Front() == 10); - REQUIRE(buf2.Back() == 20); - } + SECTION("PushBack overwrites correctly") { + auto overwrittenBack = buf.PushBack(4); + REQUIRE(overwrittenBack.has_value()); + REQUIRE(overwrittenBack.value() == 1); + REQUIRE(buf.Front() == 2); + REQUIRE(buf.Back() == 4); + } + + SECTION("PushFront with available space doesn't overwrite") { + RingBuffer buf2; + buf2.Push(10); + + auto result = buf2.PushFront(20); + REQUIRE_FALSE(result.has_value()); + REQUIRE(buf2.Count() == 2); + REQUIRE(buf2.Front() == 20); + REQUIRE(buf2.Back() == 10); + } + + SECTION("PushBack with available space doesn't overwrite") { + RingBuffer buf2; + buf2.Push(10); + + auto result = buf2.PushBack(20); + REQUIRE_FALSE(result.has_value()); + REQUIRE(buf2.Count() == 2); + REQUIRE(buf2.Front() == 10); + REQUIRE(buf2.Back() == 20); + } } 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); - - SECTION("const at() works correctly") { - const auto& constBuf = buf; - REQUIRE(constBuf.at(0) == 100); - REQUIRE(constBuf.at(1) == 200); - REQUIRE_THROWS_AS(constBuf.at(2), std::range_error); - } + REQUIRE(buf.at(0) == 100); + REQUIRE(buf.at(1) == 200); + REQUIRE_THROWS_AS(buf.at(2), std::range_error); + + SECTION("const at() works correctly") { + const auto& constBuf = buf; + REQUIRE(constBuf.at(0) == 100); + REQUIRE(constBuf.at(1) == 200); + REQUIRE_THROWS_AS(constBuf.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(); - buf.Push(4); + buf.PopBack(); + buf.Push(4); - REQUIRE(buf[0] == 2); - REQUIRE(buf[1] == 3); - REQUIRE(buf[2] == 4); + REQUIRE(buf[0] == 2); + REQUIRE(buf[1] == 3); + REQUIRE(buf[2] == 4); - // Test full wraparound - buf.Push(5); - buf.Push(6); + // Test full wraparound + buf.Push(5); + buf.Push(6); - REQUIRE(buf[0] == 4); - REQUIRE(buf[1] == 5); - REQUIRE(buf[2] == 6); - - SECTION("Wraparound with power-of-2 size") { - RingBuffer powBuf; // Power of 2 size for different code path - - for (int i = 1; i <= 4; i++) { - powBuf.Push(i); - } - - REQUIRE(powBuf[0] == 1); - REQUIRE(powBuf[3] == 4); - - powBuf.PopBack(); - powBuf.Push(5); - - REQUIRE(powBuf[0] == 2); - REQUIRE(powBuf[3] == 5); - } + REQUIRE(buf[0] == 4); + REQUIRE(buf[1] == 5); + REQUIRE(buf[2] == 6); + + SECTION("Wraparound with power-of-2 size") { + RingBuffer powBuf; // Power of 2 size for different code path + + for (int i = 1; i <= 4; i++) { + powBuf.Push(i); + } + + REQUIRE(powBuf[0] == 1); + REQUIRE(powBuf[3] == 4); + + powBuf.PopBack(); + powBuf.Push(5); + + REQUIRE(powBuf[0] == 2); + REQUIRE(powBuf[3] == 5); + } } TEST_CASE("Fill operation", "[RingBuffer]") { - RingBuffer buf; - - SECTION("Fill empty buffer") { - buf.Fill(42); - REQUIRE(buf.Count() == 5); - REQUIRE_FALSE(buf.HasFree()); - - for (int i = 0; i < 5; i++) { - REQUIRE(buf[i] == 42); - } - } - - SECTION("Fill partially full buffer") { - buf.Push(1); - buf.Push(2); - - buf.Fill(99); - REQUIRE(buf.Count() == 5); - REQUIRE_FALSE(buf.HasFree()); - - REQUIRE(buf[0] == 1); - REQUIRE(buf[1] == 2); - REQUIRE(buf[2] == 99); - REQUIRE(buf[3] == 99); - REQUIRE(buf[4] == 99); - } + RingBuffer buf; + + SECTION("Fill empty buffer") { + buf.Fill(42); + REQUIRE(buf.Count() == 5); + REQUIRE_FALSE(buf.HasFree()); + + for (int i = 0; i < 5; i++) { + REQUIRE(buf[i] == 42); + } + } + + SECTION("Fill partially full buffer") { + buf.Push(1); + buf.Push(2); + + buf.Fill(99); + REQUIRE(buf.Count() == 5); + REQUIRE_FALSE(buf.HasFree()); + + REQUIRE(buf[0] == 1); + REQUIRE(buf[1] == 2); + REQUIRE(buf[2] == 99); + REQUIRE(buf[3] == 99); + REQUIRE(buf[4] == 99); + } } 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"); - - SECTION("EmplaceNoOverwrite throws when full") { - RingBuffer buf2; - buf2.EmplaceNoOverwrite("one"); - buf2.EmplaceNoOverwrite("two"); - REQUIRE_THROWS_AS(buf2.EmplaceNoOverwrite("three"), std::overflow_error); - } + auto overwritten = buf.EmplaceFront("new"); + REQUIRE(overwritten.has_value()); + REQUIRE(overwritten.value() == "second"); + REQUIRE(buf.Front() == "new"); + + SECTION("EmplaceNoOverwrite throws when full") { + RingBuffer buf2; + buf2.EmplaceNoOverwrite("one"); + buf2.EmplaceNoOverwrite("two"); + REQUIRE_THROWS_AS(buf2.EmplaceNoOverwrite("three"), std::overflow_error); + } } 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); - SECTION("Forward iteration") { - std::vector forward; - for (int val : buf) forward.push_back(val); - REQUIRE(forward == std::vector{10, 20, 30}); - } + SECTION("Forward iteration") { + std::vector forward; + for (int val : buf) forward.push_back(val); + REQUIRE(forward == std::vector{10, 20, 30}); + } - SECTION("Reverse iteration") { - std::vector reverse; - for (auto it = buf.rbegin(); it != buf.rend(); ++it) - reverse.push_back(*it); - REQUIRE(reverse == std::vector{30, 20, 10}); - } - - SECTION("Iterator decrement") { - auto it = buf.end(); - --it; - REQUIRE(*it == 30); - --it; - REQUIRE(*it == 20); - --it; - REQUIRE(*it == 10); - } - - SECTION("Reverse iterator decrement") { - auto it = buf.rend(); - --it; - REQUIRE(*it == 10); - --it; - REQUIRE(*it == 20); - --it; - REQUIRE(*it == 30); - } - - SECTION("Iterator post-increment/decrement") { - auto it = buf.begin(); - REQUIRE(*(it++) == 10); - REQUIRE(*it == 20); - - auto it2 = --buf.end(); - REQUIRE(*(it2--) == 30); - REQUIRE(*it2 == 20); - } - - SECTION("Empty buffer iteration") { - RingBuffer emptyBuf; - REQUIRE(emptyBuf.begin() == emptyBuf.end()); - REQUIRE(emptyBuf.rbegin() == emptyBuf.rend()); - } + SECTION("Reverse iteration") { + std::vector reverse; + for (auto it = buf.rbegin(); it != buf.rend(); ++it) + reverse.push_back(*it); + REQUIRE(reverse == std::vector{30, 20, 10}); + } + + SECTION("Iterator decrement") { + auto it = buf.end(); + --it; + REQUIRE(*it == 30); + --it; + REQUIRE(*it == 20); + --it; + REQUIRE(*it == 10); + } + + SECTION("Reverse iterator decrement") { + auto it = buf.rend(); + --it; + REQUIRE(*it == 10); + --it; + REQUIRE(*it == 20); + --it; + REQUIRE(*it == 30); + } + + SECTION("Iterator post-increment/decrement") { + auto it = buf.begin(); + REQUIRE(*(it++) == 10); + REQUIRE(*it == 20); + + auto it2 = --buf.end(); + REQUIRE(*(it2--) == 30); + REQUIRE(*it2 == 20); + } + + SECTION("Empty buffer iteration") { + RingBuffer emptyBuf; + REQUIRE(emptyBuf.begin() == emptyBuf.end()); + REQUIRE(emptyBuf.rbegin() == emptyBuf.rend()); + } } 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; - SECTION("const_iterator usage") { - std::ostringstream oss; - for (auto it = constBuf.cbegin(); it != constBuf.cend(); ++it) { - oss << *it << " "; - } - REQUIRE(oss.str() == "5 6 "); - } - - SECTION("const rbegin/rend usage") { - std::vector values; - for (auto it = constBuf.crbegin(); it != constBuf.crend(); ++it) { - values.push_back(*it); - } - REQUIRE(values == std::vector{6, 5}); - } - - SECTION("const operator[]") { - REQUIRE(constBuf[0] == 5); - REQUIRE(constBuf[1] == 6); - } + SECTION("const_iterator usage") { + std::ostringstream oss; + for (auto it = constBuf.cbegin(); it != constBuf.cend(); ++it) { + oss << *it << " "; + } + REQUIRE(oss.str() == "5 6 "); + } + + SECTION("const rbegin/rend usage") { + std::vector values; + for (auto it = constBuf.crbegin(); it != constBuf.crend(); ++it) { + values.push_back(*it); + } + REQUIRE(values == std::vector{6, 5}); + } + + SECTION("const operator[]") { + REQUIRE(constBuf[0] == 5); + REQUIRE(constBuf[1] == 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); - - SECTION("Dynamic buffer wraparound") { - buf.Push(50); - REQUIRE(buf.Front() == 50); - REQUIRE(buf.Back() == 10); - - buf.Push(60); - REQUIRE(buf[0] == 20); - REQUIRE(buf[1] == 30); - REQUIRE(buf[2] == 40); - REQUIRE(buf[3] == 50); - REQUIRE(buf[4] == 60); - } + auto val = buf.PopBack(); + REQUIRE(val == 0); + REQUIRE(buf.Count() == 4); + + SECTION("Dynamic buffer wraparound") { + buf.Push(50); + REQUIRE(buf.Front() == 50); + REQUIRE(buf.Back() == 10); + + buf.Push(60); + REQUIRE(buf[0] == 20); + REQUIRE(buf[1] == 30); + REQUIRE(buf[2] == 40); + REQUIRE(buf[3] == 50); + REQUIRE(buf[4] == 60); + } } TEST_CASE("RingBuffer with complex types", "[RingBuffer][Complex]") { - RingBuffer, 3> buf; - - buf.Push(std::vector{1, 2, 3}); - buf.Emplace(std::initializer_list{4, 5, 6}); - - REQUIRE(buf.Count() == 2); - REQUIRE(buf.Front()[0] == 4); - REQUIRE(buf.Front()[2] == 6); - REQUIRE(buf.Back()[0] == 1); - REQUIRE(buf.Back()[2] == 3); - - buf.PushFront(std::vector{7, 8, 9}); - REQUIRE(buf.Front()[0] == 7); - - buf.Clear(); - REQUIRE(buf.IsEmpty()); + RingBuffer, 3> buf; + + buf.Push(std::vector{1, 2, 3}); + buf.Emplace(std::initializer_list{4, 5, 6}); + + REQUIRE(buf.Count() == 2); + REQUIRE(buf.Front()[0] == 4); + REQUIRE(buf.Front()[2] == 6); + REQUIRE(buf.Back()[0] == 1); + REQUIRE(buf.Back()[2] == 3); + + const auto ret = buf.PushFront(std::vector{7, 8, 9}); + REQUIRE(!ret.has_value()); + REQUIRE(buf.Front()[0] == 7); + + buf.Clear(); + REQUIRE(buf.IsEmpty()); } TEST_CASE("Iterator operations with wrapped buffer", "[RingBuffer][Iterators]") { - RingBuffer buf; - - // Fill buffer - for (int i = 1; i <= 5; i++) { - buf.Push(i); - } - - // Force wraparound - buf.PopBack(); - buf.PopBack(); - buf.Push(6); - buf.Push(7); - - // Buffer should now be: 3, 4, 5, 6, 7 with internal wraparound - - std::vector values; - for (auto val : buf) { - values.push_back(val); - } - - REQUIRE(values == std::vector{3, 4, 5, 6, 7}); - - std::vector reverseValues; - for (auto it = buf.rbegin(); it != buf.rend(); ++it) { - reverseValues.push_back(*it); - } - - REQUIRE(reverseValues == std::vector{7, 6, 5, 4, 3}); + RingBuffer buf; + + // Fill buffer + for (int i = 1; i <= 5; i++) { + buf.Push(i); + } + + // Force wraparound + buf.PopBack(); + buf.PopBack(); + buf.Push(6); + buf.Push(7); + + // Buffer should now be: 3, 4, 5, 6, 7 with internal wraparound + + std::vector values; + for (auto val : buf) { + values.push_back(val); + } + + REQUIRE(values == std::vector{3, 4, 5, 6, 7}); + + std::vector reverseValues; + for (auto it = buf.rbegin(); it != buf.rend(); ++it) { + reverseValues.push_back(*it); + } + + REQUIRE(reverseValues == std::vector{7, 6, 5, 4, 3}); } TEST_CASE("Edge cases", "[RingBuffer][EdgeCases]") { - SECTION("Capacity of 1") { - RingBuffer buf; - REQUIRE(buf.Capacity() == 1); - REQUIRE(buf.IsEmpty()); - - buf.Push(42); - REQUIRE(buf.Front() == 42); - REQUIRE(buf.Back() == 42); - REQUIRE_FALSE(buf.HasFree()); - - buf.Push(99); - REQUIRE(buf.Front() == 99); - REQUIRE(buf.Back() == 99); - - buf.PopFront(); - REQUIRE(buf.IsEmpty()); - REQUIRE_THROWS_AS(buf.PopFront(), std::underflow_error); - } - - SECTION("Dynamic buffer with size 1") { - RingBuffer buf(1); - buf.Push(42); - REQUIRE(buf.Front() == 42); - REQUIRE_FALSE(buf.HasFree()); - - buf.Push(99); - REQUIRE(buf.Front() == 99); - } + SECTION("Capacity of 1") { + RingBuffer buf; + REQUIRE(buf.Capacity() == 1); + REQUIRE(buf.IsEmpty()); + + buf.Push(42); + REQUIRE(buf.Front() == 42); + REQUIRE(buf.Back() == 42); + REQUIRE_FALSE(buf.HasFree()); + + buf.Push(99); + REQUIRE(buf.Front() == 99); + REQUIRE(buf.Back() == 99); + + buf.PopFront(); + REQUIRE(buf.IsEmpty()); + REQUIRE_THROWS_AS(buf.PopFront(), std::underflow_error); + } + + SECTION("Dynamic buffer with size 1") { + RingBuffer buf(1); + buf.Push(42); + REQUIRE(buf.Front() == 42); + REQUIRE_FALSE(buf.HasFree()); + + buf.Push(99); + REQUIRE(buf.Front() == 99); + } } TEST_CASE("Algorithm compatibility", "[RingBuffer][Algorithms]") { - RingBuffer buf; - for (int i = 1; i <= 5; i++) { - buf.Push(i); - } - - SECTION("std::find") { - auto it = std::find(buf.begin(), buf.end(), 3); - REQUIRE(it != buf.end()); - REQUIRE(*it == 3); - - auto notFound = std::find(buf.begin(), buf.end(), 99); - REQUIRE(notFound == buf.end()); - } - - SECTION("std::count") { - buf.Push(3); // Overwrites the 1 - int count = std::count(buf.begin(), buf.end(), 3); - REQUIRE(count == 2); - } - - SECTION("std::copy") { - std::vector target(5); - std::copy(buf.begin(), buf.end(), target.begin()); - REQUIRE(target == std::vector{1, 2, 3, 4, 5}); - } + RingBuffer buf; + for (int i = 1; i <= 5; i++) { + buf.Push(i); + } + + SECTION("std::find") { + auto it = std::find(buf.begin(), buf.end(), 3); + REQUIRE(it != buf.end()); + REQUIRE(*it == 3); + + auto notFound = std::find(buf.begin(), buf.end(), 99); + REQUIRE(notFound == buf.end()); + } + + SECTION("std::count") { + buf.Push(3); // Overwrites the 1 + int count = std::count(buf.begin(), buf.end(), 3); + REQUIRE(count == 2); + } + + SECTION("std::copy") { + std::vector target(5); + std::copy(buf.begin(), buf.end(), target.begin()); + REQUIRE(target == std::vector{1, 2, 3, 4, 5}); + } } \ No newline at end of file