00001
00002
00003
00004 #ifndef TESTINGFRAMEWORK_HH
00005 #define TESTINGFRAMEWORK_HH
00006
00007
00013
00014
00015 #include "Config.hh"
00016 #include <iosfwd>
00017 #include <sstream>
00018 #include <vector>
00019 #include <algorithm>
00020 #include <stdexcept>
00021 #include <OpenMesh/Core/Utils/Noncopyable.hh>
00022
00023
00024
00025 namespace OpenMesh {
00026 namespace Utils {
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #define TH_VERIFY( expr, expt ) \
00070 verify( expr, expt, #expr )
00071
00072
00073 #define TH_VERIFY_X( expr, expt ) \
00074 verify_x( expr, expt, #expr )
00075
00079 class TestingFramework : Noncopyable
00080 {
00081 public:
00082
00083 typedef TestingFramework Self;
00084 typedef std::logic_error verify_error;
00085
00086 #ifndef DOXY_IGNORE_THIS
00087 class TestFunc
00088 {
00089 public:
00090 TestFunc( TestingFramework& _th, const std::string& _n )
00091 : th_(_th), name_(_n)
00092 {
00093 th_.reg(this);
00094 }
00095
00096 virtual ~TestFunc()
00097 { }
00098
00099 void operator() ( void )
00100 {
00101 prolog();
00102 try
00103 {
00104 body();
00105 }
00106 catch( std::exception& x )
00107 {
00108 std::cerr << "<<Error>>: Cannot proceed test due to failure of last"
00109 << " test: " << x.what() << std::endl;
00110 }
00111 catch(...)
00112 {
00113 std::cerr << "Fatal: cannot proceed test due to unknown error!"
00114 << std::endl;
00115 }
00116 epilog();
00117 }
00118
00119 const TestingFramework& testHelper() const { return th_; }
00120
00121 protected:
00122
00123 virtual void prolog(void)
00124 {
00125 begin(name_);
00126 }
00127
00128 virtual void body(void) = 0;
00129
00130 virtual void epilog(void)
00131 {
00132 end();
00133 }
00134
00135 protected:
00136
00137 TestingFramework& testHelper() { return th_; }
00138
00139 TestFunc( const TestFunc& _cpy ) : th_(_cpy.th_), name_(_cpy.name_) { }
00140
00141
00142
00143 TestFunc& begin(std::string _title, const std::string& _info = "")
00144 { th_.begin(_title,_info); return *this; }
00145
00146
00147
00148 TestFunc& end(void)
00149 { th_.end(); return *this; }
00150
00151
00152
00153
00154 template <typename ValueType>
00155 bool
00156 verify( const ValueType& _rc, const ValueType& _expected,
00157 std::string _info )
00158 { return th_.verify( _rc, _expected, _info ); }
00159
00160 template <typename ValueType>
00161 void
00162 verify_x( const ValueType& _rc, const ValueType& _expected,
00163 std::string _info )
00164 {
00165 if ( !verify(_rc, _expected, _info) )
00166 throw verify_error(_info);
00167 }
00168
00169 TestFunc& info(const std::string& _info)
00170 { th_.info(_info); return *this; }
00171
00172 TestFunc& info(const std::ostringstream& _ostr)
00173 { th_.info(_ostr); return *this; }
00174
00175 private:
00176 TestFunc();
00177
00178 protected:
00179 TestingFramework& th_;
00180 std::string name_;
00181 };
00182 #endif
00183
00184 typedef TestFunc* TestFuncPtr;
00185 typedef std::vector<TestFuncPtr> TestSet;
00186
00187 public:
00188
00189 TestingFramework(std::ostream& _os)
00190 : errTotal_(0), errCount_(0),
00191 verifyTotal_(0), verifyCount_(0),
00192 testTotal_(0), testCount_(0),
00193 os_(_os)
00194 { }
00195
00196 protected:
00197
00198 #ifndef DOXY_IGNORE_THIS
00199 struct TestDeleter
00200 {
00201 void operator() (TestFuncPtr _tfptr) { delete _tfptr; }
00202 };
00203 #endif
00204
00205 public:
00206
00207 virtual ~TestingFramework()
00208 {
00209 std::for_each(tests_.begin(), tests_.end(), TestDeleter() );
00210 }
00211
00212 public:
00213
00214 template <typename ValueType>
00215 bool verify(const ValueType& _rc,
00216 const ValueType& _expected,
00217 const std::string& _info)
00218 {
00219 ++verifyTotal_;
00220 if ( _rc == _expected )
00221 {
00222 os_ << " " << _info << ", result: " << _rc << ", OK!" << std::endl;
00223 return true;
00224 }
00225 ++errTotal_;
00226 os_ << " " << _info << ", result: " << _rc << " != " << _expected
00227 << " <<ERROR>>" << std::endl;
00228 return false;
00229 }
00230
00231 Self& begin(std::string _title, const std::string& _info = "")
00232 {
00233 std::ostringstream ostr;
00234
00235 testTitle_ = _title;
00236 errCount_ = errTotal_;
00237 ++testTotal_;
00238
00239 ostr << _title;
00240 if ( !_info.empty() )
00241 ostr << " ["<< _info << "]";
00242 testTitle_ = ostr.str();
00243 os_ << "Begin " << testTitle_ << std::endl;
00244 return *this;
00245 }
00246
00247 Self& end()
00248 {
00249 if (errorCount()==0)
00250 ++testCount_;
00251
00252 os_ << "End " << testTitle_ << ": " << errorCount() << " Error(s)." << std::endl;
00253 return *this;
00254 }
00255
00256 Self& info(const std::string& _info)
00257 {
00258 os_ << " + " << _info << std::endl;
00259 return *this;
00260 }
00261
00262 Self& info(const std::ostringstream& _ostr)
00263 {
00264 os_ << " + " << _ostr.str() << std::endl;
00265 return *this;
00266 }
00267
00268 size_t errorTotal() const { return errTotal_; }
00269 size_t errorCount() const { return errTotal_ - errCount_; }
00270 size_t verifyTotal() const { return verifyTotal_; }
00271 size_t verifyCount() const { return verifyTotal_ - verifyCount_; }
00272 size_t goodTotal() const { return verifyTotal() - errorTotal(); }
00273 size_t goodCount() const { return verifyCount() - errorCount(); }
00274
00275 size_t testTotal() const { return testTotal_; }
00276 size_t testCount() const { return testCount_; }
00277
00278 public:
00279
00280 int run(void)
00281 {
00282 os_ << "Test started\n";
00283 TestRunner executer;
00284 std::for_each(tests_.begin(), tests_.end(), executer );
00285 os_ << std::endl;
00286 os_ << "All tests completed" << std::endl
00287 << " #Tests: " << testCount() << "/" << testTotal() << std::endl
00288 << " #Errors: " << errorTotal() << "/" << verifyTotal() << std::endl;
00289 return errorTotal();
00290 }
00291
00292 protected:
00293
00294 #ifndef DOXY_IGNORE_THIS
00295 struct TestRunner
00296 {
00297 void operator() (TestFuncPtr _tfptr) { (*_tfptr)(); }
00298 };
00299 #endif
00300
00301 int reg(TestFuncPtr _tfptr)
00302 {
00303 tests_.push_back(_tfptr);
00304 return true;
00305 }
00306
00307 friend class TestFunc;
00308
00309 private:
00310
00311 size_t errTotal_;
00312 size_t errCount_;
00313 size_t verifyTotal_;
00314 size_t verifyCount_;
00315 size_t testTotal_;
00316 size_t testCount_;
00317
00318 std::string testTitle_;
00319 std::ostream& os_;
00320
00321 TestSet tests_;
00322
00323 };
00324
00325
00326 }
00327 }
00328
00329 #endif // TESTINGFRMEWORK_HH
00330