Unit Testing framework based on http://cpputest.github.io/

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Utest.cpp Source File

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 }