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