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