From ae43f2bd724f18ffcf726e1b334ee383fe56ac55 Mon Sep 17 00:00:00 2001 From: dnkpp Date: Mon, 17 Mar 2025 16:59:45 +0100 Subject: [PATCH 1/8] feat: matchers describe function just needs to return something explicitly-convertible to std::optional --- include/mimic++/matchers/Common.hpp | 18 ++++++----- test/unit-tests/matchers/Common.cpp | 47 +++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/include/mimic++/matchers/Common.hpp b/include/mimic++/matchers/Common.hpp index 14cdea925..321b5290c 100644 --- a/include/mimic++/matchers/Common.hpp +++ b/include/mimic++/matchers/Common.hpp @@ -9,9 +9,11 @@ #pragma once #include "mimic++/Fwd.hpp" +#include "mimic++/utilities/Concepts.hpp" #include "mimic++/utilities/PriorityTag.hpp" #include +#include #include namespace mimicpp::custom @@ -32,7 +34,7 @@ namespace mimicpp::detail::matches_hook requires requires { { custom::matcher_traits{}.matches(matcher, target, others...) - } -> std::convertible_to; + } -> util::boolean_testable; } { return custom::matcher_traits{}.matches(matcher, target, others...); @@ -45,7 +47,7 @@ namespace mimicpp::detail::matches_hook Matcher const& matcher, T& target, Others&... others) - requires requires { { matcher.matches(target, others...) } -> std::convertible_to; } + requires requires { { matcher.matches(target, others...) } -> util::boolean_testable; } { return matcher.matches(target, others...); } @@ -59,7 +61,7 @@ namespace mimicpp::detail::matches_hook requires requires { { matches_impl(maxTag, matcher, target, others...) - }-> std::convertible_to; } + } -> util::boolean_testable; } { return matches_impl(maxTag, matcher, target, others...); }; @@ -75,7 +77,7 @@ namespace mimicpp::detail::describe_hook requires requires { { custom::matcher_traits{}.describe(matcher) - } -> std::convertible_to; + } -> util::explicitly_convertible_to>; } { return custom::matcher_traits{}.describe(matcher); @@ -86,7 +88,7 @@ namespace mimicpp::detail::describe_hook constexpr decltype(auto) describe_impl( [[maybe_unused]] util::priority_tag<0> const, Matcher const& matcher) - requires requires { { matcher.describe() } -> std::convertible_to; } + requires requires { { matcher.describe() } -> util::explicitly_convertible_to>; } { return matcher.describe(); } @@ -94,7 +96,7 @@ namespace mimicpp::detail::describe_hook constexpr util::priority_tag<1> maxTag{}; constexpr auto describe = [](Matcher const& matcher) -> decltype(auto) - requires requires { { describe_impl(maxTag, matcher) } -> std::convertible_to; } + requires requires { { describe_impl(maxTag, matcher) } -> util::explicitly_convertible_to>; } { return describe_impl(maxTag, matcher); }; @@ -107,8 +109,8 @@ namespace mimicpp && std::is_move_constructible_v && std::destructible && requires(T const& matcher, First& first, Others&... others) { - { detail::matches_hook::matches(matcher, first, others...) } -> std::convertible_to; - { detail::describe_hook::describe(matcher) } -> std::convertible_to; + { detail::matches_hook::matches(matcher, first, others...) } -> util::boolean_testable; + { detail::describe_hook::describe(matcher) } -> util::explicitly_convertible_to>; }; } diff --git a/test/unit-tests/matchers/Common.cpp b/test/unit-tests/matchers/Common.cpp index 3d04c679f..bb4109753 100644 --- a/test/unit-tests/matchers/Common.cpp +++ b/test/unit-tests/matchers/Common.cpp @@ -48,6 +48,12 @@ namespace MAKE_CONST_MOCK0(my_describe, StringViewT()); }; + + class CommonNullDescribeMatcher + { + MAKE_CONST_MOCK1(matches, bool(const int&)); + MAKE_CONST_MOCK0(describe, std::nullopt_t()); + }; } template <> @@ -238,8 +244,9 @@ TEST_CASE( REQUIRE_CALL(matcher, describe()) .RETURN(result); + auto const description = detail::describe_hook::describe(matcher); REQUIRE_THAT( - StringT{detail::describe_hook::describe(matcher)}, + StringT{description}, Matches::Equals(StringT{result})); } @@ -249,8 +256,9 @@ TEST_CASE( REQUIRE_CALL(matcher, describe()) .RETURN(result); + auto const description = detail::describe_hook::describe(matcher); REQUIRE_THAT( - StringT{detail::describe_hook::describe(matcher)}, + StringT{description}, Matches::Equals(StringT{result})); } } @@ -263,8 +271,9 @@ TEST_CASE( REQUIRE_CALL(matcher, my_describe()) .RETURN(result); + auto const description = detail::describe_hook::describe(matcher); REQUIRE_THAT( - StringT{detail::describe_hook::describe(matcher)}, + StringT{description}, Matches::Equals(StringT{result})); } @@ -274,25 +283,37 @@ TEST_CASE( REQUIRE_CALL(matcher, my_describe()) .RETURN(result); + auto const description = detail::describe_hook::describe(matcher); REQUIRE_THAT( - StringT{detail::describe_hook::describe(matcher)}, + StringT{description}, Matches::Equals(StringT{result})); } } + + SECTION("When matcher doesn't have a description.") + { + CommonNullDescribeMatcher matcher{}; + REQUIRE_CALL(matcher, describe()) + .RETURN(std::nullopt); + + auto const description = detail::describe_hook::describe(matcher); + REQUIRE(std::optional{} == description); + } } TEMPLATE_TEST_CASE_SIG( "Given types satisfy mimicpp::matcher_for concept.", "[matcher]", - ((bool dummy, typename Matcher, typename First, typename... Others), dummy, Matcher, First, Others...), - (true, CommonMatcher, int), - (true, CustomMatcher, int), - (true, Mixed1Matcher, int), - (true, Mixed2Matcher, int), - (true, CommonVariadicMatcher, int, double), - (true, CommonVariadicMatcher, int, double, std::string), - (true, CustomVariadicMatcher, int, double), - (true, CustomVariadicMatcher, int, double, std::string)) + ((auto dummy, typename Matcher, typename First, typename... Others), dummy, Matcher, First, Others...), + (std::ignore, CommonMatcher, int), + (std::ignore, CustomMatcher, int), + (std::ignore, Mixed1Matcher, int), + (std::ignore, Mixed2Matcher, int), + (std::ignore, CommonNullDescribeMatcher, int), + (std::ignore, CommonVariadicMatcher, int, double), + (std::ignore, CommonVariadicMatcher, int, double, std::string), + (std::ignore, CustomVariadicMatcher, int, double), + (std::ignore, CustomVariadicMatcher, int, double, std::string)) { STATIC_REQUIRE(matcher_for); STATIC_REQUIRE(matcher_for); From 39d9f4414bd6e30862d86d1e3b6af66bf3143aeb Mon Sep 17 00:00:00 2001 From: dnkpp Date: Mon, 17 Mar 2025 17:00:20 +0100 Subject: [PATCH 2/8] feat: argument-policies support null-description matchers --- include/mimic++/Expectation.hpp | 7 ++- .../policies/ArgRequirementPolicies.hpp | 35 +++++++---- test/unit-tests/Expectation.cpp | 48 ++++++++++++++ .../policies/ArgRequirementPolicies.cpp | 62 +++++++++++++++++-- 4 files changed, 134 insertions(+), 18 deletions(-) diff --git a/include/mimic++/Expectation.hpp b/include/mimic++/Expectation.hpp index 38d1d5981..dcfc912e4 100644 --- a/include/mimic++/Expectation.hpp +++ b/include/mimic++/Expectation.hpp @@ -17,6 +17,7 @@ #include "mimic++/reporting/ExpectationReport.hpp" #include "mimic++/reporting/GlobalReporter.hpp" #include "mimic++/reporting/TargetReport.hpp" +#include "mimic++/utilities/Concepts.hpp" #include "mimic++/utilities/SourceLocation.hpp" #include @@ -428,8 +429,8 @@ namespace mimicpp && std::is_destructible_v && std::same_as> && requires(T& policy, const call::info_for_signature_t& info) { - { std::as_const(policy).is_satisfied() } noexcept -> std::convertible_to; - { std::as_const(policy).matches(info) } -> std::convertible_to; + { std::as_const(policy).is_satisfied() } noexcept -> util::boolean_testable; + { std::as_const(policy).matches(info) } -> util::boolean_testable; { std::as_const(policy).describe() } -> std::convertible_to>; { policy.consume(info) }; }; @@ -453,7 +454,7 @@ namespace mimicpp && std::is_destructible_v && std::same_as> && requires(T& policy) { - { std::as_const(policy).is_satisfied() } noexcept -> std::convertible_to; + { std::as_const(policy).is_satisfied() } noexcept -> util::boolean_testable; { std::as_const(policy).state() } -> std::convertible_to; policy.consume(); }; diff --git a/include/mimic++/policies/ArgRequirementPolicies.hpp b/include/mimic++/policies/ArgRequirementPolicies.hpp index 7458e4641..f25c99656 100644 --- a/include/mimic++/policies/ArgRequirementPolicies.hpp +++ b/include/mimic++/policies/ArgRequirementPolicies.hpp @@ -10,6 +10,7 @@ #include "mimic++/matchers/Common.hpp" #include "mimic++/policies/ArgumentList.hpp" +#include "mimic++/utilities/Concepts.hpp" #include "mimic++/utilities/TypeList.hpp" #include @@ -25,7 +26,7 @@ namespace mimicpp::expectation_policies struct matcher_matches_fn { public: - const Matcher& matcher; + Matcher const& matcher; template requires std::invocable< @@ -39,7 +40,7 @@ namespace mimicpp::expectation_policies noexcept( std::is_nothrow_invocable_v< decltype(detail::matches_hook::matches), - const Matcher&, + Matcher const&, Args&...>) { return detail::matches_hook::matches(matcher, args...); @@ -72,10 +73,10 @@ namespace mimicpp::expectation_policies } template - requires std::is_invocable_r_v, const call::Info&> + requires std::is_invocable_r_v, call::Info const&> [[nodiscard]] constexpr bool matches(const call::Info& info) const - noexcept(std::is_nothrow_invocable_v, const call::Info&>) + noexcept(std::is_nothrow_invocable_v, call::Info const&>) { return std::invoke( m_MatchesStrategy, @@ -84,16 +85,28 @@ namespace mimicpp::expectation_policies } template - static constexpr void consume([[maybe_unused]] const call::Info& info) noexcept + static constexpr void consume([[maybe_unused]] call::Info const& info) noexcept { } [[nodiscard]] - StringT describe() const + std::optional describe() const { - return std::invoke( - m_DescribeStrategy, - detail::describe_hook::describe(m_Matcher)); + [[maybe_unused]] auto const description = detail::describe_hook::describe(m_Matcher); + + if constexpr (util::boolean_testable) + { + if (description) + { + return std::invoke(m_DescribeStrategy, *description); + } + } + else if constexpr (std::convertible_to) + { + return std::invoke(m_DescribeStrategy, description); + } + + return std::nullopt; } private: @@ -111,7 +124,7 @@ namespace mimicpp::expect struct arg_requirement_describer { [[nodiscard]] - StringT operator()(const StringViewT matcherDescription) const + StringT operator()(StringViewT const matcherDescription) const { StringStreamT out{}; out << "expect: arg[" << index; @@ -124,7 +137,7 @@ namespace mimicpp::expect struct all_args_requirement_describer { [[nodiscard]] - StringT operator()(const StringViewT matcherDescription) const + StringT operator()(StringViewT const matcherDescription) const { StringStreamT out{}; out << "expect: arg[all] " << matcherDescription; diff --git a/test/unit-tests/Expectation.cpp b/test/unit-tests/Expectation.cpp index 99329122c..e8d5e653b 100644 --- a/test/unit-tests/Expectation.cpp +++ b/test/unit-tests/Expectation.cpp @@ -825,6 +825,54 @@ TEST_CASE( *report.requirementDescriptions.front(), Matches::Equals("expectation description")); } + + SECTION("Expectation policies without a description are supported.") + { + struct Policy + { + [[nodiscard]] + static constexpr bool is_satisfied() noexcept + { + return true; + } + + [[nodiscard]] + static constexpr bool matches([[maybe_unused]] call::info_for_signature_t const& call) noexcept + { + return true; + } + + [[nodiscard]] + static constexpr std::nullopt_t describe() noexcept + { + return std::nullopt; + } + + static constexpr void consume([[maybe_unused]] call::info_for_signature_t const& call) noexcept + { + } + }; + + static_assert(expectation_policy_for); + + BasicExpectation< + void(), + ControlPolicyFake, + FinalizerPolicyT, + Policy> + expectation{ + {}, + make_common_target_report(), + ControlPolicyFake{}, + FinalizerPolicyT{}, + Policy{}}; + + reporting::ExpectationReport const report = expectation.report(); + REQUIRE_THAT( + report.requirementDescriptions, + Matches::SizeIs(1)); + REQUIRE_FALSE(report.requirementDescriptions.front()); + } } TEMPLATE_TEST_CASE( diff --git a/test/unit-tests/policies/ArgRequirementPolicies.cpp b/test/unit-tests/policies/ArgRequirementPolicies.cpp index a176242aa..4d6d5e1b7 100644 --- a/test/unit-tests/policies/ArgRequirementPolicies.cpp +++ b/test/unit-tests/policies/ArgRequirementPolicies.cpp @@ -24,8 +24,9 @@ TEST_CASE( SECTION("When single index is given.") { constexpr expect::detail::arg_requirement_describer<42> describer{}; + auto const description = describer(matcherDescription); REQUIRE_THAT( - describer(matcherDescription), + description, Catch::Matchers::Equals("expect: arg[42] " + matcherDescription)); } @@ -105,8 +106,10 @@ TEST_CASE( REQUIRE_CALL(describeStrategy, Invoke("matcher description")) .RETURN("expect that: matcher description"); + auto const description = policy.describe(); + REQUIRE(description); REQUIRE_THAT( - policy.describe(), + *description, Catch::Matchers::Equals("expect that: matcher description")); } @@ -124,6 +127,53 @@ TEST_CASE( } } +TEST_CASE( + "expectation_policies::ArgsRequirement supports matchers without description.", + "[expectation][expectation::policy]") +{ + using SignatureT = void(int); + using CallInfoT = call::info_for_signature_t; + int arg0{42}; + const CallInfoT info{ + .args = {arg0}, + .fromCategory = GENERATE(from_range(refQualifiers)), + .fromConstness = GENERATE(from_range(constQualifiers))}; + + using DescriberStrategyT = InvocableMock; + + struct Matcher + { + [[nodiscard]] + static constexpr bool matches([[maybe_unused]] int& arg) noexcept + { + return true; + } + + [[nodiscard]] + static constexpr std::nullopt_t describe() noexcept + { + return std::nullopt; + } + }; + + STATIC_CHECK(matcher_for); + + using MatchesStrategyT = InvocableMock< + bool, + expectation_policies::matcher_matches_fn, + const CallInfoT&>; + + MatchesStrategyT matchesStrategy{}; + DescriberStrategyT describeStrategy{}; + expectation_policies::ArgsRequirement policy{ + Matcher{}, + std::ref(matchesStrategy), + std::ref(describeStrategy)}; + + auto const description = policy.describe(); + REQUIRE_FALSE(description); +} + namespace { // using mimic++ mock here, because not possible with trompeloeil @@ -212,8 +262,10 @@ TEST_CASE( REQUIRE_CALL(matcher, describe()) .RETURN("matcher description"); + auto const description = policy.describe(); + REQUIRE(description); REQUIRE_THAT( - policy.describe(), + *description, Catch::Matchers::Equals("expect: arg[0] matcher description")); } @@ -304,8 +356,10 @@ TEST_CASE( SCOPED_EXP std::as_const(matcher).describe.expect_call() and finally::returns("matcher description"); + auto const description = policy.describe(); + REQUIRE(description); REQUIRE_THAT( - policy.describe(), + *description, Catch::Matchers::Equals("expect: arg[all] matcher description")); } From 3798209ee7f0dd7a6b3cf79586d72cc98567432a Mon Sep 17 00:00:00 2001 From: dnkpp Date: Mon, 17 Mar 2025 17:14:21 +0100 Subject: [PATCH 3/8] chore: WildcardMatcher doesn't provide a description --- include/mimic++/matchers/GeneralMatchers.hpp | 8 +++++--- test/unit-tests/matchers/GeneralMatchers.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/mimic++/matchers/GeneralMatchers.hpp b/include/mimic++/matchers/GeneralMatchers.hpp index 211fdfe1a..e7ddf1e68 100644 --- a/include/mimic++/matchers/GeneralMatchers.hpp +++ b/include/mimic++/matchers/GeneralMatchers.hpp @@ -189,14 +189,16 @@ namespace mimicpp class WildcardMatcher { public: - static constexpr bool matches([[maybe_unused]] auto&& target) noexcept + [[nodiscard]] + static consteval bool matches([[maybe_unused]] auto&& target) noexcept { return true; } - static constexpr StringViewT describe() noexcept + [[nodiscard]] + static consteval std::nullopt_t describe() noexcept { - return "has no constraints"; + return std::nullopt; } }; } diff --git a/test/unit-tests/matchers/GeneralMatchers.cpp b/test/unit-tests/matchers/GeneralMatchers.cpp index d30f97b7d..bf006413e 100644 --- a/test/unit-tests/matchers/GeneralMatchers.cpp +++ b/test/unit-tests/matchers/GeneralMatchers.cpp @@ -192,13 +192,13 @@ TEST_CASE( using AnyT = std::remove_cvref_t; STATIC_REQUIRE(matcher_for); - STATIC_REQUIRE(matcher_for); + STATIC_REQUIRE(matcher_for); constexpr int value{42}; REQUIRE(matches::_.matches(value)); - REQUIRE_THAT( - StringT{matches::_.describe()}, - Matches::Equals("has no constraints")); + + std::optional const description = matches::_.describe(); + REQUIRE_FALSE(description); } TEST_CASE( From ff76b0e461be55d16b5f1e55f168963951a7f85e Mon Sep 17 00:00:00 2001 From: dnkpp Date: Mon, 17 Mar 2025 17:49:39 +0100 Subject: [PATCH 4/8] chore: expectation_policy_for requires result of policy.describe to be explicitly-convertible to optional --- include/mimic++/Expectation.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mimic++/Expectation.hpp b/include/mimic++/Expectation.hpp index dcfc912e4..b7a961046 100644 --- a/include/mimic++/Expectation.hpp +++ b/include/mimic++/Expectation.hpp @@ -431,7 +431,7 @@ namespace mimicpp && requires(T& policy, const call::info_for_signature_t& info) { { std::as_const(policy).is_satisfied() } noexcept -> util::boolean_testable; { std::as_const(policy).matches(info) } -> util::boolean_testable; - { std::as_const(policy).describe() } -> std::convertible_to>; + { std::as_const(policy).describe() } -> util::explicitly_convertible_to>; { policy.consume(info) }; }; @@ -528,7 +528,7 @@ namespace mimicpp .requirementDescriptions = std::apply( [&](auto const&... policies) { return std::vector>{ - policies.describe()...}; + std::optional{policies.describe()}...}; }, m_Policies)}; } From 588ee973122b2ffc36d8039586a3d49a5bfa0ba9 Mon Sep 17 00:00:00 2001 From: dnkpp Date: Mon, 17 Mar 2025 17:53:47 +0100 Subject: [PATCH 5/8] chore: expectation_policies::Category only provides a description, when applied category is not any. --- include/mimic++/policies/GeneralPolicies.hpp | 24 ++++++++++++++------ test/unit-tests/policies/GeneralPolicies.cpp | 15 +++++++++--- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/include/mimic++/policies/GeneralPolicies.hpp b/include/mimic++/policies/GeneralPolicies.hpp index 03225474e..12e2c80c8 100644 --- a/include/mimic++/policies/GeneralPolicies.hpp +++ b/include/mimic++/policies/GeneralPolicies.hpp @@ -11,6 +11,7 @@ #include "mimic++/Fwd.hpp" #include "mimic++/config/Config.hpp" #include "mimic++/printing/StatePrinter.hpp" +#include "mimic++/utilities/C++23Backports.hpp" #include @@ -44,12 +45,14 @@ namespace mimicpp::expectation_policies class Category { public: + [[nodiscard]] static constexpr bool is_satisfied() noexcept { return true; } template + [[nodiscard]] static constexpr bool matches(const call::Info& info) noexcept { return mimicpp::detail::is_matching(info.fromCategory, expected); @@ -62,14 +65,21 @@ namespace mimicpp::expectation_policies } [[nodiscard]] - static StringT describe() + static auto describe() { - StringStreamT stream{}; - stream << "expect: from "; - mimicpp::print(std::ostreambuf_iterator{stream}, expected); - stream << " category overload"; - - return std::move(stream).str(); + if constexpr (ValueCategory::any != expected) + { + StringStreamT stream{}; + stream << "expect: from "; + mimicpp::print(std::ostreambuf_iterator{stream}, expected); + stream << " category overload"; + + return std::move(stream).str(); + } + else + { + return std::nullopt; + } } }; diff --git a/test/unit-tests/policies/GeneralPolicies.cpp b/test/unit-tests/policies/GeneralPolicies.cpp index afa4506fa..cdd974bd7 100644 --- a/test/unit-tests/policies/GeneralPolicies.cpp +++ b/test/unit-tests/policies/GeneralPolicies.cpp @@ -68,9 +68,18 @@ TEMPLATE_TEST_CASE_SIG( SECTION("Policy description.") { - REQUIRE_THAT( - policy.describe(), - Catch::Matchers::Equals(StringT{"expect: from "} + print(category) + " category overload")); + std::optional const description = policy.describe(); + if constexpr (ValueCategory::any == category) + { + REQUIRE_FALSE(description); + } + else + { + REQUIRE(description); + REQUIRE_THAT( + *description, + Catch::Matchers::Equals(StringT{"expect: from "} + print(category) + " category overload")); + } } const CallInfoT call{ From 141dbe39951e7f4c22de2aaf87d8ebf68aaceb39 Mon Sep 17 00:00:00 2001 From: dnkpp Date: Mon, 17 Mar 2025 17:58:17 +0100 Subject: [PATCH 6/8] chore: expectation_policies::Constness only provides a description, when applied qualification is not any. --- include/mimic++/policies/GeneralPolicies.hpp | 21 ++++++++++++++------ test/unit-tests/policies/GeneralPolicies.cpp | 15 +++++++++++--- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/include/mimic++/policies/GeneralPolicies.hpp b/include/mimic++/policies/GeneralPolicies.hpp index 12e2c80c8..42ec54fde 100644 --- a/include/mimic++/policies/GeneralPolicies.hpp +++ b/include/mimic++/policies/GeneralPolicies.hpp @@ -87,12 +87,14 @@ namespace mimicpp::expectation_policies class Constness { public: + [[nodiscard]] static constexpr bool is_satisfied() noexcept { return true; } template + [[nodiscard]] static constexpr bool matches(const call::Info& info) noexcept { return mimicpp::detail::is_matching(info.fromConstness, constness); @@ -105,14 +107,21 @@ namespace mimicpp::expectation_policies } [[nodiscard]] - static StringT describe() + static auto describe() { - StringStreamT stream{}; - stream << "expect: from "; - mimicpp::print(std::ostreambuf_iterator{stream}, constness); - stream << " qualified overload"; + if constexpr (mimicpp::Constness::any != constness) + { + StringStreamT stream{}; + stream << "expect: from "; + mimicpp::print(std::ostreambuf_iterator{stream}, constness); + stream << " qualified overload"; - return std::move(stream).str(); + return std::move(stream).str(); + } + else + { + return std::nullopt; + } } }; } diff --git a/test/unit-tests/policies/GeneralPolicies.cpp b/test/unit-tests/policies/GeneralPolicies.cpp index cdd974bd7..89334c77b 100644 --- a/test/unit-tests/policies/GeneralPolicies.cpp +++ b/test/unit-tests/policies/GeneralPolicies.cpp @@ -129,9 +129,18 @@ TEMPLATE_TEST_CASE_SIG( SECTION("Policy description.") { - REQUIRE_THAT( - policy.describe(), - Catch::Matchers::Equals(StringT{"expect: from "} + print(constness) + " qualified overload")); + std::optional const description = policy.describe(); + if constexpr (Constness::any == constness) + { + REQUIRE_FALSE(description); + } + else + { + REQUIRE(description); + REQUIRE_THAT( + *description, + Catch::Matchers::Equals(StringT{"expect: from "} + print(constness) + " qualified overload")); + } } const CallInfoT call{ From a90aace94083dcbed057e014995deaf4063fa86a Mon Sep 17 00:00:00 2001 From: dnkpp Date: Mon, 17 Mar 2025 18:27:54 +0100 Subject: [PATCH 7/8] fix: revert using constexpr instead of consteval in WildcardMatcher --- include/mimic++/matchers/GeneralMatchers.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mimic++/matchers/GeneralMatchers.hpp b/include/mimic++/matchers/GeneralMatchers.hpp index e7ddf1e68..b60a4d10a 100644 --- a/include/mimic++/matchers/GeneralMatchers.hpp +++ b/include/mimic++/matchers/GeneralMatchers.hpp @@ -190,13 +190,13 @@ namespace mimicpp { public: [[nodiscard]] - static consteval bool matches([[maybe_unused]] auto&& target) noexcept + static constexpr bool matches([[maybe_unused]] auto&& target) noexcept { return true; } [[nodiscard]] - static consteval std::nullopt_t describe() noexcept + static constexpr std::nullopt_t describe() noexcept { return std::nullopt; } From e0a6296f93b2a2458804d518a67c506e90f9d8bd Mon Sep 17 00:00:00 2001 From: Dominic Koepke Date: Mon, 17 Mar 2025 21:36:11 +0100 Subject: [PATCH 8/8] fix: please msvc --- include/mimic++/policies/ArgRequirementPolicies.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/mimic++/policies/ArgRequirementPolicies.hpp b/include/mimic++/policies/ArgRequirementPolicies.hpp index f25c99656..2c36e5b2e 100644 --- a/include/mimic++/policies/ArgRequirementPolicies.hpp +++ b/include/mimic++/policies/ArgRequirementPolicies.hpp @@ -100,13 +100,17 @@ namespace mimicpp::expectation_policies { return std::invoke(m_DescribeStrategy, *description); } + + return std::nullopt; } else if constexpr (std::convertible_to) { return std::invoke(m_DescribeStrategy, description); } - - return std::nullopt; + else + { + return std::nullopt; + } } private: