1 //  (C) Copyright Gennadiy Rozental 2011-2015.
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        : $RCSfile$
9 //
10 //  Version     : $Revision: 62023 $
11 //
12 //  Description : unit test for new assertion construction based on input expression
13 // ***************************************************************************
14 
15 // Boost.Test
16 #define BOOST_TEST_MODULE Boost.Test assertion consruction test
17 #include <boost/test/unit_test.hpp>
18 #include <boost/test/tools/assertion.hpp>
19 #include <boost/test/utils/is_forward_iterable.hpp>
20 
21 #include <boost/noncopyable.hpp>
22 
23 #include <map>
24 #include <set>
25 
26 namespace utf = boost::unit_test;
27 
28 //____________________________________________________________________________//
29 
30 #define EXPR_TYPE( E, expr ) auto const& E = assertion::seed() ->* expr
31 
32 // some broken compilers do not implement properly decltype on expressions
33 // partial implementation of is_forward_iterable when decltype not available
34 struct not_fwd_iterable_1 {
35   typedef int const_iterator;
36   typedef int value_type;
37 
38   bool size();
39 };
40 
41 struct not_fwd_iterable_2 {
42   typedef int const_iterator;
43   typedef int value_type;
44 
45   bool begin();
46 };
47 
48 struct not_fwd_iterable_3 {
49   typedef int value_type;
50   bool begin();
51   bool size();
52 };
53 
BOOST_AUTO_TEST_CASE(test_forward_iterable_concept)54 BOOST_AUTO_TEST_CASE( test_forward_iterable_concept )
55 {
56   {
57     typedef std::vector<int> type;
58     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
59     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
60     BOOST_CHECK_MESSAGE(utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
61   }
62 
63   {
64     // should also work for references, but from is_forward_iterable
65     typedef std::vector<int>& type;
66     BOOST_CHECK_MESSAGE(utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
67   }
68 
69 
70   {
71     typedef std::list<int> type;
72     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
73     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
74     BOOST_CHECK_MESSAGE(utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
75   }
76 
77   {
78     typedef std::map<int, int> type;
79     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
80     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
81     BOOST_CHECK_MESSAGE(utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
82   }
83 
84   {
85     typedef std::set<int, int> type;
86     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
87     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
88     BOOST_CHECK_MESSAGE(utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
89   }
90 
91 
92   {
93     typedef float type;
94     BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
95     BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
96     BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
97   }
98 
99   {
100     typedef not_fwd_iterable_1 type;
101     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
102     BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
103     BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
104   }
105 
106   {
107     typedef not_fwd_iterable_2 type;
108     BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
109     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
110     BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
111   }
112 
113   {
114     typedef not_fwd_iterable_3 type;
115     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
116     BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
117     BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
118   }
119 
120   {
121     typedef char type;
122     BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
123     BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
124     BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
125   }
126 
127   {
128     // tables are not in the forward_iterable concept
129     typedef int type[10];
130     BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
131     BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
132     BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
133   }
134 }
135 
BOOST_AUTO_TEST_CASE(test_basic_value_expression_construction)136 BOOST_AUTO_TEST_CASE( test_basic_value_expression_construction )
137 {
138     using namespace boost::test_tools;
139 
140     {
141         EXPR_TYPE( E, 1 );
142         predicate_result const& res = E.evaluate();
143         BOOST_TEST( res );
144         BOOST_TEST( res.message().is_empty() );
145     }
146 
147     {
148         EXPR_TYPE( E, 0 );
149         predicate_result const& res = E.evaluate();
150         BOOST_TEST( !res );
151         BOOST_TEST( res.message() == " [(bool)0 is false]" );
152     }
153 
154     {
155         EXPR_TYPE( E, true );
156         predicate_result const& res = E.evaluate();
157         BOOST_TEST( res );
158         BOOST_TEST( res.message().is_empty() );
159     }
160 
161     {
162         EXPR_TYPE( E, 1.5 );
163         predicate_result const& res = E.evaluate();
164         BOOST_TEST( res );
165     }
166 
167     {
168         EXPR_TYPE( E, "abc" );
169         predicate_result const& res = E.evaluate();
170         BOOST_TEST( res );
171     }
172 
173     {
174         EXPR_TYPE( E, 1>2 );
175         predicate_result const& res = E.evaluate();
176         BOOST_TEST( !res );
177         BOOST_TEST( res.message() == " [1 <= 2]" );
178     }
179 
180 }
181 
182 //____________________________________________________________________________//
183 
BOOST_AUTO_TEST_CASE(test_comparison_expression)184 BOOST_AUTO_TEST_CASE( test_comparison_expression )
185 {
186     using namespace boost::test_tools;
187 
188     {
189         EXPR_TYPE( E, 1>2 );
190         predicate_result const& res = E.evaluate();
191         BOOST_TEST( !res );
192         BOOST_TEST( res.message() == " [1 <= 2]" );
193     }
194 
195     {
196         EXPR_TYPE( E, 100 < 50 );
197         predicate_result const& res = E.evaluate();
198         BOOST_TEST( !res );
199         BOOST_TEST( res.message() == " [100 >= 50]" );
200     }
201 
202     {
203         EXPR_TYPE( E, 5 <= 4 );
204         predicate_result const& res = E.evaluate();
205         BOOST_TEST( !res );
206         BOOST_TEST( res.message() == " [5 > 4]" );
207     }
208 
209     {
210         EXPR_TYPE( E, 10>=20 );
211         predicate_result const& res = E.evaluate();
212         BOOST_TEST( !res );
213         BOOST_TEST( res.message() == " [10 < 20]" );
214     }
215 
216     {
217         int i = 10;
218         EXPR_TYPE( E, i != 10 );
219         predicate_result const& res = E.evaluate();
220         BOOST_TEST( !res );
221         BOOST_TEST( res.message() == " [10 == 10]" );
222     }
223 
224     {
225         int i = 5;
226         EXPR_TYPE( E, i == 3 );
227         predicate_result const& res = E.evaluate();
228         BOOST_TEST( !res );
229         BOOST_TEST( res.message() == " [5 != 3]" );
230     }
231 }
232 
233 //____________________________________________________________________________//
234 
BOOST_AUTO_TEST_CASE(test_arithmetic_ops)235 BOOST_AUTO_TEST_CASE( test_arithmetic_ops )
236 {
237     using namespace boost::test_tools;
238 
239     {
240         int i = 3;
241         int j = 5;
242         EXPR_TYPE( E, i+j !=8 );
243         predicate_result const& res = E.evaluate();
244         BOOST_TEST( !res );
245         BOOST_TEST( res.message() == " [3 + 5 == 8]" );
246     }
247 
248     {
249         int i = 3;
250         int j = 5;
251         EXPR_TYPE( E, 2*i-j > 1 );
252         predicate_result const& res = E.evaluate();
253         BOOST_TEST( !res );
254         BOOST_TEST( res.message() == " [2 * 3 - 5 <= 1]" );
255     }
256 
257     {
258         int j = 5;
259         EXPR_TYPE( E, 2<<j < 30 );
260         predicate_result const& res = E.evaluate();
261         BOOST_TEST( !res );
262         BOOST_TEST( res.message() == " [2 << 5 >= 30]" );
263     }
264 
265     {
266         int i = 2;
267         int j = 5;
268         EXPR_TYPE( E, i&j );
269         predicate_result const& res = E.evaluate();
270         BOOST_TEST( !res );
271         BOOST_TEST( res.message() == " [2 & 5]" );
272     }
273 
274     {
275         int i = 3;
276         int j = 5;
277         EXPR_TYPE( E, i^j^6 );
278         predicate_result const& res = E.evaluate();
279         BOOST_TEST( !res );
280         BOOST_TEST( res.message() == " [3 ^ 5 ^ 6]" );
281     }
282 
283     // do not support
284     // EXPR_TYPE( E, 99/2 == 48 || 101/2 > 50 );
285     // EXPR_TYPE( E, a ? 100 < 50 : 25*2 == 50 );
286     // EXPR_TYPE( E, true,false );
287 }
288 
289 //____________________________________________________________________________//
290 
291 struct Testee {
292     static int s_copy_counter;
293 
TesteeTestee294     Testee() : m_value( false ) {}
TesteeTestee295     Testee( Testee const& ) : m_value(false) { s_copy_counter++; }
TesteeTestee296     Testee( Testee&& ) : m_value(false) {}
TesteeTestee297     Testee( Testee const&& ) : m_value(false) {}
298 
fooTestee299     bool foo() { return m_value; }
operator boolTestee300     operator bool() const { return m_value; }
301 
operator <<(std::ostream & ostr,Testee const &)302     friend std::ostream& operator<<( std::ostream& ostr, Testee const& ) { return ostr << "Testee"; }
303 
304     bool m_value;
305 };
306 
307 int Testee::s_copy_counter = 0;
308 
get_obj()309 Testee          get_obj() { return Testee(); }
get_const_obj()310 Testee const    get_const_obj() { return Testee(); }
311 
312 class NC : boost::noncopyable {
313 public:
NC()314     NC() {}
315 
operator ==(NC const &) const316     bool operator==(NC const&)  const { return false; }
operator <<(std::ostream & ostr,NC const &)317     friend std::ostream& operator<<(std::ostream& ostr, NC const&)
318     {
319         return ostr << "NC";
320     }
321 };
322 
BOOST_AUTO_TEST_CASE(test_objects)323 BOOST_AUTO_TEST_CASE( test_objects )
324 {
325     using namespace boost::test_tools;
326 
327     int expected_copy_count = 0;
328 
329     {
330         Testee obj;
331         Testee::s_copy_counter = 0;
332 
333         EXPR_TYPE( E, obj );
334         predicate_result const& res = E.evaluate();
335         BOOST_TEST( !res );
336         BOOST_TEST( res.message() == " [(bool)Testee is false]" );
337         BOOST_TEST( Testee::s_copy_counter == expected_copy_count );
338     }
339 
340     {
341         Testee const obj;
342         Testee::s_copy_counter = 0;
343 
344         EXPR_TYPE( E, obj );
345         predicate_result const& res = E.evaluate();
346         BOOST_TEST( !res );
347         BOOST_TEST( res.message() == " [(bool)Testee is false]" );
348         BOOST_TEST( Testee::s_copy_counter == expected_copy_count );
349     }
350 
351     {
352         Testee::s_copy_counter = 0;
353 
354         EXPR_TYPE( E, get_obj() );
355         predicate_result const& res = E.evaluate();
356         BOOST_TEST( !res );
357         BOOST_TEST( res.message() == " [(bool)Testee is false]" );
358         BOOST_TEST( Testee::s_copy_counter == expected_copy_count );
359     }
360 
361     {
362         Testee::s_copy_counter = 0;
363 
364         EXPR_TYPE( E, get_const_obj() );
365         predicate_result const& res = E.evaluate();
366         BOOST_TEST( !res );
367         BOOST_TEST( res.message() == " [(bool)Testee is false]" );
368         BOOST_TEST( Testee::s_copy_counter == expected_copy_count );
369     }
370 
371     {
372         Testee::s_copy_counter = 0;
373 
374         Testee t1;
375         Testee t2;
376 
377         EXPR_TYPE( E, t1 != t2 );
378         predicate_result const& res = E.evaluate();
379         BOOST_TEST( !res );
380         BOOST_TEST( res.message() == " [Testee == Testee]" );
381         BOOST_TEST( Testee::s_copy_counter == 0 );
382     }
383 
384     {
385         NC nc1;
386         NC nc2;
387 
388         EXPR_TYPE( E, nc1 == nc2 );
389         predicate_result const& res = E.evaluate();
390         BOOST_TEST( !res );
391         BOOST_TEST( res.message() == " [NC != NC]" );
392     }
393 }
394 
395 //____________________________________________________________________________//
396 
BOOST_AUTO_TEST_CASE(test_pointers)397 BOOST_AUTO_TEST_CASE( test_pointers )
398 {
399     using namespace boost::test_tools;
400 
401     {
402         Testee* ptr = 0;
403 
404         EXPR_TYPE( E, ptr );
405         predicate_result const& res = E.evaluate();
406         BOOST_TEST( !res );
407     }
408 
409     {
410         Testee obj1;
411         Testee obj2;
412 
413         EXPR_TYPE( E, &obj1 == &obj2 );
414         predicate_result const& res = E.evaluate();
415         BOOST_TEST( !res );
416     }
417 
418     {
419         Testee obj;
420         Testee* ptr =&obj;
421 
422         EXPR_TYPE( E, *ptr );
423         predicate_result const& res = E.evaluate();
424         BOOST_TEST( !res );
425         BOOST_TEST( res.message() == " [(bool)Testee is false]" );
426     }
427 
428     {
429         Testee obj;
430         Testee* ptr =&obj;
431         bool Testee::* mem_ptr =&Testee::m_value;
432 
433         EXPR_TYPE( E, ptr->*mem_ptr );
434         predicate_result const& res = E.evaluate();
435         BOOST_TEST( !res );
436     }
437 
438     // do not support
439     // Testee obj;
440     // bool Testee::* mem_ptr =&Testee::m_value;
441     // EXPR_TYPE( E, obj.*mem_ptr );
442 }
443 
444 //____________________________________________________________________________//
445 
BOOST_AUTO_TEST_CASE(test_mutating_ops)446 BOOST_AUTO_TEST_CASE( test_mutating_ops )
447 {
448     using namespace boost::test_tools;
449 
450     {
451         int j = 5;
452 
453         EXPR_TYPE( E, j = 0 );
454         predicate_result const& res = E.evaluate();
455         BOOST_TEST( !res );
456         BOOST_TEST( res.message() == " [(bool)0 is false]" );
457         BOOST_TEST( j == 0 );
458     }
459 
460     {
461         int j = 5;
462 
463         EXPR_TYPE( E, j -= 5 );
464         predicate_result const& res = E.evaluate();
465         BOOST_TEST( !res );
466         BOOST_TEST( res.message() == " [(bool)0 is false]" );
467         BOOST_TEST( j == 0 );
468     }
469 
470     {
471         int j = 5;
472 
473         EXPR_TYPE( E, j *= 0 );
474         predicate_result const& res = E.evaluate();
475         BOOST_TEST( !res );
476         BOOST_TEST( res.message() == " [(bool)0 is false]" );
477         BOOST_TEST( j == 0 );
478     }
479 
480     {
481         int j = 5;
482 
483         EXPR_TYPE( E, j /= 10 );
484         predicate_result const& res = E.evaluate();
485         BOOST_TEST( !res );
486         BOOST_TEST( res.message() == " [(bool)0 is false]" );
487         BOOST_TEST( j == 0 );
488     }
489 
490     {
491         int j = 4;
492 
493         EXPR_TYPE( E, j %= 2 );
494         predicate_result const& res = E.evaluate();
495         BOOST_TEST( !res );
496         BOOST_TEST( res.message() == " [(bool)0 is false]" );
497         BOOST_TEST( j == 0 );
498     }
499 
500     {
501         int j = 5;
502 
503         EXPR_TYPE( E, j ^= j );
504         predicate_result const& res = E.evaluate();
505         BOOST_TEST( !res );
506         BOOST_TEST( res.message() == " [(bool)0 is false]" );
507         BOOST_TEST( j == 0 );
508    }
509 }
510 
511 //____________________________________________________________________________//
512 
513 // EOF
514 
515