diff --git a/include/fakeit/Mock.hpp b/include/fakeit/Mock.hpp index 0fc1a009..e6ee738d 100644 --- a/include/fakeit/Mock.hpp +++ b/include/fakeit/Mock.hpp @@ -14,8 +14,23 @@ namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + // The goal of this specialization is to replace all kinds of void (e.g. "const void") by a common type, "void". + // This is because some other parts of the code have specialization for "void", but these specializations only + // handle "void", and not "const void", so instead of modifying all these specialization to handle both types, + // we replace "const void" by "void" here. + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -38,7 +53,7 @@ namespace fakeit { // std::shared_ptr getShared() { // return impl.getShared(); // } - + C &operator()() { return get(); } @@ -57,94 +72,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } - // const non void + // const template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); - } - - // volatile non void - template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); - } - - // const volatile non void - template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); - } - - // non void - template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); - } - - // ref non void - template::value&& std::is_base_of::value>::type> - MockingContext stub(R(T::* vMethod)(arglist...) &) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } - // const ref non void + // volatile template::value&& std::is_base_of::value>::type> - MockingContext stub(R(T::* vMethod)(arglist...) const&) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } - // rref non void + // const volatile template::value&& std::is_base_of::value>::type> - MockingContext stub(R(T::* vMethod)(arglist...) &&) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } - // const rref non void + // no qualifier template::value&& std::is_base_of::value>::type> - MockingContext stub(R(T::* vMethod)(arglist...) const&&) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + // ref template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::* vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + // const ref template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::* vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + // rref template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::* vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + // const rref template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::* vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -158,4 +146,4 @@ namespace fakeit { }; -} \ No newline at end of file +} diff --git a/tests/overloadded_methods_tests.cpp b/tests/overloadded_methods_tests.cpp index c7819f9b..d95ff627 100644 --- a/tests/overloadded_methods_tests.cpp +++ b/tests/overloadded_methods_tests.cpp @@ -43,7 +43,8 @@ struct OverloadedMethods : tpunit::TestFixture { TEST(OverloadedMethods::stub_overloaded_methods_with_templates), TEST(OverloadedMethods::stub_modern_overloaded_methods), TEST(OverloadedMethods::stub_modern_rref_overloaded_method), - TEST(OverloadedMethods::stub_modern_constrref_overloaded_method) + TEST(OverloadedMethods::stub_modern_constrref_overloaded_method), + TEST(OverloadedMethods::stub_modern_overloaded_proc) ) { } @@ -105,6 +106,11 @@ struct OverloadedMethods : tpunit::TestFixture { virtual int func(int) const& = 0; virtual int func(int) && = 0; virtual int func(int) const&& = 0; + + virtual void proc(int) & = 0; + virtual void proc(int) const& = 0; + virtual void proc(int) && = 0; + virtual void proc(int) const&& = 0; }; void stub_modern_overloaded_methods() { @@ -152,4 +158,33 @@ struct OverloadedMethods : tpunit::TestFixture { VerifyNoOtherInvocations(mock); } + void stub_modern_overloaded_proc() { + Mock mock; + int ret = 0; + + When(ConstRRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 4;}); + When(ConstRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 3;}); + When(RRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 2;}); + When(RefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 1;}); + + SomeModernCppInterface& refObj = mock.get(); + const SomeModernCppInterface& refConstObj = mock.get(); + + refObj.proc(0); + ASSERT_EQUAL(1, ret); + std::move(refObj).proc(0); + ASSERT_EQUAL(2, ret); + refConstObj.proc(0); + ASSERT_EQUAL(3, ret); + std::move(refConstObj).proc(0); + ASSERT_EQUAL(4, ret); + + Verify(RefOverloadedMethod(mock, proc, void(int))).Exactly(1); + Verify(RRefOverloadedMethod(mock, proc, void(int))).Exactly(1); + Verify(ConstRefOverloadedMethod(mock, proc, void(int))).Exactly(1); + Verify(ConstRRefOverloadedMethod(mock, proc, void(int))).Exactly(1); + + VerifyNoOtherInvocations(mock); + } + } __OverloadedMethods;