COIN-OR::LEMON - Graph Library

Changeset 118:407c08a0eae9 in lemon


Ignore:
Timestamp:
04/11/08 16:20:54 (11 years ago)
Author:
Balazs Dezso <deba@…>
Branch:
default
Phase:
public
Message:

Exception related solutions removed and new LEMON_DEBUG macro

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • lemon/assert.h

    r112 r118  
    2727
    2828namespace lemon {
    29 
    30   /// @{
    31 
    32   ///\e
    33   class AssertionFailedError : public LogicError {
    34   protected:
    35     const char *_assertion;
    36     const char *_file;
    37     int _line;
    38     const char *_function;
    39     const char *_message;
    40 
    41     mutable ExceptionMember<std::string> _message_holder;
    42   public:
    43     ///\e
    44     AssertionFailedError(const char *file, int line, const char *function,
    45                          const char *msg, const char *assertion = 0) :
    46       _assertion(assertion), _file(file), _line(line),
    47       _function(function), _message(msg) {}
    48 
    49     ///\e
    50     const char* assertion() const { return _assertion; }
    51     ///\e
    52     const char* message() const { return _message; }
    53     ///\e
    54     const char* file() const { return _file; }
    55     ///\e
    56     const char* function() const { return _function; }
    57     ///\e
    58     int line() const { return _line; }
    59 
    60 
    61     virtual const char* what() const throw() {
    62       try {
    63         std::ostringstream ostr;
    64         ostr << _file << ":" << _line << ": ";
    65         if (_function)
    66           ostr << _function << ": ";
    67         ostr << _message;
    68         if (_assertion)
    69            ostr << " (assertion '" << _assertion << "' failed)";
    70         _message_holder.set(ostr.str());
    71         return ostr.str().c_str();
    72       }
    73       catch(...) {}
    74       if( _message_holder.valid() ) return _message_holder.get().c_str();
    75       return "lemon::AssertionFailedError";
    76     }
    77     virtual ~AssertionFailedError() throw() {}
    78   };
    79 
    80 
    81   inline void assert_fail_log(const char *file, int line,
    82                               const char *function,
    83                               const std::exception& exception,
    84                               const char *assertion)
    85   {
    86     std::cerr << file << ":" << line << ": ";
    87     if (function)
    88       std::cerr << function << ": ";
    89     std::cerr << exception.what();
    90     if (assertion)
    91       std::cerr << " (assertion '" << assertion << "' failed)";
    92     std::cerr << std::endl;
    93   }
    9429
    9530  inline void assert_fail_log(const char *file, int line, const char *function,
     
    10540  }
    10641
    107   inline void assert_fail_log(const char *file, int line, const char *function,
    108                               const std::string& message, const char *assertion)
    109   {
    110     assert_fail_log(file, line, function, message.c_str(), assertion);
    111   }
    112 
    113   inline void assert_fail_abort(const char *file, int line,
    114                                 const char *function,
    115                                 const std::exception& exception,
    116                                 const char *assertion)
    117   {
    118     assert_fail_log(file, line, function, exception, assertion);
    119     std::abort();
    120   }
    121 
    12242  inline void assert_fail_abort(const char *file, int line,
    12343                                const char *function, const char* message,
     
    12848  }
    12949
    130   inline void assert_fail_abort(const char *file, int line,
    131                                 const char *function,
    132                                 const std::string& message,
    133                                 const char *assertion)
    134   {
    135     assert_fail_log(file, line, function, message.c_str(), assertion);
    136     std::abort();
     50  namespace _assert_bits {
     51   
     52   
     53    inline const char* cstringify(const std::string& str) {
     54      return str.c_str();
     55    }
     56
     57    inline const char* cstringify(const char* str) {
     58      return str;
     59    }   
    13760  }
    138 
    139   inline void assert_fail_error(const char *file, int line,
    140                                   const char *function,
    141                                   const std::exception& exception,
    142                                   const char *assertion)
    143   {
    144     throw AssertionFailedError(file, line, function,
    145                                exception.what(), assertion);
    146   }
    147 
    148   inline void assert_fail_error(const char *file, int line,
    149                                   const char *function, const char *message,
    150                                   const char *assertion)
    151   {
    152     throw AssertionFailedError(file, line, function, message, assertion);
    153   }
    154 
    155   inline void assert_fail_error(const char *file, int line,
    156                                   const char *function,
    157                                   const std::string& message,
    158                                   const char *assertion)
    159   {
    160     throw AssertionFailedError(file, line, function, message.c_str(), assertion);
    161   }
    162 
    163   template <typename Exception>
    164   inline void assert_fail_exception(const char *, int, const char *,
    165                                     const Exception& exception,
    166                                     const char *, const std::exception* =
    167                                     static_cast<const Exception*>(0))
    168   {
    169     throw exception;
    170   }
    171 
    172   inline void assert_fail_exception(const char *file, int line,
    173                                     const char *function, const char *message,
    174                                     const char *assertion)
    175   {
    176     throw AssertionFailedError(file, line, function, message, assertion);
    177   }
    178 
    179   inline void assert_fail_exception(const char *file, int line,
    180                                     const char *function,
    181                                     const std::string& message,
    182                                     const char *assertion)
    183   {
    184     throw AssertionFailedError(file, line, function, message.c_str(), assertion);
    185   }
    186 
    187 /// @}
    188 
    18961}
     62
    19063#endif // LEMON_ASSERT_H
    19164
    19265#undef LEMON_ASSERT
    19366#undef LEMON_FIXME
     67#undef LEMON_DEBUG
    19468
    19569#if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +               \
    19670  (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +               \
    197   (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +               \
    198   (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +           \
    19971  (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
    20072#error "LEMON assertion system is not set properly"
     
    20375#if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +              \
    20476     (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +            \
    205      (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +            \
    206      (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +        \
    20777     (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||     \
    20878     defined(LEMON_ENABLE_ASSERTS)) &&                  \
    209   defined(LEMON_DISABLE_ASSERTS)
     79  (defined(LEMON_DISABLE_ASSERTS) ||                    \
     80   defined(NDEBUG))
    21081#error "LEMON assertion system is not set properly"
    21182#endif
     
    21889#  undef LEMON_ASSERT_HANDLER
    21990#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
    220 #elif defined LEMON_ASSERT_ERROR
    221 #  undef LEMON_ASSERT_HANDLER
    222 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error
    223 #elif defined LEMON_ASSERT_EXCEPTION
    224 #  undef LEMON_ASSERT_HANDLER
    225 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
    22691#elif defined LEMON_ASSERT_CUSTOM
    22792#  undef LEMON_ASSERT_HANDLER
     
    23095#  endif
    23196#  define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
    232 #elif defined LEMON_ENABLE_ASSERTS
    233 #  undef LEMON_ASSERT_HANDLER
     97#elif defined LEMON_DISABLE_ASSERTS
     98#  undef LEMON_ASSERT_HANDLER
     99#elif defined NDEBUG
     100#  undef LEMON_ASSERT_HANDLER
     101#else
    234102#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
    235 #else
    236 #  undef LEMON_ASSERT_HANDLER
    237 #endif
    238 
     103#endif
    239104
    240105#ifndef LEMON_FUNCTION_NAME
     
    248113/// \brief Macro for assertion with customizable message
    249114///
    250 /// Macro for assertion with customizable message. 
    251 /// \param exp An expression that must be convertible to \c bool.
    252 /// If it is \c false, then an assertion is raised. The concrete
    253 /// behaviour depends on the settings of the assertion system.
    254 /// \param msg A <tt>const char*</tt>, a <tt>const std::string&</tt> or
    255 /// a <tt>const std::exception&</tt> parameter, which can be used to
    256 /// provide information about the circumstances of the failed assertion.
    257 ///
    258 /// The assertions are disabled in the default behaviour.
    259 /// You can enable them with the following code:
    260 /// \code
    261 /// #define LEMON_ENABLE_ASSERTS
     115/// Macro for assertion with customizable message.  \param exp An
     116/// expression that must be convertible to \c bool.  If it is \c
     117/// false, then an assertion is raised. The concrete behaviour depends
     118/// on the settings of the assertion system.  \param msg A <tt>const
     119/// char*</tt> parameter, which can be used to provide information
     120/// about the circumstances of the failed assertion.
     121///
     122/// The assertions are enabled in the default behaviour.
     123/// You can disable them with the following code:
     124/// \code
     125/// #define LEMON_DISABLE_ASSERTS
    262126/// \endcode
    263127/// or with compilation parameters:
    264128/// \code
    265 /// g++ -DLEMON_ENABLE_ASSERTS
    266 /// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
    267 /// \endcode
     129/// g++ -DLEMON_DISABLE_ASSERTS
     130/// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
     131/// \endcode
     132/// The checking is also disabled when the standard macro \c NDEBUG is defined.
    268133///
    269134/// The LEMON assertion system has a wide range of customization
     
    275140/// - \c LEMON_ASSERT_LOG The failed assertion prints a short log
    276141///   message to the standard error and continues the execution.
    277 /// - \c LEMON_ASSERT_ABORT This mode is similar to the
    278 ///   \c LEMON_ASSERT_LOG, but it aborts the program. It is the default
    279 ///   behaviour mode when the assertions are enabled with
    280 ///   \c LEMON_ENABLE_ASSERTS.
    281 /// - \c LEMON_ASSERT_ERROR The assertion throws an
    282 ///   \ref lemon::AssertionFailedError "AssertionFailedError".
    283 ///   If the \c msg parameter is an exception, then the result of the
    284 ///   \ref lemon::Exception::what() "what()" member function is passed
    285 ///   as error message.
    286 /// - \c LEMON_ASSERT_EXCEPTION If the specified \c msg is an
    287 ///   exception, then it raised directly (solving that the exception
    288 ///   can not be thrown polymorphically), otherwise an \ref
    289 ///   lemon::AssertionFailedError "AssertionFailedError" is thrown with
    290 ///   the given parameters.
     142/// - \c LEMON_ASSERT_ABORT This mode is similar to the \c
     143///   LEMON_ASSERT_LOG, but it aborts the program. It is the default
     144///   behaviour.
    291145/// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
    292 ///   functions. Three overloaded functions should be defined with the
    293 ///   following parameter lists:
     146///   function.
    294147///   \code
    295148///     void custom_assert_handler(const char* file, int line, const char* function,
    296149///                                const char* message, const char* assertion);
    297 ///     void custom_assert_handler(const char* file, int line, const char* function,
    298 ///                                const std::string& message, const char* assertion);
    299 ///     void custom_assert_handler(const char* file, int line, const char* function,
    300 ///                                const std::exception& message, const char* assertion);
    301150///   \endcode
    302 ///   The name of the functions should be defined as the \c
     151///   The name of the function should be defined as the \c
    303152///   LEMON_CUSTOM_ASSERT_HANDLER macro name.
    304153///   \code
    305154///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
    306155///   \endcode
    307 ///   Whenever an assertion is occured, one of the custom assertion
    308 ///   handlers is called with appropiate parameters.
     156///   Whenever an assertion is occured, the custom assertion
     157///   handler is called with appropiate parameters.
    309158///
    310159/// The assertion mode can also be changed within one compilation unit.
     
    316165    LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
    317166                         LEMON_FUNCTION_NAME,                           \
    318                          msg, #exp), 0)))
    319 
     167                         ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
    320168
    321169/// \ingroup exceptions
     
    328176///   LEMON_ASSERT(false, msg);
    329177/// \endcode
     178///
     179/// \see LEMON_ASSERT
    330180#  define LEMON_FIXME(msg)                                              \
    331        (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,   \
    332                              "FIXME: " msg, static_cast<const char*>(0)))
     181  (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,        \
     182                        ::lemon::_assert_bits::cstringify(msg),         \
     183                        static_cast<const char*>(0)))
     184
     185/// \ingroup exceptions
     186///
     187/// \brief Macro for internal assertions
     188///
     189/// Macro for internal assertions, it is used in the library to check
     190/// the consistency of results of algorithms, several pre- and
     191/// postconditions and invariants. The checking is disabled by
     192/// default, but it can be turned on with the macro \c
     193/// LEMON_ENABLE_DEBUG.
     194/// \code
     195/// #define LEMON_ENABLE_DEBUG
     196/// \endcode
     197/// or with compilation parameters:
     198/// \code
     199/// g++ -DLEMON_ENABLE_DEBUG
     200/// make CXXFLAGS='-DLEMON_ENABLE_DEBUG'
     201/// \endcode
     202///
     203/// This macro works like the \c LEMON_ASSERT macro, therefore the
     204/// current behaviour depends on the settings of \c LEMON_ASSERT
     205/// macro.
     206///
     207/// \see LEMON_ASSERT
     208#  define LEMON_DEBUG(exp, msg)                                         \
     209  (static_cast<void> (!!(exp) ? 0 : (                                   \
     210    LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
     211                         LEMON_FUNCTION_NAME,                           \
     212                         ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
    333213
    334214#else
     
    337217#    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
    338218#    define LEMON_FIXME(msg) (static_cast<void>(0))
     219#    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
    339220#  else
    340 #    define LEMON_ASSERT(exp, msg)                 \
    341        (static_cast<void> (!!(exp) ? 0 : (         \
    342          LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
    343                               LEMON_FUNCTION_NAME, \
    344                               msg, #exp), 0)))
    345 #    define LEMON_FIXME(msg) \
     221#    define LEMON_ASSERT(exp, msg)                                      \
     222       (static_cast<void> (!!(exp) ? 0 : (                              \
     223        LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
     224                             LEMON_FUNCTION_NAME,                       \
     225                             ::lemon::_assert_bits::cstringify(msg),    \
     226                             #exp), 0)))
     227#    define LEMON_FIXME(msg)                                            \
    346228       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,   \
    347                              "FIXME: " msg,  static_cast<const char*>(0)))
     229                             ::lemon::_assert_bits::cstringify(msg),    \
     230                             static_cast<const char*>(0)))
     231
     232#    if LEMON_ENABLE_DEBUG
     233#      define LEMON_DEBUG(exp, msg)
     234         (static_cast<void> (!!(exp) ? 0 : (         \
     235           LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
     236                                LEMON_FUNCTION_NAME, \
     237                                ::lemon::_assert_bits::cstringify(msg), \
     238                                #exp), 0)))
     239#    else
     240#      define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
     241#    endif
    348242#  endif
    349243
    350244#endif
    351245
    352 
     246#ifdef DOXYGEN
     247
     248
     249#else
     250
     251
     252#endif
     253
     254
  • test/error_test.cc

    r108 r118  
    4040}
    4141
    42 void no_assertion_exception_disable() {
    43   LEMON_ASSERT(true, Exception());
    44 }
    45 
    4642void assertion_text_disable() {
    4743  LEMON_ASSERT(false, "This is a fault message");
    48 }
    49 
    50 void assertion_exception_disable() {
    51   LEMON_ASSERT(false, Exception());
    5244}
    5345
     
    5850void check_assertion_disable() {
    5951  no_assertion_text_disable();
    60   no_assertion_exception_disable();
    61   assertion_exception_disable();
    6252  assertion_text_disable();
    6353  fixme_disable();
    6454}
    6555#undef LEMON_DISABLE_ASSERTS
    66 
    67 
    68 #define LEMON_ASSERT_ERROR
    69 #include <lemon/assert.h>
    70 
    71 void no_assertion_text_error() {
    72   LEMON_ASSERT(true, "This is a fault message");
    73 }
    74 
    75 void no_assertion_exception_error() {
    76   LEMON_ASSERT(true, Exception());
    77 }
    78 
    79 void assertion_text_error() {
    80   LEMON_ASSERT(false, "This is a fault message");
    81 }
    82 
    83 void assertion_exception_error() {
    84   LEMON_ASSERT(false, Exception());
    85 }
    86 
    87 void fixme_error() {
    88   LEMON_FIXME("fixme_error() is fixme!");
    89 }
    90 
    91 void check_assertion_error() {
    92   no_assertion_text_error();
    93   no_assertion_exception_error();
    94   try {
    95     assertion_exception_error();
    96     check(false, "Assertion error");
    97   } catch (const AssertionFailedError& e) {
    98   }
    99 
    100   try {
    101     assertion_text_error();
    102     check(false, "Assertion error");
    103   } catch (const AssertionFailedError& e) {
    104   }
    105 
    106   try {
    107     fixme_error();
    108     check(false, "Assertion error");
    109   } catch (const AssertionFailedError& e) {
    110   }
    111 }
    112 #undef LEMON_ASSERT_ERROR
    113 
    114 #define LEMON_ASSERT_EXCEPTION
    115 #include <lemon/assert.h>
    116 
    117 void no_assertion_text_exception() {
    118   LEMON_ASSERT(true, "This is a fault message");
    119 }
    120 
    121 void no_assertion_exception_exception() {
    122   LEMON_ASSERT(true, Exception());
    123 }
    124 
    125 void assertion_text_exception() {
    126   LEMON_ASSERT(false, "This is a fault message");
    127 }
    128 
    129 void assertion_exception_exception() {
    130   LEMON_ASSERT(false, Exception());
    131 }
    132 
    133 void fixme_exception() {
    134   LEMON_FIXME("fixme_exception() is fixme!");
    135 }
    136 
    137 void check_assertion_exception() {
    138   no_assertion_text_exception();
    139   no_assertion_exception_exception();
    140   try {
    141     assertion_exception_exception();
    142     check(false, "Assertion error");
    143   } catch (const Exception& e) {
    144   }
    145 
    146   try {
    147     assertion_text_exception();
    148     check(false, "Assertion error");
    149   } catch (const AssertionFailedError& e) {
    150   }
    151 
    152   try {
    153     assertion_text_exception();
    154     check(false, "Assertion error");
    155   } catch (const AssertionFailedError& e) {
    156   }
    157 
    158   try {
    159     fixme_exception();
    160     check(false, "Assertion error");
    161   } catch (const AssertionFailedError& e) {
    162   }
    163 }
    164 #undef LEMON_ASSERT_EXCEPTION
    165 
    166 #define LEMON_ASSERT_LOG
    167 
    168 #include <lemon/assert.h>
    169 
    170 void no_assertion_text_log() {
    171   LEMON_ASSERT(true, "This is a fault message");
    172 }
    173 
    174 void no_assertion_exception_log() {
    175   LEMON_ASSERT(true, Exception());
    176 }
    177 
    178 void assertion_text_log() {
    179   LEMON_ASSERT(false, "This is a fault message");
    180 }
    181 
    182 void assertion_exception_log() {
    183   LEMON_ASSERT(false, Exception());
    184 }
    185 
    186 void fixme_log() {
    187   LEMON_FIXME("fixme_log() is fixme!");
    188 }
    189 
    190 void check_assertion_log() {
    191   no_assertion_text_log();
    192   no_assertion_exception_log();
    193   std::cerr << "The next 3 failure messages are expected: " << std::endl;
    194   assertion_exception_log();
    195   assertion_text_log();
    196   fixme_log();
    197   std::cerr << "End of expected error messages" << std::endl;
    198 }
    199 #undef LEMON_ASSERT_LOG
    20056
    20157#define LEMON_ASSERT_CUSTOM
     
    20763}
    20864
    209 void my_assert_handler(const char*, int, const char*,
    210                        const std::exception&, const char*) {
    211   ++cnt;
    212 }
    213 
    214 void my_assert_handler(const char*, int, const char*,
    215                        const std::string&, const char*) {
    216   ++cnt;
    217 }
    218 
    219 
    22065#define LEMON_CUSTOM_ASSERT_HANDLER my_assert_handler
    22166#include <lemon/assert.h>
     
    22570}
    22671
    227 void no_assertion_exception_custom() {
    228   LEMON_ASSERT(true, Exception());
    229 }
    230 
    23172void assertion_text_custom() {
    23273  LEMON_ASSERT(false, "This is a fault message");
    233 }
    234 
    235 void assertion_exception_custom() {
    236   LEMON_ASSERT(false, Exception());
    23774}
    23875
     
    24380void check_assertion_custom() {
    24481  no_assertion_text_custom();
    245   no_assertion_exception_custom();
    246   assertion_exception_custom();
    24782  assertion_text_custom();
    24883  fixme_custom();
    249   check(cnt == 3, "The custom assert handler does not work");
     84  check(cnt == 2, "The custom assert handler does not work");
    25085}
    25186
     
    25590int main() {
    25691  check_assertion_disable();
    257   check_assertion_error();
    258   check_assertion_exception();
    259   check_assertion_log();
    26092  check_assertion_custom();
    26193
Note: See TracChangeset for help on using the changeset viewer.