Framework.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright (C) 2014, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #ifndef ANKI_TESTS_FRAMEWORK_FRAMEWORK_H
  6. #define ANKI_TESTS_FRAMEWORK_FRAMEWORK_H
  7. #include "anki/util/Vector.h"
  8. #include "anki/util/Singleton.h"
  9. #include <stdexcept>
  10. #include <string>
  11. #include <iostream>
  12. #include <sstream>
  13. #include <cmath>
  14. namespace anki {
  15. // Forward
  16. class TestSuite;
  17. class Test;
  18. class Tester;
  19. /// The actual test
  20. typedef void (*TestCallback)(Test&);
  21. /// Test suite
  22. class TestSuite
  23. {
  24. public:
  25. std::string name;
  26. Vector<Test*> tests;
  27. ~TestSuite();
  28. };
  29. /// Test
  30. class Test
  31. {
  32. public:
  33. std::string name;
  34. TestSuite* suite = nullptr;
  35. TestCallback callback = nullptr;
  36. void run();
  37. };
  38. /// A container of test suites
  39. class Tester
  40. {
  41. public:
  42. Vector<TestSuite*> suites;
  43. std::string programName;
  44. void addTest(const char* name, const char* suite, TestCallback callback);
  45. int run(int argc, char** argv);
  46. int listTests();
  47. ~Tester()
  48. {
  49. for(TestSuite* s : suites)
  50. {
  51. delete s;
  52. }
  53. }
  54. };
  55. /// Singleton so we can do the ANKI_TEST trick
  56. extern Tester& getTesterSingleton();
  57. /// Delete the instance to make valgrind a bit happy
  58. extern void deleteTesterSingleton();
  59. //==============================================================================
  60. // Macros
  61. /// Create a new test and add it. It does a trick to add the test by using a
  62. /// static function
  63. #define ANKI_TEST(suiteName_, name_) \
  64. using namespace anki; \
  65. void test_##suiteName_##name_(Test&); \
  66. \
  67. struct Foo##suiteName_##name_ { \
  68. Foo##suiteName_##name_() { \
  69. getTesterSingleton().addTest(#name_, #suiteName_, \
  70. test_##suiteName_##name_); \
  71. } \
  72. }; \
  73. static Foo##suiteName_##name_ yada##suiteName_##name_; \
  74. void test_##suiteName_##name_(Test&)
  75. /// Intermediate macro
  76. #define ANKI_TEST_EXPECT_EQ_IMPL(file_, line_, func_, x, y) \
  77. do { \
  78. if((x) != (y)) { \
  79. std::stringstream ss; \
  80. ss << "FAILURE: " << #x << " != " << #y << " (" \
  81. << file_ << ":" << line_ << ")"; \
  82. throw std::runtime_error(ss.str()); \
  83. } \
  84. } while(0);
  85. /// Intermediate macro
  86. #define ANKI_TEST_EXPECT_NEQ_IMPL(file_, line_, func_, x, y) \
  87. do { \
  88. if((x) == (y)) { \
  89. std::stringstream ss; \
  90. ss << "FAILURE: " << #x << " == " << #y << " (" \
  91. << file_ << ":" << line_ << ")"; \
  92. throw std::runtime_error(ss.str()); \
  93. } \
  94. } while(0);
  95. /// Intermediate macro
  96. #define ANKI_TEST_EXPECT_NEAR_IMPL(file_, line_, func_, x, y, epsilon_) \
  97. do { \
  98. if(abs((x) - (y)) > (epsilon_)) { \
  99. std::stringstream ss; \
  100. ss << "FAILURE: " << #x << " != " << #y << " (" \
  101. << file_ << ":" << line_ << ")"; \
  102. throw std::runtime_error(ss.str()); \
  103. } \
  104. } while(0);
  105. /// Macro to compare equal
  106. #define ANKI_TEST_EXPECT_EQ(x_, y_) \
  107. ANKI_TEST_EXPECT_EQ_IMPL(__FILE__, __LINE__, __func__, x_, y_)
  108. /// Macro to compare equal
  109. #define ANKI_TEST_EXPECT_NEQ(x_, y_) \
  110. ANKI_TEST_EXPECT_NEQ_IMPL(__FILE__, __LINE__, __func__, x_, y_)
  111. /// Compare floats with epsilon
  112. #define ANKI_TEST_EXPECT_NEAR(x_, y_, e_) \
  113. ANKI_TEST_EXPECT_NEAR_IMPL(__FILE__, __LINE__, __func__, x_, y_, e_)
  114. } // end namespace anki
  115. #endif