TPIE

2362a60
unittest.h
1 // -*- mode: c++; tab-width: 4; indent-tabs-mode: t; c-file-style: "stroustrup"; -*-
2 // vi:set ts=4 sts=4 sw=4 noet :
3 // Copyright 2012, The TPIE development team
4 //
5 // This file is part of TPIE.
6 //
7 // TPIE is free software: you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License as published by the
9 // Free Software Foundation, either version 3 of the License, or (at your
10 // option) any later version.
11 //
12 // TPIE is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with TPIE. If not, see <http://www.gnu.org/licenses/>
19 
20 #ifndef __TPIE_UNITTEST_H__
21 #define __TPIE_UNITTEST_H__
22 
23 #include <iostream>
24 #include <tpie/types.h>
25 #include <tpie/logstream.h>
26 #include <map>
27 #include <vector>
28 #include <boost/lexical_cast.hpp>
29 #include <algorithm>
30 #include <chrono>
31 #include <stack>
32 
33 namespace tpie {
34 
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();
40 }
41 
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();
44 }
45 
46 class teststream_buf: public std::basic_streambuf<char, std::char_traits<char> > {
47 private:
48  const static size_t line_size = 2048;
49  char m_line[line_size];
50  bool m_new_line;
51 public:
53  virtual int overflow(int c = traits_type::eof());
54  void stateAlign();
55  virtual int sync();
56 };
57 
58 class teststream: public std::ostream {
59 private:
60  teststream_buf m_buff;
61  size_t failed;
62  size_t total;
63  test_time time;
64  bool do_time;
65 public:
66  teststream(bool do_time);
67  bool success();
68  friend void result_manip(teststream & s, bool success);
69 };
70 
71 template <class TP>
72 class testmanip {
73  void (*_f)(teststream&, TP);
74  TP _a;
75 public:
76  inline testmanip(void (*f)(teststream&, TP), TP a) : _f(f), _a(a) {}
77  inline friend std::ostream& operator<<(std::ostream& o, const testmanip<TP>& m) {
78  (*m._f)(static_cast<teststream&>(o), m._a);
79  return o;
80  }
81 };
82 
83 testmanip<bool> result(bool success);
84 testmanip<bool> success();
85 testmanip<bool> failure();
86 
87 #define TEST_ENSURE(cond, message) { \
88  if (! (cond) ) { \
89  tpie::log_error() << message \
90  << " (line " << __LINE__ << ")" << std::endl; \
91  return false; \
92  } \
93  }
94 
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; \
100  return false; \
101  } \
102  }
103 
104 #define TEST_FAIL(message) { \
105  tpie::log_error() << message \
106  << " (line " << __LINE__ << ")" << std::endl; \
107  return false; \
108  }
109 
110 
111 class tests;
112 
113 namespace bits {
114  class test_runner {
115  tests * t;
116  bool result;
117  test_time m_time;
118  public:
119  test_runner(tests * t, const std::string & name);
120 
121  void set_result(bool result);
122  void exception();
123 
124  ~test_runner();
125  };
126 } // namespace bits
127 
128 class tests {
129 public:
130  static const size_t lineLength = 79;
131 
132  tests(int argc, char ** argv, memory_size_type memory_limit=50);
133  virtual ~tests();
134 
135  template <typename T>
136  tests & setup(T t);
137 
138  template <typename T>
139  tests & finish(T t);
140 
141  template <typename T>
142  tests & test(T fct, const std::string & name);
143 
144  template <typename T, typename T1>
145  tests & test(T fct, const std::string & name,
146  const std::string & p1_name, T1 p1_default);
147 
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);
152 
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);
158 
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);
165 
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);
173 
174  template <typename T>
175  tests & multi_test(T fct, const std::string & name);
176 
177  template <typename T, typename T1>
178  tests & multi_test(T fct, const std::string & name, const std::string & p1_name, T1 p1_default);
179 
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);
184 
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);
190 
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);
197 
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);
205 
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);
214 
215 
216 
217  operator int();
218 protected:
219  virtual void build_information(std::ostream & o);
220 private:
221  void show_usage(std::ostream & o);
222 
223  struct func {
224  virtual void operator()() = 0;
225  virtual ~func() {}
226  };
227 
228  template <typename T>
229  struct func_impl: func {
230  T t;
231  func_impl(T t): t(t) {}
232  virtual void operator()() {t();}
233  };
234 
235 
236  struct test_log_target: public log_target {
237  test_log_target(std::ostream & os = std::cout)
238  : os(os)
239  , threshold(LOG_FATAL)
240  , bufferThreshold(LOG_FATAL)
241  , m_onNameLine(false)
242  , m_onBOL(true)
243  {
244  }
245 
246  ~test_log_target() {
247  if (!m_onBOL) os << std::endl;
248  }
249 
250  void set_test(const std::string & name) {
251  buffer.str("");
252  m_onNameLine = false;
253  m_name = name;
254  set_status(" ");
255  }
256 
257  void set_status(const std::string & status) {
258  if (m_onNameLine) {
259  os << '\r';
260  } else if (!m_onBOL) {
261  os << '\n';
262  }
263 
264  os << m_name << ' ';
265  const size_t maxNameSize = lineLength
266  - 2 // spaces before and after dots
267  - 6; // status message: "[STAT]"
268  if (maxNameSize > m_name.size()) os << std::string(maxNameSize-m_name.size(), '.');
269  os << ' ';
270 
271  os << '[' << status << ']' << std::flush;
272  m_onNameLine = true;
273  m_onBOL = false;
274  }
275 
276  void write_time(size_t n) {
277  os << " " << n << " ms" << std::flush;
278  }
279 
280  void log(log_level level, const char * buf, size_t n) {
281  if (!n) return;
282  if (level <= bufferThreshold) {
283  std::string prefix = LOG_DEBUG > bufferThreshold ? "" : (build_prefix(groups.size()) + " ");
284  std::string msg = prefix + std::string(buf, n);
285  buffer << msg;
286  }
287  if (level > threshold) return;
288  if (m_onNameLine) os << '\n';
289 
290  std::string prefix = LOG_DEBUG > threshold ? "" : (build_prefix(groups.size()) + " ");
291  std::string msg = prefix + std::string(buf, n);
292 
293  os << msg;
294  m_onNameLine = false;
295  m_onBOL = msg[msg.size()-1] == '\n' || msg[msg.size()-1] == '\r';
296  os << std::flush;
297  }
298 
299  void set_threshold(log_level level) {
300  threshold = level;
301  }
302 
303  void set_buffer_threshold(log_level level) {
304  bufferThreshold = level;
305  }
306 
307  void begin_group(const std::string & name) {
308  groups.push(name);
309  std::string msg = build_prefix(groups.size()-1) + "> " + "Entering " + name + '\n';
310 
311  if (LOG_DEBUG <= bufferThreshold) buffer << msg;
312  if (LOG_DEBUG > threshold) return;
313  if (m_onNameLine) os << '\n';
314 
315  os << msg << std::flush;
316  m_onNameLine = false;
317  m_onBOL = true;
318  }
319 
320  void end_group() {
321  std::string msg = build_prefix(groups.size()-1) + "x " + "Leaving " + groups.top() + '\n';
322  groups.pop();
323 
324  if (LOG_DEBUG <= bufferThreshold) buffer << msg;
325  if (LOG_DEBUG > threshold) return;
326  if (m_onNameLine) os << '\n';
327 
328  os << msg << std::flush;
329  m_onNameLine = false;
330  m_onBOL = true;
331  }
332 
333  std::stringstream buffer;
334  private:
335  std::string build_prefix(size_t size) {
336  return std::string(size, '|');
337  }
338 
339  std::stack<std::string> groups;
340  std::ostream & os;
341  log_level threshold;
342  log_level bufferThreshold;
343  bool m_onNameLine;
344  std::string m_name;
345  bool m_onBOL;
346  };
347 
348 
349  void start_test(const std::string & name);
350  void end_test(bool result, size_t time);
351 
352  template <typename T>
353  T get_arg(const std::string & name, T def) const;
354 
355  template <typename T>
356  std::string arg_str(const std::string & name, T def) const;
357 
358  bool bad, usage, version, do_time;
359  size_t tests_runned;
360  std::string exe_name;
361  std::string test_name;
362  bool testAll;
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;
368  test_log_target log;
369  std::vector<std::string> m_tests;
370 
371  friend class bits::test_runner;
372 };
373 
374 template <typename src, typename dst>
376  dst operator()(const src & s) {
377  return boost::lexical_cast<dst>(s);
378  }
379 };
380 
381 template <>
382 struct magic_cast_help<bool, std::string> {
383  std::string operator()(bool b) {
384  return b?"true":"false";
385  }
386 };
387 
388 template <>
389 struct magic_cast_help<std::string, bool> {
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";
393  }
394 };
395 
396 template <typename dst, typename src>
397 dst magic_cast(const src & s) {
398  return magic_cast_help<src, dst>()(s);
399 }
400 
401 template <typename T>
402 struct get_arg_help {
403  T operator()(const std::map<std::string, std::string> & args, const std::string & name, T def) {
404  T arg=def;
405  try {
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;
410  }
411  return arg;
412  }
413 };
414 
415 template <>
416 struct get_arg_help<bool> {
417  bool operator()(const std::map<std::string, std::string> & args, const std::string & name, bool) {
418  return args.count(name) != 0;
419  }
420 };
421 
422 template <typename T>
423 T tests::get_arg(const std::string & name, T def) const {
424  return get_arg_help<T>()(args, name, def);
425 }
426 
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)+")]";
431 }
432 
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);
438  try {
439  t.set_result(fct());
440  } catch (...) {
441  t.exception();
442  }
443  }
444  return *this;
445 }
446 
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);
453  try {
454  t.set_result(fct(get_arg(p1_name, p1_default)));
455  } catch (...) {
456  t.exception();
457  }
458  }
459  return *this;
460 }
461 
462 
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);
470  try {
471  t.set_result(fct(get_arg(p1_name, p1_default),
472  get_arg(p2_name, p2_default)));
473  } catch (...) {
474  t.exception();
475  }
476  }
477  return *this;
478 }
479 
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);
491  try {
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)));
495  } catch (...) {
496  t.exception();
497  }
498  }
499  return *this;
500 
501 }
502 
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);
516  try {
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)));
521  } catch (...) {
522  t.exception();
523  }
524  }
525  return *this;
526 }
527 
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);
543  try {
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)));
549  } catch (...) {
550  t.exception();
551  }
552  }
553  return *this;
554 }
555 
556 
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);
562  try {
563  teststream ts(do_time);
564  fct(ts);
565  t.set_result(ts.success());
566  } catch (...) {
567  t.exception();
568  }
569  }
570  return *this;
571 }
572 
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);
578  try {
579  teststream ts(do_time);
580  fct(ts, get_arg(p1_name, p1_default));
581  t.set_result(ts.success());
582  } catch (...) {
583  t.exception();
584  }
585  }
586  return *this;
587 }
588 
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));
596 
597  if (testAll || name == test_name) {
598  bits::test_runner t(this, name);
599  try {
600  teststream ts(do_time);
601  fct(ts,
602  get_arg(p1_name, p1_default),
603  get_arg(p2_name, p2_default));
604  t.set_result(ts.success());
605  } catch (...) {
606  t.exception();
607  }
608  }
609  return *this;
610 }
611 
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));
621 
622  if (testAll || name == test_name) {
623  bits::test_runner t(this, name);
624  try {
625  teststream ts(do_time);
626  fct(ts,
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());
631  } catch (...) {
632  t.exception();
633  }
634  }
635  return *this;
636 }
637 
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));
649 
650  if (testAll || name == test_name) {
651  bits::test_runner t(this, name);
652  try {
653  teststream ts(do_time);
654  fct(ts,
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());
660  } catch (...) {
661  t.exception();
662  }
663  }
664  return *this;
665 }
666 
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));
680 
681  if (testAll || name == test_name) {
682  bits::test_runner t(this, name);
683  try {
684  teststream ts(do_time);
685  fct(ts,
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());
692  } catch (...) {
693  t.exception();
694  }
695  }
696  return *this;
697 }
698 
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));
714 
715  if (testAll || name == test_name) {
716  bits::test_runner t(this, name);
717  try {
718  teststream ts(do_time);
719  fct(ts,
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());
727  } catch (...) {
728  t.exception();
729  }
730  }
731  return *this;
732 }
733 
734 template <typename T>
735 tests & tests::setup(T t) {
736  setups.push_back(new func_impl<T>(t));
737  return *this;
738 }
739 
740 template <typename T>
741 tests & tests::finish(T t) {
742  finishs.push_back(new func_impl<T>(t));
743  return *this;
744 }
745 
746 } //namespace tpie
747 
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...
Definition: loglevel.h:37
Typesafe bitflags.
logstream class used by definitions in tpie_log.h.
log_level
TPIE logging levels, from higest priority to lowest.
Definition: loglevel.h:33
LOG_DEBUG is the lowest level and is used by the TPIE library for logging debugging information...
Definition: loglevel.h:54
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.
Definition: buffer.h:207