| 1 | /* ---------------------------------------------------------------------------- |
| 2 | |
| 3 | * GTSAM Copyright 2010, Georgia Tech Research Corporation, |
| 4 | * Atlanta, Georgia 30332-0415 |
| 5 | * All Rights Reserved |
| 6 | * Authors: Frank Dellaert, et al. (see THANKS for the full author list) |
| 7 | |
| 8 | * See LICENSE for the license information |
| 9 | |
| 10 | * -------------------------------------------------------------------------- */ |
| 11 | |
| 12 | /////////////////////////////////////////////////////////////////////////////// |
| 13 | // |
| 14 | // TEST.H |
| 15 | // |
| 16 | // This file contains the Test class along with the macros which make effective |
| 17 | // in the harness. |
| 18 | // |
| 19 | /////////////////////////////////////////////////////////////////////////////// |
| 20 | |
| 21 | #ifndef TEST_H |
| 22 | #define TEST_H |
| 23 | |
| 24 | |
| 25 | #include <cmath> |
| 26 | #include <string> |
| 27 | |
| 28 | class TestResult; |
| 29 | |
| 30 | class Test |
| 31 | { |
| 32 | public: |
| 33 | Test (const std::string& testName); |
| 34 | Test (const std::string& testName, const std::string& filename, long lineNumber, bool safeCheck); |
| 35 | virtual ~Test() {} |
| 36 | |
| 37 | virtual void run (TestResult& result) = 0; |
| 38 | |
| 39 | |
| 40 | void setNext(Test *test); |
| 41 | Test *getNext () const; |
| 42 | std::string getName() const {return name_;} |
| 43 | std::string getFilename() const {return filename_;} |
| 44 | long getLineNumber() const {return lineNumber_;} |
| 45 | bool safe() const {return safeCheck_;} |
| 46 | |
| 47 | protected: |
| 48 | |
| 49 | bool check (long expected, long actual, TestResult& result, const std::string& fileName, long lineNumber); |
| 50 | bool check (const std::string& expected, const std::string& actual, TestResult& result, const std::string& fileName, long lineNumber); |
| 51 | |
| 52 | std::string name_; |
| 53 | Test *next_; |
| 54 | std::string filename_; |
| 55 | long lineNumber_; /// This is the line line number of the test, rather than the a single check |
| 56 | bool safeCheck_; |
| 57 | |
| 58 | }; |
| 59 | |
| 60 | /** |
| 61 | * Normal test will wrap execution in a try/catch block to catch exceptions more effectively |
| 62 | */ |
| 63 | #define TEST(testGroup, testName)\ |
| 64 | class testGroup##testName##Test : public Test \ |
| 65 | { public: testGroup##testName##Test () : Test (#testName "Test", __FILE__, __LINE__, true) {} \ |
| 66 | void run (TestResult& result_) override;} \ |
| 67 | testGroup##testName##Instance; \ |
| 68 | void testGroup##testName##Test::run (TestResult& result_) |
| 69 | |
| 70 | /** |
| 71 | * Declare friend in a class to test its private methods |
| 72 | */ |
| 73 | #define FRIEND_TEST(testGroup, testName) \ |
| 74 | friend class testGroup##testName##Test; |
| 75 | |
| 76 | /** |
| 77 | * For debugging only: use TEST_UNSAFE to allow debuggers to have access to exceptions, as this |
| 78 | * will not wrap execution with a try/catch block |
| 79 | */ |
| 80 | #define TEST_UNSAFE(testGroup, testName)\ |
| 81 | class testGroup##testName##Test : public Test \ |
| 82 | { public: testGroup##testName##Test () : Test (#testName "Test", __FILE__, __LINE__, false) {} \ |
| 83 | virtual ~testGroup##testName##Test () {} \ |
| 84 | void run (TestResult& result_) override;} \ |
| 85 | testGroup##testName##Instance; \ |
| 86 | void testGroup##testName##Test::run (TestResult& result_) |
| 87 | |
| 88 | /** |
| 89 | * Use this to disable unwanted tests without commenting them out. |
| 90 | */ |
| 91 | #define TEST_DISABLED(testGroup, testName)\ |
| 92 | void testGroup##testName##Test(TestResult& result_, const std::string& name_) |
| 93 | |
| 94 | /* |
| 95 | * Convention for tests: |
| 96 | * - "EXPECT" is a test that will not end execution of the series of tests |
| 97 | * - Otherwise, upon a failure, the test will end |
| 98 | * |
| 99 | * Usage: |
| 100 | * EXPECT is useful when checking several different parts of an condition so |
| 101 | * that a failure of one check won't hide another failure. |
| 102 | * |
| 103 | * Note: Exception tests are not available in a EXPECT form, as exceptions rarely |
| 104 | * fit the criteria of an assertion that does not need to be true to continue |
| 105 | */ |
| 106 | |
| 107 | /* True ASSERTs: tests end at first failure */ |
| 108 | #define CHECK(condition)\ |
| 109 | { if (!(condition)) \ |
| 110 | { result_.addFailure (Failure (name_, __FILE__,__LINE__, #condition)); return; } } |
| 111 | |
| 112 | #define THROWS_EXCEPTION(condition)\ |
| 113 | { try { condition; \ |
| 114 | result_.addFailure (Failure (name_, __FILE__,__LINE__, std::string("Didn't throw: ") + std::string(#condition))); \ |
| 115 | return; } \ |
| 116 | catch (...) {} } |
| 117 | |
| 118 | #define CHECK_EXCEPTION(condition, exception_name)\ |
| 119 | { try { condition; \ |
| 120 | result_.addFailure (Failure (name_, __FILE__,__LINE__, std::string("Didn't throw: ") + std::string(#condition))); \ |
| 121 | return; } \ |
| 122 | catch (exception_name&) {} \ |
| 123 | catch (...) { \ |
| 124 | result_.addFailure (Failure (name_, __FILE__,__LINE__, std::string("Wrong exception: ") + std::string(#condition) + std::string(", expected: ") + std::string(#exception_name))); \ |
| 125 | return; } } |
| 126 | |
| 127 | #define EQUALITY(expected,actual)\ |
| 128 | { if (!assert_equal(expected,actual)) \ |
| 129 | result_.addFailure(Failure(name_, __FILE__, __LINE__, #expected, #actual)); } |
| 130 | |
| 131 | #define CHECK_EQUAL(expected,actual)\ |
| 132 | { if (!((expected) == (actual))) { result_.addFailure(Failure(name_, __FILE__, __LINE__, std::to_string(expected), std::to_string(actual))); return; } } |
| 133 | |
| 134 | #define LONGS_EQUAL(expected,actual)\ |
| 135 | { long actualTemp = actual; \ |
| 136 | long expectedTemp = expected; \ |
| 137 | if ((expectedTemp) != (actualTemp)) \ |
| 138 | { result_.addFailure (Failure (name_, __FILE__, __LINE__, std::to_string(expectedTemp), \ |
| 139 | std::to_string(actualTemp))); return; } } |
| 140 | |
| 141 | #define DOUBLES_EQUAL(expected,actual,threshold)\ |
| 142 | { double actualTemp = actual; \ |
| 143 | double expectedTemp = expected; \ |
| 144 | if (!std::isfinite(actualTemp) || !std::isfinite(expectedTemp) || fabs ((expectedTemp)-(actualTemp)) > threshold) \ |
| 145 | { result_.addFailure (Failure (name_, __FILE__, __LINE__, \ |
| 146 | std::to_string((double)expectedTemp), std::to_string((double)actualTemp))); return; } } |
| 147 | |
| 148 | |
| 149 | /* EXPECTs: tests will continue running after a failure */ |
| 150 | #define EXPECT(condition)\ |
| 151 | { if (!(condition)) \ |
| 152 | { result_.addFailure (Failure (name_, __FILE__,__LINE__, #condition)); } } |
| 153 | |
| 154 | #define EXPECT_LONGS_EQUAL(expected,actual)\ |
| 155 | { long actualTemp = actual; \ |
| 156 | long expectedTemp = expected; \ |
| 157 | if ((expectedTemp) != (actualTemp)) \ |
| 158 | { result_.addFailure (Failure (name_, __FILE__, __LINE__, std::to_string(expectedTemp), \ |
| 159 | std::to_string(actualTemp))); } } |
| 160 | |
| 161 | #define EXPECT_DOUBLES_EQUAL(expected,actual,threshold)\ |
| 162 | { double actualTemp = actual; \ |
| 163 | double expectedTemp = expected; \ |
| 164 | if (!std::isfinite(actualTemp) || !std::isfinite(expectedTemp) || fabs ((expectedTemp)-(actualTemp)) > threshold) \ |
| 165 | { result_.addFailure (Failure (name_, __FILE__, __LINE__, \ |
| 166 | std::to_string((double)expectedTemp), std::to_string((double)actualTemp))); } } |
| 167 | |
| 168 | |
| 169 | #define FAIL(text) \ |
| 170 | { result_.addFailure (Failure (name_, __FILE__, __LINE__,(text))); return; } |
| 171 | |
| 172 | |
| 173 | |
| 174 | #endif |
| 175 | |