Changeset 118:407c08a0eae9 in lemon-main
- Timestamp:
- 04/11/08 16:20:54 (17 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
lemon/assert.h
r112 r118 27 27 28 28 namespace lemon { 29 30 /// @{31 32 ///\e33 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 ///\e44 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 ///\e50 const char* assertion() const { return _assertion; }51 ///\e52 const char* message() const { return _message; }53 ///\e54 const char* file() const { return _file; }55 ///\e56 const char* function() const { return _function; }57 ///\e58 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 }94 29 95 30 inline void assert_fail_log(const char *file, int line, const char *function, … … 105 40 } 106 41 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 122 42 inline void assert_fail_abort(const char *file, int line, 123 43 const char *function, const char* message, … … 128 48 } 129 49 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 } 137 60 } 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 189 61 } 62 190 63 #endif // LEMON_ASSERT_H 191 64 192 65 #undef LEMON_ASSERT 193 66 #undef LEMON_FIXME 67 #undef LEMON_DEBUG 194 68 195 69 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ 196 70 (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ 197 (defined(LEMON_ASSERT_ERROR) ? 1 : 0) + \198 (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) + \199 71 (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1 200 72 #error "LEMON assertion system is not set properly" … … 203 75 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ 204 76 (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ 205 (defined(LEMON_ASSERT_ERROR) ? 1 : 0) + \206 (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) + \207 77 (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \ 208 78 defined(LEMON_ENABLE_ASSERTS)) && \ 209 defined(LEMON_DISABLE_ASSERTS) 79 (defined(LEMON_DISABLE_ASSERTS) || \ 80 defined(NDEBUG)) 210 81 #error "LEMON assertion system is not set properly" 211 82 #endif … … 218 89 # undef LEMON_ASSERT_HANDLER 219 90 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort 220 #elif defined LEMON_ASSERT_ERROR221 # undef LEMON_ASSERT_HANDLER222 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error223 #elif defined LEMON_ASSERT_EXCEPTION224 # undef LEMON_ASSERT_HANDLER225 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception226 91 #elif defined LEMON_ASSERT_CUSTOM 227 92 # undef LEMON_ASSERT_HANDLER … … 230 95 # endif 231 96 # 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 234 102 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort 235 #else 236 # undef LEMON_ASSERT_HANDLER 237 #endif 238 103 #endif 239 104 240 105 #ifndef LEMON_FUNCTION_NAME … … 248 113 /// \brief Macro for assertion with customizable message 249 114 /// 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 262 126 /// \endcode 263 127 /// or with compilation parameters: 264 128 /// \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. 268 133 /// 269 134 /// The LEMON assertion system has a wide range of customization … … 275 140 /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log 276 141 /// 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. 291 145 /// - \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. 294 147 /// \code 295 148 /// void custom_assert_handler(const char* file, int line, const char* function, 296 149 /// 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);301 150 /// \endcode 302 /// The name of the function sshould be defined as the \c151 /// The name of the function should be defined as the \c 303 152 /// LEMON_CUSTOM_ASSERT_HANDLER macro name. 304 153 /// \code 305 154 /// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler 306 155 /// \endcode 307 /// Whenever an assertion is occured, one ofthe custom assertion308 /// handler sis called with appropiate parameters.156 /// Whenever an assertion is occured, the custom assertion 157 /// handler is called with appropiate parameters. 309 158 /// 310 159 /// The assertion mode can also be changed within one compilation unit. … … 316 165 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ 317 166 LEMON_FUNCTION_NAME, \ 318 msg, #exp), 0))) 319 167 ::lemon::_assert_bits::cstringify(msg), #exp), 0))) 320 168 321 169 /// \ingroup exceptions … … 328 176 /// LEMON_ASSERT(false, msg); 329 177 /// \endcode 178 /// 179 /// \see LEMON_ASSERT 330 180 # 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))) 333 213 334 214 #else … … 337 217 # define LEMON_ASSERT(exp, msg) (static_cast<void>(0)) 338 218 # define LEMON_FIXME(msg) (static_cast<void>(0)) 219 # define LEMON_DEBUG(exp, msg) (static_cast<void>(0)) 339 220 # 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) \ 346 228 (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 348 242 # endif 349 243 350 244 #endif 351 245 352 246 #ifdef DOXYGEN 247 248 249 #else 250 251 252 #endif 253 254 -
test/error_test.cc
r108 r118 40 40 } 41 41 42 void no_assertion_exception_disable() {43 LEMON_ASSERT(true, Exception());44 }45 46 42 void assertion_text_disable() { 47 43 LEMON_ASSERT(false, "This is a fault message"); 48 }49 50 void assertion_exception_disable() {51 LEMON_ASSERT(false, Exception());52 44 } 53 45 … … 58 50 void check_assertion_disable() { 59 51 no_assertion_text_disable(); 60 no_assertion_exception_disable();61 assertion_exception_disable();62 52 assertion_text_disable(); 63 53 fixme_disable(); 64 54 } 65 55 #undef LEMON_DISABLE_ASSERTS 66 67 68 #define LEMON_ASSERT_ERROR69 #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_ERROR113 114 #define LEMON_ASSERT_EXCEPTION115 #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_EXCEPTION165 166 #define LEMON_ASSERT_LOG167 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_LOG200 56 201 57 #define LEMON_ASSERT_CUSTOM … … 207 63 } 208 64 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 220 65 #define LEMON_CUSTOM_ASSERT_HANDLER my_assert_handler 221 66 #include <lemon/assert.h> … … 225 70 } 226 71 227 void no_assertion_exception_custom() {228 LEMON_ASSERT(true, Exception());229 }230 231 72 void assertion_text_custom() { 232 73 LEMON_ASSERT(false, "This is a fault message"); 233 }234 235 void assertion_exception_custom() {236 LEMON_ASSERT(false, Exception());237 74 } 238 75 … … 243 80 void check_assertion_custom() { 244 81 no_assertion_text_custom(); 245 no_assertion_exception_custom();246 assertion_exception_custom();247 82 assertion_text_custom(); 248 83 fixme_custom(); 249 check(cnt == 3, "The custom assert handler does not work");84 check(cnt == 2, "The custom assert handler does not work"); 250 85 } 251 86 … … 255 90 int main() { 256 91 check_assertion_disable(); 257 check_assertion_error();258 check_assertion_exception();259 check_assertion_log();260 92 check_assertion_custom(); 261 93
Note: See TracChangeset
for help on using the changeset viewer.