diff --git a/qa/qa_utils/include/qa_utils/wx_utils/unit_test_utils.h b/qa/qa_utils/include/qa_utils/wx_utils/unit_test_utils.h index f6e4541217..f7c8bfbb5d 100644 --- a/qa/qa_utils/include/qa_utils/wx_utils/unit_test_utils.h +++ b/qa/qa_utils/include/qa_utils/wx_utils/unit_test_utils.h @@ -24,7 +24,10 @@ #ifndef UNIT_TEST_UTILS__H #define UNIT_TEST_UTILS__H +#define BOOST_NO_AUTO_PTR + #include +#include #include diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index c95550fe9d..b268b68621 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -41,3 +41,4 @@ add_subdirectory( picosha2 ) add_subdirectory( json_schema_validator ) add_subdirectory( pegtl ) add_subdirectory( 3dxware_sdk ) +add_subdirectory( turtle ) diff --git a/thirdparty/turtle/BOOST.LICENSE_1_0.txt b/thirdparty/turtle/BOOST.LICENSE_1_0.txt new file mode 100644 index 0000000000..36b7cd93cd --- /dev/null +++ b/thirdparty/turtle/BOOST.LICENSE_1_0.txt @@ -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. diff --git a/thirdparty/turtle/CMakeLists.txt b/thirdparty/turtle/CMakeLists.txt new file mode 100644 index 0000000000..dfa23ac16d --- /dev/null +++ b/thirdparty/turtle/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library( turtle INTERFACE ) + +target_include_directories( turtle INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ) diff --git a/thirdparty/turtle/README.txt b/thirdparty/turtle/README.txt new file mode 100644 index 0000000000..784e784f2f --- /dev/null +++ b/thirdparty/turtle/README.txt @@ -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. diff --git a/thirdparty/turtle/turtle/catch.hpp b/thirdparty/turtle/turtle/catch.hpp new file mode 100644 index 0000000000..77c753bb76 --- /dev/null +++ b/thirdparty/turtle/turtle/catch.hpp @@ -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 + +template +struct catch_mock_error_policy +{ + static Result abort() + { + FAIL("Aborted"); + throw std::runtime_error("unreachable"); + } + + template + 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 + 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 diff --git a/thirdparty/turtle/turtle/cleanup.hpp b/thirdparty/turtle/turtle/cleanup.hpp new file mode 100644 index 0000000000..e2bde3dc37 --- /dev/null +++ b/thirdparty/turtle/turtle/cleanup.hpp @@ -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 +#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 diff --git a/thirdparty/turtle/turtle/config.hpp b/thirdparty/turtle/turtle/config.hpp new file mode 100644 index 0000000000..111d09d89b --- /dev/null +++ b/thirdparty/turtle/turtle/config.hpp @@ -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 + +#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 diff --git a/thirdparty/turtle/turtle/constraint.hpp b/thirdparty/turtle/turtle/constraint.hpp new file mode 100644 index 0000000000..8dddb222a3 --- /dev/null +++ b/thirdparty/turtle/turtle/constraint.hpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mock { +template +struct constraint +{ + constraint() {} + constraint(const Constraint& c) : c_(c) {} + Constraint c_; +}; + +namespace detail { + template + class and_ + { + public: + and_(const Lhs& lhs, const Rhs& rhs) : lhs_(lhs), rhs_(rhs) {} + template + 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 + class or_ + { + public: + or_(const Lhs& lhs, const Rhs& rhs) : lhs_(lhs), rhs_(rhs) {} + template + 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 + class not_ + { + public: + explicit not_(const Constraint& c) : c_(c) {} + template + 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 +const constraint> operator||(const constraint& lhs, const constraint& rhs) +{ + return detail::or_(lhs.c_, rhs.c_); +} + +template +const constraint> operator&&(const constraint& lhs, const constraint& rhs) +{ + return detail::and_(lhs.c_, rhs.c_); +} + +template +const constraint> operator!(const constraint& c) +{ + return detail::not_(c.c_); +} +} // namespace mock + +#define MOCK_UNARY_CONSTRAINT(Name, n, Args, Expr) \ + namespace detail { \ + struct Name \ + { \ + template \ + 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 Name; + +#define MOCK_CONSTRAINT_ASSIGN(z, n, d) expected##n(std::forward(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 + +#define MOCK_CONSTRAINT_CREF_PARAM(z, n, Args) \ + const mock::unwrap_reference_t& 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(BOOST_PP_ARRAY_ELEM(n, Args)) + +#define MOCK_NARY_CONSTRAINT(Name, n, Args, Expr) \ + namespace detail { \ + template \ + struct Name \ + { \ + template \ + explicit Name(BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ARGS, _)) : BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ASSIGN, _) \ + {} \ + template \ + bool operator()(const Actual& actual) const \ + { \ + return test(actual, BOOST_PP_ENUM(n, MOCK_CONSTRAINT_UNWRAP_REF, _)); \ + } \ + template \ + 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 \ + mock::constraint> Name( \ + BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ARG, (n, Args))) \ + { \ + return detail::Name( \ + 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 diff --git a/thirdparty/turtle/turtle/constraints.hpp b/thirdparty/turtle/turtle/constraints.hpp new file mode 100644 index 0000000000..572b7d9252 --- /dev/null +++ b/thirdparty/turtle/turtle/constraints.hpp @@ -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 +#if BOOST_VERSION >= 107000 +# include +#else +# include +#endif +#include +#include +#include + +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 + bool is_small(const T& t, const Tolerance& tolerance) + { + return boost::math::fpc::small_with_tolerance(tolerance)(t); + } + + template + bool is_close(const T1& t1, const T2& t2, const Tolerance& tolerance) + { + typedef std::common_type_t common_type; + return boost::math::fpc::close_at_tolerance(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 + struct has_equal_to : std::false_type + {}; + + template + struct has_equal_to() == std::declval())>> : std::true_type + {}; + + template + struct equal + { + explicit equal(Expected expected) : expected_(expected) {} + template + bool operator()(const Actual& actual, + std::enable_if_t>::value>* = 0) const + { + return actual == unwrap_ref(expected_); + } + template + bool operator()(const Actual& actual, + std::enable_if_t>::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 + struct same + { + explicit same(const Expected& expected) : expected_(std::addressof(unwrap_ref(expected))) {} + template + 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_; + }; + + template + struct retrieve + { + explicit retrieve(Expected& expected) : expected_(std::addressof(unwrap_ref(expected))) {} + template + bool operator()( + const Actual& actual, + std::enable_if_t>::value>* = 0) const + { + *expected_ = actual; + return true; + } + template + bool operator()( + Actual&& actual, + std::enable_if_t>::value>* = 0) const + { + *expected_ = std::move(actual); + return true; + } + template + bool operator()(Actual& actual, + std::enable_if_t>::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_; + }; + + template + struct assign + { + explicit assign(const Expected& expected) : expected_(expected) {} + template + bool operator()(Actual& actual) const + { + actual = unwrap_ref(expected_); + return true; + } + template + bool operator()(Actual* actual, + std::enable_if_t, 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 + 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 +constraint> equal(T&& t) +{ + return detail::equal(std::forward(t)); +} + +template +constraint> same(T& t) +{ + return detail::same(t); +} +template +constraint> retrieve(T& t) +{ + return detail::retrieve(t); +} +template +constraint> assign(T t) +{ + return detail::assign(t); +} +template +constraint> contain(T t) +{ + return detail::contain(t); +} + +template +constraint call(T t) +{ + return constraint(t); +} +} // namespace mock + +#endif // MOCK_CONSTRAINTS_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/action.hpp b/thirdparty/turtle/turtle/detail/action.hpp new file mode 100644 index 0000000000..8b267e55a9 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/action.hpp @@ -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 +#include +#include + +namespace mock { namespace detail { + template + class action_base + { + private: + typedef std::function functor_type; + typedef std::function 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 + void throws(Exception e) + { + a_ = [e]() -> Result { throw e; }; + } + + protected: + void set(const action_type& a) { a_ = a; } + template + void set(const std::reference_wrapper& 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 + struct value_imp : value + { + using type = std::remove_const_t>; + + template + value_imp(U&& t) : t_(std::forward(t)) + {} + type t_; + }; + + template + class action : public action_base + { + public: + template + void returns(const Value& v) + { + this->set(std::ref(store(v))); + } + template + void returns(const std::reference_wrapper& r) + { + this->set(r); + } + + template + void moves(Value&& v) + { + auto vRef = std::ref(store(std::move(v))); + this->set([vRef]() { return std::move(vRef.get()); }); + } + + private: + template + typename value_imp::type& store(T&& t) + { + v_ = std::make_unique>(std::forward(t)); + return static_cast&>(*v_).t_; + } + template + std::remove_reference_t& store(T* t) + { + v_ = std::make_unique>(t); + return static_cast&>(*v_).t_; + } + + std::unique_ptr v_; + }; + + template + class action : public action_base + { + public: + action() + { + this->set([]() {}); + } + }; + +}} // namespace mock::detail + +#endif // MOCK_ACTION_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/addressof.hpp b/thirdparty/turtle/turtle/detail/addressof.hpp new file mode 100644 index 0000000000..4e48a8dc2b --- /dev/null +++ b/thirdparty/turtle/turtle/detail/addressof.hpp @@ -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 + +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 diff --git a/thirdparty/turtle/turtle/detail/child.hpp b/thirdparty/turtle/turtle/detail/child.hpp new file mode 100644 index 0000000000..a5621fbc73 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/child.hpp @@ -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 +#include +#include + +namespace mock { namespace detail { + class child + { + public: + child() : parent_(0) {} + void update(parent& p, + boost::unit_test::const_string instance, + boost::optional 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 diff --git a/thirdparty/turtle/turtle/detail/context.hpp b/thirdparty/turtle/turtle/detail/context.hpp new file mode 100644 index 0000000000..28fc98c088 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/context.hpp @@ -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 +#include +#include + +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, + 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 diff --git a/thirdparty/turtle/turtle/detail/expectation.hpp b/thirdparty/turtle/turtle/detail/expectation.hpp new file mode 100644 index 0000000000..d4e477aaa2 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/expectation.hpp @@ -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 +#include +#include +#include + +namespace mock { namespace detail { + template + class default_matcher : public matcher_base + { + private: + bool operator()(ref_arg_t...) 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 + class single_matcher; + + template + class single_matcher : public matcher_base + { + 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(constraints)...) {} + + private: + template + bool is_valid_impl(std::index_sequence, ref_arg_t... t) + { + using expander = bool[]; + bool result = true; + (void)expander{ result &= std::get(matchers_)(static_cast>(t))... }; + return result; + } + bool operator()(ref_arg_t... t) override + { + return is_valid_impl(std::make_index_sequence{}, static_cast>(t)...); + } + template + void serialize_impl(std::index_sequence, std::ostream& s) const + { + using expander = int[]; + s << std::get<0>(matchers_); + (void)expander{ 0, (s << ", " << std::get(matchers_), 0)... }; + } + void serialize(std::ostream& s) const override + { + serialize_impl(std::make_index_sequence{}, s); + } + + private: + std::tuple...> matchers_; + }; + + template + class multi_matcher : public matcher_base + { + 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... t) override { return f_(static_cast>(t)...); } + void serialize(std::ostream& s) const override { s << mock::format(f_); } + + private: + F f_; + }; + + template + class expectation; + + template + class expectation : public action + { + static constexpr std::size_t arity = sizeof...(Args); + + public: + expectation() : expectation("unknown location", 0) {} + expectation(const char* file, int line) + : invocation_(std::make_unique()), matcher_(std::make_unique>()), + 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 i) { invocation_ = std::move(i); } + + template + std::enable_if_t<(arity > 0u) && sizeof...(Constraints) == arity> with(Constraints... c) + { + matcher_ = std::make_unique>(c...); + } + template + std::enable_if_t<(Arity > 1u)> with(const Constraint& c) + { + matcher_ = std::make_unique>(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... t) const + { + return !invocation_->exhausted() && (*matcher_)(static_cast>(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_; + std::unique_ptr> matcher_; + std::vector> sequences_; + const char* file_; + int line_; + }; +}} // namespace mock::detail + +#endif // MOCK_EXPECTATION_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/expectation_template.hpp b/thirdparty/turtle/turtle/detail/expectation_template.hpp new file mode 100644 index 0000000000..20bf6f443c --- /dev/null +++ b/thirdparty/turtle/turtle/detail/expectation_template.hpp @@ -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 diff --git a/thirdparty/turtle/turtle/detail/formatter.hpp b/thirdparty/turtle/turtle/detail/formatter.hpp new file mode 100644 index 0000000000..a27923afed --- /dev/null +++ b/thirdparty/turtle/turtle/detail/formatter.hpp @@ -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 + +namespace mock { namespace detail { + template + struct formatter + { + explicit formatter(const T& t) : t_(std::addressof(t)) {} + void serialize(stream& s) const { detail::serialize(s, *t_); } + const T* t_; + }; + + template + stream& operator<<(stream& s, const formatter& f) + { + f.serialize(s); + return s; + } + + template + std::ostream& operator<<(std::ostream& s, const formatter& f) + { + stream ss(s); + f.serialize(ss); + return s; + } +}} // namespace mock::detail + +#endif // MOCK_FORMATTER_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/function.hpp b/thirdparty/turtle/turtle/detail/function.hpp new file mode 100644 index 0000000000..e4e8c64e08 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/function.hpp @@ -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 +#include +#include + +namespace mock { namespace detail { + template + class function; + + template + class function + { + private: + typedef function_impl impl_type; + typedef typename impl_type::wrapper_type expectation_type; + typedef typename impl_type::error_type error_type; + + public: + function() : impl_(std::make_shared()) {} + + 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>(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, + boost::unit_test::const_string name) const + { + impl_->add(c, p, instance, type, name); + } + + private: + std::shared_ptr impl_; + }; +}} // namespace mock::detail + +#endif // MOCK_FUNCTION_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/function_impl.hpp b/thirdparty/turtle/turtle/detail/function_impl.hpp new file mode 100644 index 0000000000..e3524a298f --- /dev/null +++ b/thirdparty/turtle/turtle/detail/function_impl.hpp @@ -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 +#include +#include + +#ifndef MOCK_ERROR_POLICY +# error no error policy has been set +#endif + +namespace mock { namespace detail { + template + struct wrapper_base + { + wrapper_base(E& e) : e_(&e) {} + + template + void returns(T t) + { + e_->returns(t); + } + + E* e_; + }; + template + struct wrapper_base + { + wrapper_base(E& e) : e_(&e) {} + + E* e_; + }; + template + struct wrapper_base + { + wrapper_base(E& e) : e_(&e) {} + + void returns(R* r) { e_->returns(r); } + template + void returns(const std::reference_wrapper& 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 + class lazy_args; + + template + class function_impl; + + template + class function_impl : public verifiable, public std::enable_shared_from_this> + { + public: + typedef safe_error> error_type; + + public: + function_impl() : context_(0), valid_(true), exceptions_(exceptions()), mutex_(std::make_shared()) {} + 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 guard = this->shared_from_this(); + expectations_.clear(); + } + + private: + typedef expectation expectation_type; + + class wrapper : public wrapper_base + { + private: + typedef wrapper_base base_type; + static constexpr std::size_t arity = sizeof...(Args); + + public: + wrapper(const std::shared_ptr& 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()); + return *this; + } + wrapper& never() + { + this->e_->invoke(std::make_unique()); + return *this; + } + wrapper& exactly(std::size_t count) + { + this->e_->invoke(std::make_unique(count)); + return *this; + } + wrapper& at_least(std::size_t min) + { + this->e_->invoke(std::make_unique(min)); + return *this; + } + wrapper& at_most(std::size_t max) + { + this->e_->invoke(std::make_unique(max)); + return *this; + } + wrapper& between(std::size_t min, std::size_t max) + { + this->e_->invoke(std::make_unique(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 + 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 + wrapper& in(sequence& s0, MockSequences&... s) + { + using expander = int[]; + (void)expander{ (this->e_->add(s0), 0), (this->e_->add(s), 0)... }; + return *this; + } + + template + void calls(TT t) + { + this->e_->calls(t); + } + template + void throws(TT t) + { + this->e_->throws(t); + } + template + 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...) << lazy_expectations(this) + + lock _(mutex_); + valid_ = false; + for(const auto& expectation : expectations_) + { + if(expectation.is_valid(static_cast>(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>(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, + 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 expectations_; + context* context_; + mutable bool valid_; + const int exceptions_; + const std::shared_ptr mutex_; + }; + + template + class lazy_args : lazy_args + { + ArgFirst& arg_; + + public: + lazy_args(ArgFirst& arg, std::add_lvalue_reference_t... args) + : lazy_args(args...), arg_(arg) + {} + std::ostream& print(std::ostream& s) const + { + s << ' ' << mock::format(arg_) << ','; + return lazy_args::print(s); + } + }; + template + class lazy_args + { + 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 + std::ostream& operator<<(std::ostream& s, const lazy_args& a) + { + s << '('; + return a.print(s) << ')'; + } +}} // namespace mock::detail + +#endif // MOCK_FUNCTION_IMPL_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/function_impl_template.hpp b/thirdparty/turtle/turtle/detail/function_impl_template.hpp new file mode 100644 index 0000000000..3a6897115a --- /dev/null +++ b/thirdparty/turtle/turtle/detail/function_impl_template.hpp @@ -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 diff --git a/thirdparty/turtle/turtle/detail/function_iterate.hpp b/thirdparty/turtle/turtle/detail/function_iterate.hpp new file mode 100644 index 0000000000..f86538e4c2 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/function_iterate.hpp @@ -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 diff --git a/thirdparty/turtle/turtle/detail/function_template.hpp b/thirdparty/turtle/turtle/detail/function_template.hpp new file mode 100644 index 0000000000..0ebfe14452 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/function_template.hpp @@ -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 diff --git a/thirdparty/turtle/turtle/detail/functor.hpp b/thirdparty/turtle/turtle/detail/functor.hpp new file mode 100644 index 0000000000..dfb793d1ea --- /dev/null +++ b/thirdparty/turtle/turtle/detail/functor.hpp @@ -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, public mutex + { + MOCK_SINGLETON_CONS(functor_mutex_t); + }; + MOCK_SINGLETON_INST(functor_mutex) + + template + struct functor : function + { + 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 diff --git a/thirdparty/turtle/turtle/detail/group.hpp b/thirdparty/turtle/turtle/detail/group.hpp new file mode 100644 index 0000000000..d8a8e416da --- /dev/null +++ b/thirdparty/turtle/turtle/detail/group.hpp @@ -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 +#include +#include + +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 verifiables_; + }; +}} // namespace mock::detail + +#endif // MOCK_GROUP_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/invocation.hpp b/thirdparty/turtle/turtle/detail/invocation.hpp new file mode 100644 index 0000000000..5b711e26f2 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/invocation.hpp @@ -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 +#include +#include + +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::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 diff --git a/thirdparty/turtle/turtle/detail/is_functor.hpp b/thirdparty/turtle/turtle/detail/is_functor.hpp new file mode 100644 index 0000000000..bcc0699e31 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/is_functor.hpp @@ -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 + +namespace mock { namespace detail { + /// Trait to return true if F is a functor that can be called with a single argument Arg + template + struct is_functor : std::false_type + {}; + template + struct is_functor()(std::declval()))>> : std::true_type + {}; +}} // namespace mock::detail + +#endif // MOCK_IS_FUNCTOR_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/matcher_base.hpp b/thirdparty/turtle/turtle/detail/matcher_base.hpp new file mode 100644 index 0000000000..abb1fb901b --- /dev/null +++ b/thirdparty/turtle/turtle/detail/matcher_base.hpp @@ -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 + +namespace mock { namespace detail { + template + 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...) = 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 diff --git a/thirdparty/turtle/turtle/detail/matcher_base_template.hpp b/thirdparty/turtle/turtle/detail/matcher_base_template.hpp new file mode 100644 index 0000000000..07fa3264fb --- /dev/null +++ b/thirdparty/turtle/turtle/detail/matcher_base_template.hpp @@ -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 diff --git a/thirdparty/turtle/turtle/detail/mock_impl.hpp b/thirdparty/turtle/turtle/detail/mock_impl.hpp new file mode 100644 index 0000000000..211e81c674 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/mock_impl.hpp @@ -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 +#include +#include + +namespace mock { namespace detail { + /// Simplified trait to extract the argument type of a function signature with 1 argument + template + struct arg_type; + template + struct arg_type + { + using type = U; + }; + /// Used in MOCK_PROTECT_SIGNATURE to unwrap the passed function signature + /// T is something like `void(std::map)` + template + using unwrap_signature_t = std::remove_pointer_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 t##_mock_; \ + mock::detail::function& 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 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::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& t##_mock(mock::detail::context& context, boost::unit_test::const_string instance) \ + { \ + static mock::detail::function 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::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 diff --git a/thirdparty/turtle/turtle/detail/move_helper.hpp b/thirdparty/turtle/turtle/detail/move_helper.hpp new file mode 100644 index 0000000000..87f1f2ddb7 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/move_helper.hpp @@ -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 +#include +#include +#include +#include +#include + +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 diff --git a/thirdparty/turtle/turtle/detail/mutex.hpp b/thirdparty/turtle/turtle/detail/mutex.hpp new file mode 100644 index 0000000000..d74d20d450 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/mutex.hpp @@ -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 + +#ifdef MOCK_THREAD_SAFE + +# ifdef MOCK_HDR_MUTEX +# include +# else +# include +# include +# endif + +namespace mock { namespace detail { +# ifdef MOCK_HDR_MUTEX + typedef std::recursive_mutex mutex; + typedef std::lock_guard scoped_lock; +# else + typedef boost::recursive_mutex mutex; + typedef boost::lock_guard scoped_lock; +# endif + + struct lock + { + public: + lock(const std::shared_ptr& 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 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&) {} + ~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, 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 + struct safe_error + { + static Result abort() + { + scoped_lock _(error_mutex); + return Error::abort(); + } + template + 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 + 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 diff --git a/thirdparty/turtle/turtle/detail/object_impl.hpp b/thirdparty/turtle/turtle/detail/object_impl.hpp new file mode 100644 index 0000000000..081aeb26a1 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/object_impl.hpp @@ -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 +#include + +namespace mock { namespace detail { + class object_impl : public context, public verifiable, public std::enable_shared_from_this + { + public: + object_impl() : mutex_(std::make_shared()) {} + + virtual void add(const void* /*p*/, + verifiable& v, + boost::unit_test::const_string instance, + boost::optional 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 guard = shared_from_this(); + group_.reset(); + } + + private: + group group_; + parent parent_; + std::map children_; + const std::shared_ptr mutex_; + }; +}} // namespace mock::detail + +#endif // MOCK_OBJECT_IMPL_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/parameter.hpp b/thirdparty/turtle/turtle/detail/parameter.hpp new file mode 100644 index 0000000000..38925a2953 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/parameter.hpp @@ -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 +#include +#include + +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 diff --git a/thirdparty/turtle/turtle/detail/parent.hpp b/thirdparty/turtle/turtle/detail/parent.hpp new file mode 100644 index 0000000000..8c3352ee39 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/parent.hpp @@ -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 +#include +#include + +namespace mock { namespace detail { + class parent + { + public: + parent() = default; + parent(boost::unit_test::const_string instance, boost::optional 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_; + }; +}} // namespace mock::detail + +#endif // MOCK_PARENT_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/ref_arg.hpp b/thirdparty/turtle/turtle/detail/ref_arg.hpp new file mode 100644 index 0000000000..abd755fee5 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/ref_arg.hpp @@ -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 + +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 + using ref_arg_t = typename std::conditional::value, T, std::add_rvalue_reference_t>::type; +}} // namespace mock::detail + +#endif // MOCK_REF_ARG_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/root.hpp b/thirdparty/turtle/turtle/detail/root.hpp new file mode 100644 index 0000000000..664ce0aea4 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/root.hpp @@ -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 +#include +#include + +namespace mock { namespace detail { + class root_t : public singleton, public context + { + public: + virtual void add(const void* p, + verifiable& v, + boost::unit_test::const_string instance, + boost::optional 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> 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, + 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 children_; + group group_; + mutable mutex mutex_; + + MOCK_SINGLETON_CONS(root_t); + }; + MOCK_SINGLETON_INST(root) +}} // namespace mock::detail + +#endif // MOCK_ROOT_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/sequence_impl.hpp b/thirdparty/turtle/turtle/detail/sequence_impl.hpp new file mode 100644 index 0000000000..79d6fa0c93 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/sequence_impl.hpp @@ -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 +#include +#include + +namespace mock { namespace detail { + class sequence_impl + { + public: + sequence_impl() : mutex_(std::make_shared()) {} + + 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 elements_; + const std::shared_ptr mutex_; + }; +}} // namespace mock::detail + +#endif // MOCK_SEQUENCE_IMPL_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/signature.hpp b/thirdparty/turtle/turtle/detail/signature.hpp new file mode 100644 index 0000000000..cb4b3ebda9 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/signature.hpp @@ -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 + +namespace mock { namespace detail { +#define MOCK_NOARG +#define MOCK_STRIP_FUNCTION_QUALIFIERS(cv, ref) \ + template \ + struct strip_function_qualifiers \ + { \ + using type = R(Args...); \ + }; \ + template \ + struct strip_function_qualifiers \ + { \ + 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 + 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 + struct signature; + + template + struct signature + { + using type = R(Args...); + }; + + template + struct signature : signature::type> + {}; + + /// Return the (non-member) function signature out of (any) signature + template + using signature_t = typename signature::type; + + /// CRTP class to define the base_type typedef + template + 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 + T ambiguous_method_requires_to_specify_signature(const T&); +}} // namespace mock::detail + +#define MOCK_SIGNATURE(M) \ + mock::detail::signature_t + +#endif // MOCK_SIGNATURE_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/signature_traits.hpp b/thirdparty/turtle/turtle/detail/signature_traits.hpp new file mode 100644 index 0000000000..02c108ff4b --- /dev/null +++ b/thirdparty/turtle/turtle/detail/signature_traits.hpp @@ -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 + +namespace mock { namespace detail { + /// Helper class to store a tuple/list of types + template + struct tuple; + + /// Get the type at the given index in the tuple + template + struct tuple_element; + + template + struct tuple_element> : tuple_element> + {}; + + template + struct tuple_element<0, tuple> + { + using type = H; + }; + + /// Provides information about a given function signature + /// Member types: return_type, args + /// Member constant: arity + template + struct signature_traits; + + template + struct signature_traits + { + using return_type = R; + static constexpr std::size_t arity = sizeof...(Args); + using args = tuple; + }; + + /// Return the result type of the function signature + template + using result_type_t = typename signature_traits::return_type; + + /// Return the arity of the function signature + template + using function_arity_t = std::integral_constant::arity>; + + /// Return the type at the given index of the function signature + template + using parameter_t = typename tuple_element::args>::type; + +}} // namespace mock::detail + +#endif // MOCK_SIGNATURE_TRAITS_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/singleton.hpp b/thirdparty/turtle/turtle/detail/singleton.hpp new file mode 100644 index 0000000000..e1f4ae6fe6 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/singleton.hpp @@ -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 + +namespace mock { namespace detail { + + template + 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() = default + +#define MOCK_SINGLETON_INST(inst) static BOOST_JOIN(inst, _t)& inst = BOOST_JOIN(inst, _t)::instance(); + +#endif // MOCK_SINGLETON_HPP diff --git a/thirdparty/turtle/turtle/detail/type_name.hpp b/thirdparty/turtle/turtle/detail/type_name.hpp new file mode 100644 index 0000000000..1aaa79ddd9 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/type_name.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 +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __GNUC__ +# include +# include +#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(p)); } + }; + std::unique_ptr 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 + type_name make_type_name() + { + return type_name(typeid(T)); + } + template + type_name make_type_name(const T&) + { + return type_name(typeid(T)); + } +}} // namespace mock::detail + +#endif // MOCK_TYPE_NAME_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/detail/verifiable.hpp b/thirdparty/turtle/turtle/detail/verifiable.hpp new file mode 100644 index 0000000000..f6f2150d17 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/verifiable.hpp @@ -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 diff --git a/thirdparty/turtle/turtle/detail/void_t.hpp b/thirdparty/turtle/turtle/detail/void_t.hpp new file mode 100644 index 0000000000..acc2b6bca6 --- /dev/null +++ b/thirdparty/turtle/turtle/detail/void_t.hpp @@ -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 + struct make_void + { + using type = void; + }; + /// Standard helper to implement the detection idiom. Returns always void + template + using void_t = typename make_void::type; +}} // namespace mock::detail + +#endif // MOCK_VOID_T_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/error.hpp b/thirdparty/turtle/turtle/error.hpp new file mode 100644 index 0000000000..fd48a3e0f4 --- /dev/null +++ b/thirdparty/turtle/turtle/error.hpp @@ -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 +# include +# include +# include +# include + +namespace mock { +template +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(line)); + } + + template + 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(line)) + << boost::unit_test::log_all_errors << message << ": " << context + << boost::unit_test::log::end(); + } + + template + 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(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 diff --git a/thirdparty/turtle/turtle/exception.hpp b/thirdparty/turtle/turtle/exception.hpp new file mode 100644 index 0000000000..ced9893f6d --- /dev/null +++ b/thirdparty/turtle/turtle/exception.hpp @@ -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 + +namespace mock { +struct exception : virtual boost::execution_aborted +{}; +} // namespace mock + +#endif // MOCK_USE_BOOST_TEST + +#endif // MOCK_EXCEPTION_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/format.hpp b/thirdparty/turtle/turtle/format.hpp new file mode 100644 index 0000000000..56aa1e1aed --- /dev/null +++ b/thirdparty/turtle/turtle/format.hpp @@ -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 +detail::formatter format(const T& t) +{ + return detail::formatter(t); +} + +} // namespace mock + +#endif // MOCK_FORMAT_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/log.hpp b/thirdparty/turtle/turtle/log.hpp new file mode 100644 index 0000000000..c87b2598a3 --- /dev/null +++ b/thirdparty/turtle/turtle/log.hpp @@ -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 +#include +#include +#include + +namespace boost { +template +class shared_ptr; +template +class weak_ptr; +template +class reference_wrapper; +template +class optional; + +namespace phoenix { + template + struct actor; +} +namespace lambda { + template + class lambda_functor; +} +namespace assign_detail { + template + class generic_list; +} +} // namespace boost + +namespace mock { +namespace detail { + template + 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 + struct is_callable_impl : std::false_type + {}; + template + struct is_callable_impl : std::true_type + {}; + template + struct is_callable : is_callable_impl> + {}; +} // namespace detail + +template +stream& operator<<(stream& s, const std::pair& p) +{ + return s << '(' << mock::format(p.first) << ',' << mock::format(p.second) << ')'; +} + +template +stream& operator<<(stream& s, const std::deque& t) +{ + detail::serialize(s, t.begin(), t.end()); + return s; +} +template +stream& operator<<(stream& s, const std::list& t) +{ + detail::serialize(s, t.begin(), t.end()); + return s; +} +template +stream& operator<<(stream& s, const std::vector& t) +{ + detail::serialize(s, t.begin(), t.end()); + return s; +} +template +stream& operator<<(stream& s, const std::map& t) +{ + detail::serialize(s, t.begin(), t.end()); + return s; +} +template +stream& operator<<(stream& s, const std::multimap& t) +{ + detail::serialize(s, t.begin(), t.end()); + return s; +} +template +stream& operator<<(stream& s, const std::set& t) +{ + detail::serialize(s, t.begin(), t.end()); + return s; +} +template +stream& operator<<(stream& s, const std::multiset& t) +{ + detail::serialize(s, t.begin(), t.end()); + return s; +} +template +stream& operator<<(stream& s, const boost::assign_detail::generic_list& t) +{ + detail::serialize(s, t.begin(), t.end()); + return s; +} +template +stream& operator<<(stream& s, const boost::reference_wrapper& t) +{ + return s << mock::format(t.get()); +} +template +stream& operator<<(stream& s, const std::reference_wrapper& t) +{ + return s << mock::format(t.get()); +} +template +stream& operator<<(stream& s, const boost::shared_ptr& t) +{ + return s << mock::format(t.get()); +} +template +stream& operator<<(stream& s, const boost::weak_ptr& t) +{ + return s << mock::format(t.lock()); +} +inline stream& operator<<(stream& s, const boost::none_t&) +{ + return s << "none"; +} +template +stream& operator<<(stream& s, const boost::optional& t) +{ + if(t) + return s << mock::format(t.get()); + return s << boost::none; +} + +template +stream& operator<<(stream& s, const std::shared_ptr& t) +{ + return s << mock::format(t.get()); +} +template +stream& operator<<(stream& s, const std::weak_ptr& t) +{ + return s << mock::format(t.lock()); +} +template +stream& operator<<(stream& s, const std::unique_ptr& p) +{ + return s << mock::format(p.get()); +} + +template +stream& operator<<(stream& s, const boost::lambda::lambda_functor&) +{ + return s << '?'; +} +template +stream& operator<<(stream& s, const boost::phoenix::actor&) +{ + return s << '?'; +} + +inline stream& operator<<(stream& s, std::nullptr_t) +{ + return s << "nullptr"; +} + +template +std::enable_if_t::value, stream&> operator<<(stream& s, T*) +{ + return s << '?'; +} +template +std::enable_if_t::value, stream&> operator<<(stream& s, T* t) +{ + *s.s_ << t; + return s; +} +} // namespace mock + +#endif // MOCK_LOG_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/matcher.hpp b/thirdparty/turtle/turtle/matcher.hpp new file mode 100644 index 0000000000..7854d77839 --- /dev/null +++ b/thirdparty/turtle/turtle/matcher.hpp @@ -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 +#include +#include + +namespace mock { +template +class matcher +{ +public: + explicit matcher(Expected expected) : expected_(expected) {} + bool operator()(std::add_lvalue_reference_t 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 +{ +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 +class matcher> +{ +public: + explicit matcher(const constraint& c) : c_(c.c_) {} + bool operator()(detail::ref_arg_t actual) { return c_(static_cast>(actual)); } + friend std::ostream& operator<<(std::ostream& s, const matcher& m) { return s << mock::format(m.c_); } + +private: + Constraint c_; +}; + +template +class matcher::value>> +{ +public: + explicit matcher(const Functor& f) : c_(f) {} + bool operator()(detail::ref_arg_t actual) { return c_(static_cast>(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 diff --git a/thirdparty/turtle/turtle/mock.hpp b/thirdparty/turtle/turtle/mock.hpp new file mode 100644 index 0000000000..9e78a4f0c9 --- /dev/null +++ b/thirdparty/turtle/turtle/mock.hpp @@ -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 + +/// 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 diff --git a/thirdparty/turtle/turtle/object.hpp b/thirdparty/turtle/turtle/object.hpp new file mode 100644 index 0000000000..74da12ff74 --- /dev/null +++ b/thirdparty/turtle/turtle/object.hpp @@ -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 +#include +#include +#include + +namespace mock { +class object; + +namespace detail { + template + E& configure(const object& o, + E& e, + boost::unit_test::const_string instance, + boost::optional type, + boost::unit_test::const_string name); + + template + E& configure(const T& t, + E& e, + boost::unit_test::const_string instance, + boost::optional type, + boost::unit_test::const_string name, + std::enable_if_t::value>* = 0) + { + e.configure(detail::root, &t, instance, type, name); + return e; + } +} // namespace detail +class object +{ +public: + object() : impl_(std::make_shared()) {} + +protected: + ~object() = default; + +public: + std::shared_ptr impl_; +}; + +namespace detail { + template + E& configure(const object& o, + E& e, + boost::unit_test::const_string instance, + boost::optional 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 diff --git a/thirdparty/turtle/turtle/reset.hpp b/thirdparty/turtle/turtle/reset.hpp new file mode 100644 index 0000000000..4315d4c208 --- /dev/null +++ b/thirdparty/turtle/turtle/reset.hpp @@ -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 +void reset(detail::functor& f) +{ + f.reset(); +} +} // namespace mock + +#endif // MOCK_RESET_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/sequence.hpp b/thirdparty/turtle/turtle/sequence.hpp new file mode 100644 index 0000000000..a4a6281081 --- /dev/null +++ b/thirdparty/turtle/turtle/sequence.hpp @@ -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 + +namespace mock { +class sequence +{ +public: + sequence() : impl_(std::make_shared()) {} + + std::shared_ptr impl_; +}; +} // namespace mock + +#endif // MOCK_SEQUENCE_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/stream.hpp b/thirdparty/turtle/turtle/stream.hpp new file mode 100644 index 0000000000..52991eda6c --- /dev/null +++ b/thirdparty/turtle/turtle/stream.hpp @@ -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 +#include + +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 + 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 + 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 + any(const T& t) : h_(std::make_unique>(t)) + {} + std::unique_ptr 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 + S& operator<<(S& s, const T&) + { + return s << '?'; + } +}} // namespace detail::conversion + +template +stream& operator<<(stream& s, const T& t) +{ + using namespace detail::conversion; + *s.s_ << t; + return s; +} + +#endif // MOCK_USE_CONVERSIONS + +namespace detail { + template + 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 + void serialize(stream& s, const std::basic_string& 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(c); } +} // namespace detail +} // namespace mock + +#endif // MOCK_STREAM_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/unwrap_reference.hpp b/thirdparty/turtle/turtle/unwrap_reference.hpp new file mode 100644 index 0000000000..93f6f5e0f8 --- /dev/null +++ b/thirdparty/turtle/turtle/unwrap_reference.hpp @@ -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 +#include + +namespace mock { +template +struct unwrap_reference +{ + using type = T; +}; +template +struct unwrap_reference> +{ + using type = T; +}; +template +struct unwrap_reference> +{ + using type = T; +}; +template +using unwrap_reference_t = typename unwrap_reference::type; + +template +BOOST_FORCEINLINE unwrap_reference_t& unwrap_ref(T& t) noexcept +{ + return t; +} +} // namespace mock + +#endif // MOCK_UNWRAP_REFERENCE_HPP_INCLUDED diff --git a/thirdparty/turtle/turtle/verify.hpp b/thirdparty/turtle/turtle/verify.hpp new file mode 100644 index 0000000000..1995374140 --- /dev/null +++ b/thirdparty/turtle/turtle/verify.hpp @@ -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 +bool verify(const detail::functor& f) +{ + return f.verify(); +} +} // namespace mock + +#endif // MOCK_VERIFY_HPP_INCLUDED