Skip to content

Commit

Permalink
Merge branch 'dev-2.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
FranckRJ committed May 22, 2022
2 parents 081fd91 + eedd7eb commit ded6e47
Show file tree
Hide file tree
Showing 28 changed files with 6,086 additions and 4,222 deletions.
1 change: 1 addition & 0 deletions build/sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ CPP_SRCS += \
miscellaneous_tests.cpp \
msc_stubbing_multiple_values_tests.cpp \
msc_type_info_tests.cpp \
overloadded_methods_tests.cpp \
referece_types_tests.cpp \
remove_const_volatile_tests.cpp \
rvalue_arguments_tests.cpp \
Expand Down
49 changes: 12 additions & 37 deletions include/fakeit/MatchersCollector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ namespace fakeit {
template<std::size_t N>
using NakedArgType = typename naked_type<ArgType<index>>::type;

template<std::size_t N>
using ArgMatcherCreatorType = decltype(std::declval<TypedMatcherCreator<NakedArgType<N>>>());

MatchersCollector(std::vector<Destructible *> &matchers)
: _matchers(matchers) {
}
Expand All @@ -46,56 +43,34 @@ namespace fakeit {

template<typename Head>
typename std::enable_if< //
std::is_constructible<NakedArgType<index>, Head>::value, void> //
::type CollectMatchers(const Head &value) {
std::is_constructible<NakedArgType<index>, Head&&>::value, void> //
::type CollectMatchers(Head &&value) {

TypedMatcher<NakedArgType<index>> *d = Eq<NakedArgType<index>>(value).createMatcher();
TypedMatcher<NakedArgType<index>> *d = Eq(std::forward<Head>(value)).template createMatcher<NakedArgType<index>>();
_matchers.push_back(d);
}

template<typename Head, typename ...Tail>
typename std::enable_if< //
std::is_constructible<NakedArgType<index>, Head>::value //
, void> //
::type CollectMatchers(const Head &head, const Tail &... tail) {
CollectMatchers(head);
MatchersCollector<index + 1, arglist...> c(_matchers);
c.CollectMatchers(tail...);
}

template<typename Head>
typename std::enable_if< //
std::is_base_of<TypedMatcherCreator<NakedArgType<index>>, Head>::value, void> //
::type CollectMatchers(const Head &creator) {
TypedMatcher<NakedArgType<index>> *d = creator.createMatcher();
naked_type<Head>::type::template IsTypeCompatible<NakedArgType<index>>::value, void> //
::type CollectMatchers(Head &&creator) {
TypedMatcher<NakedArgType<index>> *d = creator.template createMatcher<NakedArgType<index>>();
_matchers.push_back(d);
}

template<typename Head, typename ...Tail>
//
typename std::enable_if< //
std::is_base_of<TypedMatcherCreator<NakedArgType<index>>, Head>::value, void> //
::type CollectMatchers(const Head &head, const Tail &... tail) {
CollectMatchers(head);
MatchersCollector<index + 1, arglist...> c(_matchers);
c.CollectMatchers(tail...);
}

template<typename Head>
typename std::enable_if<//
std::is_same<AnyMatcher, Head>::value, void> //
::type CollectMatchers(const Head &) {
TypedMatcher<NakedArgType<index>> *d = Any<NakedArgType<index>>().createMatcher();
std::is_same<AnyMatcher, typename naked_type<Head>::type>::value, void> //
::type CollectMatchers(Head &&) {
TypedMatcher<NakedArgType<index>> *d = Any().template createMatcher<NakedArgType<index>>();
_matchers.push_back(d);
}

template<typename Head, typename ...Tail>
typename std::enable_if< //
std::is_same<AnyMatcher, Head>::value, void> //
::type CollectMatchers(const Head &head, const Tail &... tail) {
CollectMatchers(head);
void CollectMatchers(Head &&head, Tail &&... tail) {
CollectMatchers(std::forward<Head>(head));
MatchersCollector<index + 1, arglist...> c(_matchers);
c.CollectMatchers(tail...);
c.CollectMatchers(std::forward<Tail>(tail)...);
}

};
Expand Down
58 changes: 29 additions & 29 deletions include/fakeit/MethodMockingContext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ namespace fakeit {
/**
* Return the original method. not the mock.
*/
virtual typename std::function<R(arglist&...)> getOriginalMethod() = 0;
virtual typename std::function<R(arglist&...)> getOriginalMethodCopyArgs() = 0;
virtual typename std::function<R(arglist&...)> getOriginalMethodForwardArgs() = 0;

virtual std::string getMethodName() = 0;

Expand Down Expand Up @@ -153,8 +154,12 @@ namespace fakeit {
into.push_back(&getStubbingContext().getInvolvedMock());
}

typename std::function<R(arglist &...)> getOriginalMethod() {
return getStubbingContext().getOriginalMethod();
typename std::function<R(arglist &...)> getOriginalMethodCopyArgs() {
return getStubbingContext().getOriginalMethodCopyArgs();
}

typename std::function<R(arglist &...)> getOriginalMethodForwardArgs() {
return getStubbingContext().getOriginalMethodForwardArgs();
}

void setInvocationMatcher(typename ActualInvocation<arglist...>::Matcher *matcher) {
Expand Down Expand Up @@ -222,13 +227,13 @@ namespace fakeit {
_impl->setMethodDetails(mockName, methodName);
}

void setMatchingCriteria(std::function<bool(arglist &...)> predicate) {
void setMatchingCriteria(const std::function<bool(arglist &...)>& predicate) {
typename ActualInvocation<arglist...>::Matcher *matcher{
new UserDefinedInvocationMatcher<arglist...>(predicate)};
_impl->setInvocationMatcher(matcher);
}

void setMatchingCriteria(const std::vector<Destructible *> &matchers) {
void setMatchingCriteria(std::vector<Destructible *> &matchers) {
typename ActualInvocation<arglist...>::Matcher *matcher{
new ArgumentsMatcherInvocationMatcher<arglist...>(matchers)};
_impl->setInvocationMatcher(matcher);
Expand All @@ -245,21 +250,26 @@ namespace fakeit {
_impl->setMethodBodyByAssignment(method);
}

template<class ...matcherCreators, class = typename std::enable_if<
sizeof...(matcherCreators) == sizeof...(arglist)>::type>
void setMatchingCriteria(const matcherCreators &... matcherCreator) {
template<class ...matcherCreators>
typename std::enable_if< //
sizeof...(matcherCreators) == sizeof...(arglist), void> //
::type setMatchingCriteria(matcherCreators &&... matcherCreator) {
std::vector<Destructible *> matchers;

MatchersCollector<0, arglist...> c(matchers);
c.CollectMatchers(matcherCreator...);
c.CollectMatchers(std::forward<matcherCreators>(matcherCreator)...);

MethodMockingContext<R, arglist...>::setMatchingCriteria(matchers);
}

private:

typename std::function<R(arglist&...)> getOriginalMethod() override {
return _impl->getOriginalMethod();
typename std::function<R(arglist&...)> getOriginalMethodCopyArgs() override {
return _impl->getOriginalMethodCopyArgs();
}

typename std::function<R(arglist&...)> getOriginalMethodForwardArgs() override {
return _impl->getOriginalMethodForwardArgs();
}

std::shared_ptr<Implementation> _impl;
Expand Down Expand Up @@ -287,18 +297,13 @@ namespace fakeit {
return *this;
}

MockingContext<R, arglist...> &Using(const arglist &... args) {
MethodMockingContext<R, arglist...>::setMatchingCriteria(args...);
return *this;
}

template<class ...arg_matcher>
MockingContext<R, arglist...> &Using(const arg_matcher &... arg_matchers) {
MethodMockingContext<R, arglist...>::setMatchingCriteria(arg_matchers...);
MockingContext<R, arglist...> &Using(arg_matcher &&... arg_matchers) {
MethodMockingContext<R, arglist...>::setMatchingCriteria(std::forward<arg_matcher>(arg_matchers)...);
return *this;
}

MockingContext<R, arglist...> &Matching(std::function<bool(arglist &...)> matcher) {
MockingContext<R, arglist...> &Matching(const std::function<bool(arglist &...)>& matcher) {
MethodMockingContext<R, arglist...>::setMatchingCriteria(matcher);
return *this;
}
Expand All @@ -308,7 +313,7 @@ namespace fakeit {
return *this;
}

MockingContext<R, arglist...> &operator()(std::function<bool(arglist &...)> matcher) {
MockingContext<R, arglist...> &operator()(const std::function<bool(arglist &...)>& matcher) {
MethodMockingContext<R, arglist...>::setMatchingCriteria(matcher);
return *this;
}
Expand Down Expand Up @@ -352,18 +357,13 @@ namespace fakeit {
return *this;
}

MockingContext<void, arglist...> &Using(const arglist &... args) {
MethodMockingContext<void, arglist...>::setMatchingCriteria(args...);
return *this;
}

template<class ...arg_matcher>
MockingContext<void, arglist...> &Using(const arg_matcher &... arg_matchers) {
MethodMockingContext<void, arglist...>::setMatchingCriteria(arg_matchers...);
MockingContext<void, arglist...> &Using(arg_matcher &&... arg_matchers) {
MethodMockingContext<void, arglist...>::setMatchingCriteria(std::forward<arg_matcher>(arg_matchers)...);
return *this;
}

MockingContext<void, arglist...> &Matching(std::function<bool(arglist &...)> matcher) {
MockingContext<void, arglist...> &Matching(const std::function<bool(arglist &...)>& matcher) {
MethodMockingContext<void, arglist...>::setMatchingCriteria(matcher);
return *this;
}
Expand All @@ -373,7 +373,7 @@ namespace fakeit {
return *this;
}

MockingContext<void, arglist...> &operator()(std::function<bool(arglist &...)> matcher) {
MockingContext<void, arglist...> &operator()(const std::function<bool(arglist &...)>& matcher) {
MethodMockingContext<void, arglist...>::setMatchingCriteria(matcher);
return *this;
}
Expand Down
33 changes: 29 additions & 4 deletions include/fakeit/MockImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,28 @@ namespace fakeit {
: MethodMockingContextBase<R, arglist...>(mock), _vMethod(vMethod) {
}


virtual std::function<R(arglist&...)> getOriginalMethod() override {
template<typename ... T, typename std::enable_if<all_true<std::is_copy_constructible<T>::value...>::value, int>::type = 0>
std::function<R(arglist&...)> getOriginalMethodCopyArgsInternal(int) {
void *mPtr = MethodMockingContextBase<R, arglist...>::_mock.getOriginalMethod(_vMethod);
C * instance = &(MethodMockingContextBase<R, arglist...>::_mock.get());
return [=](arglist&... args) -> R {
auto m = union_cast<typename VTableMethodType<R,arglist...>::type>(mPtr);
return m(instance, args...);
};
}

/* LCOV_EXCL_START */
template<typename ... T>
[[noreturn]] std::function<R(arglist&...)> getOriginalMethodCopyArgsInternal(long) {
std::abort(); // Shouldn't ever be called, Spy() should static_assert an error before.
}
/* LCOV_EXCL_STOP */

std::function<R(arglist&...)> getOriginalMethodCopyArgs() override {
return getOriginalMethodCopyArgsInternal<arglist...>(0);
}

std::function<R(arglist&...)> getOriginalMethodForwardArgs() override {
void *mPtr = MethodMockingContextBase<R, arglist...>::_mock.getOriginalMethod(_vMethod);
C * instance = &(MethodMockingContextBase<R, arglist...>::_mock.get());
return [=](arglist&... args) -> R {
Expand Down Expand Up @@ -225,7 +245,12 @@ namespace fakeit {
: MethodMockingContextBase<void>(mock) {
}

virtual std::function<void()> getOriginalMethod() override {
std::function<void()> getOriginalMethodCopyArgs() override {
return [=]() -> void {
};
}

std::function<void()> getOriginalMethodForwardArgs() override {
return [=]() -> void {
};
}
Expand Down Expand Up @@ -316,4 +341,4 @@ namespace fakeit {
* the stubbed method (if exists).
* This way we can also do extra work in the default implementation like mark the instance as deleted so the mock
* will know not to delete it if already deleted!!!
*/
*/
16 changes: 12 additions & 4 deletions include/fakeit/SpyFunctor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,39 @@
*/
#pragma once

#include <type_traits>

#include "fakeit/StubbingProgress.hpp"
#include "fakeit/StubbingImpl.hpp"
#include "fakeit/SpyingContext.hpp"
#include "mockutils/type_utils.hpp"

namespace fakeit {

class SpyFunctor {
private:

template<typename R, typename ... arglist>
void spy(const SpyingContext<R, arglist...> &root) {
template<typename R, typename ... arglist, typename std::enable_if<all_true<std::is_copy_constructible<arglist>::value...>::value, int>::type = 0>
void spy(const SpyingContext<R, arglist...> &root, int) {
SpyingContext<R, arglist...> &rootWithoutConst = const_cast<SpyingContext<R, arglist...> &>(root);
auto methodFromOriginalVT = rootWithoutConst.getOriginalMethod();
auto methodFromOriginalVT = rootWithoutConst.getOriginalMethodCopyArgs();
rootWithoutConst.appendAction(new ReturnDelegateValue<R, arglist...>(methodFromOriginalVT));
rootWithoutConst.commit();
}

template<typename R, typename ... arglist>
void spy(const SpyingContext<R, arglist...> &, long) {
static_assert(!std::is_same<R, R>::value, "Spy() cannot accept move-only args, use SpyWithoutVerify() instead which is able to forward these args but then they won't be available for Verify().");
}

void operator()() {
}

public:

template<typename H, typename ... M>
void operator()(const H &head, const M &... tail) {
spy(head);
spy(head, 0);
this->operator()(tail...);
}

Expand Down
33 changes: 33 additions & 0 deletions include/fakeit/SpyWithoutVerifyFunctor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include "fakeit/StubbingProgress.hpp"
#include "fakeit/StubbingImpl.hpp"
#include "fakeit/SpyingContext.hpp"

namespace fakeit {

class SpyWithoutVerifyFunctor {
private:

template<typename R, typename ... arglist>
void spy(const SpyingContext<R, arglist...> &root) {
SpyingContext<R, arglist...> &rootWithoutConst = const_cast<SpyingContext<R, arglist...> &>(root);
auto methodFromOriginalVT = rootWithoutConst.getOriginalMethodForwardArgs();
rootWithoutConst.appendAction(new ReturnDelegateValue<R, arglist...>(methodFromOriginalVT));
rootWithoutConst.commit();
}

void operator()() {
}

public:

template<typename H, typename ... M>
void operator()(const H &head, const M &... tail) {
spy(head);
this->operator()(tail...);
}

};

}
3 changes: 2 additions & 1 deletion include/fakeit/SpyingContext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace fakeit {
struct SpyingContext : Xaction {
virtual void appendAction(Action<R, arglist...> *action) = 0;

virtual std::function<R(arglist&...)> getOriginalMethod() = 0;
virtual std::function<R(arglist&...)> getOriginalMethodCopyArgs() = 0;
virtual std::function<R(arglist&...)> getOriginalMethodForwardArgs() = 0;
};
}
3 changes: 3 additions & 0 deletions include/fakeit/api_functors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "fakeit/VerifyFunctor.hpp"
#include "fakeit/VerifyNoOtherInvocationsFunctor.hpp"
#include "fakeit/SpyFunctor.hpp"
#include "fakeit/SpyWithoutVerifyFunctor.hpp"
#include "fakeit/FakeFunctor.hpp"
#include "fakeit/WhenFunctor.hpp"
#include "fakeit/UnverifiedFunctor.hpp"
Expand All @@ -15,6 +16,7 @@ namespace fakeit {
static VerifyNoOtherInvocationsFunctor VerifyNoOtherInvocations(Fakeit);
static UnverifiedFunctor Unverified(Fakeit);
static SpyFunctor Spy;
static SpyWithoutVerifyFunctor SpyWithoutVerify;
static FakeFunctor Fake;
static WhenFunctor When;

Expand All @@ -28,6 +30,7 @@ namespace fakeit {
use(&Fake);
use(&When);
use(&Spy);
use(&SpyWithoutVerify);
use(&Using);
use(&Verify);
use(&VerifyNoOtherInvocations);
Expand Down
4 changes: 2 additions & 2 deletions include/fakeit/api_macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
std::remove_reference<decltype((mock).get())>::type

#define OVERLOADED_METHOD_PTR(mock, method, prototype) \
fakeit::Prototype<prototype>::MemberType<MOCK_TYPE(mock)>::get(&MOCK_TYPE(mock)::method)
fakeit::Prototype<prototype>::MemberType<typename MOCK_TYPE(mock)>::get(&MOCK_TYPE(mock)::method)

#define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \
fakeit::Prototype<prototype>::MemberType<MOCK_TYPE(mock)>::getconst(&MOCK_TYPE(mock)::method)
fakeit::Prototype<prototype>::MemberType<typename MOCK_TYPE(mock)>::getconst(&MOCK_TYPE(mock)::method)

#define Dtor(mock) \
(mock).dtor().setMethodDetails(#mock,"destructor")
Expand Down
Loading

0 comments on commit ded6e47

Please sign in to comment.