Flow123d  JS_before_hm-887-g601087d
asserts.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file asserts.hh
15  * @brief Definitions of ASSERTS.
16  */
17 
18 #ifndef ASSERTS_HH
19 #define ASSERTS_HH
20 
21 #include <iostream>
22 #include <string>
23 #include <vector> // for vector
24 #include "system/exceptions.hh"
25 #include "system/fmt/posix.h"
26 
27 namespace feal {
28 
29 /**
30  * @brief Helper class.
31  *
32  * Stores data of assert and allow throws exception.
33  */
34 class Exc_assert : public ExceptionBase {
35  friend class Assert;
36 public:
37  // Default constructor
38  Exc_assert();
39 
40  /// Destructor.
42 
43  /// Print formatted assert message.
44  void print_info(std::ostringstream &out) const override;
45 
46 protected:
47  /// Override @p ExceptionBase::what_type_msg()
48  std::string what_type_msg() const override;
49 
50  /// Override @p ExceptionBase::form_message()
51  std::ostringstream &form_message(std::ostringstream &) const override;
52 
53  std::string expression_; ///< Assertion expression
54  std::string file_name_; ///< Actual file.
55  std::string function_; ///< Actual function.
56  int line_; ///< Actual line.
57  std::vector< std::string > current_val_; ///< Formated strings of names and values of given variables.
58  std::string what_type_msg_; ///< String representation of message type (Program error, Warning, ...)
59 };
60 
61 /**
62  * @brief Class defining debugging messages.
63  *
64  * Allows define assert, warning etc. either only for debug mode or for release mode also.
65  *
66  * Definition of asserts is designed using macros FEAL_ASSERT and FEAL_ASSERT_DBG. First macro
67  * is used for both modes, second is only for debug. Definition allows to printout given
68  * variables too. For simplifying are designed shorter names of macros ASSERT and ASSERT_DBG,
69  * these names can be used if thea aren't in conflicts with external libraries.
70  *
71  * Examples of usage:
72  *
73  * 1) We expect empty stings 's1' and 's2', if condition is not satisfied exception will be
74  * thrown. Condition is indicated in first parentheses, variables designed for printout
75  * follow as (s1)(s2). Each variable must be defined in separate parentheses. The last
76  * step is calling of the appropriate assert type, in this case error(). This assert is
77  * performed for debug and release mode.
78  @code
79  std::string s1, s2;
80  ...
81  FEAL_ASSERT(s1.empty() && s2.empty())(s1)(s2).error("Both strings must be empty!");
82  @endcode
83  *
84  * 2) Parameter of error method is optional.
85  @code
86  FEAL_ASSERT(s1.empty() && s2.empty())(s1)(s2).error();
87  @endcode
88  *
89  * 3) This example is same as previous, but assert is performed only for debug mode.
90  @code
91  FEAL_ASSERT_DBG(s1.empty() && s2.empty())(s1)(s2).error("Both strings must be empty!");
92  @endcode
93  *
94  * 4) Example is same as case 1). Assert type error is called automatically if any other is
95  * not listed. This case is not recommended, rather use explicitly calling of error() method.
96  @code
97  FEAL_ASSERT(s1.empty() && s2.empty())(s1)(s2);
98  @endcode
99  *
100  * 5) Example with same condition as all previous but with other type - warning. Any exception
101  * is not thrown, only warning is printed. Parameter of warning method is optional.
102  @code
103  FEAL_ASSERT(s1.empty() && s2.empty())(s1)(s2).warning("Both strings should be empty!");
104  @endcode
105  *
106  * For simplifying we have defined several macros for comparsion of values:
107  * - ASSERT_LT(a, b) or ASSERT_LT_DBG(a, b) ... check if (a < b)
108  * - ASSERT_LE(a, b) or ASSERT_LE_DBG(a, b) ... check if (a <= b)
109  * - ASSERT_GT(a, b) or ASSERT_GT_DBG(a, b) ... check if (a > b)
110  * - ASSERT_GE(a, b) or ASSERT_GE_DBG(a, b) ... check if (a >= b)
111  * - ASSERT_EQ(a, b) or ASSERT_EQ_DBG(a, b) ... check if (a == b)
112  * - ASSERT_PTR(obj) or ASSERT_PTR_DBG(obj) ... check if obj is non-null pointer
113  *
114  * All macros allow easier declaration of assert. Following example shows declarations of same
115  * cases with usage of different macros:
116  @code
117  ASSERT_LT( idx, arr.size() ).error("Index out of array!");
118  FEAL_ASSERT( idx < arr.size() )(idx)(arr.size()).error("Index out of array!");
119  @endcode
120  */
121 class Assert {
122 public:
123  /// Constructor.
124  Assert(const std::string& expression)
125  : _FEAL_ASSERT_A (*this),
126  _FEAL_ASSERT_B (*this),
127  thrown_(false)
128  {
129  exception_.expression_ = expression;
130  exception_.frames_to_cut_ = { "feal", "Assert"};
131  }
132 
133  /// Copy constructor.
134  Assert(const Assert& other)
135  : _FEAL_ASSERT_A (*this),
136  _FEAL_ASSERT_B (*this),
137  exception_(other.exception_),
138  thrown_(other.thrown_) {}
139 
140  /// Destructor.
141  ~Assert();
142 
143  Assert& _FEAL_ASSERT_A; ///< clever macro A
144  Assert& _FEAL_ASSERT_B; ///< clever macro B
145 
146  /// Adds name and value of variable
147  template <typename T>
148  Assert& add_value(T var_current_val, const char* var_name) {
149  std::stringstream ss;
150  ss << var_name << " : ";
151  ss << "'" << var_current_val << "'"; // Can throw exception if type T hasn't overloading << operator
152  exception_.current_val_.push_back(ss.str());
153 
154  return *this;
155  }
156 
157  /// Stores values for printing out line number, function, etc
158  Assert& set_context(const char* file_name, const char* function, const int line);
159 
160  /// Generate error with given message
161  void error(std::string error_msg = "");
162 
163  /// Generate warning with given message
164  void warning(std::string warning_msg = "");
165 
166 protected:
167  Exc_assert exception_; ///< Exception object
168  bool thrown_; ///< Flag marked if Assert thrown error, warning, ...
169 
170 };
171 
172 
173 
174 /**
175  * Helper class defined empty code.
176  *
177  * Usage only in FEAL_ASSERT_DBG macro if FLOW123D_DEBUG_ASSERTS is off.
178  */
179 class AssertNull {
180 public:
181  /// Constructor.
183  : _FEAL_ASSERT_A (*this),
184  _FEAL_ASSERT_B (*this) {}
185 
186  /// Copy constructor.
188  : _FEAL_ASSERT_A (*this),
189  _FEAL_ASSERT_B (*this) {}
190 
191  /// Destructor.
193 
194  AssertNull& _FEAL_ASSERT_A; ///< clever macro A
195  AssertNull& _FEAL_ASSERT_B; ///< clever macro B
196 
197  /// Empty method, only guarantees consistent code
198  template <typename T>
199  inline AssertNull& add_value(FMT_UNUSED T var_current_val, FMT_UNUSED const char* var_name) {
200  return *this;
201  }
202 
203  /// Empty method, only guarantees consistent code
204  inline void error(FMT_UNUSED std::string error_msg = "") {}
205 
206  /// Empty method, only guarantees consistent code
207  inline void warning(FMT_UNUSED std::string warning_msg = "") {}
208 };
209 
210 } // namespace feal
211 
212 
213 
214 /****************************************************************
215  * Definitions of macros
216  */
217 
218 /**
219  * Definitions of internal macros
220  */
221 /// Internal clever macro A
222 #define _FEAL_ASSERT_A(x) _FEAL_ASSERT_OP(x, B)
223 /// Internal clever macro B
224 #define _FEAL_ASSERT_B(x) _FEAL_ASSERT_OP(x, A)
225 /// Internal clever macro recursion
226 #define _FEAL_ASSERT_OP(x, next) \
227  _FEAL_ASSERT_A.add_value((x), #x)._FEAL_ASSERT_ ## next
228 
229 
230 /**
231  * Undefining redefinitions of comparsion macros.
232  *
233  * You can define FEAL_OVERRIDE_ASSERTS (e.g. in unit tests) and undefine macros with same name in external libraries.
234  */
235 #ifdef ASSERT_LT
236  #ifdef FEAL_OVERRIDE_ASSERTS
237  #undef ASSERT_LT
238  #else
239  #warning "ASSERT_LT already defined out of FEAL."
240  #endif
241 #endif
242 
243 #ifdef ASSERT_LE
244  #ifdef FEAL_OVERRIDE_ASSERTS
245  #undef ASSERT_LE
246  #else
247  #warning "ASSERT_LE already defined out of FEAL."
248  #endif
249 #endif
250 
251 #ifdef ASSERT_GT
252  #ifdef FEAL_OVERRIDE_ASSERTS
253  #undef ASSERT_GT
254  #else
255  #warning "ASSERT_GT already defined out of FEAL."
256  #endif
257 #endif
258 
259 #ifdef ASSERT_GE
260  #ifdef FEAL_OVERRIDE_ASSERTS
261  #undef ASSERT_GE
262  #else
263  #warning "ASSERT_GE already defined out of FEAL."
264  #endif
265 #endif
266 
267 #ifdef ASSERT_EQ
268  #ifdef FEAL_OVERRIDE_ASSERTS
269  #undef ASSERT_EQ
270  #else
271  #warning "ASSERT_EQ already defined out of FEAL."
272  #endif
273 #endif
274 
275 
276 /**
277  * Definitions of assert macros
278  */
279 /// Definition of assert for debug and release mode
280 #define FEAL_ASSERT( expr) \
281 if ( !(expr) ) \
282  feal::Assert( #expr).set_context( __FILE__, __func__, __LINE__)._FEAL_ASSERT_A
283 
284 /// Definition of assert for debug mode only
285 #ifdef FLOW123D_DEBUG_ASSERTS
286  #define FEAL_ASSERT_DBG( expr) \
287  if ( !(expr) ) \
288  feal::Assert( #expr).set_context( __FILE__, __func__, __LINE__)._FEAL_ASSERT_A
289 #else
290  #define FEAL_ASSERT_DBG( expr) \
291  if ( !(expr) ) \
292  feal::AssertNull()._FEAL_ASSERT_A
293 #endif
294 
295 /// Definition of comparative assert macro (Less Than)
296 #define ASSERT_LT(a, b) \
297  FEAL_ASSERT(a < b)(a)(b)
298 
299 /// Definition of comparative assert macro (Less Than) only for debug mode
300 #define ASSERT_LT_DBG(a, b) \
301  FEAL_ASSERT_DBG(a < b)(a)(b)
302 
303 /// Definition of comparative assert macro (Less or Equal)
304 #define ASSERT_LE(a, b) \
305  FEAL_ASSERT(a <= b)(a)(b)
306 
307 /// Definition of comparative assert macro (Less or Equal) only for debug mode
308 #define ASSERT_LE_DBG(a, b) \
309  FEAL_ASSERT_DBG(a <= b)(a)(b)
310 
311 /// Definition of comparative assert macro (Greater Than)
312 #define ASSERT_GT(a, b) \
313  FEAL_ASSERT(a > b)(a)(b)
314 
315 /// Definition of comparative assert macro (Greater Than) only for debug mode
316 #define ASSERT_GT_DBG(a, b) \
317  FEAL_ASSERT_DBG(a > b)(a)(b)
318 
319 /// Definition of comparative assert macro (Greater or Equal)
320 #define ASSERT_GE(a, b) \
321  FEAL_ASSERT(a >= b)(a)(b)
322 
323 /// Definition of comparative assert macro (Greater or Equal) only for debug mode
324 #define ASSERT_GE_DBG(a, b) \
325  FEAL_ASSERT_DBG(a >= b)(a)(b)
326 
327 /// Definition of comparative assert macro (EQual)
328 #define ASSERT_EQ(a, b) \
329  FEAL_ASSERT(a == b)(a)(b)
330 
331 /// Definition of comparative assert macro (EQual) only for debug mode
332 #define ASSERT_EQ_DBG(a, b) \
333  FEAL_ASSERT_DBG(a == b)(a)(b)
334 
335 /// Definition of assert macro checking non-null pointer (PTR)
336 #define ASSERT_PTR( ptr ) \
337  FEAL_ASSERT( (ptr) != nullptr )
338 
339 /// Definition of assert macro checking non-null pointer (PTR) only for debug mode
340 #define ASSERT_PTR_DBG( ptr ) \
341  FEAL_ASSERT_DBG( (ptr) != nullptr )
342 
343 
344 
345 /// Allow use shorter versions of macro names if these names is not used with external library
346 #ifndef ASSERT
347 #define ASSERT( expr) FEAL_ASSERT( expr)
348 #endif
349 #ifndef ASSERT_DBG
350 #define ASSERT_DBG( expr) FEAL_ASSERT_DBG( expr)
351 #endif
352 
353 
354 
355 
356 /**
357  * Sources:
358  * http://www.drdobbs.com/cpp/enhancing-assertions/184403745
359  * https://gist.github.com/hang-qi/5308285
360  * https://beliefbox.googlecode.com/svn-history/r825/trunk/src/core/SmartAssert.h
361  */
362 
363 #endif // ASSERTS_HH
AssertNull(FMT_UNUSED const Assert &other)
Copy constructor.
Definition: asserts.hh:187
Class defining debugging messages.
Definition: asserts.hh:121
bool thrown_
Flag marked if Assert thrown error, warning, ...
Definition: asserts.hh:168
#define _FEAL_ASSERT_A(x)
Internal clever macro A.
Definition: asserts.hh:222
AssertNull & _FEAL_ASSERT_B
clever macro B
Definition: asserts.hh:195
void warning(FMT_UNUSED std::string warning_msg="")
Empty method, only guarantees consistent code.
Definition: asserts.hh:207
void error(FMT_UNUSED std::string error_msg="")
Empty method, only guarantees consistent code.
Definition: asserts.hh:204
Exc_assert exception_
Exception object.
Definition: asserts.hh:167
Assert & _FEAL_ASSERT_A
clever macro A
Definition: asserts.hh:143
Assert & _FEAL_ASSERT_B
clever macro B
Definition: asserts.hh:144
std::ostringstream & form_message(std::ostringstream &) const override
Override ExceptionBase::form_message()
Definition: asserts.cc:52
#define FMT_UNUSED
Definition: posix.h:75
void print_info(std::ostringstream &out) const override
Print formatted assert message.
Definition: asserts.cc:34
#define _FEAL_ASSERT_B(x)
Internal clever macro B.
Definition: asserts.hh:224
std::string function_
Actual function.
Definition: asserts.hh:55
AssertNull()
Constructor.
Definition: asserts.hh:182
Definition: asserts.cc:23
std::string file_name_
Actual file.
Definition: asserts.hh:54
std::string what_type_msg() const override
Override ExceptionBase::what_type_msg()
Definition: asserts.cc:47
std::string expression_
Assertion expression.
Definition: asserts.hh:53
std::vector< std::string > current_val_
Formated strings of names and values of given variables.
Definition: asserts.hh:57
Assert(const std::string &expression)
Constructor.
Definition: asserts.hh:124
Helper class.
Definition: asserts.hh:34
Assert(const Assert &other)
Copy constructor.
Definition: asserts.hh:134
int line_
Actual line.
Definition: asserts.hh:56
~Exc_assert()
Destructor.
Definition: asserts.hh:41
~AssertNull()
Destructor.
Definition: asserts.hh:192
AssertNull & _FEAL_ASSERT_A
clever macro A
Definition: asserts.hh:194
AssertNull & add_value(FMT_UNUSED T var_current_val, FMT_UNUSED const char *var_name)
Empty method, only guarantees consistent code.
Definition: asserts.hh:199
Assert & add_value(T var_current_val, const char *var_name)
Adds name and value of variable.
Definition: asserts.hh:148
Base of exceptions used in Flow123d.
Definition: exceptions.hh:75
std::string what_type_msg_
String representation of message type (Program error, Warning, ...)
Definition: asserts.hh:58