[PowerPC][NFC] Cleanup PPCCTRLoopsVerify pass
[llvm-project.git] / libcxx / test / support / rapid-cxx-test.h
blob0f3dcd84ec7bdff3c3f1e3cbdb019cbb4050f005
1 #ifndef RAPID_CXX_TEST_H
2 #define RAPID_CXX_TEST_H
4 # include <cstddef>
5 # include <cstdlib>
6 # include <cstdio>
7 # include <cstring>
8 # include <cassert>
10 #include "test_macros.h"
12 #if !defined(RAPID_CXX_TEST_NO_SYSTEM_HEADER) || !defined(__GNUC__)
13 #pragma GCC system_header
14 #endif
16 # define RAPID_CXX_TEST_PP_CAT(x, y) RAPID_CXX_TEST_PP_CAT_2(x, y)
17 # define RAPID_CXX_TEST_PP_CAT_2(x, y) x##y
19 # define RAPID_CXX_TEST_PP_STR(...) RAPID_CXX_TEST_PP_STR_2(__VA_ARGS__)
20 # define RAPID_CXX_TEST_PP_STR_2(...) #__VA_ARGS__
22 # if defined(__GNUC__)
23 # define TEST_FUNC_NAME() __PRETTY_FUNCTION__
24 # define RAPID_CXX_TEST_UNUSED __attribute__((unused))
25 # else
26 # define TEST_FUNC_NAME() __func__
27 # define RAPID_CXX_TEST_UNUSED
28 # endif
30 ////////////////////////////////////////////////////////////////////////////////
31 // TEST_SUITE
32 ////////////////////////////////////////////////////////////////////////////////
33 # define TEST_SUITE(Name) \
34 namespace Name \
35 { \
36 inline ::rapid_cxx_test::test_suite & get_test_suite() \
37 { \
38 static ::rapid_cxx_test::test_suite m_suite(#Name); \
39 return m_suite; \
40 } \
42 inline int unit_test_main(int, char**) \
43 { \
44 ::rapid_cxx_test::test_runner runner(get_test_suite()); \
45 return runner.run(); \
46 } \
47 } \
48 int main(int argc, char **argv) \
49 { \
50 return Name::unit_test_main(argc, argv); \
51 } \
52 namespace Name \
53 { /* namespace closed in TEST_SUITE_END */
56 ////////////////////////////////////////////////////////////////////////////////
57 // TEST_SUITE_END
58 ////////////////////////////////////////////////////////////////////////////////
59 # define TEST_SUITE_END() \
60 } /* namespace opened in TEST_SUITE(...) */
63 ////////////////////////////////////////////////////////////////////////////////
64 // TEST_CASE
65 ////////////////////////////////////////////////////////////////////////////////
67 # if !defined(__clang__)
69 # define TEST_CASE(Name) \
70 void Name(); \
71 static void RAPID_CXX_TEST_PP_CAT(Name, _invoker)() \
72 { \
73 Name(); \
74 } \
75 static ::rapid_cxx_test::registrar \
76 RAPID_CXX_TEST_PP_CAT(rapid_cxx_test_registrar_, Name)( \
77 get_test_suite() \
78 , ::rapid_cxx_test::test_case(__FILE__, #Name, __LINE__, & RAPID_CXX_TEST_PP_CAT(Name, _invoker)) \
79 ); \
80 void Name()
82 # else /* __clang__ */
84 # define TEST_CASE(Name) \
85 void Name(); \
86 static void RAPID_CXX_TEST_PP_CAT(Name, _invoker)() \
87 { \
88 Name(); \
89 } \
90 _Pragma("clang diagnostic push") \
91 _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \
92 static ::rapid_cxx_test::registrar \
93 RAPID_CXX_TEST_PP_CAT(rapid_cxx_test_registrar_, Name)( \
94 get_test_suite() \
95 , ::rapid_cxx_test::test_case(__FILE__, #Name, __LINE__, & RAPID_CXX_TEST_PP_CAT(Name, _invoker)) \
96 ); \
97 _Pragma("clang diagnostic pop") \
98 void Name()
100 # endif /* !defined(__clang__) */
103 # define TEST_SET_CHECKPOINT() ::rapid_cxx_test::set_checkpoint(__FILE__, TEST_FUNC_NAME(), __LINE__)
105 #define RAPID_CXX_TEST_OUTCOME()
107 ////////////////////////////////////////////////////////////////////////////////
108 // TEST_UNSUPPORTED
109 ////////////////////////////////////////////////////////////////////////////////
110 # define TEST_UNSUPPORTED() \
111 do { \
112 TEST_SET_CHECKPOINT(); \
113 ::rapid_cxx_test::test_outcome m_f( \
114 ::rapid_cxx_test::failure_type::unsupported, __FILE__, TEST_FUNC_NAME(), __LINE__ \
115 , "", "" \
116 ); \
117 ::rapid_cxx_test::get_reporter().report(m_f); \
118 return; \
119 } while (false)
123 ////////////////////////////////////////////////////////////////////////////////
124 // BASIC ASSERTIONS
125 ////////////////////////////////////////////////////////////////////////////////
126 # define TEST_WARN(...) \
127 do { \
128 TEST_SET_CHECKPOINT(); \
129 ::rapid_cxx_test::test_outcome m_f( \
130 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
131 , "TEST_WARN(" #__VA_ARGS__ ")", "" \
132 ); \
133 if (not (__VA_ARGS__)) { \
134 m_f.type = ::rapid_cxx_test::failure_type::warn; \
136 ::rapid_cxx_test::get_reporter().report(m_f); \
137 } while (false)
140 # define TEST_CHECK(...) \
141 do { \
142 TEST_SET_CHECKPOINT(); \
143 ::rapid_cxx_test::test_outcome m_f( \
144 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
145 , "TEST_CHECK(" #__VA_ARGS__ ")", "" \
146 ); \
147 if (not (__VA_ARGS__)) { \
148 m_f.type = ::rapid_cxx_test::failure_type::check; \
150 ::rapid_cxx_test::get_reporter().report(m_f); \
151 } while (false)
154 # define TEST_REQUIRE(...) \
155 do { \
156 TEST_SET_CHECKPOINT(); \
157 ::rapid_cxx_test::test_outcome m_f( \
158 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
159 , "TEST_REQUIRE(" #__VA_ARGS__ ")", "" \
160 ); \
161 if (not (__VA_ARGS__)) { \
162 m_f.type = ::rapid_cxx_test::failure_type::require; \
164 ::rapid_cxx_test::get_reporter().report(m_f); \
165 if (m_f.type != ::rapid_cxx_test::failure_type::none) { \
166 return; \
168 } while (false)
171 # define TEST_ASSERT(...) \
172 do { \
173 TEST_SET_CHECKPOINT(); \
174 ::rapid_cxx_test::test_outcome m_f( \
175 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
176 , "TEST_ASSERT(" #__VA_ARGS__ ")", "" \
177 ); \
178 if (not (__VA_ARGS__)) { \
179 m_f.type = ::rapid_cxx_test::failure_type::assert; \
181 ::rapid_cxx_test::get_reporter().report(m_f); \
182 if (m_f.type != ::rapid_cxx_test::failure_type::none) { \
183 std::abort(); \
185 } while (false)
188 ////////////////////////////////////////////////////////////////////////////////
189 // TEST_CHECK_NO_THROW / TEST_CHECK_THROW
190 ////////////////////////////////////////////////////////////////////////////////
191 #ifndef TEST_HAS_NO_EXCEPTIONS
193 # define TEST_CHECK_NO_THROW(...) \
194 do { \
195 TEST_SET_CHECKPOINT(); \
196 ::rapid_cxx_test::test_outcome m_f( \
197 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
198 , "TEST_CHECK_NO_THROW(" #__VA_ARGS__ ")", "" \
199 ); \
200 try { \
201 (static_cast<void>(__VA_ARGS__)); \
202 } catch (...) { \
203 m_f.type = ::rapid_cxx_test::failure_type::check; \
205 ::rapid_cxx_test::get_reporter().report(m_f); \
206 } while (false)
209 # define TEST_CHECK_THROW(Except, ...) \
210 do { \
211 TEST_SET_CHECKPOINT(); \
212 ::rapid_cxx_test::test_outcome m_f( \
213 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
214 , "TEST_CHECK_THROW(" #Except "," #__VA_ARGS__ ")", "" \
215 ); \
216 try { \
217 (static_cast<void>(__VA_ARGS__)); \
218 m_f.type = ::rapid_cxx_test::failure_type::check; \
219 } catch (Except const &) {} \
220 ::rapid_cxx_test::get_reporter().report(m_f); \
221 } while (false)
224 #define TEST_CHECK_THROW_RESULT(Except, Checker, ...) \
225 do { \
226 TEST_SET_CHECKPOINT(); \
227 ::rapid_cxx_test::test_outcome m_f(::rapid_cxx_test::failure_type::none, \
228 __FILE__, TEST_FUNC_NAME(), __LINE__, \
229 "TEST_CHECK_THROW_RESULT(" #Except \
230 "," #Checker "," #__VA_ARGS__ ")", \
231 ""); \
232 try { \
233 (static_cast<void>(__VA_ARGS__)); \
234 m_f.type = ::rapid_cxx_test::failure_type::check; \
235 } catch (Except const& Caught) { \
236 Checker(Caught); \
238 ::rapid_cxx_test::get_reporter().report(m_f); \
239 } while (false)
242 #else // TEST_HAS_NO_EXCEPTIONS
244 # define TEST_CHECK_NO_THROW(...) \
245 do { \
246 TEST_SET_CHECKPOINT(); \
247 ::rapid_cxx_test::test_outcome m_f( \
248 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
249 , "TEST_CHECK_NO_THROW(" #__VA_ARGS__ ")", "" \
250 ); \
251 (static_cast<void>(__VA_ARGS__)); \
252 ::rapid_cxx_test::get_reporter().report(m_f); \
253 } while (false)
256 #define TEST_CHECK_THROW(Except, ...) ((void)0)
257 #define TEST_CHECK_THROW_RESULT(Except, Checker, ...) ((void)0)
259 #endif // TEST_HAS_NO_EXCEPTIONS
262 ////////////////////////////////////////////////////////////////////////////////
263 // TEST_REQUIRE_NO_THROW / TEST_REQUIRE_THROWs
264 ////////////////////////////////////////////////////////////////////////////////
265 #ifndef TEST_HAS_NO_EXCEPTIONS
267 # define TEST_REQUIRE_NO_THROW(...) \
268 do { \
269 TEST_SET_CHECKPOINT(); \
270 ::rapid_cxx_test::test_outcome m_f( \
271 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
272 , "TEST_REQUIRE_NO_THROW(" #__VA_ARGS__ ")", "" \
273 ); \
274 try { \
275 (static_cast<void>(__VA_ARGS__)); \
276 } catch (...) { \
277 m_f.type = ::rapid_cxx_test::failure_type::require; \
279 ::rapid_cxx_test::get_reporter().report(m_f); \
280 if (m_f.type != ::rapid_cxx_test::failure_type::none) { \
281 return; \
283 } while (false)
286 # define TEST_REQUIRE_THROW(Except, ...) \
287 do { \
288 TEST_SET_CHECKPOINT(); \
289 ::rapid_cxx_test::test_outcome m_f( \
290 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
291 , "TEST_REQUIRE_THROW(" #Except "," #__VA_ARGS__ ")", "" \
292 ); \
293 try { \
294 (static_cast<void>(__VA_ARGS__)); \
295 m_f.type = ::rapid_cxx_test::failure_type::require; \
296 } catch (Except const &) {} \
297 ::rapid_cxx_test::get_reporter().report(m_f); \
298 if (m_f.type != ::rapid_cxx_test::failure_type::none) { \
299 return; \
301 } while (false)
304 #else // TEST_HAS_NO_EXCEPTIONS
306 # define TEST_REQUIRE_NO_THROW(...) \
307 do { \
308 TEST_SET_CHECKPOINT(); \
309 ::rapid_cxx_test::test_outcome m_f( \
310 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
311 , "TEST_REQUIRE_NO_THROW(" #__VA_ARGS__ ")", "" \
312 ); \
313 (static_cast<void>(__VA_ARGS__)); \
314 ::rapid_cxx_test::get_reporter().report(m_f); \
315 } while (false)
318 #define TEST_REQUIRE_THROW(Except, ...) ((void)0)
320 #endif // TEST_HAS_NO_EXCEPTIONS
322 ////////////////////////////////////////////////////////////////////////////////
323 // TEST_ASSERT_NO_THROW / TEST_ASSERT_THROW
324 ////////////////////////////////////////////////////////////////////////////////
325 #ifndef TEST_HAS_NO_EXCEPTIONS
327 # define TEST_ASSERT_NO_THROW(...) \
328 do { \
329 TEST_SET_CHECKPOINT(); \
330 ::rapid_cxx_test::test_outcome m_f( \
331 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
332 , "TEST_ASSERT_NO_THROW(" #__VA_ARGS__ ")", "" \
333 ); \
334 try { \
335 (static_cast<void>(__VA_ARGS__)); \
336 } catch (...) { \
337 m_f.type = ::rapid_cxx_test::failure_type::assert; \
339 ::rapid_cxx_test::get_reporter().report(m_f); \
340 if (m_f.type != ::rapid_cxx_test::failure_type::none) { \
341 std::abort(); \
343 } while (false)
346 # define TEST_ASSERT_THROW(Except, ...) \
347 do { \
348 TEST_SET_CHECKPOINT(); \
349 ::rapid_cxx_test::test_outcome m_f( \
350 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
351 , "TEST_ASSERT_THROW(" #Except "," #__VA_ARGS__ ")", "" \
352 ); \
353 try { \
354 (static_cast<void>(__VA_ARGS__)); \
355 m_f.type = ::rapid_cxx_test::failure_type::assert; \
356 } catch (Except const &) {} \
357 ::rapid_cxx_test::get_reporter().report(m_f); \
358 if (m_f.type != ::rapid_cxx_test::failure_type::none) { \
359 std::abort(); \
361 } while (false)
364 #else // TEST_HAS_NO_EXCEPTIONS
366 # define TEST_ASSERT_NO_THROW(...) \
367 do { \
368 TEST_SET_CHECKPOINT(); \
369 ::rapid_cxx_test::test_outcome m_f( \
370 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
371 , "TEST_ASSERT_NO_THROW(" #__VA_ARGS__ ")", "" \
372 ); \
373 (static_cast<void>(__VA_ARGS__)); \
374 ::rapid_cxx_test::get_reporter().report(m_f); \
375 } while (false)
378 #define TEST_ASSERT_THROW(Except, ...) ((void)0)
380 #endif // TEST_HAS_NO_EXCEPTIONS
382 ////////////////////////////////////////////////////////////////////////////////
384 ////////////////////////////////////////////////////////////////////////////////
386 # define TEST_WARN_EQUAL_COLLECTIONS(...) \
387 do { \
388 TEST_SET_CHECKPOINT(); \
389 ::rapid_cxx_test::test_outcome m_f( \
390 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
391 , "TEST_WARN_EQUAL_COLLECTIONS(" #__VA_ARGS__ ")", "" \
392 ); \
393 if (not ::rapid_cxx_test::detail::check_equal_collections_impl(__VA_ARGS__)) { \
394 m_f.type = ::rapid_cxx_test::failure_type::warn; \
396 ::rapid_cxx_test::get_reporter().report(m_f); \
397 } while (false)
400 # define TEST_CHECK_EQUAL_COLLECTIONS(...) \
401 do { \
402 TEST_SET_CHECKPOINT(); \
403 ::rapid_cxx_test::test_outcome m_f( \
404 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
405 , "TEST_CHECK_EQUAL_COLLECTIONS(" #__VA_ARGS__ ")", "" \
406 ); \
407 if (not ::rapid_cxx_test::detail::check_equal_collections_impl(__VA_ARGS__)) { \
408 m_f.type = ::rapid_cxx_test::failure_type::check; \
410 ::rapid_cxx_test::get_reporter().report(m_f); \
411 } while (false)
414 # define TEST_REQUIRE_EQUAL_COLLECTIONS(...) \
415 do { \
416 TEST_SET_CHECKPOINT(); \
417 ::rapid_cxx_test::test_outcome m_f( \
418 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
419 , "TEST_REQUIRE_EQUAL_COLLECTIONS(" #__VA_ARGS__ ")", "" \
420 ); \
421 if (not ::rapid_cxx_test::detail::check_equal_collections_impl(__VA_ARGS__)) { \
422 m_f.type = ::rapid_cxx_test::failure_type::require; \
424 ::rapid_cxx_test::get_reporter().report(m_f); \
425 if (m_f.type != ::rapid_cxx_test::failure_type::none) { \
426 return; \
428 } while (false)
431 # define TEST_ASSERT_EQUAL_COLLECTIONS(...) \
432 do { \
433 TEST_SET_CHECKPOINT(); \
434 ::rapid_cxx_test::test_outcome m_f( \
435 ::rapid_cxx_test::failure_type::none, __FILE__, TEST_FUNC_NAME(), __LINE__ \
436 , "TEST_ASSERT_EQUAL_COLLECTIONS(" #__VA_ARGS__ ")", "" \
437 ); \
438 if (not ::rapid_cxx_test::detail::check_equal_collections_impl(__VA_ARGS__)) { \
439 m_f.type = ::rapid_cxx_test::failure_type::assert; \
441 ::rapid_cxx_test::get_reporter().report(m_f); \
442 if (m_f.type != ::rapid_cxx_test::failure_type::none) { \
443 ::std::abort(); \
445 } while (false)
448 namespace rapid_cxx_test
450 typedef void (*invoker_t)();
452 ////////////////////////////////////////////////////////////////////////////
453 struct test_case
455 test_case()
456 : file(""), func(""), line(0), invoke(NULL)
459 test_case(const char* file1, const char* func1, std::size_t line1,
460 invoker_t invoke1)
461 : file(file1), func(func1), line(line1), invoke(invoke1)
464 const char *file;
465 const char *func;
466 std::size_t line;
467 invoker_t invoke;
470 ////////////////////////////////////////////////////////////////////////////
471 struct failure_type
473 enum enum_type {
474 none,
475 unsupported,
476 warn,
477 check,
478 require,
479 assert,
480 uncaught_exception
484 typedef failure_type::enum_type failure_type_t;
486 ////////////////////////////////////////////////////////////////////////////
487 struct test_outcome
489 test_outcome()
490 : type(failure_type::none),
491 file(""), func(""), line(0),
492 expression(""), message("")
495 test_outcome(failure_type_t type1, const char* file1, const char* func1,
496 std::size_t line1, const char* expression1,
497 const char* message1)
498 : type(type1), file(file1), func(func1), line(line1),
499 expression(expression1), message(message1)
501 trim_func_string();
504 failure_type_t type;
505 const char *file;
506 const char *func;
507 std::size_t line;
508 const char *expression;
509 const char *message;
511 private:
512 void trim_file_string() {
513 const char* f_start = file;
514 const char* prev_start = f_start;
515 const char* last_start = f_start;
516 char last;
517 while ((last = *f_start) != '\0') {
518 ++f_start;
519 if (last == '/' && *f_start) {
520 prev_start = last_start;
521 last_start = f_start;
524 file = prev_start;
526 void trim_func_string() {
527 const char* void_loc = ::strstr(func, "void ");
528 if (void_loc == func) {
529 func += strlen("void ");
531 const char* namespace_loc = ::strstr(func, "::");
532 if (namespace_loc) {
533 func = namespace_loc + 2;
538 ////////////////////////////////////////////////////////////////////////////
539 struct checkpoint
541 const char *file;
542 const char *func;
543 std::size_t line;
546 namespace detail
548 inline checkpoint & global_checkpoint()
550 static checkpoint cp = {"", "", 0};
551 return cp;
555 ////////////////////////////////////////////////////////////////////////////
556 inline void set_checkpoint(const char* file, const char* func, std::size_t line)
558 checkpoint& cp = detail::global_checkpoint();
559 cp.file = file;
560 cp.func = func;
561 cp.line = line;
564 ////////////////////////////////////////////////////////////////////////////
565 inline checkpoint const & get_checkpoint()
567 return detail::global_checkpoint();
570 ////////////////////////////////////////////////////////////////////////////
571 class test_suite
573 public:
574 typedef test_case const* iterator;
575 typedef iterator const_iterator;
577 public:
578 test_suite(const char *xname)
579 : m_name(xname), m_tests(), m_size(0)
581 assert(xname);
584 public:
585 const char *name() const { return m_name; }
587 std::size_t size() const { return m_size; }
589 test_case const & operator[](std::size_t i) const
591 assert(i < m_size);
592 return m_tests[i];
595 const_iterator begin() const
596 { return m_tests; }
598 const_iterator end() const
600 return m_tests + m_size;
603 public:
604 std::size_t register_test(test_case tc)
606 static std::size_t test_case_max = sizeof(m_tests) / sizeof(test_case);
607 assert(m_size < test_case_max);
608 m_tests[m_size] = tc;
609 return m_size++;
612 private:
613 test_suite(test_suite const &);
614 test_suite & operator=(test_suite const &);
616 private:
617 const char* m_name;
618 // Since fast compile times in a priority, we use simple containers
619 // with hard limits.
620 test_case m_tests[256];
621 std::size_t m_size;
624 ////////////////////////////////////////////////////////////////////////////
625 class registrar
627 public:
628 registrar(test_suite & st, test_case tc)
630 st.register_test(tc);
634 ////////////////////////////////////////////////////////////////////////////
635 class test_reporter
637 public:
638 test_reporter()
639 : m_testcases(0), m_testcase_failures(0), m_unsupported(0),
640 m_assertions(0), m_warning_failures(0), m_check_failures(0),
641 m_require_failures(0), m_uncaught_exceptions(0), m_failure()
645 void test_case_begin()
647 ++m_testcases;
648 clear_failure();
651 void test_case_end()
653 if (m_failure.type != failure_type::none
654 && m_failure.type != failure_type::unsupported) {
655 ++m_testcase_failures;
659 # if defined(__GNUC__)
660 # pragma GCC diagnostic push
661 # pragma GCC diagnostic ignored "-Wswitch-default"
662 # endif
663 // Each assertion and failure is reported through this function.
664 void report(test_outcome o)
666 ++m_assertions;
667 switch (o.type)
669 case failure_type::none:
670 break;
671 case failure_type::unsupported:
672 ++m_unsupported;
673 m_failure = o;
674 break;
675 case failure_type::warn:
676 ++m_warning_failures;
677 report_error(o);
678 break;
679 case failure_type::check:
680 ++m_check_failures;
681 report_error(o);
682 m_failure = o;
683 break;
684 case failure_type::require:
685 ++m_require_failures;
686 report_error(o);
687 m_failure = o;
688 break;
689 case failure_type::assert:
690 report_error(o);
691 break;
692 case failure_type::uncaught_exception:
693 ++m_uncaught_exceptions;
694 std::fprintf(stderr
695 , "Test case FAILED with uncaught exception:\n"
696 " last checkpoint near %s::%lu %s\n\n"
697 , o.file, o.line, o.func
699 m_failure = o;
700 break;
703 # if defined(__GNUC__)
704 # pragma GCC diagnostic pop
705 # endif
707 test_outcome current_failure() const
709 return m_failure;
712 void clear_failure()
714 m_failure.type = failure_type::none;
715 m_failure.file = "";
716 m_failure.func = "";
717 m_failure.line = 0;
718 m_failure.expression = "";
719 m_failure.message = "";
722 std::size_t test_case_count() const
723 { return m_testcases; }
725 std::size_t test_case_failure_count() const
726 { return m_testcase_failures; }
728 std::size_t unsupported_count() const
729 { return m_unsupported; }
731 std::size_t assertion_count() const
732 { return m_assertions; }
734 std::size_t warning_failure_count() const
735 { return m_warning_failures; }
737 std::size_t check_failure_count() const
738 { return m_check_failures; }
740 std::size_t require_failure_count() const
741 { return m_require_failures; }
743 std::size_t failure_count() const
744 { return m_check_failures + m_require_failures + m_uncaught_exceptions; }
746 // Print a summary of what was run and the outcome.
747 void print_summary(const char* suitename) const
749 FILE* out = failure_count() ? stderr : stdout;
750 std::size_t testcases_run = m_testcases - m_unsupported;
751 std::fprintf(out, "Summary for testsuite %s:\n", suitename);
752 std::fprintf(out, " %lu of %lu test cases passed.\n", testcases_run - m_testcase_failures, testcases_run);
753 std::fprintf(out, " %lu of %lu assertions passed.\n", m_assertions - (m_warning_failures + m_check_failures + m_require_failures), m_assertions);
754 std::fprintf(out, " %lu unsupported test case%s.\n", m_unsupported, (m_unsupported != 1 ? "s" : ""));
757 private:
758 test_reporter(test_reporter const &);
759 test_reporter const & operator=(test_reporter const &);
761 void report_error(test_outcome o) const
763 std::fprintf(stderr, "In %s:%lu Assertion %s failed.\n in file: %s\n %s\n"
764 , o.func, o.line, o.expression, o.file, o.message ? o.message : ""
768 private:
769 // counts of testcases, failed testcases, and unsupported testcases.
770 std::size_t m_testcases;
771 std::size_t m_testcase_failures;
772 std::size_t m_unsupported;
774 // counts of assertions and assertion failures.
775 std::size_t m_assertions;
776 std::size_t m_warning_failures;
777 std::size_t m_check_failures;
778 std::size_t m_require_failures;
779 std::size_t m_uncaught_exceptions;
781 // The last failure. This is cleared between testcases.
782 test_outcome m_failure;
785 ////////////////////////////////////////////////////////////////////////////
786 inline test_reporter & get_reporter()
788 static test_reporter o;
789 return o;
792 ////////////////////////////////////////////////////////////////////////////
793 class test_runner
795 public:
796 test_runner(test_suite & ts)
797 : m_ts(ts)
800 public:
801 int run()
803 // for each testcase
804 for (test_suite::const_iterator b = m_ts.begin(), e = m_ts.end();
805 b != e; ++b)
807 test_case const& tc = *b;
808 set_checkpoint(tc.file, tc.func, tc.line);
809 get_reporter().test_case_begin();
810 #ifndef TEST_HAS_NO_EXCEPTIONS
811 try {
812 #endif
813 tc.invoke();
814 #ifndef TEST_HAS_NO_EXCEPTIONS
815 } catch (...) {
816 test_outcome o;
817 o.type = failure_type::uncaught_exception;
818 o.file = get_checkpoint().file;
819 o.func = get_checkpoint().func;
820 o.line = get_checkpoint().line;
821 o.expression = "";
822 o.message = "";
823 get_reporter().report(o);
825 #endif
826 get_reporter().test_case_end();
828 auto exit_code = get_reporter().failure_count() ? EXIT_FAILURE : EXIT_SUCCESS;
829 if (exit_code == EXIT_FAILURE || get_reporter().unsupported_count())
830 get_reporter().print_summary(m_ts.name());
831 return exit_code;
834 private:
835 test_runner(test_runner const &);
836 test_runner operator=(test_runner const &);
838 test_suite & m_ts;
841 namespace detail
843 template <class Iter1, class Iter2>
844 bool check_equal_collections_impl(
845 Iter1 start1, Iter1 const end1
846 , Iter2 start2, Iter2 const end2
849 while (start1 != end1 && start2 != end2) {
850 if (*start1 != *start2) {
851 return false;
853 ++start1; ++start2;
855 return (start1 == end1 && start2 == end2);
857 } // namespace detail
859 } // namespace rapid_cxx_test
862 # if defined(__GNUC__)
863 # pragma GCC diagnostic pop
864 # endif
866 #endif /* RAPID_CXX_TEST_H */