- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# Tools/Utils/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 // ============================================================================