test.hpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // what: simple unit test framework
  2. // who: developed by Kevlin Henney
  3. // when: November 2000
  4. // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.91
  5. #ifndef TEST_INCLUDED
  6. #define TEST_INCLUDED
  7. #include <boost/config.hpp>
  8. #include <exception>
  9. #include <iostream>
  10. #ifdef BOOST_NO_STRINGSTREAM
  11. #include <strstream> // for out-of-the-box g++ pre-2.95.3
  12. #else
  13. #include <sstream>
  14. #endif
  15. #include <string>
  16. namespace any_tests // test tuple comprises name and nullary function (object)
  17. {
  18. template<typename string_type, typename function_type>
  19. struct test
  20. {
  21. string_type name;
  22. function_type action;
  23. static test make(string_type name, function_type action)
  24. {
  25. test result; // MSVC aggreggate initializer bugs
  26. result.name = name;
  27. result.action = action;
  28. return result;
  29. }
  30. };
  31. }
  32. namespace any_tests // failure exception used to indicate checked test failures
  33. {
  34. class failure : public std::exception
  35. {
  36. public: // struction (default cases are OK)
  37. failure(const std::string & why) throw()
  38. : reason(why)
  39. {
  40. }
  41. ~failure() throw() {}
  42. public: // usage
  43. virtual const char * what() const throw()
  44. {
  45. return reason.c_str();
  46. }
  47. private: // representation
  48. std::string reason;
  49. };
  50. }
  51. namespace any_tests // not_implemented exception used to mark unimplemented tests
  52. {
  53. class not_implemented : public std::exception
  54. {
  55. public: // usage (default ctor and dtor are OK)
  56. virtual const char * what() const throw()
  57. {
  58. return "not implemented";
  59. }
  60. };
  61. }
  62. namespace any_tests // test utilities
  63. {
  64. inline void check(bool condition, const std::string & description)
  65. {
  66. if(!condition)
  67. {
  68. throw failure(description);
  69. }
  70. }
  71. inline void check_true(bool value, const std::string & description)
  72. {
  73. check(value, "expected true: " + description);
  74. }
  75. inline void check_false(bool value, const std::string & description)
  76. {
  77. check(!value, "expected false: " + description);
  78. }
  79. template<typename lhs_type, typename rhs_type>
  80. void check_equal(
  81. const lhs_type & lhs, const rhs_type & rhs,
  82. const std::string & description)
  83. {
  84. check(lhs == rhs, "expected equal values: " + description);
  85. }
  86. template<typename lhs_type, typename rhs_type>
  87. void check_unequal(
  88. const lhs_type & lhs, const rhs_type & rhs,
  89. const std::string & description)
  90. {
  91. check(lhs != rhs, "expected unequal values: " + description);
  92. }
  93. inline void check_null(const void * ptr, const std::string & description)
  94. {
  95. check(!ptr, "expected null pointer: " + description);
  96. }
  97. inline void check_non_null(const void * ptr, const std::string & description)
  98. {
  99. check(ptr != 0, "expected non-null pointer: " + description);
  100. }
  101. }
  102. #define TEST_CHECK_THROW(expression, exception, description) \
  103. try \
  104. { \
  105. expression; \
  106. throw ::any_tests::failure(description); \
  107. } \
  108. catch(exception &) \
  109. { \
  110. }
  111. namespace any_tests // memory tracking (enabled if test new and delete linked in)
  112. {
  113. class allocations
  114. {
  115. public: // singleton access
  116. static allocations & instance()
  117. {
  118. static allocations singleton;
  119. return singleton;
  120. }
  121. public: // logging
  122. void clear()
  123. {
  124. alloc_count = dealloc_count = 0;
  125. }
  126. void allocation()
  127. {
  128. ++alloc_count;
  129. }
  130. void deallocation()
  131. {
  132. ++dealloc_count;
  133. }
  134. public: // reporting
  135. unsigned long allocated() const
  136. {
  137. return alloc_count;
  138. }
  139. unsigned long deallocated() const
  140. {
  141. return dealloc_count;
  142. }
  143. bool balanced() const
  144. {
  145. return alloc_count == dealloc_count;
  146. }
  147. private: // structors (default dtor is fine)
  148. allocations()
  149. : alloc_count(0), dealloc_count(0)
  150. {
  151. }
  152. private: // prevention
  153. allocations(const allocations &);
  154. allocations & operator=(const allocations &);
  155. private: // state
  156. unsigned long alloc_count, dealloc_count;
  157. };
  158. }
  159. namespace any_tests // tester is the driver class for a sequence of tests
  160. {
  161. template<typename test_iterator>
  162. class tester
  163. {
  164. public: // structors (default destructor is OK)
  165. tester(test_iterator first_test, test_iterator after_last_test)
  166. : begin(first_test), end(after_last_test)
  167. {
  168. }
  169. public: // usage
  170. bool operator()(); // returns true if all tests passed
  171. private: // representation
  172. test_iterator begin, end;
  173. private: // prevention
  174. tester(const tester &);
  175. tester &operator=(const tester &);
  176. };
  177. #if defined(__GNUC__) && defined(__SGI_STL_PORT) && (__GNUC__ < 3)
  178. // function scope using declarations don't work:
  179. using namespace std;
  180. #endif
  181. template<typename test_iterator>
  182. bool tester<test_iterator>::operator()()
  183. {
  184. using std::cerr;
  185. using std::endl;
  186. using std::ends;
  187. using std::exception;
  188. using std::flush;
  189. using std::string;
  190. unsigned long passed = 0, failed = 0, unimplemented = 0;
  191. for(test_iterator current = begin; current != end; ++current)
  192. {
  193. cerr << "[" << current->name << "] " << flush;
  194. string result = "passed"; // optimistic
  195. try
  196. {
  197. allocations::instance().clear();
  198. current->action();
  199. if(!allocations::instance().balanced())
  200. {
  201. unsigned long allocated = allocations::instance().allocated();
  202. unsigned long deallocated = allocations::instance().deallocated();
  203. #ifdef BOOST_NO_STRINGSTREAM
  204. std::ostrstream report;
  205. #else
  206. std::ostringstream report;
  207. #endif
  208. report << "new/delete ("
  209. << allocated << " allocated, "
  210. << deallocated << " deallocated)"
  211. << ends;
  212. const string text = report.str();
  213. #ifdef BOOST_NO_STRINGSTREAM
  214. report.freeze(false);
  215. #endif
  216. throw failure(text);
  217. }
  218. ++passed;
  219. }
  220. catch(const failure & caught)
  221. {
  222. (result = "failed: ") += caught.what();
  223. ++failed;
  224. }
  225. catch(const not_implemented &)
  226. {
  227. result = "not implemented";
  228. ++unimplemented;
  229. }
  230. catch(const exception & caught)
  231. {
  232. (result = "exception: ") += caught.what();
  233. ++failed;
  234. }
  235. catch(...)
  236. {
  237. result = "failed with unknown exception";
  238. ++failed;
  239. }
  240. cerr << result << endl;
  241. }
  242. cerr << (passed + failed) << " tests: "
  243. << passed << " passed, "
  244. << failed << " failed";
  245. if(unimplemented)
  246. {
  247. cerr << " (" << unimplemented << " not implemented)";
  248. }
  249. cerr << endl;
  250. return failed == 0;
  251. }
  252. }
  253. #endif
  254. // Copyright Kevlin Henney, 2000. All rights reserved.
  255. //
  256. // Distributed under the Boost Software License, Version 1.0. (See
  257. // accompanying file LICENSE_1_0.txt or copy at
  258. // http://www.boost.org/LICENSE_1_0.txt)