COIN-OR::LEMON - Graph Library

Ticket #28: assert_rework.hg

File assert_rework.hg, 19.1 KB (added by Balazs Dezso, 17 years ago)
Line 
1# HG changeset patch
2# User Balazs Dezso <deba@inf.elte.hu>
3# Date 1207923654 -7200
4# Node ID 407c08a0eae9616db100ccdda51e1babde3ce3a8
5# Parent  7b0ce9fb1169c533d2859b8d48bf8586d16fbc91
6Exception related solutions removed and new LEMON_DEBUG macro
7
8diff -r 7b0ce9fb1169 -r 407c08a0eae9 lemon/assert.h
9--- a/lemon/assert.h    Wed Apr 09 17:19:40 2008 +0100
10+++ b/lemon/assert.h    Fri Apr 11 16:20:54 2008 +0200
11@@ -27,71 +27,6 @@
12 
13 namespace lemon {
14 
15-  /// @{
16-
17-  ///\e
18-  class AssertionFailedError : public LogicError {
19-  protected:
20-    const char *_assertion;
21-    const char *_file;
22-    int _line;
23-    const char *_function;
24-    const char *_message;
25-
26-    mutable ExceptionMember<std::string> _message_holder;
27-  public:
28-    ///\e
29-    AssertionFailedError(const char *file, int line, const char *function,
30-                        const char *msg, const char *assertion = 0) :
31-      _assertion(assertion), _file(file), _line(line),
32-      _function(function), _message(msg) {}
33-
34-    ///\e
35-    const char* assertion() const { return _assertion; }
36-    ///\e
37-    const char* message() const { return _message; }
38-    ///\e
39-    const char* file() const { return _file; }
40-    ///\e
41-    const char* function() const { return _function; }
42-    ///\e
43-    int line() const { return _line; }
44-
45-
46-    virtual const char* what() const throw() {
47-      try {
48-       std::ostringstream ostr;
49-       ostr << _file << ":" << _line << ": ";
50-       if (_function)
51-         ostr << _function << ": ";
52-       ostr << _message;
53-       if (_assertion)
54-          ostr << " (assertion '" << _assertion << "' failed)";
55-       _message_holder.set(ostr.str());
56-       return ostr.str().c_str();
57-      }
58-      catch(...) {}
59-      if( _message_holder.valid() ) return _message_holder.get().c_str();
60-      return "lemon::AssertionFailedError";
61-    }
62-    virtual ~AssertionFailedError() throw() {}
63-  };
64-
65-
66-  inline void assert_fail_log(const char *file, int line,
67-                             const char *function,
68-                             const std::exception& exception,
69-                             const char *assertion)
70-  {
71-    std::cerr << file << ":" << line << ": ";
72-    if (function)
73-      std::cerr << function << ": ";
74-    std::cerr << exception.what();
75-    if (assertion)
76-      std::cerr << " (assertion '" << assertion << "' failed)";
77-    std::cerr << std::endl;
78-  }
79-
80   inline void assert_fail_log(const char *file, int line, const char *function,
81                              const char *message, const char *assertion)
82   {
83@@ -104,21 +39,6 @@ namespace lemon {
84     std::cerr << std::endl;
85   }
86 
87-  inline void assert_fail_log(const char *file, int line, const char *function,
88-                             const std::string& message, const char *assertion)
89-  {
90-    assert_fail_log(file, line, function, message.c_str(), assertion);
91-  }
92-
93-  inline void assert_fail_abort(const char *file, int line,
94-                               const char *function,
95-                               const std::exception& exception,
96-                               const char *assertion)
97-  {
98-    assert_fail_log(file, line, function, exception, assertion);
99-    std::abort();
100-  }
101-
102   inline void assert_fail_abort(const char *file, int line,
103                                const char *function, const char* message,
104                                const char *assertion)
105@@ -127,86 +47,37 @@ namespace lemon {
106     std::abort();
107   }
108 
109-  inline void assert_fail_abort(const char *file, int line,
110-                               const char *function,
111-                               const std::string& message,
112-                               const char *assertion)
113-  {
114-    assert_fail_log(file, line, function, message.c_str(), assertion);
115-    std::abort();
116+  namespace _assert_bits {
117+   
118+   
119+    inline const char* cstringify(const std::string& str) {
120+      return str.c_str();
121+    }
122+
123+    inline const char* cstringify(const char* str) {
124+      return str;
125+    }   
126   }
127+}
128 
129-  inline void assert_fail_error(const char *file, int line,
130-                                 const char *function,
131-                                 const std::exception& exception,
132-                                 const char *assertion)
133-  {
134-    throw AssertionFailedError(file, line, function,
135-                              exception.what(), assertion);
136-  }
137-
138-  inline void assert_fail_error(const char *file, int line,
139-                                 const char *function, const char *message,
140-                                 const char *assertion)
141-  {
142-    throw AssertionFailedError(file, line, function, message, assertion);
143-  }
144-
145-  inline void assert_fail_error(const char *file, int line,
146-                                 const char *function,
147-                                 const std::string& message,
148-                                 const char *assertion)
149-  {
150-    throw AssertionFailedError(file, line, function, message.c_str(), assertion);
151-  }
152-
153-  template <typename Exception>
154-  inline void assert_fail_exception(const char *, int, const char *,
155-                                   const Exception& exception,
156-                                   const char *, const std::exception* =
157-                                   static_cast<const Exception*>(0))
158-  {
159-    throw exception;
160-  }
161-
162-  inline void assert_fail_exception(const char *file, int line,
163-                                   const char *function, const char *message,
164-                                   const char *assertion)
165-  {
166-    throw AssertionFailedError(file, line, function, message, assertion);
167-  }
168-
169-  inline void assert_fail_exception(const char *file, int line,
170-                                   const char *function,
171-                                   const std::string& message,
172-                                   const char *assertion)
173-  {
174-    throw AssertionFailedError(file, line, function, message.c_str(), assertion);
175-  }
176-
177-/// @}
178-
179-}
180 #endif // LEMON_ASSERT_H
181 
182 #undef LEMON_ASSERT
183 #undef LEMON_FIXME
184+#undef LEMON_DEBUG
185 
186 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +              \
187   (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +              \
188-  (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +              \
189-  (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +          \
190   (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
191 #error "LEMON assertion system is not set properly"
192 #endif
193 
194 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +             \
195      (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +           \
196-     (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +           \
197-     (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +       \
198      (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||    \
199      defined(LEMON_ENABLE_ASSERTS)) &&                 \
200-  defined(LEMON_DISABLE_ASSERTS)
201+  (defined(LEMON_DISABLE_ASSERTS) ||                   \
202+   defined(NDEBUG))
203 #error "LEMON assertion system is not set properly"
204 #endif
205 
206@@ -217,25 +88,19 @@ namespace lemon {
207 #elif defined LEMON_ASSERT_ABORT
208 #  undef LEMON_ASSERT_HANDLER
209 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
210-#elif defined LEMON_ASSERT_ERROR
211-#  undef LEMON_ASSERT_HANDLER
212-#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error
213-#elif defined LEMON_ASSERT_EXCEPTION
214-#  undef LEMON_ASSERT_HANDLER
215-#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
216 #elif defined LEMON_ASSERT_CUSTOM
217 #  undef LEMON_ASSERT_HANDLER
218 #  ifndef LEMON_CUSTOM_ASSERT_HANDLER
219 #    error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
220 #  endif
221 #  define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
222-#elif defined LEMON_ENABLE_ASSERTS
223+#elif defined LEMON_DISABLE_ASSERTS
224 #  undef LEMON_ASSERT_HANDLER
225+#elif defined NDEBUG
226+#  undef LEMON_ASSERT_HANDLER
227+#else
228 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
229-#else
230-#  undef LEMON_ASSERT_HANDLER
231 #endif
232-
233 
234 #ifndef LEMON_FUNCTION_NAME
235 #  define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
236@@ -247,24 +112,24 @@ namespace lemon {
237 ///
238 /// \brief Macro for assertion with customizable message
239 ///
240-/// Macro for assertion with customizable message. 
241-/// \param exp An expression that must be convertible to \c bool.
242-/// If it is \c false, then an assertion is raised. The concrete
243-/// behaviour depends on the settings of the assertion system.
244-/// \param msg A <tt>const char*</tt>, a <tt>const std::string&</tt> or
245-/// a <tt>const std::exception&</tt> parameter, which can be used to
246-/// provide information about the circumstances of the failed assertion.
247+/// Macro for assertion with customizable message.  \param exp An
248+/// expression that must be convertible to \c bool.  If it is \c
249+/// false, then an assertion is raised. The concrete behaviour depends
250+/// on the settings of the assertion system.  \param msg A <tt>const
251+/// char*</tt> parameter, which can be used to provide information
252+/// about the circumstances of the failed assertion.
253 ///
254-/// The assertions are disabled in the default behaviour.
255-/// You can enable them with the following code:
256+/// The assertions are enabled in the default behaviour.
257+/// You can disable them with the following code:
258 /// \code
259-/// #define LEMON_ENABLE_ASSERTS
260+/// #define LEMON_DISABLE_ASSERTS
261 /// \endcode
262 /// or with compilation parameters:
263 /// \code
264-/// g++ -DLEMON_ENABLE_ASSERTS
265-/// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
266+/// g++ -DLEMON_DISABLE_ASSERTS
267+/// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
268 /// \endcode
269+/// The checking is also disabled when the standard macro \c NDEBUG is defined.
270 ///
271 /// The LEMON assertion system has a wide range of customization
272 /// properties. As a default behaviour the failed assertion prints a
273@@ -274,38 +139,22 @@ namespace lemon {
274 ///
275 /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log
276 ///   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.
291+/// - \c LEMON_ASSERT_ABORT This mode is similar to the \c
292+///   LEMON_ASSERT_LOG, but it aborts the program. It is the default
293+///   behaviour.
294 /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
295-///   functions. Three overloaded functions should be defined with the
296-///   following parameter lists:
297+///   function.
298 ///   \code
299 ///     void custom_assert_handler(const char* file, int line, const char* function,
300 ///                                const char* message, const char* assertion);
301-///     void custom_assert_handler(const char* file, int line, const char* function,
302-///                                const std::string& message, const char* assertion);
303-///     void custom_assert_handler(const char* file, int line, const char* function,
304-///                                const std::exception& message, const char* assertion);
305 ///   \endcode
306-///   The name of the functions should be defined as the \c
307+///   The name of the function should be defined as the \c
308 ///   LEMON_CUSTOM_ASSERT_HANDLER macro name.
309 ///   \code
310 ///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
311 ///   \endcode
312-///   Whenever an assertion is occured, one of the custom assertion
313-///   handlers is called with appropiate parameters.
314+///   Whenever an assertion is occured, the custom assertion
315+///   handler is called with appropiate parameters.
316 ///
317 /// The assertion mode can also be changed within one compilation unit.
318 /// If the macros are redefined with other settings and the
319@@ -315,8 +164,7 @@ namespace lemon {
320   (static_cast<void> (!!(exp) ? 0 : (                                  \
321     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                           \
322                         LEMON_FUNCTION_NAME,                           \
323-                        msg, #exp), 0)))
324-
325+                        ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
326 
327 /// \ingroup exceptions
328 ///
329@@ -327,26 +175,80 @@ namespace lemon {
330 /// \code
331 ///   LEMON_ASSERT(false, msg);
332 /// \endcode
333+///
334+/// \see LEMON_ASSERT
335 #  define LEMON_FIXME(msg)                                             \
336-       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,  \
337-                            "FIXME: " msg, static_cast<const char*>(0)))
338+  (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,       \
339+                       ::lemon::_assert_bits::cstringify(msg),         \
340+                       static_cast<const char*>(0)))
341+
342+/// \ingroup exceptions
343+///
344+/// \brief Macro for internal assertions
345+///
346+/// Macro for internal assertions, it is used in the library to check
347+/// the consistency of results of algorithms, several pre- and
348+/// postconditions and invariants. The checking is disabled by
349+/// default, but it can be turned on with the macro \c
350+/// LEMON_ENABLE_DEBUG.
351+/// \code
352+/// #define LEMON_ENABLE_DEBUG
353+/// \endcode
354+/// or with compilation parameters:
355+/// \code
356+/// g++ -DLEMON_ENABLE_DEBUG
357+/// make CXXFLAGS='-DLEMON_ENABLE_DEBUG'
358+/// \endcode
359+///
360+/// This macro works like the \c LEMON_ASSERT macro, therefore the
361+/// current behaviour depends on the settings of \c LEMON_ASSERT
362+/// macro.
363+///
364+/// \see LEMON_ASSERT
365+#  define LEMON_DEBUG(exp, msg)                                                \
366+  (static_cast<void> (!!(exp) ? 0 : (                                  \
367+    LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
368+                        LEMON_FUNCTION_NAME,                           \
369+                        ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
370 
371 #else
372 
373 #  ifndef LEMON_ASSERT_HANDLER
374 #    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
375 #    define LEMON_FIXME(msg) (static_cast<void>(0))
376+#    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
377 #  else
378-#    define LEMON_ASSERT(exp, msg)                 \
379-       (static_cast<void> (!!(exp) ? 0 : (         \
380-         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
381-                              LEMON_FUNCTION_NAME, \
382-                              msg, #exp), 0)))
383-#    define LEMON_FIXME(msg) \
384+#    define LEMON_ASSERT(exp, msg)                                     \
385+       (static_cast<void> (!!(exp) ? 0 : (                             \
386+        LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
387+                            LEMON_FUNCTION_NAME,                       \
388+                            ::lemon::_assert_bits::cstringify(msg),    \
389+                            #exp), 0)))
390+#    define LEMON_FIXME(msg)                                           \
391        (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,  \
392-                            "FIXME: " msg,  static_cast<const char*>(0)))
393+                            ::lemon::_assert_bits::cstringify(msg),    \
394+                            static_cast<const char*>(0)))
395+
396+#    if LEMON_ENABLE_DEBUG
397+#      define LEMON_DEBUG(exp, msg)
398+         (static_cast<void> (!!(exp) ? 0 : (         \
399+           LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
400+                                LEMON_FUNCTION_NAME, \
401+                               ::lemon::_assert_bits::cstringify(msg), \
402+                               #exp), 0)))
403+#    else
404+#      define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
405+#    endif
406 #  endif
407 
408 #endif
409 
410+#ifdef DOXYGEN
411 
412+
413+#else
414+
415+
416+#endif
417+
418+
419diff -r 7b0ce9fb1169 -r 407c08a0eae9 test/error_test.cc
420--- a/test/error_test.cc        Wed Apr 09 17:19:40 2008 +0100
421+++ b/test/error_test.cc        Fri Apr 11 16:20:54 2008 +0200
422@@ -39,16 +39,8 @@ void no_assertion_text_disable() {
423   LEMON_ASSERT(true, "This is a fault message");
424 }
425 
426-void no_assertion_exception_disable() {
427-  LEMON_ASSERT(true, Exception());
428-}
429-
430 void assertion_text_disable() {
431   LEMON_ASSERT(false, "This is a fault message");
432-}
433-
434-void assertion_exception_disable() {
435-  LEMON_ASSERT(false, Exception());
436 }
437 
438 void fixme_disable() {
439@@ -57,146 +49,10 @@ void fixme_disable() {
440 
441 void check_assertion_disable() {
442   no_assertion_text_disable();
443-  no_assertion_exception_disable();
444-  assertion_exception_disable();
445   assertion_text_disable();
446   fixme_disable();
447 }
448 #undef LEMON_DISABLE_ASSERTS
449-
450-
451-#define LEMON_ASSERT_ERROR
452-#include <lemon/assert.h>
453-
454-void no_assertion_text_error() {
455-  LEMON_ASSERT(true, "This is a fault message");
456-}
457-
458-void no_assertion_exception_error() {
459-  LEMON_ASSERT(true, Exception());
460-}
461-
462-void assertion_text_error() {
463-  LEMON_ASSERT(false, "This is a fault message");
464-}
465-
466-void assertion_exception_error() {
467-  LEMON_ASSERT(false, Exception());
468-}
469-
470-void fixme_error() {
471-  LEMON_FIXME("fixme_error() is fixme!");
472-}
473-
474-void check_assertion_error() {
475-  no_assertion_text_error();
476-  no_assertion_exception_error();
477-  try {
478-    assertion_exception_error();
479-    check(false, "Assertion error");
480-  } catch (const AssertionFailedError& e) {
481-  }
482-
483-  try {
484-    assertion_text_error();
485-    check(false, "Assertion error");
486-  } catch (const AssertionFailedError& e) {
487-  }
488-
489-  try {
490-    fixme_error();
491-    check(false, "Assertion error");
492-  } catch (const AssertionFailedError& e) {
493-  }
494-}
495-#undef LEMON_ASSERT_ERROR
496-
497-#define LEMON_ASSERT_EXCEPTION
498-#include <lemon/assert.h>
499-
500-void no_assertion_text_exception() {
501-  LEMON_ASSERT(true, "This is a fault message");
502-}
503-
504-void no_assertion_exception_exception() {
505-  LEMON_ASSERT(true, Exception());
506-}
507-
508-void assertion_text_exception() {
509-  LEMON_ASSERT(false, "This is a fault message");
510-}
511-
512-void assertion_exception_exception() {
513-  LEMON_ASSERT(false, Exception());
514-}
515-
516-void fixme_exception() {
517-  LEMON_FIXME("fixme_exception() is fixme!");
518-}
519-
520-void check_assertion_exception() {
521-  no_assertion_text_exception();
522-  no_assertion_exception_exception();
523-  try {
524-    assertion_exception_exception();
525-    check(false, "Assertion error");
526-  } catch (const Exception& e) {
527-  }
528-
529-  try {
530-    assertion_text_exception();
531-    check(false, "Assertion error");
532-  } catch (const AssertionFailedError& e) {
533-  }
534-
535-  try {
536-    assertion_text_exception();
537-    check(false, "Assertion error");
538-  } catch (const AssertionFailedError& e) {
539-  }
540-
541-  try {
542-    fixme_exception();
543-    check(false, "Assertion error");
544-  } catch (const AssertionFailedError& e) {
545-  }
546-}
547-#undef LEMON_ASSERT_EXCEPTION
548-
549-#define LEMON_ASSERT_LOG
550-
551-#include <lemon/assert.h>
552-
553-void no_assertion_text_log() {
554-  LEMON_ASSERT(true, "This is a fault message");
555-}
556-
557-void no_assertion_exception_log() {
558-  LEMON_ASSERT(true, Exception());
559-}
560-
561-void assertion_text_log() {
562-  LEMON_ASSERT(false, "This is a fault message");
563-}
564-
565-void assertion_exception_log() {
566-  LEMON_ASSERT(false, Exception());
567-}
568-
569-void fixme_log() {
570-  LEMON_FIXME("fixme_log() is fixme!");
571-}
572-
573-void check_assertion_log() {
574-  no_assertion_text_log();
575-  no_assertion_exception_log();
576-  std::cerr << "The next 3 failure messages are expected: " << std::endl;
577-  assertion_exception_log();
578-  assertion_text_log();
579-  fixme_log();
580-  std::cerr << "End of expected error messages" << std::endl;
581-}
582-#undef LEMON_ASSERT_LOG
583 
584 #define LEMON_ASSERT_CUSTOM
585 
586@@ -206,17 +62,6 @@ void my_assert_handler(const char*, int,
587   ++cnt;
588 }
589 
590-void my_assert_handler(const char*, int, const char*,
591-                      const std::exception&, const char*) {
592-  ++cnt;
593-}
594-
595-void my_assert_handler(const char*, int, const char*,
596-                      const std::string&, const char*) {
597-  ++cnt;
598-}
599-
600-
601 #define LEMON_CUSTOM_ASSERT_HANDLER my_assert_handler
602 #include <lemon/assert.h>
603 
604@@ -224,16 +69,8 @@ void no_assertion_text_custom() {
605   LEMON_ASSERT(true, "This is a fault message");
606 }
607 
608-void no_assertion_exception_custom() {
609-  LEMON_ASSERT(true, Exception());
610-}
611-
612 void assertion_text_custom() {
613   LEMON_ASSERT(false, "This is a fault message");
614-}
615-
616-void assertion_exception_custom() {
617-  LEMON_ASSERT(false, Exception());
618 }
619 
620 void fixme_custom() {
621@@ -242,11 +79,9 @@ void fixme_custom() {
622 
623 void check_assertion_custom() {
624   no_assertion_text_custom();
625-  no_assertion_exception_custom();
626-  assertion_exception_custom();
627   assertion_text_custom();
628   fixme_custom();
629-  check(cnt == 3, "The custom assert handler does not work");
630+  check(cnt == 2, "The custom assert handler does not work");
631 }
632 
633 #undef LEMON_ASSERT_CUSTOM
634@@ -254,9 +89,6 @@ void check_assertion_custom() {
635 
636 int main() {
637   check_assertion_disable();
638-  check_assertion_error();
639-  check_assertion_exception();
640-  check_assertion_log();
641   check_assertion_custom();
642 
643   return 0;