From 3caf5531250f185189c528489d3b871c21641229 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Wed, 23 Oct 2024 23:34:26 +0200 Subject: [PATCH 01/12] reorganize test code, add mocking --- polymorphism/test/CMakeLists.txt | 17 ++++++---- .../include/test_polymorphism/mocking.hpp | 33 +++++++++++++++++++ polymorphism/test/src/mocking.cpp | 7 ++++ polymorphism/test/{ => src}/test_consume.cpp | 26 +++++++++++++++ 4 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 polymorphism/test/include/test_polymorphism/mocking.hpp create mode 100644 polymorphism/test/src/mocking.cpp rename polymorphism/test/{ => src}/test_consume.cpp (61%) diff --git a/polymorphism/test/CMakeLists.txt b/polymorphism/test/CMakeLists.txt index d351f0c..8ae12fd 100644 --- a/polymorphism/test/CMakeLists.txt +++ b/polymorphism/test/CMakeLists.txt @@ -15,17 +15,22 @@ add_library(polymorphism_lib ) target_compile_features(polymorphism_lib PUBLIC cxx_std_23) -target_include_directories(polymorphism_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) -target_include_directories(polymorphism_lib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src) +target_include_directories(polymorphism_lib + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src) add_executable(test_consume - test_consume.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/test_consume.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/mocking.cpp ) target_compile_features(test_consume PUBLIC cxx_std_23) - -target_include_directories(test_consume PUBLIC ../include) -target_include_directories(test_consume PUBLIC "${ut_SOURCE_DIR}") +target_include_directories(test_consume + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/../include + "${ut_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/../src) target_link_libraries(test_consume PRIVATE polymorphism_lib) diff --git a/polymorphism/test/include/test_polymorphism/mocking.hpp b/polymorphism/test/include/test_polymorphism/mocking.hpp new file mode 100644 index 0000000..182aef5 --- /dev/null +++ b/polymorphism/test/include/test_polymorphism/mocking.hpp @@ -0,0 +1,33 @@ +#ifndef POYMORPHISM_MOCKING_HPP +#define POYMORPHISM_MOCKING_HPP + +#include +#include +#include + +namespace mocking { + +struct Mock { + std::list collectedSetArguments; + mutable std::size_t numberOfCallsToCoolFeature { 0 }; + + std::string coolFeature() const + { + ++numberOfCallsToCoolFeature; + + if (0 != collectedSetArguments.size()) { + return collectedSetArguments.back(); + } else { + return ""; + } + } + + void set(std::string s) + { + collectedSetArguments.emplace_back(std::move(s)); + } +}; + +} // namespace mocking + +#endif // POYMORPHISM_MOCKING_HPP \ No newline at end of file diff --git a/polymorphism/test/src/mocking.cpp b/polymorphism/test/src/mocking.cpp new file mode 100644 index 0000000..9089aeb --- /dev/null +++ b/polymorphism/test/src/mocking.cpp @@ -0,0 +1,7 @@ +#include +#include + +#include + +// explicit instantiation of consume() for Mock +template std::string modern::consume(mocking::Mock&); diff --git a/polymorphism/test/test_consume.cpp b/polymorphism/test/src/test_consume.cpp similarity index 61% rename from polymorphism/test/test_consume.cpp rename to polymorphism/test/src/test_consume.cpp index 1d7f51b..133eab6 100644 --- a/polymorphism/test/test_consume.cpp +++ b/polymorphism/test/src/test_consume.cpp @@ -5,6 +5,8 @@ #include #include +#include + int main() { using namespace boost::ut; @@ -37,6 +39,30 @@ int main() expect("The answer to all questions is 42"s == result); }; + then("the state of the argument should be modified as a side effect") = [=] { + expect("42"s == impl.coolFeature()); + }; + }; + }; + }; + + "[modern mock]"_test + = [] { + given("I have a an mock that adheres to a concept") = [] { + mocking::Mock impl; + expect(""s == impl.coolFeature()); + + when("I pass it to a function that expects an argument that fulfils the constraints") = [&] { + auto result = modern::consume(impl); + + then("set() should be called twice") = [=] { + expect(2 == impl.numberOfCallsToCoolFeature); + }; + + then("the answer to all questions should be given") = [=] { + expect("The answer to all questions is 42"s == result); + }; + then("the state of the argument should be modified as a side effect") = [=] { expect("42"s == impl.coolFeature()); }; From 97adcdcbf1f58002c48843488b7616c81bb71b20 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Wed, 23 Oct 2024 23:48:52 +0200 Subject: [PATCH 02/12] refine test --- polymorphism/test/src/test_consume.cpp | 39 +++++++++++++------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/polymorphism/test/src/test_consume.cpp b/polymorphism/test/src/test_consume.cpp index 133eab6..f835ff9 100644 --- a/polymorphism/test/src/test_consume.cpp +++ b/polymorphism/test/src/test_consume.cpp @@ -46,27 +46,28 @@ int main() }; }; - "[modern mock]"_test - = [] { - given("I have a an mock that adheres to a concept") = [] { - mocking::Mock impl; - expect(""s == impl.coolFeature()); + "[modern mock]"_test = [] { + static constexpr auto EXPECTED_COOLFEATURE_CALLS = 2; // Called once for initial value and once for modification + given("I have a an mock that adheres to a concept") = [] { + mocking::Mock impl; - when("I pass it to a function that expects an argument that fulfils the constraints") = [&] { - auto result = modern::consume(impl); + expect(""s == impl.coolFeature()); - then("set() should be called twice") = [=] { - expect(2 == impl.numberOfCallsToCoolFeature); - }; + when("I pass it to a function that expects an argument that fulfils the constraints") = [&] { + auto result = modern::consume(impl); - then("the answer to all questions should be given") = [=] { - expect("The answer to all questions is 42"s == result); - }; + then("set() should be called twice") = [=] { + expect(EXPECTED_COOLFEATURE_CALLS == impl.numberOfCallsToCoolFeature); + }; - then("the state of the argument should be modified as a side effect") = [=] { - expect("42"s == impl.coolFeature()); - }; - }; - }; - }; + then("the answer to all questions should be given") = [=] { + expect("The answer to all questions is 42"s == result); + }; + + then("the state of the argument should be modified as a side effect") = [=] { + expect("42"s == impl.coolFeature()); + }; + }; + }; + }; } From 98d23c6c424da308a8eb8fa40a5667dbf681fe17 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Wed, 23 Oct 2024 23:49:34 +0200 Subject: [PATCH 03/12] fix typo in polymorphism/test/include/test_polymorphism/mocking.hpp Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- polymorphism/test/include/test_polymorphism/mocking.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polymorphism/test/include/test_polymorphism/mocking.hpp b/polymorphism/test/include/test_polymorphism/mocking.hpp index 182aef5..f281248 100644 --- a/polymorphism/test/include/test_polymorphism/mocking.hpp +++ b/polymorphism/test/include/test_polymorphism/mocking.hpp @@ -1,5 +1,5 @@ -#ifndef POYMORPHISM_MOCKING_HPP -#define POYMORPHISM_MOCKING_HPP +#ifndef POLYMORPHISM_MOCKING_HPP +#define POLYMORPHISM_MOCKING_HPP #include #include From a66fd93024d98bdc53a5fad61bf3eb76c5788c29 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Wed, 23 Oct 2024 23:55:13 +0200 Subject: [PATCH 04/12] terse decision on return value --- .../test/include/test_polymorphism/mocking.hpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/polymorphism/test/include/test_polymorphism/mocking.hpp b/polymorphism/test/include/test_polymorphism/mocking.hpp index f281248..b112b86 100644 --- a/polymorphism/test/include/test_polymorphism/mocking.hpp +++ b/polymorphism/test/include/test_polymorphism/mocking.hpp @@ -15,11 +15,9 @@ struct Mock { { ++numberOfCallsToCoolFeature; - if (0 != collectedSetArguments.size()) { - return collectedSetArguments.back(); - } else { - return ""; - } + return collectedSetArguments.empty() + ? "" + : collectedSetArguments.back(); } void set(std::string s) @@ -30,4 +28,4 @@ struct Mock { } // namespace mocking -#endif // POYMORPHISM_MOCKING_HPP \ No newline at end of file +#endif // POLYMORPHISM_MOCKING_HPP \ No newline at end of file From 90f3cad53d55110c6a0e68f1e6a8e5f90f7d5d78 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Wed, 23 Oct 2024 23:58:04 +0200 Subject: [PATCH 05/12] add commenst and reorder include directories Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- polymorphism/test/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/polymorphism/test/CMakeLists.txt b/polymorphism/test/CMakeLists.txt index 8ae12fd..c725167 100644 --- a/polymorphism/test/CMakeLists.txt +++ b/polymorphism/test/CMakeLists.txt @@ -27,10 +27,12 @@ add_executable(test_consume target_compile_features(test_consume PUBLIC cxx_std_23) target_include_directories(test_consume PRIVATE + # Library includes ${CMAKE_CURRENT_SOURCE_DIR}/../include - "${ut_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR}/../src + # Test includes ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_SOURCE_DIR}/../src) + "${ut_SOURCE_DIR}") target_link_libraries(test_consume PRIVATE polymorphism_lib) From 55d18a27314cef2d4c575ec6973f797f02d1d44e Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Thu, 24 Oct 2024 00:07:04 +0200 Subject: [PATCH 06/12] make the counter update thread-safe --- polymorphism/test/include/test_polymorphism/mocking.hpp | 3 ++- polymorphism/test/src/test_consume.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/polymorphism/test/include/test_polymorphism/mocking.hpp b/polymorphism/test/include/test_polymorphism/mocking.hpp index b112b86..34293bb 100644 --- a/polymorphism/test/include/test_polymorphism/mocking.hpp +++ b/polymorphism/test/include/test_polymorphism/mocking.hpp @@ -1,6 +1,7 @@ #ifndef POLYMORPHISM_MOCKING_HPP #define POLYMORPHISM_MOCKING_HPP +#include #include #include #include @@ -9,7 +10,7 @@ namespace mocking { struct Mock { std::list collectedSetArguments; - mutable std::size_t numberOfCallsToCoolFeature { 0 }; + mutable std::atomic numberOfCallsToCoolFeature { 0 }; std::string coolFeature() const { diff --git a/polymorphism/test/src/test_consume.cpp b/polymorphism/test/src/test_consume.cpp index f835ff9..7548145 100644 --- a/polymorphism/test/src/test_consume.cpp +++ b/polymorphism/test/src/test_consume.cpp @@ -56,7 +56,7 @@ int main() when("I pass it to a function that expects an argument that fulfils the constraints") = [&] { auto result = modern::consume(impl); - then("set() should be called twice") = [=] { + then("set() should be called twice") = [&] { expect(EXPECTED_COOLFEATURE_CALLS == impl.numberOfCallsToCoolFeature); }; @@ -64,7 +64,7 @@ int main() expect("The answer to all questions is 42"s == result); }; - then("the state of the argument should be modified as a side effect") = [=] { + then("the state of the argument should be modified as a side effect") = [&] { expect("42"s == impl.coolFeature()); }; }; From 2db7dd8266947ebd7538e6e89af746fb6ed30fb0 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Thu, 24 Oct 2024 00:10:52 +0200 Subject: [PATCH 07/12] add docstrings and check empty string argument Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- polymorphism/test/include/test_polymorphism/mocking.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/polymorphism/test/include/test_polymorphism/mocking.hpp b/polymorphism/test/include/test_polymorphism/mocking.hpp index 34293bb..f26007e 100644 --- a/polymorphism/test/include/test_polymorphism/mocking.hpp +++ b/polymorphism/test/include/test_polymorphism/mocking.hpp @@ -21,8 +21,16 @@ struct Mock { : collectedSetArguments.back(); } + /** + * @brief Stores a string value for later retrieval by coolFeature + * @param s The string to store (must not be empty) + * @throws std::invalid_argument if the string is empty + */ void set(std::string s) { + if (s.empty()) { + throw std::invalid_argument("Empty strings are not allowed"); + } collectedSetArguments.emplace_back(std::move(s)); } }; From 21aa9e0c70424da7c91b350c8537c0456aaf0ab0 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Thu, 24 Oct 2024 00:11:34 +0200 Subject: [PATCH 08/12] simplify source code paths Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- polymorphism/test/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polymorphism/test/CMakeLists.txt b/polymorphism/test/CMakeLists.txt index c725167..c40aef7 100644 --- a/polymorphism/test/CMakeLists.txt +++ b/polymorphism/test/CMakeLists.txt @@ -20,8 +20,8 @@ target_include_directories(polymorphism_lib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src) add_executable(test_consume - ${CMAKE_CURRENT_SOURCE_DIR}/src/test_consume.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/mocking.cpp + src/test_consume.cpp + src/mocking.cpp ) target_compile_features(test_consume PUBLIC cxx_std_23) From cd5ebf7ede02d2e1a17d92b628679b464f7c23a0 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Thu, 24 Oct 2024 00:12:25 +0200 Subject: [PATCH 09/12] refine comments on counter variable Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- polymorphism/test/src/test_consume.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/polymorphism/test/src/test_consume.cpp b/polymorphism/test/src/test_consume.cpp index 7548145..968b2bd 100644 --- a/polymorphism/test/src/test_consume.cpp +++ b/polymorphism/test/src/test_consume.cpp @@ -47,7 +47,9 @@ int main() }; "[modern mock]"_test = [] { - static constexpr auto EXPECTED_COOLFEATURE_CALLS = 2; // Called once for initial value and once for modification + static constexpr auto EXPECTED_COOLFEATURE_CALLS = 2; // coolFeature() is called: + // 1. During initial value check (line 54) + // 2. During side effect verification (line 68) given("I have a an mock that adheres to a concept") = [] { mocking::Mock impl; From f85e5b5c38ead1ab9664b8b7e41199f12720a8b1 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Thu, 24 Oct 2024 00:13:56 +0200 Subject: [PATCH 10/12] add comments to method Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- polymorphism/test/include/test_polymorphism/mocking.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/polymorphism/test/include/test_polymorphism/mocking.hpp b/polymorphism/test/include/test_polymorphism/mocking.hpp index f26007e..d93f1f7 100644 --- a/polymorphism/test/include/test_polymorphism/mocking.hpp +++ b/polymorphism/test/include/test_polymorphism/mocking.hpp @@ -12,6 +12,11 @@ struct Mock { std::list collectedSetArguments; mutable std::atomic numberOfCallsToCoolFeature { 0 }; + /** + * @brief Returns the last set value or a default value if none exists. + * @note Thread-safe. Multiple concurrent calls are safe. + * @return The last set string or "" if no strings were set + */ std::string coolFeature() const { ++numberOfCallsToCoolFeature; From a3e08188d8449155df5c9f697b20526f581e1dd2 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Thu, 24 Oct 2024 00:17:05 +0200 Subject: [PATCH 11/12] align comments --- polymorphism/test/src/test_consume.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polymorphism/test/src/test_consume.cpp b/polymorphism/test/src/test_consume.cpp index 968b2bd..29ad7b7 100644 --- a/polymorphism/test/src/test_consume.cpp +++ b/polymorphism/test/src/test_consume.cpp @@ -48,8 +48,8 @@ int main() "[modern mock]"_test = [] { static constexpr auto EXPECTED_COOLFEATURE_CALLS = 2; // coolFeature() is called: - // 1. During initial value check (line 54) - // 2. During side effect verification (line 68) + // 1. During initial value check (line 56) + // 2. During side effect verification (line 70) given("I have a an mock that adheres to a concept") = [] { mocking::Mock impl; From 944493b0a586dc5dcda39020fe0566af59d90a68 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Sun, 27 Oct 2024 08:12:18 +0100 Subject: [PATCH 12/12] fix typo in include guard --- .../polymorphism/consume_class_that_adheres_to_concept.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/polymorphism/include/polymorphism/consume_class_that_adheres_to_concept.hpp b/polymorphism/include/polymorphism/consume_class_that_adheres_to_concept.hpp index 4a7f695..fe09c36 100644 --- a/polymorphism/include/polymorphism/consume_class_that_adheres_to_concept.hpp +++ b/polymorphism/include/polymorphism/consume_class_that_adheres_to_concept.hpp @@ -1,5 +1,5 @@ -#ifndef POYMORPHISM_CONSUME_CLASS_THAT_ADHERES_TO_CONCEPT_HPP -#define POYMORPHISM_CONSUME_CLASS_THAT_ADHERES_TO_CONCEPT_HPP +#ifndef POLYMORPHISM_CONSUME_CLASS_THAT_ADHERES_TO_CONCEPT_HPP +#define POLYMORPHISM_CONSUME_CLASS_THAT_ADHERES_TO_CONCEPT_HPP #include @@ -12,4 +12,4 @@ std::string consume(has_super_cool_features auto& s); } // namespace modern -#endif // POYMORPHISM_CONSUME_CLASS_THAT_ADHERES_TO_CONCEPT_HPP \ No newline at end of file +#endif // POLYMORPHISM_CONSUME_CLASS_THAT_ADHERES_TO_CONCEPT_HPP \ No newline at end of file