38 #ifndef VIGRA_UNIT_TEST_HPP 39 #define VIGRA_UNIT_TEST_HPP 51 #include "vigra/config.hxx" 52 #include "vigra/error.hxx" 54 #ifdef VIGRA_NO_WORKING_STRINGSTREAM 56 #define VIGRA_SSTREAM std::strstream 57 #define VIGRA_SSTREAM_STR(s) ((s << char()), std::string(s.str())) 60 #define VIGRA_SSTREAM std::basic_stringstream<char> 61 #define VIGRA_SSTREAM_STR(s) s.str() 84 #elif defined(__CYGWIN__) 86 #define VIGRA_CANT_CATCH_SIGNALS 88 #elif defined(__unix) || defined(unix) 92 #include <sys/signal.h> 97 #define VIGRA_CANT_CATCH_SIGNALS 101 #define VIGRA_TEST_CASE(function) vigra::create_test_case(function, #function "()") 103 #define testCase VIGRA_TEST_CASE 105 #define VIGRA_TEST_SUITE(testsuite) ( new testsuite ) 107 #define VIGRA_CHECKPOINT(message) \ 108 vigra::detail::checkpoint_impl(message, __FILE__, __LINE__) 110 #define VIGRA_ASSERT(predicate) \ 111 vigra::detail::should_impl((predicate), #predicate, __FILE__, __LINE__) 113 #define should VIGRA_ASSERT 115 #define VIGRA_ASSERT_MESSAGE(predicate, message) \ 116 vigra::detail::should_impl((predicate), message, __FILE__, __LINE__) 118 #define shouldMsg VIGRA_ASSERT_MESSAGE 120 #define shouldEqual(left, right) \ 121 vigra::detail::equal_impl(left, right, #left " == " #right, __FILE__, __LINE__) 123 #define shouldEqualMessage(left, right, message) \ 124 vigra::detail::equal_impl(left, right, message "\n" #left " == " #right, __FILE__, __LINE__) 126 #define shouldEqualTolerance(left, right, eps) \ 127 vigra::detail::tolerance_equal_impl(left, right, eps, #left " == " #right, __FILE__, __LINE__) 129 #define shouldEqualToleranceMessage(left, right, eps, message) \ 130 vigra::detail::tolerance_equal_impl(left, right, eps, message "\n" #left " == " #right, __FILE__, __LINE__) 132 #define shouldEqualSequence(begin1, end1, begin2) \ 133 vigra::detail::sequence_equal_impl(begin1, end1, begin2, __FILE__, __LINE__) 135 #define shouldEqualSequenceTolerance(begin1, end1, begin2, eps) \ 136 vigra::detail::sequence_equal_tolerance_impl(begin1, end1, begin2, eps, __FILE__, __LINE__) 138 #define VIGRA_ERROR(message) \ 139 vigra::detail::should_impl(false, message, __FILE__, __LINE__) 141 #define failTest VIGRA_ERROR 152 std::string str() {
return VIGRA_SSTREAM_STR(buf); }
154 errstream &
operator<<(T t) { buf << t;
return *
this; }
157 inline std::string & exception_checkpoint()
159 static std::string test_checkpoint_;
160 return test_checkpoint_;
164 inline void report_exception( detail::errstream & os,
165 const char * name,
const char * info )
167 os <<
"Unexpected " << name <<
" " << info <<
"\n";
168 if(exception_checkpoint().size() > 0)
170 os <<
"Last checkpoint: " << exception_checkpoint() <<
"\n";
175 unexpected_exception = -1,
177 memory_access_violation = -3,
178 destructor_failure = -4
181 inline bool critical_error(
int i)
182 {
return i <= memory_access_violation; }
184 inline bool unexpected_error(
int i)
187 #ifndef VIGRA_CANT_CATCH_SIGNALS 191 inline long handle_signal_here(
long code)
195 case EXCEPTION_ACCESS_VIOLATION:
196 case EXCEPTION_INT_DIVIDE_BY_ZERO:
197 return EXCEPTION_EXECUTE_HANDLER;
199 return EXCEPTION_CONTINUE_SEARCH;
203 template<
class Generator >
204 int catch_signals( Generator function_object, detail::errstream & err,
int timeout )
210 result = function_object();
212 __except (handle_signal_here(code = GetExceptionCode()))
216 case EXCEPTION_ACCESS_VIOLATION:
217 report_exception(err,
"operating system exception:",
"memory access violation");
218 result = memory_access_violation;
220 case EXCEPTION_INT_DIVIDE_BY_ZERO:
221 report_exception(err,
"operating system exception:",
"integer divide by zero");
222 result = os_exception;
225 report_exception(err,
"operating system exception:",
"unrecognized exception or signal");
226 result = os_exception;
234 #elif defined(__unix) 238 inline jmp_buf & unit_test_jump_buffer()
240 static jmp_buf unit_test_jump_buffer_;
241 return unit_test_jump_buffer_;
244 static void unit_test_signal_handler(
int sig)
246 longjmp(unit_test_jump_buffer(), sig);
251 template<
class Generator >
252 int catch_signals( Generator function_object, detail::errstream & err,
int timeout)
254 volatile int sigtype;
257 #if defined(linux) || defined(__linux) 258 signal(SIGFPE, &unit_test_signal_handler);
259 signal(SIGTRAP, &unit_test_signal_handler);
260 signal(SIGSEGV, &unit_test_signal_handler);
261 signal(SIGBUS, &unit_test_signal_handler);
263 sigset(SIGFPE, &unit_test_signal_handler);
264 sigset(SIGTRAP, &unit_test_signal_handler);
265 sigset(SIGSEGV, &unit_test_signal_handler);
266 sigset(SIGBUS, &unit_test_signal_handler);
271 #if defined(linux) || defined(__linux) 272 signal(SIGALRM, &unit_test_signal_handler);
274 sigset(SIGALRM, &unit_test_signal_handler);
279 sigtype = setjmp(unit_test_jump_buffer());
282 result = function_object();
289 report_exception(err,
"signal:",
"SIGALRM (timeout while executing function)");
290 result = os_exception;
293 report_exception(err,
"signal:",
"SIGTRAP (perhaps integer divide by zero)");
294 result = os_exception;
297 report_exception(err,
"signal:",
"SIGFPE (arithmetic exception)");
298 result = os_exception;
302 report_exception(err,
"signal:",
"memory access violation");
303 result = memory_access_violation;
306 report_exception(err,
"signal:",
"unrecognized signal");
307 result = os_exception;
314 #if defined(linux) || defined(__linux) 320 #if defined(linux) || defined(__linux) 335 template<
class Generator >
336 int catch_signals( Generator function_object, detail::errstream & err ,
int)
338 return function_object();
345 template<
class Generator >
346 int catch_exceptions( Generator function_object, detail::errstream & err,
int timeout )
348 int result = detail::unexpected_exception;
352 result = detail::catch_signals(function_object, err, timeout);
363 catch ( vigra::ContractViolation & ex )
364 { detail::report_exception( err,
"Contract exception: ", ex.what() ); }
365 catch (
const char * ex )
366 { detail::report_exception( err,
"string exception: ", ex ); }
367 catch (
const std::string & ex )
368 { detail::report_exception( err,
"string exception: ", ex.c_str() ); }
371 catch (
const std::bad_alloc & ex )
372 { detail::report_exception( err,
"exception: std::bad_alloc:", ex.what() ); }
374 # if !defined(__BORLANDC__) || __BORLANDC__ > 0x0551 375 catch (
const std::bad_cast & ex )
376 { detail::report_exception( err,
"exception: std::bad_cast:", ex.what() ); }
377 catch (
const std::bad_typeid & ex )
378 { detail::report_exception( err,
"exception: std::bad_typeid:", ex.what() ); }
380 catch (
const std::bad_cast & ex )
381 { detail::report_exception( err,
"exception: std::bad_cast",
"" ); }
382 catch (
const std::bad_typeid & ex )
383 { detail::report_exception( err,
"exception: std::bad_typeid",
"" ); }
386 catch (
const std::bad_exception & ex )
387 { detail::report_exception( err,
"exception: std::bad_exception:", ex.what() ); }
388 catch (
const std::domain_error & ex )
389 { detail::report_exception( err,
"exception: std::domain_error:", ex.what() ); }
390 catch (
const std::invalid_argument & ex )
391 { detail::report_exception( err,
"exception: std::invalid_argument:", ex.what() ); }
392 catch (
const std::length_error & ex )
393 { detail::report_exception( err,
"exception: std::length_error:", ex.what() ); }
394 catch (
const std::out_of_range & ex )
395 { detail::report_exception( err,
"exception: std::out_of_range:", ex.what() ); }
396 catch (
const std::range_error & ex )
397 { detail::report_exception( err,
"exception: std::range_error:", ex.what() ); }
398 catch (
const std::overflow_error & ex )
399 { detail::report_exception( err,
"exception: std::overflow_error:", ex.what() ); }
400 catch (
const std::underflow_error & ex )
401 { detail::report_exception( err,
"exception: std::underflow_error:", ex.what() ); }
402 catch (
const std::logic_error & ex )
403 { detail::report_exception( err,
"exception: std::logic_error:", ex.what() ); }
404 catch (
const std::runtime_error & ex )
405 { detail::report_exception( err,
"exception: std::runtime_error:", ex.what() ); }
406 catch (
const std::exception & ex )
407 { detail::report_exception( err,
"exception: std::exception:", ex.what() ); }
411 detail::report_exception( err,
"unknown exception",
"" );
418 template<
class Generator >
420 int catch_exceptions( Generator function_object, detail::errstream & err)
422 return catch_exceptions(function_object, err, 0);
427 struct unit_test_failed
428 :
public std::exception
430 unit_test_failed(std::string
const & message)
434 virtual ~unit_test_failed() throw()
438 virtual const char * what()
const throw()
440 return what_.c_str();
447 checkpoint_impl(
const char * message,
const char * file,
int line)
449 detail::errstream buf;
450 buf << message <<
" (" << file <<
":" << line <<
")";
451 exception_checkpoint() = buf.str();
455 should_impl(
bool predicate,
const char * message,
const char * file,
int line)
457 checkpoint_impl(message, file, line);
460 detail::errstream buf;
461 buf << message <<
" (" << file <<
":" << line <<
")";
462 throw unit_test_failed(buf.str());
466 template <
class Iter1,
class Iter2>
468 sequence_equal_impl(Iter1 i1, Iter1 end1, Iter2 i2,
const char * file,
int line)
470 for(
int counter = 0; i1 != end1; ++i1, ++i2, ++counter)
474 detail::errstream buf;
475 buf <<
"Sequence items differ at index " << counter <<
476 " ["<< *i1 <<
" != " << *i2 <<
"]";
477 should_impl(
false, buf.str().c_str(), file, line);
486 struct ScalarType {};
487 struct VectorType {};
492 typedef VectorType ScalarOrVector;
496 struct FloatTraits<float>
498 typedef ScalarType ScalarOrVector;
499 static float epsilon() {
return FLT_EPSILON; }
500 static float smallestPositive() {
return FLT_MIN; }
501 static float min() {
return -FLT_MAX; }
502 static float max() {
return FLT_MAX; }
506 struct FloatTraits<double>
508 typedef ScalarType ScalarOrVector;
509 static double epsilon() {
return DBL_EPSILON; }
510 static double smallestPositive() {
return DBL_MIN; }
511 static double min() {
return -DBL_MAX; }
512 static double max() {
return DBL_MAX; }
516 struct FloatTraits<long double>
518 typedef ScalarType ScalarOrVector;
519 static long double epsilon() {
return LDBL_EPSILON; }
520 static long double smallestPositive() {
return LDBL_MIN; }
521 static long double min() {
return -LDBL_MAX; }
522 static long double max() {
return LDBL_MAX; }
527 FPT fpt_abs( FPT
arg )
529 return arg < 0 ? -arg :
arg;
538 FPT safe_fpt_division( FPT f1, FPT f2 )
550 return ((f2 < 1) && (f1 > (f2 * FloatTraits<FPT>::max()))) ?
551 FloatTraits<FPT>::max() :
552 ((((f2 > 1) && (f1 < (f2 * FloatTraits<FPT>::smallestPositive())))
553 || (f1 == 0)) ? 0 : f1/f2 );
562 class close_at_tolerance {
564 explicit close_at_tolerance( FPT tolerance,
bool strong_test =
true )
565 : m_strong_test( strong_test ),
566 m_tolerance( tolerance ) {}
568 explicit close_at_tolerance(
int number_of_rounding_errors,
bool strong_test =
true )
569 : m_strong_test( strong_test ),
570 m_tolerance( FloatTraits<FPT>::epsilon() * number_of_rounding_errors / 2.0 ) {}
572 bool operator()( FPT left, FPT right )
const 574 if (left == 0 && right != 0)
576 return (fpt_abs(right) <= m_tolerance);
578 if (right == 0 && left != 0)
580 return (fpt_abs(left) <= m_tolerance);
582 FPT diff = fpt_abs( left - right );
583 FPT d1 = safe_fpt_division( diff, fpt_abs( right ) );
584 FPT d2 = safe_fpt_division( diff, fpt_abs( left ) );
586 return m_strong_test ? (d1 <= m_tolerance && d2 <= m_tolerance)
587 : (d1 <= m_tolerance || d2 <= m_tolerance);
597 template <
class T1,
class T2,
class T3>
599 tolerance_equal_impl(T1 left, T2 right, T3 epsilon,
600 const char * message,
const char * file,
int line, ScalarType)
602 detail::errstream buf;
603 buf << message <<
" [" << left <<
" != " << right <<
"]";
605 close_at_tolerance<T3> fcomparator( epsilon );
606 bool compare = fcomparator ( (T3)left , (T3)right );
607 should_impl(compare, buf.str().c_str(), file, line);
611 template <
class T1,
class T2,
class T3>
613 tolerance_equal_impl(T1 left, T2 right, T3 epsilon,
614 const char * message,
const char * file,
int line, VectorType)
616 detail::errstream buf;
617 buf << message <<
" [" << left <<
" != " << right <<
"]";
620 for(
unsigned int i=0; i<epsilon.size(); ++i)
622 close_at_tolerance<typename T3::value_type> fcomparator( epsilon[i] );
623 compare = compare && fcomparator ( left[i] , right[i] );
625 should_impl(compare, buf.str().c_str(), file, line);
628 template <
class T1,
class T2,
class T3>
630 tolerance_equal_impl(T1 left, T2 right, T3 epsilon,
const char * message,
const char * file,
int line)
632 tolerance_equal_impl(left, right, epsilon,
633 message, file, line,
typename FloatTraits<T3>::ScalarOrVector());
636 template <
class Iter1,
class Iter2,
class T>
638 sequence_equal_tolerance_impl(Iter1 i1, Iter1 end1, Iter2 i2, T epsilon,
const char * file,
int line)
640 for(
int counter = 0; i1 != end1; ++i1, ++i2, ++counter)
642 detail::errstream buf;
643 buf <<
"Sequence items differ at index " << counter;
644 tolerance_equal_impl(*i1, *i2, epsilon, buf.str().c_str(), file, line,
typename FloatTraits<T>::ScalarOrVector());
648 template <
class Left,
class Right>
650 equal_impl(Left left, Right right,
const char * message,
const char * file,
int line)
652 detail::errstream buf;
653 buf << message <<
" [" << left <<
" != " << right <<
"]";
654 should_impl(left == right, buf.str().c_str(), file, line);
657 template <
class Left,
class Right>
659 equal_impl(Left * left, Right * right,
const char * message,
const char * file,
int line)
661 detail::errstream buf;
662 buf << message <<
" [" << (
void*)left <<
" != " << (
void*)right << "]";
663 should_impl(left == right, buf.str().c_str(), file, line);
667 equal_impl(
double left,
double right, const
char * message, const
char * file,
int line)
669 tolerance_equal_impl(left, right, 1.0e-16, message, file, line);
673 equal_impl(
float left,
float right,
const char * message,
const char * file,
int line)
675 tolerance_equal_impl(left, right, 1.0e-6f, message, file, line);
679 equal_impl(
float left,
double right,
const char * message,
const char * file,
int line)
681 tolerance_equal_impl(left, right, 1.0e-6f, message, file, line);
685 equal_impl(
double left,
float right,
const char * message,
const char * file,
int line)
687 tolerance_equal_impl(left, right, 1.0e-6f, message, file, line);
694 test_case(
char const * name =
"Unnamed")
695 : name_(name), timeout(0)
698 virtual ~test_case() {}
700 virtual int run() {
return run(std::vector<std::string>()); }
701 virtual int run(std::vector<std::string>
const & testsToBeRun) = 0;
702 virtual void do_init() {}
703 virtual void do_run() {}
704 virtual void do_destroy() {}
706 virtual char const * name() {
return name_.c_str(); }
707 virtual int size()
const {
return 1; }
709 virtual int numberOfTestsToRun(std::vector<std::string>
const & testsToBeRun)
const 711 if(testsToBeRun.empty())
713 for(
unsigned int k=0; k<testsToBeRun.size(); ++k)
714 if(this->name_.find(testsToBeRun[k]) != std::string::npos)
727 std::vector<std::string> testsToBeExecuted(
int argc,
char ** argv)
729 std::vector<std::string> res;
730 for(
int i=1; i < argc; ++i)
731 res.push_back(std::string(argv[i]));
736 :
public detail::test_case
739 using detail::test_case::run;
741 test_suite(
char const * name =
"TopLevel")
742 : detail::test_case(name),
746 virtual ~test_suite()
748 for(
unsigned int i=0; i != testcases_.size(); ++i)
749 delete testcases_[i];
752 virtual void add(detail::test_case * t,
int timeout = 0)
754 t->timeout = timeout;
755 testcases_.push_back(t);
759 virtual int run(std::vector<std::string>
const & testsToBeRun)
761 int size = numberOfTestsToRun(testsToBeRun);
763 std::vector<std::string> testsToBeRunRecursive =
766 : std::vector<std::string>();
769 report_ = std::string(
"Entering test suite ") + name() +
"\n";
771 for(
unsigned int i=0; i != testcases_.size(); ++i)
773 int result = testcases_[i]->run(testsToBeRunRecursive);
774 report_ += testcases_[i]->report_;
776 if(detail::critical_error(result))
778 report_ += std::string(
"\nFatal error - aborting test suite ") + name() +
".\n";
781 else if(detail::unexpected_error(result))
789 detail::errstream buf;
790 buf <<
"\n" << failed <<
" of " << size <<
791 " tests failed in test suite " << name() <<
"\n";
792 report_ += buf.str();
796 detail::errstream buf;
797 buf <<
"All (" << size <<
798 ") tests passed in test suite " << name() <<
"\n";
799 report_ += buf.str();
802 report_ += std::string(
"Leaving test suite ") + name() +
"\n";
807 virtual int numberOfTestsToRun(std::vector<std::string>
const & testsToBeRun)
const 809 if(detail::test_case::numberOfTestsToRun(testsToBeRun) > 0)
812 for(
unsigned int i=0; i != testcases_.size(); ++i)
813 size += testcases_[i]->numberOfTestsToRun(testsToBeRun);
817 virtual int size()
const {
return size_; }
818 virtual std::string report() {
return report_; }
820 std::vector<detail::test_case *> testcases_;
826 struct test_case_init_functor
828 detail::errstream & buf_;
829 test_case * test_case_;
831 test_case_init_functor(detail::errstream & b, test_case * tc)
832 : buf_(b), test_case_(tc)
839 test_case_->do_init();
842 catch(unit_test_failed & e)
844 buf_ <<
"Assertion failed: " << e.what() <<
"\n";
850 struct test_case_run_functor
852 detail::errstream & buf_;
853 test_case * test_case_;
855 test_case_run_functor(detail::errstream & b, test_case * tc)
856 : buf_(b), test_case_(tc)
863 test_case_->do_run();
866 catch(unit_test_failed & e)
868 buf_ <<
"Assertion failed: " << e.what() <<
"\n";
874 struct test_case_destroy_functor
876 detail::errstream & buf_;
877 test_case * test_case_;
879 test_case_destroy_functor(detail::errstream & b, test_case * tc)
880 : buf_(b), test_case_(tc)
887 test_case_->do_destroy();
890 catch(unit_test_failed & e)
892 buf_ <<
"Assertion failed: " << e.what() <<
"\n";
898 template <
class TESTCASE>
899 class class_test_case
903 using test_case::run;
905 class_test_case(
void (TESTCASE::*fct)(),
char const * name)
911 virtual ~class_test_case()
916 virtual void do_init()
918 testcase_ =
new TESTCASE;
923 exception_checkpoint() =
"";
927 detail::errstream buf;
928 buf <<
"\nFailure in initialization of " << name() <<
"\n";
931 buf <<
"Test case failed to clean up after previous run.\n";
936 failed = catch_exceptions(
937 detail::test_case_init_functor(buf,
this), buf, timeout);
942 report_ += buf.str();
948 virtual void do_run()
951 (testcase_->*fct_)();
954 virtual int run(std::vector<std::string>
const & testsToBeRun)
956 if(numberOfTestsToRun(testsToBeRun) == 0)
964 detail::errstream buf;
965 buf <<
"\nFailure in " << name() <<
"\n";
967 failed = catch_exceptions(
968 detail::test_case_run_functor(buf,
this), buf, timeout);
970 report_ += buf.str();
972 if(critical_error(failed))
975 int destruction_failed = destroy();
977 return destruction_failed ?
982 virtual void do_destroy()
990 detail::errstream buf;
991 buf <<
"\nFailure in destruction of " <<
"\n";
993 int failed = catch_exceptions(
994 detail::test_case_destroy_functor(buf,
this), buf, timeout);
997 report_ += buf.str();
998 return destructor_failure;
1006 void (TESTCASE::*fct_)();
1007 TESTCASE * testcase_;
1010 class function_test_case
1014 using test_case::run;
1016 function_test_case(
void (*fct)(),
char const * name)
1021 virtual void do_run()
1026 virtual int run(std::vector<std::string>
const & testsToBeRun)
1028 if(numberOfTestsToRun(testsToBeRun) == 0)
1032 exception_checkpoint() =
"";
1034 detail::errstream buf;
1035 buf <<
"\nFailure in " << name() <<
"\n";
1037 int failed = catch_exceptions(
1038 detail::test_case_run_functor(buf,
this), buf, timeout);
1041 report_ += buf.str();
1050 template <
class FCT>
1053 virtual ~test_functor() {}
1054 virtual void operator()() = 0;
1057 {
return FCT(static_cast<FCT const &>(*
this)); }
1060 template <
class FCT>
1061 class functor_test_case
1065 using test_case::run;
1067 functor_test_case(FCT
const & fct,
char const * name)
1072 virtual void do_run()
1077 virtual int run(std::vector<std::string>
const & testsToBeRun)
1079 if(numberOfTestsToRun(testsToBeRun) == 0)
1083 exception_checkpoint() =
"";
1085 detail::errstream buf;
1086 buf <<
"\nFailure in " << name() <<
"\n";
1088 int failed = catch_exceptions(
1089 detail::test_case_run_functor(buf,
this), buf, timeout);
1092 report_ += buf.str();
1103 template <
class TESTCASE>
1106 create_test_case(
void (TESTCASE::*fct)(),
char const * name)
1108 if(*name ==
'&') ++name;
1109 return new detail::class_test_case<TESTCASE>(fct, name);
1114 create_test_case(
void (*fct)(),
char const * name)
1116 if(*name ==
'&') ++name;
1117 return new detail::function_test_case(fct, name);
1120 template <
class FCT>
1123 create_test_case(detail::test_functor<FCT>
const & fct,
char const * name)
1125 if(*name ==
'&') ++name;
1126 return new detail::functor_test_case<FCT>(fct.clone(), name);
1132 #if !defined(__GNUC__) || __GNUC__ >= 3 1136 template <
class E,
class T,
class V>
1138 std::basic_ostream<E,T> & operator,(std::basic_ostream<E,T> & o, V
const & t)
1140 return (o <<
' ' << t);
1143 template <
class E,
class T>
1145 std::basic_ostream<E,T> & operator,(std::basic_ostream<E,T> & o,
1146 std::basic_ostream<E,T> & (*t)(std::basic_ostream<E,T> &))
1155 std::ostream & operator,(std::ostream & o, V
const & t)
1157 return (o <<
' ' << t);
1161 std::ostream & operator,(std::ostream & o,
1162 std::ostream & (*t)(std::ostream &))
R arg(const FFTWComplex< R > &a)
pahse
Definition: fftw3.hxx:1009
void add(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r, FixedPoint< IntBits3, FracBits3 > &result)
addition with enforced result type.
Definition: fixedpoint.hxx:561
Definition: accessor.hxx:43
ostream & operator<<(ostream &s, const vigra::MultiArrayView< 2, T, C > &m)
Definition: matrix.hxx:2322