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