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