mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
Replace Boost PP_Iterate by C++11 variadic templates
This allows support for any number of arguments and makes setting MOCK_MAX_ARGS unnecessary. It also allows for easier debugging due to being able to step into actual code instead of preprocessor generated stuff
This commit is contained in:
parent
90d9ac8055
commit
fca30e7780
17 changed files with 368 additions and 472 deletions
|
|
@ -15,6 +15,7 @@ Released -
|
|||
* Removed MOCK_*_TPL as they are no longer required, use the non _TPL variant even for templates
|
||||
* Added MOCK_PROTECT_SIGNATURE to pass function signatures with commas in the return type
|
||||
* Remove support for protecting function signatures via BOOST_IDENTITY_TYPE, use MOCK_PROTECT_SIGNATURE instead
|
||||
* Add support for unlimitted number of arguments making MOCK_MAX_ARGS superflous
|
||||
|
||||
[endsect]
|
||||
|
||||
|
|
|
|||
|
|
@ -110,24 +110,6 @@ For more information about the serialization operator and the use of mock::forma
|
|||
|
||||
[endsect]
|
||||
|
||||
[section Number of arguments]
|
||||
|
||||
The maximum number of arguments a mocked method can have is defined by MOCK_MAX_ARGS.
|
||||
By default this value is set to 9, but if needed it can be changed before including the library :
|
||||
|
||||
[max_args]
|
||||
|
||||
This means methods with up to 20 arguments will then be accepted.
|
||||
|
||||
The mock object library uses several boost libraries and will adjust some of their constants if they haven't already been defined :
|
||||
|
||||
* Boost.Function with BOOST_FUNCTION_MAX_ARGS required at MOCK_MAX_ARGS or higher
|
||||
* Boost.FunctionTypes with BOOST_FT_MAX_ARITY required at MOCK_MAX_ARGS + 1 or higher
|
||||
|
||||
A compilation error will happen if one of those constants is already defined too low.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Test framework integration]
|
||||
|
||||
By default the library expects to be used in conjunction with Boost.Test e.g. :
|
||||
|
|
|
|||
|
|
@ -145,12 +145,6 @@ BOOST_AUTO_TEST_CASE(near_constraint_works_with_with_float_wrapper_and_cref)
|
|||
}
|
||||
} // namespace near_constraint_cref_test
|
||||
|
||||
#undef MOCK_MAX_ARGS
|
||||
//[ max_args
|
||||
#define MOCK_MAX_ARGS 20
|
||||
#include <turtle/mock.hpp>
|
||||
//]
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
|
|
|||
|
|
@ -18,10 +18,6 @@
|
|||
# define MOCK_USE_BOOST_TEST
|
||||
#endif
|
||||
|
||||
#ifndef MOCK_MAX_ARGS
|
||||
# define MOCK_MAX_ARGS 9
|
||||
#endif
|
||||
|
||||
#ifndef MOCK_MAX_SEQUENCES
|
||||
# define MOCK_MAX_SEQUENCES 10
|
||||
#endif
|
||||
|
|
|
|||
184
include/turtle/detail/expectation.hpp
Normal file
184
include/turtle/detail/expectation.hpp
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// http://turtle.sourceforge.net
|
||||
//
|
||||
// Copyright Mathieu Champlon 2012
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef MOCK_EXPECTATION_HPP_INCLUDED
|
||||
#define MOCK_EXPECTATION_HPP_INCLUDED
|
||||
|
||||
#include "../matcher.hpp"
|
||||
#include "../sequence.hpp"
|
||||
#include "action.hpp"
|
||||
#include "invocation.hpp"
|
||||
#include "matcher_base.hpp"
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace mock { namespace detail {
|
||||
template<typename... Args>
|
||||
class default_matcher : public matcher_base<Args...>
|
||||
{
|
||||
private:
|
||||
bool operator()(typename ref_arg<Args>::type...) override { return true; }
|
||||
void serialize(std::ostream& s) const override
|
||||
{
|
||||
for(unsigned i = 0; i < sizeof...(Args); ++i)
|
||||
{
|
||||
if(i)
|
||||
s << ", ";
|
||||
s << "any";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ConstraintPack, typename... Args>
|
||||
class single_matcher;
|
||||
|
||||
template<typename... Constraints, typename... Args>
|
||||
class single_matcher<void(Constraints...), Args...> : public matcher_base<Args...>
|
||||
{
|
||||
static_assert(sizeof...(Args) > 0, "This class is only useful for functions with arguments");
|
||||
static_assert(sizeof...(Constraints) == sizeof...(Args), "Need exactly 1 constraint per argument");
|
||||
|
||||
public:
|
||||
single_matcher(Constraints... constraints) : matchers_(matcher<Args, Constraints>(constraints)...) {}
|
||||
|
||||
private:
|
||||
template<std::size_t... I>
|
||||
bool is_valid_impl(std::index_sequence<I...>, typename ref_arg<Args>::type... t)
|
||||
{
|
||||
using expander = bool[];
|
||||
bool result = true;
|
||||
(void)expander{ result &= std::get<I>(matchers_)(std::forward<Args>(t))... };
|
||||
return result;
|
||||
}
|
||||
bool operator()(typename ref_arg<Args>::type... t) override
|
||||
{
|
||||
return is_valid_impl(std::make_index_sequence<sizeof...(Args)>{}, std::forward<Args>(t)...);
|
||||
}
|
||||
template<std::size_t... I>
|
||||
void serialize_impl(std::index_sequence<I...>, std::ostream& s) const
|
||||
{
|
||||
using expander = int[];
|
||||
s << std::get<0>(matchers_);
|
||||
(void)expander{ 0, (s << ", " << std::get<I + 1>(matchers_), 0)... };
|
||||
}
|
||||
void serialize(std::ostream& s) const override
|
||||
{
|
||||
serialize_impl(std::make_index_sequence<sizeof...(Args) - 1>{}, s);
|
||||
}
|
||||
|
||||
private:
|
||||
std::tuple<matcher<Args, Constraints>...> matchers_;
|
||||
};
|
||||
|
||||
template<typename F, typename... Args>
|
||||
class multi_matcher : public matcher_base<Args...>
|
||||
{
|
||||
static_assert(sizeof...(Args) > 0, "This class is only useful for functions with arguments");
|
||||
|
||||
public:
|
||||
multi_matcher(const F& f) : f_(f) {}
|
||||
|
||||
private:
|
||||
bool operator()(typename ref_arg<Args>::type... t) override { return f_(std::forward<Args>(t)...); }
|
||||
void serialize(std::ostream& s) const override { s << mock::format(f_); }
|
||||
|
||||
private:
|
||||
F f_;
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
class expectation;
|
||||
|
||||
template<typename R, typename... Args>
|
||||
class expectation<R(Args...)> : public action<R, R(Args...)>
|
||||
{
|
||||
static constexpr auto arity = sizeof...(Args);
|
||||
|
||||
public:
|
||||
expectation() : expectation("unknown location", 0) {}
|
||||
expectation(const char* file, int line)
|
||||
: invocation_(std::make_unique<unlimited>()), matcher_(std::make_unique<default_matcher<Args...>>()),
|
||||
file_(file), line_(line)
|
||||
{}
|
||||
|
||||
expectation(expectation&&) = default;
|
||||
expectation(expectation const&) = default;
|
||||
expectation& operator=(expectation&&) = default;
|
||||
expectation& operator=(expectation const&) = default;
|
||||
|
||||
~expectation()
|
||||
{
|
||||
for(auto& sequence : sequences_)
|
||||
sequence->remove(this);
|
||||
}
|
||||
|
||||
void invoke(std::unique_ptr<invocation> i) { invocation_ = std::move(i); }
|
||||
|
||||
template<typename... Constraints>
|
||||
std::enable_if_t<(arity > 0) && sizeof...(Constraints) == arity, expectation&> with(Constraints... c)
|
||||
{
|
||||
matcher_ = std::make_unique<single_matcher<void(Constraints...), Args...>>(c...);
|
||||
return *this;
|
||||
}
|
||||
template<typename Constraint, std::size_t Arity = arity>
|
||||
std::enable_if_t<(Arity > 1), expectation&> with(const Constraint& c)
|
||||
{
|
||||
matcher_ = std::make_unique<multi_matcher<Constraint, Args...>>(c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void add(sequence& s)
|
||||
{
|
||||
s.impl_->add(this);
|
||||
sequences_.push_back(s.impl_);
|
||||
}
|
||||
|
||||
bool verify() const { return invocation_->verify(); }
|
||||
|
||||
bool is_valid(typename ref_arg<Args>::type... t) const
|
||||
{
|
||||
return !invocation_->exhausted() && (*matcher_)(std::forward<Args>(t)...);
|
||||
}
|
||||
|
||||
bool invoke() const
|
||||
{
|
||||
for(auto& sequence : sequences_)
|
||||
{
|
||||
if(!sequence->is_valid(this))
|
||||
return false;
|
||||
}
|
||||
bool result = invocation_->invoke();
|
||||
for(auto& sequence : sequences_)
|
||||
sequence->invalidate(this);
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* file() const { return file_; }
|
||||
int line() const { return line_; }
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const expectation& e)
|
||||
{
|
||||
s << (e.invocation_->exhausted() ? 'v' : '.') << ' ' << *e.invocation_;
|
||||
constexpr bool hasArguments = arity > 0u;
|
||||
if(hasArguments)
|
||||
s << ".with( " << *e.matcher_ << " )";
|
||||
return s;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<invocation> invocation_;
|
||||
std::unique_ptr<matcher_base<Args...>> matcher_;
|
||||
std::vector<std::shared_ptr<sequence_impl>> sequences_;
|
||||
const char* file_;
|
||||
int line_;
|
||||
};
|
||||
}} // namespace mock::detail
|
||||
|
||||
#endif // MOCK_EXPECTATION_HPP_INCLUDED
|
||||
|
|
@ -1,201 +0,0 @@
|
|||
// http://turtle.sourceforge.net
|
||||
//
|
||||
// Copyright Mathieu Champlon 2012
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "matcher_base_template.hpp"
|
||||
|
||||
#define MOCK_EXPECTATION_INITIALIZE(z, n, d) BOOST_PP_COMMA_IF(n) c##n##_(c##n)
|
||||
|
||||
#define MOCK_EXPECTATION_MEMBER(z, n, d) matcher<T##n, Constraint_##n> c##n##_;
|
||||
|
||||
#define MOCK_EXPECTATION_IS_VALID(z, n, d) BOOST_PP_IF(n, &&, ) c##n##_(std::forward<T##n>(a##n))
|
||||
|
||||
#define MOCK_EXPECTATION_SERIALIZE(z, n, d) BOOST_PP_IF(n, << ", " <<, ) c##n##_
|
||||
|
||||
#define MOCK_EXPECTATION_SERIALIZE_ANY(z, n, d) BOOST_PP_IF(n, << ", " <<, ) "any"
|
||||
|
||||
#define MOCK_EXPECTATION_PARAM(z, n, Args) std::forward<T##n>(a##n)
|
||||
|
||||
#define MOCK_REF_ARG(z, n, d) typename ref_arg<T##n>::type a##n
|
||||
|
||||
#define MOCK_REF_ARG_T(z, n, d) typename ref_arg<T##n>::type
|
||||
|
||||
namespace mock { namespace detail {
|
||||
template<typename Signature>
|
||||
class default_matcher;
|
||||
|
||||
template<BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename T)>
|
||||
class default_matcher<void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))> :
|
||||
public matcher_base<void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>
|
||||
{
|
||||
private:
|
||||
virtual bool operator()(BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG_T, _)) { return true; }
|
||||
virtual void serialize(std::ostream& s) const
|
||||
{
|
||||
s << "" BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_EXPECTATION_SERIALIZE_ANY, _);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef MOCK_NUM_ARGS_0
|
||||
|
||||
template<typename Constraint, typename Signature>
|
||||
class single_matcher;
|
||||
|
||||
template<BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename Constraint_), BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename T)>
|
||||
class single_matcher<void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, Constraint_)),
|
||||
void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))> :
|
||||
public matcher_base<void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>
|
||||
{
|
||||
public:
|
||||
single_matcher(BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, Constraint_, c))
|
||||
: BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_EXPECTATION_INITIALIZE, _)
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual bool operator()(BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG, _))
|
||||
{
|
||||
return BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_EXPECTATION_IS_VALID, _);
|
||||
}
|
||||
virtual void serialize(std::ostream& s) const
|
||||
{
|
||||
s << BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_EXPECTATION_SERIALIZE, _);
|
||||
}
|
||||
|
||||
private:
|
||||
BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_EXPECTATION_MEMBER, _)
|
||||
};
|
||||
|
||||
template<typename F, typename Signature>
|
||||
class multi_matcher;
|
||||
|
||||
template<typename F, BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename T)>
|
||||
class multi_matcher<F, void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))> :
|
||||
public matcher_base<void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>
|
||||
{
|
||||
public:
|
||||
multi_matcher(const F& f) : f_(f) {}
|
||||
|
||||
private:
|
||||
virtual bool operator()(BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG, _))
|
||||
{
|
||||
return f_(BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_EXPECTATION_PARAM, _));
|
||||
}
|
||||
virtual void serialize(std::ostream& s) const { s << mock::format(f_); }
|
||||
|
||||
private:
|
||||
F f_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template<typename Signature>
|
||||
class expectation;
|
||||
|
||||
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(MOCK_NUM_ARGS, typename T)>
|
||||
class expectation<R(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))> :
|
||||
public action<R, R(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>
|
||||
{
|
||||
public:
|
||||
expectation()
|
||||
: invocation_(std::make_unique<unlimited>()),
|
||||
matcher_(std::make_unique<default_matcher<void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>>()),
|
||||
file_("unknown location"), line_(0)
|
||||
{}
|
||||
expectation(const char* file, int line)
|
||||
: invocation_(std::make_unique<unlimited>()),
|
||||
matcher_(std::make_unique<default_matcher<void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>>()), file_(file),
|
||||
line_(line)
|
||||
{}
|
||||
|
||||
expectation(expectation&&) = default;
|
||||
expectation(expectation const&) = default;
|
||||
expectation& operator=(expectation&&) = default;
|
||||
expectation& operator=(expectation const&) = default;
|
||||
|
||||
~expectation()
|
||||
{
|
||||
for(auto& sequence : sequences_)
|
||||
sequence->remove(this);
|
||||
}
|
||||
|
||||
void invoke(std::unique_ptr<invocation> i) { invocation_ = std::move(i); }
|
||||
|
||||
#ifndef MOCK_NUM_ARGS_0
|
||||
template<BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename Constraint_)>
|
||||
expectation& with(BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, Constraint_, c))
|
||||
{
|
||||
matcher_ = std::make_unique<single_matcher<void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, Constraint_)),
|
||||
void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>>(
|
||||
BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, c));
|
||||
return *this;
|
||||
}
|
||||
# if MOCK_NUM_ARGS > 1
|
||||
template<typename Constraint>
|
||||
expectation& with(const Constraint& c)
|
||||
{
|
||||
matcher_ = std::make_unique<multi_matcher<Constraint, void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>>(c);
|
||||
return *this;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void add(sequence& s)
|
||||
{
|
||||
s.impl_->add(this);
|
||||
sequences_.push_back(s.impl_);
|
||||
}
|
||||
|
||||
bool verify() const { return invocation_->verify(); }
|
||||
|
||||
bool is_valid(BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG, _)) const
|
||||
{
|
||||
return !invocation_->exhausted() && (*matcher_)(BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_EXPECTATION_PARAM, _));
|
||||
}
|
||||
|
||||
bool invoke() const
|
||||
{
|
||||
for(auto& sequence : sequences_)
|
||||
{
|
||||
if(!sequence->is_valid(this))
|
||||
return false;
|
||||
}
|
||||
bool result = invocation_->invoke();
|
||||
for(auto& sequence : sequences_)
|
||||
sequence->invalidate(this);
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* file() const { return file_; }
|
||||
int line() const { return line_; }
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const expectation& e)
|
||||
{
|
||||
return s << (e.invocation_->exhausted() ? 'v' : '.') << ' ' << *e.invocation_
|
||||
#ifndef MOCK_NUM_ARGS_0
|
||||
<< ".with( " << *e.matcher_ << " )"
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<invocation> invocation_;
|
||||
std::unique_ptr<matcher_base<void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>> matcher_;
|
||||
std::vector<std::shared_ptr<sequence_impl>> sequences_;
|
||||
const char* file_;
|
||||
int line_;
|
||||
};
|
||||
}} // namespace mock::detail
|
||||
|
||||
#undef MOCK_EXPECTATION_INITIALIZE
|
||||
#undef MOCK_EXPECTATION_MEMBER
|
||||
#undef MOCK_EXPECTATION_IS_VALID
|
||||
#undef MOCK_EXPECTATION_SERIALIZE
|
||||
#undef MOCK_EXPECTATION_SERIALIZE_ANY
|
||||
#undef MOCK_EXPECTATION_PARAM
|
||||
#undef MOCK_REF_ARG
|
||||
#undef MOCK_REF_ARG_T
|
||||
#undef MOCK_RV_REF
|
||||
|
|
@ -10,88 +10,72 @@
|
|||
#define MOCK_FUNCTION_HPP_INCLUDED
|
||||
|
||||
#include "../config.hpp"
|
||||
#include "../constraints.hpp"
|
||||
#include "../error.hpp"
|
||||
#include "../log.hpp"
|
||||
#include "../matcher.hpp"
|
||||
#include "../sequence.hpp"
|
||||
#include "action.hpp"
|
||||
#include "context.hpp"
|
||||
#include "invocation.hpp"
|
||||
#include "move_helper.hpp"
|
||||
#include "mutex.hpp"
|
||||
#include "function_impl.hpp"
|
||||
#include "type_name.hpp"
|
||||
#include "verifiable.hpp"
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/preprocessor/comparison/equal.hpp>
|
||||
#include <boost/preprocessor/comparison/greater.hpp>
|
||||
#include <boost/preprocessor/iteration/iterate.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
||||
#include <boost/test/utils/lazy_ostream.hpp>
|
||||
#include <list>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
namespace mock { namespace detail {
|
||||
template<typename R, typename E>
|
||||
struct wrapper_base
|
||||
{
|
||||
wrapper_base(E& e) : e_(&e) {}
|
||||
template<typename Signature>
|
||||
class function;
|
||||
|
||||
template<typename T>
|
||||
void returns(T t)
|
||||
template<typename R, typename... Ts>
|
||||
class function<R(Ts...)>
|
||||
{
|
||||
e_->returns(t);
|
||||
private:
|
||||
typedef function_impl<R(Ts...)> impl_type;
|
||||
typedef typename impl_type::wrapper_type expectation_type;
|
||||
typedef typename impl_type::error_type error_type;
|
||||
|
||||
public:
|
||||
function() : impl_(std::make_shared<impl_type>()) {}
|
||||
|
||||
bool verify() const { return impl_->verify(); }
|
||||
bool verify(const char* file, int line) const
|
||||
{
|
||||
error_type::pass(file, line);
|
||||
return impl_->verify();
|
||||
}
|
||||
void reset() { impl_->reset(); }
|
||||
void reset(const char* file, int line)
|
||||
{
|
||||
error_type::pass(file, line);
|
||||
impl_->reset();
|
||||
}
|
||||
|
||||
E* e_;
|
||||
};
|
||||
template<typename E>
|
||||
struct wrapper_base<void, E>
|
||||
expectation_type expect(const char* file, int line)
|
||||
{
|
||||
wrapper_base(E& e) : e_(&e) {}
|
||||
error_type::pass(file, line);
|
||||
return impl_->expect(file, line);
|
||||
}
|
||||
expectation_type expect() { return impl_->expect(); }
|
||||
|
||||
E* e_;
|
||||
};
|
||||
template<typename R, typename E>
|
||||
struct wrapper_base<R*, E>
|
||||
{
|
||||
wrapper_base(E& e) : e_(&e) {}
|
||||
R operator()(Ts... args) const { return (*impl_)(std::forward<Ts>(args)...); }
|
||||
|
||||
void returns(R* r) { e_->returns(r); }
|
||||
template<typename Y>
|
||||
void returns(const std::reference_wrapper<Y>& r)
|
||||
friend std::ostream& operator<<(std::ostream& s, const function& f) { return s << *f.impl_; }
|
||||
|
||||
function& operator()(context& c, boost::unit_test::const_string instance)
|
||||
{
|
||||
e_->returns(r);
|
||||
impl_->add(c, impl_.get(), instance, boost::none, "");
|
||||
return *this;
|
||||
}
|
||||
|
||||
E* e_;
|
||||
};
|
||||
|
||||
inline int exceptions()
|
||||
void configure(context& c,
|
||||
const void* p,
|
||||
boost::unit_test::const_string instance,
|
||||
boost::optional<type_name> type,
|
||||
boost::unit_test::const_string name) const
|
||||
{
|
||||
#ifdef MOCK_UNCAUGHT_EXCEPTIONS
|
||||
using namespace std;
|
||||
return uncaught_exceptions();
|
||||
#else
|
||||
return std::uncaught_exception() ? 1 : 0;
|
||||
#endif
|
||||
impl_->add(c, p, instance, type, name);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<impl_type> impl_;
|
||||
};
|
||||
}} // namespace mock::detail
|
||||
|
||||
#define MOCK_NUM_ARGS 0
|
||||
#define MOCK_NUM_ARGS_0
|
||||
#include "function_template.hpp"
|
||||
#undef MOCK_NUM_ARGS_0
|
||||
#undef MOCK_NUM_ARGS
|
||||
|
||||
#define BOOST_PP_FILENAME_1 <turtle/detail/function_iterate.hpp>
|
||||
#define BOOST_PP_ITERATION_LIMITS (1, MOCK_MAX_ARGS)
|
||||
#include BOOST_PP_ITERATE()
|
||||
#undef BOOST_PP_FILENAME_1
|
||||
#undef BOOST_PP_ITERATION_LIMITS
|
||||
|
||||
#endif // MOCK_FUNCTION_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -6,29 +6,74 @@
|
|||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "expectation_template.hpp"
|
||||
#ifndef MOCK_FUNCTION_IMPL_HPP_INCLUDED
|
||||
#define MOCK_FUNCTION_IMPL_HPP_INCLUDED
|
||||
|
||||
#include "../error.hpp"
|
||||
#include "expectation.hpp"
|
||||
#include "mutex.hpp"
|
||||
#include "verifiable.hpp"
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/test/utils/lazy_ostream.hpp>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#ifndef MOCK_ERROR_POLICY
|
||||
# error no error policy has been set
|
||||
#endif
|
||||
|
||||
#define MOCK_FUNCTION_FORMAT(z, n, N) << ' ' << mock::format(t##n) << BOOST_PP_IF(BOOST_PP_EQUAL(N, n), ' ', ',')
|
||||
|
||||
#define MOCK_FUNCTION_CONTEXT \
|
||||
boost::unit_test::lazy_ostream::instance() \
|
||||
<< lazy_context(this) << '(' BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_FUNCTION_FORMAT, BOOST_PP_DEC(MOCK_NUM_ARGS)) \
|
||||
<< ')' << lazy_expectations(this)
|
||||
|
||||
#define MOCK_FORWARD(z, n, d) std::forward<T##n>(t##n)
|
||||
|
||||
namespace mock { namespace detail {
|
||||
template<typename R, typename E>
|
||||
struct wrapper_base
|
||||
{
|
||||
wrapper_base(E& e) : e_(&e) {}
|
||||
|
||||
template<typename T>
|
||||
void returns(T t)
|
||||
{
|
||||
e_->returns(t);
|
||||
}
|
||||
|
||||
E* e_;
|
||||
};
|
||||
template<typename E>
|
||||
struct wrapper_base<void, E>
|
||||
{
|
||||
wrapper_base(E& e) : e_(&e) {}
|
||||
|
||||
E* e_;
|
||||
};
|
||||
template<typename R, typename E>
|
||||
struct wrapper_base<R*, E>
|
||||
{
|
||||
wrapper_base(E& e) : e_(&e) {}
|
||||
|
||||
void returns(R* r) { e_->returns(r); }
|
||||
template<typename Y>
|
||||
void returns(const std::reference_wrapper<Y>& r)
|
||||
{
|
||||
e_->returns(r);
|
||||
}
|
||||
|
||||
E* e_;
|
||||
};
|
||||
|
||||
inline int exceptions()
|
||||
{
|
||||
#ifdef MOCK_UNCAUGHT_EXCEPTIONS
|
||||
using namespace std;
|
||||
return uncaught_exceptions();
|
||||
#else
|
||||
return std::uncaught_exception() ? 1 : 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Signature>
|
||||
class function_impl;
|
||||
|
||||
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(MOCK_NUM_ARGS, typename T)>
|
||||
class function_impl<R(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))> :
|
||||
public verifiable,
|
||||
public std::enable_shared_from_this<function_impl<R(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>>
|
||||
template<typename R, typename... Args>
|
||||
class function_impl<R(Args...)> : public verifiable, public std::enable_shared_from_this<function_impl<R(Args...)>>
|
||||
{
|
||||
public:
|
||||
typedef safe_error<R, MOCK_ERROR_POLICY<R>> error_type;
|
||||
|
|
@ -82,12 +127,13 @@ namespace mock { namespace detail {
|
|||
}
|
||||
|
||||
private:
|
||||
typedef expectation<R(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))> expectation_type;
|
||||
typedef expectation<R(Args...)> expectation_type;
|
||||
|
||||
class wrapper : public wrapper_base<R, expectation_type>
|
||||
{
|
||||
private:
|
||||
typedef wrapper_base<R, expectation_type> base_type;
|
||||
static constexpr auto arity = sizeof...(Args);
|
||||
|
||||
public:
|
||||
wrapper(const std::shared_ptr<mutex>& m, expectation_type& e) : base_type(e), lock_(m) {}
|
||||
|
|
@ -126,24 +172,18 @@ namespace mock { namespace detail {
|
|||
return *this;
|
||||
}
|
||||
|
||||
#ifndef MOCK_NUM_ARGS_0
|
||||
template<BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename Constraint_)>
|
||||
wrapper& with(BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, Constraint_, c))
|
||||
/// Callable only for functions taking arguments
|
||||
/// Number of constraints must match the number of arguments
|
||||
/// or a single constraint checking all arguments must be passed
|
||||
template<typename... Constraints>
|
||||
std::enable_if_t<(arity > 0u && (sizeof...(Constraints) == arity || sizeof...(Constraints) == 1u)),
|
||||
wrapper&>
|
||||
with(Constraints... c)
|
||||
{
|
||||
this->e_->with(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, c));
|
||||
this->e_->with(c...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
# if MOCK_NUM_ARGS > 1
|
||||
template<typename Constraint>
|
||||
wrapper& with(const Constraint& c)
|
||||
{
|
||||
this->e_->with(c);
|
||||
return *this;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define MOCK_FUNCTION_IN_ADD(z, n, d) this->e_->add(s##n);
|
||||
|
||||
#define MOCK_FUNCTION_IN(z, n, d) \
|
||||
|
|
@ -195,13 +235,17 @@ namespace mock { namespace detail {
|
|||
return wrapper(mutex_, expectations_.back());
|
||||
}
|
||||
|
||||
R operator()(BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, t)) const
|
||||
R operator()(Args... args) const
|
||||
{
|
||||
// Due to lifetime rules of references this must be created and consumed in one line
|
||||
#define MOCK_FUNCTION_CONTEXT \
|
||||
boost::unit_test::lazy_ostream::instance() << lazy_context(this) << lazy_args(args...) << lazy_expectations(this)
|
||||
|
||||
lock _(mutex_);
|
||||
valid_ = false;
|
||||
for(const auto& expectation : expectations_)
|
||||
{
|
||||
if(expectation.is_valid(BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _)))
|
||||
if(expectation.is_valid(std::forward<Args>(args)...))
|
||||
{
|
||||
if(!expectation.invoke())
|
||||
{
|
||||
|
|
@ -218,12 +262,13 @@ namespace mock { namespace detail {
|
|||
valid_ = true;
|
||||
error_type::call(MOCK_FUNCTION_CONTEXT, expectation.file(), expectation.line());
|
||||
if(expectation.functor())
|
||||
return expectation.functor()(BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _));
|
||||
return expectation.functor()(std::forward<Args>(args)...);
|
||||
return expectation.trigger();
|
||||
}
|
||||
}
|
||||
error_type::fail("unexpected call", MOCK_FUNCTION_CONTEXT);
|
||||
return error_type::abort();
|
||||
#undef MOCK_FUNCTION_CONTEXT
|
||||
}
|
||||
|
||||
void add(context& c,
|
||||
|
|
@ -271,6 +316,29 @@ namespace mock { namespace detail {
|
|||
const function_impl* impl_;
|
||||
};
|
||||
|
||||
struct lazy_args
|
||||
{
|
||||
lazy_args(std::add_lvalue_reference_t<Args>... args) : args_(args...) {}
|
||||
friend std::ostream& operator<<(std::ostream& s, const lazy_args& a)
|
||||
{
|
||||
return a.print_impl(std::make_index_sequence<sizeof...(Args)>{}, s);
|
||||
}
|
||||
|
||||
private:
|
||||
std::tuple<std::add_lvalue_reference_t<Args>...> args_;
|
||||
|
||||
template<std::size_t... I>
|
||||
std::ostream& print_impl(std::index_sequence<I...>, std::ostream& s) const
|
||||
{
|
||||
s << '(';
|
||||
using expander = int[];
|
||||
(void)expander{
|
||||
0, (s << ' ' << mock::format(std::get<I>(args_)) << (sizeof...(Args) - 1u == I ? ' ' : ','), 0)...
|
||||
};
|
||||
return s << ')';
|
||||
}
|
||||
};
|
||||
|
||||
std::list<expectation_type> expectations_;
|
||||
context* context_;
|
||||
mutable bool valid_;
|
||||
|
|
@ -279,6 +347,4 @@ namespace mock { namespace detail {
|
|||
};
|
||||
}} // namespace mock::detail
|
||||
|
||||
#undef MOCK_FUNCTION_FORMAT
|
||||
#undef MOCK_FUNCTION_CONTEXT
|
||||
#undef MOCK_FORWARD
|
||||
#endif // MOCK_FUNCTION_IMPL_HPP_INCLUDED
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
// http://turtle.sourceforge.net
|
||||
//
|
||||
// Copyright Mathieu Champlon 2012
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define MOCK_NUM_ARGS BOOST_PP_ITERATION()
|
||||
#include "function_template.hpp"
|
||||
#undef MOCK_NUM_ARGS
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
// http://turtle.sourceforge.net
|
||||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "function_impl_template.hpp"
|
||||
|
||||
#define MOCK_FORWARD(z, n, d) std::forward<T##n>(t##n)
|
||||
|
||||
namespace mock { namespace detail {
|
||||
template<typename Signature>
|
||||
class function;
|
||||
|
||||
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(MOCK_NUM_ARGS, typename T)>
|
||||
class function<R(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>
|
||||
{
|
||||
private:
|
||||
typedef function_impl<R(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))> impl_type;
|
||||
typedef typename impl_type::wrapper_type expectation_type;
|
||||
typedef typename impl_type::error_type error_type;
|
||||
|
||||
public:
|
||||
function() : impl_(std::make_shared<impl_type>()) {}
|
||||
|
||||
bool verify() const { return impl_->verify(); }
|
||||
bool verify(const char* file, int line) const
|
||||
{
|
||||
error_type::pass(file, line);
|
||||
return impl_->verify();
|
||||
}
|
||||
void reset() { impl_->reset(); }
|
||||
void reset(const char* file, int line)
|
||||
{
|
||||
error_type::pass(file, line);
|
||||
impl_->reset();
|
||||
}
|
||||
|
||||
expectation_type expect(const char* file, int line)
|
||||
{
|
||||
error_type::pass(file, line);
|
||||
return impl_->expect(file, line);
|
||||
}
|
||||
expectation_type expect() { return impl_->expect(); }
|
||||
|
||||
R operator()(BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, t)) const
|
||||
{
|
||||
return (*impl_)(BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _));
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const function& f) { return s << *f.impl_; }
|
||||
|
||||
function& operator()(context& c, boost::unit_test::const_string instance)
|
||||
{
|
||||
impl_->add(c, impl_.get(), instance, boost::none, "");
|
||||
return *this;
|
||||
}
|
||||
|
||||
void configure(context& c,
|
||||
const void* p,
|
||||
boost::unit_test::const_string instance,
|
||||
boost::optional<type_name> type,
|
||||
boost::unit_test::const_string name) const
|
||||
{
|
||||
impl_->add(c, p, instance, type, name);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<impl_type> impl_;
|
||||
};
|
||||
}} // namespace mock::detail
|
||||
|
||||
#undef MOCK_FORWARD
|
||||
|
|
@ -6,14 +6,15 @@
|
|||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define MOCK_REF_ARG(z, n, d) typename ref_arg<T##n>::type
|
||||
#ifndef MOCK_MATCHER_BASE_HPP_INCLUDED
|
||||
#define MOCK_MATCHER_BASE_HPP_INCLUDED
|
||||
|
||||
#include "move_helper.hpp"
|
||||
#include <ostream>
|
||||
|
||||
namespace mock { namespace detail {
|
||||
template<typename Signature>
|
||||
class matcher_base;
|
||||
|
||||
template<BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename T)>
|
||||
class matcher_base<void(BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T))>
|
||||
template<typename... Ts>
|
||||
class matcher_base
|
||||
{
|
||||
public:
|
||||
matcher_base() = default;
|
||||
|
|
@ -21,7 +22,7 @@ namespace mock { namespace detail {
|
|||
matcher_base& operator=(const matcher_base&) = delete;
|
||||
virtual ~matcher_base() = default;
|
||||
|
||||
virtual bool operator()(BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG, _)) = 0;
|
||||
virtual bool operator()(typename ref_arg<Ts>::type...) = 0;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const matcher_base& m)
|
||||
{
|
||||
|
|
@ -34,4 +35,4 @@ namespace mock { namespace detail {
|
|||
};
|
||||
}} // namespace mock::detail
|
||||
|
||||
#undef MOCK_REF_ARG
|
||||
#endif // MOCK_MATCHER_BASE_HPP_INCLUDED
|
||||
|
|
@ -6,8 +6,8 @@
|
|||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef MOCK_PARAMETER_HPP_INCLUDED
|
||||
#define MOCK_PARAMETER_HPP_INCLUDED
|
||||
#ifndef MOCK_SIGNATURE_TRAITS_HPP_INCLUDED
|
||||
#define MOCK_SIGNATURE_TRAITS_HPP_INCLUDED
|
||||
|
||||
#include "../config.hpp"
|
||||
#include <cstddef>
|
||||
|
|
@ -59,4 +59,4 @@ namespace mock { namespace detail {
|
|||
|
||||
}} // namespace mock::detail
|
||||
|
||||
#endif // MOCK_PARAMETER_HPP_INCLUDED
|
||||
#endif // MOCK_SIGNATURE_TRAITS_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ set(testsUsingUndefinedCPP test_function test_integration)
|
|||
foreach(testFile IN LISTS testFiles)
|
||||
get_filename_component(name ${testFile} NAME_WE)
|
||||
|
||||
foreach(testVariant IN ITEMS "" _max_args _use_conversions _thread_safe)
|
||||
foreach(testVariant IN ITEMS "" _use_conversions _thread_safe)
|
||||
set(curName ${name}${testVariant})
|
||||
add_executable(${curName} ${testFile})
|
||||
if(name IN_LIST testsUsingUndefinedCPP)
|
||||
|
|
@ -50,7 +50,6 @@ foreach(testFile IN LISTS testFiles)
|
|||
add_test(NAME ${curName} COMMAND ${curName})
|
||||
endforeach()
|
||||
|
||||
target_compile_definitions(${name}_max_args PRIVATE MOCK_MAX_ARGS=21)
|
||||
target_compile_definitions(${name}_use_conversions PRIVATE MOCK_USE_CONVERSIONS)
|
||||
|
||||
target_link_libraries(${name}_thread_safe PRIVATE Boost::thread)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ alias mock_inspect :
|
|||
rule run-test ( name )
|
||||
{
|
||||
run $(name) defined_1.cpp defined_2.cpp undefined.cpp /boost//unit_test_framework : : : : $(name)_ ;
|
||||
run $(name) undefined.cpp /boost//unit_test_framework : : : <define>MOCK_MAX_ARGS=21 : $(name)_max_args ;
|
||||
run $(name) undefined.cpp /boost//unit_test_framework : : : <define>MOCK_USE_CONVERSIONS : $(name)_use_conversions ;
|
||||
run $(name) undefined.cpp /boost//unit_test_framework /boost//thread : : : <define>MOCK_THREAD_SAFE <define>BOOST_THREAD_USES_MOVE <threading>multi : $(name)_thread_safe ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
// http://turtle.sourceforge.net
|
||||
//
|
||||
// Copyright Mathieu Champlon 2011
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <turtle/mock.hpp>
|
||||
|
||||
BOOST_STATIC_ASSERT(MOCK_MAX_ARGS == 9);
|
||||
|
||||
namespace {
|
||||
struct my_base
|
||||
{
|
||||
virtual ~my_base() = default;
|
||||
virtual void my_method(int, int, int, int, int, int, int, int, int, int) = 0;
|
||||
};
|
||||
|
||||
MOCK_BASE_CLASS(my_class, my_base)
|
||||
{
|
||||
MOCK_METHOD(my_method, 10)
|
||||
};
|
||||
} // namespace
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <turtle/detail/function.hpp>
|
||||
#include <turtle/detail/expectation.hpp>
|
||||
#include <turtle/matcher.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <functional>
|
||||
|
|
@ -88,16 +88,16 @@ std::string serialize(const T& t)
|
|||
BOOST_AUTO_TEST_CASE(default_matcher_is_serialized_to_any)
|
||||
{
|
||||
using mock::detail::default_matcher;
|
||||
BOOST_TEST(serialize(default_matcher<void()>{}) == "");
|
||||
BOOST_TEST(serialize(default_matcher<void(int)>{}) == "any");
|
||||
BOOST_TEST(serialize(default_matcher<void(int, int)>{}) == "any, any");
|
||||
BOOST_TEST(serialize(default_matcher<void(int, int, int, int, int)>{}) == "any, any, any, any, any");
|
||||
BOOST_TEST(serialize(default_matcher<>{}) == "");
|
||||
BOOST_TEST(serialize(default_matcher<int>{}) == "any");
|
||||
BOOST_TEST(serialize(default_matcher<int, int>{}) == "any, any");
|
||||
BOOST_TEST(serialize(default_matcher<int, int, int, int, int>{}) == "any, any, any, any, any");
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct custom_constraint
|
||||
{
|
||||
int expected_ = 42;
|
||||
int expected_;
|
||||
custom_constraint(int expected = 42) : expected_(expected) {}
|
||||
friend std::ostream& operator<<(std::ostream& s, const custom_constraint& c)
|
||||
{
|
||||
|
|
@ -110,16 +110,15 @@ struct custom_constraint
|
|||
BOOST_AUTO_TEST_CASE(single_matcher_serializes)
|
||||
{
|
||||
using mock::detail::single_matcher;
|
||||
BOOST_TEST(serialize(single_matcher<void(int), void(int)>(1)) == "1");
|
||||
BOOST_TEST(serialize(single_matcher<void(int, int), void(int, int)>(1, 2)) == "1, 2");
|
||||
BOOST_TEST(serialize(single_matcher<void(int), int>(1)) == "1");
|
||||
BOOST_TEST(serialize(single_matcher<void(int, int), int, int>(1, 2)) == "1, 2");
|
||||
BOOST_TEST(
|
||||
serialize(
|
||||
single_matcher<void(int, int, mock::constraint<custom_constraint>, int, int), void(int, int, int, int, int)>(
|
||||
serialize(single_matcher<void(int, int, mock::constraint<custom_constraint>, int, int), int, int, int, int, int>(
|
||||
1, 2, custom_constraint(), 4, 5)) == "1, 2, custom42, 4, 5");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(multi_matcher_serializes)
|
||||
{
|
||||
using mock::detail::multi_matcher;
|
||||
BOOST_TEST(serialize(multi_matcher<custom_constraint, void(int)>(custom_constraint(1337))) == "custom1337");
|
||||
BOOST_TEST(serialize(multi_matcher<custom_constraint, int>(custom_constraint(1337))) == "custom1337");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,28 +11,30 @@
|
|||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#define IDENTITY(z, n, d) d
|
||||
#define IDENTITY(z, n, text) text
|
||||
// Number of arguments is (now) unlimited, so take any high value here
|
||||
#define NUM_TEST_ARGS 100
|
||||
|
||||
namespace {
|
||||
struct my_custom_mock
|
||||
{
|
||||
MOCK_METHOD(method, MOCK_MAX_ARGS, void(BOOST_PP_ENUM(MOCK_MAX_ARGS, IDENTITY, int)), tag)
|
||||
MOCK_METHOD(method2, MOCK_MAX_ARGS, int(BOOST_PP_ENUM(MOCK_MAX_ARGS, IDENTITY, int)), tag_2)
|
||||
MOCK_METHOD(method, NUM_TEST_ARGS, void(BOOST_PP_ENUM(NUM_TEST_ARGS, IDENTITY, int)), tag)
|
||||
MOCK_METHOD(method2, NUM_TEST_ARGS, int(BOOST_PP_ENUM(NUM_TEST_ARGS, IDENTITY, int)), tag_2)
|
||||
};
|
||||
} // namespace
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(call_mock_method_with_max_number_of_args, mock_error_fixture)
|
||||
{
|
||||
my_custom_mock m;
|
||||
MOCK_EXPECT(m.tag).once().with(BOOST_PP_ENUM(MOCK_MAX_ARGS, IDENTITY, 0));
|
||||
m.method(BOOST_PP_ENUM(MOCK_MAX_ARGS, IDENTITY, 0));
|
||||
MOCK_EXPECT(m.tag).once().with(BOOST_PP_ENUM(NUM_TEST_ARGS, IDENTITY, 0));
|
||||
m.method(BOOST_PP_ENUM(NUM_TEST_ARGS, IDENTITY, 0));
|
||||
CHECK_CALLS(1);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(call_mock_method_with_max_number_of_args_and_a_return_value, mock_error_fixture)
|
||||
{
|
||||
my_custom_mock m;
|
||||
MOCK_EXPECT(m.tag_2).once().with(BOOST_PP_ENUM(MOCK_MAX_ARGS, IDENTITY, 0)).returns(42);
|
||||
BOOST_CHECK_EQUAL(42, m.method2(BOOST_PP_ENUM(MOCK_MAX_ARGS, IDENTITY, 0)));
|
||||
MOCK_EXPECT(m.tag_2).once().with(BOOST_PP_ENUM(NUM_TEST_ARGS, IDENTITY, 0)).returns(42);
|
||||
BOOST_CHECK_EQUAL(42, m.method2(BOOST_PP_ENUM(NUM_TEST_ARGS, IDENTITY, 0)));
|
||||
CHECK_CALLS(1);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue