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 
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 // ============================================================================
Helper class for test programms.
Definition: TestingFramework.hh:124
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:64
This class demonstrates the non copyable idiom.
Definition: Noncopyable.hh:76

Project OpenMesh, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .