fork
Fork of cpputest by
Embed:
(wiki syntax)
Show/hide line numbers
Utest.cpp
00001 /* 00002 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * * Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of the <organization> nor the 00013 * names of its contributors may be used to endorse or promote products 00014 * derived from this software without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY 00017 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY 00020 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00022 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00023 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00025 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 #include "CppUTest/TestHarness.h" 00029 #include "CppUTest/TestRegistry.h" 00030 #include "CppUTest/PlatformSpecificFunctions.h" 00031 #include "CppUTest/TestOutput.h" 00032 00033 bool doubles_equal(double d1, double d2, double threshold) 00034 { 00035 if (PlatformSpecificIsNan(d1) || PlatformSpecificIsNan(d2) || PlatformSpecificIsNan(threshold)) 00036 return false; 00037 return PlatformSpecificFabs(d1 - d2) <= threshold; 00038 } 00039 00040 /* Sometimes stubs use the CppUTest assertions. 00041 * Its not correct to do so, but this small helper class will prevent a segmentation fault and instead 00042 * will give an error message and also the file/line of the check that was executed outside the tests. 00043 */ 00044 class OutsideTestRunnerUTest: public UtestShell 00045 { 00046 public: 00047 static OutsideTestRunnerUTest& instance(); 00048 virtual TestResult& getTestResult() 00049 { 00050 return defaultTestResult; 00051 } 00052 virtual void exitCurrentTest() 00053 { 00054 } 00055 virtual ~OutsideTestRunnerUTest() 00056 { 00057 } 00058 private: 00059 OutsideTestRunnerUTest() : 00060 UtestShell("\n\t NOTE: Assertion happened without being in a test run (perhaps in main?)", "\n\t Something is very wrong. Check this assertion and fix", "unknown file", 0), 00061 defaultTestResult(defaultOutput) 00062 { 00063 } 00064 ConsoleTestOutput defaultOutput; 00065 TestResult defaultTestResult; 00066 }; 00067 00068 OutsideTestRunnerUTest& OutsideTestRunnerUTest::instance() 00069 { 00070 static OutsideTestRunnerUTest instance_; 00071 return instance_; 00072 } 00073 00074 /* 00075 * Below helpers are used for the PlatformSpecificSetJmp and LongJmp. They pass a method for what needs to happen after 00076 * the jump, so that the stack stays right. 00077 * 00078 */ 00079 00080 extern "C" { 00081 00082 static void helperDoTestSetup(void* data) 00083 { 00084 ((Utest*)data)->setup(); 00085 } 00086 00087 static void helperDoTestBody(void* data) 00088 { 00089 ((Utest*)data)->testBody(); 00090 } 00091 00092 static void helperDoTestTeardown(void* data) 00093 { 00094 ((Utest*)data)->teardown(); 00095 } 00096 00097 struct HelperTestRunInfo 00098 { 00099 HelperTestRunInfo(UtestShell* shell, TestPlugin* plugin, TestResult* result) : shell_(shell), plugin_(plugin), result_(result){} 00100 00101 UtestShell* shell_; 00102 TestPlugin* plugin_; 00103 TestResult* result_; 00104 }; 00105 00106 static void helperDoRunOneTestInCurrentProcess(void* data) 00107 { 00108 HelperTestRunInfo* runInfo = (HelperTestRunInfo*) data; 00109 00110 UtestShell* shell = runInfo->shell_; 00111 TestPlugin* plugin = runInfo->plugin_; 00112 TestResult* result = runInfo->result_; 00113 00114 shell->runOneTestInCurrentProcess(plugin, *result); 00115 } 00116 00117 static void helperDoRunOneTestSeperateProcess(void* data) 00118 { 00119 HelperTestRunInfo* runInfo = (HelperTestRunInfo*) data; 00120 00121 UtestShell* shell = runInfo->shell_; 00122 TestPlugin* plugin = runInfo->plugin_; 00123 TestResult* result = runInfo->result_; 00124 PlatformSpecificRunTestInASeperateProcess(shell, plugin, result); 00125 } 00126 00127 } 00128 00129 /******************************** */ 00130 00131 UtestShell::UtestShell() : 00132 group_("UndefinedTestGroup"), name_("UndefinedTest"), file_("UndefinedFile"), lineNumber_(0), next_(&NullTestShell::instance()), isRunAsSeperateProcess_(false), hasFailed_(false) 00133 { 00134 } 00135 00136 UtestShell::UtestShell(const char* groupName, const char* testName, const char* fileName, int lineNumber) : 00137 group_(groupName), name_(testName), file_(fileName), lineNumber_(lineNumber), next_(&NullTestShell::instance()), isRunAsSeperateProcess_(false), hasFailed_(false) 00138 { 00139 } 00140 00141 UtestShell::UtestShell(const char* groupName, const char* testName, const char* fileName, int lineNumber, UtestShell* nextTest) : 00142 group_(groupName), name_(testName), file_(fileName), lineNumber_(lineNumber), next_(nextTest), isRunAsSeperateProcess_(false), hasFailed_(false) 00143 { 00144 } 00145 00146 UtestShell::~UtestShell() 00147 { 00148 } 00149 00150 static void defaultCrashMethod() 00151 { 00152 UtestShell* ptr = (UtestShell*) 0x0; ptr->countTests(); 00153 } 00154 00155 static void (*pleaseCrashMeRightNow) () = defaultCrashMethod; 00156 00157 void UtestShell::setCrashMethod(void (*crashme)()) 00158 { 00159 pleaseCrashMeRightNow = crashme; 00160 } 00161 00162 void UtestShell::resetCrashMethod() 00163 { 00164 pleaseCrashMeRightNow = defaultCrashMethod; 00165 } 00166 00167 void UtestShell::crash() 00168 { 00169 pleaseCrashMeRightNow(); 00170 } 00171 00172 void UtestShell::runOneTest(TestPlugin* plugin, TestResult& result) 00173 { 00174 HelperTestRunInfo runInfo(this, plugin, &result); 00175 if (isRunInSeperateProcess()) 00176 PlatformSpecificSetJmp(helperDoRunOneTestSeperateProcess, &runInfo); 00177 else 00178 PlatformSpecificSetJmp(helperDoRunOneTestInCurrentProcess, &runInfo); 00179 } 00180 00181 Utest* UtestShell::createTest() 00182 { 00183 return new Utest(); 00184 } 00185 00186 void UtestShell::destroyTest(Utest* test) 00187 { 00188 delete test; 00189 } 00190 00191 void UtestShell::runOneTestInCurrentProcess(TestPlugin* plugin, TestResult& result) 00192 { 00193 plugin->runAllPreTestAction(*this, result); 00194 00195 //save test context, so that test class can be tested 00196 UtestShell* savedTest = UtestShell::getCurrent(); 00197 TestResult* savedResult = UtestShell::getTestResult(); 00198 00199 result.countRun(); 00200 UtestShell::setTestResult(&result); 00201 UtestShell::setCurrentTest(this); 00202 00203 Utest* testToRun = createTest(); 00204 testToRun->run(); 00205 destroyTest(testToRun); 00206 00207 UtestShell::setCurrentTest(savedTest); 00208 UtestShell::setTestResult(savedResult); 00209 00210 plugin->runAllPostTestAction(*this, result); 00211 } 00212 00213 UtestShell *UtestShell::getNext() const 00214 { 00215 return next_; 00216 } 00217 00218 UtestShell* UtestShell::addTest(UtestShell *test) 00219 { 00220 next_ = test; 00221 return this; 00222 } 00223 00224 int UtestShell::countTests() 00225 { 00226 return next_->countTests() + 1; 00227 } 00228 00229 bool UtestShell::isNull() const 00230 { 00231 return false; 00232 } 00233 00234 SimpleString UtestShell::getMacroName() const 00235 { 00236 return "TEST"; 00237 } 00238 00239 const SimpleString UtestShell::getName() const 00240 { 00241 return SimpleString(name_); 00242 } 00243 00244 const SimpleString UtestShell::getGroup() const 00245 { 00246 return SimpleString(group_); 00247 } 00248 00249 SimpleString UtestShell::getFormattedName() const 00250 { 00251 SimpleString formattedName(getMacroName()); 00252 formattedName += "("; 00253 formattedName += group_; 00254 formattedName += ", "; 00255 formattedName += name_; 00256 formattedName += ")"; 00257 00258 return formattedName; 00259 } 00260 00261 bool UtestShell::hasFailed() const 00262 { 00263 return hasFailed_; 00264 } 00265 00266 const char* UtestShell::getProgressIndicator() const 00267 { 00268 return "."; 00269 } 00270 00271 bool UtestShell::isRunInSeperateProcess() const 00272 { 00273 return isRunAsSeperateProcess_; 00274 } 00275 00276 void UtestShell::setRunInSeperateProcess() 00277 { 00278 isRunAsSeperateProcess_ = true; 00279 } 00280 00281 00282 void UtestShell::setFileName(const char* fileName) 00283 { 00284 file_ = fileName; 00285 } 00286 00287 void UtestShell::setLineNumber(int lineNumber) 00288 { 00289 lineNumber_ = lineNumber; 00290 } 00291 00292 void UtestShell::setGroupName(const char* groupName) 00293 { 00294 group_ = groupName; 00295 } 00296 00297 void UtestShell::setTestName(const char* testName) 00298 { 00299 name_ = testName; 00300 } 00301 00302 const SimpleString UtestShell::getFile() const 00303 { 00304 return SimpleString(file_); 00305 } 00306 00307 int UtestShell::getLineNumber() const 00308 { 00309 return lineNumber_; 00310 } 00311 00312 bool UtestShell::shouldRun(const TestFilter& groupFilter, const TestFilter& nameFilter) const 00313 { 00314 if (groupFilter.match(group_) && nameFilter.match(name_)) return true; 00315 00316 return false; 00317 } 00318 00319 void UtestShell::failWith(const TestFailure& failure) 00320 { 00321 failWith(failure, NormalTestTerminator()); 00322 } 00323 00324 void UtestShell::failWith(const TestFailure& failure, const TestTerminator& terminator) 00325 { 00326 hasFailed_ = true; 00327 getTestResult()->addFailure(failure); 00328 terminator.exitCurrentTest(); 00329 } 00330 00331 void UtestShell::assertTrue(bool condition, const char * checkString, const char* conditionString, const char* fileName, int lineNumber, const TestTerminator& testTerminator) 00332 { 00333 assertTrueText(condition, checkString, conditionString, "", fileName, lineNumber, testTerminator); 00334 } 00335 00336 void UtestShell::assertTrueText(bool condition, const char *checkString, const char *conditionString, const char* text, const char *fileName, int lineNumber, const TestTerminator& testTerminator) 00337 { 00338 getTestResult()->countCheck(); 00339 if (!condition) 00340 failWith(CheckFailure(this, fileName, lineNumber, checkString, conditionString, text), testTerminator); 00341 } 00342 00343 void UtestShell::fail(const char *text, const char* fileName, int lineNumber, const TestTerminator& testTerminator) 00344 { 00345 getTestResult()->countCheck(); 00346 failWith(FailFailure(this, fileName, lineNumber, text), testTerminator); 00347 } 00348 00349 void UtestShell::assertCstrEqual(const char* expected, const char* actual, const char* fileName, int lineNumber, const TestTerminator& testTerminator) 00350 { 00351 getTestResult()->countCheck(); 00352 if (actual == 0 && expected == 0) return; 00353 if (actual == 0 || expected == 0) 00354 failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual), testTerminator); 00355 if (PlatformSpecificStrCmp(expected, actual) != 0) 00356 failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual), testTerminator); 00357 } 00358 00359 void UtestShell::assertCstrNoCaseEqual(const char* expected, const char* actual, const char* fileName, int lineNumber) 00360 { 00361 getTestResult()->countCheck(); 00362 if (actual == 0 && expected == 0) return; 00363 if (actual == 0 || expected == 0) 00364 failWith(StringEqualNoCaseFailure(this, fileName, lineNumber, expected, actual)); 00365 if (!SimpleString(expected).equalsNoCase(actual)) 00366 failWith(StringEqualNoCaseFailure(this, fileName, lineNumber, expected, actual)); 00367 } 00368 00369 void UtestShell::assertCstrContains(const char* expected, const char* actual, const char* fileName, int lineNumber) 00370 { 00371 getTestResult()->countCheck(); 00372 if (actual == 0 && expected == 0) return; 00373 if(actual == 0 || expected == 0) 00374 failWith(ContainsFailure(this, fileName, lineNumber, expected, actual)); 00375 if (!SimpleString(actual).contains(expected)) 00376 failWith(ContainsFailure(this, fileName, lineNumber, expected, actual)); 00377 } 00378 00379 void UtestShell::assertCstrNoCaseContains(const char* expected, const char* actual, const char* fileName, int lineNumber) 00380 { 00381 getTestResult()->countCheck(); 00382 if (actual == 0 && expected == 0) return; 00383 if(actual == 0 || expected == 0) 00384 failWith(ContainsFailure(this, fileName, lineNumber, expected, actual)); 00385 if (!SimpleString(actual).containsNoCase(expected)) 00386 failWith(ContainsFailure(this, fileName, lineNumber, expected, actual)); 00387 } 00388 00389 void UtestShell::assertLongsEqual(long expected, long actual, const char* fileName, int lineNumber, const TestTerminator& testTerminator) 00390 { 00391 getTestResult()->countCheck(); 00392 if (expected != actual) 00393 failWith(LongsEqualFailure (this, fileName, lineNumber, expected, actual), testTerminator); 00394 } 00395 00396 void UtestShell::assertUnsignedLongsEqual(unsigned long expected, unsigned long actual, const char* fileName, int lineNumber, const TestTerminator& testTerminator) 00397 { 00398 getTestResult()->countCheck(); 00399 if (expected != actual) 00400 failWith(UnsignedLongsEqualFailure (this, fileName, lineNumber, expected, actual), testTerminator); 00401 } 00402 00403 void UtestShell::assertPointersEqual(const void* expected, const void* actual, const char* fileName, int lineNumber) 00404 { 00405 getTestResult()->countCheck(); 00406 if (expected != actual) 00407 failWith(EqualsFailure(this, fileName, lineNumber, StringFrom(expected), StringFrom(actual))); 00408 } 00409 00410 void UtestShell::assertDoublesEqual(double expected, double actual, double threshold, const char* fileName, int lineNumber, const TestTerminator& testTerminator) 00411 { 00412 getTestResult()->countCheck(); 00413 if (!doubles_equal(expected, actual, threshold)) 00414 failWith(DoublesEqualFailure(this, fileName, lineNumber, expected, actual, threshold), testTerminator); 00415 } 00416 00417 void UtestShell::assertEquals(bool failed, const char* expected, const char* actual, const char* file, int line, const TestTerminator& testTerminator) 00418 { 00419 getTestResult()->countCheck(); 00420 if (failed) 00421 failWith(CheckEqualFailure(this, file, line, expected, actual), testTerminator); 00422 } 00423 00424 00425 void UtestShell::print(const char *text, const char* fileName, int lineNumber) 00426 { 00427 SimpleString stringToPrint = "\n"; 00428 stringToPrint += fileName; 00429 stringToPrint += ":"; 00430 stringToPrint += StringFrom(lineNumber); 00431 stringToPrint += " "; 00432 stringToPrint += text; 00433 getTestResult()->print(stringToPrint.asCharString()); 00434 } 00435 00436 void UtestShell::print(const SimpleString& text, const char* fileName, int lineNumber) 00437 { 00438 print(text.asCharString(), fileName, lineNumber); 00439 } 00440 00441 TestResult* UtestShell::testResult_ = NULL; 00442 UtestShell* UtestShell::currentTest_ = NULL; 00443 00444 void UtestShell::setTestResult(TestResult* result) 00445 { 00446 testResult_ = result; 00447 } 00448 00449 void UtestShell::setCurrentTest(UtestShell* test) 00450 { 00451 currentTest_ = test; 00452 } 00453 00454 TestResult* UtestShell::getTestResult() 00455 { 00456 if (testResult_ == NULL) 00457 return &OutsideTestRunnerUTest::instance().getTestResult(); 00458 return testResult_; 00459 } 00460 00461 UtestShell* UtestShell::getCurrent() 00462 { 00463 if (currentTest_ == NULL) 00464 return &OutsideTestRunnerUTest::instance(); 00465 return currentTest_; 00466 } 00467 00468 00469 ExecFunctionTestShell::~ExecFunctionTestShell() 00470 { 00471 } 00472 00473 ////////////// Utest //////////// 00474 00475 Utest::Utest() 00476 { 00477 } 00478 00479 Utest::~Utest() 00480 { 00481 } 00482 00483 #if CPPUTEST_USE_STD_CPP_LIB 00484 00485 void Utest::run() 00486 { 00487 try { 00488 if (PlatformSpecificSetJmp(helperDoTestSetup, this)) { 00489 PlatformSpecificSetJmp(helperDoTestBody, this); 00490 } 00491 } 00492 catch (CppUTestFailedException&) 00493 { 00494 PlatformSpecificRestoreJumpBuffer(); 00495 } 00496 00497 try { 00498 PlatformSpecificSetJmp(helperDoTestTeardown, this); 00499 } 00500 catch (CppUTestFailedException&) 00501 { 00502 PlatformSpecificRestoreJumpBuffer(); 00503 } 00504 00505 } 00506 #else 00507 00508 void Utest::run() 00509 { 00510 if (PlatformSpecificSetJmp(helperDoTestSetup, this)) { 00511 PlatformSpecificSetJmp(helperDoTestBody, this); 00512 } 00513 PlatformSpecificSetJmp(helperDoTestTeardown, this); 00514 } 00515 00516 #endif 00517 00518 void Utest::setup() 00519 { 00520 } 00521 00522 void Utest::testBody() 00523 { 00524 } 00525 00526 void Utest::teardown() 00527 { 00528 } 00529 00530 00531 ////////////// NullTestShell //////////// 00532 00533 00534 NullTestShell::NullTestShell() : 00535 UtestShell("NullGroup", "NullName", "NullFile", -1, 0) 00536 { 00537 } 00538 00539 NullTestShell::NullTestShell(const char* fileName, int lineNumber) : 00540 UtestShell("NullGroup", "NullName", fileName, lineNumber, 0) 00541 { 00542 } 00543 00544 NullTestShell::~NullTestShell() 00545 { 00546 } 00547 00548 NullTestShell& NullTestShell::instance() 00549 { 00550 static NullTestShell _instance; 00551 return _instance; 00552 } 00553 00554 int NullTestShell::countTests() 00555 { 00556 return 0; 00557 } 00558 00559 UtestShell* NullTestShell::getNext() const 00560 { 00561 return &instance(); 00562 } 00563 00564 bool NullTestShell::isNull() const 00565 { 00566 return true; 00567 } 00568 00569 void NullTestShell::testBody() 00570 { 00571 } 00572 00573 00574 /////////////////// Terminators 00575 00576 TestTerminator::~TestTerminator() 00577 { 00578 } 00579 00580 void NormalTestTerminator::exitCurrentTest() const 00581 { 00582 #if CPPUTEST_USE_STD_CPP_LIB 00583 throw CppUTestFailedException(); 00584 #else 00585 TestTerminatorWithoutExceptions().exitCurrentTest(); 00586 #endif 00587 } 00588 00589 NormalTestTerminator::~NormalTestTerminator() 00590 { 00591 } 00592 00593 void TestTerminatorWithoutExceptions::exitCurrentTest() const 00594 { 00595 PlatformSpecificLongJmp(); 00596 } 00597 00598 TestTerminatorWithoutExceptions::~TestTerminatorWithoutExceptions() 00599 { 00600 } 00601 00602 //////////////////// ExecFunctionTest 00603 00604 ExecFunctionTest::ExecFunctionTest(ExecFunctionTestShell* shell) 00605 : shell_(shell) 00606 { 00607 } 00608 00609 void ExecFunctionTest::testBody() 00610 { 00611 if (shell_->testFunction_) shell_->testFunction_(); 00612 } 00613 00614 void ExecFunctionTest::setup() 00615 { 00616 if (shell_->setup_) shell_->setup_(); 00617 } 00618 00619 void ExecFunctionTest::teardown() 00620 { 00621 if (shell_->teardown_) shell_->teardown_(); 00622 } 00623 00624 /////////////// IgnoredUtestShell ///////////// 00625 IgnoredUtestShell::IgnoredUtestShell() 00626 { 00627 } 00628 00629 IgnoredUtestShell::~IgnoredUtestShell() 00630 { 00631 } 00632 00633 const char* IgnoredUtestShell::getProgressIndicator() const 00634 { 00635 return "!"; 00636 } 00637 00638 SimpleString IgnoredUtestShell::getMacroName() const 00639 { 00640 return "IGNORE_TEST"; 00641 } 00642 00643 void IgnoredUtestShell::runOneTest(TestPlugin* /* plugin */, TestResult& result) 00644 { 00645 result.countIgnored(); 00646 } 00647 00648 00649 ////////////// TestInstaller //////////// 00650 00651 TestInstaller::TestInstaller(UtestShell& shell, const char* groupName, const char* testName, const char* fileName, int lineNumber) 00652 { 00653 shell.setGroupName(groupName); 00654 shell.setTestName(testName); 00655 shell.setFileName(fileName); 00656 shell.setLineNumber(lineNumber); 00657 TestRegistry::getCurrentRegistry()->addTest(&shell); 00658 } 00659 00660 TestInstaller::~TestInstaller() 00661 { 00662 } 00663 00664 void TestInstaller::unDo() 00665 { 00666 TestRegistry::getCurrentRegistry()->unDoLastAddTest(); 00667 }
Generated on Tue Jul 12 2022 21:37:56 by 1.7.2