| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- #ifndef ANKI_TESTS_FRAMEWORK_FRAMEWORK_H
- #define ANKI_TESTS_FRAMEWORK_FRAMEWORK_H
- #include "anki/util/Vector.h"
- #include "anki/util/Singleton.h"
- #include <stdexcept>
- #include <string>
- #include <iostream>
- #include <sstream>
- #include <cmath>
- namespace anki {
- // Forward
- class TestSuite;
- class Test;
- class Tester;
- /// The actual test
- typedef void (*TestCallback)(Test&);
- /// Test suite
- struct TestSuite
- {
- std::string name;
- PtrVector<Test> tests;
- };
- /// Test
- struct Test
- {
- std::string name;
- TestSuite* suite = nullptr;
- TestCallback callback = nullptr;
- void run();
- };
- /// A container of test suites
- struct Tester
- {
- PtrVector<TestSuite> suites;
- std::string programName;
- void addTest(const char* name, const char* suite, TestCallback callback);
- int run(int argc, char** argv);
- int listTests();
- };
- /// Singleton so we can do the ANKI_TEST trick
- extern Tester& getTesterSingleton();
- /// Delete the instance to make valgrind a bit happy
- extern void deleteTesterSingleton();
- //==============================================================================
- // Macros
- /// Create a new test and add it. It does a trick to add the test by using a
- /// static function
- #define ANKI_TEST(suiteName_, name_) \
- using namespace anki; \
- void test_##suiteName_##name_(Test&); \
- \
- struct Foo##suiteName_##name_ { \
- Foo##suiteName_##name_() { \
- getTesterSingleton().addTest(#name_, #suiteName_, \
- test_##suiteName_##name_); \
- } \
- }; \
- static Foo##suiteName_##name_ yada##suiteName_##name_; \
- void test_##suiteName_##name_(Test&)
- /// Intermediate macro
- #define ANKI_TEST_EXPECT_EQ_IMPL(file_, line_, func_, x, y) \
- do { \
- if((x) != (y)) { \
- std::stringstream ss; \
- ss << #x << " != " << #y << " (" \
- << file_ << ":" << line_ << ")"; \
- throw std::runtime_error(ss.str()); \
- } \
- } while(0);
- /// Intermediate macro
- #define ANKI_TEST_EXPECT_NEQ_IMPL(file_, line_, func_, x, y) \
- do { \
- if((x) == (y)) { \
- std::stringstream ss; \
- ss << #x << " == " << #y << " (" \
- << file_ << ":" << line_ << ")"; \
- throw std::runtime_error(ss.str()); \
- } \
- } while(0);
- /// Intermediate macro
- #define ANKI_TEST_EXPECT_NEAR_IMPL(file_, line_, func_, x, y, epsilon_) \
- do { \
- if(fabs((x) - (y)) > (epsilon_)) { \
- std::stringstream ss; \
- ss << #x << " != " << #y << " (" \
- << file_ << ":" << line_ << ")"; \
- throw std::runtime_error(ss.str()); \
- } \
- } while(0);
- /// Macro to compare equal
- #define ANKI_TEST_EXPECT_EQ(x_, y_) \
- ANKI_TEST_EXPECT_EQ_IMPL(__FILE__, __LINE__, __func__, x_, y_)
- /// Macro to compare equal
- #define ANKI_TEST_EXPECT_NEQ(x_, y_) \
- ANKI_TEST_EXPECT_NEQ_IMPL(__FILE__, __LINE__, __func__, x_, y_)
- /// XXX
- #define ANKI_TEST_EXPECT_NEAR(x_, y_, e_) \
- ANKI_TEST_EXPECT_NEAR_IMPL(__FILE__, __LINE__, __func__, x_, y_, e_)
- } // end namespace anki
- #endif
|