20 #ifndef __TPIE_UNITTEST_H__
21 #define __TPIE_UNITTEST_H__
28 #include <boost/lexical_cast.hpp>
35 typedef std::chrono::high_resolution_clock test_clock;
36 typedef std::chrono::time_point<test_clock> test_time;
37 inline test_time test_now() {
return test_clock::now();}
38 inline double test_millisecs(
const test_time & from,
const test_time & to) {
39 return std::chrono::duration_cast<std::chrono::duration<double, std::milli> >(to-from).count();
42 inline double test_secs(
const test_time & from,
const test_time & to) {
43 return std::chrono::duration_cast<std::chrono::duration<double>>(to-from).count();
46 class teststream_buf:
public std::basic_streambuf<char, std::char_traits<char> > {
48 const static size_t line_size = 2048;
49 char m_line[line_size];
53 virtual int overflow(
int c = traits_type::eof());
68 friend void result_manip(
teststream & s,
bool success);
77 inline friend std::ostream& operator<<(std::ostream& o, const testmanip<TP>& m) {
78 (*m._f)(static_cast<teststream&>(o), m._a);
87 #define TEST_ENSURE(cond, message) { \
89 tpie::log_error() << message \
90 << " (line " << __LINE__ << ")" << std::endl; \
95 #define TEST_ENSURE_EQUALITY(v1, v2, message) { \
96 if ( !((v1) == (v2)) ) { \
97 tpie::log_error() << message \
98 << " (" << v1 << " != " << v2 \
99 << " line " << __LINE__ << ")" << std::endl; \
104 #define TEST_FAIL(message) { \
105 tpie::log_error() << message \
106 << " (line " << __LINE__ << ")" << std::endl; \
121 void set_result(
bool result);
130 static const size_t lineLength = 79;
132 tests(
int argc,
char ** argv, memory_size_type memory_limit=50);
135 template <
typename T>
138 template <
typename T>
141 template <
typename T>
142 tests & test(T fct,
const std::string & name);
144 template <
typename T,
typename T1>
145 tests & test(T fct,
const std::string & name,
146 const std::string & p1_name, T1 p1_default);
148 template <
typename T,
typename T1,
typename T2>
149 tests & test(T fct,
const std::string & name,
150 const std::string & p1_name, T1 p1_default,
151 const std::string & p2_name, T2 p2_default);
153 template <
typename T,
typename T1,
typename T2,
typename T3>
154 tests & test(T fct,
const std::string & name,
155 const std::string & p1_name, T1 p1_default,
156 const std::string & p2_name, T2 p2_default,
157 const std::string & p3_name, T3 p3_default);
159 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
160 tests & 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,
163 const std::string & p3_name, T3 p3_default,
164 const std::string & p4_name, T4 p4_default);
166 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
167 tests & test(T fct,
const std::string & name,
168 const std::string & p1_name, T1 p1_default,
169 const std::string & p2_name, T2 p2_default,
170 const std::string & p3_name, T3 p3_default,
171 const std::string & p4_name, T4 p4_default,
172 const std::string & p5_name, T5 p5_default);
174 template <
typename T>
175 tests & multi_test(T fct,
const std::string & name);
177 template <
typename T,
typename T1>
178 tests & multi_test(T fct,
const std::string & name,
const std::string & p1_name, T1 p1_default);
180 template <
typename T,
typename T1,
typename T2>
181 tests & multi_test(T fct,
const std::string & name,
182 const std::string & p1_name, T1 p1_default,
183 const std::string & p2_name, T2 p2_default);
185 template <
typename T,
typename T1,
typename T2,
typename T3>
186 tests & multi_test(T fct,
const std::string & name,
187 const std::string & p1_name, T1 p1_default,
188 const std::string & p2_name, T2 p2_default,
189 const std::string & p3_name, T3 p3_default);
191 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
192 tests & multi_test(T fct,
const std::string & name,
193 const std::string & p1_name, T1 p1_default,
194 const std::string & p2_name, T2 p2_default,
195 const std::string & p3_name, T3 p3_default,
196 const std::string & p4_name, T4 p4_default);
198 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
199 tests & multi_test(T fct,
const std::string & name,
200 const std::string & p1_name, T1 p1_default,
201 const std::string & p2_name, T2 p2_default,
202 const std::string & p3_name, T3 p3_default,
203 const std::string & p4_name, T4 p4_default,
204 const std::string & p5_name, T5 p5_default);
206 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6>
207 tests & multi_test(T fct,
const std::string & name,
208 const std::string & p1_name, T1 p1_default,
209 const std::string & p2_name, T2 p2_default,
210 const std::string & p3_name, T3 p3_default,
211 const std::string & p4_name, T4 p4_default,
212 const std::string & p5_name, T5 p5_default,
213 const std::string & p6_name, T6 p6_default);
219 virtual void build_information(std::ostream & o);
221 void show_usage(std::ostream & o);
224 virtual void operator()() = 0;
228 template <
typename T>
229 struct func_impl: func {
231 func_impl(T t): t(t) {}
232 virtual void operator()() {t();}
237 test_log_target(std::ostream & os = std::cout)
241 , m_onNameLine(
false)
247 if (!m_onBOL) os << std::endl;
250 void set_test(
const std::string & name) {
252 m_onNameLine =
false;
257 void set_status(
const std::string & status) {
260 }
else if (!m_onBOL) {
265 const size_t maxNameSize = lineLength
268 if (maxNameSize > m_name.size()) os << std::string(maxNameSize-m_name.size(),
'.');
271 os <<
'[' << status <<
']' << std::flush;
276 void write_time(
size_t n) {
277 os <<
" " << n <<
" ms" << std::flush;
280 void log(
log_level level,
const char * buf,
size_t n) {
282 if (level <= bufferThreshold) {
283 std::string prefix =
LOG_DEBUG > bufferThreshold ?
"" : (build_prefix(groups.size()) +
" ");
284 std::string msg = prefix + std::string(buf, n);
287 if (level > threshold)
return;
288 if (m_onNameLine) os <<
'\n';
290 std::string prefix =
LOG_DEBUG > threshold ?
"" : (build_prefix(groups.size()) +
" ");
291 std::string msg = prefix + std::string(buf, n);
294 m_onNameLine =
false;
295 m_onBOL = msg[msg.size()-1] ==
'\n' || msg[msg.size()-1] ==
'\r';
303 void set_buffer_threshold(
log_level level) {
304 bufferThreshold = level;
307 void begin_group(
const std::string & name) {
309 std::string msg = build_prefix(groups.size()-1) +
"> " +
"Entering " + name +
'\n';
313 if (m_onNameLine) os <<
'\n';
315 os << msg << std::flush;
316 m_onNameLine =
false;
321 std::string msg = build_prefix(groups.size()-1) +
"x " +
"Leaving " + groups.top() +
'\n';
326 if (m_onNameLine) os <<
'\n';
328 os << msg << std::flush;
329 m_onNameLine =
false;
335 std::string build_prefix(
size_t size) {
336 return std::string(size,
'|');
339 std::stack<std::string> groups;
349 void start_test(
const std::string & name);
350 void end_test(
bool result,
size_t time);
352 template <
typename T>
353 T get_arg(
const std::string & name, T def)
const;
355 template <
typename T>
356 std::string arg_str(
const std::string & name, T def)
const;
358 bool bad, usage, version, do_time;
360 std::string exe_name;
361 std::string test_name;
363 std::map<std::string, std::string> args;
364 memory_size_type memory_limit;
365 std::string current_name;
366 std::vector<func *> setups;
367 std::vector<func *> finishs;
369 std::vector<std::string> m_tests;
374 template <
typename src,
typename dst>
376 dst operator()(
const src & s) {
377 return boost::lexical_cast<dst>(s);
383 std::string operator()(
bool b) {
384 return b?
"true":
"false";
390 bool operator()(std::string v) {
391 std::transform(v.begin(), v.end(), v.begin(), tolower);
392 return v ==
"true" || v ==
"1" || v ==
"on" || v ==
"yes";
396 template <
typename dst,
typename src>
397 dst magic_cast(
const src & s) {
401 template <
typename T>
403 T operator()(
const std::map<std::string, std::string> & args,
const std::string & name, T def) {
406 std::map<std::string, std::string>::const_iterator i=args.find(name);
407 if (i != args.end()) arg=magic_cast<T>(i->second);
408 }
catch (std::bad_cast) {
409 std::cerr <<
"The argument " << name <<
" has the wrong type" << std::endl;
417 bool operator()(
const std::map<std::string, std::string> & args,
const std::string & name,
bool) {
418 return args.count(name) != 0;
422 template <
typename T>
423 T tests::get_arg(
const std::string & name, T def)
const {
427 template <
typename T>
428 std::string tests::arg_str(
const std::string & name, T def)
const {
429 std::string dashes((name.size() == 1) ? 1 : 2,
'-');
430 return std::string(
" [")+dashes+name+
" ARG (= "+magic_cast<std::string>(def)+
")]";
433 template <
typename T>
434 tests & tests::test(T fct,
const std::string & name) {
435 m_tests.push_back(name);
436 if (testAll || name == test_name) {
437 bits::test_runner t(
this, name);
447 template <
typename T,
typename T1>
448 tests & tests::test(T fct,
const std::string & name,
const std::string & p1_name, T1 p1_default) {
449 m_tests.push_back(name
450 + arg_str(p1_name, p1_default));
451 if (testAll || name == test_name) {
452 bits::test_runner t(
this, name);
454 t.set_result(fct(get_arg(p1_name, p1_default)));
463 template <
typename T,
typename T1,
typename T2>
464 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) {
465 m_tests.push_back(name
466 + arg_str(p1_name, p1_default)
467 + arg_str(p2_name, p2_default));
468 if (testAll || name == test_name) {
469 bits::test_runner t(
this, name);
471 t.set_result(fct(get_arg(p1_name, p1_default),
472 get_arg(p2_name, p2_default)));
480 template <
typename T,
typename T1,
typename T2,
typename T3>
481 tests & tests::test(T fct,
const std::string & name,
482 const std::string & p1_name, T1 p1_default,
483 const std::string & p2_name, T2 p2_default,
484 const std::string & p3_name, T3 p3_default) {
485 m_tests.push_back(name
486 + arg_str(p1_name, p1_default)
487 + arg_str(p2_name, p2_default)
488 + arg_str(p3_name, p3_default));
489 if (testAll || name == test_name) {
490 bits::test_runner t(
this, name);
492 t.set_result(fct(get_arg(p1_name, p1_default),
493 get_arg(p2_name, p2_default),
494 get_arg(p3_name, p3_default)));
503 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
504 tests & tests::test(T fct,
const std::string & name,
505 const std::string & p1_name, T1 p1_default,
506 const std::string & p2_name, T2 p2_default,
507 const std::string & p3_name, T3 p3_default,
508 const std::string & p4_name, T4 p4_default) {
509 m_tests.push_back(name
510 + arg_str(p1_name, p1_default)
511 + arg_str(p2_name, p2_default)
512 + arg_str(p3_name, p3_default)
513 + arg_str(p4_name, p4_default));
514 if (testAll || name == test_name) {
515 bits::test_runner t(
this, name);
517 t.set_result(fct(get_arg(p1_name, p1_default),
518 get_arg(p2_name, p2_default),
519 get_arg(p3_name, p3_default),
520 get_arg(p4_name, p4_default)));
528 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
529 tests & tests::test(T fct,
const std::string & name,
530 const std::string & p1_name, T1 p1_default,
531 const std::string & p2_name, T2 p2_default,
532 const std::string & p3_name, T3 p3_default,
533 const std::string & p4_name, T4 p4_default,
534 const std::string & p5_name, T5 p5_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)
539 + arg_str(p4_name, p4_default)
540 + arg_str(p5_name, p5_default));
541 if (testAll || name == test_name) {
542 bits::test_runner t(
this, name);
544 t.set_result(fct(get_arg(p1_name, p1_default),
545 get_arg(p2_name, p2_default),
546 get_arg(p3_name, p3_default),
547 get_arg(p4_name, p4_default),
548 get_arg(p5_name, p5_default)));
557 template <
typename T>
558 tests & tests::multi_test(T fct,
const std::string & name) {
559 m_tests.push_back(name);
560 if (testAll || name == test_name) {
561 bits::test_runner t(
this, name);
563 teststream ts(do_time);
565 t.set_result(ts.success());
573 template <
typename T,
typename T1>
574 tests & tests::multi_test(T fct,
const std::string & name,
const std::string & p1_name, T1 p1_default) {
575 m_tests.push_back(name+ arg_str(p1_name, p1_default));
576 if (testAll || name == test_name) {
577 bits::test_runner t(
this, name);
579 teststream ts(do_time);
580 fct(ts, get_arg(p1_name, p1_default));
581 t.set_result(ts.success());
589 template <
typename T,
typename T1,
typename T2>
590 tests & tests::multi_test(T fct,
const std::string & name,
591 const std::string & p1_name, T1 p1_default,
592 const std::string & p2_name, T2 p2_default) {
593 m_tests.push_back(name+
594 arg_str(p1_name, p1_default) +
595 arg_str(p2_name, p2_default));
597 if (testAll || name == test_name) {
598 bits::test_runner t(
this, name);
600 teststream ts(do_time);
602 get_arg(p1_name, p1_default),
603 get_arg(p2_name, p2_default));
604 t.set_result(ts.success());
612 template <
typename T,
typename T1,
typename T2,
typename T3>
613 tests & tests::multi_test(T fct,
const std::string & name,
614 const std::string & p1_name, T1 p1_default,
615 const std::string & p2_name, T2 p2_default,
616 const std::string & p3_name, T3 p3_default) {
617 m_tests.push_back(name+
618 arg_str(p1_name, p1_default) +
619 arg_str(p2_name, p2_default) +
620 arg_str(p3_name, p3_default));
622 if (testAll || name == test_name) {
623 bits::test_runner t(
this, name);
625 teststream ts(do_time);
627 get_arg(p1_name, p1_default),
628 get_arg(p2_name, p2_default),
629 get_arg(p3_name, p3_default));
630 t.set_result(ts.success());
638 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4>
639 tests & tests::multi_test(T fct,
const std::string & name,
640 const std::string & p1_name, T1 p1_default,
641 const std::string & p2_name, T2 p2_default,
642 const std::string & p3_name, T3 p3_default,
643 const std::string & p4_name, T4 p4_default) {
644 m_tests.push_back(name+
645 arg_str(p1_name, p1_default) +
646 arg_str(p2_name, p2_default) +
647 arg_str(p3_name, p3_default) +
648 arg_str(p4_name, p4_default));
650 if (testAll || name == test_name) {
651 bits::test_runner t(
this, name);
653 teststream ts(do_time);
655 get_arg(p1_name, p1_default),
656 get_arg(p2_name, p2_default),
657 get_arg(p3_name, p3_default),
658 get_arg(p4_name, p4_default));
659 t.set_result(ts.success());
667 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
668 tests & tests::multi_test(T fct,
const std::string & name,
669 const std::string & p1_name, T1 p1_default,
670 const std::string & p2_name, T2 p2_default,
671 const std::string & p3_name, T3 p3_default,
672 const std::string & p4_name, T4 p4_default,
673 const std::string & p5_name, T5 p5_default) {
674 m_tests.push_back(name+
675 arg_str(p1_name, p1_default) +
676 arg_str(p2_name, p2_default) +
677 arg_str(p3_name, p3_default) +
678 arg_str(p4_name, p4_default) +
679 arg_str(p5_name, p5_default));
681 if (testAll || name == test_name) {
682 bits::test_runner t(
this, name);
684 teststream ts(do_time);
686 get_arg(p1_name, p1_default),
687 get_arg(p2_name, p2_default),
688 get_arg(p3_name, p3_default),
689 get_arg(p4_name, p4_default),
690 get_arg(p5_name, p5_default));
691 t.set_result(ts.success());
699 template <
typename T,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6>
700 tests & tests::multi_test(T fct,
const std::string & name,
701 const std::string & p1_name, T1 p1_default,
702 const std::string & p2_name, T2 p2_default,
703 const std::string & p3_name, T3 p3_default,
704 const std::string & p4_name, T4 p4_default,
705 const std::string & p5_name, T5 p5_default,
706 const std::string & p6_name, T6 p6_default) {
707 m_tests.push_back(name+
708 arg_str(p1_name, p1_default) +
709 arg_str(p2_name, p2_default) +
710 arg_str(p3_name, p3_default) +
711 arg_str(p4_name, p4_default) +
712 arg_str(p5_name, p5_default) +
713 arg_str(p6_name, p6_default));
715 if (testAll || name == test_name) {
716 bits::test_runner t(
this, name);
718 teststream ts(do_time);
720 get_arg(p1_name, p1_default),
721 get_arg(p2_name, p2_default),
722 get_arg(p3_name, p3_default),
723 get_arg(p4_name, p4_default),
724 get_arg(p5_name, p5_default),
725 get_arg(p6_name, p6_default));
726 t.set_result(ts.success());
734 template <
typename T>
735 tests & tests::setup(T t) {
736 setups.push_back(
new func_impl<T>(t));
740 template <
typename T>
741 tests & tests::finish(T t) {
742 finishs.push_back(
new func_impl<T>(t));
748 #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.
LOG_DEBUG is the lowest level and is used by the TPIE library for logging debugging information...
pipe_middle< split_factory< bits::buffer_input_t, node, bits::buffer_output_t > > buffer
The buffer node inserts a phase boundary into the pipeline by writing items to disk.