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