source: tags/ms_r16q2/CORE/arb_assert.h

Last change on this file was 14833, checked in by westram, 8 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 KB
Line 
1/*  ====================================================================
2
3    File      : arb_assert.h
4    Purpose   : Global assert macro
5
6
7  Coded by Ralf Westram (coder@reallysoft.de) in August 2002
8  Copyright Department of Microbiology (Technical University Munich)
9
10  Visit our web site at: http://www.arb-home.de/
11
12
13  ==================================================================== */
14
15#ifndef ARB_ASSERT_H
16#define ARB_ASSERT_H
17
18// [WhyIncludeHere]
19// need to include all headers needed for unit-tests here [sic]
20// if only included inside test_global.h, developing with active unit-tests
21// will always break non-unit-test-builds.
22
23#ifndef _STDARG_H
24#include <stdarg.h>
25#endif
26#ifndef _STDIO_H
27#include <stdio.h>
28#endif
29#ifndef _STDLIB_H
30#include <stdlib.h>
31#endif
32#ifndef _ERRNO_H
33#include <errno.h>
34#endif
35#ifndef _STRING_H
36#include <string.h>
37#endif
38#ifndef _SIGNAL_H
39#include <signal.h>
40#endif
41
42/* ------------------------------------------------------------
43 * Include arb_simple_assert.h to avoid dependency from CORE library!
44 * ------------------------------------------------------------
45 * available assertion flavors:
46 *
47 * ASSERT_CRASH                 if assert fails debugger stops at assert macro
48 * ASSERT_BACKTRACE_AND_CRASH   like ASSERT_CRASH - with backtrace
49 * ASSERT_ERROR                 assert prints an error and ARB exits
50 * ASSERT_PRINT                 assert prints a message (anyway) and ARB continues
51 * ASSERT_NONE                  assertions inactive
52 *
53 * ------------------------------------------------------------ */
54
55// check correct definition of DEBUG/NDEBUG
56#ifndef NDEBUG
57# ifndef DEBUG
58#  error Neither DEBUG nor NDEBUG is defined!
59# endif
60#else
61# ifdef DEBUG
62#  error Both DEBUG and NDEBUG are defined - only one should be!
63# endif
64#endif
65
66#ifdef arb_assert
67#error arb_assert already defined
68#endif
69
70// --------------------------------------------------------------------
71// use exactly ONE of the following ASSERT_xxx defines in each section:
72#if defined(DEBUG) && !defined(DEVEL_RELEASE)
73
74// assert that raises SIGSEGV (recommended for DEBUG version!)
75// # define ASSERT_CRASH
76// # define ASSERT_BACKTRACE_AND_CRASH
77// # define ASSERT_STOP
78# define ASSERT_BACKTRACE_AND_STOP
79// test if a bug has to do with assertion code
80// # define ASSERT_NONE
81
82#else
83
84// no assert (recommended for final version!)
85# define ASSERT_NONE
86// assert as error in final version (allows basic debugging of NDEBUG version)
87// # define ASSERT_ERROR
88// assert as print in final version (allows basic debugging of NDEBUG version)
89// # define ASSERT_PRINT
90
91#endif
92
93// ------------------------------------------------------------
94
95#if defined(__cplusplus)
96inline void provoke_core_dump() {
97    raise(SIGSEGV);
98}
99#else // !defined(__cplusplus)
100#define provoke_core_dump() do { *(int*)0 = 0; } while(0)
101#endif
102
103// ------------------------------------------------------------
104
105#if defined(SIMPLE_ARB_ASSERT)
106
107// code here is independent from CORE library and glib
108
109#define ARB_SIGSEGV(backtrace) do {     \
110        provoke_core_dump();            \
111    } while (0)
112
113#define ARB_STOP(backtrace) ARB_SIGSEGV(backtrace)
114
115#ifndef ASSERT_NONE
116# define arb_assert(cond)                                               \
117    do {                                                                \
118        if (!(cond)) {                                                  \
119            fprintf(stderr, "Assertion '%s' failed in '%s' #%i\n",      \
120                    #cond, __FILE__, __LINE__);                         \
121            provoke_core_dump();                                        \
122        }                                                               \
123    } while (0)
124#endif
125
126
127// ------------------------------------------------------------
128
129#else // !SIMPLE_ARB_ASSERT
130
131/* Provoke a SIGSEGV (which will stop the debugger or terminated the application)
132 * Do backtrace manually here and uninstall SIGSEGV-handler
133 * (done because automatic backtrace on SIGSEGV lacks name of current function)
134 */
135
136#ifndef ARB_CORE_H
137#include <arb_core.h>
138#endif
139#ifndef __G_LIB_H__
140#include <glib.h>
141#endif
142
143#define stop_in_debugger() G_BREAKPOINT()
144
145#define ARB_SIGSEGV(backtrace) do {                             \
146        if (backtrace) GBK_dump_backtrace(NULL, "ARB_SIGSEGV"); \
147        GBK_install_SIGSEGV_handler(false);                     \
148        provoke_core_dump();                                    \
149    } while (0)
150
151#define ARB_STOP(backtrace)                                     \
152    do {                                                        \
153        if (backtrace) GBK_dump_backtrace(NULL, "ARB_STOP");    \
154        stop_in_debugger();                                     \
155    } while(0)
156
157# define arb_assert_crash(cond)         \
158    do {                                \
159        if (!(cond)) ARB_SIGSEGV(0);    \
160    } while (0)
161
162# define arb_assert_stop(cond)          \
163    do {                                \
164        if (!(cond)) ARB_STOP(0);       \
165    } while (0)
166
167# define arb_assert_backtrace_and_crash(cond)                           \
168    do {                                                                \
169        if (!(cond)) {                                                  \
170            fputs(GBK_assert_msg(#cond, __FILE__, __LINE__), stderr);   \
171            fflush(stderr);                                             \
172            ARB_SIGSEGV(1);                                             \
173        }                                                               \
174    } while (0)
175
176# define arb_assert_backtrace_and_stop(cond)                            \
177    do {                                                                \
178        if (!(cond)) {                                                  \
179            fputs(GBK_assert_msg(#cond, __FILE__, __LINE__), stderr);   \
180            fflush(stderr);                                             \
181            ARB_STOP(1);                                                \
182        }                                                               \
183    } while (0)
184
185#ifdef ASSERT_CRASH
186# define arb_assert(cond) arb_assert_crash(cond)
187#endif
188#ifdef ASSERT_STOP
189# define arb_assert(cond) arb_assert_stop(cond)
190#endif
191#ifdef ASSERT_BACKTRACE_AND_CRASH
192# define arb_assert(cond) arb_assert_backtrace_and_crash(cond)
193#endif
194#ifdef ASSERT_BACKTRACE_AND_STOP
195# define arb_assert(cond) arb_assert_backtrace_and_stop(cond)
196#endif
197#ifdef ASSERT_ERROR
198# define arb_assert(cond) assert_or_exit(cond)
199#endif
200
201#ifdef ASSERT_PRINT
202# define arb_assert(cond)                                               \
203    do {                                                                \
204        fprintf(stderr, "at %s #%i\n", __FILE__, __LINE__);             \
205        if (!(cond)) fprintf(stderr, "assertion '%s' failed!\n", #cond); \
206        fflush(stderr);                                                 \
207    } while (0)
208#endif
209
210#endif // SIMPLE_ARB_ASSERT
211
212// ------------------------------------------------------------
213
214#ifdef ASSERT_NONE
215# define arb_assert(cond)
216#else
217# define ASSERTION_USED
218#endif
219
220#undef ASSERT_CRASH
221#undef ASSERT_BACKTRACE_AND_CRASH
222#undef ASSERT_STOP
223#undef ASSERT_BACKTRACE_AND_STOP
224#undef ASSERT_ERROR
225#undef ASSERT_PRINT
226#undef ASSERT_NONE
227
228#ifndef arb_assert
229# error arb_assert has not been defined -- check ASSERT_xxx definitions
230#endif
231
232#if !defined(SIMPLE_ARB_ASSERT)
233#define assert_or_exit(cond)                                            \
234    do {                                                                \
235        if (!(cond)) {                                                  \
236            GBK_terminate(GBK_assert_msg(#cond, __FILE__, __LINE__));   \
237        }                                                               \
238    } while (0)
239#endif // SIMPLE_ARB_ASSERT
240
241// ------------------------------------------------------------
242
243#ifdef UNIT_TESTS // UT_DIFF
244#ifndef TEST_GLOBAL_H
245#include <test_global.h> // overrides arb_assert()!
246#endif
247#else
248#define RUNNING_TEST() false
249#endif
250
251// ------------------------------------------------------------
252// logical operators (mostly used for assertions)
253
254// Note: 'conclusion' is not evaluated if 'hypothesis' is wrong!
255#define implicated(hypothesis,conclusion) (!(hypothesis) || !!(conclusion))
256
257#ifdef __cplusplus
258inline bool correlated(bool hypo1, bool hypo2) { return implicated(hypo1, hypo2) == implicated(hypo2, hypo1); } // equivalence!
259inline bool contradicted(bool hypo1, bool hypo2) { return !correlated(hypo1, hypo2); } // non-equivalence!
260#endif
261
262// ------------------------------------------------------------
263// use the following macros for parameters etc. only appearing in one version
264
265#ifdef DEBUG
266# define IF_DEBUG(x) x
267# define IF_NDEBUG(x)
268#else
269# define IF_DEBUG(x)
270# define IF_NDEBUG(x) x
271#endif
272
273#ifdef ASSERTION_USED
274# define IF_ASSERTION_USED(x) x
275#else
276# define IF_ASSERTION_USED(x)
277#endif
278
279// ------------------------------------------------------------
280// Assert specific result in DEBUG and silence __ATTR__USERESULT warnings in NDEBUG.
281//
282// The value 'Expected' (or 'Limit') should be side-effect-free (it is only executed in DEBUG mode).
283// The given 'Expr' is evaluated under all conditions!
284//
285// Important note:
286//      When you swap 'Expected' and 'Expr' by mistake,
287//      code working in DEBUG, may suddenly stop working in NDEBUG!
288
289#ifdef ASSERTION_USED
290
291# define ASSERT_RESULT(Type, Expected, Expr) do {       \
292        Type value = (Expr);                            \
293        arb_assert(value == (Expected));                \
294    } while (0)
295
296# define ASSERT_RESULT_PREDICATE(Pred, Expr) do {       \
297        arb_assert(Pred(Expr));                         \
298    } while (0)
299
300#else
301
302template <typename T> inline void dont_warn_unused_result(T) {}
303
304# define ASSERT_RESULT(Type, Expected, Expr) do {       \
305        dont_warn_unused_result<Type>(Expr);            \
306    } while(0)
307
308# define ASSERT_RESULT_PREDICATE(Pred, Expr) do {       \
309        (void)Expr;                                     \
310    } while(0)
311
312#endif
313
314#define ASSERT_NULL_RESULT(ptrExpr) ASSERT_RESULT(const void*, NULL, ptrExpr)
315#define ASSERT_NO_ERROR(errorExpr)  ASSERT_RESULT(GB_ERROR, NULL, errorExpr)
316
317#define ASSERT_TRUE(boolExpr)  ASSERT_RESULT(bool, true, boolExpr)
318#define ASSERT_FALSE(boolExpr) ASSERT_RESULT(bool, false, boolExpr)
319
320// ------------------------------------------------------------
321
322#if defined(ASSERTION_USED)
323inline bool knownNonNull(const void *nonnull) { // use to suppress -Wnonnull-compare (only allowed in assertions)
324    return nonnull != NULL;
325}
326#endif
327
328// ------------------------------------------------------------
329// UNCOVERED is used to document/test missing test coverage
330// see ../INCLUDE/test_global.h@UNCOVERED
331
332#ifndef UNCOVERED
333#define UNCOVERED()
334#endif
335
336// ------------------------------------------------------------
337
338#ifdef DEVEL_RELEASE
339# ifdef ASSERTION_USED
340#  error Assertions enabled in release
341# endif
342#endif
343
344// ------------------------------------------------------------
345
346#if !defined(SIMPLE_ARB_ASSERT)
347#ifndef ARB_CORE_H
348#include <arb_core.h>
349#endif
350#endif // SIMPLE_ARB_ASSERT
351
352#else
353#error arb_assert.h included twice
354#endif // ARB_ASSERT_H
355
Note: See TracBrowser for help on using the repository browser.