Changeset 936
- Timestamp:
- Sep 9, 2011, 4:39:00 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lol/unit.h
r934 r936 45 45 virtual ~FixtureBase() {} 46 46 47 /* The FixtureBase class keeps track of all instanciated children 48 * fixtures through this method. */ 49 static FixtureBase *GetOrSetTest(FixtureBase *set = NULL) 50 { 51 static FixtureBase *head = NULL, *tail = NULL; 52 if (set) 53 { 54 if (!head) 55 head = set; 56 if (tail) 57 tail->m_next = set; 58 tail = set; 59 } 60 return head; 61 } 62 63 virtual void runFixture() = 0; 47 static void AddFixture(FixtureBase *fixture) 48 { 49 /* Protect against several instances of the same Fixture subclass */ 50 if (fixture->MarkFixture()) 51 return; 52 FixtureListHelper(fixture); 53 } 54 static FixtureBase *FixtureList() { return FixtureListHelper(NULL); } 55 56 virtual void RunFixture() = 0; 57 virtual bool MarkFixture() = 0; 64 58 65 59 /* Prevent compiler complaints about unreachable code */ … … 71 65 char const *m_fixturename, *m_currentname; 72 66 std::stringstream m_errorlog, m_context; 67 68 private: 69 /* The FixtureBase class keeps track of all instanciated children 70 * fixtures through this method. */ 71 static FixtureBase *FixtureListHelper(FixtureBase *set) 72 { 73 static FixtureBase *head = NULL, *tail = NULL; 74 75 if (set) 76 { 77 if (!head) head = set; 78 if (tail) tail->m_next = set; 79 tail = set; 80 } 81 return head; 82 } 73 83 }; 74 75 #define LOLUNIT_FIXTURE(FixtureName) \76 class FixtureName; \77 template<typename T> struct Make##FixtureName \78 { \79 Make##FixtureName() { p = new T(); } \80 ~Make##FixtureName() { delete p; } \81 T *p; \82 }; \83 Make##FixtureName<FixtureName> lol_unit_fixture_##FixtureName; \84 static char const *LolUnitFixtureName(FixtureName *p) \85 { \86 (void)p; \87 return #FixtureName; \88 } \89 class FixtureName : public lol::Fixture<FixtureName>90 84 91 85 /* … … 98 92 typedef T FixtureClass; 99 93 100 class TestCase 101 { 102 public: 94 struct TestCase 95 { 103 96 void (FixtureClass::* m_fun)(); 104 97 char const *m_testname; 105 98 TestCase *m_next; 106 107 static void AddTestCase(TestCase *that, char const *name,108 void (FixtureClass::*fun)())109 {110 that->m_fun = fun;111 that->m_testname = name;112 that->m_next = NULL;113 GetOrSetTestCase(that);114 }115 99 }; 116 100 117 101 Fixture<T>() 118 102 { 119 GetOrSetTest(this);103 AddFixture(this); 120 104 } 121 105 122 106 /* Run all test cases in this fixture. */ 123 virtual void runFixture()107 virtual void RunFixture() 124 108 { 125 109 m_errorlog.str(""); 126 110 m_testcases = 0; 127 111 m_failcases = 0; 128 for (TestCase *c = GetOrSetTestCase(); c; c = c->m_next)112 for (TestCase *c = TestCaseList(); c; c = c->m_next) 129 113 { 130 114 m_testcases++; … … 140 124 } 141 125 126 /* Mark the current fixture type as already registered and return whether 127 * it was seen before. */ 128 virtual bool MarkFixture() 129 { 130 static bool seen = false; 131 if (seen) 132 { 133 SealFixture(); 134 return true; 135 } 136 seen = true; 137 return false; 138 } 139 140 /* Manage Fixture sealing. Once SealFixture() has been called, we 141 * will no longer accept TestCase registrations. */ 142 static void SealFixture() { SealFixtureHelper(true); } 143 static bool IsFixtureSealed() { return SealFixtureHelper(false); } 144 142 145 /* Each Fixture class specialisation keeps track of its instanciated 143 * test cases through this method. */ 144 static TestCase *GetOrSetTestCase(TestCase *set = NULL) 146 * test cases. */ 147 static void AddTestCase(TestCase *that, char const *name, 148 void (FixtureClass::*fun)()) 149 { 150 if (IsFixtureSealed()) 151 return; 152 153 that->m_fun = fun; 154 that->m_testname = name; 155 that->m_next = NULL; 156 TestCaseListHelper(that); 157 } 158 static TestCase *TestCaseList() { return TestCaseListHelper(NULL); } 159 160 private: 161 static bool SealFixtureHelper(bool set) 162 { 163 static bool sealed = false; 164 if (set) sealed = true; 165 return sealed; 166 } 167 168 static TestCase *TestCaseListHelper(TestCase *set) 145 169 { 146 170 static TestCase *head = NULL, *tail = NULL; … … 154 178 } 155 179 }; 156 157 #define LOLUNIT_TEST(TestCaseName) \158 class TestCase##TestCaseName : public TestCase \159 { \160 public: \161 TestCase##TestCaseName() \162 { \163 AddTestCase(this, #TestCaseName, \164 (void (FixtureClass::*)()) &FixtureClass::TestCaseName); \165 } \166 }; \167 TestCase##TestCaseName lol_unit_test_case_##TestCaseName; \168 void TestCaseName()169 180 170 181 /* … … 181 192 int failcases = 0, testcases = 0; 182 193 183 for (FixtureBase *f = FixtureBase:: GetOrSetTest(); f; f = f->m_next)194 for (FixtureBase *f = FixtureBase::FixtureList(); f; f = f->m_next) 184 195 { 185 196 f->setUp(); 186 f-> runFixture();197 f->RunFixture(); 187 198 f->tearDown(); 188 199 … … 222 233 m_errorlog << std::endl << std::endl; \ 223 234 m_errorlog << ++m_failcases << ") test: " \ 224 << LolUnitFixtureName(this) << "::" << m_currentname \235 << lol_unit_helper_name(this) << "::" << m_currentname \ 225 236 << " (F) line: " << __LINE__ << " " \ 226 237 << __FILE__ << std::endl; \ … … 231 242 return; \ 232 243 } \ 233 } while (!True())244 } while (!True()) 234 245 235 246 #define LOLUNIT_ASSERT_OP(op, modifier, opdesc, msg, a, b) \ … … 240 251 m_errorlog << std::endl << std::endl; \ 241 252 m_errorlog << ++m_failcases << ") test: " \ 242 << LolUnitFixtureName(this) << "::" << m_currentname \253 << lol_unit_helper_name(this) << "::" << m_currentname \ 243 254 << " (F) line: " << __LINE__ << " " \ 244 255 << __FILE__ << std::endl; \ … … 251 262 return; \ 252 263 } \ 253 } while (!True())264 } while (!True()) 254 265 255 266 #define LOLUNIT_MSG(msg) \ … … 263 274 m_errorlog << std::endl << std::endl; \ 264 275 m_errorlog << ++m_failcases << ") test: " \ 265 << LolUnitFixtureName(this) << "::" << m_currentname \276 << lol_unit_helper_name(this) << "::" << m_currentname \ 266 277 << " (F) line: " << __LINE__ << " " \ 267 278 << __FILE__ << std::endl; \ … … 278 289 return; \ 279 290 } \ 280 } while(!True()) 291 } while (!True()) 292 293 /* 294 * Public helper macros 295 */ 296 297 #define LOLUNIT_FIXTURE(N) \ 298 class N; \ 299 /* This pattern allows us to statically create a Fixture instance \ 300 * before its exact implementation was defined. */ \ 301 template<typename T> struct lol_unit_helper_fixture_##N \ 302 { \ 303 lol_unit_helper_fixture_##N() { p = new T(); } \ 304 ~lol_unit_helper_fixture_##N() { delete p; } \ 305 T *p; \ 306 }; \ 307 lol_unit_helper_fixture_##N<N> lol_unit_helper_fixture_##N##_instance; \ 308 /* Allow to retrieve the class name without using RTTI and without \ 309 * knowing the type of "this". */ \ 310 static inline char const *lol_unit_helper_name(N *p) \ 311 { \ 312 (void)p; \ 313 return #N; \ 314 } \ 315 /* Now the user can define the implementation */ \ 316 class N : public lol::Fixture<N> 317 318 #define LOLUNIT_TEST(N) \ 319 /* For each test in the fixture, we create an object that will \ 320 * automatically register the test method in a list global to the \ 321 * specialised fixture. */ \ 322 class lol_unit_helper_test_##N : public TestCase \ 323 { \ 324 public: \ 325 lol_unit_helper_test_##N() \ 326 { \ 327 AddTestCase(this, #N, \ 328 (void (FixtureClass::*)()) &FixtureClass::N); \ 329 } \ 330 }; \ 331 lol_unit_helper_test_##N lol_unit_helper_test_instance_##N; \ 332 void N() 333 334 /* 335 * Provide context for error messages 336 */ 337 338 #define LOLUNIT_SET_CONTEXT(n) \ 339 do { \ 340 m_context.str(""); \ 341 m_context << "- Context : " << #n << " = " << (n) << std::endl; \ 342 } while (!True()) 343 344 #define LOLUNIT_UNSET_CONTEXT(n) \ 345 m_context.str("") 281 346 282 347 /* … … 289 354 m_errorlog << std::endl << std::endl; \ 290 355 m_errorlog << ++m_failcases << ") test: " \ 291 << LolUnitFixtureName(this) << "::" << m_currentname \356 << lol_unit_helper_name(this) << "::" << m_currentname \ 292 357 << " (F) line: " << __LINE__ << " " \ 293 358 << __FILE__ << std::endl; \ … … 297 362 m_failure = true; \ 298 363 return; \ 299 } while(!True()) 300 301 #define LOLUNIT_SET_CONTEXT(n) \ 302 do { \ 303 m_context.str(""); \ 304 m_context << "- Context : " << #n << " = " << (n) << std::endl; \ 305 } while(!True()) 306 307 #define LOLUNIT_UNSET_CONTEXT(n) \ 308 m_context.str("") 364 } while (!True()) 309 365 310 366 #define LOLUNIT_ASSERT(cond) \
Note: See TracChangeset
for help on using the changeset viewer.