# HG changeset patch # User Balazs Dezso # Date 1206459404 -3600 # Node ID 889d0c289d19d3b4b50387d6ff9b6e5d3bc803aa # Parent 31a2e6d28f61ca3a3011726dcd6fc0668e5f6f9b Reworking assertions and moving to distinict file diff -r 31a2e6d28f61 -r 889d0c289d19 lemon/Makefile.am --- a/lemon/Makefile.am Fri Mar 21 22:25:40 2008 +0000 +++ b/lemon/Makefile.am Tue Mar 25 16:36:44 2008 +0100 @@ -17,6 +17,7 @@ lemon_HEADERS += \ lemon/arg_parser.h \ + lemon/assert.h \ lemon/bfs.h \ lemon/bin_heap.h \ lemon/dfs.h \ diff -r 31a2e6d28f61 -r 889d0c289d19 lemon/arg_parser.h --- a/lemon/arg_parser.h Fri Mar 21 22:25:40 2008 +0000 +++ b/lemon/arg_parser.h Tue Mar 25 16:36:44 2008 +0100 @@ -26,7 +26,7 @@ #include #include #include -#include +#include ///\ingroup misc ///\file diff -r 31a2e6d28f61 -r 889d0c289d19 lemon/assert.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/assert.h Tue Mar 25 16:36:44 2008 +0100 @@ -0,0 +1,364 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_ASSERT_H +#define LEMON_ASSERT_H + +/// \ingroup exceptions +/// \file +/// \brief Extended assertion handling + +#include + +namespace lemon { + + /// @{ + + ///\e + class AssertionFailedError : public LogicError { + protected: + const char *_assertion; + const char *_file; + int _line; + const char *_function; + const char *_message; + + mutable ExceptionMember _message_holder; + public: + ///\e + AssertionFailedError(const char *file, int line, const char *function, + const char *msg, const char *assertion = 0) : + _assertion(assertion), _file(file), _line(line), + _function(function), _message(msg) {} + + ///\e + const char* assertion() const { return _assertion; } + ///\e + const char* message() const { return _message; } + ///\e + const char* file() const { return _file; } + ///\e + const char* function() const { return _function; } + ///\e + int line() const { return _line; } + + + virtual const char* what() const throw() { + try { + std::ostringstream ostr; + ostr << _file << ":" << _line << ": "; + if (_function) + ostr << _function << ": "; + ostr << _message; + if (_assertion) + ostr << " (assertion '" << _assertion << "' failed)"; + _message_holder.set(ostr.str()); + return ostr.str().c_str(); + } + catch(...) {} + if( _message_holder.valid() ) return _message_holder.get().c_str(); + return "lemon::AssertionFailedError"; + } + virtual ~AssertionFailedError() throw() {} + }; + + + inline void assert_fail_log(const char *file, int line, + const char *function, + const std::exception& exception, + const char *assertion) + { + std::cerr << file << ":" << line << ": "; + if (function) + std::cerr << function << ": "; + std::cerr << exception.what(); + if (assertion) + std::cerr << " (assertion '" << assertion << "' failed)"; + std::cerr << std::endl; + } + + inline void assert_fail_log(const char *file, int line, const char *function, + const char *message, const char *assertion) + { + std::cerr << file << ":" << line << ": "; + if (function) + std::cerr << function << ": "; + std::cerr << message; + if (assertion) + std::cerr << " (assertion '" << assertion << "' failed)"; + std::cerr << std::endl; + } + + inline void assert_fail_log(const char *file, int line, const char *function, + const std::string& message, const char *assertion) + { + assert_fail_log(file, line, function, message.c_str(), assertion); + } + + inline void assert_fail_abort(const char *file, int line, + const char *function, + const std::exception& exception, + const char *assertion) + { + std::cerr << file << ":" << line << ": "; + if (function) + std::cerr << function << ": "; + std::cerr << exception.what(); + if (assertion) + std::cerr << " (assertion '" << assertion << "' failed)"; + std::cerr << std::endl; + std::abort(); + } + + inline void assert_fail_abort(const char *file, int line, + const char *function, const char* message, + const char *assertion) + { + std::cerr << file << ":" << line << ": "; + if (function) + std::cerr << function << ": "; + std::cerr << message; + if (assertion) + std::cerr << " (assertion '" << assertion << "' failed)"; + std::cerr << std::endl; + std::abort(); + } + + inline void assert_fail_abort(const char *file, int line, + const char *function, + const std::string& message, + const char *assertion) + { + assert_fail_abort(file, line, function, message.c_str(), assertion); + } + + inline void assert_fail_error(const char *file, int line, + const char *function, + const std::exception& exception, + const char *assertion) + { + throw AssertionFailedError(file, line, function, + exception.what(), assertion); + } + + inline void assert_fail_error(const char *file, int line, + const char *function, const char *message, + const char *assertion) + { + throw AssertionFailedError(file, line, function, message, assertion); + } + + inline void assert_fail_error(const char *file, int line, + const char *function, + const std::string& message, + const char *assertion) + { + assert_fail_error(file, line, function, message.c_str(), assertion); + } + + template + inline void assert_fail_exception(const char *, int, const char *, + const Exception& exception, + const char *, const std::exception* = + static_cast(0)) + { + throw exception; + } + + inline void assert_fail_exception(const char *file, int line, + const char *function, const char *message, + const char *assertion) + { + throw AssertionFailedError(file, line, function, message, assertion); + } + + inline void assert_fail_exception(const char *file, int line, + const char *function, + const std::string& message, + const char *assertion) + { + assert_fail_exception(file, line, function, message.c_str(), assertion); + } + +/// @} + +} +#endif // LEMON_ASSERT_H + +#undef LEMON_ASSERT +#undef LEMON_FIXME + +#if (defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ + (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ + (defined(LEMON_ASSERT_ERROR) ? 1 : 0) + \ + (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) + \ + (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1 +#error "Lemon assertion system is not set properly" +#endif + +#if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ + (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ + (defined(LEMON_ASSERT_ERROR) ? 1 : 0) + \ + (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) + \ + (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \ + defined(LEMON_ENABLE_ASSERT)) && \ + defined(LEMON_DISABLE_ASSERTS) +#error "Lemon assertion system is not set properly" +#endif + + +#if defined LEMON_ASSERT_LOG +# undef LEMON_ASSERT_HANDLER +# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log +#elif defined LEMON_ASSERT_ABORT +# undef LEMON_ASSERT_HANDLER +# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort +#elif defined LEMON_ASSERT_ERROR +# undef LEMON_ASSERT_HANDLER +# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error +#elif defined LEMON_ASSERT_EXCEPTION +# undef LEMON_ASSERT_HANDLER +# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception +#elif defined LEMON_ASSERT_CUSTOM +# undef LEMON_ASSERT_HANDLER +# ifndef LEMON_CUSTOM_ASSERT_HANDLER +# error "LEMON_CUSTOM_ASSERT_HANDLER is not set" +# endif +# define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER +#elif defined LEMON_ENABLE_ASSERTS +# undef LEMON_ASSERT_HANDLER +# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort +#else +# undef LEMON_ASSERT_HANDLER +#endif + + +#ifndef LEMON_FUNCTION_NAME +# define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__) +#endif + +#ifdef DOXYGEN + +/// \ingroup exceptions +/// +/// \brief Macro for assertions with customizable message +/// +/// Macro for assertions with customizable message. +/// \param exp An expression convertible to bool. If the expression is +/// false, then an assertion is raised. The concrete behaviour depends +/// on the settings of the assertion system. +/// \param msg A \e const \e char*, a \e const std::string& or a \e +/// const \e std::exception& parameter. The variable can be used to +/// provide information about the circumstances of failed assertion. +/// +/// The assertions are disabled in the default behaviour. You can +/// enable the assertions with the following code: +/// \code +/// #define LEMON_ENABLE_ASSERTS +/// \endcode +/// or with compilation parameters: +/// \code +/// g++ -DLEMON_ENABLE_ASSERTS +/// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS' +/// \endcode +/// +/// The %lemon assertion system has a wide range of customization +/// properties. As default behaviour the failed assertion prints a +/// short log message to the standard ouput and aborts the execution. +/// +/// The following modes can be used in the assertion system: +/// +/// - \e LEMON_ASSERT_LOG The failed assert print a short convenient +/// error message to the standard error and continues the +/// execution. +/// - \e LEMON_ASSERT_ABORT This mode is similar to the \e +/// LEMON_ASSERT_LOG, but it aborts the program. It is the default +/// operation mode when the asserts are enabled with \e +/// LEMON_ENABLE_ASSERTS. +/// - \e LEMON_ASSERT_ERROR The assert throws an \ref +/// lemon::AssertionFailedError "AssertionFailedError". If the \c +/// msg parameter is an exception, then the result of the \ref +/// lemon::Exception::what() "what()" member function is passed as +/// error message. +/// - \e LEMON_ASSERT_EXCEPTION If the specified \c msg is an +/// exception then it raised directly (solving that the exception +/// can not be thrown polymorphically), otherwise an \ref +/// lemon::AssertionFailedError "AssertionFailedError" is thrown with +/// the given parameter. +/// - \e LEMON_ASSERT_CUSTOM The user can define an own assertion +/// handler functions. Three overloaded functions should be defined +/// with the following parameter lists: +/// \code +/// void custom_assert_handler(const char* file, int line, +/// const char* function, const char* message, const char* expression); +/// void custom_assert_handler(const char* file, int line, +/// const char* function, const std::string& message, const char* expression); +/// void custom_assert_handler(const char* file, int line, +/// const char* function, const std::exception& message, const char* expression); +/// \endcode +/// The name of the functions should be defined as the \c +/// LEMON_CUSTOM_ASSERT_HANDLER macro name. +/// \code +/// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler +/// \endcode +/// Whenever an assertion is occured, one of the custom assertion +/// handler is called with appropiate parameters. +/// +/// The assertion mode can be changed within one compilation unit, if +/// the macros are redefined with other settings and the +/// lemon/assert.h file is reincluded then the behaviour is changed +/// appropiately to the new settings. +# define LEMON_ASSERT(exp, msg) \ + (static_cast (!!(exp) ? 0 : ( \ + LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ + LEMON_FUNCTION_NAME, \ + msg, #exp), 0))) + + +/// \ingroup exceptions +/// +/// \brief Macro for mark not yet implemented features. +/// +/// Macro for mark not yet implemented features and outstanding bugs. +/// It is close to be the shortcut of the following code: +/// \code +/// LEMON_ASSERT(false, msg); +/// \endcode +# define LEMON_FIXME(msg) \ + (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ + "FIXME: " msg, static_cast(0))) + +#else + +# ifndef LEMON_ASSERT_HANDLER +# define LEMON_ASSERT(exp, msg) (static_cast (0)) +# define LEMON_FIXME(msg) (static_cast(0)) +# else +# define LEMON_ASSERT(exp, msg) \ + (static_cast (!!(exp) ? 0 : ( \ + LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ + LEMON_FUNCTION_NAME, \ + msg, #exp), 0))) +# define LEMON_FIXME(msg) \ + (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ + "FIXME: " msg, static_cast(0))) +# endif + +#endif + + diff -r 31a2e6d28f61 -r 889d0c289d19 lemon/error.h --- a/lemon/error.h Fri Mar 21 22:25:40 2008 +0000 +++ b/lemon/error.h Tue Mar 25 16:36:44 2008 +0100 @@ -93,7 +93,7 @@ std::auto_ptr<_Type> ptr; }; - /// Exception-safe convenient "error message" class. + /// Exception-safe convenient error message builder class. /// Helper class which provides a convenient ostream-like (operator << /// based) interface to create a string message. Mostly useful in @@ -413,263 +413,8 @@ virtual ~IoParameterError() throw() {} }; - - ///\e - class AssertionFailedError : public LogicError { - protected: - const char *assertion; - const char *file; - int line; - const char *function; - const char *message; - - mutable ExceptionMember _message_holder; - public: - ///\e - AssertionFailedError(const char *_file, int _line, const char *func, - const char *msg, const char *_assertion = 0) : - assertion(_assertion), file(_file), line(_line), function(func), - message(msg) {} - - ///\e - const char* get_assertion() const { return assertion; } - ///\e - const char* get_message() const { return message; } - ///\e - const char* get_file() const { return file; } - ///\e - const char* get_function() const { return function; } - ///\e - int get_line() const { return line; } - - - virtual const char* what() const throw() { - try { - std::ostringstream ostr; - ostr << file << ":" << line << ": "; - if( function ) - ostr << function << ": "; - ostr << message; - if( assertion ) - ostr << " (assertion '" << assertion << "' failed)"; - _message_holder.set(ostr.str()); - return ostr.str().c_str(); - } - catch(...) {} - if( _message_holder.valid() ) return _message_holder.get().c_str(); - return "lemon::AssertionFailedError"; - } - virtual ~AssertionFailedError() throw() {} - }; - - - /**************** Macros ****************/ - - - template - inline void assert_fail(const char *file, int line, - const char *func, - Exception exception, - const char *assertion = 0, - bool do_abort=true) - { - using namespace std; - cerr << file << ":" << line << ": "; - if (func) - cerr << func << ": "; - cerr << exception.what(); - if (assertion) - cerr << " (assertion '" << assertion << "' failed)"; - cerr << endl; - if (do_abort) - abort(); - } - - template <> - inline void assert_fail(const char *file, int line, - const char *func, - const char *message, - const char *assertion, - bool do_abort) - { - using namespace std; - cerr << file << ":" << line << ": "; - if (func) - cerr << func << ": "; - cerr << message; - if (assertion) - cerr << " (assertion '" << assertion << "' failed)"; - cerr << endl; - if (do_abort) - abort(); - } - - template <> - inline void assert_fail(const char *file, int line, - const char *func, - std::string message, - const char *assertion, - bool do_abort) - { - assert_fail(file, line, func, message.c_str(), assertion, do_abort); - } - - template - inline void assert_fail_failure(const char *file, int line, const char *func, - Exception exception, - const char *assertion = 0, - bool = true) - { - throw AssertionFailedError(file, line, func, exception.what(), assertion); - } - - template <> - inline void assert_fail_failure(const char *file, int line, - const char *func, - const char *message, - const char *assertion, - bool) - { - throw AssertionFailedError(file, line, func, message, assertion); - } - - template <> - inline void assert_fail_failure(const char *file, int line, - const char *func, - std::string message, - const char *assertion, - bool) - { - assert_fail_failure(file, line, func, message.c_str(), assertion, true); - } - - template - inline void assert_fail_exception(const char *file, int line, const char *func, - Exception exception, - const char *assertion = 0, bool = true) - { - throw exception; - } - - template <> - inline void assert_fail_exception(const char *file, int line, - const char *func, - const char *message, - const char *assertion, - bool) - { - throw AssertionFailedError(file, line, func, message, assertion); - } - - template <> - inline void assert_fail_exception(const char *file, int line, - const char *func, - std::string message, - const char *assertion, - bool) - { - assert_fail_exception(file, line, func, message.c_str(), assertion, true); - } - -/// @} + /// @} } + #endif // LEMON_ERROR_H - -#undef LEMON_ASSERT -#undef LEMON_FIXME - -#ifdef LEMON_ENABLE_ASSERTS -# define LEMON_ASSERT_ABORT -#endif - -#ifndef LEMON_ASSERT_DO_ABORT -# define LEMON_ASSERT_DO_ABORT 1 -#endif - -#ifndef LEMON_ASSERT_HANDLER -# if defined LEMON_ASSERT_EXCEPTION -# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception -# elif defined LEMON_ASSERT_FAILURE -# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure -# elif defined LEMON_ASSERT_ABORT -# define LEMON_ASSERT_HANDLER ::lemon::assert_fail -# else -# define LEMON_DISABLE_ASSERTS -# endif -#endif - -#ifdef DOXYGEN - -/// \brief Macro for assertions with customizable message -/// -/// Macro for assertions with customizable message. -/// -/// The assertions are disabled in the default behaviour. You can -/// enable the assertions with the -/// \code -/// #define LEMON_ENABLE_ASSERTS -/// \endcode -/// Then an assert -/// provides a log on the standard error about the assertion and aborts -/// the program if LEMON_ASSERT_DO_ABORT is also defined (otherwise the -/// program keeps on running). -/// By defining LEMON_ASSERT_FAILURE or -/// LEMON_ASSERT_EXCEPTION, you can set other behaviour to the -/// assertions. In case LEMON_ASSERT_FAILURE is given, LEMON_ASSERT -/// will always throw an \c AssertionFailedError exception with -/// the \c msg error message. By using -/// LEMON_ASSERT_EXCEPTION, one can define an arbitrary exception to be thrown. -/// -/// The LEMON_ASSERT macro should be called with the \c exp parameter -/// which should be an expression convertible to bool. If the given -/// parameter is false the assertion is raised and one of the assertion -/// behaviour will be activated. The \c msg should be either a const -/// char* message or an exception. When the \c msg is an exception the -/// \ref lemon::Exception::what() "what()" function is called to retrieve and -/// display the error message. -/// -/// \todo We should provide some way to reset to the default behaviour, -/// shouldn't we? -/// -/// \todo This whole 'assert' business should be placed in a separate -/// include file. The boost assert is not guarded by header sentries -/// which may help to change the behaviour of the assertions in -/// the files. -/// -/// \todo __PRETTY_FUNCTION__ should be replaced by something -/// compiler-independent, like BOOST_CURRENT_FUNCTION - -# define LEMON_ASSERT(exp, msg) \ - (static_cast (!!(exp) ? 0 : ( \ - LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ - __PRETTY_FUNCTION__, \ - msg, #exp, LEMON_ASSERT_DO_ABORT), 0))) - -#else -# if defined LEMON_DISABLE_ASSERTS - -# define LEMON_ASSERT(exp, msg) (static_cast (0)) - -# else -# define LEMON_ASSERT(exp, msg) \ - (static_cast (!!(exp) ? 0 : ( \ - LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ - __PRETTY_FUNCTION__, \ - msg, #exp, LEMON_ASSERT_DO_ABORT), 0))) -# endif -#endif - -/** - * \brief Macro for mark not yet implemented features. - * - * \todo Is this the right place for this? It should be used only in - * modules under development. - * - * \todo __PRETTY_FUNCTION__ should be replaced by something - * compiler-independent, like BOOST_CURRENT_FUNCTION - */ - -#define LEMON_FIXME(msg) \ - (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \ - "FIXME: " msg)) diff -r 31a2e6d28f61 -r 889d0c289d19 test/Makefile.am --- a/test/Makefile.am Fri Mar 21 22:25:40 2008 +0000 +++ b/test/Makefile.am Tue Mar 25 16:36:44 2008 +0100 @@ -12,6 +12,7 @@ test/dfs_test \ test/digraph_test \ test/dim_test \ + test/error_test \ test/graph_test \ test/kruskal_test \ test/maps_test \ @@ -28,7 +29,7 @@ test_dfs_test_SOURCES = test/dfs_test.cc test_digraph_test_SOURCES = test/digraph_test.cc test_dim_test_SOURCES = test/dim_test.cc -#test_error_test_SOURCES = test/error_test.cc +test_error_test_SOURCES = test/error_test.cc test_graph_test_SOURCES = test/graph_test.cc # test_heap_test_SOURCES = test/heap_test.cc test_kruskal_test_SOURCES = test/kruskal_test.cc diff -r 31a2e6d28f61 -r 889d0c289d19 test/error_test.cc --- a/test/error_test.cc Fri Mar 21 22:25:40 2008 +0000 +++ b/test/error_test.cc Tue Mar 25 16:36:44 2008 +0100 @@ -22,47 +22,242 @@ #include "test_tools.h" using namespace lemon; -using std::cout; -using std::endl; -void faulty_fn() { - fault("This is a fault message"); +#ifdef LEMON_ENABLE_ASSERTS +#undef LEMON_ENABLE_ASSERTS +#endif + +#ifdef LEMON_DISABLE_ASSERTS +#undef LEMON_DISABLE_ASSERTS +#endif + +//checking disabled asserts +#define LEMON_DISABLE_ASSERTS +#include + +void no_assertion_text_disable() { + LEMON_ASSERT(true, "This is a fault message"); } -void exception_fn() { - throw Exception("This is a function throwing exception with some args: ") - << 5 << ", " << 18; +void no_assertion_exception_disable() { + LEMON_ASSERT(true, Exception()); } -void unfinished_fn() { - LEMON_FIXME("unfinished_fn() is unfinished!"); +void assertion_text_disable() { + LEMON_ASSERT(false, "This is a fault message"); } +void assertion_exception_disable() { + LEMON_ASSERT(false, Exception()); +} -int main() { +void fixme_disable() { + LEMON_FIXME("fixme_disable() is fixme!"); +} + +void check_assertion_disable() { + no_assertion_text_disable(); + no_assertion_exception_disable(); + assertion_exception_disable(); + assertion_text_disable(); + fixme_disable(); +} +#undef LEMON_DISABLE_ASSERTS + + +#define LEMON_ASSERT_ERROR +#include + +void no_assertion_text_error() { + LEMON_ASSERT(true, "This is a fault message"); +} + +void no_assertion_exception_error() { + LEMON_ASSERT(true, Exception()); +} + +void assertion_text_error() { + LEMON_ASSERT(false, "This is a fault message"); +} + +void assertion_exception_error() { + LEMON_ASSERT(false, Exception()); +} + +void fixme_error() { + LEMON_FIXME("fixme_error() is fixme!"); +} + +void check_assertion_error() { + no_assertion_text_error(); + no_assertion_exception_error(); try { - faulty_fn(); - check(false, "A faulty function did not fail."); - } - catch(const Exception &e) { - cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl; + assertion_exception_error(); + check(false, "Assertion error"); + } catch (const AssertionFailedError& e) { } try { - exception_fn(); - check(false, "The function did not throw Exception."); - } - catch(const Exception &e) { - cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl; + assertion_text_error(); + check(false, "Assertion error"); + } catch (const AssertionFailedError& e) { } try { - unfinished_fn(); - check(false, "FIXME macro does not work."); + fixme_error(); + check(false, "Assertion error"); + } catch (const AssertionFailedError& e) { } - catch(const Exception &e) { - cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl; +} +#undef LEMON_ASSERT_ERROR + +#define LEMON_ASSERT_EXCEPTION +#include + +void no_assertion_text_exception() { + LEMON_ASSERT(true, "This is a fault message"); +} + +void no_assertion_exception_exception() { + LEMON_ASSERT(true, Exception()); +} + +void assertion_text_exception() { + LEMON_ASSERT(false, "This is a fault message"); +} + +void assertion_exception_exception() { + LEMON_ASSERT(false, Exception()); +} + +void fixme_exception() { + LEMON_FIXME("fixme_exception() is fixme!"); +} + +void check_assertion_exception() { + no_assertion_text_exception(); + no_assertion_exception_exception(); + try { + assertion_exception_exception(); + check(false, "Assertion error"); + } catch (const Exception& e) { } + try { + assertion_text_exception(); + check(false, "Assertion error"); + } catch (const AssertionFailedError& e) { + } + + try { + assertion_text_exception(); + check(false, "Assertion error"); + } catch (const AssertionFailedError& e) { + } + + try { + fixme_exception(); + check(false, "Assertion error"); + } catch (const AssertionFailedError& e) { + } +} +#undef LEMON_ASSERT_EXCEPTION + +#define LEMON_ASSERT_LOG + +#include + +void no_assertion_text_log() { + LEMON_ASSERT(true, "This is a fault message"); +} + +void no_assertion_exception_log() { + LEMON_ASSERT(true, Exception()); +} + +void assertion_text_log() { + LEMON_ASSERT(false, "This is a fault message"); +} + +void assertion_exception_log() { + LEMON_ASSERT(false, Exception()); +} + +void fixme_log() { + LEMON_FIXME("fixme_log() is fixme!"); +} + +void check_assertion_log() { + no_assertion_text_log(); + no_assertion_exception_log(); + std::cerr << "The next 3 failure messages are expected: " << std::endl; + assertion_exception_log(); + assertion_text_log(); + fixme_log(); + std::cerr << "End of expected error messages" << std::endl; +} +#undef LEMON_ASSERT_LOG + +#define LEMON_ASSERT_CUSTOM + +static int cnt = 0; +void my_assert_handler(const char*, int, const char*, + const char*, const char*) { + ++cnt; +} + +void my_assert_handler(const char*, int, const char*, + const std::exception&, const char*) { + ++cnt; +} + +void my_assert_handler(const char*, int, const char*, + const std::string&, const char*) { + ++cnt; +} + + +#define LEMON_CUSTOM_ASSERT_HANDLER my_assert_handler +#include + +void no_assertion_text_custom() { + LEMON_ASSERT(true, "This is a fault message"); +} + +void no_assertion_exception_custom() { + LEMON_ASSERT(true, Exception()); +} + +void assertion_text_custom() { + LEMON_ASSERT(false, "This is a fault message"); +} + +void assertion_exception_custom() { + LEMON_ASSERT(false, Exception()); +} + +void fixme_custom() { + LEMON_FIXME("fixme_custom() is fixme!"); +} + +void check_assertion_custom() { + no_assertion_text_custom(); + no_assertion_exception_custom(); + assertion_exception_custom(); + assertion_text_custom(); + fixme_custom(); + check(cnt == 3, "The custom assert handler does not work"); +} + +#undef LEMON_ASSERT_CUSTOM + + +int main() { + check_assertion_disable(); + check_assertion_error(); + check_assertion_exception(); + check_assertion_log(); + check_assertion_custom(); + return 0; }