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