Reworking assertions and moving to distinict file
authorBalazs Dezso <deba@inf.elte.hu>
Tue, 25 Mar 2008 16:36:44 +0100
changeset 108889d0c289d19
parent 107 31a2e6d28f61
child 109 abddaa08b507
child 112 d2ee5e7f00ef
Reworking assertions and moving to distinict file
lemon/Makefile.am
lemon/arg_parser.h
lemon/assert.h
lemon/error.h
test/Makefile.am
test/error_test.cc
     1.1 --- a/lemon/Makefile.am	Fri Mar 21 22:25:40 2008 +0000
     1.2 +++ b/lemon/Makefile.am	Tue Mar 25 16:36:44 2008 +0100
     1.3 @@ -17,6 +17,7 @@
     1.4  
     1.5  lemon_HEADERS += \
     1.6          lemon/arg_parser.h \
     1.7 +	lemon/assert.h \
     1.8          lemon/bfs.h \
     1.9          lemon/bin_heap.h \
    1.10          lemon/dfs.h \
     2.1 --- a/lemon/arg_parser.h	Fri Mar 21 22:25:40 2008 +0000
     2.2 +++ b/lemon/arg_parser.h	Tue Mar 25 16:36:44 2008 +0100
     2.3 @@ -26,7 +26,7 @@
     2.4  #include <iostream>
     2.5  #include <sstream>
     2.6  #include <algorithm>
     2.7 -#include <lemon/error.h>
     2.8 +#include <lemon/assert.h>
     2.9  
    2.10  ///\ingroup misc
    2.11  ///\file
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/lemon/assert.h	Tue Mar 25 16:36:44 2008 +0100
     3.3 @@ -0,0 +1,364 @@
     3.4 +/* -*- C++ -*-
     3.5 + *
     3.6 + * This file is a part of LEMON, a generic C++ optimization library
     3.7 + *
     3.8 + * Copyright (C) 2003-2008
     3.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    3.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    3.11 + *
    3.12 + * Permission to use, modify and distribute this software is granted
    3.13 + * provided that this copyright notice appears in all copies. For
    3.14 + * precise terms see the accompanying LICENSE file.
    3.15 + *
    3.16 + * This software is provided "AS IS" with no warranty of any kind,
    3.17 + * express or implied, and with no claim as to its suitability for any
    3.18 + * purpose.
    3.19 + *
    3.20 + */
    3.21 +
    3.22 +#ifndef LEMON_ASSERT_H
    3.23 +#define LEMON_ASSERT_H
    3.24 +
    3.25 +/// \ingroup exceptions
    3.26 +/// \file
    3.27 +/// \brief Extended assertion handling
    3.28 +
    3.29 +#include <lemon/error.h>
    3.30 +
    3.31 +namespace lemon {
    3.32 +
    3.33 +  /// @{
    3.34 +
    3.35 +  ///\e
    3.36 +  class AssertionFailedError : public LogicError {
    3.37 +  protected:
    3.38 +    const char *_assertion;
    3.39 +    const char *_file;
    3.40 +    int _line;
    3.41 +    const char *_function;
    3.42 +    const char *_message;
    3.43 +
    3.44 +    mutable ExceptionMember<std::string> _message_holder;
    3.45 +  public:
    3.46 +    ///\e
    3.47 +    AssertionFailedError(const char *file, int line, const char *function,
    3.48 +			 const char *msg, const char *assertion = 0) :
    3.49 +      _assertion(assertion), _file(file), _line(line), 
    3.50 +      _function(function), _message(msg) {}
    3.51 +
    3.52 +    ///\e
    3.53 +    const char* assertion() const { return _assertion; }
    3.54 +    ///\e
    3.55 +    const char* message() const { return _message; }
    3.56 +    ///\e
    3.57 +    const char* file() const { return _file; }
    3.58 +    ///\e
    3.59 +    const char* function() const { return _function; }
    3.60 +    ///\e
    3.61 +    int line() const { return _line; }
    3.62 +
    3.63 +
    3.64 +    virtual const char* what() const throw() {
    3.65 +      try {
    3.66 +	std::ostringstream ostr;
    3.67 +	ostr << _file << ":" << _line << ": ";
    3.68 +	if (_function)
    3.69 +	  ostr << _function << ": ";
    3.70 +	ostr << _message;
    3.71 +	if (_assertion)
    3.72 +	   ostr << " (assertion '" << _assertion << "' failed)";
    3.73 +	_message_holder.set(ostr.str());
    3.74 +	return ostr.str().c_str();
    3.75 +      }
    3.76 +      catch(...) {}
    3.77 +      if( _message_holder.valid() ) return _message_holder.get().c_str();
    3.78 +      return "lemon::AssertionFailedError";
    3.79 +    }
    3.80 +    virtual ~AssertionFailedError() throw() {}
    3.81 +  };
    3.82 +
    3.83 +
    3.84 +  inline void assert_fail_log(const char *file, int line,
    3.85 +			      const char *function,
    3.86 +			      const std::exception& exception, 
    3.87 +			      const char *assertion)
    3.88 +  {
    3.89 +    std::cerr << file << ":" << line << ": ";
    3.90 +    if (function)
    3.91 +      std::cerr << function << ": ";
    3.92 +    std::cerr << exception.what();
    3.93 +    if (assertion)
    3.94 +      std::cerr << " (assertion '" << assertion << "' failed)";
    3.95 +    std::cerr << std::endl;
    3.96 +  }
    3.97 +
    3.98 +  inline void assert_fail_log(const char *file, int line, const char *function,
    3.99 +			      const char *message, const char *assertion)
   3.100 +  {
   3.101 +    std::cerr << file << ":" << line << ": ";
   3.102 +    if (function)
   3.103 +      std::cerr << function << ": ";
   3.104 +    std::cerr << message;
   3.105 +    if (assertion)
   3.106 +      std::cerr << " (assertion '" << assertion << "' failed)";
   3.107 +    std::cerr << std::endl;
   3.108 +  }
   3.109 +
   3.110 +  inline void assert_fail_log(const char *file, int line, const char *function, 
   3.111 +			      const std::string& message, const char *assertion)
   3.112 +  {
   3.113 +    assert_fail_log(file, line, function, message.c_str(), assertion);
   3.114 +  }
   3.115 +
   3.116 +  inline void assert_fail_abort(const char *file, int line, 
   3.117 +				const char *function,
   3.118 +				const std::exception& exception,
   3.119 +				const char *assertion)
   3.120 +  {
   3.121 +    std::cerr << file << ":" << line << ": ";
   3.122 +    if (function)
   3.123 +      std::cerr << function << ": ";
   3.124 +    std::cerr << exception.what();
   3.125 +    if (assertion)
   3.126 +      std::cerr << " (assertion '" << assertion << "' failed)";
   3.127 +    std::cerr << std::endl;
   3.128 +    std::abort();
   3.129 +  }
   3.130 +
   3.131 +  inline void assert_fail_abort(const char *file, int line,
   3.132 +				const char *function, const char* message,
   3.133 +				const char *assertion)
   3.134 +  {
   3.135 +    std::cerr << file << ":" << line << ": ";
   3.136 +    if (function)
   3.137 +      std::cerr << function << ": ";
   3.138 +    std::cerr << message;
   3.139 +    if (assertion)
   3.140 +      std::cerr << " (assertion '" << assertion << "' failed)";
   3.141 +    std::cerr << std::endl;
   3.142 +    std::abort();
   3.143 +  }
   3.144 +
   3.145 +  inline void assert_fail_abort(const char *file, int line, 
   3.146 +				const char *function, 
   3.147 +				const std::string& message,
   3.148 +				const char *assertion)
   3.149 +  {
   3.150 +    assert_fail_abort(file, line, function, message.c_str(), assertion);
   3.151 +  }
   3.152 +
   3.153 +  inline void assert_fail_error(const char *file, int line, 
   3.154 +				  const char *function,
   3.155 +				  const std::exception& exception,
   3.156 +				  const char *assertion)
   3.157 +  {
   3.158 +    throw AssertionFailedError(file, line, function, 
   3.159 +			       exception.what(), assertion);
   3.160 +  }
   3.161 +
   3.162 +  inline void assert_fail_error(const char *file, int line,
   3.163 +				  const char *function, const char *message,
   3.164 +				  const char *assertion)
   3.165 +  {
   3.166 +    throw AssertionFailedError(file, line, function, message, assertion);
   3.167 +  }
   3.168 +
   3.169 +  inline void assert_fail_error(const char *file, int line,
   3.170 +				  const char *function, 
   3.171 +				  const std::string& message,
   3.172 +				  const char *assertion)
   3.173 +  {
   3.174 +    assert_fail_error(file, line, function, message.c_str(), assertion);
   3.175 +  }
   3.176 +
   3.177 +  template <typename Exception>
   3.178 +  inline void assert_fail_exception(const char *, int, const char *,
   3.179 +				    const Exception& exception,
   3.180 +				    const char *, const std::exception* = 
   3.181 +				    static_cast<const Exception*>(0))
   3.182 +  {
   3.183 +    throw exception;
   3.184 +  }
   3.185 +
   3.186 +  inline void assert_fail_exception(const char *file, int line,
   3.187 +				    const char *function, const char *message,
   3.188 +				    const char *assertion)
   3.189 +  {
   3.190 +    throw AssertionFailedError(file, line, function, message, assertion);
   3.191 +  }
   3.192 +
   3.193 +  inline void assert_fail_exception(const char *file, int line, 
   3.194 +				    const char *function, 
   3.195 +				    const std::string& message,
   3.196 +				    const char *assertion)
   3.197 +  {
   3.198 +    assert_fail_exception(file, line, function, message.c_str(), assertion);
   3.199 +  }
   3.200 +
   3.201 +/// @}
   3.202 +
   3.203 +}
   3.204 +#endif // LEMON_ASSERT_H
   3.205 +
   3.206 +#undef LEMON_ASSERT
   3.207 +#undef LEMON_FIXME
   3.208 +
   3.209 +#if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
   3.210 +  (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
   3.211 +  (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +		\
   3.212 +  (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +		\
   3.213 +  (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
   3.214 +#error "Lemon assertion system is not set properly"
   3.215 +#endif
   3.216 +
   3.217 +#if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
   3.218 +     (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
   3.219 +     (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +		\
   3.220 +     (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +	\
   3.221 +     (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||	\
   3.222 +     defined(LEMON_ENABLE_ASSERT)) &&			\
   3.223 +  defined(LEMON_DISABLE_ASSERTS)
   3.224 +#error "Lemon assertion system is not set properly"
   3.225 +#endif
   3.226 +
   3.227 +
   3.228 +#if defined LEMON_ASSERT_LOG
   3.229 +#  undef LEMON_ASSERT_HANDLER
   3.230 +#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log
   3.231 +#elif defined LEMON_ASSERT_ABORT
   3.232 +#  undef LEMON_ASSERT_HANDLER
   3.233 +#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
   3.234 +#elif defined LEMON_ASSERT_ERROR
   3.235 +#  undef LEMON_ASSERT_HANDLER
   3.236 +#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error
   3.237 +#elif defined LEMON_ASSERT_EXCEPTION
   3.238 +#  undef LEMON_ASSERT_HANDLER
   3.239 +#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
   3.240 +#elif defined LEMON_ASSERT_CUSTOM
   3.241 +#  undef LEMON_ASSERT_HANDLER
   3.242 +#  ifndef LEMON_CUSTOM_ASSERT_HANDLER
   3.243 +#    error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
   3.244 +#  endif
   3.245 +#  define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
   3.246 +#elif defined LEMON_ENABLE_ASSERTS
   3.247 +#  undef LEMON_ASSERT_HANDLER
   3.248 +#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
   3.249 +#else
   3.250 +#  undef LEMON_ASSERT_HANDLER
   3.251 +#endif
   3.252 +
   3.253 +
   3.254 +#ifndef LEMON_FUNCTION_NAME
   3.255 +#  define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
   3.256 +#endif
   3.257 +
   3.258 +#ifdef DOXYGEN
   3.259 +
   3.260 +/// \ingroup exceptions
   3.261 +///
   3.262 +/// \brief Macro for assertions with customizable message
   3.263 +///
   3.264 +/// Macro for assertions with customizable message.  
   3.265 +/// \param exp An expression convertible to bool. If the expression is
   3.266 +/// false, then an assertion is raised. The concrete behaviour depends
   3.267 +/// on the settings of the assertion system.
   3.268 +/// \param msg A \e const \e char*, a \e const std::string& or a \e
   3.269 +/// const \e std::exception& parameter. The variable can be used to
   3.270 +/// provide information about the circumstances of failed assertion.
   3.271 +///
   3.272 +/// The assertions are disabled in the default behaviour. You can
   3.273 +/// enable the assertions with the following code:
   3.274 +/// \code
   3.275 +/// #define LEMON_ENABLE_ASSERTS
   3.276 +/// \endcode
   3.277 +/// or with compilation parameters:
   3.278 +/// \code
   3.279 +/// g++ -DLEMON_ENABLE_ASSERTS
   3.280 +/// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
   3.281 +/// \endcode
   3.282 +/// 
   3.283 +/// The %lemon assertion system has a wide range of customization
   3.284 +/// properties. As default behaviour the failed assertion prints a
   3.285 +/// short log message to the standard ouput and aborts the execution.
   3.286 +///
   3.287 +/// The following modes can be used in the assertion system: 
   3.288 +///
   3.289 +/// - \e LEMON_ASSERT_LOG The failed assert print a short convenient
   3.290 +///   error message to the standard error and continues the
   3.291 +///   execution.
   3.292 +/// - \e LEMON_ASSERT_ABORT This mode is similar to the \e
   3.293 +///   LEMON_ASSERT_LOG, but it aborts the program. It is the default
   3.294 +///   operation mode when the asserts are enabled with \e
   3.295 +///   LEMON_ENABLE_ASSERTS.
   3.296 +/// - \e LEMON_ASSERT_ERROR The assert throws an \ref
   3.297 +///   lemon::AssertionFailedError "AssertionFailedError". If the \c
   3.298 +///   msg parameter is an exception, then the result of the \ref
   3.299 +///   lemon::Exception::what() "what()" member function is passed as
   3.300 +///   error message.
   3.301 +/// - \e LEMON_ASSERT_EXCEPTION If the specified \c msg is an
   3.302 +///   exception then it raised directly (solving that the exception
   3.303 +///   can not be thrown polymorphically), otherwise an \ref
   3.304 +///   lemon::AssertionFailedError "AssertionFailedError" is thrown with
   3.305 +///   the given parameter.
   3.306 +/// - \e LEMON_ASSERT_CUSTOM The user can define an own assertion
   3.307 +///   handler functions. Three overloaded functions should be defined
   3.308 +///   with the following parameter lists:
   3.309 +///   \code
   3.310 +///     void custom_assert_handler(const char* file, int line, 
   3.311 +///                                const char* function, const char* message, const char* expression);
   3.312 +///     void custom_assert_handler(const char* file, int line, 
   3.313 +///                                const char* function, const std::string& message, const char* expression);
   3.314 +///     void custom_assert_handler(const char* file, int line, 
   3.315 +///                                const char* function, const std::exception& message, const char* expression);
   3.316 +///   \endcode
   3.317 +///   The name of the functions should be defined as the \c
   3.318 +///   LEMON_CUSTOM_ASSERT_HANDLER macro name. 
   3.319 +///   \code
   3.320 +///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
   3.321 +///   \endcode
   3.322 +///   Whenever an assertion is occured, one of the custom assertion
   3.323 +///   handler is called with appropiate parameters.
   3.324 +///
   3.325 +/// The assertion mode can be changed within one compilation unit, if
   3.326 +/// the macros are redefined with other settings and the
   3.327 +/// lemon/assert.h file is reincluded then the behaviour is changed
   3.328 +/// appropiately to the new settings.
   3.329 +#  define LEMON_ASSERT(exp, msg)					\
   3.330 +  (static_cast<void> (!!(exp) ? 0 : (					\
   3.331 +    LEMON_ASSERT_HANDLER(__FILE__, __LINE__,				\
   3.332 +			 LEMON_FUNCTION_NAME,				\
   3.333 +			 msg, #exp), 0)))
   3.334 +
   3.335 +
   3.336 +/// \ingroup exceptions
   3.337 +///
   3.338 +/// \brief Macro for mark not yet implemented features.
   3.339 +///
   3.340 +/// Macro for mark not yet implemented features and outstanding bugs.
   3.341 +/// It is close to be the shortcut of the following code:
   3.342 +/// \code
   3.343 +///   LEMON_ASSERT(false, msg);
   3.344 +/// \endcode
   3.345 +#  define LEMON_FIXME(msg)						\
   3.346 +       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,	\
   3.347 +			     "FIXME: " msg, static_cast<const char*>(0)))
   3.348 +
   3.349 +#else
   3.350 +
   3.351 +#  ifndef LEMON_ASSERT_HANDLER
   3.352 +#    define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
   3.353 +#    define LEMON_FIXME(msg) (static_cast<void>(0))
   3.354 +#  else
   3.355 +#    define LEMON_ASSERT(exp, msg)                 \
   3.356 +       (static_cast<void> (!!(exp) ? 0 : (         \
   3.357 +         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   3.358 +                              LEMON_FUNCTION_NAME, \
   3.359 +                              msg, #exp), 0)))
   3.360 +#    define LEMON_FIXME(msg) \
   3.361 +       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,	\
   3.362 +			     "FIXME: " msg,  static_cast<const char*>(0)))
   3.363 +#  endif
   3.364 +
   3.365 +#endif
   3.366 +
   3.367 +
     4.1 --- a/lemon/error.h	Fri Mar 21 22:25:40 2008 +0000
     4.2 +++ b/lemon/error.h	Tue Mar 25 16:36:44 2008 +0100
     4.3 @@ -93,7 +93,7 @@
     4.4      std::auto_ptr<_Type> ptr;
     4.5    };
     4.6  
     4.7 -  /// Exception-safe convenient "error message" class.
     4.8 +  /// Exception-safe convenient error message builder class.
     4.9  
    4.10    /// Helper class which provides a convenient ostream-like (operator <<
    4.11    /// based) interface to create a string message. Mostly useful in
    4.12 @@ -413,263 +413,8 @@
    4.13      virtual ~IoParameterError() throw() {}
    4.14    };
    4.15  
    4.16 -
    4.17 -  ///\e
    4.18 -  class AssertionFailedError : public LogicError {
    4.19 -  protected:
    4.20 -    const char *assertion;
    4.21 -    const char *file;
    4.22 -    int line;
    4.23 -    const char *function;
    4.24 -    const char *message;
    4.25 -
    4.26 -    mutable ExceptionMember<std::string> _message_holder;
    4.27 -  public:
    4.28 -    ///\e
    4.29 -    AssertionFailedError(const char *_file, int _line, const char *func,
    4.30 -			 const char *msg, const char *_assertion = 0) :
    4.31 -      assertion(_assertion), file(_file), line(_line), function(func),
    4.32 -      message(msg) {}
    4.33 -
    4.34 -    ///\e
    4.35 -    const char* get_assertion() const { return assertion; }
    4.36 -    ///\e
    4.37 -    const char* get_message() const { return message; }
    4.38 -    ///\e
    4.39 -    const char* get_file() const { return file; }
    4.40 -    ///\e
    4.41 -    const char* get_function() const { return function; }
    4.42 -    ///\e
    4.43 -    int get_line() const { return line; }
    4.44 -
    4.45 -
    4.46 -    virtual const char* what() const throw() {
    4.47 -      try {
    4.48 -	std::ostringstream ostr;
    4.49 -	ostr << file << ":" << line << ": ";
    4.50 -	if( function )
    4.51 -	  ostr << function << ": ";
    4.52 -	ostr << message;
    4.53 -	if( assertion )
    4.54 -	   ostr << " (assertion '" << assertion << "' failed)";
    4.55 -	_message_holder.set(ostr.str());
    4.56 -	return ostr.str().c_str();
    4.57 -      }
    4.58 -      catch(...) {}
    4.59 -      if( _message_holder.valid() ) return _message_holder.get().c_str();
    4.60 -      return "lemon::AssertionFailedError";
    4.61 -    }
    4.62 -   virtual ~AssertionFailedError() throw() {}
    4.63 -  };
    4.64 -
    4.65 -
    4.66 -  /****************  Macros  ****************/
    4.67 -
    4.68 -
    4.69 -  template <typename Exception>
    4.70 -  inline void assert_fail(const char *file, int line,
    4.71 -                          const char *func,
    4.72 -                          Exception exception,
    4.73 -                          const char *assertion = 0,
    4.74 -                          bool do_abort=true)
    4.75 -  {
    4.76 -    using namespace std;
    4.77 -    cerr << file << ":" << line << ": ";
    4.78 -    if (func)
    4.79 -      cerr << func << ": ";
    4.80 -    cerr << exception.what();
    4.81 -    if (assertion)
    4.82 -      cerr << " (assertion '" << assertion << "' failed)";
    4.83 -    cerr << endl;
    4.84 -    if (do_abort)
    4.85 -      abort();
    4.86 -  }
    4.87 -
    4.88 -  template <>
    4.89 -  inline void assert_fail<const char *>(const char *file, int line,
    4.90 -                                        const char *func,
    4.91 -                                        const char *message,
    4.92 -                                        const char *assertion,
    4.93 -                                        bool do_abort)
    4.94 -  {
    4.95 -    using namespace std;
    4.96 -    cerr << file << ":" << line << ": ";
    4.97 -    if (func)
    4.98 -      cerr << func << ": ";
    4.99 -    cerr << message;
   4.100 -    if (assertion)
   4.101 -      cerr << " (assertion '" << assertion << "' failed)";
   4.102 -    cerr << endl;
   4.103 -    if (do_abort)
   4.104 -      abort();
   4.105 -  }
   4.106 -
   4.107 -  template <>
   4.108 -  inline void assert_fail<std::string>(const char *file, int line,
   4.109 -                                       const char *func,
   4.110 -                                       std::string message,
   4.111 -                                       const char *assertion,
   4.112 -                                       bool do_abort)
   4.113 -  {
   4.114 -    assert_fail(file, line, func, message.c_str(), assertion, do_abort);
   4.115 -  }
   4.116 -
   4.117 -  template <typename Exception>
   4.118 -  inline void assert_fail_failure(const char *file, int line, const char *func,
   4.119 -			   Exception exception,
   4.120 -			   const char *assertion = 0,
   4.121 -			   bool = true)
   4.122 -  {
   4.123 -    throw AssertionFailedError(file, line, func, exception.what(), assertion);
   4.124 -  }
   4.125 -
   4.126 -  template <>
   4.127 -  inline void assert_fail_failure<const char *>(const char *file, int line,
   4.128 -                                                const char *func,
   4.129 -                                                const char *message,
   4.130 -                                                const char *assertion,
   4.131 -                                                bool)
   4.132 -  {
   4.133 -    throw AssertionFailedError(file, line, func, message, assertion);
   4.134 -  }
   4.135 -
   4.136 -  template <>
   4.137 -  inline void assert_fail_failure<std::string>(const char *file, int line,
   4.138 -                                               const char *func,
   4.139 -                                               std::string message,
   4.140 -                                               const char *assertion,
   4.141 -                                               bool)
   4.142 -  {
   4.143 -    assert_fail_failure(file, line, func, message.c_str(), assertion, true);
   4.144 -  }
   4.145 -
   4.146 -  template <typename Exception>
   4.147 -  inline void assert_fail_exception(const char *file, int line, const char *func,
   4.148 -			     Exception exception,
   4.149 -			     const char *assertion = 0, bool = true)
   4.150 -  {
   4.151 -    throw exception;
   4.152 -  }
   4.153 -
   4.154 -  template <>
   4.155 -  inline void assert_fail_exception<const char *>(const char *file, int line,
   4.156 -					   const char *func,
   4.157 -					   const char *message,
   4.158 -					   const char *assertion,
   4.159 -					   bool)
   4.160 -  {
   4.161 -    throw AssertionFailedError(file, line, func, message, assertion);
   4.162 -  }
   4.163 -
   4.164 -  template <>
   4.165 -  inline void assert_fail_exception<std::string>(const char *file, int line,
   4.166 -                                                 const char *func,
   4.167 -                                                 std::string message,
   4.168 -                                                 const char *assertion,
   4.169 -                                                 bool)
   4.170 -  {
   4.171 -    assert_fail_exception(file, line, func, message.c_str(), assertion, true);
   4.172 -  }
   4.173 -
   4.174 -/// @}
   4.175 +  /// @}
   4.176  
   4.177  }
   4.178 +
   4.179  #endif // LEMON_ERROR_H
   4.180 -
   4.181 -#undef LEMON_ASSERT
   4.182 -#undef LEMON_FIXME
   4.183 -
   4.184 -#ifdef LEMON_ENABLE_ASSERTS
   4.185 -#  define LEMON_ASSERT_ABORT
   4.186 -#endif
   4.187 -
   4.188 -#ifndef LEMON_ASSERT_DO_ABORT
   4.189 -#  define LEMON_ASSERT_DO_ABORT 1
   4.190 -#endif
   4.191 -
   4.192 -#ifndef LEMON_ASSERT_HANDLER
   4.193 -#  if defined LEMON_ASSERT_EXCEPTION
   4.194 -#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
   4.195 -#  elif defined LEMON_ASSERT_FAILURE
   4.196 -#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure
   4.197 -#  elif defined LEMON_ASSERT_ABORT
   4.198 -#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
   4.199 -#  else
   4.200 -#    define LEMON_DISABLE_ASSERTS
   4.201 -#  endif
   4.202 -#endif
   4.203 -
   4.204 -#ifdef DOXYGEN
   4.205 -
   4.206 -/// \brief Macro for assertions with customizable message
   4.207 -///
   4.208 -/// Macro for assertions with customizable message.
   4.209 -///
   4.210 -/// The assertions are disabled in the default behaviour. You can
   4.211 -/// enable the assertions with the
   4.212 -/// \code
   4.213 -/// #define LEMON_ENABLE_ASSERTS
   4.214 -/// \endcode
   4.215 -/// Then an assert
   4.216 -/// provides a log on the standard error about the assertion and aborts
   4.217 -/// the program if LEMON_ASSERT_DO_ABORT is also defined (otherwise the
   4.218 -/// program keeps on running).
   4.219 -/// By defining LEMON_ASSERT_FAILURE or
   4.220 -/// LEMON_ASSERT_EXCEPTION, you can set other behaviour to the
   4.221 -/// assertions. In case LEMON_ASSERT_FAILURE is given, LEMON_ASSERT
   4.222 -/// will always throw an \c AssertionFailedError exception with
   4.223 -/// the \c msg error message. By using
   4.224 -/// LEMON_ASSERT_EXCEPTION, one can define an arbitrary exception to be thrown.
   4.225 -///
   4.226 -/// The LEMON_ASSERT macro should be called with the \c exp parameter
   4.227 -/// which should be an expression convertible to bool. If the given
   4.228 -/// parameter is false the assertion is raised and one of the assertion
   4.229 -/// behaviour will be activated. The \c msg should be either a const
   4.230 -/// char* message or an exception. When the \c msg is an exception the
   4.231 -/// \ref lemon::Exception::what() "what()" function is called to retrieve and
   4.232 -/// display the error message.
   4.233 -///
   4.234 -/// \todo We should provide some way to reset to the default behaviour,
   4.235 -/// shouldn't we?
   4.236 -///
   4.237 -/// \todo This whole 'assert' business should be placed in a separate
   4.238 -/// include file. The boost assert is not guarded by header sentries
   4.239 -/// which may help to change the behaviour of the assertions in
   4.240 -/// the files.
   4.241 -///
   4.242 -/// \todo __PRETTY_FUNCTION__ should be replaced by something
   4.243 -/// compiler-independent, like BOOST_CURRENT_FUNCTION
   4.244 -
   4.245 -#  define LEMON_ASSERT(exp, msg)                 \
   4.246 -     (static_cast<void> (!!(exp) ? 0 : (         \
   4.247 -       LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   4.248 -                            __PRETTY_FUNCTION__, \
   4.249 -                            msg, #exp, LEMON_ASSERT_DO_ABORT), 0)))
   4.250 -
   4.251 -#else
   4.252 -#  if defined LEMON_DISABLE_ASSERTS
   4.253 -
   4.254 -#    define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
   4.255 -
   4.256 -#  else
   4.257 -#    define LEMON_ASSERT(exp, msg)                 \
   4.258 -       (static_cast<void> (!!(exp) ? 0 : (         \
   4.259 -         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   4.260 -                              __PRETTY_FUNCTION__, \
   4.261 -                              msg, #exp, LEMON_ASSERT_DO_ABORT), 0)))
   4.262 -#  endif
   4.263 -#endif
   4.264 -
   4.265 -/**
   4.266 - * \brief Macro for mark not yet implemented features.
   4.267 - *
   4.268 - * \todo Is this the right place for this? It should be used only in
   4.269 - * modules under development.
   4.270 - *
   4.271 - * \todo __PRETTY_FUNCTION__ should be replaced by something
   4.272 - * compiler-independent, like BOOST_CURRENT_FUNCTION
   4.273 - */
   4.274 -
   4.275 -#define LEMON_FIXME(msg) \
   4.276 -    (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
   4.277 -			  "FIXME: " msg))
     5.1 --- a/test/Makefile.am	Fri Mar 21 22:25:40 2008 +0000
     5.2 +++ b/test/Makefile.am	Tue Mar 25 16:36:44 2008 +0100
     5.3 @@ -12,6 +12,7 @@
     5.4  	test/dfs_test \
     5.5  	test/digraph_test \
     5.6          test/dim_test \
     5.7 +	test/error_test \
     5.8  	test/graph_test \
     5.9  	test/kruskal_test \
    5.10          test/maps_test \
    5.11 @@ -28,7 +29,7 @@
    5.12  test_dfs_test_SOURCES = test/dfs_test.cc
    5.13  test_digraph_test_SOURCES = test/digraph_test.cc
    5.14  test_dim_test_SOURCES = test/dim_test.cc
    5.15 -#test_error_test_SOURCES = test/error_test.cc
    5.16 +test_error_test_SOURCES = test/error_test.cc
    5.17  test_graph_test_SOURCES = test/graph_test.cc
    5.18  # test_heap_test_SOURCES = test/heap_test.cc
    5.19  test_kruskal_test_SOURCES = test/kruskal_test.cc
     6.1 --- a/test/error_test.cc	Fri Mar 21 22:25:40 2008 +0000
     6.2 +++ b/test/error_test.cc	Tue Mar 25 16:36:44 2008 +0100
     6.3 @@ -22,47 +22,242 @@
     6.4  #include "test_tools.h"
     6.5  
     6.6  using namespace lemon;
     6.7 -using std::cout;
     6.8 -using std::endl;
     6.9  
    6.10 -void faulty_fn() {
    6.11 -  fault("This is a fault message");
    6.12 +#ifdef LEMON_ENABLE_ASSERTS
    6.13 +#undef LEMON_ENABLE_ASSERTS
    6.14 +#endif
    6.15 +
    6.16 +#ifdef LEMON_DISABLE_ASSERTS
    6.17 +#undef LEMON_DISABLE_ASSERTS
    6.18 +#endif
    6.19 +
    6.20 +//checking disabled asserts
    6.21 +#define LEMON_DISABLE_ASSERTS
    6.22 +#include <lemon/assert.h>
    6.23 +
    6.24 +void no_assertion_text_disable() {
    6.25 +  LEMON_ASSERT(true, "This is a fault message");
    6.26  }
    6.27  
    6.28 -void exception_fn() {
    6.29 -  throw Exception("This is a function throwing exception with some args: ")
    6.30 -    << 5 << ", " << 18;
    6.31 +void no_assertion_exception_disable() {
    6.32 +  LEMON_ASSERT(true, Exception());
    6.33  }
    6.34  
    6.35 -void unfinished_fn() {
    6.36 -  LEMON_FIXME("unfinished_fn() is unfinished!");
    6.37 +void assertion_text_disable() {
    6.38 +  LEMON_ASSERT(false, "This is a fault message");
    6.39  }
    6.40  
    6.41 +void assertion_exception_disable() {
    6.42 +  LEMON_ASSERT(false, Exception());
    6.43 +}
    6.44  
    6.45 -int main() {
    6.46 +void fixme_disable() {
    6.47 +  LEMON_FIXME("fixme_disable() is fixme!");
    6.48 +}
    6.49 +
    6.50 +void check_assertion_disable() {
    6.51 +  no_assertion_text_disable();
    6.52 +  no_assertion_exception_disable();
    6.53 +  assertion_exception_disable();
    6.54 +  assertion_text_disable();
    6.55 +  fixme_disable();
    6.56 +}
    6.57 +#undef LEMON_DISABLE_ASSERTS
    6.58 +
    6.59 +
    6.60 +#define LEMON_ASSERT_ERROR
    6.61 +#include <lemon/assert.h>
    6.62 +
    6.63 +void no_assertion_text_error() {
    6.64 +  LEMON_ASSERT(true, "This is a fault message");
    6.65 +}
    6.66 +
    6.67 +void no_assertion_exception_error() {
    6.68 +  LEMON_ASSERT(true, Exception());
    6.69 +}
    6.70 +
    6.71 +void assertion_text_error() {
    6.72 +  LEMON_ASSERT(false, "This is a fault message");
    6.73 +}
    6.74 +
    6.75 +void assertion_exception_error() {
    6.76 +  LEMON_ASSERT(false, Exception());
    6.77 +}
    6.78 +
    6.79 +void fixme_error() {
    6.80 +  LEMON_FIXME("fixme_error() is fixme!");
    6.81 +}
    6.82 +
    6.83 +void check_assertion_error() {
    6.84 +  no_assertion_text_error();
    6.85 +  no_assertion_exception_error();
    6.86    try {
    6.87 -    faulty_fn();
    6.88 -    check(false, "A faulty function did not fail.");
    6.89 -  }
    6.90 -  catch(const Exception &e) {
    6.91 -    cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl;
    6.92 +    assertion_exception_error();
    6.93 +    check(false, "Assertion error");
    6.94 +  } catch (const AssertionFailedError& e) {
    6.95    }
    6.96  
    6.97    try {
    6.98 -    exception_fn();
    6.99 -    check(false, "The function did not throw Exception.");
   6.100 -  }
   6.101 -  catch(const Exception &e) {
   6.102 -    cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl;
   6.103 +    assertion_text_error();
   6.104 +    check(false, "Assertion error");
   6.105 +  } catch (const AssertionFailedError& e) {
   6.106    }
   6.107  
   6.108    try {
   6.109 -    unfinished_fn();
   6.110 -    check(false, "FIXME macro does not work.");
   6.111 +    fixme_error();
   6.112 +    check(false, "Assertion error");
   6.113 +  } catch (const AssertionFailedError& e) {
   6.114    }
   6.115 -  catch(const Exception &e) {
   6.116 -    cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl;
   6.117 +}
   6.118 +#undef LEMON_ASSERT_ERROR
   6.119 +
   6.120 +#define LEMON_ASSERT_EXCEPTION
   6.121 +#include <lemon/assert.h>
   6.122 +
   6.123 +void no_assertion_text_exception() {
   6.124 +  LEMON_ASSERT(true, "This is a fault message");
   6.125 +}
   6.126 +
   6.127 +void no_assertion_exception_exception() {
   6.128 +  LEMON_ASSERT(true, Exception());
   6.129 +}
   6.130 +
   6.131 +void assertion_text_exception() {
   6.132 +  LEMON_ASSERT(false, "This is a fault message");
   6.133 +}
   6.134 +
   6.135 +void assertion_exception_exception() {
   6.136 +  LEMON_ASSERT(false, Exception());
   6.137 +}
   6.138 +
   6.139 +void fixme_exception() {
   6.140 +  LEMON_FIXME("fixme_exception() is fixme!");
   6.141 +}
   6.142 +
   6.143 +void check_assertion_exception() {
   6.144 +  no_assertion_text_exception();
   6.145 +  no_assertion_exception_exception();
   6.146 +  try {
   6.147 +    assertion_exception_exception();
   6.148 +    check(false, "Assertion error");
   6.149 +  } catch (const Exception& e) {
   6.150    }
   6.151  
   6.152 +  try {
   6.153 +    assertion_text_exception();
   6.154 +    check(false, "Assertion error");
   6.155 +  } catch (const AssertionFailedError& e) {
   6.156 +  }
   6.157 +
   6.158 +  try {
   6.159 +    assertion_text_exception();
   6.160 +    check(false, "Assertion error");
   6.161 +  } catch (const AssertionFailedError& e) {
   6.162 +  }
   6.163 +
   6.164 +  try {
   6.165 +    fixme_exception();
   6.166 +    check(false, "Assertion error");
   6.167 +  } catch (const AssertionFailedError& e) {
   6.168 +  }
   6.169 +}
   6.170 +#undef LEMON_ASSERT_EXCEPTION
   6.171 +
   6.172 +#define LEMON_ASSERT_LOG
   6.173 +
   6.174 +#include <lemon/assert.h>
   6.175 +
   6.176 +void no_assertion_text_log() {
   6.177 +  LEMON_ASSERT(true, "This is a fault message");
   6.178 +}
   6.179 +
   6.180 +void no_assertion_exception_log() {
   6.181 +  LEMON_ASSERT(true, Exception());
   6.182 +}
   6.183 +
   6.184 +void assertion_text_log() {
   6.185 +  LEMON_ASSERT(false, "This is a fault message");
   6.186 +}
   6.187 +
   6.188 +void assertion_exception_log() {
   6.189 +  LEMON_ASSERT(false, Exception());
   6.190 +}
   6.191 +
   6.192 +void fixme_log() {
   6.193 +  LEMON_FIXME("fixme_log() is fixme!");
   6.194 +}
   6.195 +
   6.196 +void check_assertion_log() {
   6.197 +  no_assertion_text_log();
   6.198 +  no_assertion_exception_log();
   6.199 +  std::cerr << "The next 3 failure messages are expected: " << std::endl;
   6.200 +  assertion_exception_log();
   6.201 +  assertion_text_log();
   6.202 +  fixme_log();
   6.203 +  std::cerr << "End of expected error messages" << std::endl;
   6.204 +}
   6.205 +#undef LEMON_ASSERT_LOG
   6.206 +
   6.207 +#define LEMON_ASSERT_CUSTOM
   6.208 +
   6.209 +static int cnt = 0;
   6.210 +void my_assert_handler(const char*, int, const char*, 
   6.211 +		       const char*, const char*) {
   6.212 +  ++cnt;
   6.213 +}
   6.214 +
   6.215 +void my_assert_handler(const char*, int, const char*, 
   6.216 +		       const std::exception&, const char*) {
   6.217 +  ++cnt;
   6.218 +}
   6.219 +
   6.220 +void my_assert_handler(const char*, int, const char*, 
   6.221 +		       const std::string&, const char*) {
   6.222 +  ++cnt;
   6.223 +}
   6.224 +
   6.225 +
   6.226 +#define LEMON_CUSTOM_ASSERT_HANDLER my_assert_handler
   6.227 +#include <lemon/assert.h>
   6.228 +
   6.229 +void no_assertion_text_custom() {
   6.230 +  LEMON_ASSERT(true, "This is a fault message");
   6.231 +}
   6.232 +
   6.233 +void no_assertion_exception_custom() {
   6.234 +  LEMON_ASSERT(true, Exception());
   6.235 +}
   6.236 +
   6.237 +void assertion_text_custom() {
   6.238 +  LEMON_ASSERT(false, "This is a fault message");
   6.239 +}
   6.240 +
   6.241 +void assertion_exception_custom() {
   6.242 +  LEMON_ASSERT(false, Exception());
   6.243 +}
   6.244 +
   6.245 +void fixme_custom() {
   6.246 +  LEMON_FIXME("fixme_custom() is fixme!");
   6.247 +}
   6.248 +
   6.249 +void check_assertion_custom() {
   6.250 +  no_assertion_text_custom();
   6.251 +  no_assertion_exception_custom();
   6.252 +  assertion_exception_custom();
   6.253 +  assertion_text_custom();
   6.254 +  fixme_custom();
   6.255 +  check(cnt == 3, "The custom assert handler does not work");
   6.256 +}
   6.257 +
   6.258 +#undef LEMON_ASSERT_CUSTOM
   6.259 +
   6.260 +
   6.261 +int main() {
   6.262 +  check_assertion_disable();
   6.263 +  check_assertion_error();
   6.264 +  check_assertion_exception();
   6.265 +  check_assertion_log();
   6.266 +  check_assertion_custom();
   6.267 +
   6.268    return 0;
   6.269  }