assertion.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. // (C) Copyright Gennadiy Rozental 2001.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org/libs/test for the library home page.
  6. //
  7. //!@file
  8. //!@brief Defines framework for automated assertion construction
  9. // ***************************************************************************
  10. #ifndef BOOST_TEST_TOOLS_ASSERTION_HPP_100911GER
  11. #define BOOST_TEST_TOOLS_ASSERTION_HPP_100911GER
  12. // Boost.Test
  13. #include <boost/test/tools/assertion_result.hpp>
  14. #include <boost/test/tools/detail/print_helper.hpp>
  15. #include <boost/test/tools/detail/fwd.hpp>
  16. // Boost
  17. #include <boost/type.hpp>
  18. #include <boost/type_traits/decay.hpp>
  19. #include <boost/mpl/assert.hpp>
  20. #include <boost/utility/declval.hpp>
  21. #include <boost/type_traits/remove_reference.hpp>
  22. #include <boost/type_traits/remove_const.hpp>
  23. // STL
  24. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  25. #include <utility>
  26. #endif
  27. #include <boost/test/detail/suppress_warnings.hpp>
  28. //____________________________________________________________________________//
  29. namespace boost {
  30. namespace test_tools {
  31. namespace assertion {
  32. // ************************************************************************** //
  33. // ************** assertion::operators ************** //
  34. // ************************************************************************** //
  35. // precedence 4: ->*, .*
  36. // precedence 5: *, /, %
  37. // precedence 6: +, -
  38. // precedence 7: << , >>
  39. // precedence 8: <, <=, > and >=
  40. // precedence 9: == and !=
  41. // precedence 10: bitwise AND
  42. // precedence 11: bitwise XOR
  43. // precedence 12: bitwise OR
  44. // precedence 13: logical AND
  45. // disabled
  46. // precedence 14: logical OR
  47. // disabled
  48. // precedence 15: ternary conditional
  49. // disabled
  50. // precedence 16: = and OP= operators
  51. // precedence 17: throw operator
  52. // not supported
  53. // precedence 18: comma
  54. // not supported
  55. namespace op {
  56. #define BOOST_TEST_FOR_EACH_COMP_OP(action) \
  57. action( < , LT, >= ) \
  58. action( <=, LE, > ) \
  59. action( > , GT, <= ) \
  60. action( >=, GE, < ) \
  61. action( ==, EQ, != ) \
  62. action( !=, NE, == ) \
  63. /**/
  64. //____________________________________________________________________________//
  65. #ifndef BOOST_NO_CXX11_DECLTYPE
  66. #define BOOST_TEST_FOR_EACH_CONST_OP(action)\
  67. action(->*, MEMP, ->* ) \
  68. \
  69. action( * , MUL, * ) \
  70. action( / , DIV, / ) \
  71. action( % , MOD, % ) \
  72. \
  73. action( + , ADD, + ) \
  74. action( - , SUB, - ) \
  75. \
  76. action( <<, LSH, << ) \
  77. action( >>, RSH, >> ) \
  78. \
  79. BOOST_TEST_FOR_EACH_COMP_OP(action) \
  80. \
  81. action( & , BAND, & ) \
  82. action( ^ , XOR, ^ ) \
  83. action( | , BOR, | ) \
  84. /**/
  85. #else
  86. #define BOOST_TEST_FOR_EACH_CONST_OP(action)\
  87. BOOST_TEST_FOR_EACH_COMP_OP(action) \
  88. /**/
  89. #endif
  90. //____________________________________________________________________________//
  91. #define BOOST_TEST_FOR_EACH_MUT_OP(action) \
  92. action( = , SET , = ) \
  93. action( +=, IADD, += ) \
  94. action( -=, ISUB, -= ) \
  95. action( *=, IMUL, *= ) \
  96. action( /=, IDIV, /= ) \
  97. action( %=, IMOD, %= ) \
  98. action(<<=, ILSH, <<=) \
  99. action(>>=, IRSH, >>=) \
  100. action( &=, IAND, &= ) \
  101. action( ^=, IXOR, ^= ) \
  102. action( |=, IOR , |= ) \
  103. /**/
  104. //____________________________________________________________________________//
  105. #ifndef BOOST_NO_CXX11_DECLTYPE
  106. # define DEDUCE_RESULT_TYPE( oper ) \
  107. decltype(boost::declval<Lhs>() oper boost::declval<Rhs>() ) optype; \
  108. typedef typename boost::remove_reference<optype>::type \
  109. /**/
  110. #else
  111. # define DEDUCE_RESULT_TYPE( oper ) bool
  112. #endif
  113. #define DEFINE_CONST_OPER( oper, name, rev ) \
  114. template<typename Lhs, typename Rhs, \
  115. typename Enabler=void> \
  116. struct name { \
  117. typedef DEDUCE_RESULT_TYPE( oper ) result_type; \
  118. \
  119. static result_type \
  120. eval( Lhs const& lhs, Rhs const& rhs ) \
  121. { \
  122. return lhs oper rhs; \
  123. } \
  124. \
  125. template<typename PrevExprType> \
  126. static void \
  127. report( std::ostream& ostr, \
  128. PrevExprType const& lhs, \
  129. Rhs const& rhs) \
  130. { \
  131. lhs.report( ostr ); \
  132. ostr << revert() \
  133. << tt_detail::print_helper( rhs ); \
  134. } \
  135. \
  136. static char const* revert() \
  137. { return " " #rev " "; } \
  138. }; \
  139. /**/
  140. BOOST_TEST_FOR_EACH_CONST_OP( DEFINE_CONST_OPER )
  141. #undef DEDUCE_RESULT_TYPE
  142. #undef DEFINE_CONST_OPER
  143. //____________________________________________________________________________//
  144. } // namespace op
  145. // ************************************************************************** //
  146. // ************** assertion::expression_base ************** //
  147. // ************************************************************************** //
  148. // Defines expression operators
  149. template<typename Lhs, typename Rhs, typename OP> class binary_expr;
  150. template<typename ExprType,typename ValType>
  151. class expression_base {
  152. public:
  153. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  154. template<typename T>
  155. struct RhsT : remove_const<typename remove_reference<T>::type> {};
  156. #define ADD_OP_SUPPORT( oper, name, _ ) \
  157. template<typename T> \
  158. binary_expr<ExprType,T, \
  159. op::name<ValType,typename RhsT<T>::type> > \
  160. operator oper( T&& rhs ) \
  161. { \
  162. return binary_expr<ExprType,T, \
  163. op::name<ValType,typename RhsT<T>::type> > \
  164. ( std::forward<ExprType>( \
  165. *static_cast<ExprType*>(this) ), \
  166. std::forward<T>(rhs) ); \
  167. } \
  168. /**/
  169. #else
  170. #define ADD_OP_SUPPORT( oper, name, _ ) \
  171. template<typename T> \
  172. binary_expr<ExprType,typename boost::decay<T const>::type, \
  173. op::name<ValType,typename boost::decay<T const>::type> >\
  174. operator oper( T const& rhs ) const \
  175. { \
  176. typedef typename boost::decay<T const>::type Rhs; \
  177. return binary_expr<ExprType,Rhs,op::name<ValType,Rhs> > \
  178. ( *static_cast<ExprType const*>(this), \
  179. rhs ); \
  180. } \
  181. /**/
  182. #endif
  183. BOOST_TEST_FOR_EACH_CONST_OP( ADD_OP_SUPPORT )
  184. #undef ADD_OP_SUPPORT
  185. #ifndef BOOST_NO_CXX11_AUTO_DECLARATIONS
  186. // Disabled operators
  187. template<typename T>
  188. ExprType&
  189. operator ||( T const& /*rhs*/ )
  190. {
  191. BOOST_MPL_ASSERT_MSG(false, CANT_USE_LOGICAL_OPERATOR_OR_WITHIN_THIS_TESTING_TOOL, () );
  192. return *static_cast<ExprType*>(this);
  193. }
  194. template<typename T>
  195. ExprType&
  196. operator &&( T const& /*rhs*/ )
  197. {
  198. BOOST_MPL_ASSERT_MSG(false, CANT_USE_LOGICAL_OPERATOR_AND_WITHIN_THIS_TESTING_TOOL, () );
  199. return *static_cast<ExprType*>(this);
  200. }
  201. operator bool()
  202. {
  203. BOOST_MPL_ASSERT_MSG(false, CANT_USE_TERNARY_OPERATOR_WITHIN_THIS_TESTING_TOOL, () );
  204. return false;
  205. }
  206. #endif
  207. };
  208. // ************************************************************************** //
  209. // ************** assertion::value_expr ************** //
  210. // ************************************************************************** //
  211. // simple value expression
  212. template<typename T>
  213. class value_expr : public expression_base<value_expr<T>,typename remove_const<typename remove_reference<T>::type>::type> {
  214. public:
  215. // Public types
  216. typedef T result_type;
  217. // Constructor
  218. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  219. value_expr( value_expr&& ve )
  220. : m_value( std::forward<T>(ve.m_value) )
  221. {}
  222. explicit value_expr( T&& val )
  223. : m_value( std::forward<T>(val) )
  224. {}
  225. #else
  226. explicit value_expr( T const& val )
  227. : m_value( val )
  228. {}
  229. #endif
  230. // Specific expression interface
  231. T const& value() const
  232. {
  233. return m_value;
  234. }
  235. void report( std::ostream& ostr ) const
  236. {
  237. ostr << tt_detail::print_helper( value() );
  238. }
  239. // Mutating operators
  240. #define ADD_OP_SUPPORT( OPER, ID, _ ) \
  241. template<typename U> \
  242. value_expr<T>& \
  243. operator OPER( U const& rhs ) \
  244. { \
  245. m_value OPER rhs; \
  246. \
  247. return *this; \
  248. } \
  249. /**/
  250. BOOST_TEST_FOR_EACH_MUT_OP( ADD_OP_SUPPORT )
  251. #undef ADD_OP_SUPPORT
  252. // expression interface
  253. assertion_result evaluate( bool no_message = false ) const
  254. {
  255. assertion_result res( value() );
  256. if( no_message || res )
  257. return res;
  258. format_message( res.message(), value() );
  259. return tt_detail::format_assertion_result( "", res.message().str() );
  260. }
  261. private:
  262. template<typename U>
  263. static void format_message( wrap_stringstream& ostr, U const& v )
  264. {
  265. ostr << "['" << tt_detail::print_helper(v) << "' evaluates to false]";
  266. }
  267. static void format_message( wrap_stringstream& /*ostr*/, bool /*v*/ ) {}
  268. static void format_message( wrap_stringstream& /*ostr*/, assertion_result const& /*v*/ ) {}
  269. // Data members
  270. T m_value;
  271. };
  272. // ************************************************************************** //
  273. // ************** assertion::binary_expr ************** //
  274. // ************************************************************************** //
  275. // binary expression
  276. template<typename LExpr, typename Rhs, typename OP>
  277. class binary_expr : public expression_base<binary_expr<LExpr,Rhs,OP>,typename OP::result_type> {
  278. public:
  279. // Public types
  280. typedef typename OP::result_type result_type;
  281. // Constructor
  282. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  283. binary_expr( binary_expr&& be )
  284. : m_lhs( std::forward<LExpr>(be.m_lhs) )
  285. , m_rhs( std::forward<Rhs>(be.m_rhs) )
  286. {}
  287. binary_expr( LExpr&& lhs, Rhs&& rhs )
  288. : m_lhs( std::forward<LExpr>(lhs) )
  289. , m_rhs( std::forward<Rhs>(rhs) )
  290. {}
  291. #else
  292. binary_expr( LExpr const& lhs, Rhs const& rhs )
  293. : m_lhs( lhs )
  294. , m_rhs( rhs )
  295. {}
  296. #endif
  297. // Specific expression interface
  298. result_type value() const
  299. {
  300. return OP::eval( m_lhs.value(), m_rhs );
  301. }
  302. void report( std::ostream& ostr ) const
  303. {
  304. return OP::report( ostr, m_lhs, m_rhs );
  305. }
  306. assertion_result evaluate( bool no_message = false ) const
  307. {
  308. assertion_result const expr_res( value() );
  309. if( no_message || expr_res )
  310. return expr_res;
  311. wrap_stringstream buff;
  312. report( buff.stream() );
  313. return tt_detail::format_assertion_result( buff.stream().str(), expr_res.message() );
  314. }
  315. // To support custom manipulators
  316. LExpr const& lhs() const { return m_lhs; }
  317. Rhs const& rhs() const { return m_rhs; }
  318. private:
  319. // Data members
  320. LExpr m_lhs;
  321. Rhs m_rhs;
  322. };
  323. // ************************************************************************** //
  324. // ************** assertion::seed ************** //
  325. // ************************************************************************** //
  326. // seed added ot the input expression to form an assertion expression
  327. class seed {
  328. public:
  329. // ->* is highest precedence left to right operator
  330. template<typename T>
  331. value_expr<T>
  332. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  333. operator->*( T&& v ) const
  334. {
  335. return value_expr<T>( std::forward<T>( v ) );
  336. }
  337. #else
  338. operator->*( T const& v ) const
  339. {
  340. return value_expr<T>( v );
  341. }
  342. #endif
  343. };
  344. #undef BOOST_TEST_FOR_EACH_CONST_OP
  345. } // namespace assertion
  346. } // namespace test_tools
  347. } // namespace boost
  348. #include <boost/test/detail/enable_warnings.hpp>
  349. #endif // BOOST_TEST_TOOLS_ASSERTION_HPP_100911GER