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
28class TestResult;
29
30class Test
31{
32public:
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
47protected:
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), \
139std::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__, \
146std::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), \
159std::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__, \
166std::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