From 4ce413a1d7a6195a23fe6fcaf6a4b97ac39fef87 Mon Sep 17 00:00:00 2001 From: light7734 Date: Tue, 21 Oct 2025 15:37:33 +0330 Subject: [PATCH] wip --- modules/test/CMakeLists.txt | 2 +- modules/test/private/mock.test.cpp | 52 +++++++++++++++++ modules/test/public/mock.hpp | 94 ++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 modules/test/private/mock.test.cpp create mode 100644 modules/test/public/mock.hpp diff --git a/modules/test/CMakeLists.txt b/modules/test/CMakeLists.txt index 66e40dd..48ba4b4 100644 --- a/modules/test/CMakeLists.txt +++ b/modules/test/CMakeLists.txt @@ -4,4 +4,4 @@ add_library_module(fuzz_test test.cpp fuzz.cpp) target_link_libraries(test PUBLIC tbb logger) target_link_libraries(fuzz_test PUBLIC tbb logger) -add_test_module(test test.test.cpp) +add_test_module(test test.test.cpp mock.test.cpp) diff --git a/modules/test/private/mock.test.cpp b/modules/test/private/mock.test.cpp new file mode 100644 index 0000000..416650c --- /dev/null +++ b/modules/test/private/mock.test.cpp @@ -0,0 +1,52 @@ +#include +#include + +using namespace lt::test; +using namespace lt::test::mock; + +class ExpensiveClass +{ +private: +public: + virtual int expensive(std::string str, std::optional opt) + { + return 0; + } +}; + +class MockClass: public ExpensiveClass +{ +public: + int expensive(std::string str, std::optional opt) override + { + return expensive_mock(str, opt); + }; + + Mock)> expensive_mock {}; +}; + +class ExpensiveUser +{ +public: + ExpensiveUser(ExpensiveClass &dependency) + { + dependency.expensive("", 10); + } +}; + + +// problem #1: matcher functions should construct an invokable object to test against the indexed +// argument. + +Suite raii = "mock_raii"_suite = [] { + Case { "happy path won't throw" } = [] { + auto a = std::function {}; + auto expensive = MockClass {}; + auto side_effect = false; + expensive.expensive_mock.expect("test", std::nullopt) + .apply([&](auto str, auto opt) { side_effect = true; }) + .returns(69); + + auto user = ExpensiveUser { expensive }; + }; +}; diff --git a/modules/test/public/mock.hpp b/modules/test/public/mock.hpp new file mode 100644 index 0000000..fb3dab2 --- /dev/null +++ b/modules/test/public/mock.hpp @@ -0,0 +1,94 @@ +#pragma once + +namespace lt::test { + +template +class Mock; + +template +class Mock +{ +public: + auto at_least() -> Mock & + { + return *this; + } + + auto operator&&(Mock &mock) -> Mock & + { + return mock; + } + + auto operator()(Arg_Types... arguments) -> Return_Type + { + ++m_call_index; + + for (auto &side_effect : m_side_effects) + { + side_effect(std::forward(arguments)...); + } + + if (m_return_func) + { + return m_return_func(std::forward(arguments)...); + } + return m_return_value; + } + + /** With any arguments. */ + template + auto expect() -> Mock & + { + m_expected_counter = counter; + return *this; + } + + auto apply(std::function side_effect) -> Mock & + { + m_side_effects.emplace_back(std::move(side_effect)); + return *this; + } + + /** Returns a fixed value. */ + auto returns(Return_Type value) -> Mock & + { + m_return_value = value; + return *this; + } + + /** Returns a value based on input. */ + auto returns(std::function func) -> Mock & + { + m_return_func = std::move(func); + return *this; + } + +private: + Return_Type m_return_value {}; + + std::function m_return_func {}; + + std::vector> m_side_effects {}; + + uint32_t m_call_index = 0; + + std::vector, uint32_t>> m_expected_args; + + uint32_t m_expected_counter {}; +}; + +namespace mock::range { + +[[nodiscard]] auto is_empty() -> bool +{ + return false; +} + +}; // namespace mock::range + +[[nodiscard]] auto eq(auto rhs) -> bool +{ + return false; +} + +} // namespace lt::test