LifeV
LifeAssertSmart.cpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5 Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6 Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8 This file is part of LifeV.
9 
10 LifeV is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14 
15 LifeV is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 /*!
27  @file
28  @brief Complex assertion mechanism
29 
30  @date 16-01-2005
31  @author Christophe Prud'homme <christophe.prudhomme@epfl.ch>
32 
33  @maintainer Radu Popescu <radu.popescu@epfl.ch>
34 */
35 
36 #include <cstdlib>
37 
38 #include <fstream>
39 #include <stdexcept>
40 
41 #include <lifev/core/util/LifeAssertSmart.hpp>
42 
43 // TODO: TO BE REMOVED: ARGUABLY USELESS AND BREAKS COMPILATION ON SOME
44 // SYSTEMS (BG/P etc.)
46 {
47  // MSVC, BCB,
48 #if (defined _MSC_VER) || (defined __BORLANDC__)
49  // __asm { int 3 };
50 #elif defined(__GNUC__)
51  // GCC
52  // __asm ("int $0x3");
53 #else
54  //# error Please supply instruction to break into code
55 #endif
56 }
57 
58 namespace LifeV
59 {
60 namespace
61 {
62 // in case we're logging using the default logger...
64 {
65  StreamHolder() : M_outputStream ( 0), M_ownership ( false) {}
67  {
68  if ( M_ownership)
69  {
70  delete M_outputStream;
71  }
72  M_outputStream = 0;
73  }
74  std::ostream* M_outputStream;
76 };
77 // information about the stream we write to, in case
78 // we're using the default logger
80 
81 // intitializes the SMART_ASSERT library
83 {
85  {
87  }
88 }
89 init;
90 } // anonymous namespace
91 
92 namespace SmartAssert
93 {
94 
95 // returns a message corresponding to the type of level
96 std::string getTypeofLevel ( int nLevel)
97 {
98  switch ( nLevel)
99  {
100  case lvl_warn:
101  return "Warning";
102  case lvl_debug:
103  return "Assertion failed";
104  case lvl_error:
105  return "Assertion failed (Error)";
106  case lvl_fatal:
107  return "Assertion failed (FATAL)";
108  default:
109  {
110  std::ostringstream out;
111  out << "Assertion failed (level=" << nLevel << ")";
112  return out.str();
113  }
114  };
115 }
116 
117 // helpers, for dumping the assertion context
118 void dumpContextSummary ( const AssertContext& context, std::ostream& out)
119 {
120  out << "\n" << getTypeofLevel ( context.level() )
121  << " in " << context.file() << ":" << context.contextLine() << '\n';
122  if ( !context.message().empty() )
123  // we have a user-friendly message
124  {
125  out << context.message();
126  }
127  else
128  {
129  out << "\nExpression: " << context.expression();
130  }
131  out << std::endl;
132 }
133 
134 void dumpContextDetail ( const AssertContext& context, std::ostream& out)
135 {
136  out << "\n" << getTypeofLevel ( context.level() )
137  << " in " << context.file() << ":" << context.contextLine() << '\n';
138  if ( !context.message().empty() )
139  {
140  out << "User-friendly msg: '" << context.message() << "'\n";
141  }
142  out << "\nExpression: '" << context.expression() << "'\n";
143 
144  typedef AssertContext::valueArray_Type valueArray_Type;
145  const valueArray_Type& aVals = context.values();
146  if ( !aVals.empty() )
147  {
148  bool bFirstTime = true;
149  valueArray_Type::const_iterator first = aVals.begin(), last = aVals.end();
150  while ( first != last)
151  {
152  if ( bFirstTime)
153  {
154  out << "Values: ";
155  bFirstTime = false;
156  }
157  else
158  {
159  out << " ";
160  }
161  out << first->second << "='" << first->first << "'\n";
162  ++first;
163  }
164  }
165  out << std::endl;
166 }
167 
168 ///////////////////////////////////////////////////////
169 // logger
170 
171 void defaultLogger ( const AssertContext& context)
172 {
174  {
175  return;
176  }
178 }
179 
180 ///////////////////////////////////////////////////////
181 // handlers
182 
183 // warn : just dump summary to console
184 void defaultWarnHandler ( const AssertContext& context)
185 {
186  dumpContextSummary ( context, std::cout);
187 }
188 
189 
190 // debug: ask user what to do
191 void defaultDebugHandler ( const AssertContext& context)
192 {
193  static bool ignore_all = false;
194  if ( ignore_all)
195  // ignore All asserts
196  {
197  return;
198  }
199  typedef std::pair< std::string, int> fileAndLine;
200  static std::set< fileAndLine> ignorer;
201  if ( ignorer.find ( fileAndLine ( context.file(), context.contextLine() ) ) != ignorer.end() )
202  // this is Ignored Forever
203  {
204  return;
205  }
206 
207  dumpContextSummary ( context, std::cerr );
208  std::cerr << "\nPress (I)gnore/ Igore (F)orever/ Ignore (A)ll/ (D)ebug/ A(b)ort: ";
209  std::cerr.flush();
210  char ch = 0;
211 
212  bool bContinue = true;
213  while ( bContinue && std::cin.get ( ch) )
214  {
215  bContinue = false;
216  switch ( ch)
217  {
218  case 'i':
219  case 'I':
220  // ignore
221  break;
222 
223  case 'f':
224  case 'F':
225  // ignore forever
226  ignorer.insert ( fileAndLine ( context.file(), context.contextLine() ) );
227  break;
228 
229  case 'a':
230  case 'A':
231  // ignore all
232  ignore_all = true;
233  break;
234 
235  case 'd':
236  case 'D':
237  // break
238  breakIntoDebugger();
239  break;
240 
241  case 'b':
242  case 'B':
243  abort();
244  break;
245 
246  default:
247  bContinue = true;
248  break;
249  }
250  }
251 }
252 
253 
254 // error : throw a runtime exception
255 void defaultErrorHandler ( const AssertContext& context)
256 {
257  std::ostringstream out;
258  dumpContextSummary ( context, out);
259  throw std::runtime_error ( out.str() );
260 }
261 
262 
263 // fatal : dump error and abort
264 void defaultFatalHandler ( const AssertContext& context)
265 {
266  dumpContextDetail ( context, std::cerr);
267  abort();
268 }
269 
270 
271 } // namespace SmartAssert
272 
273 
274 namespace Private
275 {
276 
278 {
284 }
285 
286 // sets the default logger to write to this stream
287 void setDefaultLogStream ( std::ostream& out)
288 {
291 }
292 
293 // sets the default logger to write to this file
294 void setDefaultLogName ( const char* str)
295 {
297  defaultLoggerInfo.M_outputStream = new std::ofstream ( str);
299 }
300 
301 
302 } // namespace Private
303 
304 }
static void setLog(assertFunction_Type log)
void setDefaultLogName(const char *str)
void defaultFatalHandler(const AssertContext &context)
void defaultLogger(const AssertContext &context)
void breakIntoDebugger()
void dumpContextSummary(const AssertContext &context, std::ostream &out)
void updateInverseJacobian(const UInt &iQuadPt)
void defaultWarnHandler(const AssertContext &context)
void defaultDebugHandler(const AssertContext &context)
const valueArray_Type & values() const
static void setHandler(int nLevel, assertFunction_Type handler)
contains details about a failed assertion
void setDefaultLogStream(std::ostream &out)
std::vector< valueAndString_Type > valueArray_Type
void defaultErrorHandler(const AssertContext &context)
void dumpContextDetail(const AssertContext &context, std::ostream &out)
const std::string & message() const
std::string getTypeofLevel(int nLevel)