Skip to content

Commit

Permalink
De-duplicated some code related to stubbing void / non-void methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
FranckRJ committed Apr 16, 2023
1 parent 059cf8b commit 435de0f
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 63 deletions.
112 changes: 50 additions & 62 deletions include/fakeit/Mock.hpp
Expand Up @@ -14,8 +14,23 @@

namespace fakeit {
namespace internal {
template<typename T, typename = void>
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<typename T>
struct WithCommonVoid<T, typename std::enable_if<std::is_void<T>::value, void>::type> {
using type = void;
};

template<typename T>
using WithCommonVoid_t = typename WithCommonVoid<T>::type;
}
using namespace fakeit::internal;

template<typename C, typename ... baseclasses>
class Mock : public ActualInvocationsSource {
Expand All @@ -38,7 +53,7 @@ namespace fakeit {
// std::shared_ptr<C> getShared() {
// return impl.getShared();
// }

C &operator()() {
return get();
}
Expand All @@ -57,94 +72,67 @@ namespace fakeit {
return impl.stubDataMember(member, ctorargs...);
}

// const non void
// const
template<int id, typename R, typename T, typename ... arglist, class = typename std::enable_if<
!std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R (T::*vMethod)(arglist...) const) {
auto methodWithoutConstVolatile = reinterpret_cast<R (T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// volatile non void
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
!std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R(T::*vMethod)(arglist...) volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<R(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// const volatile non void
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
!std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<R(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// non void
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
!std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R(T::*vMethod)(arglist...)) {
return impl.template stubMethod<id>(vMethod);
}

// ref non void
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
!std::is_void<R>::value&& std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R(T::* vMethod)(arglist...) &) {
auto methodWithoutConstVolatile = reinterpret_cast<R(T::*)(arglist...)>(vMethod);
std::is_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R (T::*vMethod)(arglist...) const) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R> (T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// const ref non void
// volatile
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
!std::is_void<R>::value&& std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R(T::* vMethod)(arglist...) const&) {
auto methodWithoutConstVolatile = reinterpret_cast<R(T::*)(arglist...)>(vMethod);
std::is_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// rref non void
// const volatile
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
!std::is_void<R>::value&& std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R(T::* vMethod)(arglist...) &&) {
auto methodWithoutConstVolatile = reinterpret_cast<R(T::*)(arglist...)>(vMethod);
std::is_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// const rref non void
// no qualifier
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
!std::is_void<R>::value&& std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R(T::* vMethod)(arglist...) const&&) {
auto methodWithoutConstVolatile = reinterpret_cast<R(T::*)(arglist...)>(vMethod);
std::is_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...)) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// ref
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...) const) {
auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
std::is_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::* vMethod)(arglist...) &) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// const ref
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...) volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
std::is_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::* vMethod)(arglist...) const&) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// rref
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
std::is_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::* vMethod)(arglist...) &&) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// const rref
template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...)) {
auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
std::is_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::* vMethod)(arglist...) const&&) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

Expand All @@ -158,4 +146,4 @@ namespace fakeit {

};

}
}
37 changes: 36 additions & 1 deletion tests/overloadded_methods_tests.cpp
Expand Up @@ -43,7 +43,8 @@ struct OverloadedMethods : tpunit::TestFixture {
TEST(OverloadedMethods::stub_overloaded_methods_with_templates<SomeInterface>),
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)
) {
}

Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -152,4 +158,33 @@ struct OverloadedMethods : tpunit::TestFixture {
VerifyNoOtherInvocations(mock);
}

void stub_modern_overloaded_proc() {
Mock<SomeModernCppInterface> 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;

0 comments on commit 435de0f

Please sign in to comment.