PageRenderTime 35ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/mordor/test/test.h

http://github.com/mozy/mordor
C Header | 377 lines | 312 code | 52 blank | 13 comment | 12 complexity | da3a6968ce85e43d62bc5b16d0c7f083 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #ifndef __TEST_H__
  2. #define __TEST_H__
  3. // Copyright (c) 2009 - Mozy, Inc.
  4. #include <map>
  5. #include <sstream>
  6. #include <typeinfo>
  7. #include <vector>
  8. #include "mordor/assert.h"
  9. namespace Mordor {
  10. namespace Test {
  11. class TestInstance;
  12. typedef void (*TestDg)();
  13. typedef std::pair<TestDg, std::map<std::string, TestDg> > TestSuite;
  14. typedef std::map<std::string, TestSuite> TestSuites;
  15. /// Create an invariant that is run before and after every test in TestSuite
  16. #define MORDOR_SUITE_INVARIANT(TestSuite) \
  17. static void _ ## TestSuite ## _invariant(); \
  18. namespace { \
  19. static struct register__ ## TestSuite ## _invariant_struct { \
  20. register__ ## TestSuite ## _invariant_struct() { \
  21. ::Mordor::Test::registerSuiteInvariant(#TestSuite, \
  22. &_ ## TestSuite ## _invariant); \
  23. } \
  24. } g__ ## TestSuite ## _invariant_registration; \
  25. } \
  26. static void _ ## TestSuite ## _invariant()
  27. /// Create a unit test that is part of TestSuite
  28. #define MORDOR_UNITTEST(TestSuite, TestName) \
  29. static void TestSuite ## _ ## TestName(); \
  30. namespace { \
  31. static struct register_ ## TestSuite ## _ ## TestName ## _struct { \
  32. register_ ## TestSuite ## _ ## TestName ## _struct() { \
  33. ::Mordor::Test::registerTest(#TestSuite, #TestName, \
  34. & TestSuite ## _ ## TestName ); \
  35. } \
  36. } g_ ## TestSuite ## _ ## TestName ## _registration; \
  37. } \
  38. static void TestSuite ## _ ## TestName()
  39. /// Create a unit test that is part of TestSuite, and runs as a member function
  40. /// of Fixture
  41. #define MORDOR_UNITTEST_FIXTURE(Fixture, TestSuite, TestName) \
  42. class TestSuite ## _ ## TestName ## Helper : public Fixture \
  43. { \
  44. public: \
  45. void run(); \
  46. }; \
  47. MORDOR_UNITTEST(TestSuite, TestName) \
  48. { \
  49. TestSuite ## _ ## TestName ## Helper helper; \
  50. helper.run(); \
  51. } \
  52. void TestSuite ## _ ## TestName ## Helper::run()
  53. // Public interface
  54. class TestListener
  55. {
  56. public:
  57. virtual ~TestListener() {}
  58. virtual void testStarted(const std::string &suite,
  59. const std::string &test) = 0;
  60. virtual void testComplete(const std::string &suite,
  61. const std::string &test) = 0;
  62. virtual void testSkipped(const std::string &suite,
  63. const std::string &test) = 0;
  64. virtual void testAsserted(const std::string &suite,
  65. const std::string &test, const Assertion &assertion) = 0;
  66. virtual void testException(const std::string &suite,
  67. const std::string &test) = 0;
  68. virtual void testsComplete() = 0;
  69. };
  70. // Internal functions
  71. void registerTest(const std::string &suite, const std::string &testName,
  72. TestDg test);
  73. void registerSuiteInvariant(const std::string &suite, TestDg invariant);
  74. // Public functions
  75. TestSuites &allTests();
  76. TestSuites testsForArguments(int argc, char **argv);
  77. bool runTests();
  78. bool runTests(const TestSuites &suites);
  79. bool runTests(TestListener &listener);
  80. bool runTests(const TestSuites &suites,
  81. TestListener &listener);
  82. struct TestSkippedException {};
  83. // Serialization for assertion reporting
  84. template <class T>
  85. struct serializer
  86. {
  87. serializer(const T &t) : m_t(t) {}
  88. std::ostream &serialize(std::ostream &os)
  89. {
  90. return os << m_t;
  91. }
  92. const T& m_t;
  93. };
  94. template <class T>
  95. std::ostream &operator <<(std::ostream &os, serializer<T> t)
  96. {
  97. return t.serialize(os);
  98. }
  99. template <class T>
  100. struct type_serializer
  101. {
  102. std::ostream &serialize(std::ostream &os)
  103. {
  104. return os << typeid(T).name();
  105. }
  106. };
  107. #define MORDOR_NO_SERIALIZE_BARE(type) \
  108. struct serializer<type> : public ::Mordor::Test::type_serializer<type> \
  109. { \
  110. serializer(const type &t) {} \
  111. };
  112. #define MORDOR_NO_SERIALIZE(type) \
  113. template <> \
  114. MORDOR_NO_SERIALIZE_BARE(type)
  115. template <class T>
  116. MORDOR_NO_SERIALIZE_BARE(std::vector<T>)
  117. // Assertion macros
  118. #define MORDOR_TEST_ASSERT(expr) \
  119. if (!(expr)) ::Mordor::Test::assertion(__FILE__, __LINE__, \
  120. BOOST_CURRENT_FUNCTION, #expr)
  121. #define MORDOR_TEST_ASSERT_EQUAL(lhs, rhs) \
  122. ::Mordor::Test::assertEqual(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, \
  123. lhs, rhs, #lhs, #rhs)
  124. #define MORDOR_TEST_ASSERT_NOT_EQUAL(lhs, rhs) \
  125. ::Mordor::Test::assertNotEqual(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, \
  126. lhs, rhs, #lhs, #rhs)
  127. #define MORDOR_TEST_ASSERT_LESS_THAN(lhs, rhs) \
  128. ::Mordor::Test::assertLessThan(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, \
  129. lhs, rhs, #lhs, #rhs)
  130. #define MORDOR_TEST_ASSERT_LESS_THAN_OR_EQUAL(lhs, rhs) \
  131. ::Mordor::Test::assertLessThanOrEqual(__FILE__, __LINE__, \
  132. BOOST_CURRENT_FUNCTION, lhs, rhs, #lhs, #rhs)
  133. #define MORDOR_TEST_ASSERT_GREATER_THAN(lhs, rhs) \
  134. ::Mordor::Test::assertGreaterThan(__FILE__, __LINE__, \
  135. BOOST_CURRENT_FUNCTION, lhs, rhs, #lhs, #rhs)
  136. #define MORDOR_TEST_ASSERT_GREATER_THAN_OR_EQUAL(lhs, rhs) \
  137. ::Mordor::Test::assertGreaterThanOrEqual(__FILE__, __LINE__, \
  138. BOOST_CURRENT_FUNCTION, lhs, rhs, #lhs, #rhs)
  139. #define MORDOR_TEST_ASSERT_ABOUT_EQUAL(lhs, rhs, variance) \
  140. ::Mordor::Test::assertAboutEqual(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION,\
  141. lhs, rhs, #lhs, #rhs, variance)
  142. #define MORDOR_TEST_ASSERT_EXCEPTION(code, exception) \
  143. try { \
  144. code; \
  145. ::Mordor::Test::assertion(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, \
  146. "Expected " + std::string(typeid(exception).name()) + \
  147. " from " #code); \
  148. } catch (exception &) { \
  149. }
  150. #define MORDOR_TEST_ASSERT_ANY_EXCEPTION(code) \
  151. try { \
  152. code; \
  153. ::Mordor::Test::assertion(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, \
  154. "Expected an exception from " #code); \
  155. } catch (...) { \
  156. }
  157. #define MORDOR_TEST_ASSERT_ASSERTED(code) \
  158. { \
  159. bool __selfAsserted = false; \
  160. try { \
  161. code; \
  162. __selfAsserted = true; \
  163. ::Mordor::Test::assertion(__FILE__, __LINE__, \
  164. BOOST_CURRENT_FUNCTION, "Expected Assertion from " #code); \
  165. } catch (::Mordor::Assertion &) { \
  166. if (__selfAsserted) \
  167. throw; \
  168. } \
  169. }
  170. /// Asserts on destruction if it was alive for longer than us microseconds
  171. struct TimeConstraint
  172. {
  173. TimeConstraint(unsigned long long us);
  174. ~TimeConstraint();
  175. private:
  176. unsigned long long m_end;
  177. };
  178. /// Assert on destruction if it was alive for shorter than us microseconds
  179. struct TakesAtLeast
  180. {
  181. TakesAtLeast(unsigned long long us);
  182. ~TakesAtLeast();
  183. private:
  184. unsigned long long m_until;
  185. };
  186. // Assertion internal functions
  187. void assertion(const char *file, int line, const char *function,
  188. const std::string &expr);
  189. template <class T, class U>
  190. void assertComparison(const char *file, int line, const char *function,
  191. T lhs, U rhs, const char *lhsExpr, const char *rhsExpr,
  192. const char *op)
  193. {
  194. std::ostringstream os;
  195. serializer<T> t(lhs);
  196. serializer<U> u(rhs);
  197. os << lhsExpr << " " << op << " " << rhsExpr
  198. << "\n" << t << " " << op << " " << u;
  199. assertion(file, line, function, os.str());
  200. }
  201. template <class T, class U>
  202. void assertEqual(const char *file, int line, const char *function,
  203. T lhs, U rhs, const char *lhsExpr, const char *rhsExpr)
  204. {
  205. if (!(lhs == rhs)) {
  206. assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
  207. "==");
  208. }
  209. }
  210. template <>
  211. void assertEqual<const char *, const char *>(const char *file,
  212. int line, const char *function, const char *lhs, const char *rhs,
  213. const char *lhsExpr, const char *rhsExpr);
  214. #ifdef WINDOWS
  215. template <>
  216. void assertEqual<const wchar_t *, const wchar_t *>(const char *file,
  217. int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
  218. const char *lhsExpr, const char *rhsExpr);
  219. #endif
  220. template <class T, class U>
  221. void assertNotEqual(const char *file, int line, const char *function,
  222. T lhs, U rhs, const char *lhsExpr, const char *rhsExpr)
  223. {
  224. if (!(lhs != rhs)) {
  225. assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
  226. "!=");
  227. }
  228. }
  229. template <>
  230. void assertNotEqual<const char *, const char *>(const char *file,
  231. int line, const char *function, const char *lhs, const char *rhs,
  232. const char *lhsExpr, const char *rhsExpr);
  233. #ifdef WINDOWS
  234. template <>
  235. void assertNotEqual<const wchar_t *, const wchar_t *>(const char *file,
  236. int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
  237. const char *lhsExpr, const char *rhsExpr);
  238. #endif
  239. template <class T, class U>
  240. void assertLessThan(const char *file, int line, const char *function,
  241. T lhs, U rhs, const char *lhsExpr, const char *rhsExpr)
  242. {
  243. if (!(lhs < rhs)) {
  244. assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
  245. "<");
  246. }
  247. }
  248. template <>
  249. void assertLessThan<const char *, const char *>(const char *file,
  250. int line, const char *function, const char *lhs, const char *rhs,
  251. const char *lhsExpr, const char *rhsExpr);
  252. #ifdef WINDOWS
  253. template <>
  254. void assertLessThan<const wchar_t *, const wchar_t *>(const char *file,
  255. int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
  256. const char *lhsExpr, const char *rhsExpr);
  257. #endif
  258. template <class T, class U>
  259. void assertLessThanOrEqual(const char *file, int line, const char *function,
  260. T lhs, U rhs, const char *lhsExpr, const char *rhsExpr)
  261. {
  262. if (!(lhs <= rhs)) {
  263. assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
  264. "<=");
  265. }
  266. }
  267. template <>
  268. void assertLessThanOrEqual<const char *, const char *>(const char *file,
  269. int line, const char *function, const char *lhs, const char *rhs,
  270. const char *lhsExpr, const char *rhsExpr);
  271. #ifdef WINDOWS
  272. template <>
  273. void assertLessThanOrEqual<const wchar_t *, const wchar_t *>(const char *file,
  274. int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
  275. const char *lhsExpr, const char *rhsExpr);
  276. #endif
  277. template <class T, class U>
  278. void assertGreaterThan(const char *file, int line, const char *function,
  279. T lhs, U rhs, const char *lhsExpr, const char *rhsExpr)
  280. {
  281. if (!(lhs > rhs)) {
  282. assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
  283. ">");
  284. }
  285. }
  286. template <>
  287. void assertGreaterThan<const char *, const char *>(const char *file,
  288. int line, const char *function, const char *lhs, const char *rhs,
  289. const char *lhsExpr, const char *rhsExpr);
  290. #ifdef WINDOWS
  291. template <>
  292. void assertGreaterThan<const wchar_t *, const wchar_t *>(const char *file,
  293. int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
  294. const char *lhsExpr, const char *rhsExpr);
  295. #endif
  296. template <class T, class U>
  297. void assertGreaterThanOrEqual(const char *file, int line, const char *function,
  298. T lhs, U rhs, const char *lhsExpr, const char *rhsExpr)
  299. {
  300. if (!(lhs >= rhs)) {
  301. assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
  302. ">=");
  303. }
  304. }
  305. template <>
  306. void assertGreaterThanOrEqual<const char *, const char *>(const char *file,
  307. int line, const char *function, const char *lhs, const char *rhs,
  308. const char *lhsExpr, const char *rhsExpr);
  309. #ifdef WINDOWS
  310. template <>
  311. void assertGreaterThanOrEqual<const wchar_t *, const wchar_t *>(const char *file,
  312. int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
  313. const char *lhsExpr, const char *rhsExpr);
  314. #endif
  315. template <class T, class U, class V>
  316. void assertAboutEqual(const char *file, int line, const char *function,
  317. T lhs, U rhs, const char *lhsExpr, const char *rhsExpr, V variance)
  318. {
  319. if (!(lhs - variance <= rhs && lhs + variance >= rhs)) {
  320. assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
  321. "~==");
  322. }
  323. }
  324. }}
  325. #endif