utils.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #ifndef __CXXCALL_TESTS_UTILS__
  2. #define __CXXCALL_TESTS_UTILS__ 1
  3. #include <iostream>
  4. #include <cstdlib>
  5. #include <string>
  6. #include <vector>
  7. #include <utility>
  8. #include <tuple>
  9. #include <typeinfo>
  10. #include <sstream>
  11. #define ASSERT(Cond) \
  12. do \
  13. { \
  14. if (!(Cond)) \
  15. { \
  16. std::cerr << "\n\nAssertion failed: " << #Cond << \
  17. "\nLine: " << __LINE__ << "\nFile: " << __FILE__ << \
  18. "\nFunction: " << cur_fname << "\n\n"; \
  19. exit (EXIT_FAILURE); \
  20. } \
  21. } \
  22. while (false)
  23. #define CONCAT_(x, y) x ## y
  24. #define CONCAT(x, y) CONCAT_(x, y)
  25. #define TUPLE std::make_tuple
  26. static std::string cur_fname;
  27. struct test_fn
  28. {
  29. std::string msg;
  30. void (*fct) ();
  31. test_fn (const std::string& m, void (*f) ()) : msg (m), fct (f)
  32. {
  33. }
  34. void run () const
  35. {
  36. std::cout << "Testing " << this->msg << "...";
  37. this->fct ();
  38. std::cout << " OK\n";
  39. }
  40. };
  41. std::vector<test_fn>& test_suite ()
  42. {
  43. static std::vector<test_fn> ts;
  44. return (ts);
  45. }
  46. void run_tests ()
  47. {
  48. for (auto& tst : test_suite ())
  49. tst.run ();
  50. std::cout << "Done\n";
  51. }
  52. struct test_module
  53. {
  54. typedef std::pair<std::string, void (*) ()> pair_type;
  55. test_module (const char *name, std::initializer_list<pair_type> tests)
  56. {
  57. std::string nm = std::string (" (") + name + ") ";
  58. for (auto pair : tests)
  59. test_suite().push_back (test_fn (pair.first + nm, pair.second));
  60. }
  61. };
  62. template <class T>
  63. struct equal
  64. {
  65. template <class ...Args>
  66. static bool eq (void *addr, T (*fn) (Args...), Args... args)
  67. {
  68. return (*(const T *)addr == fn (args...));
  69. }
  70. };
  71. template <>
  72. struct equal<void>
  73. {
  74. static bool eq (void *, ...)
  75. {
  76. return (true);
  77. }
  78. };
  79. static void *global_tuple;
  80. template <class T>
  81. static bool eq_tuples (const T& left)
  82. {
  83. return (left == *(const T *)global_tuple);
  84. }
  85. template <class ...>
  86. struct sum_type;
  87. template <class T>
  88. struct sum_type<T>
  89. {
  90. typedef T type;
  91. };
  92. template <class T, class ...Args>
  93. struct sum_type<T, Args...>
  94. {
  95. typedef typename sum_type<Args...>::type rtype;
  96. typedef decltype (std::declval<T>() + std::declval<rtype>()) type;
  97. };
  98. template <class T>
  99. T sum (T x)
  100. {
  101. std::ostringstream ostr;
  102. ostr << "sum (" << typeid(x).name () << ")";
  103. cur_fname = ostr.str ();
  104. ASSERT (eq_tuples (TUPLE (x)));
  105. return (x);
  106. }
  107. template <class T>
  108. void print_type (std::ostringstream& ostr, T x)
  109. {
  110. ostr << typeid(x).name () << ", ";
  111. }
  112. template <class T, class ...Args>
  113. auto sum (T x, Args... args) -> typename sum_type<T, Args...>::type
  114. {
  115. std::ostringstream ostr;
  116. ostr << "sum (";
  117. using helper_type = int[];
  118. helper_type { (print_type (ostr, x), 0), (print_type (ostr, args), 0)... };
  119. std::string s = ostr.str ();
  120. s.erase (s.end () - 2, s.end ());
  121. cur_fname = s + ')';
  122. ASSERT (eq_tuples (TUPLE (x, args...)));
  123. return (x + sum (args...));
  124. }
  125. #endif