Main Page | Modules | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

TestingFramework.hh

Go to the documentation of this file.
00001 // ============================================================================
00002 // $Id: TestingFramework.hh,v 1.1.1.1 2004/09/06 12:37:50 botsch Exp $
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 // ------------------------------------------------------------- namespace ----
00024 
00025 namespace OpenMesh { // BEGIN_NS_OPENMESH
00026 namespace Utils { // BEGIN_NS_UTILS
00027 
00028 
00029 // ----------------------------------------------------------------- class ----
00030 //
00031 // Usage Example
00032 //
00033 // #include <iostream>
00034 // #include <.../TestingFramework.hh>
00035 //
00036 // struct test_func : public TestingFramework::TestFunc
00037 // {
00038 //    typedef test_func Self;
00039 //
00040 //    // define ctor and copy-ctor
00041 //    test_func( TestingFramework& _th, std::string _n ) : TestingFramework::TestFunc( _th, _n ) { }
00042 //    test_func( Self& _cpy ) : TestingFramework::TestFunc(_cpy) { }
00043 //
00044 //    // overload body()
00045 //    void body()
00046 //    {
00047 //
00048 //       // Do the tests
00049 //       // direct call to verify
00050 //       verify( testResult, expectedResult, "additional information" );
00051 //
00052 //       // or use the define TH_VERIFY. The test-expression will be used as the message string
00053 //       TH_VERIFY( testResult, expectedResult );
00054 //
00055 //       ...
00056 //    }
00057 // };
00058 //
00059 // int main(...)
00060 // {
00061 //    TestingFramework testSuite(std::cout); // send output to stdout
00062 //
00063 //    new test_func(testSuite);        // create new test instance. It registers with testSuite.
00064 //    return testSuite.run();
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     // Use the following method in prolog()
00143     TestFunc& begin(std::string _title, const std::string& _info = "")
00144     { th_.begin(_title,_info); return *this; }
00145     
00146     
00147     // Use the following method in epilog()
00148     TestFunc& end(void)
00149     { th_.end(); return *this; }
00150     
00151     
00152     // Use the followin methods in body()
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_;   // #Tests
00316   size_t testCount_;   // #Tests ohne Fehler
00317   
00318   std::string testTitle_;
00319   std::ostream& os_;
00320   
00321   TestSet tests_;
00322   
00323 };
00324 
00325 // ============================================================================
00326 } // END_NS_UTILS
00327 } // END_NS_OPENMESH
00328 // ============================================================================
00329 #endif // TESTINGFRMEWORK_HH
00330 // ============================================================================

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