lightweight_test.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_HPP
  2. #define BOOST_CORE_LIGHTWEIGHT_TEST_HPP
  3. // MS compatible compilers support #pragma once
  4. #if defined(_MSC_VER)
  5. # pragma once
  6. #endif
  7. //
  8. // boost/core/lightweight_test.hpp - lightweight test library
  9. //
  10. // Copyright (c) 2002, 2009, 2014 Peter Dimov
  11. // Copyright (2) Beman Dawes 2010, 2011
  12. // Copyright (3) Ion Gaztanaga 2013
  13. //
  14. // Distributed under the Boost Software License, Version 1.0.
  15. // See accompanying file LICENSE_1_0.txt or copy at
  16. // http://www.boost.org/LICENSE_1_0.txt
  17. //
  18. #include <boost/core/no_exceptions_support.hpp>
  19. #include <boost/assert.hpp>
  20. #include <boost/current_function.hpp>
  21. #include <iostream>
  22. #include <iterator>
  23. #include <cstring>
  24. #include <cstddef>
  25. // IDE's like Visual Studio perform better if output goes to std::cout or
  26. // some other stream, so allow user to configure output stream:
  27. #ifndef BOOST_LIGHTWEIGHT_TEST_OSTREAM
  28. # define BOOST_LIGHTWEIGHT_TEST_OSTREAM std::cerr
  29. #endif
  30. namespace boost
  31. {
  32. namespace detail
  33. {
  34. struct report_errors_reminder
  35. {
  36. bool called_report_errors_function;
  37. report_errors_reminder() : called_report_errors_function(false) {}
  38. ~report_errors_reminder()
  39. {
  40. BOOST_ASSERT(called_report_errors_function); // verify report_errors() was called
  41. }
  42. };
  43. inline report_errors_reminder& report_errors_remind()
  44. {
  45. static report_errors_reminder r;
  46. return r;
  47. }
  48. inline int & test_errors()
  49. {
  50. static int x = 0;
  51. report_errors_remind();
  52. return x;
  53. }
  54. inline void test_failed_impl(char const * expr, char const * file, int line, char const * function)
  55. {
  56. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  57. << file << "(" << line << "): test '" << expr << "' failed in function '"
  58. << function << "'" << std::endl;
  59. ++test_errors();
  60. }
  61. inline void error_impl(char const * msg, char const * file, int line, char const * function)
  62. {
  63. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  64. << file << "(" << line << "): " << msg << " in function '"
  65. << function << "'" << std::endl;
  66. ++test_errors();
  67. }
  68. inline void throw_failed_impl(char const * excep, char const * file, int line, char const * function)
  69. {
  70. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  71. << file << "(" << line << "): Exception '" << excep << "' not thrown in function '"
  72. << function << "'" << std::endl;
  73. ++test_errors();
  74. }
  75. // In the comparisons below, it is possible that T and U are signed and unsigned integer types, which generates warnings in some compilers.
  76. // A cleaner fix would require common_type trait or some meta-programming, which would introduce a dependency on Boost.TypeTraits. To avoid
  77. // the dependency we just disable the warnings.
  78. #if defined(_MSC_VER)
  79. # pragma warning(push)
  80. # pragma warning(disable: 4389)
  81. #elif defined(__clang__) && defined(__has_warning)
  82. # if __has_warning("-Wsign-compare")
  83. # pragma clang diagnostic push
  84. # pragma clang diagnostic ignored "-Wsign-compare"
  85. # endif
  86. #elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
  87. # pragma GCC diagnostic push
  88. # pragma GCC diagnostic ignored "-Wsign-compare"
  89. #endif
  90. // specialize test output for char pointers to avoid printing as cstring
  91. template <class T> inline const T& test_output_impl(const T& v) { return v; }
  92. inline const void* test_output_impl(const char* v) { return v; }
  93. inline const void* test_output_impl(const unsigned char* v) { return v; }
  94. inline const void* test_output_impl(const signed char* v) { return v; }
  95. inline const void* test_output_impl(char* v) { return v; }
  96. inline const void* test_output_impl(unsigned char* v) { return v; }
  97. inline const void* test_output_impl(signed char* v) { return v; }
  98. template<class T> inline const void* test_output_impl(T volatile* v) { return const_cast<T*>(v); }
  99. #if !defined( BOOST_NO_CXX11_NULLPTR )
  100. inline const void* test_output_impl(std::nullptr_t) { return nullptr; }
  101. #endif
  102. template<class T, class U> inline void test_eq_impl( char const * expr1, char const * expr2,
  103. char const * file, int line, char const * function, T const & t, U const & u )
  104. {
  105. if( t == u )
  106. {
  107. report_errors_remind();
  108. }
  109. else
  110. {
  111. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  112. << file << "(" << line << "): test '" << expr1 << " == " << expr2
  113. << "' failed in function '" << function << "': "
  114. << "'" << test_output_impl(t) << "' != '" << test_output_impl(u) << "'" << std::endl;
  115. ++test_errors();
  116. }
  117. }
  118. template<class T, class U> inline void test_ne_impl( char const * expr1, char const * expr2,
  119. char const * file, int line, char const * function, T const & t, U const & u )
  120. {
  121. if( t != u )
  122. {
  123. report_errors_remind();
  124. }
  125. else
  126. {
  127. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  128. << file << "(" << line << "): test '" << expr1 << " != " << expr2
  129. << "' failed in function '" << function << "': "
  130. << "'" << test_output_impl(t) << "' == '" << test_output_impl(u) << "'" << std::endl;
  131. ++test_errors();
  132. }
  133. }
  134. template<class T, class U> inline void test_lt_impl( char const * expr1, char const * expr2,
  135. char const * file, int line, char const * function, T const & t, U const & u )
  136. {
  137. if( t < u )
  138. {
  139. report_errors_remind();
  140. }
  141. else
  142. {
  143. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  144. << file << "(" << line << "): test '" << expr1 << " < " << expr2
  145. << "' failed in function '" << function << "': "
  146. << "'" << test_output_impl(t) << "' >= '" << test_output_impl(u) << "'" << std::endl;
  147. ++test_errors();
  148. }
  149. }
  150. template<class T, class U> inline void test_le_impl( char const * expr1, char const * expr2,
  151. char const * file, int line, char const * function, T const & t, U const & u )
  152. {
  153. if( t <= u )
  154. {
  155. report_errors_remind();
  156. }
  157. else
  158. {
  159. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  160. << file << "(" << line << "): test '" << expr1 << " <= " << expr2
  161. << "' failed in function '" << function << "': "
  162. << "'" << test_output_impl(t) << "' > '" << test_output_impl(u) << "'" << std::endl;
  163. ++test_errors();
  164. }
  165. }
  166. template<class T, class U> inline void test_gt_impl( char const * expr1, char const * expr2,
  167. char const * file, int line, char const * function, T const & t, U const & u )
  168. {
  169. if( t > u )
  170. {
  171. report_errors_remind();
  172. }
  173. else
  174. {
  175. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  176. << file << "(" << line << "): test '" << expr1 << " > " << expr2
  177. << "' failed in function '" << function << "': "
  178. << "'" << test_output_impl(t) << "' <= '" << test_output_impl(u) << "'" << std::endl;
  179. ++test_errors();
  180. }
  181. }
  182. template<class T, class U> inline void test_ge_impl( char const * expr1, char const * expr2,
  183. char const * file, int line, char const * function, T const & t, U const & u )
  184. {
  185. if( t >= u )
  186. {
  187. report_errors_remind();
  188. }
  189. else
  190. {
  191. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  192. << file << "(" << line << "): test '" << expr1 << " >= " << expr2
  193. << "' failed in function '" << function << "': "
  194. << "'" << test_output_impl(t) << "' < '" << test_output_impl(u) << "'" << std::endl;
  195. ++test_errors();
  196. }
  197. }
  198. inline void test_cstr_eq_impl( char const * expr1, char const * expr2,
  199. char const * file, int line, char const * function, char const * const t, char const * const u )
  200. {
  201. if( std::strcmp(t, u) == 0 )
  202. {
  203. report_errors_remind();
  204. }
  205. else
  206. {
  207. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  208. << file << "(" << line << "): test '" << expr1 << " == " << expr2
  209. << "' failed in function '" << function << "': "
  210. << "'" << t << "' != '" << u << "'" << std::endl;
  211. ++test_errors();
  212. }
  213. }
  214. inline void test_cstr_ne_impl( char const * expr1, char const * expr2,
  215. char const * file, int line, char const * function, char const * const t, char const * const u )
  216. {
  217. if( std::strcmp(t, u) != 0 )
  218. {
  219. report_errors_remind();
  220. }
  221. else
  222. {
  223. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  224. << file << "(" << line << "): test '" << expr1 << " == " << expr2
  225. << "' failed in function '" << function << "': "
  226. << "'" << t << "' == '" << u << "'" << std::endl;
  227. ++test_errors();
  228. }
  229. }
  230. template<class FormattedOutputFunction, class InputIterator1, class InputIterator2>
  231. void test_all_eq_impl(FormattedOutputFunction& output,
  232. char const * file, int line, char const * function,
  233. InputIterator1 first_begin, InputIterator1 first_end,
  234. InputIterator2 second_begin, InputIterator2 second_end)
  235. {
  236. InputIterator1 first_it = first_begin;
  237. InputIterator2 second_it = second_begin;
  238. typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
  239. typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
  240. std::size_t error_count = 0;
  241. const std::size_t max_count = 8;
  242. do
  243. {
  244. while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it))
  245. {
  246. ++first_it;
  247. ++second_it;
  248. ++first_index;
  249. ++second_index;
  250. }
  251. if ((first_it == first_end) || (second_it == second_end))
  252. {
  253. break; // do-while
  254. }
  255. if (error_count == 0)
  256. {
  257. output << file << "(" << line << "): Container contents differ in function '" << function << "':";
  258. }
  259. else if (error_count >= max_count)
  260. {
  261. output << " ...";
  262. break;
  263. }
  264. output << " [" << first_index << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'";
  265. ++first_it;
  266. ++second_it;
  267. ++first_index;
  268. ++second_index;
  269. ++error_count;
  270. } while (first_it != first_end);
  271. first_index += std::distance(first_it, first_end);
  272. second_index += std::distance(second_it, second_end);
  273. if (first_index != second_index)
  274. {
  275. if (error_count == 0)
  276. {
  277. output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
  278. }
  279. else
  280. {
  281. output << " [*] size(" << first_index << ") != size(" << second_index << ")";
  282. }
  283. ++error_count;
  284. }
  285. if (error_count == 0)
  286. {
  287. boost::detail::report_errors_remind();
  288. }
  289. else
  290. {
  291. output << std::endl;
  292. ++boost::detail::test_errors();
  293. }
  294. }
  295. template<class FormattedOutputFunction, class InputIterator1, class InputIterator2, typename BinaryPredicate>
  296. void test_all_with_impl(FormattedOutputFunction& output,
  297. char const * file, int line, char const * function,
  298. InputIterator1 first_begin, InputIterator1 first_end,
  299. InputIterator2 second_begin, InputIterator2 second_end,
  300. BinaryPredicate predicate)
  301. {
  302. InputIterator1 first_it = first_begin;
  303. InputIterator2 second_it = second_begin;
  304. typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
  305. typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
  306. std::size_t error_count = 0;
  307. const std::size_t max_count = 8;
  308. do
  309. {
  310. while ((first_it != first_end) && (second_it != second_end) && predicate(*first_it, *second_it))
  311. {
  312. ++first_it;
  313. ++second_it;
  314. ++first_index;
  315. ++second_index;
  316. }
  317. if ((first_it == first_end) || (second_it == second_end))
  318. {
  319. break; // do-while
  320. }
  321. if (error_count == 0)
  322. {
  323. output << file << "(" << line << "): Container contents differ in function '" << function << "':";
  324. }
  325. else if (error_count >= max_count)
  326. {
  327. output << " ...";
  328. break;
  329. }
  330. output << " [" << first_index << "]";
  331. ++first_it;
  332. ++second_it;
  333. ++first_index;
  334. ++second_index;
  335. ++error_count;
  336. } while (first_it != first_end);
  337. first_index += std::distance(first_it, first_end);
  338. second_index += std::distance(second_it, second_end);
  339. if (first_index != second_index)
  340. {
  341. if (error_count == 0)
  342. {
  343. output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
  344. }
  345. else
  346. {
  347. output << " [*] size(" << first_index << ") != size(" << second_index << ")";
  348. }
  349. ++error_count;
  350. }
  351. if (error_count == 0)
  352. {
  353. report_errors_remind();
  354. }
  355. else
  356. {
  357. output << std::endl;
  358. ++test_errors();
  359. }
  360. }
  361. #if defined(_MSC_VER)
  362. # pragma warning(pop)
  363. #elif defined(__clang__) && defined(__has_warning)
  364. # if __has_warning("-Wsign-compare")
  365. # pragma clang diagnostic pop
  366. # endif
  367. #elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
  368. # pragma GCC diagnostic pop
  369. #endif
  370. } // namespace detail
  371. inline int report_errors()
  372. {
  373. boost::detail::report_errors_remind().called_report_errors_function = true;
  374. int errors = boost::detail::test_errors();
  375. if( errors == 0 )
  376. {
  377. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  378. << "No errors detected." << std::endl;
  379. return 0;
  380. }
  381. else
  382. {
  383. BOOST_LIGHTWEIGHT_TEST_OSTREAM
  384. << errors << " error" << (errors == 1? "": "s") << " detected." << std::endl;
  385. return 1;
  386. }
  387. }
  388. } // namespace boost
  389. #define BOOST_TEST(expr) ((expr)? (void)0: ::boost::detail::test_failed_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION))
  390. #define BOOST_TEST_NOT(expr) BOOST_TEST(!(expr))
  391. #define BOOST_ERROR(msg) ( ::boost::detail::error_impl(msg, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
  392. #define BOOST_TEST_EQ(expr1,expr2) ( ::boost::detail::test_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
  393. #define BOOST_TEST_NE(expr1,expr2) ( ::boost::detail::test_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
  394. #define BOOST_TEST_LT(expr1,expr2) ( ::boost::detail::test_lt_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
  395. #define BOOST_TEST_LE(expr1,expr2) ( ::boost::detail::test_le_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
  396. #define BOOST_TEST_GT(expr1,expr2) ( ::boost::detail::test_gt_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
  397. #define BOOST_TEST_GE(expr1,expr2) ( ::boost::detail::test_ge_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
  398. #define BOOST_TEST_CSTR_EQ(expr1,expr2) ( ::boost::detail::test_cstr_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
  399. #define BOOST_TEST_CSTR_NE(expr1,expr2) ( ::boost::detail::test_cstr_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
  400. #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) )
  401. #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) )
  402. #ifndef BOOST_NO_EXCEPTIONS
  403. #define BOOST_TEST_THROWS( EXPR, EXCEP ) \
  404. try { \
  405. EXPR; \
  406. ::boost::detail::throw_failed_impl \
  407. (#EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
  408. } \
  409. catch(EXCEP const&) { \
  410. } \
  411. catch(...) { \
  412. ::boost::detail::throw_failed_impl \
  413. (#EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
  414. } \
  415. //
  416. #else
  417. #define BOOST_TEST_THROWS( EXPR, EXCEP )
  418. #endif
  419. #endif // #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_HPP