1#ifndef BOOST_CORE_LIGHTWEIGHT_TEST_HPP
2#define BOOST_CORE_LIGHTWEIGHT_TEST_HPP
3
4// MS compatible compilers support #pragma once
5
6#if defined(_MSC_VER)
7# pragma once
8#endif
9
10//
11// boost/core/lightweight_test.hpp - lightweight test library
12//
13// Copyright (c) 2002, 2009, 2014 Peter Dimov
14// Copyright (2) Beman Dawes 2010, 2011
15// Copyright (3) Ion Gaztanaga 2013
16//
17// Copyright 2018 Glen Joseph Fernandes
18// (glenjofe@gmail.com)
19//
20// Distributed under the Boost Software License, Version 1.0.
21// See accompanying file LICENSE_1_0.txt or copy at
22// http://www.boost.org/LICENSE_1_0.txt
23//
24
25#include <boost/core/detail/lwt_unattended.hpp>
26#include <boost/current_function.hpp>
27#include <boost/config.hpp>
28#include <exception>
29#include <iostream>
30#include <iterator>
31#include <string>
32#include <cstdlib>
33#include <cstring>
34#include <cstddef>
35#include <cctype>
36
37// IDE's like Visual Studio perform better if output goes to std::cout or
38// some other stream, so allow user to configure output stream:
39#ifndef BOOST_LIGHTWEIGHT_TEST_OSTREAM
40# define BOOST_LIGHTWEIGHT_TEST_OSTREAM std::cerr
41#endif
42
43namespace boost
44{
45namespace detail
46{
47
48class test_result
49{
50public:
51
52 test_result(): report_( false ), errors_( 0 )
53 {
54 core::detail::lwt_unattended();
55 }
56
57 ~test_result()
58 {
59 if( !report_ )
60 {
61 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "main() should return report_errors()" << std::endl;
62 std::abort();
63 }
64 }
65
66 int& errors()
67 {
68 return errors_;
69 }
70
71 void done()
72 {
73 report_ = true;
74 }
75
76private:
77
78 bool report_;
79 int errors_;
80};
81
82inline test_result& test_results()
83{
84 static test_result instance;
85 return instance;
86}
87
88inline int& test_errors()
89{
90 return test_results().errors();
91}
92
93inline bool test_impl(char const * expr, char const * file, int line, char const * function, bool v)
94{
95 if( v )
96 {
97 test_results();
98 return true;
99 }
100 else
101 {
102 BOOST_LIGHTWEIGHT_TEST_OSTREAM
103 << file << "(" << line << "): test '" << expr << "' failed in function '"
104 << function << "'" << std::endl;
105 ++test_results().errors();
106 return false;
107 }
108}
109
110inline void error_impl(char const * msg, char const * file, int line, char const * function)
111{
112 BOOST_LIGHTWEIGHT_TEST_OSTREAM
113 << file << "(" << line << "): " << msg << " in function '"
114 << function << "'" << std::endl;
115 ++test_results().errors();
116}
117
118inline void throw_failed_impl(const char* expr, char const * excep, char const * file, int line, char const * function)
119{
120 BOOST_LIGHTWEIGHT_TEST_OSTREAM
121 << file << "(" << line << "): expression '" << expr << "' did not throw exception '" << excep << "' in function '"
122 << function << "'" << std::endl;
123 ++test_results().errors();
124}
125
126inline void no_throw_failed_impl(const char* expr, const char* file, int line, const char* function)
127{
128 BOOST_LIGHTWEIGHT_TEST_OSTREAM
129 << file << "(" << line << "): expression '" << expr << "' threw an exception in function '"
130 << function << "'" << std::endl;
131 ++test_results().errors();
132}
133
134inline void no_throw_failed_impl(const char* expr, const char* what, const char* file, int line, const char* function)
135{
136 BOOST_LIGHTWEIGHT_TEST_OSTREAM
137 << file << "(" << line << "): expression '" << expr << "' threw an exception in function '"
138 << function << "': " << what << std::endl;
139 ++test_results().errors();
140}
141
142// In the comparisons below, it is possible that T and U are signed and unsigned integer types, which generates warnings in some compilers.
143// A cleaner fix would require common_type trait or some meta-programming, which would introduce a dependency on Boost.TypeTraits. To avoid
144// the dependency we just disable the warnings.
145#if defined(__clang__) && defined(__has_warning)
146# if __has_warning("-Wsign-compare")
147# pragma clang diagnostic push
148# pragma clang diagnostic ignored "-Wsign-compare"
149# endif
150#elif defined(_MSC_VER)
151# pragma warning(push)
152# pragma warning(disable: 4389)
153#elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
154# pragma GCC diagnostic push
155# pragma GCC diagnostic ignored "-Wsign-compare"
156#endif
157
158// specialize test output for char pointers to avoid printing as cstring
159template <class T> inline const T& test_output_impl(const T& v) { return v; }
160inline const void* test_output_impl(const char* v) { return v; }
161inline const void* test_output_impl(const unsigned char* v) { return v; }
162inline const void* test_output_impl(const signed char* v) { return v; }
163inline const void* test_output_impl(char* v) { return v; }
164inline const void* test_output_impl(unsigned char* v) { return v; }
165inline const void* test_output_impl(signed char* v) { return v; }
166template<class T> inline const void* test_output_impl(T volatile* v) { return const_cast<T*>(v); }
167
168#if !defined( BOOST_NO_CXX11_NULLPTR )
169inline const void* test_output_impl(std::nullptr_t) { return nullptr; }
170#endif
171
172// print chars as numeric
173
174inline int test_output_impl( signed char const& v ) { return v; }
175inline unsigned test_output_impl( unsigned char const& v ) { return v; }
176
177// Whether wchar_t is signed is implementation-defined
178
179template<bool Signed> struct lwt_long_type {};
180template<> struct lwt_long_type<true> { typedef long type; };
181template<> struct lwt_long_type<false> { typedef unsigned long type; };
182
183inline lwt_long_type<(static_cast<wchar_t>(-1) < static_cast<wchar_t>(0))>::type test_output_impl( wchar_t const& v ) { return v; }
184
185#if !defined( BOOST_NO_CXX11_CHAR16_T )
186inline unsigned long test_output_impl( char16_t const& v ) { return v; }
187#endif
188
189#if !defined( BOOST_NO_CXX11_CHAR32_T )
190inline unsigned long test_output_impl( char32_t const& v ) { return v; }
191#endif
192
193inline std::string test_output_impl( char const& v )
194{
195 if( std::isprint( static_cast<unsigned char>( v ) ) )
196 {
197 return std::string( 1, v );
198 }
199 else
200 {
201 static const char char_table[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
202 char buffer[ 4 ];
203 buffer[ 0 ] = '\\';
204 buffer[ 1 ] = 'x';
205 buffer[ 2 ] = char_table[ (static_cast<unsigned char>( v ) >> 4u) & 0x0f ];
206 buffer[ 3 ] = char_table[ static_cast<unsigned char>( v ) & 0x0f ];
207
208 return std::string( buffer, 4u );
209 }
210}
211
212// predicates
213
214struct lw_test_eq
215{
216 template <typename T, typename U>
217 bool operator()(const T& t, const U& u) const { return t == u; }
218};
219
220struct lw_test_ne
221{
222 template <typename T, typename U>
223 bool operator()(const T& t, const U& u) const { return t != u; }
224};
225
226struct lw_test_lt
227{
228 template <typename T, typename U>
229 bool operator()(const T& t, const U& u) const { return t < u; }
230};
231
232struct lw_test_le
233{
234 template <typename T, typename U>
235 bool operator()(const T& t, const U& u) const { return t <= u; }
236};
237
238struct lw_test_gt
239{
240 template <typename T, typename U>
241 bool operator()(const T& t, const U& u) const { return t > u; }
242};
243
244struct lw_test_ge
245{
246 template <typename T, typename U>
247 bool operator()(const T& t, const U& u) const { return t >= u; }
248};
249
250// lwt_predicate_name
251
252template<class T> char const * lwt_predicate_name( T const& )
253{
254 return "~=";
255}
256
257inline char const * lwt_predicate_name( lw_test_eq const& )
258{
259 return "==";
260}
261
262inline char const * lwt_predicate_name( lw_test_ne const& )
263{
264 return "!=";
265}
266
267inline char const * lwt_predicate_name( lw_test_lt const& )
268{
269 return "<";
270}
271
272inline char const * lwt_predicate_name( lw_test_le const& )
273{
274 return "<=";
275}
276
277inline char const * lwt_predicate_name( lw_test_gt const& )
278{
279 return ">";
280}
281
282inline char const * lwt_predicate_name( lw_test_ge const& )
283{
284 return ">=";
285}
286
287//
288
289template<class BinaryPredicate, class T, class U>
290inline bool test_with_impl(BinaryPredicate pred, char const * expr1, char const * expr2,
291 char const * file, int line, char const * function,
292 T const & t, U const & u)
293{
294 if( pred(t, u) )
295 {
296 test_results();
297 return true;
298 }
299 else
300 {
301 BOOST_LIGHTWEIGHT_TEST_OSTREAM
302 << file << "(" << line << "): test '" << expr1 << " " << lwt_predicate_name(pred) << " " << expr2
303 << "' ('" << test_output_impl(t) << "' " << lwt_predicate_name(pred) << " '" << test_output_impl(u)
304 << "') failed in function '" << function << "'" << std::endl;
305 ++test_results().errors();
306 return false;
307 }
308}
309
310inline bool test_cstr_eq_impl( char const * expr1, char const * expr2,
311 char const * file, int line, char const * function, char const * const t, char const * const u )
312{
313 if( std::strcmp(s1: t, s2: u) == 0 )
314 {
315 test_results();
316 return true;
317 }
318 else
319 {
320 BOOST_LIGHTWEIGHT_TEST_OSTREAM
321 << file << "(" << line << "): test '" << expr1 << " == " << expr2 << "' ('" << t
322 << "' == '" << u << "') failed in function '" << function << "'" << std::endl;
323 ++test_results().errors();
324 return false;
325 }
326}
327
328inline bool test_cstr_ne_impl( char const * expr1, char const * expr2,
329 char const * file, int line, char const * function, char const * const t, char const * const u )
330{
331 if( std::strcmp(s1: t, s2: u) != 0 )
332 {
333 test_results();
334 return true;
335 }
336 else
337 {
338 BOOST_LIGHTWEIGHT_TEST_OSTREAM
339 << file << "(" << line << "): test '" << expr1 << " != " << expr2 << "' ('" << t
340 << "' != '" << u << "') failed in function '" << function << "'" << std::endl;
341 ++test_results().errors();
342 return false;
343 }
344}
345
346template<class FormattedOutputFunction, class InputIterator1, class InputIterator2>
347bool test_all_eq_impl(FormattedOutputFunction& output,
348 char const * file, int line, char const * function,
349 InputIterator1 first_begin, InputIterator1 first_end,
350 InputIterator2 second_begin, InputIterator2 second_end)
351{
352 InputIterator1 first_it = first_begin;
353 InputIterator2 second_it = second_begin;
354 typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
355 typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
356 std::size_t error_count = 0;
357 const std::size_t max_count = 8;
358 do
359 {
360 while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it))
361 {
362 ++first_it;
363 ++second_it;
364 ++first_index;
365 ++second_index;
366 }
367 if ((first_it == first_end) || (second_it == second_end))
368 {
369 break; // do-while
370 }
371 if (error_count == 0)
372 {
373 output << file << "(" << line << "): Container contents differ in function '" << function << "':";
374 }
375 else if (error_count >= max_count)
376 {
377 output << " ...";
378 break;
379 }
380 output << " [" << first_index << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'";
381 ++first_it;
382 ++second_it;
383 ++first_index;
384 ++second_index;
385 ++error_count;
386 } while (first_it != first_end);
387
388 first_index += std::distance(first_it, first_end);
389 second_index += std::distance(second_it, second_end);
390 if (first_index != second_index)
391 {
392 if (error_count == 0)
393 {
394 output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
395 }
396 else
397 {
398 output << " [*] size(" << first_index << ") != size(" << second_index << ")";
399 }
400 ++error_count;
401 }
402
403 if (error_count == 0)
404 {
405 test_results();
406 return true;
407 }
408 else
409 {
410 output << std::endl;
411 ++test_results().errors();
412 return false;
413 }
414}
415
416template<class FormattedOutputFunction, class InputIterator1, class InputIterator2, typename BinaryPredicate>
417bool test_all_with_impl(FormattedOutputFunction& output,
418 char const * file, int line, char const * function,
419 InputIterator1 first_begin, InputIterator1 first_end,
420 InputIterator2 second_begin, InputIterator2 second_end,
421 BinaryPredicate predicate)
422{
423 InputIterator1 first_it = first_begin;
424 InputIterator2 second_it = second_begin;
425 typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
426 typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
427 std::size_t error_count = 0;
428 const std::size_t max_count = 8;
429 do
430 {
431 while ((first_it != first_end) && (second_it != second_end) && predicate(*first_it, *second_it))
432 {
433 ++first_it;
434 ++second_it;
435 ++first_index;
436 ++second_index;
437 }
438 if ((first_it == first_end) || (second_it == second_end))
439 {
440 break; // do-while
441 }
442 if (error_count == 0)
443 {
444 output << file << "(" << line << "): Container contents differ in function '" << function << "':";
445 }
446 else if (error_count >= max_count)
447 {
448 output << " ...";
449 break;
450 }
451 output << " [" << first_index << "]";
452 ++first_it;
453 ++second_it;
454 ++first_index;
455 ++second_index;
456 ++error_count;
457 } while (first_it != first_end);
458
459 first_index += std::distance(first_it, first_end);
460 second_index += std::distance(second_it, second_end);
461 if (first_index != second_index)
462 {
463 if (error_count == 0)
464 {
465 output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
466 }
467 else
468 {
469 output << " [*] size(" << first_index << ") != size(" << second_index << ")";
470 }
471 ++error_count;
472 }
473
474 if (error_count == 0)
475 {
476 test_results();
477 return true;
478 }
479 else
480 {
481 output << std::endl;
482 ++test_results().errors();
483 return false;
484 }
485}
486
487#if defined(__clang__) && defined(__has_warning)
488# if __has_warning("-Wsign-compare")
489# pragma clang diagnostic pop
490# endif
491#elif defined(_MSC_VER)
492# pragma warning(pop)
493#elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
494# pragma GCC diagnostic pop
495#endif
496
497} // namespace detail
498
499inline int report_errors()
500{
501 boost::detail::test_result& result = boost::detail::test_results();
502 result.done();
503
504 int errors = result.errors();
505
506 if( errors == 0 )
507 {
508 BOOST_LIGHTWEIGHT_TEST_OSTREAM
509 << "No errors detected." << std::endl;
510 }
511 else
512 {
513 BOOST_LIGHTWEIGHT_TEST_OSTREAM
514 << errors << " error" << (errors == 1? "": "s") << " detected." << std::endl;
515 }
516
517 // `return report_errors();` from main only supports 8 bit exit codes
518 return errors < 256? errors: 255;
519}
520
521namespace core
522{
523
524inline void lwt_init()
525{
526 boost::detail::test_results();
527}
528
529} // namespace core
530} // namespace boost
531
532#define BOOST_TEST(expr) ( ::boost::detail::test_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (expr)? true: false) )
533#define BOOST_TEST_NOT(expr) BOOST_TEST(!(expr))
534
535#define BOOST_ERROR(msg) ( ::boost::detail::error_impl(msg, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
536
537#define BOOST_TEST_WITH(expr1,expr2,predicate) ( ::boost::detail::test_with_impl(predicate, #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
538
539#define BOOST_TEST_EQ(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_eq(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
540#define BOOST_TEST_NE(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_ne(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
541
542#define BOOST_TEST_LT(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_lt(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
543#define BOOST_TEST_LE(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_le(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
544#define BOOST_TEST_GT(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_gt(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
545#define BOOST_TEST_GE(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_ge(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
546
547#define BOOST_TEST_CSTR_EQ(expr1,expr2) ( ::boost::detail::test_cstr_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
548#define BOOST_TEST_CSTR_NE(expr1,expr2) ( ::boost::detail::test_cstr_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
549
550#define BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) ( ::boost::detail::test_all_eq_impl(BOOST_LIGHTWEIGHT_TEST_OSTREAM, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, begin1, end1, begin2, end2) )
551#define BOOST_TEST_ALL_WITH(begin1, end1, begin2, end2, predicate) ( ::boost::detail::test_all_with_impl(BOOST_LIGHTWEIGHT_TEST_OSTREAM, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, begin1, end1, begin2, end2, predicate) )
552
553#ifndef BOOST_NO_EXCEPTIONS
554 #define BOOST_TEST_THROWS( EXPR, EXCEP ) \
555 try { \
556 EXPR; \
557 ::boost::detail::throw_failed_impl \
558 (#EXPR, #EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
559 } \
560 catch(EXCEP const&) { \
561 ::boost::detail::test_results(); \
562 } \
563 catch(...) { \
564 ::boost::detail::throw_failed_impl \
565 (#EXPR, #EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
566 } \
567 //
568#else
569 #define BOOST_TEST_THROWS( EXPR, EXCEP )
570#endif
571
572#ifndef BOOST_NO_EXCEPTIONS
573# define BOOST_TEST_NO_THROW(EXPR) \
574 try { \
575 EXPR; \
576 } catch (const std::exception& e) { \
577 ::boost::detail::no_throw_failed_impl \
578 (#EXPR, e.what(), __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
579 } catch (...) { \
580 ::boost::detail::no_throw_failed_impl \
581 (#EXPR, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
582 }
583 //
584#else
585# define BOOST_TEST_NO_THROW(EXPR) { EXPR; }
586#endif
587
588#endif // #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_HPP
589

source code of boost/libs/core/include/boost/core/lightweight_test.hpp