test_macros.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #ifndef SOPUHS_TESTS_MACROS_HPP
  2. #define SOPUHS_TESTS_MACROS_HPP
  3. #include <sophus/types.hpp>
  4. #include <sophus/formatstring.hpp>
  5. namespace Sophus {
  6. namespace details {
  7. template <class Scalar>
  8. class Pretty {
  9. public:
  10. static std::string impl(Scalar s) { return FormatString("%", s); }
  11. };
  12. template <class Scalar, int M, int N>
  13. class Pretty<Eigen::Matrix<Scalar, M, N>> {
  14. public:
  15. static std::string impl(Matrix<Scalar, M, N> const& v) {
  16. return FormatString("\n%\n", v);
  17. }
  18. };
  19. template <class T>
  20. std::string pretty(T const& v) {
  21. return Pretty<T>::impl(v);
  22. }
  23. template <class... Args>
  24. void testFailed(bool& passed, char const* func, char const* file, int line,
  25. std::string const& msg) {
  26. std::cerr << FormatString("Test failed in function %, file %, line %\n", func,
  27. file, line);
  28. std::cerr << msg << "\n\n";
  29. passed = false;
  30. }
  31. } // namespace details
  32. void processTestResult(bool passed) {
  33. if (!passed) {
  34. // LCOV_EXCL_START
  35. std::cerr << "failed!" << std::endl << std::endl;
  36. exit(-1);
  37. // LCOV_EXCL_STOP
  38. }
  39. std::cerr << "passed." << std::endl << std::endl;
  40. }
  41. } // namespace Sophus
  42. #define SOPHUS_STRINGIFY(x) #x
  43. /// GenericTests whether condition is true.
  44. /// The in-out parameter passed will be set to false if test fails.
  45. #define SOPHUS_TEST(passed, condition, ...) \
  46. do { \
  47. if (!(condition)) { \
  48. std::string msg = Sophus::details::FormatString( \
  49. "condition ``%`` is false\n", SOPHUS_STRINGIFY(condition)); \
  50. msg += Sophus::details::FormatString(__VA_ARGS__); \
  51. Sophus::details::testFailed(passed, SOPHUS_FUNCTION, __FILE__, __LINE__, \
  52. msg); \
  53. } \
  54. } while (false)
  55. /// GenericTests whether left is equal to right given a threshold.
  56. /// The in-out parameter passed will be set to false if test fails.
  57. #define SOPHUS_TEST_EQUAL(passed, left, right, ...) \
  58. do { \
  59. if (left != right) { \
  60. std::string msg = Sophus::details::FormatString( \
  61. "% (=%) is not equal to % (=%)\n", SOPHUS_STRINGIFY(left), \
  62. Sophus::details::pretty(left), SOPHUS_STRINGIFY(right), \
  63. Sophus::details::pretty(right)); \
  64. msg += Sophus::details::FormatString(__VA_ARGS__); \
  65. Sophus::details::testFailed(passed, SOPHUS_FUNCTION, __FILE__, __LINE__, \
  66. msg); \
  67. } \
  68. } while (false)
  69. /// GenericTests whether left is equal to right given a threshold.
  70. /// The in-out parameter passed will be set to false if test fails.
  71. #define SOPHUS_TEST_NEQ(passed, left, right, ...) \
  72. do { \
  73. if (left == right) { \
  74. std::string msg = Sophus::details::FormatString( \
  75. "% (=%) shoudl not be equal to % (=%)\n", SOPHUS_STRINGIFY(left), \
  76. Sophus::details::pretty(left), SOPHUS_STRINGIFY(right), \
  77. Sophus::details::pretty(right)); \
  78. msg += Sophus::details::FormatString(__VA_ARGS__); \
  79. Sophus::details::testFailed(passed, SOPHUS_FUNCTION, __FILE__, __LINE__, \
  80. msg); \
  81. } \
  82. } while (false)
  83. /// GenericTests whether left is approximatly equal to right given a threshold.
  84. /// The in-out parameter passed will be set to false if test fails.
  85. #define SOPHUS_TEST_APPROX(passed, left, right, thr, ...) \
  86. do { \
  87. auto nrm = Sophus::maxMetric((left), (right)); \
  88. if (!(nrm < (thr))) { \
  89. std::string msg = Sophus::details::FormatString( \
  90. "% (=%) is not approx % (=%); % is %; nrm is %\n", \
  91. SOPHUS_STRINGIFY(left), Sophus::details::pretty(left), \
  92. SOPHUS_STRINGIFY(right), Sophus::details::pretty(right), \
  93. SOPHUS_STRINGIFY(thr), Sophus::details::pretty(thr), nrm); \
  94. msg += Sophus::details::FormatString(__VA_ARGS__); \
  95. Sophus::details::testFailed(passed, SOPHUS_FUNCTION, __FILE__, __LINE__, \
  96. msg); \
  97. } \
  98. } while (false)
  99. /// GenericTests whether left is NOT approximatly equal to right given a
  100. /// threshold. The in-out parameter passed will be set to false if test fails.
  101. #define SOPHUS_TEST_NOT_APPROX(passed, left, right, thr, ...) \
  102. do { \
  103. auto nrm = Sophus::maxMetric((left), (right)); \
  104. if (nrm < (thr)) { \
  105. std::string msg = Sophus::details::FormatString( \
  106. "% (=%) is approx % (=%), but it should not!\n % is %; nrm is %\n", \
  107. SOPHUS_STRINGIFY(left), Sophus::details::pretty(left), \
  108. SOPHUS_STRINGIFY(right), Sophus::details::pretty(right), \
  109. SOPHUS_STRINGIFY(thr), Sophus::details::pretty(thr), nrm); \
  110. msg += Sophus::details::FormatString(__VA_ARGS__); \
  111. Sophus::details::testFailed(passed, SOPHUS_FUNCTION, __FILE__, __LINE__, \
  112. msg); \
  113. } \
  114. } while (false)
  115. #endif // SOPUHS_TESTS_MACROS_HPP