1 #ifndef RAPID_CXX_TEST_H
2 #define RAPID_CXX_TEST_H
10 #include "test_macros.h"
12 #if !defined(RAPID_CXX_TEST_NO_SYSTEM_HEADER) || !defined(__GNUC__)
13 #pragma GCC system_header
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))
26 # define TEST_FUNC_NAME() __func__
27 # define RAPID_CXX_TEST_UNUSED
30 ////////////////////////////////////////////////////////////////////////////////
32 ////////////////////////////////////////////////////////////////////////////////
33 # define TEST_SUITE(Name) \
36 inline ::rapid_cxx_test::test_suite & get_test_suite() \
38 static ::rapid_cxx_test::test_suite m_suite(#Name); \
42 inline int unit_test_main(int, char**) \
44 ::rapid_cxx_test::test_runner runner(get_test_suite()); \
45 return runner.run(); \
48 int main(int argc, char **argv) \
50 return Name::unit_test_main(argc, argv); \
53 { /* namespace closed in TEST_SUITE_END */
56 ////////////////////////////////////////////////////////////////////////////////
58 ////////////////////////////////////////////////////////////////////////////////
59 # define TEST_SUITE_END() \
60 } /* namespace opened in TEST_SUITE(...) */
63 ////////////////////////////////////////////////////////////////////////////////
65 ////////////////////////////////////////////////////////////////////////////////
67 # if !defined(__clang__)
69 # define TEST_CASE(Name) \
71 static void RAPID_CXX_TEST_PP_CAT(Name, _invoker)() \
75 static ::rapid_cxx_test::registrar \
76 RAPID_CXX_TEST_PP_CAT(rapid_cxx_test_registrar_, Name)( \
78 , ::rapid_cxx_test::test_case(__FILE__, #Name, __LINE__, & RAPID_CXX_TEST_PP_CAT(Name, _invoker)) \
82 # else /* __clang__ */
84 # define TEST_CASE(Name) \
86 static void RAPID_CXX_TEST_PP_CAT(Name, _invoker)() \
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)( \
95 , ::rapid_cxx_test::test_case(__FILE__, #Name, __LINE__, & RAPID_CXX_TEST_PP_CAT(Name, _invoker)) \
97 _Pragma("clang diagnostic pop") \
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 ////////////////////////////////////////////////////////////////////////////////
109 ////////////////////////////////////////////////////////////////////////////////
110 # define TEST_UNSUPPORTED() \
112 TEST_SET_CHECKPOINT(); \
113 ::rapid_cxx_test::test_outcome m_f( \
114 ::rapid_cxx_test::failure_type::unsupported, __FILE__, TEST_FUNC_NAME(), __LINE__ \
117 ::rapid_cxx_test::get_reporter().report(m_f); \
123 ////////////////////////////////////////////////////////////////////////////////
125 ////////////////////////////////////////////////////////////////////////////////
126 # define TEST_WARN(...) \
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__ ")", "" \
133 if (not (__VA_ARGS__)) { \
134 m_f.type = ::rapid_cxx_test::failure_type::warn; \
136 ::rapid_cxx_test::get_reporter().report(m_f); \
140 # define TEST_CHECK(...) \
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__ ")", "" \
147 if (not (__VA_ARGS__)) { \
148 m_f.type = ::rapid_cxx_test::failure_type::check; \
150 ::rapid_cxx_test::get_reporter().report(m_f); \
154 # define TEST_REQUIRE(...) \
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__ ")", "" \
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) { \
171 # define TEST_ASSERT(...) \
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__ ")", "" \
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) { \
188 ////////////////////////////////////////////////////////////////////////////////
189 // TEST_CHECK_NO_THROW / TEST_CHECK_THROW
190 ////////////////////////////////////////////////////////////////////////////////
191 #ifndef TEST_HAS_NO_EXCEPTIONS
193 # define TEST_CHECK_NO_THROW(...) \
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__ ")", "" \
201 (static_cast<void>(__VA_ARGS__)); \
203 m_f.type = ::rapid_cxx_test::failure_type::check; \
205 ::rapid_cxx_test::get_reporter().report(m_f); \
209 # define TEST_CHECK_THROW(Except, ...) \
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__ ")", "" \
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); \
224 #define TEST_CHECK_THROW_RESULT(Except, Checker, ...) \
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__ ")", \
233 (static_cast<void>(__VA_ARGS__)); \
234 m_f.type = ::rapid_cxx_test::failure_type::check; \
235 } catch (Except const& Caught) { \
238 ::rapid_cxx_test::get_reporter().report(m_f); \
242 #else // TEST_HAS_NO_EXCEPTIONS
244 # define TEST_CHECK_NO_THROW(...) \
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__ ")", "" \
251 (static_cast<void>(__VA_ARGS__)); \
252 ::rapid_cxx_test::get_reporter().report(m_f); \
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(...) \
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__ ")", "" \
275 (static_cast<void>(__VA_ARGS__)); \
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) { \
286 # define TEST_REQUIRE_THROW(Except, ...) \
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__ ")", "" \
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) { \
304 #else // TEST_HAS_NO_EXCEPTIONS
306 # define TEST_REQUIRE_NO_THROW(...) \
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__ ")", "" \
313 (static_cast<void>(__VA_ARGS__)); \
314 ::rapid_cxx_test::get_reporter().report(m_f); \
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(...) \
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__ ")", "" \
335 (static_cast<void>(__VA_ARGS__)); \
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) { \
346 # define TEST_ASSERT_THROW(Except, ...) \
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__ ")", "" \
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) { \
364 #else // TEST_HAS_NO_EXCEPTIONS
366 # define TEST_ASSERT_NO_THROW(...) \
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__ ")", "" \
373 (static_cast<void>(__VA_ARGS__)); \
374 ::rapid_cxx_test::get_reporter().report(m_f); \
378 #define TEST_ASSERT_THROW(Except, ...) ((void)0)
380 #endif // TEST_HAS_NO_EXCEPTIONS
382 ////////////////////////////////////////////////////////////////////////////////
384 ////////////////////////////////////////////////////////////////////////////////
386 # define TEST_WARN_EQUAL_COLLECTIONS(...) \
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__ ")", "" \
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); \
400 # define TEST_CHECK_EQUAL_COLLECTIONS(...) \
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__ ")", "" \
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); \
414 # define TEST_REQUIRE_EQUAL_COLLECTIONS(...) \
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__ ")", "" \
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) { \
431 # define TEST_ASSERT_EQUAL_COLLECTIONS(...) \
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__ ")", "" \
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) { \
448 namespace rapid_cxx_test
450 typedef void (*invoker_t
)();
452 ////////////////////////////////////////////////////////////////////////////
456 : file(""), func(""), line(0), invoke(NULL
)
459 test_case(const char* file1
, const char* func1
, std::size_t line1
,
461 : file(file1
), func(func1
), line(line1
), invoke(invoke1
)
470 ////////////////////////////////////////////////////////////////////////////
484 typedef failure_type::enum_type failure_type_t
;
486 ////////////////////////////////////////////////////////////////////////////
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
)
508 const char *expression
;
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
;
517 while ((last
= *f_start
) != '\0') {
519 if (last
== '/' && *f_start
) {
520 prev_start
= last_start
;
521 last_start
= f_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
, "::");
533 func
= namespace_loc
+ 2;
538 ////////////////////////////////////////////////////////////////////////////
548 inline checkpoint
& global_checkpoint()
550 static checkpoint cp
= {"", "", 0};
555 ////////////////////////////////////////////////////////////////////////////
556 inline void set_checkpoint(const char* file
, const char* func
, std::size_t line
)
558 checkpoint
& cp
= detail::global_checkpoint();
564 ////////////////////////////////////////////////////////////////////////////
565 inline checkpoint
const & get_checkpoint()
567 return detail::global_checkpoint();
570 ////////////////////////////////////////////////////////////////////////////
574 typedef test_case
const* iterator
;
575 typedef iterator const_iterator
;
578 test_suite(const char *xname
)
579 : m_name(xname
), m_tests(), m_size(0)
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
595 const_iterator
begin() const
598 const_iterator
end() const
600 return m_tests
+ m_size
;
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
;
613 test_suite(test_suite
const &);
614 test_suite
& operator=(test_suite
const &);
618 // Since fast compile times in a priority, we use simple containers
620 test_case m_tests
[256];
624 ////////////////////////////////////////////////////////////////////////////
628 registrar(test_suite
& st
, test_case tc
)
630 st
.register_test(tc
);
634 ////////////////////////////////////////////////////////////////////////////
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()
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"
663 // Each assertion and failure is reported through this function.
664 void report(test_outcome o
)
669 case failure_type::none
:
671 case failure_type::unsupported
:
675 case failure_type::warn
:
676 ++m_warning_failures
;
679 case failure_type::check
:
684 case failure_type::require
:
685 ++m_require_failures
;
689 case failure_type::assert:
692 case failure_type::uncaught_exception
:
693 ++m_uncaught_exceptions
;
695 , "Test case FAILED with uncaught exception:\n"
696 " last checkpoint near %s::%lu %s\n\n"
697 , o
.file
, o
.line
, o
.func
703 # if defined(__GNUC__)
704 # pragma GCC diagnostic pop
707 test_outcome
current_failure() const
714 m_failure
.type
= failure_type::none
;
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" : ""));
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
: ""
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
;
792 ////////////////////////////////////////////////////////////////////////////
796 test_runner(test_suite
& ts
)
804 for (test_suite::const_iterator b
= m_ts
.begin(), e
= m_ts
.end();
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
814 #ifndef TEST_HAS_NO_EXCEPTIONS
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
;
823 get_reporter().report(o
);
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());
835 test_runner(test_runner
const &);
836 test_runner
operator=(test_runner
const &);
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
) {
855 return (start1
== end1
&& start2
== end2
);
857 } // namespace detail
859 } // namespace rapid_cxx_test
862 # if defined(__GNUC__)
863 # pragma GCC diagnostic pop
866 #endif /* RAPID_CXX_TEST_H */