1 /*==========================================================================
2 SeqAn - The Library for Sequence Analysis
4 ============================================================================
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 ============================================================================
18 $Id: basic_debug.h,v 1.1 2008/08/25 16:20:01 langmead Exp $
19 ==========================================================================*/
21 #ifndef SEQAN_HEADER_BASIC_DEBUG_H
22 #define SEQAN_HEADER_BASIC_DEBUG_H
24 #ifndef SEQAN_DEBUG_OR_TEST_
26 #define SEQAN_DEBUG_OR_TEST_
27 #else //#ifdef SEQAN_DEBUG
29 #define SEQAN_DEBUG_OR_TEST_
30 #endif //#ifdef SEQAN_TEST
31 #endif //#ifdef SEQAN_DEBUG
32 #endif //#ifndef SEQAN_DEBUG_OR_TEST_
35 #ifdef SEQAN_DEBUG_OR_TEST_
37 #endif //#ifdef SEQAN_DEBUG_OR_TEST_
41 //throw a fatal debug report if _cond is false
42 #define SEQAN_ASSERT(_cond) { if (!(_cond)) ::SEQAN_NAMESPACE_MAIN::debug::Error< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, #_cond " is FALSE"); }
43 #define SEQAN_ASSERT1(_cond) SEQAN_ASSERT(_cond)
44 #define SEQAN_ASSERT2(_cond, _comment) { if (!(_cond)) ::SEQAN_NAMESPACE_MAIN::debug::Error< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, _comment); }
46 //throw a debug report if _cond is false
47 #define SEQAN_CHECK(_cond) { if (!(_cond)) ::SEQAN_NAMESPACE_MAIN::debug::Message< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, #_cond " is FALSE"); }
48 #define SEQAN_CHECK1(_cond) SEQAN_CHECK(_cond)
49 #define SEQAN_CHECK2(_cond, _comment) { if (!(_cond)) ::SEQAN_NAMESPACE_MAIN::debug::Message< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, _comment); }
51 #define SEQAN_DO(_cond) { if (!(_cond)) ::SEQAN_NAMESPACE_MAIN::debug::Message< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, #_cond " is FALSE"); }
52 #define SEQAN_DO1(_cond) SEQAN_DO(_cond)
53 #define SEQAN_DO2(_cond, _comment) { if (!(_cond)) ::SEQAN_NAMESPACE_MAIN::debug::Error< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, _comment); }
56 #define SEQAN_ABORT(_comment) { ::SEQAN_NAMESPACE_MAIN::debug::Error< ::SEQAN_NAMESPACE_MAIN::debug::Report >(__FILE__, __LINE__, _comment); }
57 #define SEQAN_REPORT(_comment) { ::SEQAN_NAMESPACE_MAIN::debug::Message< ::SEQAN_NAMESPACE_MAIN::debug::Report >(__FILE__, __LINE__, _comment); }
59 #else //#ifdef SEQAN_DEBUG
61 //disable debug reports in release built
62 #define SEQAN_ASSERT(_cond) {}
63 #define SEQAN_ASSERT1(_cond) {}
64 #define SEQAN_ASSERT2(_cond, _comment) {}
66 #define SEQAN_CHECK(_cond) {}
67 #define SEQAN_CHECK1(_cond) {}
68 #define SEQAN_CHECK2(_cond, _comment) {}
70 #define SEQAN_DO(_cond) { _cond; }
71 #define SEQAN_DO1(_cond) SEQAN_DO(_cond)
72 #define SEQAN_DO2(_cond, _comment) { _cond; }
74 #define SEQAN_ABORT(_comment) {}
75 #define SEQAN_REPORT(_comment) {}
77 #endif //#ifdef SEQAN_DEBUG
81 //test a condition and report test result
82 #define SEQAN_TASSERT(_cond) \
83 { if (!(_cond)) ::SEQAN_NAMESPACE_MAIN::debug::Error< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, "(" #_cond ") is FALSE"); }
84 #define SEQAN_TASSERT1(_cond) SEQAN_TASSERT(_cond)
85 #define SEQAN_TASSERT2(_cond, _comment) \
86 { if (!(_cond)) ::SEQAN_NAMESPACE_MAIN::debug::Error< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, _comment); }
88 #define SEQAN_TCHECK(_cond) \
89 { if (_cond) ::SEQAN_NAMESPACE_MAIN::debug::Result< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, "(" #_cond ") is TRUE"); \
90 else ::SEQAN_NAMESPACE_MAIN::debug::Result< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, "(" #_cond ") is FALSE"); }
91 #define SEQAN_TCHECK1(_cond) SEQAN_TCHECK(_cond)
92 #define SEQAN_TCHECK2(_cond, _comment) \
93 { if (_cond) ::SEQAN_NAMESPACE_MAIN::debug::Result< ::SEQAN_NAMESPACE_MAIN::debug::Check >(__FILE__, __LINE__, _comment); }
95 //report a test result
96 #define SEQAN_TABORT(_comment) { ::SEQAN_NAMESPACE_MAIN::debug::Error< ::SEQAN_NAMESPACE_MAIN::debug::Report >(__FILE__, __LINE__, _comment); }
97 #define SEQAN_TREPORT(_comment) { ::SEQAN_NAMESPACE_MAIN::debug::Result< ::SEQAN_NAMESPACE_MAIN::debug::Report >(__FILE__, __LINE__, _comment); }
99 #else //#ifdef SEQAN_TEST
101 #define SEQAN_TASSERT(_cond) {}
102 #define SEQAN_TASSERT1(_cond) {}
103 #define SEQAN_TASSERT2(_cond, _comment) {}
105 #define SEQAN_TCHECK(_cond) {}
106 #define SEQAN_TABORT(_comment) {}
107 #define SEQAN_TREPORT(_comment) {}
109 #endif //#ifdef SEQAN_TEST
110 //____________________________________________________________________________
112 #ifdef SEQAN_DEBUG_OR_TEST_
114 //Test Helper Functions
116 // compare two files, do not translate linebreaks
118 _compareBinaryFiles(char * file1, char * file2)
122 FILE * fl1 = fopen(file1, "rb");
123 if (!fl1) return ret;
125 FILE * fl2 = fopen(file2, "rb");
132 while (!feof(fl1) && !feof(fl2))
134 if (fgetc(fl1) != fgetc(fl2)) goto End;
137 ret = feof(fl1) && feof(fl2);
146 //____________________________________________________________________________
148 //one line break is either \r, \n, or \r\n.
150 _compareTextFiles_readChar(FILE * fl, char & c, bool & is_lb, bool & is_eof)
159 char c_help = fgetc(fl);
160 if (feof(fl)) is_eof = true;
166 if (feof(fl)) is_eof = true;
175 if (feof(fl)) is_eof = true;
179 // compare two files, translate linebreaks
181 _compareTextFiles(char * file1, char * file2)
183 FILE * fl1 = fopen(file1, "rb");
184 if (!fl1) return false;
186 FILE * fl2 = fopen(file2, "rb");
195 bool is_lb1, is_lb2, is_eof1, is_eof2;
198 while (!feof(fl1) && !feof(fl2))
200 _compareTextFiles_readChar(fl1, c1, is_lb1, is_eof1);
201 _compareTextFiles_readChar(fl2, c2, is_lb2, is_eof2);
207 if (is_eof1 ^ is_eof2)
217 ret = feof(fl1) && feof(fl2);
228 //____________________________________________________________________________
230 namespace SEQAN_NAMESPACE_MAIN
236 //action of SEQAN_ASSERT, SEQAN_TCHECK and SEQAN_CHECK
237 //use as template argument for Error<> and Message<> and Result<>
240 //action of SEQAN_ABORT, SEQAN_TREPORT and SEQAN_REPORT
241 //use as template argument for Error<> and Message<> and Result<>
246 //template argument TAction is the action (Check or Report)
247 //use explicit instatiation for overwriting the default behavior
248 template <typename TAction>
249 void Error(const char * file, int line, const char * comment="-")
251 std::fprintf(stderr, "%s(%i) : SEQAN: %s\nSEQAN: execution aborted\n", file, line, comment);
255 //report debug message
256 //template argument TAction is the action (Check or Report)
257 //use explicit instatiation for overwriting the default behavior
258 template <typename TAction>
259 void Message(const char * file, int line, const char * comment="-")
261 std::fprintf(stderr, "%s(%i) : SEQAN: %s\n", file, line, comment);
265 //template argument TAction is the action (Check or Report)
266 //use explicit instatiation for overwriting the default behavior
267 template <typename TAction>
268 void Result(const char * file, int line, const char * comment="-")
270 std::fprintf(stdout, "%s(%i) : %s\n", file, line, comment);
275 } //namespace SEQAN_NAMESPACE_MAIN
277 #endif //#ifdef SEQAN_DEBUG_OR_TEST_
280 //____________________________________________________________________________
283 //note: this framework relies on the filenames in the project to be unique
291 namespace SEQAN_NAMESPACE_MAIN
301 struct CheckpointLess : public ::std::binary_function <Checkpoint, Checkpoint, bool>
303 inline bool operator() (Checkpoint const &a, Checkpoint const &b) const
305 int c = strcmp(a.file, b.file);
306 return c < 0 || (c == 0 && a.line < b.line);
310 template <typename T = void>
311 struct CheckpointStore
313 static ::std::set<Checkpoint, CheckpointLess> data;
315 template <typename T>
316 ::std::set<Checkpoint, CheckpointLess> CheckpointStore<T>::data;
320 checkpoint(unsigned int line, char const* file)
322 char const* file_name = strrchr(file, '/');
323 char const* file_name_2 = strrchr(file, '\\');
324 if (file_name_2 > file_name) file_name = file_name_2;
325 if (!file_name) file_name = file;
328 Checkpoint cp = {file_name, line};
329 CheckpointStore<>::data.insert(cp);
332 #define SEQAN_CHECKPOINT \
333 ::SEQAN_NAMESPACE_MAIN::debug::checkpoint(__LINE__, __FILE__);
337 testCheckpoint(char const* file, unsigned int line)
339 Checkpoint cp = {file, line};
340 if (CheckpointStore<>::data.find(cp) == CheckpointStore<>::data.end())
341 Message< Report >(file, line, "Checkpoint lost");
345 verifyCheckpoints(char const* file)
347 char const* file_name = strrchr(file, '/');
348 char const* file_name_2 = strrchr(file, '\\');
349 if (file_name_2 > file_name) file_name = file_name_2;
350 if (!file_name) file_name = file;
353 FILE * fl = ::std::fopen(file, "r");
356 Error< Report >(file, 0, "verifyCheckpoints could not find this file.");
358 unsigned int line_number = 1;
361 while (::std::fgets(buf, sizeof(buf), fl))
363 if (::std::strstr(buf, "SEQAN_CHECKPOINT"))
365 testCheckpoint(file_name, line_number);
375 } //namespace SEQAN_NAMESPACE_MAIN
377 #else //#ifdef SEQAN_TEST
379 #define SEQAN_CHECKPOINT
381 #endif //#ifdef SEQAN_TEST
383 //____________________________________________________________________________
385 #endif //#ifndef SEQAN_HEADER_...