Osi  trunk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
OsiUnitTests.hpp
Go to the documentation of this file.
00001 // Copyright (C) 2010
00002 // All Rights Reserved.
00003 // This code is licensed under the terms of the Eclipse Public License (EPL).
00004 
00010 #ifndef OSISOLVERINTERFACETEST_HPP_
00011 #define OSISOLVERINTERFACETEST_HPP_
00012 
00013 #include <cstdio>
00014 #include <cstdlib>
00015 #include <iostream>
00016 #include <string>
00017 #include <sstream>
00018 #include <vector>
00019 #include <list>
00020 #include <map>
00021 
00022 class OsiSolverInterface;
00023 class CoinPackedVectorBase;
00024 
00038 void OsiSolverInterfaceMpsUnitTest
00039   (const std::vector<OsiSolverInterface*> & vecEmptySiP,
00040    const std::string& mpsDir);
00041 
00046 void OsiSolverInterfaceCommonUnitTest
00047   (const OsiSolverInterface* emptySi,
00048    const std::string& mpsDir,
00049    const std::string& netlibDir);
00050 
00052 void OsiColCutUnitTest
00053   (const OsiSolverInterface * baseSiP,
00054    const std::string & mpsDir);
00055 
00057 void OsiRowCutUnitTest
00058   (const OsiSolverInterface * baseSiP,
00059    const std::string & mpsDir);
00060 
00062 void OsiRowCutDebuggerUnitTest
00063   (const OsiSolverInterface * siP,
00064    const std::string & mpsDir);
00065 
00067 void OsiCutsUnitTest();
00068 
00070 namespace OsiUnitTest {
00071 
00072 class TestOutcomes;
00073 
00078 extern unsigned int verbosity;
00079 
00086 extern unsigned int haltonerror;
00087 
00093 extern TestOutcomes outcomes;
00094 
00102 void failureMessage(const std::string &solverName,
00103                     const std::string &message) ;
00105 void failureMessage(const OsiSolverInterface &si,
00106                     const std::string &message) ;
00107 
00114 void failureMessage(const std::string &solverName,
00115                     const std::string &testname, const std::string &testcond) ;
00116 
00118 void failureMessage(const OsiSolverInterface &si,
00119                     const std::string &testname, const std::string &testcond) ;
00120 
00125 void testingMessage(const char *const msg) ;
00126 
00133 bool equivalentVectors(const OsiSolverInterface * si1,
00134                        const OsiSolverInterface * si2,
00135                        double tol, const double * v1, const double * v2, int size) ;
00136 
00143 bool compareProblems(OsiSolverInterface *osi1, OsiSolverInterface *osi2) ;
00144 
00151 bool isEquivalent(const CoinPackedVectorBase &pv, int n, const double *fv) ;
00152 
00161 bool processParameters (int argc, const char **argv,
00162                         std::map<std::string,std::string>& parms,
00163       const std::map<std::string,int>& ignorekeywords = std::map<std::string,int>());
00164 
00166 class TestOutcome {
00167   public:
00169     typedef enum {
00170             NOTE     = 0,
00171             PASSED   = 1,
00172             WARNING  = 2,
00173             ERROR    = 3,
00174             LAST     = 4
00175     } SeverityLevel;
00177     static std::string SeverityLevelName[LAST];
00179     std::string     component;
00181     std::string     testname;
00183     std::string     testcond;
00185     SeverityLevel   severity;
00187     bool            expected;
00189     std::string     filename;
00191     int             linenumber;
00193     TestOutcome(const std::string& comp, const std::string& tst,
00194                 const char* cond, SeverityLevel sev,
00195                 const char* file, int line, bool exp = false)
00196       : component(comp),testname(tst),testcond(cond),severity(sev),
00197         expected(exp),filename(file),linenumber(line)
00198     { }
00200     void print() const;
00201 };
00202 
00204 class TestOutcomes : public std::list<TestOutcome> {
00205   public:
00207     void add(std::string comp, std::string tst, const char* cond,
00208              TestOutcome::SeverityLevel sev, const char* file, int line,
00209              bool exp = false)
00210     { push_back(TestOutcome(comp,tst,cond,sev,file,line,exp)); }
00211 
00216     void add(const OsiSolverInterface& si, std::string tst, const char* cond,
00217              TestOutcome::SeverityLevel sev, const char* file, int line,
00218              bool exp = false);
00220     void print() const;
00226     void getCountBySeverity(TestOutcome::SeverityLevel sev,
00227                             int& total, int& expected) const;
00228 };
00229 
00231 #define OSIUNITTEST_QUOTEME_(x) #x
00232 
00233 #define OSIUNITTEST_QUOTEME(x) OSIUNITTEST_QUOTEME_(x)
00234 
00235 template <typename Component>
00236 bool OsiUnitTestAssertSeverityExpected(
00237     bool condition, const char * condition_str, const char *filename,
00238     int line, const Component& component, const std::string& testname,
00239     TestOutcome::SeverityLevel severity, bool expected)
00240 {
00241   if (condition) {
00242     OsiUnitTest::outcomes.add(component, testname, condition_str,
00243         OsiUnitTest::TestOutcome::PASSED, filename, line, false);
00244     if (OsiUnitTest::verbosity >= 2) {
00245       std::ostringstream successmsg;
00246       successmsg << __FILE__ << ":" << __LINE__ << ": " << testname
00247           << " (condition \'" << condition_str << "\') passed.\n";
00248       OsiUnitTest::testingMessage(successmsg.str().c_str());
00249     }
00250     return true;
00251   }
00252   OsiUnitTest::outcomes.add(component, testname, condition_str,
00253       severity, filename, line, expected);
00254   OsiUnitTest::failureMessage(component, testname, condition_str);
00255   switch (OsiUnitTest::haltonerror) {
00256     case 2:
00257     { if (severity >= OsiUnitTest::TestOutcome::ERROR ) std::abort(); break; }
00258     case 1:
00259     { std::cout << std::endl << "press any key to continue..." << std::endl;
00260       std::getchar();
00261       break ; }
00262     default: ;
00263   }
00264   return false;
00265 }
00266 
00268 #define OSIUNITTEST_ADD_OUTCOME(component,testname,testcondition,severity,expected) \
00269     OsiUnitTest::outcomes.add(component,testname,testcondition,severity,\
00270     __FILE__,__LINE__,expected)
00271 
00281 #define OSIUNITTEST_ASSERT_SEVERITY_EXPECTED(condition,failurecode,component,\
00282                                              testname, severity, expected) \
00283 { \
00284   if (!OsiUnitTestAssertSeverityExpected(condition, #condition, \
00285       __FILE__, __LINE__, component, testname, severity, expected)) { \
00286     failurecode; \
00287   } \
00288 }
00289 
00293 #define OSIUNITTEST_ASSERT_ERROR(condition, failurecode, component, testname) \
00294   OSIUNITTEST_ASSERT_SEVERITY_EXPECTED(condition,failurecode,component,testname,\
00295                                        OsiUnitTest::TestOutcome::ERROR,false)
00296 
00300 #define OSIUNITTEST_ASSERT_WARNING(condition, failurecode, component, testname) \
00301   OSIUNITTEST_ASSERT_SEVERITY_EXPECTED(condition,failurecode,component,testname,\
00302                                        OsiUnitTest::TestOutcome::WARNING,false)
00303 
00314 #define OSIUNITTEST_CATCH_SEVERITY_EXPECTED(trycode, catchcode, component, testname,\
00315                                             severity, expected) \
00316 { \
00317   try { \
00318     trycode; \
00319     OSIUNITTEST_ADD_OUTCOME(component,testname,#trycode " did not throw exception",\
00320                             OsiUnitTest::TestOutcome::PASSED,false); \
00321     if (OsiUnitTest::verbosity >= 2) { \
00322       std::string successmsg( __FILE__ ":" OSIUNITTEST_QUOTEME(__LINE__) ": "); \
00323       successmsg = successmsg + testname; \
00324       successmsg = successmsg + " (code \'" #trycode "\') did not throw exception"; \
00325       successmsg = successmsg + ".\n" ; \
00326       OsiUnitTest::testingMessage(successmsg.c_str()); \
00327     } \
00328   } catch (CoinError& e) { \
00329     std::stringstream errmsg; \
00330     errmsg << #trycode " threw CoinError: " << e.message(); \
00331     if (e.className().length() > 0) \
00332       errmsg << " in " << e.className(); \
00333     if (e.methodName().length() > 0) \
00334       errmsg << " in " << e.methodName(); \
00335     if (e.lineNumber() >= 0) \
00336       errmsg << " at " << e.fileName() << ":" << e.lineNumber(); \
00337     OSIUNITTEST_ADD_OUTCOME(component,testname,errmsg.str().c_str(),\
00338                             severity,expected); \
00339     OsiUnitTest::failureMessage(component,testname,errmsg.str().c_str()); \
00340     switch(OsiUnitTest::haltonerror) { \
00341       case 2: \
00342       { if (severity >= OsiUnitTest::TestOutcome::ERROR) abort(); break; } \
00343       case 1: \
00344       { std::cout << std::endl << "press any key to continue..." << std::endl; \
00345         getchar(); \
00346         break ; } \
00347       default: ; \
00348     } \
00349     catchcode; \
00350   } catch (...) { \
00351     std::string errmsg; \
00352     errmsg = #trycode; \
00353     errmsg = errmsg + " threw unknown exception"; \
00354     OSIUNITTEST_ADD_OUTCOME(component,testname,errmsg.c_str(),severity,false); \
00355     OsiUnitTest::failureMessage(component,testname,errmsg.c_str()); \
00356     catchcode; \
00357   } \
00358 }
00359 
00363 #define OSIUNITTEST_CATCH_ERROR(trycode, catchcode, component, testname) \
00364         OSIUNITTEST_CATCH_SEVERITY_EXPECTED(trycode, catchcode, component, testname, OsiUnitTest::TestOutcome::ERROR, false)
00365 
00369 #define OSIUNITTEST_CATCH_WARNING(trycode, catchcode, component, testname) \
00370         OSIUNITTEST_CATCH_SEVERITY_EXPECTED(trycode, catchcode, component, testname, OsiUnitTest::TestOutcome::WARNING, false)
00371 
00372 } // end namespace OsiUnitTest
00373 
00374 #endif /*OSISOLVERINTERFACETEST_HPP_*/
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines