committed by
Seth Hillbrand
55 changed files with 4435 additions and 0 deletions
-
3qa/qa_utils/include/qa_utils/wx_utils/unit_test_utils.h
-
1thirdparty/CMakeLists.txt
-
23thirdparty/turtle/BOOST.LICENSE_1_0.txt
-
3thirdparty/turtle/CMakeLists.txt
-
6thirdparty/turtle/README.txt
-
46thirdparty/turtle/turtle/catch.hpp
-
34thirdparty/turtle/turtle/cleanup.hpp
-
33thirdparty/turtle/turtle/config.hpp
-
188thirdparty/turtle/turtle/constraint.hpp
-
253thirdparty/turtle/turtle/constraints.hpp
-
137thirdparty/turtle/turtle/detail/action.hpp
-
36thirdparty/turtle/turtle/detail/addressof.hpp
-
47thirdparty/turtle/turtle/detail/child.hpp
-
42thirdparty/turtle/turtle/detail/context.hpp
-
183thirdparty/turtle/turtle/detail/expectation.hpp
-
276thirdparty/turtle/turtle/detail/expectation_template.hpp
-
41thirdparty/turtle/turtle/detail/formatter.hpp
-
81thirdparty/turtle/turtle/detail/function.hpp
-
361thirdparty/turtle/turtle/detail/function_impl.hpp
-
329thirdparty/turtle/turtle/detail/function_impl_template.hpp
-
11thirdparty/turtle/turtle/detail/function_iterate.hpp
-
106thirdparty/turtle/turtle/detail/function_template.hpp
-
54thirdparty/turtle/turtle/detail/functor.hpp
-
49thirdparty/turtle/turtle/detail/group.hpp
-
134thirdparty/turtle/turtle/detail/invocation.hpp
-
26thirdparty/turtle/turtle/detail/is_functor.hpp
-
38thirdparty/turtle/turtle/detail/matcher_base.hpp
-
42thirdparty/turtle/turtle/detail/matcher_base_template.hpp
-
113thirdparty/turtle/turtle/detail/mock_impl.hpp
-
78thirdparty/turtle/turtle/detail/move_helper.hpp
-
134thirdparty/turtle/turtle/detail/mutex.hpp
-
83thirdparty/turtle/turtle/detail/object_impl.hpp
-
34thirdparty/turtle/turtle/detail/parameter.hpp
-
40thirdparty/turtle/turtle/detail/parent.hpp
-
22thirdparty/turtle/turtle/detail/ref_arg.hpp
-
119thirdparty/turtle/turtle/detail/root.hpp
-
55thirdparty/turtle/turtle/detail/sequence_impl.hpp
-
77thirdparty/turtle/turtle/detail/signature.hpp
-
62thirdparty/turtle/turtle/detail/signature_traits.hpp
-
44thirdparty/turtle/turtle/detail/singleton.hpp
-
119thirdparty/turtle/turtle/detail/type_name.hpp
-
29thirdparty/turtle/turtle/detail/verifiable.hpp
-
23thirdparty/turtle/turtle/detail/void_t.hpp
-
70thirdparty/turtle/turtle/error.hpp
-
23thirdparty/turtle/turtle/exception.hpp
-
24thirdparty/turtle/turtle/format.hpp
-
196thirdparty/turtle/turtle/log.hpp
-
74thirdparty/turtle/turtle/matcher.hpp
-
116thirdparty/turtle/turtle/mock.hpp
-
70thirdparty/turtle/turtle/object.hpp
-
33thirdparty/turtle/turtle/reset.hpp
-
26thirdparty/turtle/turtle/sequence.hpp
-
114thirdparty/turtle/turtle/stream.hpp
-
41thirdparty/turtle/turtle/unwrap_reference.hpp
-
33thirdparty/turtle/turtle/verify.hpp
@ -0,0 +1,23 @@ |
|||
Boost Software License - Version 1.0 - August 17th, 2003 |
|||
|
|||
Permission is hereby granted, free of charge, to any person or organization |
|||
obtaining a copy of the software and accompanying documentation covered by |
|||
this license (the "Software") to use, reproduce, display, distribute, |
|||
execute, and transmit the Software, and to prepare derivative works of the |
|||
Software, and to permit third-parties to whom the Software is furnished to |
|||
do so, all subject to the following: |
|||
|
|||
The copyright notices in the Software and this entire statement, including |
|||
the above license grant, this restriction and the following disclaimer, |
|||
must be included in all copies of the Software, in whole or in part, and |
|||
all derivative works of the Software, unless such copies or derivative |
|||
works are solely in the form of machine-executable object code generated by |
|||
a source language processor. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT |
|||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE |
|||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, |
|||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|||
DEALINGS IN THE SOFTWARE. |
@ -0,0 +1,3 @@ |
|||
add_library( turtle INTERFACE ) |
|||
|
|||
target_include_directories( turtle INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ) |
@ -0,0 +1,6 @@ |
|||
This directory contains the Turtle Mocking Framework version 1.3.2 (0dd0dfa15fbc2774213523fb3a65bc1acb2857b3) |
|||
from https://github.com/mat007/turtle |
|||
|
|||
Turtle is a C++ mock object library based on Boost with a focus on usability, simplicity and flexibility. |
|||
|
|||
Distributed under the Boost Software License, Version 1.0, with license text in this directory. |
@ -0,0 +1,46 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Mathieu Champlon and Ovanes Markarian 2017
|
|||
//
|
|||
// 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_CATCH_HPP_INCLUDED
|
|||
#define MOCK_CATCH_HPP_INCLUDED
|
|||
|
|||
#include <catch.hpp>
|
|||
|
|||
template<typename Result> |
|||
struct catch_mock_error_policy |
|||
{ |
|||
static Result abort() |
|||
{ |
|||
FAIL("Aborted"); |
|||
throw std::runtime_error("unreachable"); |
|||
} |
|||
|
|||
template<typename Context> |
|||
static void fail(const char* message, |
|||
const Context& context, |
|||
const char* file = "file://unknown-location", |
|||
int line = 0) |
|||
{ |
|||
CAPTURE(context); |
|||
FAIL_CHECK(message << " in: " << file << ":" << line); |
|||
} |
|||
|
|||
template<typename Context> |
|||
static void call(const Context& context, const char* file, int line) |
|||
{ |
|||
CAPTURE(context); |
|||
INFO(file << ":" << line); |
|||
} |
|||
|
|||
static void pass(const char* file, int line) { INFO(file << ":" << line); } |
|||
}; |
|||
|
|||
#define MOCK_ERROR_POLICY catch_mock_error_policy
|
|||
#include "mock.hpp"
|
|||
|
|||
#endif // MOCK_CATCH_HPP_INCLUDED
|
@ -0,0 +1,34 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_CLEANUP_HPP_INCLUDED
|
|||
#define MOCK_CLEANUP_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include "reset.hpp"
|
|||
#include "verify.hpp"
|
|||
#ifdef MOCK_USE_BOOST_TEST
|
|||
# include <boost/test/unit_test_suite.hpp>
|
|||
#endif
|
|||
|
|||
namespace mock { |
|||
struct cleanup |
|||
{ |
|||
~cleanup() { mock::reset(); } |
|||
}; |
|||
|
|||
#ifdef MOCK_USE_BOOST_TEST
|
|||
BOOST_GLOBAL_FIXTURE(cleanup) |
|||
# if BOOST_VERSION >= 105900
|
|||
; |
|||
# endif
|
|||
#endif
|
|||
|
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_CLEANUP_HPP_INCLUDED
|
@ -0,0 +1,33 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Mathieu Champlon 2009
|
|||
//
|
|||
// 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)
|
|||
|
|||
// boost-no-inspect
|
|||
|
|||
#ifndef MOCK_CONFIG_HPP_INCLUDED
|
|||
#define MOCK_CONFIG_HPP_INCLUDED
|
|||
|
|||
#include <boost/config.hpp>
|
|||
|
|||
#ifndef MOCK_ERROR_POLICY
|
|||
# define MOCK_ERROR_POLICY mock::error
|
|||
# define MOCK_USE_BOOST_TEST
|
|||
#endif
|
|||
|
|||
#if !defined(BOOST_NO_CXX11_HDR_MUTEX) && !defined(BOOST_NO_0X_HDR_MUTEX)
|
|||
# ifndef MOCK_NO_HDR_MUTEX
|
|||
# define MOCK_HDR_MUTEX
|
|||
# endif
|
|||
#endif
|
|||
|
|||
#if defined(__cpp_lib_uncaught_exceptions) || defined(_MSC_VER) && (_MSC_VER >= 1900)
|
|||
# ifndef MOCK_NO_UNCAUGHT_EXCEPTIONS
|
|||
# define MOCK_UNCAUGHT_EXCEPTIONS
|
|||
# endif
|
|||
#endif
|
|||
|
|||
#endif // MOCK_CONFIG_HPP_INCLUDED
|
@ -0,0 +1,188 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_CONSTRAINT_HPP_INCLUDED
|
|||
#define MOCK_CONSTRAINT_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include "log.hpp"
|
|||
#include "unwrap_reference.hpp"
|
|||
#include <boost/preprocessor/array.hpp>
|
|||
#include <boost/preprocessor/control/if.hpp>
|
|||
#include <boost/preprocessor/repetition/enum.hpp>
|
|||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
|||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
|||
#include <boost/preprocessor/stringize.hpp>
|
|||
#include <boost/preprocessor/variadic/size.hpp>
|
|||
#include <functional>
|
|||
#include <type_traits>
|
|||
|
|||
namespace mock { |
|||
template<typename Constraint> |
|||
struct constraint |
|||
{ |
|||
constraint() {} |
|||
constraint(const Constraint& c) : c_(c) {} |
|||
Constraint c_; |
|||
}; |
|||
|
|||
namespace detail { |
|||
template<typename Lhs, typename Rhs> |
|||
class and_ |
|||
{ |
|||
public: |
|||
and_(const Lhs& lhs, const Rhs& rhs) : lhs_(lhs), rhs_(rhs) {} |
|||
template<typename Actual> |
|||
bool operator()(const Actual& actual) const |
|||
{ |
|||
return lhs_(actual) && rhs_(actual); |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& s, const and_& a) |
|||
{ |
|||
return s << "( " << mock::format(a.lhs_) << " && " << mock::format(a.rhs_) << " )"; |
|||
} |
|||
|
|||
private: |
|||
Lhs lhs_; |
|||
Rhs rhs_; |
|||
}; |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
class or_ |
|||
{ |
|||
public: |
|||
or_(const Lhs& lhs, const Rhs& rhs) : lhs_(lhs), rhs_(rhs) {} |
|||
template<typename Actual> |
|||
bool operator()(const Actual& actual) const |
|||
{ |
|||
return lhs_(actual) || rhs_(actual); |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& s, const or_& o) |
|||
{ |
|||
return s << "( " << mock::format(o.lhs_) << " || " << mock::format(o.rhs_) << " )"; |
|||
} |
|||
|
|||
private: |
|||
Lhs lhs_; |
|||
Rhs rhs_; |
|||
}; |
|||
|
|||
template<typename Constraint> |
|||
class not_ |
|||
{ |
|||
public: |
|||
explicit not_(const Constraint& c) : c_(c) {} |
|||
template<typename Actual> |
|||
bool operator()(const Actual& actual) const |
|||
{ |
|||
return !c_(actual); |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& s, const not_& n) { return s << "! " << mock::format(n.c_); } |
|||
|
|||
private: |
|||
Constraint c_; |
|||
}; |
|||
} // namespace detail
|
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
const constraint<detail::or_<Lhs, Rhs>> operator||(const constraint<Lhs>& lhs, const constraint<Rhs>& rhs) |
|||
{ |
|||
return detail::or_<Lhs, Rhs>(lhs.c_, rhs.c_); |
|||
} |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
const constraint<detail::and_<Lhs, Rhs>> operator&&(const constraint<Lhs>& lhs, const constraint<Rhs>& rhs) |
|||
{ |
|||
return detail::and_<Lhs, Rhs>(lhs.c_, rhs.c_); |
|||
} |
|||
|
|||
template<typename Constraint> |
|||
const constraint<detail::not_<Constraint>> operator!(const constraint<Constraint>& c) |
|||
{ |
|||
return detail::not_<Constraint>(c.c_); |
|||
} |
|||
} // namespace mock
|
|||
|
|||
#define MOCK_UNARY_CONSTRAINT(Name, n, Args, Expr) \
|
|||
namespace detail { \ |
|||
struct Name \ |
|||
{ \ |
|||
template<typename Actual> \ |
|||
bool operator()(const Actual& actual) const \ |
|||
{ \ |
|||
(void)actual; \ |
|||
return Expr; \ |
|||
} \ |
|||
friend std::ostream& operator<<(std::ostream& s, const Name&) { return s << BOOST_STRINGIZE(Name); } \ |
|||
}; \ |
|||
} \ |
|||
const mock::constraint<detail::Name> Name; |
|||
|
|||
#define MOCK_CONSTRAINT_ASSIGN(z, n, d) expected##n(std::forward<T##n>(e##n))
|
|||
|
|||
#define MOCK_CONSTRAINT_UNWRAP_REF(z, n, d) mock::unwrap_ref(expected##n)
|
|||
|
|||
#define MOCK_CONSTRAINT_FORMAT(z, n, d) BOOST_PP_IF(n, << ", " <<, ) mock::format(c.expected##n)
|
|||
|
|||
#define MOCK_CONSTRAINT_MEMBER(z, n, d) Expected_##n expected##n;
|
|||
|
|||
#define MOCK_CONSTRAINT_TPL_TYPE(z, n, d) std::decay_t<const T##n>
|
|||
|
|||
#define MOCK_CONSTRAINT_CREF_PARAM(z, n, Args) \
|
|||
const mock::unwrap_reference_t<Expected_##n>& BOOST_PP_ARRAY_ELEM(n, Args) |
|||
|
|||
#define MOCK_CONSTRAINT_ARG(z, n, Args) T##n&& BOOST_PP_ARRAY_ELEM(n, Args)
|
|||
|
|||
#define MOCK_CONSTRAINT_ARGS(z, n, Args) T##n&& e##n
|
|||
|
|||
#define MOCK_CONSTRAINT_PARAM(z, n, Args) std::forward<T##n>(BOOST_PP_ARRAY_ELEM(n, Args))
|
|||
|
|||
#define MOCK_NARY_CONSTRAINT(Name, n, Args, Expr) \
|
|||
namespace detail { \ |
|||
template<BOOST_PP_ENUM_PARAMS(n, typename Expected_)> \ |
|||
struct Name \ |
|||
{ \ |
|||
template<BOOST_PP_ENUM_PARAMS(n, typename T)> \ |
|||
explicit Name(BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ARGS, _)) : BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ASSIGN, _) \ |
|||
{} \ |
|||
template<typename Actual> \ |
|||
bool operator()(const Actual& actual) const \ |
|||
{ \ |
|||
return test(actual, BOOST_PP_ENUM(n, MOCK_CONSTRAINT_UNWRAP_REF, _)); \ |
|||
} \ |
|||
template<typename Actual> \ |
|||
bool test(const Actual& actual, BOOST_PP_ENUM(n, MOCK_CONSTRAINT_CREF_PARAM, (n, Args))) const \ |
|||
{ \ |
|||
return Expr; \ |
|||
} \ |
|||
friend std::ostream& operator<<(std::ostream& s, const Name& c) \ |
|||
{ \ |
|||
return s << BOOST_STRINGIZE(Name) << "( " << BOOST_PP_REPEAT(n, MOCK_CONSTRAINT_FORMAT, _) << " )"; \ |
|||
} \ |
|||
BOOST_PP_REPEAT(n, MOCK_CONSTRAINT_MEMBER, _) \ |
|||
}; \ |
|||
} \ |
|||
template<BOOST_PP_ENUM_PARAMS(n, typename T)> \ |
|||
mock::constraint<detail::Name<BOOST_PP_ENUM(n, MOCK_CONSTRAINT_TPL_TYPE, _)>> Name( \ |
|||
BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ARG, (n, Args))) \ |
|||
{ \ |
|||
return detail::Name<BOOST_PP_ENUM(n, MOCK_CONSTRAINT_TPL_TYPE, _)>( \ |
|||
BOOST_PP_ENUM(n, MOCK_CONSTRAINT_PARAM, (n, Args))); \ |
|||
} |
|||
|
|||
#define MOCK_CONSTRAINT_EXT(Name, n, Args, Expr) \
|
|||
BOOST_PP_IF(n, MOCK_NARY_CONSTRAINT, MOCK_UNARY_CONSTRAINT)(Name, n, Args, Expr) |
|||
|
|||
#define MOCK_CONSTRAINT_AUX_AUX(Name, n, Array) \
|
|||
MOCK_CONSTRAINT_EXT(Name, n, BOOST_PP_ARRAY_TO_TUPLE(BOOST_PP_ARRAY_POP_BACK(Array)), BOOST_PP_ARRAY_ELEM(n, Array)) |
|||
|
|||
#define MOCK_CONSTRAINT_AUX(Name, Size, Tuple) MOCK_CONSTRAINT_AUX_AUX(Name, BOOST_PP_DEC(Size), (Size, Tuple))
|
|||
|
|||
#define MOCK_CONSTRAINT(Name, ...) MOCK_CONSTRAINT_AUX(Name, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), (__VA_ARGS__))
|
|||
|
|||
#endif // MOCK_CONSTRAINT_HPP_INCLUDED
|
@ -0,0 +1,253 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_CONSTRAINTS_HPP_INCLUDED
|
|||
#define MOCK_CONSTRAINTS_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include "constraint.hpp"
|
|||
#include "detail/void_t.hpp"
|
|||
#include "unwrap_reference.hpp"
|
|||
#include <boost/version.hpp>
|
|||
#if BOOST_VERSION >= 107000
|
|||
# include <boost/test/tools/floating_point_comparison.hpp>
|
|||
#else
|
|||
# include <boost/test/floating_point_comparison.hpp>
|
|||
#endif
|
|||
#include <functional>
|
|||
#include <memory>
|
|||
#include <type_traits>
|
|||
|
|||
namespace mock { |
|||
MOCK_UNARY_CONSTRAINT(any, 0, , ((void)actual, true)) |
|||
MOCK_UNARY_CONSTRAINT(affirm, 0, , !!actual) |
|||
MOCK_UNARY_CONSTRAINT(negate, 0, , !actual) |
|||
MOCK_UNARY_CONSTRAINT(evaluate, 0, , actual()) |
|||
|
|||
MOCK_NARY_CONSTRAINT(less, 1, (expected), actual < expected) |
|||
MOCK_NARY_CONSTRAINT(greater, 1, (expected), actual > expected) |
|||
MOCK_NARY_CONSTRAINT(less_equal, 1, (expected), actual <= expected) |
|||
MOCK_NARY_CONSTRAINT(greater_equal, 1, (expected), actual >= expected) |
|||
|
|||
#if BOOST_VERSION < 105900
|
|||
|
|||
# define MOCK_SMALL() boost::test_tools::check_is_small(actual, tolerance)
|
|||
# define MOCK_PERCENT_TOLERANCE() \
|
|||
boost::test_tools::check_is_close(actual, expected, boost::test_tools::percent_tolerance(tolerance)) |
|||
# define MOCK_FRACTION_TOLERANCE() \
|
|||
boost::test_tools::check_is_close(actual, expected, boost::test_tools::fraction_tolerance(tolerance)) |
|||
|
|||
#else // BOOST_VERSION < 105900
|
|||
|
|||
namespace detail { |
|||
template<typename T, typename Tolerance> |
|||
bool is_small(const T& t, const Tolerance& tolerance) |
|||
{ |
|||
return boost::math::fpc::small_with_tolerance<T>(tolerance)(t); |
|||
} |
|||
|
|||
template<typename T1, typename T2, typename Tolerance> |
|||
bool is_close(const T1& t1, const T2& t2, const Tolerance& tolerance) |
|||
{ |
|||
typedef std::common_type_t<T1, T2> common_type; |
|||
return boost::math::fpc::close_at_tolerance<common_type>(tolerance, boost::math::fpc::FPC_STRONG)(t1, t2); |
|||
} |
|||
} // namespace detail
|
|||
|
|||
# define MOCK_SMALL() detail::is_small(actual, tolerance)
|
|||
# define MOCK_PERCENT_TOLERANCE() detail::is_close(actual, expected, boost::math::fpc::percent_tolerance(tolerance))
|
|||
# define MOCK_FRACTION_TOLERANCE() detail::is_close(actual, expected, tolerance)
|
|||
|
|||
#endif // BOOST_VERSION < 105900
|
|||
|
|||
#ifdef small
|
|||
# pragma push_macro("small")
|
|||
# undef small
|
|||
# define MOCK_SMALL_DEFINED
|
|||
#endif
|
|||
MOCK_NARY_CONSTRAINT(small, 1, (tolerance), (MOCK_SMALL())) |
|||
#ifdef MOCK_SMALL_DEFINED
|
|||
# pragma pop_macro("small")
|
|||
#endif
|
|||
|
|||
MOCK_NARY_CONSTRAINT(close, 2, (expected, tolerance), (MOCK_PERCENT_TOLERANCE())) |
|||
|
|||
MOCK_NARY_CONSTRAINT(close_fraction, 2, (expected, tolerance), (MOCK_FRACTION_TOLERANCE())) |
|||
|
|||
#undef MOCK_PERCENT_TOLERANCE
|
|||
#undef MOCK_FRACTION_TOLERANCE
|
|||
|
|||
#ifdef near
|
|||
# pragma push_macro("near")
|
|||
# undef near
|
|||
# define MOCK_NEAR_DEFINED
|
|||
#endif
|
|||
MOCK_NARY_CONSTRAINT(near, 2, (expected, tolerance), std::abs(actual - expected) <= tolerance) |
|||
#ifdef MOCK_NEAR_DEFINED
|
|||
# pragma pop_macro("near")
|
|||
#endif
|
|||
|
|||
namespace detail { |
|||
template<class T, class U = T, class = void> |
|||
struct has_equal_to : std::false_type |
|||
{}; |
|||
|
|||
template<class T, class U> |
|||
struct has_equal_to<T, U, void_t<decltype(std::declval<T>() == std::declval<U>())>> : std::true_type |
|||
{}; |
|||
|
|||
template<typename Expected> |
|||
struct equal |
|||
{ |
|||
explicit equal(Expected expected) : expected_(expected) {} |
|||
template<typename Actual> |
|||
bool operator()(const Actual& actual, |
|||
std::enable_if_t<has_equal_to<Actual, unwrap_reference_t<Expected>>::value>* = 0) const |
|||
{ |
|||
return actual == unwrap_ref(expected_); |
|||
} |
|||
template<typename Actual> |
|||
bool operator()(const Actual& actual, |
|||
std::enable_if_t<!has_equal_to<Actual, unwrap_reference_t<Expected>>::value>* = 0) const |
|||
{ |
|||
return actual && *actual == unwrap_ref(expected_); |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& s, const equal& e) |
|||
{ |
|||
return s << "equal( " << mock::format(e.expected_) << " )"; |
|||
} |
|||
Expected expected_; |
|||
}; |
|||
|
|||
template<typename Expected> |
|||
struct same |
|||
{ |
|||
explicit same(const Expected& expected) : expected_(std::addressof(unwrap_ref(expected))) {} |
|||
template<typename Actual> |
|||
bool operator()(const Actual& actual) const |
|||
{ |
|||
return std::addressof(actual) == expected_; |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& os, const same& s) |
|||
{ |
|||
return os << "same( " << mock::format(*s.expected_) << " )"; |
|||
} |
|||
const unwrap_reference_t<Expected>* expected_; |
|||
}; |
|||
|
|||
template<typename Expected> |
|||
struct retrieve |
|||
{ |
|||
explicit retrieve(Expected& expected) : expected_(std::addressof(unwrap_ref(expected))) {} |
|||
template<typename Actual> |
|||
bool operator()( |
|||
const Actual& actual, |
|||
std::enable_if_t<!std::is_convertible<const Actual*, unwrap_reference_t<Expected>>::value>* = 0) const |
|||
{ |
|||
*expected_ = actual; |
|||
return true; |
|||
} |
|||
template<typename Actual> |
|||
bool operator()( |
|||
Actual&& actual, |
|||
std::enable_if_t<!std::is_convertible<const Actual*, unwrap_reference_t<Expected>>::value>* = 0) const |
|||
{ |
|||
*expected_ = std::move(actual); |
|||
return true; |
|||
} |
|||
template<typename Actual> |
|||
bool operator()(Actual& actual, |
|||
std::enable_if_t<std::is_convertible<Actual*, unwrap_reference_t<Expected>>::value>* = 0) const |
|||
{ |
|||
*expected_ = std::addressof(actual); |
|||
return true; |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& s, const retrieve& r) |
|||
{ |
|||
return s << "retrieve( " << mock::format(*r.expected_) << " )"; |
|||
} |
|||
unwrap_reference_t<Expected>* expected_; |
|||
}; |
|||
|
|||
template<typename Expected> |
|||
struct assign |
|||
{ |
|||
explicit assign(const Expected& expected) : expected_(expected) {} |
|||
template<typename Actual> |
|||
bool operator()(Actual& actual) const |
|||
{ |
|||
actual = unwrap_ref(expected_); |
|||
return true; |
|||
} |
|||
template<typename Actual> |
|||
bool operator()(Actual* actual, |
|||
std::enable_if_t<std::is_convertible<unwrap_reference_t<Expected>, Actual>::value>* = 0) const |
|||
{ |
|||
if(!actual) |
|||
return false; |
|||
*actual = unwrap_ref(expected_); |
|||
return true; |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& s, const assign& a) |
|||
{ |
|||
return s << "assign( " << mock::format(a.expected_) << " )"; |
|||
} |
|||
Expected expected_; |
|||
}; |
|||
|
|||
template<typename Expected> |
|||
struct contain |
|||
{ |
|||
explicit contain(const Expected& expected) : expected_(expected) {} |
|||
bool operator()(const std::string& actual) const |
|||
{ |
|||
return actual.find(unwrap_ref(expected_)) != std::string::npos; |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& s, const contain& n) |
|||
{ |
|||
return s << "contain( " << mock::format(n.expected_) << " )"; |
|||
} |
|||
Expected expected_; |
|||
}; |
|||
} // namespace detail
|
|||
|
|||
template<typename T> |
|||
constraint<detail::equal<T>> equal(T&& t) |
|||
{ |
|||
return detail::equal<T>(std::forward<T>(t)); |
|||
} |
|||
|
|||
template<typename T> |
|||
constraint<detail::same<T>> same(T& t) |
|||
{ |
|||
return detail::same<T>(t); |
|||
} |
|||
template<typename T> |
|||
constraint<detail::retrieve<T>> retrieve(T& t) |
|||
{ |
|||
return detail::retrieve<T>(t); |
|||
} |
|||
template<typename T> |
|||
constraint<detail::assign<T>> assign(T t) |
|||
{ |
|||
return detail::assign<T>(t); |
|||
} |
|||
template<typename T> |
|||
constraint<detail::contain<T>> contain(T t) |
|||
{ |
|||
return detail::contain<T>(t); |
|||
} |
|||
|
|||
template<typename T> |
|||
constraint<T> call(T t) |
|||
{ |
|||
return constraint<T>(t); |
|||
} |
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_CONSTRAINTS_HPP_INCLUDED
|
@ -0,0 +1,137 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_ACTION_HPP_INCLUDED
|
|||
#define MOCK_ACTION_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include <functional>
|
|||
#include <memory>
|
|||
#include <type_traits>
|
|||
|
|||
namespace mock { namespace detail { |
|||
template<typename Result, typename Signature> |
|||
class action_base |
|||
{ |
|||
private: |
|||
typedef std::function<Signature> functor_type; |
|||
typedef std::function<Result()> action_type; |
|||
|
|||
protected: |
|||
// Meant to be subclassed and not be directly used
|
|||
// Non-relocatable (contained functions may wrap references/pointers which could be invalidated)
|
|||
action_base() = default; |
|||
action_base(const action_base&) = delete; |
|||
action_base(action_base&&) = delete; |
|||
action_base& operator=(const action_base&) = delete; |
|||
action_base& operator=(action_base&&) = delete; |
|||
|
|||
public: |
|||
const functor_type& functor() const { return f_; } |
|||
bool valid() const { return f_ || a_; } |
|||
Result trigger() const { return a_(); } |
|||
|
|||
void calls(const functor_type& f) |
|||
{ |
|||
if(!f) |
|||
throw std::invalid_argument("null functor"); |
|||
f_ = f; |
|||
} |
|||
|
|||
template<typename Exception> |
|||
void throws(Exception e) |
|||
{ |
|||
a_ = [e]() -> Result { throw e; }; |
|||
} |
|||
|
|||
protected: |
|||
void set(const action_type& a) { a_ = a; } |
|||
template<typename Y> |
|||
void set(const std::reference_wrapper<Y>& r) |
|||
{ |
|||
a_ = [r]() -> Result { return r.get(); }; |
|||
} |
|||
|
|||
private: |
|||
functor_type f_; |
|||
action_type a_; |
|||
}; |
|||
|
|||
/// Type erased value storage
|
|||
struct value |
|||
{ |
|||
value() = default; |
|||
value(const value&) = delete; |
|||
value& operator=(const value&) = delete; |
|||
virtual ~value() = default; |
|||
}; |
|||
/// Actual value storage,
|
|||
/// holds an instance of T (stripped of reference qualifiers)
|
|||
template<typename T> |
|||
struct value_imp : value |
|||
{ |
|||
using type = std::remove_const_t<std::remove_reference_t<T>>; |
|||
|
|||
template<typename U> |
|||
value_imp(U&& t) : t_(std::forward<U>(t)) |
|||
{} |
|||
type t_; |
|||
}; |
|||
|
|||
template<typename Result, typename Signature> |
|||
class action : public action_base<Result, Signature> |
|||
{ |
|||
public: |
|||
template<typename Value> |
|||
void returns(const Value& v) |
|||
{ |
|||
this->set(std::ref(store(v))); |
|||
} |
|||
template<typename Y> |
|||
void returns(const std::reference_wrapper<Y>& r) |
|||
{ |
|||
this->set(r); |
|||
} |
|||
|
|||
template<typename Value> |
|||
void moves(Value&& v) |
|||
{ |
|||
auto vRef = std::ref(store(std::move(v))); |
|||
this->set([vRef]() { return std::move(vRef.get()); }); |
|||
} |
|||
|
|||
private: |
|||
template<typename T> |
|||
typename value_imp<T>::type& store(T&& t) |
|||
{ |
|||
v_ = std::make_unique<value_imp<T>>(std::forward<T>(t)); |
|||
return static_cast<value_imp<T>&>(*v_).t_; |
|||
} |
|||
template<typename T> |
|||
std::remove_reference_t<Result>& store(T* t) |
|||
{ |
|||
v_ = std::make_unique<value_imp<Result>>(t); |
|||
return static_cast<value_imp<Result>&>(*v_).t_; |
|||
} |
|||
|
|||
std::unique_ptr<value> v_; |
|||
}; |
|||
|
|||
template<typename Signature> |
|||
class action<void, Signature> : public action_base<void, Signature> |
|||
{ |
|||
public: |
|||
action() |
|||
{ |
|||
this->set([]() {}); |
|||
} |
|||
}; |
|||
|
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_ACTION_HPP_INCLUDED
|
@ -0,0 +1,36 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Mathieu Champlon 2013
|
|||
//
|
|||
// 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_ADDRESSOF_HPP_INCLUDED
|
|||
#define MOCK_ADDRESSOF_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include <boost/utility/addressof.hpp>
|
|||
|
|||
namespace mock |
|||
{ |
|||
namespace detail |
|||
{ |
|||
using boost::addressof; |
|||
|
|||
#ifdef MOCK_NULLPTR
|
|||
|
|||
inline const std::nullptr_t* addressof( const std::nullptr_t& p ) |
|||
{ |
|||
return &p; |
|||
} |
|||
inline std::nullptr_t* addressof( std::nullptr_t& p ) |
|||
{ |
|||
return &p; |
|||
} |
|||
|
|||
#endif
|
|||
} |
|||
} // mock
|
|||
|
|||
#endif // MOCK_ADDRESSOF_HPP_INCLUDED
|
@ -0,0 +1,47 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_CHILD_HPP_INCLUDED
|
|||
#define MOCK_CHILD_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "parent.hpp"
|
|||
#include "type_name.hpp"
|
|||
#include <boost/optional.hpp>
|
|||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
|||
#include <ostream>
|
|||
|
|||
namespace mock { namespace detail { |
|||
class child |
|||
{ |
|||
public: |
|||
child() : parent_(0) {} |
|||
void update(parent& p, |
|||
boost::unit_test::const_string instance, |
|||
boost::optional<type_name> type, |
|||
boost::unit_test::const_string name) |
|||
{ |
|||
if(instance != "?." || name_.empty()) |
|||
p = parent(instance, type); |
|||
parent_ = &p; |
|||
name_ = name; |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& s, const child& c) |
|||
{ |
|||
if(c.parent_) |
|||
s << *c.parent_; |
|||
return s << c.name_; |
|||
} |
|||
|
|||
private: |
|||
const parent* parent_; |
|||
boost::unit_test::const_string name_; |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_CHILD_HPP_INCLUDED
|
@ -0,0 +1,42 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_CONTEXT_HPP_INCLUDED
|
|||
#define MOCK_CONTEXT_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "type_name.hpp"
|
|||
#include <boost/optional.hpp>
|
|||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
|||
#include <ostream>
|
|||
|
|||
namespace mock { namespace detail { |
|||
class verifiable; |
|||
|
|||
class context |
|||
{ |
|||
public: |
|||
context() = default; |
|||
context(const context&) = delete; |
|||
context& operator=(const context&) = delete; |
|||
|
|||
virtual ~context() = default; |
|||
|
|||
virtual void add(const void* p, |
|||
verifiable& v, |
|||
boost::unit_test::const_string instance, |
|||
boost::optional<type_name> type, |
|||
boost::unit_test::const_string name) = 0; |
|||
virtual void add(verifiable& v) = 0; |
|||
virtual void remove(verifiable& v) = 0; |
|||
|
|||
virtual void serialize(std::ostream& s, const verifiable& v) const = 0; |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_CONTEXT_HPP_INCLUDED
|
@ -0,0 +1,183 @@ |
|||
// 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()(ref_arg_t<Args>...) override { return true; } |
|||
void serialize(std::ostream& s) const override |
|||
{ |
|||
constexpr auto arity = sizeof...(Args); |
|||
for(unsigned i = 0; i < arity; ++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...>, ref_arg_t<Args>... t) |
|||
{ |
|||
using expander = bool[]; |
|||
bool result = true; |
|||
(void)expander{ result &= std::get<I>(matchers_)(static_cast<ref_arg_t<Args>>(t))... }; |
|||
return result; |
|||
} |
|||
bool operator()(ref_arg_t<Args>... t) override |
|||
{ |
|||
return is_valid_impl(std::make_index_sequence<sizeof...(Args)>{}, static_cast<ref_arg_t<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()(ref_arg_t<Args>... t) override { return f_(static_cast<ref_arg_t<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 std::size_t 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 > 0u) && sizeof...(Constraints) == arity> with(Constraints... c) |
|||
{ |
|||
matcher_ = std::make_unique<single_matcher<void(Constraints...), Args...>>(c...); |
|||
} |
|||
template<typename Constraint, std::size_t Arity = arity> |
|||
std::enable_if_t<(Arity > 1u)> with(const Constraint& c) |
|||
{ |
|||
matcher_ = std::make_unique<multi_matcher<Constraint, Args...>>(c); |
|||
} |
|||
|
|||
void add(sequence& s) |
|||
{ |
|||
s.impl_->add(this); |
|||
sequences_.push_back(s.impl_); |
|||
} |
|||
|
|||
bool verify() const { return invocation_->verify(); } |
|||
|
|||
bool is_valid(ref_arg_t<Args>... t) const |
|||
{ |
|||
return !invocation_->exhausted() && (*matcher_)(static_cast<ref_arg_t<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
|
@ -0,0 +1,276 @@ |
|||
// 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##_( mock::detail::move_if_not_lvalue_reference< 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) \
|
|||
mock::detail::move_if_not_lvalue_reference< 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_( boost::make_shared< unlimited >() ) |
|||
, matcher_( |
|||
boost::make_shared< |
|||
default_matcher< |
|||
void( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) |
|||
> |
|||
> () ) |
|||
, file_( "unknown location" ) |
|||
, line_( 0 ) |
|||
{} |
|||
expectation( const char* file, int line ) |
|||
: invocation_( boost::make_shared< unlimited >() ) |
|||
, matcher_( |
|||
boost::make_shared< |
|||
default_matcher< |
|||
void( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) |
|||
> |
|||
> () ) |
|||
, file_( file ) |
|||
, line_( line ) |
|||
{} |
|||
|
|||
~expectation() |
|||
{ |
|||
for( sequences_cit it = sequences_.begin(); |
|||
it != sequences_.end(); ++it ) |
|||
(*it)->remove( this ); |
|||
} |
|||
|
|||
void invoke( const boost::shared_ptr< invocation >& i ) |
|||
{ |
|||
invocation_ = 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_.reset( |
|||
new 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_.reset( |
|||
new 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( sequences_cit it = sequences_.begin(); |
|||
it != sequences_.end(); ++it ) |
|||
if( ! (*it)->is_valid( this ) ) |
|||
return false; |
|||
bool result = invocation_->invoke(); |
|||
for( sequences_cit it = sequences_.begin(); |
|||
it != sequences_.end(); ++it ) |
|||
(*it)->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: |
|||
typedef std::vector< |
|||
boost::shared_ptr< sequence_impl > |
|||
> sequences_type; |
|||
typedef sequences_type::const_iterator sequences_cit; |
|||
|
|||
boost::shared_ptr< invocation > invocation_; |
|||
boost::shared_ptr< |
|||
matcher_base< |
|||
void( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) |
|||
> |
|||
> matcher_; |
|||
sequences_type sequences_; |
|||
const char* file_; |
|||
int line_; |
|||
}; |
|||
} |
|||
} // mock
|
|||
|
|||
#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
|
@ -0,0 +1,41 @@ |
|||
// 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_FORMATTER_HPP_INCLUDED
|
|||
#define MOCK_FORMATTER_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "../stream.hpp"
|
|||
#include <memory>
|
|||
|
|||
namespace mock { namespace detail { |
|||
template<typename T> |
|||
struct formatter |
|||
{ |
|||
explicit formatter(const T& t) : t_(std::addressof(t)) {} |
|||
void serialize(stream& s) const { detail::serialize(s, *t_); } |
|||
const T* t_; |
|||
}; |
|||
|
|||
template<typename T> |
|||
stream& operator<<(stream& s, const formatter<T>& f) |
|||
{ |
|||
f.serialize(s); |
|||
return s; |
|||
} |
|||
|
|||
template<typename T> |
|||
std::ostream& operator<<(std::ostream& s, const formatter<T>& f) |
|||
{ |
|||
stream ss(s); |
|||
f.serialize(ss); |
|||
return s; |
|||
} |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_FORMATTER_HPP_INCLUDED
|
@ -0,0 +1,81 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_FUNCTION_HPP_INCLUDED
|
|||
#define MOCK_FUNCTION_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "../log.hpp"
|
|||
#include "../sequence.hpp"
|
|||
#include "context.hpp"
|
|||
#include "function_impl.hpp"
|
|||
#include "type_name.hpp"
|
|||
#include <boost/optional.hpp>
|
|||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
|||
#include <ostream>
|
|||
|
|||
namespace mock { namespace detail { |
|||
template<typename Signature> |
|||
class function; |
|||
|
|||
template<typename R, typename... Ts> |
|||
class function<R(Ts...)> |
|||
{ |
|||
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(); |
|||
} |
|||
|
|||
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()(Ts... args) const { return (*impl_)(static_cast<ref_arg_t<Ts>>(args)...); } |
|||
|
|||
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
|
|||
|
|||
#endif // MOCK_FUNCTION_HPP_INCLUDED
|
@ -0,0 +1,361 @@ |
|||
// 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_FUNCTION_IMPL_HPP_INCLUDED
|
|||
#define MOCK_FUNCTION_IMPL_HPP_INCLUDED
|
|||
|
|||
#include "../error.hpp"
|
|||
#include "expectation.hpp"
|
|||
#include "mutex.hpp"
|
|||
#include "verifiable.hpp"
|
|||
#include <boost/test/utils/lazy_ostream.hpp>
|
|||
#include <list>
|
|||
#include <memory>
|
|||
|
|||
#ifndef MOCK_ERROR_POLICY
|
|||
# error no error policy has been set
|
|||
#endif
|
|||
|
|||
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... Arg> |
|||
class lazy_args; |
|||
|
|||
template<typename Signature> |
|||
class function_impl; |
|||
|
|||
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; |
|||
|
|||
public: |
|||
function_impl() : context_(0), valid_(true), exceptions_(exceptions()), mutex_(std::make_shared<mutex>()) {} |
|||
virtual ~function_impl() |
|||
{ |
|||
if(valid_ && exceptions_ >= exceptions()) |
|||
{ |
|||
for(const auto& expectation : expectations_) |
|||
{ |
|||
if(!expectation.verify()) |
|||
{ |
|||
error_type::fail("untriggered expectation", |
|||
boost::unit_test::lazy_ostream::instance() |
|||
<< lazy_context(this) << lazy_expectations(this), |
|||
expectation.file(), |
|||
expectation.line()); |
|||
} |
|||
} |
|||
} |
|||
if(context_) |
|||
context_->remove(*this); |
|||
} |
|||
|
|||
virtual bool verify() const |
|||
{ |
|||
lock _(mutex_); |
|||
for(const auto& expectation : expectations_) |
|||
{ |
|||
if(!expectation.verify()) |
|||
{ |
|||
valid_ = false; |
|||
error_type::fail("verification failed", |
|||
boost::unit_test::lazy_ostream::instance() |
|||
<< lazy_context(this) << lazy_expectations(this), |
|||
expectation.file(), |
|||
expectation.line()); |
|||
} |
|||
} |
|||
return valid_; |
|||
} |
|||
|
|||
virtual void reset() |
|||
{ |
|||
lock _(mutex_); |
|||
valid_ = true; |
|||
std::shared_ptr<function_impl> guard = this->shared_from_this(); |
|||
expectations_.clear(); |
|||
} |
|||
|
|||
private: |
|||
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 std::size_t arity = sizeof...(Args); |
|||
|
|||
public: |
|||
wrapper(const std::shared_ptr<mutex>& m, expectation_type& e) : base_type(e), lock_(m) {} |
|||
wrapper(const wrapper&) = delete; |
|||
wrapper(wrapper&& x) = default; |
|||
wrapper& operator=(const wrapper&) = delete; |
|||
wrapper& operator=(wrapper&& x) = default; |
|||
wrapper& once() |
|||
{ |
|||
this->e_->invoke(std::make_unique<detail::once>()); |
|||
return *this; |
|||
} |
|||
wrapper& never() |
|||
{ |
|||
this->e_->invoke(std::make_unique<detail::never>()); |
|||
return *this; |
|||
} |
|||
wrapper& exactly(std::size_t count) |
|||
{ |
|||
this->e_->invoke(std::make_unique<detail::exactly>(count)); |
|||
return *this; |
|||
} |
|||
wrapper& at_least(std::size_t min) |
|||
{ |
|||
this->e_->invoke(std::make_unique<detail::at_least>(min)); |
|||
return *this; |
|||
} |
|||
wrapper& at_most(std::size_t max) |
|||
{ |
|||
this->e_->invoke(std::make_unique<detail::at_most>(max)); |
|||
return *this; |
|||
} |
|||
wrapper& between(std::size_t min, std::size_t max) |
|||
{ |
|||
this->e_->invoke(std::make_unique<detail::between>(min, max)); |
|||
return *this; |
|||
} |
|||
|
|||
/// 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(c...); |
|||
return *this; |
|||
} |
|||
|
|||
/// Ensure the expectation is met in the given sequence(s)
|
|||
template<class... MockSequences> |
|||
wrapper& in(sequence& s0, MockSequences&... s) |
|||
{ |
|||
using expander = int[]; |
|||
(void)expander{ (this->e_->add(s0), 0), (this->e_->add(s), 0)... }; |
|||
return *this; |
|||
} |
|||
|
|||
template<typename TT> |
|||
void calls(TT t) |
|||
{ |
|||
this->e_->calls(t); |
|||
} |
|||
template<typename TT> |
|||
void throws(TT t) |
|||
{ |
|||
this->e_->throws(t); |
|||
} |
|||
template<typename TT> |
|||
void moves(TT&& t) |
|||
{ |
|||
this->e_->moves(std::move(t)); |
|||
} |
|||
|
|||
lock lock_; |
|||
}; |
|||
|
|||
public: |
|||
typedef wrapper wrapper_type; |
|||
|
|||
wrapper expect(const char* file, int line) |
|||
{ |
|||
lock _(mutex_); |
|||
expectations_.emplace_back(file, line); |
|||
valid_ = true; |
|||
return wrapper(mutex_, expectations_.back()); |
|||
} |
|||
wrapper expect() |
|||
{ |
|||
lock _(mutex_); |
|||
expectations_.emplace_back(); |
|||
valid_ = true; |
|||
return wrapper(mutex_, expectations_.back()); |
|||
} |
|||
|
|||
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...>(args...) << lazy_expectations(this) |
|||
|
|||
lock _(mutex_); |
|||
valid_ = false; |
|||
for(const auto& expectation : expectations_) |
|||
{ |
|||
if(expectation.is_valid(static_cast<ref_arg_t<Args>>(args)...)) |
|||
{ |
|||
if(!expectation.invoke()) |
|||
{ |
|||
error_type::fail( |
|||
"sequence failed", MOCK_FUNCTION_CONTEXT, expectation.file(), expectation.line()); |
|||
return error_type::abort(); |
|||
} |
|||
if(!expectation.valid()) |
|||
{ |
|||
error_type::fail( |
|||
"missing action", MOCK_FUNCTION_CONTEXT, expectation.file(), expectation.line()); |
|||
return error_type::abort(); |
|||
} |
|||
valid_ = true; |
|||
error_type::call(MOCK_FUNCTION_CONTEXT, expectation.file(), expectation.line()); |
|||
if(expectation.functor()) |
|||
return expectation.functor()(static_cast<ref_arg_t<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, |
|||
const void* p, |
|||
boost::unit_test::const_string instance, |
|||
boost::optional<type_name> type, |
|||
boost::unit_test::const_string name) |
|||
{ |
|||
lock _(mutex_); |
|||
if(!context_) |
|||
c.add(*this); |
|||
c.add(p, *this, instance, type, name); |
|||
context_ = &c; |
|||
} |
|||
|
|||
friend std::ostream& operator<<(std::ostream& s, const function_impl& impl) |
|||
{ |
|||
lock _(impl.mutex_); |
|||
return s << lazy_context(&impl) << lazy_expectations(&impl); |
|||
} |
|||
|
|||
struct lazy_context |
|||
{ |
|||
lazy_context(const function_impl* impl) : impl_(impl) {} |
|||
friend std::ostream& operator<<(std::ostream& s, const lazy_context& c) |
|||
{ |
|||
if(c.impl_->context_) |
|||
c.impl_->context_->serialize(s, *c.impl_); |
|||
else |
|||
s << '?'; |
|||
return s; |
|||
} |
|||
const function_impl* impl_; |
|||
}; |
|||
|
|||
struct lazy_expectations |
|||
{ |
|||
lazy_expectations(const function_impl* impl) : impl_(impl) {} |
|||
friend std::ostream& operator<<(std::ostream& s, const lazy_expectations& e) |
|||
{ |
|||
for(const auto& expectation : e.impl_->expectations_) |
|||
s << std::endl << expectation; |
|||
return s; |
|||
} |
|||
const function_impl* impl_; |
|||
}; |
|||
|
|||
std::list<expectation_type> expectations_; |
|||
context* context_; |
|||
mutable bool valid_; |
|||
const int exceptions_; |
|||
const std::shared_ptr<mutex> mutex_; |
|||
}; |
|||
|
|||
template<typename ArgFirst, typename... ArgRest> |
|||
class lazy_args<ArgFirst, ArgRest...> : lazy_args<ArgRest...> |
|||
{ |
|||
ArgFirst& arg_; |
|||
|
|||
public: |
|||
lazy_args(ArgFirst& arg, std::add_lvalue_reference_t<ArgRest>... args) |
|||
: lazy_args<ArgRest...>(args...), arg_(arg) |
|||
{} |
|||
std::ostream& print(std::ostream& s) const |
|||
{ |
|||
s << ' ' << mock::format(arg_) << ','; |
|||
return lazy_args<ArgRest...>::print(s); |
|||
} |
|||
}; |
|||
template<typename ArgFirst> |
|||
class lazy_args<ArgFirst> |
|||
{ |
|||
ArgFirst& arg_; |
|||
|
|||
public: |
|||
lazy_args(ArgFirst& arg) : arg_(arg) {} |
|||
std::ostream& print(std::ostream& s) const { return s << ' ' << mock::format(arg_) << ' '; } |
|||
}; |
|||
template<> |
|||
class lazy_args<> |
|||
{ |
|||
public: |
|||
std::ostream& print(std::ostream& s) const { return s; } |
|||
}; |
|||
template<typename... Args> |
|||
std::ostream& operator<<(std::ostream& s, const lazy_args<Args...>& a) |
|||
{ |
|||
s << '('; |
|||
return a.print(s) << ')'; |
|||
} |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_FUNCTION_IMPL_HPP_INCLUDED
|
@ -0,0 +1,329 @@ |
|||
// 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 "expectation_template.hpp"
|
|||
|
|||
#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_MOVE(z, n, d) \
|
|||
mock::detail::move_if_not_lvalue_reference< T##n >( t##n ) |
|||
|
|||
namespace mock |
|||
{ |
|||
namespace detail |
|||
{ |
|||
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 boost::enable_shared_from_this< |
|||
function_impl< R ( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) )> > |
|||
{ |
|||
public: |
|||
typedef safe_error< R, MOCK_ERROR_POLICY< R > > error_type; |
|||
|
|||
public: |
|||
function_impl() |
|||
: context_( 0 ) |
|||
, valid_( true ) |
|||
, exceptions_( exceptions() ) |
|||
, mutex_( boost::make_shared< mutex >() ) |
|||
{} |
|||
virtual ~function_impl() |
|||
{ |
|||
if( valid_ && exceptions_ >= exceptions() ) |
|||
for( expectations_cit it = expectations_.begin(); |
|||
it != expectations_.end(); ++it ) |
|||
if( ! it->verify() ) |
|||
error_type::fail( "untriggered expectation", |
|||
boost::unit_test::lazy_ostream::instance() |
|||
<< lazy_context( this ) |
|||
<< lazy_expectations( this ), |
|||
it->file(), it->line() ); |
|||
if( context_ ) |
|||
context_->remove( *this ); |
|||
} |
|||
|
|||
virtual bool verify() const |
|||
{ |
|||
lock _( mutex_ ); |
|||
for( expectations_cit it = expectations_.begin(); |
|||
it != expectations_.end(); ++it ) |
|||
if( ! it->verify() ) |
|||
{ |
|||
valid_ = false; |
|||
error_type::fail( "verification failed", |
|||
boost::unit_test::lazy_ostream::instance() |
|||
<< lazy_context( this ) |
|||
<< lazy_expectations( this ), |
|||
it->file(), it->line() ); |
|||
} |
|||
return valid_; |
|||
} |
|||
|
|||
virtual void reset() |
|||
{ |
|||
lock _( mutex_ ); |
|||
valid_ = true; |
|||
boost::shared_ptr< function_impl > guard = |
|||
this->shared_from_this(); |
|||
expectations_.clear(); |
|||
} |
|||
|
|||
private: |
|||
typedef expectation< |
|||
R( BOOST_PP_ENUM_PARAMS( MOCK_NUM_ARGS, T ) ) |
|||
> expectation_type; |
|||
|
|||
class wrapper : public wrapper_base< R, expectation_type > |
|||
{ |
|||
private: |
|||
typedef wrapper_base< R, expectation_type > base_type; |
|||
BOOST_MOVABLE_BUT_NOT_COPYABLE(wrapper) |
|||
|
|||
public: |
|||
wrapper( const boost::shared_ptr< mutex >& m, expectation_type& e ) |
|||
: base_type( e ) |
|||
, lock_( m ) |
|||
{} |
|||
wrapper( BOOST_RV_REF( wrapper ) x ) |
|||
: base_type( x ) |
|||
, lock_( boost::move( x.lock_) ) |
|||
{} |
|||
wrapper& operator=( BOOST_RV_REF( wrapper ) x ) |
|||
{ |
|||
static_cast< base_type& >( *this ) = x; |
|||
lock_ = boost::move( x.lock_ ); |
|||
return *this; |
|||
} |
|||
wrapper& once() |
|||
{ |
|||
this->e_->invoke( boost::make_shared< detail::once >() ); |
|||
return *this; |
|||
} |
|||
wrapper& never() |
|||
{ |
|||
this->e_->invoke( boost::make_shared< detail::never >() ); |
|||
return *this; |
|||
} |
|||
wrapper& exactly( std::size_t count ) |
|||
{ |
|||
this->e_->invoke( |
|||
boost::make_shared< detail::exactly >( count ) ); |
|||
return *this; |
|||
} |
|||
wrapper& at_least( std::size_t min ) |
|||
{ |
|||
this->e_->invoke( |
|||
boost::make_shared< detail::at_least >( min ) ); |
|||
return *this; |
|||
} |
|||
wrapper& at_most( std::size_t max ) |
|||
{ |
|||
this->e_->invoke( |
|||
boost::make_shared< detail::at_most >( max ) ); |
|||
return *this; |
|||
} |
|||
wrapper& between( std::size_t min, std::size_t max ) |
|||
{ |
|||
this->e_->invoke( |
|||
boost::make_shared< detail::between >( min, max ) ); |
|||
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) ) |
|||
{ |
|||
this->e_->with( |
|||
BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, 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) \
|
|||
wrapper& in( BOOST_PP_ENUM_PARAMS(n, sequence& s) ) \ |
|||
{ \ |
|||
BOOST_PP_REPEAT(n, MOCK_FUNCTION_IN_ADD, _) \ |
|||
return *this; \ |
|||
} |
|||
|
|||
BOOST_PP_REPEAT(MOCK_MAX_SEQUENCES, |
|||
MOCK_FUNCTION_IN, _) |
|||
|
|||
#undef MOCK_FUNCTION_IN
|
|||
#undef MOCK_FUNCTION_IN_ADD
|
|||
|
|||
template< typename TT > |
|||
void calls( TT t ) |
|||
{ |
|||
this->e_->calls( t ); |
|||
} |
|||
template< typename TT > |
|||
void throws( TT t ) |
|||
{ |
|||
this->e_->throws( t ); |
|||
} |
|||
template< typename TT > |
|||
void moves( BOOST_RV_REF(TT) t ) |
|||
{ |
|||
this->e_->moves( boost::move( t ) ); |
|||
} |
|||
|
|||
lock lock_; |
|||
}; |
|||
|
|||
public: |
|||
typedef wrapper wrapper_type; |
|||
|
|||
wrapper expect( const char* file, int line ) |
|||
{ |
|||
lock _( mutex_ ); |
|||
expectations_.push_back( expectation_type( file, line ) ); |
|||
valid_ = true; |
|||
return wrapper( mutex_, expectations_.back() ); |
|||
} |
|||
wrapper expect() |
|||
{ |
|||
lock _( mutex_ ); |
|||
expectations_.push_back( expectation_type() ); |
|||
valid_ = true; |
|||
return wrapper( mutex_, expectations_.back() ); |
|||
} |
|||
|
|||
R operator()( |
|||
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, t) ) const |
|||
{ |
|||
lock _( mutex_ ); |
|||
valid_ = false; |
|||
for( expectations_cit it = expectations_.begin(); |
|||
it != expectations_.end(); ++it ) |
|||
if( it->is_valid( |
|||
BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_MOVE, _) ) ) |
|||
{ |
|||
if( ! it->invoke() ) |
|||
{ |
|||
error_type::fail( "sequence failed", |
|||
MOCK_FUNCTION_CONTEXT, it->file(), it->line() ); |
|||
return error_type::abort(); |
|||
} |
|||
if( ! it->valid() ) |
|||
{ |
|||
error_type::fail( "missing action", |
|||
MOCK_FUNCTION_CONTEXT, it->file(), it->line() ); |
|||
return error_type::abort(); |
|||
} |
|||
valid_ = true; |
|||
error_type::call( |
|||
MOCK_FUNCTION_CONTEXT, it->file(), it->line() ); |
|||
if( it->functor() ) |
|||
return it->functor()( |
|||
BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_MOVE, _) ); |
|||
return it->trigger(); |
|||
} |
|||
error_type::fail( "unexpected call", MOCK_FUNCTION_CONTEXT ); |
|||
return error_type::abort(); |
|||
} |
|||
|
|||
void add( context& c, const void* p, |
|||
boost::unit_test::const_string instance, |
|||
boost::optional< type_name > type, |
|||
boost::unit_test::const_string name ) |
|||
{ |
|||
lock _( mutex_ ); |
|||
if( ! context_ ) |
|||
c.add( *this ); |
|||
c.add( p, *this, instance, type, name ); |
|||
context_ = &c; |
|||
} |
|||
|
|||
friend std::ostream& operator<<( |
|||
std::ostream& s, const function_impl& impl ) |
|||
{ |
|||
lock _( impl.mutex_ ); |
|||
return s << lazy_context( &impl ) << lazy_expectations( &impl ); |
|||
} |
|||
|
|||
struct lazy_context |
|||
{ |
|||
lazy_context( const function_impl* impl ) |
|||
: impl_( impl ) |
|||
{} |
|||
friend std::ostream& operator<<( |
|||
std::ostream& s, const lazy_context& c ) |
|||
{ |
|||
if( c.impl_->context_ ) |
|||
c.impl_->context_->serialize( s, *c.impl_ ); |
|||
else |
|||
s << '?'; |
|||
return s; |
|||
} |
|||
const function_impl* impl_; |
|||
}; |
|||
|
|||
struct lazy_expectations |
|||
{ |
|||
lazy_expectations( const function_impl* impl ) |
|||
: impl_( impl ) |
|||
{} |
|||
friend std::ostream& operator<<( |
|||
std::ostream& s, const lazy_expectations& e ) |
|||
{ |
|||
for( expectations_cit it = e.impl_->expectations_.begin(); |
|||
it != e.impl_->expectations_.end(); ++it ) |
|||
s << std::endl << *it; |
|||
return s; |
|||
} |
|||
const function_impl* impl_; |
|||
}; |
|||
|
|||
typedef std::list< expectation_type > expectations_type; |
|||
typedef typename expectations_type::const_iterator expectations_cit; |
|||
|
|||
expectations_type expectations_; |
|||
context* context_; |
|||
mutable bool valid_; |
|||
const int exceptions_; |
|||
const boost::shared_ptr< mutex > mutex_; |
|||
}; |
|||
} |
|||
} // mock
|
|||
|
|||
#undef MOCK_FUNCTION_FORMAT
|
|||
#undef MOCK_FUNCTION_CONTEXT
|
|||
#undef MOCK_MOVE
|
@ -0,0 +1,11 @@ |
|||
// 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
|
@ -0,0 +1,106 @@ |
|||
// 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_MOVE(z, n, d) \
|
|||
mock::detail::move_if_not_lvalue_reference< 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) ) > |
|||
{ |
|||
public: |
|||
typedef R result_type; |
|||
|
|||
template< typename Args > |
|||
struct sig |
|||
{ |
|||
typedef R type; |
|||
}; |
|||
|
|||
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_( boost::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_MOVE, _) ); |
|||
} |
|||
|
|||
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: |
|||
boost::shared_ptr< impl_type > impl_; |
|||
}; |
|||
} |
|||
} // mock
|
|||
|
|||
#undef MOCK_MOVE
|
@ -0,0 +1,54 @@ |
|||
// 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_FUNCTOR_HPP_INCLUDED
|
|||
#define MOCK_FUNCTOR_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "function.hpp"
|
|||
#include "mutex.hpp"
|
|||
#include "singleton.hpp"
|
|||
|
|||
namespace mock { namespace detail { |
|||
class functor_mutex_t : public singleton<functor_mutex_t>, public mutex |
|||
{ |
|||
MOCK_SINGLETON_CONS(functor_mutex_t); |
|||
}; |
|||
MOCK_SINGLETON_INST(functor_mutex) |
|||
|
|||
template<typename Signature> |
|||
struct functor : function<Signature> |
|||
{ |
|||
functor() |
|||
{ |
|||
scoped_lock _(functor_mutex); |
|||
// MOCK_FUNCTOR creates 2 functor objects:
|
|||
// The user-usable one with the passed name and a 2nd used by MOCK_EXPECT with a suffixed name
|
|||
// We need the 2nd to be a copy of the first and use a static variable for storing a pointer to the first
|
|||
static functor* f = nullptr; |
|||
if(f) |
|||
{ |
|||
// Release the lock from the first call (see below) so other threads can create functors again
|
|||
// after the function exits (the scoped_lock still holds the mutex)
|
|||
functor_mutex.unlock(); |
|||
// Copy the first functor to the current (2nd) one
|
|||
*this = *f; |
|||
f = nullptr; |
|||
} else |
|||
{ |
|||
// This is the first object, store its pointer
|
|||
f = this; |
|||
// Lock the mutex again so only this thread can create new instances of a functor
|
|||
// making sure that we copy the right instance above and not one from a concurrent thread
|
|||
functor_mutex.lock(); |
|||
} |
|||
} |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_FUNCTOR_HPP_INCLUDED
|
@ -0,0 +1,49 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_GROUP_HPP_INCLUDED
|
|||
#define MOCK_GROUP_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "verifiable.hpp"
|
|||
#include <algorithm>
|
|||
#include <functional>
|
|||
#include <vector>
|
|||
|
|||
namespace mock { namespace detail { |
|||
class group |
|||
{ |
|||
public: |
|||
void add(verifiable& v) { verifiables_.push_back(&v); } |
|||
void remove(verifiable& v) |
|||
{ |
|||
verifiables_.erase(std::remove(verifiables_.begin(), verifiables_.end(), &v), verifiables_.end()); |
|||
} |
|||
|
|||
bool verify() const |
|||
{ |
|||
bool valid = true; |
|||
for(const auto* verifiable : verifiables_) |
|||
if(!verifiable->verify()) |
|||
valid = false; |
|||
return valid; |
|||
} |
|||
void reset() |
|||
{ |
|||
const auto verifiables = verifiables_; |
|||
for(auto* verifiable : verifiables) |
|||
if(std::find(verifiables_.begin(), verifiables_.end(), verifiable) != verifiables_.end()) |
|||
verifiable->reset(); |
|||
} |
|||
|
|||
private: |
|||
std::vector<verifiable*> verifiables_; |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_GROUP_HPP_INCLUDED
|
@ -0,0 +1,134 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_INVOCATION_HPP_INCLUDED
|
|||
#define MOCK_INVOCATION_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include <limits>
|
|||
#include <ostream>
|
|||
#include <stdexcept>
|
|||
|
|||
namespace mock { namespace detail { |
|||
class invocation |
|||
{ |
|||
public: |
|||
invocation() = default; |
|||
invocation(const invocation&) = delete; |
|||
invocation& operator=(const invocation&) = delete; |
|||
|
|||
virtual ~invocation() = default; |
|||
|
|||
virtual bool invoke() = 0; |
|||
virtual bool verify() const = 0; |
|||
|
|||
virtual bool exhausted() const = 0; |
|||
|
|||
friend std::ostream& operator<<(std::ostream& s, const invocation& i) { return i.serialize(s); } |
|||
|
|||
private: |
|||
virtual std::ostream& serialize(std::ostream& s) const = 0; |
|||
}; |
|||
|
|||
class between : public invocation |
|||
{ |
|||
public: |
|||
between(std::size_t min, std::size_t max) : min_(min), max_(max), count_(0) |
|||
{ |
|||
if(min > max) |
|||
throw std::invalid_argument("'min' > 'max'"); |
|||
} |
|||
|
|||
virtual bool invoke() |
|||
{ |
|||
if(count_ == max_) |
|||
return false; |
|||
++count_; |
|||
return true; |
|||
} |
|||
|
|||
virtual bool exhausted() const { return count_ >= max_; } |
|||
|
|||
virtual bool verify() const { return min_ <= count_ && count_ <= max_; } |
|||
|
|||
protected: |
|||
const std::size_t min_, max_; |
|||
std::size_t count_; |
|||
|
|||
private: |
|||
virtual std::ostream& serialize(std::ostream& s) const |
|||
{ |
|||
return s << "between( " << count_ << "/[" << min_ << ',' << max_ << "] )"; |
|||
} |
|||
}; |
|||
|
|||
class exactly : public between |
|||
{ |
|||
public: |
|||
explicit exactly(std::size_t count) : between(count, count) {} |
|||
|
|||
private: |
|||
virtual std::ostream& serialize(std::ostream& s) const |
|||
{ |
|||
return s << "exactly( " << count_ << '/' << max_ << " )"; |
|||
} |
|||
}; |
|||
|
|||
class never : public exactly |
|||
{ |
|||
public: |
|||
never() : exactly(0) {} |
|||
|
|||
private: |
|||
virtual std::ostream& serialize(std::ostream& s) const { return s << "never()"; } |
|||
}; |
|||
|
|||
class once : public exactly |
|||
{ |
|||
public: |
|||
once() : exactly(1) {} |
|||
|
|||
private: |
|||
virtual std::ostream& serialize(std::ostream& s) const { return s << "once()"; } |
|||
}; |
|||
|
|||
class at_least : public between |
|||
{ |
|||
public: |
|||
explicit at_least(std::size_t min) : between(min, (std::numeric_limits<std::size_t>::max)()) {} |
|||
|
|||
private: |
|||
virtual std::ostream& serialize(std::ostream& s) const |
|||
{ |
|||
return s << "at_least( " << count_ << '/' << min_ << " )"; |
|||
} |
|||
}; |
|||
|
|||
class at_most : public between |
|||
{ |
|||
public: |
|||
explicit at_most(std::size_t max) : between(0, max) {} |
|||
|
|||
private: |
|||
virtual std::ostream& serialize(std::ostream& s) const |
|||
{ |
|||
return s << "at_most( " << count_ << '/' << max_ << " )"; |
|||
} |
|||
}; |
|||
|
|||
class unlimited : public at_least |
|||
{ |
|||
public: |
|||
unlimited() : at_least(0) {} |
|||
|
|||
private: |
|||
virtual std::ostream& serialize(std::ostream& s) const { return s << "unlimited()"; } |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_INVOCATION_HPP_INCLUDED
|
@ -0,0 +1,26 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Mathieu Champlon 2009
|
|||
//
|
|||
// 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_IS_FUNCTOR_HPP_INCLUDED
|
|||
#define MOCK_IS_FUNCTOR_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "void_t.hpp"
|
|||
#include <type_traits>
|
|||
|
|||
namespace mock { namespace detail { |
|||
/// Trait to return true if F is a functor that can be called with a single argument Arg
|
|||
template<typename F, typename Arg, class = void> |
|||
struct is_functor : std::false_type |
|||
{}; |
|||
template<typename F, typename Arg> |
|||
struct is_functor<F, Arg, void_t<decltype(std::declval<F>()(std::declval<Arg>()))>> : std::true_type |
|||
{}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_IS_FUNCTOR_HPP_INCLUDED
|
@ -0,0 +1,38 @@ |
|||
// 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_MATCHER_BASE_HPP_INCLUDED
|
|||
#define MOCK_MATCHER_BASE_HPP_INCLUDED
|
|||
|
|||
#include "ref_arg.hpp"
|
|||
#include <ostream>
|
|||
|
|||
namespace mock { namespace detail { |
|||
template<typename... Args> |
|||
class matcher_base |
|||
{ |
|||
public: |
|||
matcher_base() = default; |
|||
matcher_base(const matcher_base&) = delete; |
|||
matcher_base& operator=(const matcher_base&) = delete; |
|||
virtual ~matcher_base() = default; |
|||
|
|||
virtual bool operator()(ref_arg_t<Args>...) = 0; |
|||
|
|||
friend std::ostream& operator<<(std::ostream& s, const matcher_base& m) |
|||
{ |
|||
m.serialize(s); |
|||
return s; |
|||
} |
|||
|
|||
private: |
|||
virtual void serialize(std::ostream&) const = 0; |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_MATCHER_BASE_HPP_INCLUDED
|
@ -0,0 +1,42 @@ |
|||
// 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_REF_ARG(z, n, d) \
|
|||
typename ref_arg< T##n >::type |
|||
|
|||
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) ) > |
|||
: boost::noncopyable |
|||
{ |
|||
public: |
|||
virtual ~matcher_base() {} |
|||
|
|||
virtual bool operator()( |
|||
BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG, _) ) = 0; |
|||
|
|||
friend std::ostream& operator<<( |
|||
std::ostream& s, const matcher_base& m ) |
|||
{ |
|||
m.serialize( s ); |
|||
return s; |
|||
} |
|||
|
|||
private: |
|||
virtual void serialize( std::ostream& ) const = 0; |
|||
}; |
|||
} |
|||
} // mock
|
|||
|
|||
#undef MOCK_REF_ARG
|
@ -0,0 +1,113 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_MOCK_IMPL_HPP_INCLUDED
|
|||
#define MOCK_MOCK_IMPL_HPP_INCLUDED
|
|||
|
|||
#include "function.hpp"
|
|||
#include "functor.hpp"
|
|||
#include "signature.hpp"
|
|||
#include "signature_traits.hpp"
|
|||
#include "type_name.hpp"
|
|||
#include <boost/preprocessor/repetition/repeat.hpp>
|
|||
#include <boost/preprocessor/stringize.hpp>
|
|||
#include <type_traits>
|
|||
|
|||
namespace mock { namespace detail { |
|||
/// Simplified trait to extract the argument type of a function signature with 1 argument
|
|||
template<typename T> |
|||
struct arg_type; |
|||
template<typename T, typename U> |
|||
struct arg_type<T(U)> |
|||
{ |
|||
using type = U; |
|||
}; |
|||
/// Used in MOCK_PROTECT_SIGNATURE to unwrap the passed function signature
|
|||
/// T is something like `void(std::map<int, float>)`
|
|||
template<typename T> |
|||
using unwrap_signature_t = std::remove_pointer_t<typename arg_type<T>::type>; |
|||
}} // namespace mock::detail
|
|||
|
|||
#define MOCK_HELPER(t) t##_mock(mock::detail::root, BOOST_PP_STRINGIZE(t))
|
|||
#define MOCK_ANONYMOUS_HELPER(t) t##_mock(mock::detail::root, "?.")
|
|||
|
|||
#define MOCK_METHOD_HELPER(S, t) \
|
|||
mutable mock::detail::function<S> t##_mock_; \ |
|||
mock::detail::function<S>& t##_mock(const mock::detail::context&, const boost::unit_test::const_string& instance) \ |
|||
const \ |
|||
{ \ |
|||
mock::detail::configure(*this, \ |
|||
t##_mock_, \ |
|||
instance.substr(0, instance.rfind(BOOST_PP_STRINGIZE(t))), \ |
|||
mock::detail::make_type_name(*this), \ |
|||
BOOST_PP_STRINGIZE(t)); \ |
|||
return t##_mock_; \ |
|||
} |
|||
|
|||
#define MOCK_PARAM(S) mock::detail::parameter_t < S
|
|||
#define MOCK_DECL_PARAM(z, n, d) BOOST_PP_COMMA_IF(n) d, n > p##n
|
|||
#define MOCK_DECL_PARAMS(n, S) BOOST_PP_REPEAT(n, MOCK_DECL_PARAM, MOCK_PARAM(S))
|
|||
#define MOCK_DECL(M, n, S, c) mock::detail::result_type_t<S> M(MOCK_DECL_PARAMS(n, S)) c
|
|||
|
|||
#define MOCK_FORWARD_PARAM(z, n, d) BOOST_PP_COMMA_IF(n) d, n >> (p##n)
|
|||
#define MOCK_FORWARD_PARAMS(n, S) BOOST_PP_REPEAT(n, MOCK_FORWARD_PARAM, std::forward < MOCK_PARAM(S))
|
|||
#define MOCK_METHOD_AUX(M, n, S, t, c) \
|
|||
static_assert(n == mock::detail::function_arity_t<S>::value, "Arity mismatch"); \ |
|||
MOCK_DECL(M, n, S, c) { return MOCK_ANONYMOUS_HELPER(t)(MOCK_FORWARD_PARAMS(n, S)); } |
|||
|
|||
#define MOCK_METHOD_EXT(M, n, S, t) \
|
|||
MOCK_METHOD_AUX(M, n, S, t, ) \ |
|||
MOCK_METHOD_AUX(M, n, S, t, const) \ |
|||
MOCK_METHOD_HELPER(S, t) |
|||
#define MOCK_CONST_METHOD_EXT(M, n, S, t) \
|
|||
MOCK_METHOD_AUX(M, n, S, t, const) \ |
|||
MOCK_METHOD_HELPER(S, t) |
|||
#define MOCK_NON_CONST_METHOD_EXT(M, n, S, t) \
|
|||
MOCK_METHOD_AUX(M, n, S, t, ) \ |
|||
MOCK_METHOD_HELPER(S, t) |
|||
|
|||
#define MOCK_FUNCTION_HELPER(S, t, s) \
|
|||
s mock::detail::function<S>& t##_mock(mock::detail::context& context, boost::unit_test::const_string instance) \ |
|||
{ \ |
|||
static mock::detail::function<S> f; \ |
|||
return f(context, instance); \ |
|||
} |
|||
|
|||
#define MOCK_CONSTRUCTOR_AUX(T, n, A, t) \
|
|||
T(MOCK_DECL_PARAMS(n, void A)) { MOCK_HELPER(t)(MOCK_FORWARD_PARAMS(n, void A)); } \ |
|||
MOCK_FUNCTION_HELPER(void A, t, static) |
|||
|
|||
#define MOCK_FUNCTION_AUX(F, n, S, t, s) \
|
|||
MOCK_FUNCTION_HELPER(S, t, s) \ |
|||
static_assert(n == mock::detail::function_arity_t<S>::value, "Arity mismatch"); \ |
|||
s MOCK_DECL(F, n, S, ) { return MOCK_HELPER(t)(MOCK_FORWARD_PARAMS(n, S)); } |
|||
|
|||
#define MOCK_VARIADIC_ELEM_0(e0, ...) e0
|
|||
#define MOCK_VARIADIC_ELEM_1(e0, e1, ...) e1
|
|||
#define MOCK_VARIADIC_ELEM_2(e0, e1, e2, ...) e2
|
|||
|
|||
#define MOCK_REPLACED_MACRO_ERROR(oldName, newName) static_assert(false, #oldName " has been replaced by " #newName)
|
|||
// Replaced macros
|
|||
#define MOCK_CONST_CONVERSION_OPERATOR_TPL(...) \
|
|||
MOCK_REPLACED_MACRO_ERROR(MOCK_CONST_CONVERSION_OPERATOR_TPL, MOCK_CONST_CONVERSION_OPERATOR) |
|||
#define MOCK_CONST_METHOD_EXT_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_CONST_METHOD_EXT_TPL, MOCK_CONST_METHOD)
|
|||
#define MOCK_CONST_METHOD_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_CONST_METHOD_TPL, MOCK_CONST_METHOD)
|
|||
#define MOCK_CONVERSION_OPERATOR_TPL(...) \
|
|||
MOCK_REPLACED_MACRO_ERROR(MOCK_CONVERSION_OPERATOR_TPL, MOCK_CONVERSION_OPERATOR) |
|||
#define MOCK_FUNCTOR_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_FUNCTOR_TPL, MOCK_FUNCTOR)
|
|||
#define MOCK_METHOD_EXT_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_METHOD_EXT_TPL, MOCK_METHOD)
|
|||
#define MOCK_METHOD_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_METHOD_TPL, MOCK_METHOD)
|
|||
#define MOCK_NON_CONST_CONVERSION_OPERATOR_TPL(...) \
|
|||
MOCK_REPLACED_MACRO_ERROR(MOCK_NON_CONST_CONVERSION_OPERATOR_TPL, MOCK_NON_CONST_CONVERSION_OPERATOR) |
|||
#define MOCK_NON_CONST_METHOD_EXT_TPL(...) \
|
|||
MOCK_REPLACED_MACRO_ERROR(MOCK_NON_CONST_METHOD_EXT_TPL, MOCK_NON_CONST_METHOD) |
|||
#define MOCK_NON_CONST_METHOD_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_NON_CONST_METHOD_TPL, MOCK_NON_CONST_METHOD)
|
|||
#define MOCK_STATIC_METHOD_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_STATIC_METHOD_TPL, MOCK_STATIC_METHOD)
|
|||
#define MOCK_CONSTRUCTOR_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_CONSTRUCTOR_TPL, MOCK_CONSTRUCTOR)
|
|||
|
|||
#endif // MOCK_MOCK_IMPL_HPP_INCLUDED
|
@ -0,0 +1,78 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Mathieu Champlon 2018
|
|||
//
|
|||
// 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_MOVE_HELPER_HPP_INCLUDED
|
|||
#define MOCK_MOVE_HELPER_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include <boost/type_traits/conditional.hpp>
|
|||
#include <boost/type_traits/is_reference.hpp>
|
|||
#include <boost/type_traits/remove_reference.hpp>
|
|||
#include <boost/type_traits/add_reference.hpp>
|
|||
#include <boost/type_traits/add_rvalue_reference.hpp>
|
|||
#include <boost/type_traits/decay.hpp>
|
|||
|
|||
namespace mock |
|||
{ |
|||
namespace detail |
|||
{ |
|||
#ifdef MOCK_RVALUE_REFERENCES
|
|||
template< typename T > |
|||
struct forward_type |
|||
{ |
|||
typedef T type; |
|||
}; |
|||
template< typename T > |
|||
struct ref_arg |
|||
{ |
|||
typedef typename boost::conditional< |
|||
boost::is_reference< T >::value, |
|||
T, |
|||
typename boost::add_rvalue_reference< T >::type >::type type; |
|||
}; |
|||
|
|||
template< typename T > |
|||
inline T&& move_if_not_lvalue_reference(typename boost::remove_reference< T >::type& t) |
|||
{ |
|||
return static_cast< T&& >(t); |
|||
} |
|||
|
|||
template< typename T > |
|||
inline T&& move_if_not_lvalue_reference(typename boost::remove_reference< T >::type&& t) |
|||
{ |
|||
return static_cast< T&& >(t); |
|||
} |
|||
#else
|
|||
template< typename T > |
|||
struct forward_type |
|||
{ |
|||
typedef typename boost::decay< const T >::type type; |
|||
}; |
|||
template< class T> |
|||
struct forward_type< boost::rv< T > > |
|||
{ |
|||
typedef T type; |
|||
}; |
|||
template< typename T > |
|||
struct ref_arg |
|||
{ |
|||
typedef typename boost::conditional< |
|||
boost::is_reference< T >::value, |
|||
T, |
|||
const typename boost::add_reference< T >::type >::type type; |
|||
}; |
|||
template< typename T > |
|||
inline typename boost::remove_reference< T >::type& move_if_not_lvalue_reference(typename boost::remove_reference< T >::type& t) |
|||
{ |
|||
return t; |
|||
} |
|||
#endif
|
|||
} |
|||
} |
|||
|
|||
#endif // MOCK_MOVE_HELPER_HPP_INCLUDED
|
@ -0,0 +1,134 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Mathieu Champlon 2014
|
|||
//
|
|||
// 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_MUTEX_HPP_INCLUDED
|
|||
#define MOCK_MUTEX_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "singleton.hpp"
|
|||
#include <memory>
|
|||
|
|||
#ifdef MOCK_THREAD_SAFE
|
|||
|
|||
# ifdef MOCK_HDR_MUTEX
|
|||
# include <mutex>
|
|||
# else
|
|||
# include <boost/thread/lock_guard.hpp>
|
|||
# include <boost/thread/recursive_mutex.hpp>
|
|||
# endif
|
|||
|
|||
namespace mock { namespace detail { |
|||
# ifdef MOCK_HDR_MUTEX
|
|||
typedef std::recursive_mutex mutex; |
|||
typedef std::lock_guard<mutex> scoped_lock; |
|||
# else
|
|||
typedef boost::recursive_mutex mutex; |
|||
typedef boost::lock_guard<mutex> scoped_lock; |
|||
# endif
|
|||
|
|||
struct lock |
|||
{ |
|||
public: |
|||
lock(const std::shared_ptr<mutex>& m) : m_(m) { m_->lock(); } |
|||
~lock() |
|||
{ |
|||
if(m_) |
|||
m_->unlock(); |
|||
} |
|||
lock(const lock&) = delete; |
|||
lock(lock&& x) = default; |
|||
lock& operator=(const lock&) = delete; |
|||
lock& operator=(lock&& x) = default; |
|||
|
|||
private: |
|||
std::shared_ptr<mutex> m_; |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#else // MOCK_THREAD_SAFE
|
|||
|
|||
namespace mock { namespace detail { |
|||
struct mutex |
|||
{ |
|||
mutex() = default; |
|||
mutex(const mutex&) = delete; |
|||
mutex& operator=(const mutex&) = delete; |
|||
|
|||
void lock() {} |
|||
void unlock() {} |
|||
}; |
|||
// Dummy lock classes.
|
|||
// Constructor + Destructor make it RAII classes for compilers and avoid unused variable warnings
|
|||
struct scoped_lock |
|||
{ |
|||
scoped_lock(const scoped_lock&) = delete; |
|||
scoped_lock& operator=(const scoped_lock&) = delete; |
|||
|
|||
scoped_lock(mutex&) {} |
|||
~scoped_lock() {} |
|||
}; |
|||
class lock |
|||
{ |
|||
public: |
|||
lock(const std::shared_ptr<mutex>&) {} |
|||
~lock() {} |
|||
lock(const lock&) = delete; |
|||
lock(lock&&) = default; |
|||
lock& operator=(const lock&) = delete; |
|||
lock& operator=(lock&&) = default; |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_THREAD_SAFE
|
|||
|
|||
namespace mock { namespace detail { |
|||
class error_mutex_t : public singleton<error_mutex_t>, public mutex |
|||
{ |
|||
MOCK_SINGLETON_CONS(error_mutex_t); |
|||
}; |
|||
MOCK_SINGLETON_INST(error_mutex) |
|||
|
|||
#ifdef BOOST_MSVC
|
|||
# pragma warning(push)
|
|||
# pragma warning(disable : 4702)
|
|||
#endif
|
|||
template<typename Result, typename Error> |
|||
struct safe_error |
|||
{ |
|||
static Result abort() |
|||
{ |
|||
scoped_lock _(error_mutex); |
|||
return Error::abort(); |
|||
} |
|||
template<typename Context> |
|||
static void fail(const char* message, |
|||
const Context& context, |
|||
const char* file = "unknown location", |
|||
int line = 0) |
|||
{ |
|||
scoped_lock _(error_mutex); |
|||
Error::fail(message, context, file, line); |
|||
} |
|||
template<typename Context> |
|||
static void call(const Context& context, const char* file, int line) |
|||
{ |
|||
scoped_lock _(error_mutex); |
|||
Error::call(context, file, line); |
|||
} |
|||
static void pass(const char* file, int line) |
|||
{ |
|||
scoped_lock _(error_mutex); |
|||
Error::pass(file, line); |
|||
} |
|||
}; |
|||
#ifdef BOOST_MSVC
|
|||
# pragma warning(pop)
|
|||
#endif
|
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_MUTEX_HPP_INCLUDED
|
@ -0,0 +1,83 @@ |
|||
// 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_OBJECT_IMPL_HPP_INCLUDED
|
|||
#define MOCK_OBJECT_IMPL_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "child.hpp"
|
|||
#include "context.hpp"
|
|||
#include "mutex.hpp"
|
|||
#include "parent.hpp"
|
|||
#include "root.hpp"
|
|||
#include "type_name.hpp"
|
|||
#include <boost/optional.hpp>
|
|||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
|||
|
|||
namespace mock { namespace detail { |
|||
class object_impl : public context, public verifiable, public std::enable_shared_from_this<object_impl> |
|||
{ |
|||
public: |
|||
object_impl() : mutex_(std::make_shared<mutex>()) {} |
|||
|
|||
virtual void add(const void* /*p*/, |
|||
verifiable& v, |
|||
boost::unit_test::const_string instance, |
|||
boost::optional<type_name> type, |
|||
boost::unit_test::const_string name) |
|||
{ |
|||
lock _(mutex_); |
|||
if(children_.empty()) |
|||
detail::root.add(*this); |
|||
children_[&v].update(parent_, instance, type, name); |
|||
} |
|||
virtual void add(verifiable& v) |
|||
{ |
|||
lock _(mutex_); |
|||
group_.add(v); |
|||
} |
|||
virtual void remove(verifiable& v) |
|||
{ |
|||
lock _(mutex_); |
|||
group_.remove(v); |
|||
children_.erase(&v); |
|||
if(children_.empty()) |
|||
detail::root.remove(*this); |
|||
} |
|||
|
|||
virtual void serialize(std::ostream& s, const verifiable& v) const |
|||
{ |
|||
lock _(mutex_); |
|||
const auto it = children_.find(&v); |
|||
if(it != children_.end()) |
|||
s << it->second; |
|||
else |
|||
s << "?"; |
|||
} |
|||
|
|||
virtual bool verify() const |
|||
{ |
|||
lock _(mutex_); |
|||
return group_.verify(); |
|||
} |
|||
virtual void reset() |
|||
{ |
|||
lock _(mutex_); |
|||
std::shared_ptr<object_impl> guard = shared_from_this(); |
|||
group_.reset(); |
|||
} |
|||
|
|||
private: |
|||
group group_; |
|||
parent parent_; |
|||
std::map<const verifiable*, child> children_; |
|||
const std::shared_ptr<mutex> mutex_; |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_OBJECT_IMPL_HPP_INCLUDED
|
@ -0,0 +1,34 @@ |
|||
// 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_PARAMETER_HPP_INCLUDED
|
|||
#define MOCK_PARAMETER_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include <boost/function_types/parameter_types.hpp>
|
|||
#include <boost/function_types/function_arity.hpp>
|
|||
#include <boost/mpl/at.hpp>
|
|||
|
|||
namespace mock |
|||
{ |
|||
namespace detail |
|||
{ |
|||
template< typename Signature, int n > |
|||
struct parameter |
|||
{ |
|||
typedef typename |
|||
boost::mpl::at_c< |
|||
typename |
|||
boost::function_types::parameter_types< Signature >, |
|||
n |
|||
>::type type; |
|||
}; |
|||
} |
|||
} // mock
|
|||
|
|||
#endif // MOCK_PARAMETER_HPP_INCLUDED
|
@ -0,0 +1,40 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_PARENT_HPP_INCLUDED
|
|||
#define MOCK_PARENT_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "type_name.hpp"
|
|||
#include <boost/optional.hpp>
|
|||
#include <boost/test/utils/basic_cstring/io.hpp>
|
|||
#include <ostream>
|
|||
|
|||
namespace mock { namespace detail { |
|||
class parent |
|||
{ |
|||
public: |
|||
parent() = default; |
|||
parent(boost::unit_test::const_string instance, boost::optional<type_name> type) |
|||
: instance_(instance), type_(type) |
|||
{} |
|||
friend std::ostream& operator<<(std::ostream& s, const parent& p) |
|||
{ |
|||
s << p.instance_; |
|||
if(p.type_) |
|||
s << *p.type_ << "::"; |
|||
return s; |
|||
} |
|||
|
|||
private: |
|||
boost::unit_test::const_string instance_; |
|||
boost::optional<type_name> type_; |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_PARENT_HPP_INCLUDED
|
@ -0,0 +1,22 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Mathieu Champlon 2018
|
|||
//
|
|||
// 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_REF_ARG_HPP_INCLUDED
|
|||
#define MOCK_REF_ARG_HPP_INCLUDED
|
|||
|
|||
#include <type_traits>
|
|||
|
|||
namespace mock { namespace detail { |
|||
/// Make T a reference type:
|
|||
/// If T is already a reference type, return T, else return an rvalue reference to T
|
|||
/// Useful to pass along arguments keeping the ability to modify them (e.g. move from them)
|
|||
template<typename T> |
|||
using ref_arg_t = typename std::conditional<std::is_reference<T>::value, T, std::add_rvalue_reference_t<T>>::type; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_REF_ARG_HPP_INCLUDED
|
@ -0,0 +1,119 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_ROOT_HPP_INCLUDED
|
|||
#define MOCK_ROOT_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "child.hpp"
|
|||
#include "context.hpp"
|
|||
#include "group.hpp"
|
|||
#include "mutex.hpp"
|
|||
#include "parent.hpp"
|
|||
#include "singleton.hpp"
|
|||
#include <boost/optional.hpp>
|
|||
#include <map>
|
|||
#include <ostream>
|
|||
|
|||
namespace mock { namespace detail { |
|||
class root_t : public singleton<root_t>, public context |
|||
{ |
|||
public: |
|||
virtual void add(const void* p, |
|||
verifiable& v, |
|||
boost::unit_test::const_string instance, |
|||
boost::optional<type_name> type, |
|||
boost::unit_test::const_string name) |
|||
{ |
|||
scoped_lock _(mutex_); |
|||
auto it = children_.lower_bound(&v); |
|||
if(it == children_.end() || children_.key_comp()(&v, it->first)) |
|||
it = children_.insert(it, std::make_pair(&v, counter_child(parents_, p))); |
|||
it->second.update(instance, type, name); |
|||
} |
|||
virtual void add(verifiable& v) |
|||
{ |
|||
scoped_lock _(mutex_); |
|||
group_.add(v); |
|||
} |
|||
|
|||
virtual void remove(verifiable& v) |
|||
{ |
|||
scoped_lock _(mutex_); |
|||
group_.remove(v); |
|||
children_.erase(&v); |
|||
} |
|||
|
|||
bool verify() const |
|||
{ |
|||
scoped_lock _(mutex_); |
|||
return group_.verify(); |
|||
} |
|||
void reset() |
|||
{ |
|||
scoped_lock _(mutex_); |
|||
group_.reset(); |
|||
} |
|||
|
|||
virtual void serialize(std::ostream& s, const verifiable& v) const |
|||
{ |
|||
scoped_lock _(mutex_); |
|||
const auto it = children_.find(&v); |
|||
if(it != children_.end()) |
|||
s << it->second; |
|||
else |
|||
s << "?"; |
|||
} |
|||
|
|||
private: |
|||
typedef std::map<const void*, std::pair<parent, std::size_t>> parents_t; |
|||
|
|||
class counter_child |
|||
{ |
|||
public: |
|||
counter_child(parents_t& parents, const void* p) |
|||
: parents_(&parents), it_(parents.insert(std::make_pair(p, parents_t::mapped_type())).first) |
|||
{ |
|||
++it_->second.second; |
|||
} |
|||
counter_child(const counter_child& rhs) : parents_(rhs.parents_), it_(rhs.it_), child_(rhs.child_) |
|||
{ |
|||
++it_->second.second; |
|||
} |
|||
~counter_child() |
|||
{ |
|||
if(--it_->second.second == 0) |
|||
parents_->erase(it_); |
|||
} |
|||
void update(boost::unit_test::const_string instance, |
|||
boost::optional<type_name> type, |
|||
boost::unit_test::const_string name) |
|||
{ |
|||
child_.update(it_->second.first, instance, type, name); |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& s, const counter_child& c) { return s << c.child_; } |
|||
|
|||
private: |
|||
counter_child& operator=(const counter_child&); |
|||
|
|||
parents_t* parents_; |
|||
parents_t::iterator it_; |
|||
child child_; |
|||
}; |
|||
|
|||
parents_t parents_; |
|||
std::map<const verifiable*, counter_child> children_; |
|||
group group_; |
|||
mutable mutex mutex_; |
|||
|
|||
MOCK_SINGLETON_CONS(root_t); |
|||
}; |
|||
MOCK_SINGLETON_INST(root) |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_ROOT_HPP_INCLUDED
|
@ -0,0 +1,55 @@ |
|||
// 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_SEQUENCE_IMPL_HPP_INCLUDED
|
|||
#define MOCK_SEQUENCE_IMPL_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include "mutex.hpp"
|
|||
#include <algorithm>
|
|||
#include <memory>
|
|||
#include <vector>
|
|||
|
|||
namespace mock { namespace detail { |
|||
class sequence_impl |
|||
{ |
|||
public: |
|||
sequence_impl() : mutex_(std::make_shared<mutex>()) {} |
|||
|
|||
void add(void* e) |
|||
{ |
|||
lock _(mutex_); |
|||
elements_.push_back(e); |
|||
} |
|||
void remove(void* e) |
|||
{ |
|||
lock _(mutex_); |
|||
elements_.erase(std::remove(elements_.begin(), elements_.end(), e), elements_.end()); |
|||
} |
|||
|
|||
bool is_valid(const void* e) const |
|||
{ |
|||
lock _(mutex_); |
|||
return std::find(elements_.begin(), elements_.end(), e) != elements_.end(); |
|||
} |
|||
|
|||
void invalidate(const void* e) |
|||
{ |
|||
lock _(mutex_); |
|||
const auto it = std::find(elements_.begin(), elements_.end(), e); |
|||
if(it != elements_.end()) |
|||
elements_.erase(elements_.begin(), it); |
|||
} |
|||
|
|||
private: |
|||
std::vector<void*> elements_; |
|||
const std::shared_ptr<mutex> mutex_; |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_SEQUENCE_IMPL_HPP_INCLUDED
|
@ -0,0 +1,77 @@ |
|||
// 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_SIGNATURE_HPP_INCLUDED
|
|||
#define MOCK_SIGNATURE_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include <type_traits>
|
|||
|
|||
namespace mock { namespace detail { |
|||
#define MOCK_NOARG
|
|||
#define MOCK_STRIP_FUNCTION_QUALIFIERS(cv, ref) \
|
|||
template<typename R, typename... Args> \ |
|||
struct strip_function_qualifiers<R(Args...) cv ref> \ |
|||
{ \ |
|||
using type = R(Args...); \ |
|||
}; \ |
|||
template<typename R, typename... Args> \ |
|||
struct strip_function_qualifiers<R(Args..., ...) cv ref> \ |
|||
{ \ |
|||
using type = R(Args..., ...); \ |
|||
}; |
|||
|
|||
#define MOCK_STRIP_FUNCTION_QUALIFIERS_REF(cv) \
|
|||
MOCK_STRIP_FUNCTION_QUALIFIERS(cv, ) \ |
|||
MOCK_STRIP_FUNCTION_QUALIFIERS(cv, &) \ |
|||
MOCK_STRIP_FUNCTION_QUALIFIERS(cv, &&) |
|||
|
|||
template<typename> |
|||
struct strip_function_qualifiers; |
|||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(MOCK_NOARG) |
|||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(const) |
|||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(volatile) |
|||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(const volatile) |
|||
#undef MOCK_NOARG
|
|||
#undef MOCK_STRIP_FUNCTION_QUALIFIERS
|
|||
#undef MOCK_STRIP_FUNCTION_QUALIFIERS_REF
|
|||
|
|||
template<typename M> |
|||
struct signature; |
|||
|
|||
template<typename R, typename... Args> |
|||
struct signature<R(Args...)> |
|||
{ |
|||
using type = R(Args...); |
|||
}; |
|||
|
|||
template<typename Sig, typename C> |
|||
struct signature<Sig(C::*)> : signature<typename strip_function_qualifiers<Sig>::type> |
|||
{}; |
|||
|
|||
/// Return the (non-member) function signature out of (any) signature
|
|||
template<typename M> |
|||
using signature_t = typename signature<M>::type; |
|||
|
|||
/// CRTP class to define the base_type typedef
|
|||
template<typename T> |
|||
struct base |
|||
{ |
|||
using base_type = T; |
|||
}; |
|||
|
|||
// If an error is generated by the line below it means the method is ambiguous.
|
|||
// Specify its signature to disambiguate
|
|||
template<typename T> |
|||
T ambiguous_method_requires_to_specify_signature(const T&); |
|||
}} // namespace mock::detail
|
|||
|
|||
#define MOCK_SIGNATURE(M) \
|
|||
mock::detail::signature_t<decltype(mock::detail::ambiguous_method_requires_to_specify_signature(&base_type::M))> |
|||
|
|||
#endif // MOCK_SIGNATURE_HPP_INCLUDED
|
@ -0,0 +1,62 @@ |
|||
// 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_SIGNATURE_TRAITS_HPP_INCLUDED
|
|||
#define MOCK_SIGNATURE_TRAITS_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include <cstddef>
|
|||
|
|||
namespace mock { namespace detail { |
|||
/// Helper class to store a tuple/list of types
|
|||
template<class...> |
|||
struct tuple; |
|||
|
|||
/// Get the type at the given index in the tuple
|
|||
template<std::size_t index, class Tuple> |
|||
struct tuple_element; |
|||
|
|||
template<std::size_t I, class H, class... T> |
|||
struct tuple_element<I, tuple<H, T...>> : tuple_element<I - 1, tuple<T...>> |
|||
{}; |
|||
|
|||
template<class H, class... T> |
|||
struct tuple_element<0, tuple<H, T...>> |
|||
{ |
|||
using type = H; |
|||
}; |
|||
|
|||
/// Provides information about a given function signature
|
|||
/// Member types: return_type, args
|
|||
/// Member constant: arity
|
|||
template<typename Signature> |
|||
struct signature_traits; |
|||
|
|||
template<typename R, typename... Args> |
|||
struct signature_traits<R(Args...)> |
|||
{ |
|||
using return_type = R; |
|||
static constexpr std::size_t arity = sizeof...(Args); |
|||
using args = tuple<Args...>; |
|||
}; |
|||
|
|||
/// Return the result type of the function signature
|
|||
template<typename Signature> |
|||
using result_type_t = typename signature_traits<Signature>::return_type; |
|||
|
|||
/// Return the arity of the function signature
|
|||
template<typename Signature> |
|||
using function_arity_t = std::integral_constant<std::size_t, signature_traits<Signature>::arity>; |
|||
|
|||
/// Return the type at the given index of the function signature
|
|||
template<typename Signature, std::size_t idx> |
|||
using parameter_t = typename tuple_element<idx, typename signature_traits<Signature>::args>::type; |
|||
|
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_SIGNATURE_TRAITS_HPP_INCLUDED
|
@ -0,0 +1,44 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Mathieu Champlon 2014
|
|||
//
|
|||
// 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_SINGLETON_HPP
|
|||
#define MOCK_SINGLETON_HPP
|
|||
|
|||
#include <boost/config.hpp>
|
|||
|
|||
namespace mock { namespace detail { |
|||
|
|||
template<typename Derived> |
|||
class singleton |
|||
{ |
|||
public: |
|||
static Derived& instance() |
|||
{ |
|||
static Derived the_inst; |
|||
return the_inst; |
|||
} |
|||
|
|||
singleton(singleton const&) = delete; |
|||
singleton& operator=(singleton const&) = delete; |
|||
|
|||
protected: |
|||
singleton() = default; |
|||
~singleton() = default; |
|||
}; |
|||
|
|||
}} // namespace mock::detail
|
|||
|
|||
// Add a private ctor to the type to prevent misuse
|
|||
#define MOCK_SINGLETON_CONS(type) \
|
|||
private: \ |
|||
friend class mock::detail::singleton<type>; \ |
|||
type() = default |
|||
|
|||
#define MOCK_SINGLETON_INST(inst) static BOOST_JOIN(inst, _t)& inst = BOOST_JOIN(inst, _t)::instance();
|
|||
|
|||
#endif // MOCK_SINGLETON_HPP
|
@ -0,0 +1,119 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Mathieu Champlon 2009
|
|||
//
|
|||
// 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_TYPE_NAME_HPP_INCLUDED
|
|||
#define MOCK_TYPE_NAME_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
#include <boost/algorithm/string/erase.hpp>
|
|||
#include <boost/algorithm/string/replace.hpp>
|
|||
#include <boost/algorithm/string/trim.hpp>
|
|||
#include <boost/test/utils/basic_cstring/io.hpp>
|
|||
#include <boost/version.hpp>
|
|||
#include <memory>
|
|||
#include <ostream>
|
|||
#include <stdexcept>
|
|||
#include <typeinfo>
|
|||
#ifdef __GNUC__
|
|||
# include <cstdlib>
|
|||
# include <cxxabi.h>
|
|||
#endif
|
|||
|
|||
namespace mock { namespace detail { |
|||
class type_name |
|||
{ |
|||
public: |
|||
explicit type_name(const std::type_info& info) : info_(&info) {} |
|||
friend std::ostream& operator<<(std::ostream& s, const type_name& t) |
|||
{ |
|||
t.serialize(s, *t.info_); |
|||
return s; |
|||
} |
|||
|
|||
private: |
|||
static void serialize(std::ostream& s, const std::type_info& info) |
|||
{ |
|||
const char* name = info.name(); |
|||
#ifdef __GNUC__
|
|||
int status = 0; |
|||
struct Deleter |
|||
{ |
|||
void operator()(const void* p) { std::free(const_cast<void*>(p)); } |
|||
}; |
|||
std::unique_ptr<const char, Deleter> demangled(abi::__cxa_demangle(name, 0, 0, &status)); |
|||
if(!status && demangled) |
|||
name = demangled.get(); |
|||
#endif
|
|||
serialize(s, name); |
|||
} |
|||
|
|||
typedef std::string::size_type size_type; |
|||
|
|||
static void serialize(std::ostream& s, std::string name) |
|||
{ |
|||
const size_type nm = rfind(name, ':') + 1; |
|||
const size_type tpl = name.find('<', nm); |
|||
s << clean(name.substr(nm, tpl - nm)); |
|||
if(tpl == std::string::npos) |
|||
return; |
|||
s << '<'; |
|||
list(s, name.substr(tpl + 1, name.rfind('>') - tpl - 1)); |
|||
s << '>'; |
|||
} |
|||
static void list(std::ostream& s, const std::string& name) |
|||
{ |
|||
const size_type comma = rfind(name, ','); |
|||
if(comma != std::string::npos) |
|||
{ |
|||
list(s, name.substr(0, comma)); |
|||
s << ", "; |
|||
} |
|||
serialize(s, name.substr(comma + 1)); |
|||
} |
|||
static std::string clean(std::string name) |
|||
{ |
|||
boost::algorithm::trim(name); |
|||
boost::algorithm::erase_all(name, "class "); |
|||
boost::algorithm::erase_all(name, "struct "); |
|||
boost::algorithm::erase_all(name, "__ptr64"); |
|||
boost::algorithm::replace_all(name, " &", "&"); |
|||
boost::algorithm::replace_all(name, "& ", "&"); |
|||
boost::algorithm::replace_all(name, " *", "*"); |
|||
boost::algorithm::replace_all(name, "* ", "*"); |
|||
return name; |
|||
} |
|||
static size_type rfind(const std::string& name, char c) |
|||
{ |
|||
size_type count = 0; |
|||
for(size_type i = name.size() - 1; i > 0; --i) |
|||
{ |
|||
if(name[i] == '>') |
|||
++count; |
|||
else if(name[i] == '<') |
|||
--count; |
|||
if(name[i] == c && count == 0) |
|||
return i; |
|||
} |
|||
return std::string::npos; |
|||
} |
|||
|
|||
const std::type_info* info_; |
|||
}; |
|||
template<typename T> |
|||
type_name make_type_name() |
|||
{ |
|||
return type_name(typeid(T)); |
|||
} |
|||
template<typename T> |
|||
type_name make_type_name(const T&) |
|||
{ |
|||
return type_name(typeid(T)); |
|||
} |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_TYPE_NAME_HPP_INCLUDED
|
@ -0,0 +1,29 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_VERIFIABLE_HPP_INCLUDED
|
|||
#define MOCK_VERIFIABLE_HPP_INCLUDED
|
|||
|
|||
#include "../config.hpp"
|
|||
|
|||
namespace mock { namespace detail { |
|||
class verifiable |
|||
{ |
|||
public: |
|||
verifiable() = default; |
|||
verifiable(const verifiable&) = delete; |
|||
verifiable& operator=(const verifiable&) = delete; |
|||
virtual ~verifiable() = default; |
|||
|
|||
virtual bool verify() const = 0; |
|||
|
|||
virtual void reset() = 0; |
|||
}; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_VERIFIABLE_HPP_INCLUDED
|
@ -0,0 +1,23 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Alexander Grund 2020
|
|||
//
|
|||
// 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_VOID_T_HPP_INCLUDED
|
|||
#define MOCK_VOID_T_HPP_INCLUDED
|
|||
|
|||
namespace mock { namespace detail { |
|||
template<typename...> |
|||
struct make_void |
|||
{ |
|||
using type = void; |
|||
}; |
|||
/// Standard helper to implement the detection idiom. Returns always void
|
|||
template<typename... Ts> |
|||
using void_t = typename make_void<Ts...>::type; |
|||
}} // namespace mock::detail
|
|||
|
|||
#endif // MOCK_VOID_T_HPP_INCLUDED
|
@ -0,0 +1,70 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_ERROR_HPP_INCLUDED
|
|||
#define MOCK_ERROR_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#ifdef MOCK_USE_BOOST_TEST
|
|||
# include "exception.hpp"
|
|||
# include <boost/exception/enable_current_exception.hpp>
|
|||
# include <boost/test/framework.hpp>
|
|||
# include <boost/test/test_tools.hpp>
|
|||
# include <boost/test/unit_test_suite.hpp>
|
|||
# include <boost/version.hpp>
|
|||
|
|||
namespace mock { |
|||
template<typename Result> |
|||
struct error |
|||
{ |
|||
static Result abort() |
|||
{ |
|||
boost::unit_test::framework::test_unit_aborted(boost::unit_test::framework::current_test_case()); |
|||
throw boost::enable_current_exception(exception()); |
|||
} |
|||
|
|||
static void pass(const char* file, int line) |
|||
{ |
|||
boost::unit_test::unit_test_log.set_checkpoint(file, static_cast<std::size_t>(line)); |
|||
} |
|||
|
|||
template<typename Context> |
|||
static void fail(const char* message, const Context& context, const char* file = "unknown location", int line = 0) |
|||
{ |
|||
boost::unit_test::framework::assertion_result( |
|||
# if BOOST_VERSION < 105900
|
|||
false |
|||
# else
|
|||
boost::unit_test::AR_FAILED |
|||
# endif
|
|||
); |
|||
boost::unit_test::unit_test_log << boost::unit_test::log::begin(file, static_cast<std::size_t>(line)) |
|||
<< boost::unit_test::log_all_errors << message << ": " << context |
|||
<< boost::unit_test::log::end(); |
|||
} |
|||
|
|||
template<typename Context> |
|||
static void call(const Context& context, const char* file, int line) |
|||
{ |
|||
boost::unit_test::framework::assertion_result( |
|||
# if BOOST_VERSION < 105900
|
|||
true |
|||
# else
|
|||
boost::unit_test::AR_PASSED |
|||
# endif
|
|||
); |
|||
boost::unit_test::unit_test_log << boost::unit_test::log::begin(file, static_cast<std::size_t>(line)) |
|||
<< boost::unit_test::log_successful_tests |
|||
<< "mock expectation fulfilled: " << context << boost::unit_test::log::end(); |
|||
} |
|||
}; |
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_USE_BOOST_TEST
|
|||
|
|||
#endif // MOCK_ERROR_HPP_INCLUDED
|
@ -0,0 +1,23 @@ |
|||
// 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_EXCEPTION_HPP_INCLUDED
|
|||
#define MOCK_EXCEPTION_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#ifdef MOCK_USE_BOOST_TEST
|
|||
# include <boost/test/execution_monitor.hpp>
|
|||
|
|||
namespace mock { |
|||
struct exception : virtual boost::execution_aborted |
|||
{}; |
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_USE_BOOST_TEST
|
|||
|
|||
#endif // MOCK_EXCEPTION_HPP_INCLUDED
|
@ -0,0 +1,24 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_FORMAT_HPP_INCLUDED
|
|||
#define MOCK_FORMAT_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include "detail/formatter.hpp"
|
|||
|
|||
namespace mock { |
|||
template<typename T> |
|||
detail::formatter<T> format(const T& t) |
|||
{ |
|||
return detail::formatter<T>(t); |
|||
} |
|||
|
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_FORMAT_HPP_INCLUDED
|
@ -0,0 +1,196 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_LOG_HPP_INCLUDED
|
|||
#define MOCK_LOG_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include "format.hpp"
|
|||
#include "stream.hpp"
|
|||
#include <boost/detail/container_fwd.hpp>
|
|||
#include <boost/none.hpp>
|
|||
#include <memory>
|
|||
#include <type_traits>
|
|||
|
|||
namespace boost { |
|||
template<typename T> |
|||
class shared_ptr; |
|||
template<typename T> |
|||
class weak_ptr; |
|||
template<typename T> |
|||
class reference_wrapper; |
|||
template<typename T> |
|||
class optional; |
|||
|
|||
namespace phoenix { |
|||
template<typename T> |
|||
struct actor; |
|||
} |
|||
namespace lambda { |
|||
template<typename T> |
|||
class lambda_functor; |
|||
} |
|||
namespace assign_detail { |
|||
template<typename T> |
|||
class generic_list; |
|||
} |
|||
} // namespace boost
|
|||
|
|||
namespace mock { |
|||
namespace detail { |
|||
template<typename T> |
|||
void serialize(stream& s, const T& begin, const T& end) |
|||
{ |
|||
s << '('; |
|||
for(T it = begin; it != end; ++it) |
|||
s << (it == begin ? "" : ",") << mock::format(*it); |
|||
s << ')'; |
|||
} |
|||
template<typename T> |
|||
struct is_callable_impl : std::false_type |
|||
{}; |
|||
template<typename R, typename... Args> |
|||
struct is_callable_impl<R(Args...)> : std::true_type |
|||
{}; |
|||
template<typename T> |
|||
struct is_callable : is_callable_impl<std::remove_cv_t<T>> |
|||
{}; |
|||
} // namespace detail
|
|||
|
|||
template<typename T1, typename T2> |
|||
stream& operator<<(stream& s, const std::pair<T1, T2>& p) |
|||
{ |
|||
return s << '(' << mock::format(p.first) << ',' << mock::format(p.second) << ')'; |
|||
} |
|||
|
|||
template<typename T, typename A> |
|||
stream& operator<<(stream& s, const std::deque<T, A>& t) |
|||
{ |
|||
detail::serialize(s, t.begin(), t.end()); |
|||
return s; |
|||
} |
|||
template<typename T, typename A> |
|||
stream& operator<<(stream& s, const std::list<T, A>& t) |
|||
{ |
|||
detail::serialize(s, t.begin(), t.end()); |
|||
return s; |
|||
} |
|||
template<typename T, typename A> |
|||
stream& operator<<(stream& s, const std::vector<T, A>& t) |
|||
{ |
|||
detail::serialize(s, t.begin(), t.end()); |
|||
return s; |
|||
} |
|||
template<typename K, typename T, typename C, typename A> |
|||
stream& operator<<(stream& s, const std::map<K, T, C, A>& t) |
|||
{ |
|||
detail::serialize(s, t.begin(), t.end()); |
|||
return s; |
|||
} |
|||
template<typename K, typename T, typename C, typename A> |
|||
stream& operator<<(stream& s, const std::multimap<K, T, C, A>& t) |
|||
{ |
|||
detail::serialize(s, t.begin(), t.end()); |
|||
return s; |
|||
} |
|||
template<typename T, typename C, typename A> |
|||
stream& operator<<(stream& s, const std::set<T, C, A>& t) |
|||
{ |
|||
detail::serialize(s, t.begin(), t.end()); |
|||
return s; |
|||
} |
|||
template<typename T, typename C, typename A> |
|||
stream& operator<<(stream& s, const std::multiset<T, C, A>& t) |
|||
{ |
|||
detail::serialize(s, t.begin(), t.end()); |
|||
return s; |
|||
} |
|||
template<typename T> |
|||
stream& operator<<(stream& s, const boost::assign_detail::generic_list<T>& t) |
|||
{ |
|||
detail::serialize(s, t.begin(), t.end()); |
|||
return s; |
|||
} |
|||
template<typename T> |
|||
stream& operator<<(stream& s, const boost::reference_wrapper<T>& t) |
|||
{ |
|||
return s << mock::format(t.get()); |
|||
} |
|||
template<typename T> |
|||
stream& operator<<(stream& s, const std::reference_wrapper<T>& t) |
|||
{ |
|||
return s << mock::format(t.get()); |
|||
} |
|||
template<typename T> |
|||
stream& operator<<(stream& s, const boost::shared_ptr<T>& t) |
|||
{ |
|||
return s << mock::format(t.get()); |
|||
} |
|||
template<typename T> |
|||
stream& operator<<(stream& s, const boost::weak_ptr<T>& t) |
|||
{ |
|||
return s << mock::format(t.lock()); |
|||
} |
|||
inline stream& operator<<(stream& s, const boost::none_t&) |
|||
{ |
|||
return s << "none"; |
|||
} |
|||
template<typename T> |
|||
stream& operator<<(stream& s, const boost::optional<T>& t) |
|||
{ |
|||
if(t) |
|||
return s << mock::format(t.get()); |
|||
return s << boost::none; |
|||
} |
|||
|
|||
template<typename T> |
|||
stream& operator<<(stream& s, const std::shared_ptr<T>& t) |
|||
{ |
|||
return s << mock::format(t.get()); |
|||
} |
|||
template<typename T> |
|||
stream& operator<<(stream& s, const std::weak_ptr<T>& t) |
|||
{ |
|||
return s << mock::format(t.lock()); |
|||
} |
|||
template<typename T, typename D> |
|||
stream& operator<<(stream& s, const std::unique_ptr<T, D>& p) |
|||
{ |
|||
return s << mock::format(p.get()); |
|||
} |
|||
|
|||
template<typename T> |
|||
stream& operator<<(stream& s, const boost::lambda::lambda_functor<T>&) |
|||
{ |
|||
return s << '?'; |
|||
} |
|||
template<typename T> |
|||
stream& operator<<(stream& s, const boost::phoenix::actor<T>&) |
|||
{ |
|||
return s << '?'; |
|||
} |
|||
|
|||
inline stream& operator<<(stream& s, std::nullptr_t) |
|||
{ |
|||
return s << "nullptr"; |
|||
} |
|||
|
|||
template<typename T> |
|||
std::enable_if_t<detail::is_callable<T>::value, stream&> operator<<(stream& s, T*) |
|||
{ |
|||
return s << '?'; |
|||
} |
|||
template<typename T> |
|||
std::enable_if_t<!detail::is_callable<T>::value, stream&> operator<<(stream& s, T* t) |
|||
{ |
|||
*s.s_ << t; |
|||
return s; |
|||
} |
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_LOG_HPP_INCLUDED
|
@ -0,0 +1,74 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_MATCHER_HPP_INCLUDED
|
|||
#define MOCK_MATCHER_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include "constraints.hpp"
|
|||
#include "detail/is_functor.hpp"
|
|||
#include "detail/ref_arg.hpp"
|
|||
#include "log.hpp"
|
|||
#include <cstring>
|
|||
#include <functional>
|
|||
#include <type_traits>
|
|||
|
|||
namespace mock { |
|||
template<typename Actual, typename Expected, typename Enable = void> |
|||
class matcher |
|||
{ |
|||
public: |
|||
explicit matcher(Expected expected) : expected_(expected) {} |
|||
bool operator()(std::add_lvalue_reference_t<const Actual> actual) |
|||
{ |
|||
return mock::equal(mock::unwrap_ref(expected_)).c_(actual); |
|||
} |
|||
friend std::ostream& operator<<(std::ostream& s, const matcher& m) { return s << mock::format(m.expected_); } |
|||
|
|||
private: |
|||
Expected expected_; |
|||
}; |
|||
|
|||
template<> |
|||
class matcher<const char*, const char*> |
|||
{ |
|||
public: |
|||
explicit matcher(const char* expected) : expected_(expected) {} |
|||
bool operator()(const char* actual) { return std::strcmp(actual, expected_) == 0; } |
|||
friend std::ostream& operator<<(std::ostream& s, const matcher& m) { return s << mock::format(m.expected_); } |
|||
|
|||
private: |
|||
const char* expected_; |
|||
}; |
|||
|
|||
template<typename Actual, typename Constraint> |
|||
class matcher<Actual, mock::constraint<Constraint>> |
|||
{ |
|||
public: |
|||
explicit matcher(const constraint<Constraint>& c) : c_(c.c_) {} |
|||
bool operator()(detail::ref_arg_t<Actual> actual) { return c_(static_cast<detail::ref_arg_t<Actual>>(actual)); } |
|||
friend std::ostream& operator<<(std::ostream& s, const matcher& m) { return s << mock::format(m.c_); } |
|||
|
|||
private: |
|||
Constraint c_; |
|||
}; |
|||
|
|||
template<typename Actual, typename Functor> |
|||
class matcher<Actual, Functor, std::enable_if_t<detail::is_functor<Functor, Actual>::value>> |
|||
{ |
|||
public: |
|||
explicit matcher(const Functor& f) : c_(f) {} |
|||
bool operator()(detail::ref_arg_t<Actual> actual) { return c_(static_cast<detail::ref_arg_t<Actual>>(actual)); } |
|||
friend std::ostream& operator<<(std::ostream& s, const matcher& m) { return s << mock::format(m.c_); } |
|||
|
|||
private: |
|||
Functor c_; |
|||
}; |
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_MATCHER_HPP_INCLUDED
|
@ -0,0 +1,116 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_MOCK_HPP_INCLUDED
|
|||
#define MOCK_MOCK_HPP_INCLUDED
|
|||
|
|||
#include "cleanup.hpp"
|
|||
#include "config.hpp"
|
|||
#include "detail/mock_impl.hpp"
|
|||
#include "object.hpp"
|
|||
#include "reset.hpp"
|
|||
#include "verify.hpp"
|
|||
|
|||
/// MOCK_CLASS( name )
|
|||
/// Define a class
|
|||
#define MOCK_CLASS(name) struct name : mock::object
|
|||
|
|||
/// MOCK_BASE_CLASS( name, base )
|
|||
/// Define a class deriving from a base class
|
|||
#define MOCK_BASE_CLASS(name, ...) struct name : __VA_ARGS__, mock::object, mock::detail::base<__VA_ARGS__>
|
|||
|
|||
/// MOCK_PROTECT_SIGNATURE( signature )
|
|||
/// Use this with MOCK_FUNCTION/MOCK_*_METHOD if the return type contains commas
|
|||
#define MOCK_PROTECT_SIGNATURE(...) mock::detail::unwrap_signature_t<void(__VA_ARGS__)>
|
|||
|
|||
/// MOCK_FUNCTOR( name, signature )
|
|||
/// Define a callable variable/member
|
|||
#define MOCK_FUNCTOR(name, ...) mock::detail::functor<__VA_ARGS__> name, name##_mock
|
|||
|
|||
/// MOCK_CONVERSION_OPERATOR( [calling convention] name, type, identifier )
|
|||
/// generates both const and non-const conversion operators
|
|||
#define MOCK_CONVERSION_OPERATOR(M, T, identifier) \
|
|||
M T() const { return MOCK_ANONYMOUS_HELPER(identifier)(); } \ |
|||
M T() { return MOCK_ANONYMOUS_HELPER(identifier)(); } \ |
|||
MOCK_METHOD_HELPER(T(), identifier) |
|||
/// MOCK_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier )
|
|||
/// generates only a const conversion operator
|
|||
#define MOCK_CONST_CONVERSION_OPERATOR(M, T, identifier) \
|
|||
M T() const { return MOCK_ANONYMOUS_HELPER(identifier)(); } \ |
|||
MOCK_METHOD_HELPER(T(), identifier) |
|||
/// MOCK_NON_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier )
|
|||
/// generates only a non-const conversion operator
|
|||
#define MOCK_NON_CONST_CONVERSION_OPERATOR(M, T, identifier) \
|
|||
M T() { return MOCK_ANONYMOUS_HELPER(identifier)(); } \ |
|||
MOCK_METHOD_HELPER(T(), identifier) |
|||
|
|||
/// MOCK_CONSTRUCTOR( [calling convention] name, arity, parameters, identifier )
|
|||
/// As constructors do not have a return type, the usual signature gets restricted here to just the parameters.
|
|||
#define MOCK_CONSTRUCTOR(T, arity, parameters, identifier) MOCK_CONSTRUCTOR_AUX(T, arity, parameters, identifier)
|
|||
|
|||
/// MOCK_DESTRUCTOR( [calling convention] ~name, identifier )
|
|||
#define MOCK_DESTRUCTOR(T, identifier) \
|
|||
T() \ |
|||
{ \ |
|||
try \ |
|||
{ \ |
|||
MOCK_ANONYMOUS_HELPER(identifier)(); \ |
|||
} catch(...) \ |
|||
{} \ |
|||
} \ |
|||
MOCK_METHOD_HELPER(void(), identifier) |
|||
|
|||
/// MOCK_METHOD( [calling convention] name, arity[, signature[, identifier]] )
|
|||
/// generates both const and non-const methods
|
|||
/// The 'signature' can be omitted if it can be uniquely identified from the base class
|
|||
/// if 'identifier' is omitted it will default to 'name'
|
|||
#define MOCK_METHOD(M, ...) \
|
|||
MOCK_METHOD_EXT(M, \ |
|||
MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \ |
|||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, MOCK_SIGNATURE(M), ), \ |
|||
MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M, )) |
|||
/// MOCK_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] )
|
|||
/// generates only the const version of the method
|
|||
/// The 'signature' can be omitted if it can be uniquely identified from the base class
|
|||
/// if 'identifier' is omitted it will default to 'name'
|
|||
#define MOCK_CONST_METHOD(M, ...) \
|
|||
MOCK_CONST_METHOD_EXT(M, \ |
|||
MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \ |
|||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, MOCK_SIGNATURE(M), ), \ |
|||
MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M, )) |
|||
/// MOCK_NON_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] )
|
|||
/// generates only the non-const version of the method
|
|||
/// The 'signature' can be omitted if it can be uniquely identified from the base class
|
|||
/// if 'identifier' is omitted it will default to 'name'
|
|||
#define MOCK_NON_CONST_METHOD(M, ...) \
|
|||
MOCK_NON_CONST_METHOD_EXT(M, \ |
|||
MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \ |
|||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, MOCK_SIGNATURE(M), ), \ |
|||
MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M, )) |
|||
|
|||
/// MOCK_FUNCTION( [calling convention] name, arity, signature[, identifier] )
|
|||
/// if 'identifier' is omitted it will default to 'name'
|
|||
#define MOCK_FUNCTION(F, arity, ...) \
|
|||
MOCK_FUNCTION_AUX(F, arity, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F, ), inline) |
|||
|
|||
/// MOCK_STATIC_METHOD( [calling convention] name, arity, signature[, identifier] )
|
|||
/// if 'identifier' is omitted it will default to 'name'
|
|||
#define MOCK_STATIC_METHOD(F, arity, ...) \
|
|||
MOCK_FUNCTION_AUX(F, arity, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F, ), static) |
|||
|
|||
/// MOCK_EXPECT( identifier )
|
|||
/// Begin setting up expectation for the identifier
|
|||
#define MOCK_EXPECT(identifier) MOCK_HELPER(identifier).expect(__FILE__, __LINE__)
|
|||
/// MOCK_RESET( identifier )
|
|||
/// Reset all pending expectations for the identifier
|
|||
#define MOCK_RESET(identifier) MOCK_HELPER(identifier).reset(__FILE__, __LINE__)
|
|||
/// MOCK_VERIFY( identifier )
|
|||
/// Verify all expectations for the identifier have been met
|
|||
#define MOCK_VERIFY(identifier) MOCK_HELPER(identifier).verify(__FILE__, __LINE__)
|
|||
|
|||
#endif // MOCK_MOCK_HPP_INCLUDED
|
@ -0,0 +1,70 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_OBJECT_HPP_INCLUDED
|
|||
#define MOCK_OBJECT_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include "detail/object_impl.hpp"
|
|||
#include "detail/root.hpp"
|
|||
#include "detail/type_name.hpp"
|
|||
#include <boost/optional.hpp>
|
|||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
|||
#include <memory>
|
|||
#include <type_traits>
|
|||
|
|||
namespace mock { |
|||
class object; |
|||
|
|||
namespace detail { |
|||
template<typename E> |
|||
E& configure(const object& o, |
|||
E& e, |
|||
boost::unit_test::const_string instance, |
|||
boost::optional<type_name> type, |
|||
boost::unit_test::const_string name); |
|||
|
|||
template<typename T, typename E> |
|||
E& configure(const T& t, |
|||
E& e, |
|||
boost::unit_test::const_string instance, |
|||
boost::optional<type_name> type, |
|||
boost::unit_test::const_string name, |
|||
std::enable_if_t<!std::is_base_of<object, T>::value>* = 0) |
|||
{ |
|||
e.configure(detail::root, &t, instance, type, name); |
|||
return e; |
|||
} |
|||
} // namespace detail
|
|||
class object |
|||
{ |
|||
public: |
|||
object() : impl_(std::make_shared<detail::object_impl>()) {} |
|||
|
|||
protected: |
|||
~object() = default; |
|||
|
|||
public: |
|||
std::shared_ptr<detail::object_impl> impl_; |
|||
}; |
|||
|
|||
namespace detail { |
|||
template<typename E> |
|||
E& configure(const object& o, |
|||
E& e, |
|||
boost::unit_test::const_string instance, |
|||
boost::optional<type_name> type, |
|||
boost::unit_test::const_string name) |
|||
{ |
|||
e.configure(*o.impl_, o.impl_.get(), instance, type, name); |
|||
return e; |
|||
} |
|||
} // namespace detail
|
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_OBJECT_HPP_INCLUDED
|
@ -0,0 +1,33 @@ |
|||
// 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_RESET_HPP_INCLUDED
|
|||
#define MOCK_RESET_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include "detail/functor.hpp"
|
|||
#include "detail/root.hpp"
|
|||
#include "object.hpp"
|
|||
|
|||
namespace mock { |
|||
inline void reset() |
|||
{ |
|||
detail::root.reset(); |
|||
} |
|||
inline void reset(const object& o) |
|||
{ |
|||
o.impl_->reset(); |
|||
} |
|||
template<typename Signature> |
|||
void reset(detail::functor<Signature>& f) |
|||
{ |
|||
f.reset(); |
|||
} |
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_RESET_HPP_INCLUDED
|
@ -0,0 +1,26 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_SEQUENCE_HPP_INCLUDED
|
|||
#define MOCK_SEQUENCE_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include "detail/sequence_impl.hpp"
|
|||
#include <memory>
|
|||
|
|||
namespace mock { |
|||
class sequence |
|||
{ |
|||
public: |
|||
sequence() : impl_(std::make_shared<detail::sequence_impl>()) {} |
|||
|
|||
std::shared_ptr<detail::sequence_impl> impl_; |
|||
}; |
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_SEQUENCE_HPP_INCLUDED
|
@ -0,0 +1,114 @@ |
|||
// 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)
|
|||
|
|||
#ifndef MOCK_STREAM_HPP_INCLUDED
|
|||
#define MOCK_STREAM_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include <memory>
|
|||
#include <ostream>
|
|||
|
|||
namespace mock { |
|||
struct stream |
|||
{ |
|||
explicit stream(std::ostream& s) : s_(&s) {} |
|||
std::ostream* s_; |
|||
}; |
|||
|
|||
#ifdef MOCK_USE_CONVERSIONS
|
|||
|
|||
namespace detail { namespace conversion { |
|||
struct sink |
|||
{ |
|||
template<typename T> |
|||
sink(const T&) |
|||
{} |
|||
}; |
|||
|
|||
inline std::ostream& operator<<(std::ostream& s, const sink&) { return s << '?'; } |
|||
|
|||
struct holder |
|||
{ |
|||
holder() = default; |
|||
holder(const holder&) = delete; |
|||
holder& operator=(const holder&) = delete; |
|||
|
|||
virtual ~holder() = default; |
|||
virtual void serialize(std::ostream& s) const = 0; |
|||
}; |
|||
|
|||
template<typename T> |
|||
struct holder_imp : holder |
|||
{ |
|||
explicit holder_imp(const T& t) : t_(t) {} |
|||
virtual void serialize(std::ostream& s) const |
|||
{ |
|||
// if an error about an ambiguous conversion is generated by the
|
|||
// line below the solution is to add a serialization operator to a
|
|||
// mock::stream for T
|
|||
s << t_; |
|||
} |
|||
const T& t_; |
|||
}; |
|||
|
|||
struct any |
|||
{ |
|||
template<typename T> |
|||
any(const T& t) : h_(std::make_unique<holder_imp<T>>(t)) |
|||
{} |
|||
std::unique_ptr<holder> h_; |
|||
}; |
|||
}} // namespace detail::conversion
|
|||
|
|||
inline stream& operator<<(stream& s, const detail::conversion::any& d) |
|||
{ |
|||
d.h_->serialize(*s.s_); |
|||
return s; |
|||
} |
|||
|
|||
#else // MOCK_USE_CONVERSIONS
|
|||
|
|||
namespace detail { namespace conversion { |
|||
template<typename S, typename T> |
|||
S& operator<<(S& s, const T&) |
|||
{ |
|||
return s << '?'; |
|||
} |
|||
}} // namespace detail::conversion
|
|||
|
|||
template<typename T> |
|||
stream& operator<<(stream& s, const T& t) |
|||
{ |
|||
using namespace detail::conversion; |
|||
*s.s_ << t; |
|||
return s; |
|||
} |
|||
|
|||
#endif // MOCK_USE_CONVERSIONS
|
|||
|
|||
namespace detail { |
|||
template<typename T> |
|||
void serialize(stream& s, const T& t) |
|||
{ |
|||
// if an error about an ambiguous conversion is generated by the
|
|||
// line below the solution is to add a serialization operator to a
|
|||
// mock::stream for T
|
|||
s << t; |
|||
} |
|||
inline void serialize(stream& s, bool b) { s << (b ? "true" : "false"); } |
|||
template<typename C, typename T, typename A> |
|||
void serialize(stream& s, const std::basic_string<C, T, A>& str) |
|||
{ |
|||
s << '"' << str << '"'; |
|||
} |
|||
inline void serialize(stream& s, const char* const str) { s << '"' << str << '"'; } |
|||
inline void serialize(stream& s, unsigned char c) { s << static_cast<int>(c); } |
|||
} // namespace detail
|
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_STREAM_HPP_INCLUDED
|
@ -0,0 +1,41 @@ |
|||
// http://turtle.sourceforge.net
|
|||
//
|
|||
// Copyright Alexander Grund 2020
|
|||
//
|
|||
// 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_UNWRAP_REFERENCE_HPP_INCLUDED
|
|||
#define MOCK_UNWRAP_REFERENCE_HPP_INCLUDED
|
|||
|
|||
#include <functional>
|
|||
#include <type_traits>
|
|||
|
|||
namespace mock { |
|||
template<class T> |
|||
struct unwrap_reference |
|||
{ |
|||
using type = T; |
|||
}; |
|||
template<class T> |
|||
struct unwrap_reference<std::reference_wrapper<T>> |
|||
{ |
|||
using type = T; |
|||
}; |
|||
template<class T> |
|||
struct unwrap_reference<const std::reference_wrapper<T>> |
|||
{ |
|||
using type = T; |
|||
}; |
|||
template<class T> |
|||
using unwrap_reference_t = typename unwrap_reference<T>::type; |
|||
|
|||
template<class T> |
|||
BOOST_FORCEINLINE unwrap_reference_t<T>& unwrap_ref(T& t) noexcept |
|||
{ |
|||
return t; |
|||
} |
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_UNWRAP_REFERENCE_HPP_INCLUDED
|
@ -0,0 +1,33 @@ |
|||
// 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_VERIFY_HPP_INCLUDED
|
|||
#define MOCK_VERIFY_HPP_INCLUDED
|
|||
|
|||
#include "config.hpp"
|
|||
#include "detail/functor.hpp"
|
|||
#include "detail/root.hpp"
|
|||
#include "object.hpp"
|
|||
|
|||
namespace mock { |
|||
inline bool verify() |
|||
{ |
|||
return detail::root.verify(); |
|||
} |
|||
inline bool verify(const object& o) |
|||
{ |
|||
return o.impl_->verify(); |
|||
} |
|||
template<typename Signature> |
|||
bool verify(const detail::functor<Signature>& f) |
|||
{ |
|||
return f.verify(); |
|||
} |
|||
} // namespace mock
|
|||
|
|||
#endif // MOCK_VERIFY_HPP_INCLUDED
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue