From d99ed9d70987e93b9fb7a7fcdaeecd9212c0dfce Mon Sep 17 00:00:00 2001 From: Vlada Kanivets Date: Mon, 11 Aug 2025 19:59:16 +0200 Subject: [PATCH 1/2] add tests for Guard --- test/CMakeLists.txt | 1 + test/GuardTest.cpp | 169 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 test/GuardTest.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0c2103b..23a698e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -44,6 +44,7 @@ wdk_add_driver(kf-test WINVER NTDDI_WIN10 STL HexTest.cpp MapTest.cpp Vector.cpp + GuardTest.cpp ) target_link_libraries(kf-test kf::kf kmtest::kmtest) diff --git a/test/GuardTest.cpp b/test/GuardTest.cpp new file mode 100644 index 0000000..eba1a4e --- /dev/null +++ b/test/GuardTest.cpp @@ -0,0 +1,169 @@ +#include "pch.h" +#include + +struct TestResource +{ + int m_value = 0; +}; + +static int g_closeCallCount = 0; +static TestResource* g_lastClosedResource = nullptr; + +void closeFn(TestResource* res) +{ + ++g_closeCallCount; + g_lastClosedResource = res; +} + +SCENARIO("Testing kf::Guard::Guard basic functionality") +{ + using TestGuard = kf::Guard::Guard< TestResource*, nullptr, decltype(&closeFn), &closeFn>; + + GIVEN("A default constructed Guard") + { + TestGuard guard; + g_closeCallCount = 0; + g_lastClosedResource = nullptr; + + THEN("Its value is nullptr and close function is not called on destruction") + { + REQUIRE(static_cast(guard) == nullptr); + REQUIRE(g_closeCallCount == 0); + } + + WHEN("reset is called with nullptr explicitly") + { + guard.reset(nullptr); + THEN("Close function is not called") + { + REQUIRE(g_closeCallCount == 0); + REQUIRE(guard.get() == nullptr); + } + } + } + + GIVEN("A Guard constructed with a valid resource pointer") + { + TestResource resource(123); + TestGuard guard(&resource); + g_closeCallCount = 0; + g_lastClosedResource = nullptr; + + THEN("Value is stored correctly") + { + REQUIRE(guard.get() == &resource); + } + + WHEN("Guard is reset with no arguments") + { + guard.reset(); + + THEN("Close function is called once with the resource") + { + REQUIRE(g_closeCallCount == 1); + REQUIRE(g_lastClosedResource == &resource); + REQUIRE(guard.get() == nullptr); + } + } + } + + GIVEN("A Guard constructed with a valid resource pointer") + { + TestResource resource(123); + TestGuard guard(&resource); + g_closeCallCount = 0; + g_lastClosedResource = nullptr; + + WHEN("Guard is released") + { + TestResource* released = guard.release(); + + THEN("Released value is the resource pointer") + { + REQUIRE(released == &resource); + } + + THEN("Guard now holds nullptr") + { + REQUIRE(guard.get() == nullptr); + } + + THEN("Close function was not called on release") + { + REQUIRE(g_closeCallCount == 0); + } + } + } + + GIVEN("A Guard constructed with a valid resource pointer") + { + TestResource resource(123); + TestGuard guard(&resource); + g_closeCallCount = 0; + g_lastClosedResource = nullptr; + + WHEN("Guard is move-constructed from another Guard") + { + TestGuard otherGuard(std::move(guard)); + + THEN("The second Guard owns the resource") + { + REQUIRE(otherGuard.get() == &resource); + } + + THEN("The original guard holds nullptr and no closeFn was called for the resource") + { + REQUIRE(g_closeCallCount == 0); + REQUIRE(guard.get() == nullptr); + } + } + } + + GIVEN("A Guard constructed with a valid resource pointer") + { + TestResource resource(123); + TestGuard guard(&resource); + g_closeCallCount = 0; + g_lastClosedResource = nullptr; + + WHEN("Guard is move-assigned from another Guard") + { + TestResource otherResource{ 456 }; + TestGuard guard2(&otherResource); + + guard2 = std::move(guard); + + THEN("The second guard now owns the first resource") + { + REQUIRE(guard2.get() == &resource); + } + + THEN("The original guard holds nullptr and closeFn was called for other resource") + { + REQUIRE(g_lastClosedResource == &otherResource); + REQUIRE(g_closeCallCount == 1); + REQUIRE(guard.get() == nullptr); + } + } + } + + GIVEN("A Guard constructed with a valid resource pointer") + { + TestResource resource(123); + g_closeCallCount = 0; + g_lastClosedResource = nullptr; + + WHEN("Guard is destroyed") + { + { + TestGuard guard(&resource); + } + + THEN("Close function is called on destruction") + { + REQUIRE(g_closeCallCount == 1); + REQUIRE(g_lastClosedResource == &resource); + } + } + } +} From 71cd311b7d110ccfcc77806e53194068c99b1120 Mon Sep 17 00:00:00 2001 From: Vlada Kanivets Date: Tue, 12 Aug 2025 17:11:35 +0200 Subject: [PATCH 2/2] refactoring --- test/GuardTest.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/test/GuardTest.cpp b/test/GuardTest.cpp index eba1a4e..21ab990 100644 --- a/test/GuardTest.cpp +++ b/test/GuardTest.cpp @@ -44,7 +44,8 @@ SCENARIO("Testing kf::Guard::Guard basic functionality") GIVEN("A Guard constructed with a valid resource pointer") { - TestResource resource(123); + int value = 123; + TestResource resource(value); TestGuard guard(&resource); g_closeCallCount = 0; g_lastClosedResource = nullptr; @@ -52,6 +53,7 @@ SCENARIO("Testing kf::Guard::Guard basic functionality") THEN("Value is stored correctly") { REQUIRE(guard.get() == &resource); + REQUIRE(guard.get()->m_value == value); } WHEN("Guard is reset with no arguments") @@ -97,7 +99,8 @@ SCENARIO("Testing kf::Guard::Guard basic functionality") GIVEN("A Guard constructed with a valid resource pointer") { - TestResource resource(123); + int value = 123; + TestResource resource(value); TestGuard guard(&resource); g_closeCallCount = 0; g_lastClosedResource = nullptr; @@ -109,6 +112,7 @@ SCENARIO("Testing kf::Guard::Guard basic functionality") THEN("The second Guard owns the resource") { REQUIRE(otherGuard.get() == &resource); + REQUIRE(otherGuard.get()->m_value == value); } THEN("The original guard holds nullptr and no closeFn was called for the resource") @@ -121,14 +125,16 @@ SCENARIO("Testing kf::Guard::Guard basic functionality") GIVEN("A Guard constructed with a valid resource pointer") { - TestResource resource(123); + int value = 123; + TestResource resource(value); TestGuard guard(&resource); g_closeCallCount = 0; g_lastClosedResource = nullptr; WHEN("Guard is move-assigned from another Guard") { - TestResource otherResource{ 456 }; + int otherValue = 456; + TestResource otherResource(otherValue); TestGuard guard2(&otherResource); guard2 = std::move(guard); @@ -136,6 +142,7 @@ SCENARIO("Testing kf::Guard::Guard basic functionality") THEN("The second guard now owns the first resource") { REQUIRE(guard2.get() == &resource); + REQUIRE(guard2.get()->m_value == value); } THEN("The original guard holds nullptr and closeFn was called for other resource")