OpenMesh
|
00001 /*===========================================================================*\ 00002 * * 00003 * OpenMesh * 00004 * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * 00005 * www.openmesh.org * 00006 * * 00007 *---------------------------------------------------------------------------* 00008 * This file is part of OpenMesh. * 00009 * * 00010 * OpenMesh is free software: you can redistribute it and/or modify * 00011 * it under the terms of the GNU Lesser General Public License as * 00012 * published by the Free Software Foundation, either version 3 of * 00013 * the License, or (at your option) any later version with the * 00014 * following exceptions: * 00015 * * 00016 * If other files instantiate templates or use macros * 00017 * or inline functions from this file, or you compile this file and * 00018 * link it with other files to produce an executable, this file does * 00019 * not by itself cause the resulting executable to be covered by the * 00020 * GNU Lesser General Public License. This exception does not however * 00021 * invalidate any other reasons why the executable file might be * 00022 * covered by the GNU Lesser General Public License. * 00023 * * 00024 * OpenMesh is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU Lesser General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU LesserGeneral Public * 00030 * License along with OpenMesh. If not, * 00031 * see <http://www.gnu.org/licenses/>. * 00032 * * 00033 \*===========================================================================*/ 00034 00035 /*===========================================================================*\ 00036 * * 00037 * $Revision: 362 $ * 00038 * $Date: 2011-01-26 10:21:12 +0100 (Mi, 26 Jan 2011) $ * 00039 * * 00040 \*===========================================================================*/ 00041 00042 #ifndef TESTINGFRAMEWORK_HH 00043 #define TESTINGFRAMEWORK_HH 00044 // ---------------------------------------------------------------------------- 00045 00051 // ---------------------------------------------------------------------------- 00052 00053 #include "Config.hh" 00054 #include <iosfwd> 00055 #include <sstream> 00056 #include <vector> 00057 #include <algorithm> 00058 #include <stdexcept> 00059 #include <OpenMesh/Core/Utils/Noncopyable.hh> 00060 00061 // ------------------------------------------------------------- namespace ---- 00062 00063 namespace OpenMesh { // BEGIN_NS_OPENMESH 00064 namespace Utils { // BEGIN_NS_UTILS 00065 00066 00067 // ----------------------------------------------------------------- class ---- 00068 // 00069 // Usage Example 00070 // 00071 // #include <iostream> 00072 // #include <.../TestingFramework.hh> 00073 // 00074 // struct test_func : public TestingFramework::TestFunc 00075 // { 00076 // typedef test_func Self; 00077 // 00078 // // define ctor and copy-ctor 00079 // test_func( TestingFramework& _th, std::string _n ) : TestingFramework::TestFunc( _th, _n ) { } 00080 // test_func( Self& _cpy ) : TestingFramework::TestFunc(_cpy) { } 00081 // 00082 // // overload body() 00083 // void body() 00084 // { 00085 // 00086 // // Do the tests 00087 // // direct call to verify 00088 // verify( testResult, expectedResult, "additional information" ); 00089 // 00090 // // or use the define TH_VERIFY. The test-expression will be used as the message string 00091 // TH_VERIFY( testResult, expectedResult ); 00092 // 00093 // ... 00094 // } 00095 // }; 00096 // 00097 // int main(...) 00098 // { 00099 // TestingFramework testSuite(std::cout); // send output to stdout 00100 // 00101 // new test_func(testSuite); // create new test instance. It registers with testSuite. 00102 // return testSuite.run(); 00103 // } 00104 // 00105 00106 // 00107 #define TH_VERIFY( expr, expt ) \ 00108 verify( expr, expt, #expr ) 00109 00110 // 00111 #define TH_VERIFY_X( expr, expt ) \ 00112 verify_x( expr, expt, #expr ) 00113 00117 class TestingFramework : Noncopyable 00118 { 00119 public: 00120 00121 typedef TestingFramework Self; 00122 typedef std::logic_error verify_error; 00123 00124 #ifndef DOXY_IGNORE_THIS 00125 class TestFunc 00126 { 00127 public: 00128 TestFunc( TestingFramework& _th, const std::string& _n ) 00129 : th_(_th), name_(_n) 00130 { 00131 th_.reg(this); 00132 } 00133 00134 virtual ~TestFunc() 00135 { } 00136 00137 void operator() ( void ) 00138 { 00139 prolog(); 00140 try 00141 { 00142 body(); 00143 } 00144 catch( std::exception& x ) 00145 { 00146 std::cerr << "<<Error>>: Cannot proceed test due to failure of last" 00147 << " test: " << x.what() << std::endl; 00148 } 00149 catch(...) 00150 { 00151 std::cerr << "Fatal: cannot proceed test due to unknown error!" 00152 << std::endl; 00153 } 00154 epilog(); 00155 } 00156 00157 const TestingFramework& testHelper() const { return th_; } 00158 00159 protected: 00160 00161 virtual void prolog(void) 00162 { 00163 begin(name_); 00164 } 00165 00166 virtual void body(void) = 0; 00167 00168 virtual void epilog(void) 00169 { 00170 end(); 00171 } 00172 00173 protected: 00174 00175 TestingFramework& testHelper() { return th_; } 00176 00177 TestFunc( const TestFunc& _cpy ) : th_(_cpy.th_), name_(_cpy.name_) { } 00178 00179 00180 // Use the following method in prolog() 00181 TestFunc& begin(std::string _title, const std::string& _info = "") 00182 { th_.begin(_title,_info); return *this; } 00183 00184 00185 // Use the following method in epilog() 00186 TestFunc& end(void) 00187 { th_.end(); return *this; } 00188 00189 00190 // Use the followin methods in body() 00191 00192 template <typename ValueType> 00193 bool 00194 verify( const ValueType& _rc, const ValueType& _expected, 00195 std::string _info ) 00196 { return th_.verify( _rc, _expected, _info ); } 00197 00198 template <typename ValueType> 00199 void 00200 verify_x( const ValueType& _rc, const ValueType& _expected, 00201 std::string _info ) 00202 { 00203 if ( !verify(_rc, _expected, _info) ) 00204 throw verify_error(_info); 00205 } 00206 00207 TestFunc& info(const std::string& _info) 00208 { th_.info(_info); return *this; } 00209 00210 TestFunc& info(const std::ostringstream& _ostr) 00211 { th_.info(_ostr); return *this; } 00212 00213 private: 00214 TestFunc(); 00215 00216 protected: 00217 TestingFramework& th_; 00218 std::string name_; 00219 }; 00220 #endif 00221 00222 typedef TestFunc* TestFuncPtr; 00223 typedef std::vector<TestFuncPtr> TestSet; 00224 00225 public: 00226 00227 TestingFramework(std::ostream& _os) 00228 : errTotal_(0), errCount_(0), 00229 verifyTotal_(0), verifyCount_(0), 00230 testTotal_(0), testCount_(0), 00231 os_(_os) 00232 { } 00233 00234 protected: 00235 00236 #ifndef DOXY_IGNORE_THIS 00237 struct TestDeleter 00238 { 00239 void operator() (TestFuncPtr _tfptr) { delete _tfptr; } 00240 }; 00241 #endif 00242 00243 public: 00244 00245 virtual ~TestingFramework() 00246 { 00247 std::for_each(tests_.begin(), tests_.end(), TestDeleter() ); 00248 } 00249 00250 public: 00251 00252 template <typename ValueType> 00253 bool verify(const ValueType& _rc, 00254 const ValueType& _expected, 00255 const std::string& _info) 00256 { 00257 ++verifyTotal_; 00258 if ( _rc == _expected ) 00259 { 00260 os_ << " " << _info << ", result: " << _rc << ", OK!" << std::endl; 00261 return true; 00262 } 00263 ++errTotal_; 00264 os_ << " " << _info << ", result: " << _rc << " != " << _expected 00265 << " <<ERROR>>" << std::endl; 00266 return false; 00267 } 00268 00269 Self& begin(std::string _title, const std::string& _info = "") 00270 { 00271 std::ostringstream ostr; 00272 00273 testTitle_ = _title; 00274 errCount_ = errTotal_; 00275 ++testTotal_; 00276 00277 ostr << _title; 00278 if ( !_info.empty() ) 00279 ostr << " ["<< _info << "]"; 00280 testTitle_ = ostr.str(); 00281 os_ << "Begin " << testTitle_ << std::endl; 00282 return *this; 00283 } 00284 00285 Self& end() 00286 { 00287 if (errorCount()==0) 00288 ++testCount_; 00289 00290 os_ << "End " << testTitle_ << ": " << errorCount() << " Error(s)." << std::endl; 00291 return *this; 00292 } 00293 00294 Self& info(const std::string& _info) 00295 { 00296 os_ << " + " << _info << std::endl; 00297 return *this; 00298 } 00299 00300 Self& info(const std::ostringstream& _ostr) 00301 { 00302 os_ << " + " << _ostr.str() << std::endl; 00303 return *this; 00304 } 00305 00306 size_t errorTotal() const { return errTotal_; } 00307 size_t errorCount() const { return errTotal_ - errCount_; } 00308 size_t verifyTotal() const { return verifyTotal_; } 00309 size_t verifyCount() const { return verifyTotal_ - verifyCount_; } 00310 size_t goodTotal() const { return verifyTotal() - errorTotal(); } 00311 size_t goodCount() const { return verifyCount() - errorCount(); } 00312 00313 size_t testTotal() const { return testTotal_; } 00314 size_t testCount() const { return testCount_; } 00315 00316 public: 00317 00318 int run(void) 00319 { 00320 os_ << "Test started\n"; 00321 TestRunner executer; 00322 std::for_each(tests_.begin(), tests_.end(), executer ); 00323 os_ << std::endl; 00324 os_ << "All tests completed" << std::endl 00325 << " #Tests: " << testCount() << "/" << testTotal() << std::endl 00326 << " #Errors: " << errorTotal() << "/" << verifyTotal() << std::endl; 00327 return errorTotal(); 00328 } 00329 00330 protected: 00331 00332 #ifndef DOXY_IGNORE_THIS 00333 struct TestRunner 00334 { 00335 void operator() (TestFuncPtr _tfptr) { (*_tfptr)(); } 00336 }; 00337 #endif 00338 00339 int reg(TestFuncPtr _tfptr) 00340 { 00341 tests_.push_back(_tfptr); 00342 return true; 00343 } 00344 00345 friend class TestFunc; 00346 00347 private: 00348 00349 size_t errTotal_; 00350 size_t errCount_; 00351 size_t verifyTotal_; 00352 size_t verifyCount_; 00353 size_t testTotal_; // #Tests 00354 size_t testCount_; // #Tests ohne Fehler 00355 00356 std::string testTitle_; 00357 std::ostream& os_; 00358 00359 TestSet tests_; 00360 00361 }; 00362 00363 // ============================================================================ 00364 } // END_NS_UTILS 00365 } // END_NS_OPENMESH 00366 // ============================================================================ 00367 #endif // TESTINGFRMEWORK_HH 00368 // ============================================================================