assertion.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  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, >=, GE ) \
  58. action( <=, LE, > , GT ) \
  59. action( > , GT, <=, LE ) \
  60. action( >=, GE, < , LT ) \
  61. action( ==, EQ, !=, NE ) \
  62. action( !=, NE, ==, EQ ) \
  63. /**/
  64. //____________________________________________________________________________//
  65. #ifndef BOOST_NO_CXX11_DECLTYPE
  66. #define BOOST_TEST_FOR_EACH_CONST_OP(action)\
  67. action(->*, MEMP, ->*, MEMP ) \
  68. \
  69. action( * , MUL , * , MUL ) \
  70. action( / , DIV , / , DIV ) \
  71. action( % , MOD , % , MOD ) \
  72. \
  73. action( + , ADD , + , ADD ) \
  74. action( - , SUB , - , SUB ) \
  75. \
  76. action( <<, LSH , << , LSH ) \
  77. action( >>, RSH , >> , RSH ) \
  78. \
  79. BOOST_TEST_FOR_EACH_COMP_OP(action) \
  80. \
  81. action( & , BAND, & , BAND ) \
  82. action( ^ , XOR , ^ , XOR ) \
  83. action( | , BOR , | , 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 , = , SET ) \
  93. action( +=, IADD, += , IADD ) \
  94. action( -=, ISUB, -= , ISUB ) \
  95. action( *=, IMUL, *= , IMUL ) \
  96. action( /=, IDIV, /= , IDIV ) \
  97. action( %=, IMOD, %= , IMOD ) \
  98. action(<<=, ILSH, <<=, ILSH ) \
  99. action(>>=, IRSH, >>=, IRSH ) \
  100. action( &=, IAND, &= , IAND ) \
  101. action( ^=, IXOR, ^= , IXOR ) \
  102. action( |=, IOR , |= , 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_FWD_DECL( oper, name, rev, name_inverse ) \
  114. template<typename Lhs, typename Rhs, \
  115. typename Enabler=void> \
  116. struct name; \
  117. /**/
  118. BOOST_TEST_FOR_EACH_CONST_OP( DEFINE_CONST_OPER_FWD_DECL )
  119. #define DEFINE_CONST_OPER( oper, name, rev, name_inverse ) \
  120. template<typename Lhs, typename Rhs, \
  121. typename Enabler> \
  122. struct name { \
  123. typedef DEDUCE_RESULT_TYPE( oper ) result_type; \
  124. typedef name_inverse<Lhs, Rhs> inverse; \
  125. \
  126. static result_type \
  127. eval( Lhs const& lhs, Rhs const& rhs ) \
  128. { \
  129. return lhs oper rhs; \
  130. } \
  131. \
  132. template<typename PrevExprType> \
  133. static void \
  134. report( std::ostream& ostr, \
  135. PrevExprType const& lhs, \
  136. Rhs const& rhs) \
  137. { \
  138. lhs.report( ostr ); \
  139. ostr << revert() \
  140. << tt_detail::print_helper( rhs ); \
  141. } \
  142. \
  143. static char const* forward() \
  144. { return " " #oper " "; } \
  145. static char const* revert() \
  146. { return " " #rev " "; } \
  147. }; \
  148. /**/
  149. BOOST_TEST_FOR_EACH_CONST_OP( DEFINE_CONST_OPER )
  150. #undef DEDUCE_RESULT_TYPE
  151. #undef DEFINE_CONST_OPER
  152. //____________________________________________________________________________//
  153. } // namespace op
  154. // ************************************************************************** //
  155. // ************** assertion::expression_base ************** //
  156. // ************************************************************************** //
  157. // Defines expression operators
  158. template<typename Lhs, typename Rhs, typename OP> class binary_expr;
  159. template<typename ExprType,typename ValType>
  160. class expression_base {
  161. public:
  162. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  163. template<typename T>
  164. struct RhsT : remove_const<typename remove_reference<T>::type> {};
  165. #define ADD_OP_SUPPORT( oper, name, _, _i ) \
  166. template<typename T> \
  167. binary_expr<ExprType,T, \
  168. op::name<ValType,typename RhsT<T>::type> > \
  169. operator oper( T&& rhs ) \
  170. { \
  171. return binary_expr<ExprType,T, \
  172. op::name<ValType,typename RhsT<T>::type> > \
  173. ( std::forward<ExprType>( \
  174. *static_cast<ExprType*>(this) ), \
  175. std::forward<T>(rhs) ); \
  176. } \
  177. /**/
  178. #else
  179. #define ADD_OP_SUPPORT( oper, name, _, _i ) \
  180. template<typename T> \
  181. binary_expr<ExprType,typename boost::decay<T const>::type, \
  182. op::name<ValType,typename boost::decay<T const>::type> >\
  183. operator oper( T const& rhs ) const \
  184. { \
  185. typedef typename boost::decay<T const>::type Rhs; \
  186. return binary_expr<ExprType,Rhs,op::name<ValType,Rhs> > \
  187. ( *static_cast<ExprType const*>(this), \
  188. rhs ); \
  189. } \
  190. /**/
  191. #endif
  192. BOOST_TEST_FOR_EACH_CONST_OP( ADD_OP_SUPPORT )
  193. #undef ADD_OP_SUPPORT
  194. #ifndef BOOST_NO_CXX11_AUTO_DECLARATIONS
  195. // Disabled operators
  196. template<typename T>
  197. ExprType&
  198. operator ||( T const& /*rhs*/ )
  199. {
  200. BOOST_MPL_ASSERT_MSG(false, CANT_USE_LOGICAL_OPERATOR_OR_WITHIN_THIS_TESTING_TOOL, () );
  201. return *static_cast<ExprType*>(this);
  202. }
  203. template<typename T>
  204. ExprType&
  205. operator &&( T const& /*rhs*/ )
  206. {
  207. BOOST_MPL_ASSERT_MSG(false, CANT_USE_LOGICAL_OPERATOR_AND_WITHIN_THIS_TESTING_TOOL, () );
  208. return *static_cast<ExprType*>(this);
  209. }
  210. operator bool()
  211. {
  212. BOOST_MPL_ASSERT_MSG(false, CANT_USE_TERNARY_OPERATOR_WITHIN_THIS_TESTING_TOOL, () );
  213. return false;
  214. }
  215. #endif
  216. };
  217. // ************************************************************************** //
  218. // ************** assertion::value_expr ************** //
  219. // ************************************************************************** //
  220. // simple value expression
  221. template<typename T>
  222. class value_expr : public expression_base<value_expr<T>,typename remove_const<typename remove_reference<T>::type>::type> {
  223. public:
  224. // Public types
  225. typedef T result_type;
  226. // Constructor
  227. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  228. value_expr( value_expr&& ve )
  229. : m_value( std::forward<T>(ve.m_value) )
  230. {}
  231. explicit value_expr( T&& val )
  232. : m_value( std::forward<T>(val) )
  233. {}
  234. #else
  235. explicit value_expr( T const& val )
  236. : m_value( val )
  237. {}
  238. #endif
  239. // Specific expression interface
  240. T const& value() const
  241. {
  242. return m_value;
  243. }
  244. void report( std::ostream& ostr ) const
  245. {
  246. ostr << tt_detail::print_helper( value() );
  247. }
  248. // Mutating operators
  249. #define ADD_OP_SUPPORT( OPER, ID, _, _i)\
  250. template<typename U> \
  251. value_expr<T>& \
  252. operator OPER( U const& rhs ) \
  253. { \
  254. m_value OPER rhs; \
  255. \
  256. return *this; \
  257. } \
  258. /**/
  259. BOOST_TEST_FOR_EACH_MUT_OP( ADD_OP_SUPPORT )
  260. #undef ADD_OP_SUPPORT
  261. // expression interface
  262. assertion_result evaluate( bool no_message = false ) const
  263. {
  264. assertion_result res( value() );
  265. if( no_message || res )
  266. return res;
  267. format_message( res.message(), value() );
  268. return tt_detail::format_assertion_result( "", res.message().str() );
  269. }
  270. private:
  271. template<typename U>
  272. static void format_message( wrap_stringstream& ostr, U const& v )
  273. {
  274. ostr << "['" << tt_detail::print_helper(v) << "' evaluates to false]";
  275. }
  276. static void format_message( wrap_stringstream& /*ostr*/, bool /*v*/ ) {}
  277. static void format_message( wrap_stringstream& /*ostr*/, assertion_result const& /*v*/ ) {}
  278. // Data members
  279. T m_value;
  280. };
  281. // ************************************************************************** //
  282. // ************** assertion::binary_expr ************** //
  283. // ************************************************************************** //
  284. // binary expression
  285. template<typename LExpr, typename Rhs, typename OP>
  286. class binary_expr : public expression_base<binary_expr<LExpr,Rhs,OP>,typename OP::result_type> {
  287. public:
  288. // Public types
  289. typedef typename OP::result_type result_type;
  290. // Constructor
  291. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  292. binary_expr( binary_expr&& be )
  293. : m_lhs( std::forward<LExpr>(be.m_lhs) )
  294. , m_rhs( std::forward<Rhs>(be.m_rhs) )
  295. {}
  296. binary_expr( LExpr&& lhs, Rhs&& rhs )
  297. : m_lhs( std::forward<LExpr>(lhs) )
  298. , m_rhs( std::forward<Rhs>(rhs) )
  299. {}
  300. #else
  301. binary_expr( LExpr const& lhs, Rhs const& rhs )
  302. : m_lhs( lhs )
  303. , m_rhs( rhs )
  304. {}
  305. #endif
  306. // Specific expression interface
  307. result_type value() const
  308. {
  309. return OP::eval( m_lhs.value(), m_rhs );
  310. }
  311. void report( std::ostream& ostr ) const
  312. {
  313. return OP::report( ostr, m_lhs, m_rhs );
  314. }
  315. assertion_result evaluate( bool no_message = false ) const
  316. {
  317. assertion_result const expr_res( value() );
  318. if( no_message || expr_res )
  319. return expr_res;
  320. wrap_stringstream buff;
  321. report( buff.stream() );
  322. return tt_detail::format_assertion_result( buff.stream().str(), expr_res.message() );
  323. }
  324. // To support custom manipulators
  325. LExpr const& lhs() const { return m_lhs; }
  326. Rhs const& rhs() const { return m_rhs; }
  327. private:
  328. // Data members
  329. LExpr m_lhs;
  330. Rhs m_rhs;
  331. };
  332. // ************************************************************************** //
  333. // ************** assertion::seed ************** //
  334. // ************************************************************************** //
  335. // seed added ot the input expression to form an assertion expression
  336. class seed {
  337. public:
  338. // ->* is highest precedence left to right operator
  339. template<typename T>
  340. value_expr<T>
  341. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  342. operator->*( T&& v ) const
  343. {
  344. return value_expr<T>( std::forward<T>( v ) );
  345. }
  346. #else
  347. operator->*( T const& v ) const
  348. {
  349. return value_expr<T>( v );
  350. }
  351. #endif
  352. };
  353. #undef BOOST_TEST_FOR_EACH_CONST_OP
  354. } // namespace assertion
  355. } // namespace test_tools
  356. } // namespace boost
  357. #include <boost/test/detail/enable_warnings.hpp>
  358. #endif // BOOST_TEST_TOOLS_ASSERTION_HPP_100911GER