00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef Fennel_TestBase_Included
00025 #define Fennel_TestBase_Included
00026
00027 #include "fennel/common/ConfigMap.h"
00028 #include "fennel/synch/SynchObj.h"
00029 #include "fennel/common/TraceTarget.h"
00030 #include "fennel/common/FileStatsTarget.h"
00031 #include "fennel/synch/StatsTimer.h"
00032
00033 #define BOOST_TEST_DYN_LINK
00034
00035 #include <boost/shared_ptr.hpp>
00036 #include <boost/test/unit_test.hpp>
00037 #include <boost/test/unit_test_suite.hpp>
00038 #include <boost/test/parameterized_test.hpp>
00039 #include <boost/enable_shared_from_this.hpp>
00040 #include <fstream>
00041 #include <vector>
00042
00043 typedef boost::unit_test_framework::test_suite TestSuite;
00044
00045 FENNEL_BEGIN_NAMESPACE
00046
00050 class FENNEL_TEST_EXPORT TestBase
00051 : public TraceTarget,
00052 public boost::enable_shared_from_this<TestBase>
00053
00054 {
00055 protected:
00059 TestSuite *pTestSuite;
00060
00061 boost::shared_ptr<TestBase> pTestObj;
00062
00066 std::ofstream traceStream;
00067
00071 StrictMutex traceMutex;
00072
00076 std::string testName;
00077
00081 TraceLevel traceLevel;
00082
00086 FileStatsTarget statsTarget;
00087
00091 StatsTimer statsTimer;
00092
00093
00094 void snooze(uint nSeconds);
00095
00099 bool traceStdout;
00100
00104 bool traceFile;
00105
00110 static bool runAll;
00111
00116 static std::string runSingle;
00117
00122 class FENNEL_TEST_EXPORT TestCaseGroup
00123 {
00124 struct Item
00125 {
00126 std::string name;
00127 boost::unit_test::test_unit * tu;
00128 Item(std::string name, boost::unit_test::test_unit* tu)
00129 : name(name), tu(tu) {}
00130 };
00132 std::vector<Item> items;
00133 public:
00134 void addTest(std::string name, boost::unit_test::test_unit *tu);
00135 boost::unit_test::test_unit* findTest(std::string name) const;
00136 void addAllToTestSuite(TestSuite *) const;
00137 };
00138
00139 TestCaseGroup defaultTests;
00140 TestCaseGroup extraTests;
00141
00142 public:
00143 static ParamName paramTestSuiteName;
00144 static ParamName paramTraceFileName;
00145 static ParamName paramDictionaryFileName;
00146 static ParamName paramTraceLevel;
00147 static ParamName paramStatsFileName;
00148 static ParamName paramTraceStdout;
00149 static ParamName paramDegreeOfParallelism;
00150
00155 static ConfigMap configMap;
00156
00157 explicit TestBase();
00158 virtual ~TestBase();
00159
00160
00161 static void readParams(int argc,char **argv);
00162 TestSuite *releaseTestSuite();
00163 void beforeTestCase(std::string testCaseName);
00164 void afterTestCase(std::string testCaseName);
00165
00170 virtual void testCaseSetUp();
00171
00176 virtual void testCaseTearDown();
00177
00178
00179 virtual void notifyTrace(
00180 std::string source,TraceLevel level,std::string message);
00181 virtual TraceLevel getSourceTraceLevel(std::string source);
00182 };
00183
00188 template<class UserTestClass>
00189 class TestWrapperTemplate
00190 {
00191 public:
00192 typedef void (UserTestClass::*FunctionType)();
00193
00194 private:
00195 std::string name;
00196 boost::shared_ptr<UserTestClass> pUserTestCase;
00197
00198 public:
00199
00200 TestWrapperTemplate(
00201 std::string nameInit,
00202 boost::shared_ptr<UserTestClass>& pUserTestCaseInit)
00203 : pUserTestCase(pUserTestCaseInit)
00204 {
00205 name = nameInit;
00206 }
00207
00208 void runTest(FunctionType pFunction)
00209 {
00210 pUserTestCase->beforeTestCase(name);
00211 pUserTestCase->testCaseSetUp();
00212 try {
00213 try {
00214 ((*pUserTestCase).*pFunction)();
00215 } catch (std::exception &ex) {
00216 pUserTestCase->notifyTrace(name, TRACE_SEVERE, ex.what());
00217 throw ex;
00218 }
00219 } catch (...) {
00220 try {
00221 pUserTestCase->testCaseTearDown();
00222 } catch (...) {
00223
00224 }
00225 throw;
00226 }
00227 try {
00228 pUserTestCase->testCaseTearDown();
00229 } catch (...) {
00230 pUserTestCase->afterTestCase(name);
00231 throw;
00232 }
00233 pUserTestCase->afterTestCase(name);
00234 }
00235 };
00236
00237
00238
00239
00240
00241 #define FENNEL_UNIT_TEST_SUITE(UserTestClass) \
00242 bool init_unit_test() \
00243 { \
00244 TestBase::readParams( \
00245 boost::unit_test::framework::master_test_suite().argc, \
00246 boost::unit_test::framework::master_test_suite().argv); \
00247 std::string paramKey(TestBase::paramTestSuiteName); \
00248 std::string paramVal(#UserTestClass); \
00249 TestBase::configMap.setStringParam(paramKey,paramVal); \
00250 UserTestClass *pTestObj = new UserTestClass(); \
00251 TestBase::configMap.disableTracing(); \
00252 boost::unit_test::framework::master_test_suite().add( \
00253 pTestObj->releaseTestSuite()); \
00254 return true; \
00255 } \
00256 \
00257 int main(int argc, char **argv) \
00258 { \
00259 return ::boost::unit_test::unit_test_main(&init_unit_test, argc, argv); \
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 #define FENNEL_UNIT_TEST_CASE(UserTestClass,testMethodName) \
00271 FENNEL_DEFINE_UNIT_TEST_CASE(defaultTests,UserTestClass,testMethodName)
00272
00273 #define FENNEL_EXTRA_UNIT_TEST_CASE(UserTestClass,testMethodName) \
00274 FENNEL_DEFINE_UNIT_TEST_CASE(extraTests,UserTestClass,testMethodName)
00275
00276
00277
00278
00279 #define FENNEL_DEFINE_UNIT_TEST_CASE(group,UserTestClass,testMethodName) \
00280 do { \
00281 typedef TestWrapperTemplate<UserTestClass> TestWrapper; \
00282 boost::shared_ptr<UserTestClass> pDerivedTestObj = \
00283 boost::dynamic_pointer_cast<UserTestClass>(pTestObj); \
00284 TestWrapper::FunctionType params [] = \
00285 { &UserTestClass::testMethodName }; \
00286 boost::unit_test::test_unit *tu = \
00287 boost::unit_test::make_test_case<TestWrapper>(\
00288 &TestWrapper::runTest, \
00289 #testMethodName, \
00290 boost::shared_ptr<TestWrapper>(new TestWrapper(\
00291 #testMethodName, \
00292 pDerivedTestObj)), \
00293 params, \
00294 params + 1).next(); \
00295 group.addTest(#testMethodName, tu); \
00296 } while (0)
00297
00298 FENNEL_END_NAMESPACE
00299
00300 #endif
00301
00302