OpenMesh

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
TestingFramework.hh
Go to the documentation of this file.
1 /*===========================================================================*\
2 * *
3 * OpenMesh *
4 * Copyright (C) 2001-2012 by Computer Graphics Group, RWTH Aachen *
5 * www.openmesh.org *
6 * *
7 *---------------------------------------------------------------------------*
8 * This file is part of OpenMesh. *
9 * *
10 * OpenMesh is free software: you can redistribute it and/or modify *
11 * it under the terms of the GNU Lesser General Public License as *
12 * published by the Free Software Foundation, either version 3 of *
13 * the License, or (at your option) any later version with the *
14 * following exceptions: *
15 * *
16 * If other files instantiate templates or use macros *
17 * or inline functions from this file, or you compile this file and *
18 * link it with other files to produce an executable, this file does *
19 * not by itself cause the resulting executable to be covered by the *
20 * GNU Lesser General Public License. This exception does not however *
21 * invalidate any other reasons why the executable file might be *
22 * covered by the GNU Lesser General Public License. *
23 * *
24 * OpenMesh is distributed in the hope that it will be useful, *
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27 * GNU Lesser General Public License for more details. *
28 * *
29 * You should have received a copy of the GNU LesserGeneral Public *
30 * License along with OpenMesh. If not, *
31 * see <http://www.gnu.org/licenses/>. *
32 * *
33 \*===========================================================================*/
34
35 /*===========================================================================*\
36 * *
37 * $Revision: 736 $ *
38 * $Date: 2012-10-08 09:30:49 +0200 (Mo, 08 Okt 2012) $ *
39 * *
40 \*===========================================================================*/
41
42 #ifndef TESTINGFRAMEWORK_HH
43 #define TESTINGFRAMEWORK_HH
44 // ----------------------------------------------------------------------------
45
51 // ----------------------------------------------------------------------------
52
53 #include "Config.hh"
54 #include <iosfwd>
55 #include <sstream>
56 #include <vector>
57 #include <algorithm>
58 #include <stdexcept>
59 #include <OpenMesh/Core/Utils/Noncopyable.hh>
60
61 // ------------------------------------------------------------- namespace ----
62
63 namespace OpenMesh { // BEGIN_NS_OPENMESH
64 namespace Utils { // BEGIN_NS_UTILS
65
66
67 // ----------------------------------------------------------------- class ----
68 //
69 // Usage Example
70 //
71 // #include <iostream>
72 // #include <.../TestingFramework.hh>
73 //
74 // struct test_func : public TestingFramework::TestFunc
75 // {
76 // typedef test_func Self;
77 //
78 // // define ctor and copy-ctor
79 // test_func( TestingFramework& _th, std::string _n ) : TestingFramework::TestFunc( _th, _n ) { }
80 // test_func( Self& _cpy ) : TestingFramework::TestFunc(_cpy) { }
81 //
82 // // overload body()
83 // void body()
84 // {
85 //
86 // // Do the tests
87 // // direct call to verify
88 // verify( testResult, expectedResult, "additional information" );
89 //
90 // // or use the define TH_VERIFY. The test-expression will be used as the message string
91 // TH_VERIFY( testResult, expectedResult );
92 //
93 // ...
94 // }
95 // };
96 //
97 // int main(...)
98 // {
99 // TestingFramework testSuite(std::cout); // send output to stdout
100 //
101 // new test_func(testSuite); // create new test instance. It registers with testSuite.
102 // return testSuite.run();
103 // }
104 //
105
106 //
107 #define TH_VERIFY( expr, expt ) \
108 verify( expr, expt, #expr )
109
110 //
111 #define TH_VERIFY_X( expr, expt ) \
112 verify_x( expr, expt, #expr )
113
117 class TestingFramework : Noncopyable
118 {
119 public:
120
121 typedef TestingFramework Self;
122 typedef std::logic_error verify_error;
123
124 #ifndef DOXY_IGNORE_THIS
125 class TestFunc
126 {
127 public:
128 TestFunc( TestingFramework& _th, const std::string& _n )
129 : th_(_th), name_(_n)
130 {
131 th_.reg(this);
132 }
133
134 virtual ~TestFunc()
135 { }
136
137 void operator() ( void )
138 {
139 prolog();
140 try
141 {
142 body();
143 }
144 catch( std::exception& x )
145 {
146 std::cerr << "<<Error>>: Cannot proceed test due to failure of last"
147 << " test: " << x.what() << std::endl;
148 }
149 catch(...)
150 {
151 std::cerr << "Fatal: cannot proceed test due to unknown error!"
152 << std::endl;
153 }
154 epilog();
155 }
156
157 const TestingFramework& testHelper() const { return th_; }
158
159 protected:
160
161 virtual void prolog(void)
162 {
163 begin(name_);
164 }
165
166 virtual void body(void) = 0;
167
168 virtual void epilog(void)
169 {
170 end();
171 }
172
173 protected:
174
175 TestingFramework& testHelper() { return th_; }
176
177 TestFunc( const TestFunc& _cpy ) : th_(_cpy.th_), name_(_cpy.name_) { }
178
179
180 // Use the following method in prolog()
181 TestFunc& begin(std::string _title, const std::string& _info = "")
182 { th_.begin(_title,_info); return *this; }
183
184
185 // Use the following method in epilog()
186 TestFunc& end(void)
187 { th_.end(); return *this; }
188
189
190 // Use the followin methods in body()
191
192 template <typename ValueType>
193 bool
194 verify( const ValueType& _rc, const ValueType& _expected,
195 std::string _info )
196 { return th_.verify( _rc, _expected, _info ); }
197
198 template <typename ValueType>
199 void
200 verify_x( const ValueType& _rc, const ValueType& _expected,
201 std::string _info )
202 {
203 if ( !verify(_rc, _expected, _info) )
204 throw verify_error(_info);
205 }
206
207 TestFunc& info(const std::string& _info)
208 { th_.info(_info); return *this; }
209
210 TestFunc& info(const std::ostringstream& _ostr)
211 { th_.info(_ostr); return *this; }
212
213 private:
214 TestFunc();
215
216 protected:
217 TestingFramework& th_;
218 std::string name_;
219 };
220 #endif
221
222 typedef TestFunc* TestFuncPtr;
223 typedef std::vector<TestFuncPtr> TestSet;
224
225 public:
226
227 TestingFramework(std::ostream& _os)
228 : errTotal_(0), errCount_(0),
229 verifyTotal_(0), verifyCount_(0),
230 testTotal_(0), testCount_(0),
231 os_(_os)
232 { }
233
234 protected:
235
236 #ifndef DOXY_IGNORE_THIS
237 struct TestDeleter
238 {
239 void operator() (TestFuncPtr _tfptr) { delete _tfptr; }
240 };
241 #endif
242
243 public:
244
245 virtual ~TestingFramework()
246 {
247 std::for_each(tests_.begin(), tests_.end(), TestDeleter() );
248 }
249
250 public:
251
252 template <typename ValueType>
253 bool verify(const ValueType& _rc,
254 const ValueType& _expected,
255 const std::string& _info)
256 {
257 ++verifyTotal_;
258 if ( _rc == _expected )
259 {
260 os_ << " " << _info << ", result: " << _rc << ", OK!" << std::endl;
261 return true;
262 }
263 ++errTotal_;
264 os_ << " " << _info << ", result: " << _rc << " != " << _expected
265 << " <<ERROR>>" << std::endl;
266 return false;
267 }
268
269 Self& begin(std::string _title, const std::string& _info = "")
270 {
271 std::ostringstream ostr;
272
273 testTitle_ = _title;
274 errCount_ = errTotal_;
275 ++testTotal_;
276
277 ostr << _title;
278 if ( !_info.empty() )
279 ostr << " ["<< _info << "]";
280 testTitle_ = ostr.str();
281 os_ << "Begin " << testTitle_ << std::endl;
282 return *this;
283 }
284
285 Self& end()
286 {
287 if (errorCount()==0)
288 ++testCount_;
289
290 os_ << "End " << testTitle_ << ": " << errorCount() << " Error(s)." << std::endl;
291 return *this;
292 }
293
294 Self& info(const std::string& _info)
295 {
296 os_ << " + " << _info << std::endl;
297 return *this;
298 }
299
300 Self& info(const std::ostringstream& _ostr)
301 {
302 os_ << " + " << _ostr.str() << std::endl;
303 return *this;
304 }
305
306 size_t errorTotal() const { return errTotal_; }
307 size_t errorCount() const { return errTotal_ - errCount_; }
308 size_t verifyTotal() const { return verifyTotal_; }
309 size_t verifyCount() const { return verifyTotal_ - verifyCount_; }
310 size_t goodTotal() const { return verifyTotal() - errorTotal(); }
311 size_t goodCount() const { return verifyCount() - errorCount(); }
312
313 size_t testTotal() const { return testTotal_; }
314 size_t testCount() const { return testCount_; }
315
316 public:
317
318 int run(void)
319 {
320 os_ << "Test started\n";
321 TestRunner executer;
322 std::for_each(tests_.begin(), tests_.end(), executer );
323 os_ << std::endl;
324 os_ << "All tests completed" << std::endl
325 << " #Tests: " << testCount() << "/" << testTotal() << std::endl
326 << " #Errors: " << errorTotal() << "/" << verifyTotal() << std::endl;
327 return errorTotal();
328 }
329
330 protected:
331
332 #ifndef DOXY_IGNORE_THIS
333 struct TestRunner
334 {
335 void operator() (TestFuncPtr _tfptr) { (*_tfptr)(); }
336 };
337 #endif
338
339 int reg(TestFuncPtr _tfptr)
340 {
341 tests_.push_back(_tfptr);
342 return true;
343 }
344
345 friend class TestFunc;
346
347 private:
348
349 size_t errTotal_;
350 size_t errCount_;
351 size_t verifyTotal_;
352 size_t verifyCount_;
353 size_t testTotal_; // #Tests
354 size_t testCount_; // #Tests ohne Fehler
355
356 std::string testTitle_;
357 std::ostream& os_;
358
359 TestSet tests_;
360
361 };
362
363 // ============================================================================
364 } // END_NS_UTILS
365 } // END_NS_OPENMESH
366 // ============================================================================
367 #endif // TESTINGFRMEWORK_HH
368 // ============================================================================