20 #ifndef __TPIE_UNITTEST_H__
21 #define __TPIE_UNITTEST_H__
28 #include <boost/lexical_cast.hpp>
33 class teststream_buf:
public std::basic_streambuf<char, std::char_traits<char> > {
35 const static size_t line_size = 2048;
36 char m_line[line_size];
40 virtual int overflow(
int c = traits_type::eof());
53 friend void result_manip(
teststream & s,
bool success);
62 inline friend std::ostream& operator<<(std::ostream& o, const testmanip<TP>& m) {
63 (*m._f)(static_cast<teststream&>(o), m._a);
73 #define TEST_ENSURE(cond, message) { \
75 tpie::log_error() << message \
76 << " (line " << __LINE__ << ")" << std::endl; \
81 #define TEST_ENSURE_EQUALITY(v1, v2, message) { \
82 if ( !((v1) == (v2)) ) { \
83 tpie::log_error() << message \
84 << " (" << v1 << " != " << v2 \
85 << " line " << __LINE__ << ")" << std::endl; \
100 void set_result(
bool result);
109 static const size_t lineLength = 79;
111 tests(
int argc,
char ** argv, memory_size_type memory_limit=50);
114 template <
typename T>
117 template <
typename T>
120 template <
typename T>
121 tests & test(T fct,
const std::string & name);
123 template <
typename T,
typename T1>
124 tests & test(T fct,
const std::string & name,
125 const std::string & p1_name, T1 p1_default);
127 template <
typename T,
typename T1,
typename T2>
128 tests & test(T fct,
const std::string & name,
129 const std::string & p1_name, T1 p1_default,
130 const std::string & p2_name, T2 p2_default);
132 template <
typename T,
typename T1,
typename T2,
typename T3>
133 tests & test(T fct,
const std::string & name,
134 const std::string & p1_name, T1 p1_default,
135 const std::string & p2_name, T2 p2_default,
136 const std::string & p3_name, T3 p3_default);
138 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
139 tests & test(T fct,
const std::string & name,
140 const std::string & p1_name, T1 p1_default,
141 const std::string & p2_name, T2 p2_default,
142 const std::string & p3_name, T3 p3_default,
143 const std::string & p4_name, T4 p4_default);
145 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
146 tests & test(T fct,
const std::string & name,
147 const std::string & p1_name, T1 p1_default,
148 const std::string & p2_name, T2 p2_default,
149 const std::string & p3_name, T3 p3_default,
150 const std::string & p4_name, T4 p4_default,
151 const std::string & p5_name, T5 p5_default);
153 template <
typename T>
154 tests & multi_test(T fct,
const std::string & name);
156 template <
typename T,
typename T1>
157 tests & multi_test(T fct,
const std::string & name,
const std::string & p1_name, T1 p1_default);
159 template <
typename T,
typename T1,
typename T2>
160 tests & multi_test(T fct,
const std::string & name,
161 const std::string & p1_name, T1 p1_default,
162 const std::string & p2_name, T2 p2_default);
164 template <
typename T,
typename T1,
typename T2,
typename T3>
165 tests & multi_test(T fct,
const std::string & name,
166 const std::string & p1_name, T1 p1_default,
167 const std::string & p2_name, T2 p2_default,
168 const std::string & p3_name, T3 p3_default);
170 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
171 tests & multi_test(T fct,
const std::string & name,
172 const std::string & p1_name, T1 p1_default,
173 const std::string & p2_name, T2 p2_default,
174 const std::string & p3_name, T3 p3_default,
175 const std::string & p4_name, T4 p4_default);
179 virtual void build_information(std::ostream & o);
181 void show_usage(std::ostream & o);
184 virtual void operator()() = 0;
188 template <
typename T>
189 struct func_impl: func {
191 func_impl(T t): t(t) {}
192 virtual void operator()() {t();}
197 test_log_target(std::ostream & os = std::cout)
201 , m_onNameLine(
false)
207 if (!m_onBOL) os << std::endl;
210 void set_test(
const std::string & name) {
212 m_onNameLine =
false;
217 void set_status(
const std::string & status) {
220 }
else if (!m_onBOL) {
225 const size_t maxNameSize = lineLength
228 if (maxNameSize > m_name.size()) os << std::string(maxNameSize-m_name.size(),
'.');
231 os <<
'[' << status <<
']' << std::flush;
236 void log(
log_level level,
const char * buf,
size_t n) {
238 if (level <= bufferThreshold) buffer << std::string(buf, n);
239 if (level > threshold)
return;
240 if (m_onNameLine) os <<
'\n';
241 std::string msg(buf, n);
243 m_onNameLine =
false;
244 m_onBOL = msg[msg.size()-1] ==
'\n' || msg[msg.size()-1] ==
'\r';
252 void set_buffer_threshold(
log_level level) {
253 bufferThreshold = level;
256 std::stringstream buffer;
267 void start_test(
const std::string & name);
268 void end_test(
bool result);
270 template <
typename T>
271 T get_arg(
const std::string & name, T def)
const;
273 template <
typename T>
274 std::string arg_str(
const std::string & name, T def)
const;
276 bool bad, usage, version;
278 std::string exe_name;
279 std::string test_name;
281 std::map<std::string, std::string> args;
282 memory_size_type memory_limit;
283 std::string current_name;
284 std::vector<func *> setups;
285 std::vector<func *> finishs;
287 std::vector<std::string> m_tests;
292 template <
typename src,
typename dst>
294 dst operator()(
const src & s) {
295 return boost::lexical_cast<dst>(s);
301 std::string operator()(
bool b) {
302 return b?
"true":
"false";
308 bool operator()(std::string v) {
309 std::transform(v.begin(), v.end(), v.begin(), tolower);
310 return v ==
"true" || v ==
"1" || v ==
"on" || v ==
"yes";
314 template <
typename dst,
typename src>
315 dst magic_cast(
const src & s) {
319 template <
typename T>
321 T operator()(
const std::map<std::string, std::string> & args,
const std::string & name, T def) {
324 std::map<std::string, std::string>::const_iterator i=args.find(name);
325 if (i != args.end()) arg=magic_cast<T>(i->second);
326 }
catch (std::bad_cast) {
327 std::cerr <<
"The argument " << name <<
" has the wrong type" << std::endl;
335 bool operator()(
const std::map<std::string, std::string> & args,
const std::string & name,
bool) {
336 return args.count(name) != 0;
340 template <
typename T>
341 T tests::get_arg(
const std::string & name, T def)
const {
345 template <
typename T>
346 std::string tests::arg_str(
const std::string & name, T def)
const {
347 std::string dashes((name.size() == 1) ? 1 : 2,
'-');
348 return std::string(
" [")+dashes+name+
" ARG (= "+magic_cast<std::string>(def)+
")]";
351 template <
typename T>
352 tests & tests::test(T fct,
const std::string & name) {
353 m_tests.push_back(name);
354 if (testAll || name == test_name) {
355 bits::test_runner t(
this, name);
365 template <
typename T,
typename T1>
366 tests & tests::test(T fct,
const std::string & name,
const std::string & p1_name, T1 p1_default) {
367 m_tests.push_back(name
368 + arg_str(p1_name, p1_default));
369 if (testAll || name == test_name) {
370 bits::test_runner t(
this, name);
372 t.set_result(fct(get_arg(p1_name, p1_default)));
381 template <
typename T,
typename T1,
typename T2>
382 tests & tests::test(T fct,
const std::string & name,
const std::string & p1_name, T1 p1_default,
const std::string & p2_name, T2 p2_default) {
383 m_tests.push_back(name
384 + arg_str(p1_name, p1_default)
385 + arg_str(p2_name, p2_default));
386 if (testAll || name == test_name) {
387 bits::test_runner t(
this, name);
389 t.set_result(fct(get_arg(p1_name, p1_default),
390 get_arg(p2_name, p2_default)));
398 template <
typename T,
typename T1,
typename T2,
typename T3>
399 tests & tests::test(T fct,
const std::string & name,
400 const std::string & p1_name, T1 p1_default,
401 const std::string & p2_name, T2 p2_default,
402 const std::string & p3_name, T3 p3_default) {
403 m_tests.push_back(name
404 + arg_str(p1_name, p1_default)
405 + arg_str(p2_name, p2_default)
406 + arg_str(p3_name, p3_default));
407 if (testAll || name == test_name) {
408 bits::test_runner t(
this, name);
410 t.set_result(fct(get_arg(p1_name, p1_default),
411 get_arg(p2_name, p2_default),
412 get_arg(p3_name, p3_default)));
421 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
422 tests & tests::test(T fct,
const std::string & name,
423 const std::string & p1_name, T1 p1_default,
424 const std::string & p2_name, T2 p2_default,
425 const std::string & p3_name, T3 p3_default,
426 const std::string & p4_name, T4 p4_default) {
427 m_tests.push_back(name
428 + arg_str(p1_name, p1_default)
429 + arg_str(p2_name, p2_default)
430 + arg_str(p3_name, p3_default)
431 + arg_str(p4_name, p4_default));
432 if (testAll || name == test_name) {
433 bits::test_runner t(
this, name);
435 t.set_result(fct(get_arg(p1_name, p1_default),
436 get_arg(p2_name, p2_default),
437 get_arg(p3_name, p3_default),
438 get_arg(p4_name, p4_default)));
446 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
447 tests & tests::test(T fct,
const std::string & name,
448 const std::string & p1_name, T1 p1_default,
449 const std::string & p2_name, T2 p2_default,
450 const std::string & p3_name, T3 p3_default,
451 const std::string & p4_name, T4 p4_default,
452 const std::string & p5_name, T5 p5_default) {
453 m_tests.push_back(name
454 + arg_str(p1_name, p1_default)
455 + arg_str(p2_name, p2_default)
456 + arg_str(p3_name, p3_default)
457 + arg_str(p4_name, p4_default)
458 + arg_str(p5_name, p5_default));
459 if (testAll || name == test_name) {
460 bits::test_runner t(
this, name);
462 t.set_result(fct(get_arg(p1_name, p1_default),
463 get_arg(p2_name, p2_default),
464 get_arg(p3_name, p3_default),
465 get_arg(p4_name, p4_default),
466 get_arg(p5_name, p5_default)));
475 template <
typename T>
476 tests & tests::multi_test(T fct,
const std::string & name) {
477 m_tests.push_back(name);
478 if (testAll || name == test_name) {
479 bits::test_runner t(
this, name);
483 t.set_result(ts.success());
491 template <
typename T,
typename T1>
492 tests & tests::multi_test(T fct,
const std::string & name,
const std::string & p1_name, T1 p1_default) {
493 m_tests.push_back(name+ arg_str(p1_name, p1_default));
494 if (testAll || name == test_name) {
495 bits::test_runner t(
this, name);
498 fct(ts, get_arg(p1_name, p1_default));
499 t.set_result(ts.success());
507 template <
typename T,
typename T1,
typename T2>
508 tests & tests::multi_test(T fct,
const std::string & name,
509 const std::string & p1_name, T1 p1_default,
510 const std::string & p2_name, T2 p2_default) {
511 m_tests.push_back(name+
512 arg_str(p1_name, p1_default) +
513 arg_str(p2_name, p2_default));
515 if (testAll || name == test_name) {
516 bits::test_runner t(
this, name);
520 get_arg(p1_name, p1_default),
521 get_arg(p2_name, p2_default));
522 t.set_result(ts.success());
530 template <
typename T,
typename T1,
typename T2,
typename T3>
531 tests & tests::multi_test(T fct,
const std::string & name,
532 const std::string & p1_name, T1 p1_default,
533 const std::string & p2_name, T2 p2_default,
534 const std::string & p3_name, T3 p3_default) {
535 m_tests.push_back(name+
536 arg_str(p1_name, p1_default) +
537 arg_str(p2_name, p2_default) +
538 arg_str(p3_name, p3_default));
540 if (testAll || name == test_name) {
541 bits::test_runner t(
this, name);
545 get_arg(p1_name, p1_default),
546 get_arg(p2_name, p2_default),
547 get_arg(p3_name, p3_default));
548 t.set_result(ts.success());
556 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
557 tests & tests::multi_test(T fct,
const std::string & name,
558 const std::string & p1_name, T1 p1_default,
559 const std::string & p2_name, T2 p2_default,
560 const std::string & p3_name, T3 p3_default,
561 const std::string & p4_name, T4 p4_default) {
562 m_tests.push_back(name+
563 arg_str(p1_name, p1_default) +
564 arg_str(p2_name, p2_default) +
565 arg_str(p3_name, p3_default) +
566 arg_str(p4_name, p4_default));
568 if (testAll || name == test_name) {
569 bits::test_runner t(
this, name);
573 get_arg(p1_name, p1_default),
574 get_arg(p2_name, p2_default),
575 get_arg(p3_name, p3_default),
576 get_arg(p4_name, p4_default));
577 t.set_result(ts.success());
585 template <
typename T>
586 tests & tests::setup(T t) {
587 setups.push_back(
new func_impl<T>(t));
591 template <
typename T>
592 tests & tests::finish(T t) {
593 finishs.push_back(
new func_impl<T>(t));
599 #endif // __TPIE_UNITTEST_H__
LOG_FATAL is the highest error level and is used for all kinds of errors that would normally impair s...
logstream class used by definitions in tpie_log.h.
log_level
TPIE logging levels, from higest priority to lowest.