source: branches/stable/CORE/arb_assert.h

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