20 #ifndef __TPIE_UNITTEST_H__
21 #define __TPIE_UNITTEST_H__
23 #include <tpie/tpie_export.h>
29 #include <boost/lexical_cast.hpp>
36 typedef std::chrono::high_resolution_clock test_clock;
37 typedef std::chrono::time_point<test_clock> test_time;
38 inline test_time test_now() {
return test_clock::now();}
39 inline double test_millisecs(
const test_time & from,
const test_time & to) {
40 return std::chrono::duration_cast<std::chrono::duration<double, std::milli> >(to-from).count();
43 inline double test_secs(
const test_time & from,
const test_time & to) {
44 return std::chrono::duration_cast<std::chrono::duration<double>>(to-from).count();
47 class TPIE_EXPORT
teststream_buf:
public std::basic_streambuf<char, std::char_traits<char> > {
49 const static size_t line_size = 2048;
50 char m_line[line_size];
54 virtual int overflow(
int c = traits_type::eof());
69 friend void result_manip(
teststream & s,
bool success);
78 inline friend std::ostream& operator<<(std::ostream& o,
const testmanip<TP>& m) {
88 #define TEST_ENSURE(cond, message) { \
90 tpie::log_error() << message \
91 << " (line " << __LINE__ << ")" << std::endl; \
96 #define TEST_ENSURE_EQUALITY(_v1, _v2, message) { \
99 if ( !(v1 == v2) ) { \
100 tpie::log_error() << message \
101 << " (" << v1 << " != " << v2 \
102 << " line " << __LINE__ << ")" << std::endl; \
107 #define TEST_FAIL(message) { \
108 tpie::log_error() << message \
109 << " (line " << __LINE__ << ")" << std::endl; \
124 void set_result(
bool result);
133 static const size_t lineLength = 79;
135 tests(
int argc,
char ** argv, memory_size_type memory_limit=50);
138 template <
typename T>
141 template <
typename T>
144 template <
typename T>
145 tests & test(T fct,
const std::string & name);
147 template <
typename T,
typename T1>
148 tests & test(T fct,
const std::string & name,
149 const std::string & p1_name, T1 p1_default);
151 template <
typename T,
typename T1,
typename T2>
152 tests & test(T fct,
const std::string & name,
153 const std::string & p1_name, T1 p1_default,
154 const std::string & p2_name, T2 p2_default);
156 template <
typename T,
typename T1,
typename T2,
typename T3>
157 tests & test(T fct,
const std::string & name,
158 const std::string & p1_name, T1 p1_default,
159 const std::string & p2_name, T2 p2_default,
160 const std::string & p3_name, T3 p3_default);
162 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
163 tests & test(T fct,
const std::string & name,
164 const std::string & p1_name, T1 p1_default,
165 const std::string & p2_name, T2 p2_default,
166 const std::string & p3_name, T3 p3_default,
167 const std::string & p4_name, T4 p4_default);
169 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
170 tests & test(T fct,
const std::string & name,
171 const std::string & p1_name, T1 p1_default,
172 const std::string & p2_name, T2 p2_default,
173 const std::string & p3_name, T3 p3_default,
174 const std::string & p4_name, T4 p4_default,
175 const std::string & p5_name, T5 p5_default);
177 template <
typename T>
178 tests & multi_test(T fct,
const std::string & name);
180 template <
typename T,
typename T1>
181 tests & multi_test(T fct,
const std::string & name,
const std::string & p1_name, T1 p1_default);
183 template <
typename T,
typename T1,
typename T2>
184 tests & multi_test(T fct,
const std::string & name,
185 const std::string & p1_name, T1 p1_default,
186 const std::string & p2_name, T2 p2_default);
188 template <
typename T,
typename T1,
typename T2,
typename T3>
189 tests & multi_test(T fct,
const std::string & name,
190 const std::string & p1_name, T1 p1_default,
191 const std::string & p2_name, T2 p2_default,
192 const std::string & p3_name, T3 p3_default);
194 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
195 tests & multi_test(T fct,
const std::string & name,
196 const std::string & p1_name, T1 p1_default,
197 const std::string & p2_name, T2 p2_default,
198 const std::string & p3_name, T3 p3_default,
199 const std::string & p4_name, T4 p4_default);
201 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
202 tests & multi_test(T fct,
const std::string & name,
203 const std::string & p1_name, T1 p1_default,
204 const std::string & p2_name, T2 p2_default,
205 const std::string & p3_name, T3 p3_default,
206 const std::string & p4_name, T4 p4_default,
207 const std::string & p5_name, T5 p5_default);
209 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6>
210 tests & multi_test(T fct,
const std::string & name,
211 const std::string & p1_name, T1 p1_default,
212 const std::string & p2_name, T2 p2_default,
213 const std::string & p3_name, T3 p3_default,
214 const std::string & p4_name, T4 p4_default,
215 const std::string & p5_name, T5 p5_default,
216 const std::string & p6_name, T6 p6_default);
222 virtual void build_information(std::ostream & o);
224 void show_usage(std::ostream & o);
227 virtual void operator()() = 0;
231 template <
typename T>
232 struct func_impl: func {
234 func_impl(T t): t(t) {}
235 virtual void operator()() {t();}
240 test_log_target(std::ostream & os = std::cout)
244 , m_onNameLine(
false)
250 if (!m_onBOL) os << std::endl;
253 void set_test(
const std::string & name) {
255 m_onNameLine =
false;
260 void set_status(
const std::string & status) {
263 }
else if (!m_onBOL) {
268 const size_t maxNameSize = lineLength
271 if (maxNameSize > m_name.size()) os << std::string(maxNameSize-m_name.size(),
'.');
274 os <<
'[' << status <<
']' << std::flush;
279 void write_time(
size_t n) {
280 os <<
" " << n <<
" ms" << std::flush;
283 void log(
log_level level,
const char * buf,
size_t n) {
285 if (level <= bufferThreshold) {
286 std::string prefix =
LOG_DEBUG > bufferThreshold ?
"" : (build_prefix(groups.size()) +
" ");
287 std::string msg = prefix + std::string(buf, n);
290 if (level > threshold)
return;
291 if (m_onNameLine) os <<
'\n';
293 std::string prefix =
LOG_DEBUG > threshold ?
"" : (build_prefix(groups.size()) +
" ");
294 std::string msg = prefix + std::string(buf, n);
297 m_onNameLine =
false;
298 m_onBOL = msg[msg.size()-1] ==
'\n' || msg[msg.size()-1] ==
'\r';
306 void set_buffer_threshold(
log_level level) {
307 bufferThreshold = level;
310 void begin_group(
const std::string & name) {
312 std::string msg = build_prefix(groups.size()-1) +
"> " +
"Entering " + name +
'\n';
316 if (m_onNameLine) os <<
'\n';
318 os << msg << std::flush;
319 m_onNameLine =
false;
324 std::string msg = build_prefix(groups.size()-1) +
"x " +
"Leaving " + groups.top() +
'\n';
329 if (m_onNameLine) os <<
'\n';
331 os << msg << std::flush;
332 m_onNameLine =
false;
338 std::string build_prefix(
size_t size) {
339 return std::string(size,
'|');
342 std::stack<std::string> groups;
352 void start_test(
const std::string & name);
353 void end_test(
bool result,
size_t time);
355 template <
typename T>
356 T get_arg(
const std::string & name, T def)
const;
358 template <
typename T>
359 std::string arg_str(
const std::string & name, T def)
const;
361 bool bad, usage, version, do_time;
363 std::string exe_name;
364 std::string test_name;
366 std::map<std::string, std::string> args;
367 memory_size_type memory_limit;
368 std::string current_name;
369 std::vector<func *> setups;
370 std::vector<func *> finishs;
372 std::vector<std::string> m_tests;
377 template <
typename src,
typename dst>
379 dst operator()(
const src & s) {
380 return boost::lexical_cast<dst>(s);
386 std::string operator()(
bool b) {
387 return b?
"true":
"false";
393 bool operator()(std::string v) {
394 std::transform(v.begin(), v.end(), v.begin(), tolower);
395 return v ==
"true" || v ==
"1" || v ==
"on" || v ==
"yes";
399 template <
typename dst,
typename src>
400 dst magic_cast(
const src & s) {
404 template <
typename T>
406 T operator()(
const std::map<std::string, std::string> & args,
const std::string & name, T def) {
409 std::map<std::string, std::string>::const_iterator i=args.find(name);
410 if (i != args.end()) arg=magic_cast<T>(i->second);
411 }
catch (std::bad_cast &) {
412 std::cerr <<
"The argument " << name <<
" has the wrong type" << std::endl;
420 bool operator()(
const std::map<std::string, std::string> & args,
const std::string & name,
bool) {
421 return args.count(name) != 0;
425 template <
typename T>
426 T tests::get_arg(
const std::string & name, T def)
const {
430 template <
typename T>
431 std::string tests::arg_str(
const std::string & name, T def)
const {
432 std::string dashes((name.size() == 1) ? 1 : 2,
'-');
433 return std::string(
" [")+dashes+name+
" ARG (= "+magic_cast<std::string>(def)+
")]";
436 template <
typename T>
437 tests & tests::test(T fct,
const std::string & name) {
438 m_tests.push_back(name);
439 if (testAll || name == test_name) {
440 bits::test_runner t(
this, name);
450 template <
typename T,
typename T1>
451 tests & tests::test(T fct,
const std::string & name,
const std::string & p1_name, T1 p1_default) {
452 m_tests.push_back(name
453 + arg_str(p1_name, p1_default));
454 if (testAll || name == test_name) {
455 bits::test_runner t(
this, name);
457 t.set_result(fct(get_arg(p1_name, p1_default)));
466 template <
typename T,
typename T1,
typename T2>
467 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) {
468 m_tests.push_back(name
469 + arg_str(p1_name, p1_default)
470 + arg_str(p2_name, p2_default));
471 if (testAll || name == test_name) {
472 bits::test_runner t(
this, name);
474 t.set_result(fct(get_arg(p1_name, p1_default),
475 get_arg(p2_name, p2_default)));
483 template <
typename T,
typename T1,
typename T2,
typename T3>
484 tests & tests::test(T fct,
const std::string & name,
485 const std::string & p1_name, T1 p1_default,
486 const std::string & p2_name, T2 p2_default,
487 const std::string & p3_name, T3 p3_default) {
488 m_tests.push_back(name
489 + arg_str(p1_name, p1_default)
490 + arg_str(p2_name, p2_default)
491 + arg_str(p3_name, p3_default));
492 if (testAll || name == test_name) {
493 bits::test_runner t(
this, name);
495 t.set_result(fct(get_arg(p1_name, p1_default),
496 get_arg(p2_name, p2_default),
497 get_arg(p3_name, p3_default)));
506 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
507 tests & tests::test(T fct,
const std::string & name,
508 const std::string & p1_name, T1 p1_default,
509 const std::string & p2_name, T2 p2_default,
510 const std::string & p3_name, T3 p3_default,
511 const std::string & p4_name, T4 p4_default) {
512 m_tests.push_back(name
513 + arg_str(p1_name, p1_default)
514 + arg_str(p2_name, p2_default)
515 + arg_str(p3_name, p3_default)
516 + arg_str(p4_name, p4_default));
517 if (testAll || name == test_name) {
518 bits::test_runner t(
this, name);
520 t.set_result(fct(get_arg(p1_name, p1_default),
521 get_arg(p2_name, p2_default),
522 get_arg(p3_name, p3_default),
523 get_arg(p4_name, p4_default)));
531 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
532 tests & tests::test(T fct,
const std::string & name,
533 const std::string & p1_name, T1 p1_default,
534 const std::string & p2_name, T2 p2_default,
535 const std::string & p3_name, T3 p3_default,
536 const std::string & p4_name, T4 p4_default,
537 const std::string & p5_name, T5 p5_default) {
538 m_tests.push_back(name
539 + arg_str(p1_name, p1_default)
540 + arg_str(p2_name, p2_default)
541 + arg_str(p3_name, p3_default)
542 + arg_str(p4_name, p4_default)
543 + arg_str(p5_name, p5_default));
544 if (testAll || name == test_name) {
545 bits::test_runner t(
this, name);
547 t.set_result(fct(get_arg(p1_name, p1_default),
548 get_arg(p2_name, p2_default),
549 get_arg(p3_name, p3_default),
550 get_arg(p4_name, p4_default),
551 get_arg(p5_name, p5_default)));
560 template <
typename T>
561 tests & tests::multi_test(T fct,
const std::string & name) {
562 m_tests.push_back(name);
563 if (testAll || name == test_name) {
564 bits::test_runner t(
this, name);
566 teststream ts(do_time);
568 t.set_result(ts.success());
576 template <
typename T,
typename T1>
577 tests & tests::multi_test(T fct,
const std::string & name,
const std::string & p1_name, T1 p1_default) {
578 m_tests.push_back(name+ arg_str(p1_name, p1_default));
579 if (testAll || name == test_name) {
580 bits::test_runner t(
this, name);
582 teststream ts(do_time);
583 fct(ts, get_arg(p1_name, p1_default));
584 t.set_result(ts.success());
592 template <
typename T,
typename T1,
typename T2>
593 tests & tests::multi_test(T fct,
const std::string & name,
594 const std::string & p1_name, T1 p1_default,
595 const std::string & p2_name, T2 p2_default) {
596 m_tests.push_back(name+
597 arg_str(p1_name, p1_default) +
598 arg_str(p2_name, p2_default));
600 if (testAll || name == test_name) {
601 bits::test_runner t(
this, name);
603 teststream ts(do_time);
605 get_arg(p1_name, p1_default),
606 get_arg(p2_name, p2_default));
607 t.set_result(ts.success());
615 template <
typename T,
typename T1,
typename T2,
typename T3>
616 tests & tests::multi_test(T fct,
const std::string & name,
617 const std::string & p1_name, T1 p1_default,
618 const std::string & p2_name, T2 p2_default,
619 const std::string & p3_name, T3 p3_default) {
620 m_tests.push_back(name+
621 arg_str(p1_name, p1_default) +
622 arg_str(p2_name, p2_default) +
623 arg_str(p3_name, p3_default));
625 if (testAll || name == test_name) {
626 bits::test_runner t(
this, name);
628 teststream ts(do_time);
630 get_arg(p1_name, p1_default),
631 get_arg(p2_name, p2_default),
632 get_arg(p3_name, p3_default));
633 t.set_result(ts.success());
641 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
642 tests & tests::multi_test(T fct,
const std::string & name,
643 const std::string & p1_name, T1 p1_default,
644 const std::string & p2_name, T2 p2_default,
645 const std::string & p3_name, T3 p3_default,
646 const std::string & p4_name, T4 p4_default) {
647 m_tests.push_back(name+
648 arg_str(p1_name, p1_default) +
649 arg_str(p2_name, p2_default) +
650 arg_str(p3_name, p3_default) +
651 arg_str(p4_name, p4_default));
653 if (testAll || name == test_name) {
654 bits::test_runner t(
this, name);
656 teststream ts(do_time);
658 get_arg(p1_name, p1_default),
659 get_arg(p2_name, p2_default),
660 get_arg(p3_name, p3_default),
661 get_arg(p4_name, p4_default));
662 t.set_result(ts.success());
670 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
671 tests & tests::multi_test(T fct,
const std::string & name,
672 const std::string & p1_name, T1 p1_default,
673 const std::string & p2_name, T2 p2_default,
674 const std::string & p3_name, T3 p3_default,
675 const std::string & p4_name, T4 p4_default,
676 const std::string & p5_name, T5 p5_default) {
677 m_tests.push_back(name+
678 arg_str(p1_name, p1_default) +
679 arg_str(p2_name, p2_default) +
680 arg_str(p3_name, p3_default) +
681 arg_str(p4_name, p4_default) +
682 arg_str(p5_name, p5_default));
684 if (testAll || name == test_name) {
685 bits::test_runner t(
this, name);
687 teststream ts(do_time);
689 get_arg(p1_name, p1_default),
690 get_arg(p2_name, p2_default),
691 get_arg(p3_name, p3_default),
692 get_arg(p4_name, p4_default),
693 get_arg(p5_name, p5_default));
694 t.set_result(ts.success());
702 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6>
703 tests & tests::multi_test(T fct,
const std::string & name,
704 const std::string & p1_name, T1 p1_default,
705 const std::string & p2_name, T2 p2_default,
706 const std::string & p3_name, T3 p3_default,
707 const std::string & p4_name, T4 p4_default,
708 const std::string & p5_name, T5 p5_default,
709 const std::string & p6_name, T6 p6_default) {
710 m_tests.push_back(name+
711 arg_str(p1_name, p1_default) +
712 arg_str(p2_name, p2_default) +
713 arg_str(p3_name, p3_default) +
714 arg_str(p4_name, p4_default) +
715 arg_str(p5_name, p5_default) +
716 arg_str(p6_name, p6_default));
718 if (testAll || name == test_name) {
719 bits::test_runner t(
this, name);
721 teststream ts(do_time);
723 get_arg(p1_name, p1_default),
724 get_arg(p2_name, p2_default),
725 get_arg(p3_name, p3_default),
726 get_arg(p4_name, p4_default),
727 get_arg(p5_name, p5_default),
728 get_arg(p6_name, p6_default));
729 t.set_result(ts.success());
737 template <
typename T>
738 tests & tests::setup(T t) {
739 setups.push_back(
new func_impl<T>(t));
743 template <
typename T>
744 tests & tests::finish(T t) {
745 finishs.push_back(
new func_impl<T>(t));
751 #endif // __TPIE_UNITTEST_H__