Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 Fri Jul 15 2022 01:46:33 by
1.7.2