Line data Source code
1 : ///////////////////////////////////////////////////////////////////////////
2 : // Inastemp - Berenger Bramas MPCDF - 2016
3 : // Under LGPL Licence, please you must read the LICENCE file.
4 : ///////////////////////////////////////////////////////////////////////////
5 : #ifndef UTESTER_HPP
6 : #define UTESTER_HPP
7 :
8 : #include <iostream>
9 : #include <list>
10 : #include <string>
11 : #include <cstdio>
12 : #include <atomic>
13 :
14 : template < class TestClass >
15 : class UTester {
16 : // Test function pointer
17 : typedef void (TestClass::*TestFunc)(void);
18 :
19 : /** Test descriptor */
20 : struct TestFuncDescriptor {
21 : TestFunc func; //< Test adress
22 : std::string name; //< Test name
23 : };
24 :
25 :
26 : std::list< TestFuncDescriptor > tests; //< all tests
27 :
28 : std::atomic<int> totalTests; //< number of tests
29 :
30 : std::atomic<int> currentTest; //< current processing test in the run
31 : std::atomic<int> currentStep; //< current processing step in the run
32 :
33 : std::atomic<int> failedSteps; //< number of failed step in the current test
34 : std::atomic<int> failedTests; //< number of failed tests
35 :
36 : protected:
37 : /** Constructor */
38 25 : UTester() {
39 25 : totalTests = 0;
40 25 : }
41 :
42 25 : virtual ~UTester(){}
43 :
44 : /** Callback before processing test */
45 25 : virtual void Before() {
46 25 : }
47 :
48 : /** Callback after processing test */
49 25 : virtual void After() {
50 25 : }
51 :
52 : /** Callback before each unit test */
53 45 : virtual void PreTest() {
54 45 : }
55 :
56 : /** Callback after each unit test */
57 45 : virtual void PostTest() {
58 45 : }
59 :
60 : /**
61 : * This function has to add tests
62 : * <code> AddTest(&MyTest::TestOne); </code>
63 : */
64 : virtual void SetTests() = 0;
65 :
66 : /**
67 : * Add a test without giving a name
68 : * @param inFunc test function address
69 : */
70 : void AddTest(TestFunc inFunc) {
71 : char buff[256];
72 : sprintf(buff, "Unnamed Test number %d", totalTests + 1);
73 : AddTest(inFunc, buff);
74 : }
75 :
76 : /**
77 : * Add a test with a name
78 : * @param inFunc test function address
79 : * @param inFuncName function name
80 : */
81 45 : void AddTest(TestFunc inFunc, const std::string& inFuncName) {
82 45 : ++totalTests;
83 90 : TestFuncDescriptor desc;
84 45 : desc.func = inFunc;
85 45 : desc.name = inFuncName;
86 45 : tests.push_back(desc);
87 45 : }
88 :
89 285 : void uassertIsTrue(const bool shouldBeTrue,
90 : const std::string str, const int line, const std::string file) {
91 285 : ++currentStep;
92 285 : if (!shouldBeTrue) {
93 0 : std::cout << ">> Step " << currentStep << " Equality Failed: " << str << "\n";
94 0 : std::cout << ">> In file :" << file << "\n";
95 0 : std::cout << ">> At line :" << line << "\n";
96 0 : ++failedSteps;
97 : }
98 285 : }
99 :
100 : template < class ValueType >
101 495054 : void uassertAreEqual(const ValueType v1, const ValueType v2,
102 : const std::string str, const int line, const std::string file) {
103 495054 : ++currentStep;
104 495054 : if (!(v1 == v2)) {
105 0 : std::cout << ">> Step " << currentStep << " Equality Failed: " << str << "\n";
106 0 : std::cout << ">> In file :" << file << "\n";
107 0 : std::cout << ">> At line :" << line << "\n";
108 0 : std::cout << ">> v1 :" << v1 << "\n";
109 0 : std::cout << ">> v2 :" << v2 << "\n";
110 0 : ++failedSteps;
111 : }
112 495054 : }
113 :
114 : template < class ValueType >
115 3 : void uassertAreDiff(const ValueType v1, const ValueType v2,
116 : const std::string str, const int line, const std::string file) {
117 3 : ++currentStep;
118 3 : if (!(v1 != v2)) {
119 0 : std::cout << ">> Step " << currentStep << " Difference Failed: " << str << "\n";
120 0 : std::cout << ">> In file :" << file << "\n";
121 0 : std::cout << ">> At line :" << line << "\n";
122 0 : std::cout << ">> v1 :" << v1 << "\n";
123 0 : std::cout << ">> v2 :" << v2 << "\n";
124 0 : ++failedSteps;
125 : }
126 3 : }
127 :
128 : public:
129 : /**
130 : * Processing the test
131 : * return application exit code (= nb of errors)
132 : */
133 25 : int Run() {
134 25 : tests.clear();
135 : // register tests
136 25 : SetTests();
137 :
138 25 : TestClass* const toTest = static_cast< TestClass* >(this);
139 25 : currentTest = 0;
140 25 : failedTests = 0;
141 :
142 25 : Before();
143 :
144 : // for each tests
145 25 : const typename std::list< TestFuncDescriptor >::const_iterator end = tests.end();
146 70 : for (typename std::list< TestFuncDescriptor >::iterator iter = tests.begin(); iter != end; ++iter) {
147 45 : currentStep = 0;
148 45 : failedSteps = 0;
149 :
150 45 : std::cout << "[Start] " << (*iter).name << "\n";
151 :
152 45 : PreTest();
153 45 : TestFunc ff = (*iter).func;
154 45 : (toTest->*ff)();
155 45 : PostTest();
156 :
157 45 : if (failedSteps) {
158 0 : std::cout << "[Finished] FAILED (" << failedSteps << "/" << currentStep << " steps failed)\n";
159 0 : ++failedTests;
160 : } else {
161 45 : std::cout << "[Finished] PASSED (" << currentStep << " steps)\n";
162 : }
163 :
164 45 : ++currentTest;
165 : }
166 :
167 :
168 25 : After();
169 :
170 25 : std::cout << "Test is over, " << (totalTests - failedTests) << " Passed, " << failedTests << " Failed\n";
171 :
172 50 : return failedTests;
173 : }
174 : };
175 :
176 : #define UASSERTETRUE(condition) \
177 : this->uassertIsTrue(condition, #condition, __LINE__, __FILE__);
178 :
179 : #define UASSERTEEQUAL(v1, v2) \
180 : this->uassertAreEqual(v1, v2, #v1 " == " #v2, __LINE__, __FILE__);
181 :
182 : #define UASSERTEDIFF(v1, v2) \
183 : this->uassertAreDiff(v1, v2, #v1 " != " #v2, __LINE__, __FILE__);
184 :
185 : #define UASSERTETRUE_OFFSET(condition, offset) \
186 : this->uassertIsTrue(condition, #condition, __LINE__ + offset, __FILE__);
187 :
188 : #define UASSERTEEQUAL_OFFSET(v1, v2, offset) \
189 : this->uassertAreEqual(v1, v2, #v1 " == " #v2, __LINE__ + offset, __FILE__);
190 :
191 : #define UASSERTEDIFF_OFFSET(v1, v2, offset) \
192 : this->uassertAreDiff(v1, v2, #v1 " != " #v2, __LINE__ + offset, __FILE__);
193 :
194 : #endif
195 :
196 : #define TestClass(X)\
197 : int main(void){\
198 : X Controller;\
199 : return Controller.Run();\
200 : }
|