OpenMesh: OpenMesh/Tools/Utils/TestingFramework.hh Source File

| OpenMesh

TestingFramework.hh
Go to the documentation of this file.
1 /* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openmesh.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenMesh. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 * ========================================================================= */
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $Date$ *
46 * *
47 \*===========================================================================*/
48
49 #ifndef TESTINGFRAMEWORK_HH
50 #define TESTINGFRAMEWORK_HH
51 // ----------------------------------------------------------------------------
52
58 // ----------------------------------------------------------------------------
59
60 #include "Config.hh"
61 #include <iosfwd>
62 #include <sstream>
63 #include <vector>
64 #include <algorithm>
65 #include <stdexcept>
66 #include <OpenMesh/Core/Utils/Noncopyable.hh>
67
68 // ------------------------------------------------------------- namespace ----
69
70 namespace OpenMesh { // BEGIN_NS_OPENMESH
71 namespace Utils { // BEGIN_NS_UTILS
72
73
74 // ----------------------------------------------------------------- class ----
75 //
76 // Usage Example
77 //
78 // #include <iostream>
79 // #include <.../TestingFramework.hh>
80 //
81 // struct test_func : public TestingFramework::TestFunc
82 // {
83 // typedef test_func Self;
84 //
85 // // define ctor and copy-ctor
86 // test_func( TestingFramework& _th, std::string _n ) : TestingFramework::TestFunc( _th, _n ) { }
87 // test_func( Self& _cpy ) : TestingFramework::TestFunc(_cpy) { }
88 //
89 // // overload body()
90 // void body()
91 // {
92 //
93 // // Do the tests
94 // // direct call to verify
95 // verify( testResult, expectedResult, "additional information" );
96 //
97 // // or use the define TH_VERIFY. The test-expression will be used as the message string
98 // TH_VERIFY( testResult, expectedResult );
99 //
100 // ...
101 // }
102 // };
103 //
104 // int main(...)
105 // {
106 // TestingFramework testSuite(std::cout); // send output to stdout
107 //
108 // new test_func(testSuite); // create new test instance. It registers with testSuite.
109 // return testSuite.run();
110 // }
111 //
112
113 //
114 #define TH_VERIFY( expr, expt ) \
115 verify( expr, expt, #expr )
116
117 //
118 #define TH_VERIFY_X( expr, expt ) \
119 verify_x( expr, expt, #expr )
120
124 class TestingFramework : Noncopyable
125 {
126 public:
127
128 typedef TestingFramework Self;
129 typedef std::logic_error verify_error;
130
131 #ifndef DOXY_IGNORE_THIS
132 class TestFunc
133 {
134 public:
135 TestFunc( TestingFramework& _th, const std::string& _n )
136 : th_(_th), name_(_n)
137 {
138 th_.reg(this);
139 }
140
141 virtual ~TestFunc()
142 { }
143
144 void operator() ( void )
145 {
146 prolog();
147 try
148 {
149 body();
150 }
151 catch( std::exception& x )
152 {
153 std::cerr << "<<Error>>: Cannot proceed test due to failure of last"
154 << " test: " << x.what() << std::endl;
155 }
156 catch(...)
157 {
158 std::cerr << "Fatal: cannot proceed test due to unknown error!"
159 << std::endl;
160 }
161 epilog();
162 }
163
164 const TestingFramework& testHelper() const { return th_; }
165
166 protected:
167
168 virtual void prolog(void)
169 {
170 begin(name_);
171 }
172
173 virtual void body(void) = 0;
174
175 virtual void epilog(void)
176 {
177 end();
178 }
179
180 protected:
181
182 TestingFramework& testHelper() { return th_; }
183
184 TestFunc( const TestFunc& _cpy ) : th_(_cpy.th_), name_(_cpy.name_) { }
185
186
187 // Use the following method in prolog()
188 TestFunc& begin(std::string _title, const std::string& _info = "")
189 { th_.begin(_title,_info); return *this; }
190
191
192 // Use the following method in epilog()
193 TestFunc& end(void)
194 { th_.end(); return *this; }
195
196
197 // Use the followin methods in body()
198
199 template <typename ValueType>
200 bool
201 verify( const ValueType& _rc, const ValueType& _expected,
202 std::string _info )
203 { return th_.verify( _rc, _expected, _info ); }
204
205 template <typename ValueType>
206 void
207 verify_x( const ValueType& _rc, const ValueType& _expected,
208 std::string _info )
209 {
210 if ( !verify(_rc, _expected, _info) )
211 throw verify_error(_info);
212 }
213
214 TestFunc& info(const std::string& _info)
215 { th_.info(_info); return *this; }
216
217 TestFunc& info(const std::ostringstream& _ostr)
218 { th_.info(_ostr); return *this; }
219
220 private:
221 TestFunc();
222
223 protected:
224 TestingFramework& th_;
225 std::string name_;
226 };
227 #endif
228
229 typedef TestFunc* TestFuncPtr;
230 typedef std::vector<TestFuncPtr> TestSet;
231
232 public:
233
234 TestingFramework(std::ostream& _os)
235 : errTotal_(0), errCount_(0),
236 verifyTotal_(0), verifyCount_(0),
237 testTotal_(0), testCount_(0),
238 os_(_os)
239 { }
240
241 protected:
242
243 #ifndef DOXY_IGNORE_THIS
244 struct TestDeleter
245 {
246 void operator() (TestFuncPtr _tfptr) { delete _tfptr; }
247 };
248 #endif
249
250 public:
251
252 virtual ~TestingFramework()
253 {
254 std::for_each(tests_.begin(), tests_.end(), TestDeleter() );
255 }
256
257 public:
258
259 template <typename ValueType>
260 bool verify(const ValueType& _rc,
261 const ValueType& _expected,
262 const std::string& _info)
263 {
264 ++verifyTotal_;
265 if ( _rc == _expected )
266 {
267 os_ << " " << _info << ", result: " << _rc << ", OK!" << std::endl;
268 return true;
269 }
270 ++errTotal_;
271 os_ << " " << _info << ", result: " << _rc << " != " << _expected
272 << " <<ERROR>>" << std::endl;
273 return false;
274 }
275
276 Self& begin(std::string _title, const std::string& _info = "")
277 {
278 std::ostringstream ostr;
279
280 testTitle_ = _title;
281 errCount_ = errTotal_;
282 ++testTotal_;
283
284 ostr << _title;
285 if ( !_info.empty() )
286 ostr << " ["<< _info << "]";
287 testTitle_ = ostr.str();
288 os_ << "Begin " << testTitle_ << std::endl;
289 return *this;
290 }
291
292 Self& end()
293 {
294 if (errorCount()==0)
295 ++testCount_;
296
297 os_ << "End " << testTitle_ << ": " << errorCount() << " Error(s)." << std::endl;
298 return *this;
299 }
300
301 Self& info(const std::string& _info)
302 {
303 os_ << " + " << _info << std::endl;
304 return *this;
305 }
306
307 Self& info(const std::ostringstream& _ostr)
308 {
309 os_ << " + " << _ostr.str() << std::endl;
310 return *this;
311 }
312
313 size_t errorTotal() const { return errTotal_; }
314 size_t errorCount() const { return errTotal_ - errCount_; }
315 size_t verifyTotal() const { return verifyTotal_; }
316 size_t verifyCount() const { return verifyTotal_ - verifyCount_; }
317 size_t goodTotal() const { return verifyTotal() - errorTotal(); }
318 size_t goodCount() const { return verifyCount() - errorCount(); }
319
320 size_t testTotal() const { return testTotal_; }
321 size_t testCount() const { return testCount_; }
322
323 public:
324
325 int run(void)
326 {
327 os_ << "Test started\n";
328 TestRunner executer;
329 std::for_each(tests_.begin(), tests_.end(), executer );
330 os_ << std::endl;
331 os_ << "All tests completed" << std::endl
332 << " #Tests: " << testCount() << "/" << testTotal() << std::endl
333 << " #Errors: " << errorTotal() << "/" << verifyTotal() << std::endl;
334 return errorTotal();
335 }
336
337 protected:
338
339 #ifndef DOXY_IGNORE_THIS
340 struct TestRunner
341 {
342 void operator() (TestFuncPtr _tfptr) { (*_tfptr)(); }
343 };
344 #endif
345
346 int reg(TestFuncPtr _tfptr)
347 {
348 tests_.push_back(_tfptr);
349 return true;
350 }
351
352 friend class TestFunc;
353
354 private:
355
356 size_t errTotal_;
357 size_t errCount_;
358 size_t verifyTotal_;
359 size_t verifyCount_;
360 size_t testTotal_; // #Tests
361 size_t testCount_; // #Tests ohne Fehler
362
363 std::string testTitle_;
364 std::ostream& os_;
365
366 TestSet tests_;
367
368 };
369
370 // ============================================================================
371 } // END_NS_UTILS
372 } // END_NS_OPENMESH
373 // ============================================================================
374 #endif // TESTINGFRMEWORK_HH
375 // ============================================================================
OpenMesh::Utils::TestingFramework
Helper class for test programms.
Definition: TestingFramework.hh:124
Config.hh
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:64
OpenMesh::Utils::Noncopyable
This class demonstrates the non copyable idiom.
Definition: Noncopyable.hh:76