1 /*
2  * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the <organization> nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "CppUTest/TestHarness.h"
29 #include "CppUTest/TestRegistry.h"
30 #include "CppUTest/PlatformSpecificFunctions.h"
31 #include "CppUTest/TestOutput.h"
32 
doubles_equal(double d1,double d2,double threshold)33 bool doubles_equal(double d1, double d2, double threshold)
34 {
35     if (PlatformSpecificIsNan(d1) || PlatformSpecificIsNan(d2) || PlatformSpecificIsNan(threshold))
36         return false;
37 
38     if (PlatformSpecificIsInf(d1) && PlatformSpecificIsInf(d2))
39     {
40         return true;
41     }
42 
43     return PlatformSpecificFabs(d1 - d2) <= threshold;
44 }
45 
46 /* Sometimes stubs use the CppUTest assertions.
47  * Its not correct to do so, but this small helper class will prevent a segmentation fault and instead
48  * will give an error message and also the file/line of the check that was executed outside the tests.
49  */
50 class OutsideTestRunnerUTest: public UtestShell
51 {
52 public:
53     static OutsideTestRunnerUTest& instance();
getTestResult()54     virtual TestResult& getTestResult()
55     {
56         return defaultTestResult;
57     }
~OutsideTestRunnerUTest()58     virtual ~OutsideTestRunnerUTest() _destructor_override
59     {
60     }
61 private:
OutsideTestRunnerUTest()62     OutsideTestRunnerUTest() :
63         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),
64                 defaultTestResult(defaultOutput)
65     {
66     }
67     ConsoleTestOutput defaultOutput;
68     TestResult defaultTestResult;
69 };
70 
instance()71 OutsideTestRunnerUTest& OutsideTestRunnerUTest::instance()
72 {
73     static OutsideTestRunnerUTest instance_;
74     return instance_;
75 }
76 
77 /*
78  * Below helpers are used for the PlatformSpecificSetJmp and LongJmp. They pass a method for what needs to happen after
79  * the jump, so that the stack stays right.
80  *
81  */
82 
83 extern "C" {
84 
helperDoTestSetup(void * data)85     static void helperDoTestSetup(void* data)
86     {
87         ((Utest*)data)->setup();
88     }
89 
helperDoTestBody(void * data)90     static void helperDoTestBody(void* data)
91     {
92         ((Utest*)data)->testBody();
93     }
94 
helperDoTestTeardown(void * data)95     static void helperDoTestTeardown(void* data)
96     {
97         ((Utest*)data)->teardown();
98     }
99 
100     struct HelperTestRunInfo
101     {
HelperTestRunInfoHelperTestRunInfo102         HelperTestRunInfo(UtestShell* shell, TestPlugin* plugin, TestResult* result) : shell_(shell), plugin_(plugin), result_(result){}
103 
104         UtestShell* shell_;
105         TestPlugin* plugin_;
106         TestResult* result_;
107     };
108 
helperDoRunOneTestInCurrentProcess(void * data)109     static void helperDoRunOneTestInCurrentProcess(void* data)
110     {
111         HelperTestRunInfo* runInfo = (HelperTestRunInfo*) data;
112 
113         UtestShell* shell = runInfo->shell_;
114         TestPlugin* plugin = runInfo->plugin_;
115         TestResult* result = runInfo->result_;
116 
117         shell->runOneTestInCurrentProcess(plugin, *result);
118     }
119 
helperDoRunOneTestSeperateProcess(void * data)120     static void helperDoRunOneTestSeperateProcess(void* data)
121     {
122         HelperTestRunInfo* runInfo = (HelperTestRunInfo*) data;
123 
124         UtestShell* shell = runInfo->shell_;
125         TestPlugin* plugin = runInfo->plugin_;
126         TestResult* result = runInfo->result_;
127         PlatformSpecificRunTestInASeperateProcess(shell, plugin, result);
128     }
129 
130 }
131 
132 /******************************** */
133 
UtestShell()134 UtestShell::UtestShell() :
135     group_("UndefinedTestGroup"), name_("UndefinedTest"), file_("UndefinedFile"), lineNumber_(0), next_(NULLPTR), isRunAsSeperateProcess_(false), hasFailed_(false)
136 {
137 }
138 
UtestShell(const char * groupName,const char * testName,const char * fileName,size_t lineNumber)139 UtestShell::UtestShell(const char* groupName, const char* testName, const char* fileName, size_t lineNumber) :
140     group_(groupName), name_(testName), file_(fileName), lineNumber_(lineNumber), next_(NULLPTR), isRunAsSeperateProcess_(false), hasFailed_(false)
141 {
142 }
143 
UtestShell(const char * groupName,const char * testName,const char * fileName,size_t lineNumber,UtestShell * nextTest)144 UtestShell::UtestShell(const char* groupName, const char* testName, const char* fileName, size_t lineNumber, UtestShell* nextTest) :
145     group_(groupName), name_(testName), file_(fileName), lineNumber_(lineNumber), next_(nextTest), isRunAsSeperateProcess_(false), hasFailed_(false)
146 {
147 }
148 
~UtestShell()149 UtestShell::~UtestShell()
150 {
151 }
152 
153 // LCOV_EXCL_START - actually covered but not in .gcno due to race condition
defaultCrashMethod()154 static void defaultCrashMethod()
155 {
156     UtestShell* ptr = (UtestShell*) NULLPTR; ptr->countTests();
157 }
158 // LCOV_EXCL_STOP
159 
160 static void (*pleaseCrashMeRightNow) () = defaultCrashMethod;
161 
setCrashMethod(void (* crashme)())162 void UtestShell::setCrashMethod(void (*crashme)())
163 {
164     pleaseCrashMeRightNow = crashme;
165 }
166 
resetCrashMethod()167 void UtestShell::resetCrashMethod()
168 {
169     pleaseCrashMeRightNow = defaultCrashMethod;
170 }
171 
crash()172 void UtestShell::crash()
173 {
174     pleaseCrashMeRightNow();
175 }
176 
runOneTest(TestPlugin * plugin,TestResult & result)177 void UtestShell::runOneTest(TestPlugin* plugin, TestResult& result)
178 {
179     hasFailed_ = false;
180     result.countRun();
181     HelperTestRunInfo runInfo(this, plugin, &result);
182     if (isRunInSeperateProcess())
183         PlatformSpecificSetJmp(helperDoRunOneTestSeperateProcess, &runInfo);
184     else
185         PlatformSpecificSetJmp(helperDoRunOneTestInCurrentProcess, &runInfo);
186 }
187 
createTest()188 Utest* UtestShell::createTest()
189 {
190     return new Utest();
191 }
192 
destroyTest(Utest * test)193 void UtestShell::destroyTest(Utest* test)
194 {
195     delete test;
196 }
197 
runOneTestInCurrentProcess(TestPlugin * plugin,TestResult & result)198 void UtestShell::runOneTestInCurrentProcess(TestPlugin* plugin, TestResult& result)
199 {
200     result.printVeryVerbose("\n-- before runAllPreTestAction: ");
201     plugin->runAllPreTestAction(*this, result);
202     result.printVeryVerbose("\n-- after runAllPreTestAction: ");
203 
204     //save test context, so that test class can be tested
205     UtestShell* savedTest = UtestShell::getCurrent();
206     TestResult* savedResult = UtestShell::getTestResult();
207 
208     UtestShell::setTestResult(&result);
209     UtestShell::setCurrentTest(this);
210 
211     result.printVeryVerbose("\n---- before createTest: ");
212     Utest* testToRun = createTest();
213     result.printVeryVerbose("\n---- after createTest: ");
214 
215     result.printVeryVerbose("\n------ before runTest: ");
216     testToRun->run();
217     result.printVeryVerbose("\n------ after runTest: ");
218 
219     UtestShell::setCurrentTest(savedTest);
220     UtestShell::setTestResult(savedResult);
221 
222     result.printVeryVerbose("\n---- before destroyTest: ");
223     destroyTest(testToRun);
224     result.printVeryVerbose("\n---- after destroyTest: ");
225 
226     result.printVeryVerbose("\n-- before runAllPostTestAction: ");
227     plugin->runAllPostTestAction(*this, result);
228     result.printVeryVerbose("\n-- after runAllPostTestAction: ");
229 }
230 
getNext() const231 UtestShell *UtestShell::getNext() const
232 {
233     return next_;
234 }
235 
addTest(UtestShell * test)236 UtestShell* UtestShell::addTest(UtestShell *test)
237 {
238     next_ = test;
239     return this;
240 }
241 
countTests()242 size_t UtestShell::countTests()
243 {
244     return next_ ? next_->countTests() + 1 : 1;
245 }
246 
getMacroName() const247 SimpleString UtestShell::getMacroName() const
248 {
249     return "TEST";
250 }
251 
getName() const252 const SimpleString UtestShell::getName() const
253 {
254     return SimpleString(name_);
255 }
256 
getGroup() const257 const SimpleString UtestShell::getGroup() const
258 {
259     return SimpleString(group_);
260 }
261 
getFormattedName() const262 SimpleString UtestShell::getFormattedName() const
263 {
264     SimpleString formattedName(getMacroName());
265     formattedName += "(";
266     formattedName += group_;
267     formattedName += ", ";
268     formattedName += name_;
269     formattedName += ")";
270 
271     return formattedName;
272 }
273 
hasFailed() const274 bool UtestShell::hasFailed() const
275 {
276     return hasFailed_;
277 }
278 
countCheck()279 void UtestShell::countCheck()
280 {
281     getTestResult()->countCheck();
282 }
283 
willRun() const284 bool UtestShell::willRun() const
285 {
286     return true;
287 }
288 
isRunInSeperateProcess() const289 bool UtestShell::isRunInSeperateProcess() const
290 {
291     return isRunAsSeperateProcess_;
292 }
293 
setRunInSeperateProcess()294 void UtestShell::setRunInSeperateProcess()
295 {
296     isRunAsSeperateProcess_ = true;
297 }
298 
299 
setRunIgnored()300 void UtestShell::setRunIgnored()
301 {
302 
303 }
304 
setFileName(const char * fileName)305 void UtestShell::setFileName(const char* fileName)
306 {
307     file_ = fileName;
308 }
309 
setLineNumber(size_t lineNumber)310 void UtestShell::setLineNumber(size_t lineNumber)
311 {
312     lineNumber_ = lineNumber;
313 }
314 
setGroupName(const char * groupName)315 void UtestShell::setGroupName(const char* groupName)
316 {
317     group_ = groupName;
318 }
319 
setTestName(const char * testName)320 void UtestShell::setTestName(const char* testName)
321 {
322     name_ = testName;
323 }
324 
getFile() const325 const SimpleString UtestShell::getFile() const
326 {
327     return SimpleString(file_);
328 }
329 
getLineNumber() const330 size_t UtestShell::getLineNumber() const
331 {
332     return lineNumber_;
333 }
334 
match(const char * target,const TestFilter * filters) const335 bool UtestShell::match(const char* target, const TestFilter* filters) const
336 {
337     if(filters == NULLPTR) return true;
338 
339     for(; filters != NULLPTR; filters = filters->getNext())
340         if(filters->match(target)) return true;
341 
342     return false;
343 }
344 
shouldRun(const TestFilter * groupFilters,const TestFilter * nameFilters) const345 bool UtestShell::shouldRun(const TestFilter* groupFilters, const TestFilter* nameFilters) const
346 {
347     return match(group_, groupFilters) && match(name_, nameFilters);
348 }
349 
failWith(const TestFailure & failure)350 void UtestShell::failWith(const TestFailure& failure)
351 {
352     failWith(failure, NormalTestTerminator());
353 } // LCOV_EXCL_LINE
354 
failWith(const TestFailure & failure,const TestTerminator & terminator)355 void UtestShell::failWith(const TestFailure& failure, const TestTerminator& terminator)
356 {
357     hasFailed_ = true;
358     getTestResult()->addFailure(failure);
359     terminator.exitCurrentTest();
360 } // LCOV_EXCL_LINE
361 
exitTest(const TestTerminator & terminator)362 void UtestShell::exitTest(const TestTerminator& terminator)
363 {
364     terminator.exitCurrentTest();
365 } // LCOV_EXCL_LINE
366 
assertTrue(bool condition,const char * checkString,const char * conditionString,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)367 void UtestShell::assertTrue(bool condition, const char *checkString, const char *conditionString, const char* text, const char *fileName, size_t lineNumber, const TestTerminator& testTerminator)
368 {
369     getTestResult()->countCheck();
370     if (!condition)
371         failWith(CheckFailure(this, fileName, lineNumber, checkString, conditionString, text), testTerminator);
372 }
373 
fail(const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)374 void UtestShell::fail(const char *text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
375 {
376     getTestResult()->countCheck();
377     failWith(FailFailure(this, fileName, lineNumber, text), testTerminator);
378 } // LCOV_EXCL_LINE
379 
assertCstrEqual(const char * expected,const char * actual,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)380 void UtestShell::assertCstrEqual(const char* expected, const char* actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
381 {
382     getTestResult()->countCheck();
383     if (actual == NULLPTR && expected == NULLPTR) return;
384     if (actual == NULLPTR || expected == NULLPTR)
385         failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
386     if (SimpleString::StrCmp(expected, actual) != 0)
387         failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
388 }
389 
assertCstrNEqual(const char * expected,const char * actual,size_t length,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)390 void UtestShell::assertCstrNEqual(const char* expected, const char* actual, size_t length, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
391 {
392     getTestResult()->countCheck();
393     if (actual == NULLPTR && expected == NULLPTR) return;
394     if (actual == NULLPTR || expected == NULLPTR)
395         failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
396     if (SimpleString::StrNCmp(expected, actual, length) != 0)
397         failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
398 }
399 
assertCstrNoCaseEqual(const char * expected,const char * actual,const char * text,const char * fileName,size_t lineNumber)400 void UtestShell::assertCstrNoCaseEqual(const char* expected, const char* actual, const char* text, const char* fileName, size_t lineNumber)
401 {
402     getTestResult()->countCheck();
403     if (actual == NULLPTR && expected == NULLPTR) return;
404     if (actual == NULLPTR || expected == NULLPTR)
405         failWith(StringEqualNoCaseFailure(this, fileName, lineNumber, expected, actual, text));
406     if (!SimpleString(expected).equalsNoCase(actual))
407         failWith(StringEqualNoCaseFailure(this, fileName, lineNumber, expected, actual, text));
408 }
409 
assertCstrContains(const char * expected,const char * actual,const char * text,const char * fileName,size_t lineNumber)410 void UtestShell::assertCstrContains(const char* expected, const char* actual, const char* text, const char* fileName, size_t lineNumber)
411 {
412     getTestResult()->countCheck();
413     if (actual == NULLPTR && expected == NULLPTR) return;
414     if (actual == NULLPTR || expected == NULLPTR)
415         failWith(ContainsFailure(this, fileName, lineNumber, expected, actual, text));
416     if (!SimpleString(actual).contains(expected))
417         failWith(ContainsFailure(this, fileName, lineNumber, expected, actual, text));
418 }
419 
assertCstrNoCaseContains(const char * expected,const char * actual,const char * text,const char * fileName,size_t lineNumber)420 void UtestShell::assertCstrNoCaseContains(const char* expected, const char* actual, const char* text, const char* fileName, size_t lineNumber)
421 {
422     getTestResult()->countCheck();
423     if (actual == NULLPTR && expected == NULLPTR) return;
424     if (actual == NULLPTR || expected == NULLPTR)
425         failWith(ContainsFailure(this, fileName, lineNumber, expected, actual, text));
426     if (!SimpleString(actual).containsNoCase(expected))
427         failWith(ContainsFailure(this, fileName, lineNumber, expected, actual, text));
428 }
429 
assertLongsEqual(long expected,long actual,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)430 void UtestShell::assertLongsEqual(long expected, long actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
431 {
432     getTestResult()->countCheck();
433     if (expected != actual)
434         failWith(LongsEqualFailure (this, fileName, lineNumber, expected, actual, text), testTerminator);
435 }
436 
assertUnsignedLongsEqual(unsigned long expected,unsigned long actual,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)437 void UtestShell::assertUnsignedLongsEqual(unsigned long expected, unsigned long actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
438 {
439     getTestResult()->countCheck();
440     if (expected != actual)
441         failWith(UnsignedLongsEqualFailure (this, fileName, lineNumber, expected, actual, text), testTerminator);
442 }
443 
assertLongLongsEqual(cpputest_longlong expected,cpputest_longlong actual,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)444 void UtestShell::assertLongLongsEqual(cpputest_longlong expected, cpputest_longlong actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
445 {
446     getTestResult()->countCheck();
447 #ifdef CPPUTEST_USE_LONG_LONG
448     if (expected != actual)
449         failWith(LongLongsEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
450 #else
451     (void)expected;
452     (void)actual;
453     failWith(FeatureUnsupportedFailure(this, fileName, lineNumber, "CPPUTEST_USE_LONG_LONG", text), testTerminator);
454 #endif
455 }
456 
assertUnsignedLongLongsEqual(cpputest_ulonglong expected,cpputest_ulonglong actual,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)457 void UtestShell::assertUnsignedLongLongsEqual(cpputest_ulonglong expected, cpputest_ulonglong actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
458 {
459     getTestResult()->countCheck();
460 #ifdef CPPUTEST_USE_LONG_LONG
461     if (expected != actual)
462         failWith(UnsignedLongLongsEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
463 #else
464     (void)expected;
465     (void)actual;
466     failWith(FeatureUnsupportedFailure(this, fileName, lineNumber, "CPPUTEST_USE_LONG_LONG", text), testTerminator);
467 #endif
468 }
469 
assertSignedBytesEqual(signed char expected,signed char actual,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)470 void UtestShell::assertSignedBytesEqual(signed char expected, signed char actual, const char* text, const char *fileName, size_t lineNumber, const TestTerminator& testTerminator)
471 {
472     getTestResult()->countCheck();
473     if (expected != actual)
474         failWith(SignedBytesEqualFailure (this, fileName, lineNumber, expected, actual, text), testTerminator);
475 }
476 
assertPointersEqual(const void * expected,const void * actual,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)477 void UtestShell::assertPointersEqual(const void* expected, const void* actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
478 {
479     getTestResult()->countCheck();
480     if (expected != actual)
481         failWith(EqualsFailure(this, fileName, lineNumber, StringFrom(expected), StringFrom(actual), text), testTerminator);
482 }
483 
assertFunctionPointersEqual(void (* expected)(),void (* actual)(),const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)484 void UtestShell::assertFunctionPointersEqual(void (*expected)(), void (*actual)(), const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
485 {
486     getTestResult()->countCheck();
487     if (expected != actual)
488         failWith(EqualsFailure(this, fileName, lineNumber, StringFrom(expected), StringFrom(actual), text), testTerminator);
489 }
490 
assertDoublesEqual(double expected,double actual,double threshold,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)491 void UtestShell::assertDoublesEqual(double expected, double actual, double threshold, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
492 {
493     getTestResult()->countCheck();
494     if (!doubles_equal(expected, actual, threshold))
495         failWith(DoublesEqualFailure(this, fileName, lineNumber, expected, actual, threshold, text), testTerminator);
496 }
497 
assertBinaryEqual(const void * expected,const void * actual,size_t length,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)498 void UtestShell::assertBinaryEqual(const void *expected, const void *actual, size_t length, const char* text, const char *fileName, size_t lineNumber, const TestTerminator& testTerminator)
499 {
500     getTestResult()->countCheck();
501 	if (length == 0) return;
502     if (actual == NULLPTR && expected == NULLPTR) return;
503     if (actual == NULLPTR || expected == NULLPTR)
504         failWith(BinaryEqualFailure(this, fileName, lineNumber, (const unsigned char *) expected, (const unsigned char *) actual, length, text), testTerminator);
505     if (SimpleString::MemCmp(expected, actual, length) != 0)
506         failWith(BinaryEqualFailure(this, fileName, lineNumber, (const unsigned char *) expected, (const unsigned char *) actual, length, text), testTerminator);
507 }
508 
assertBitsEqual(unsigned long expected,unsigned long actual,unsigned long mask,size_t byteCount,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)509 void UtestShell::assertBitsEqual(unsigned long expected, unsigned long actual, unsigned long mask, size_t byteCount, const char* text, const char *fileName, size_t lineNumber, const TestTerminator& testTerminator)
510 {
511     getTestResult()->countCheck();
512     if ((expected & mask) != (actual & mask))
513         failWith(BitsEqualFailure(this, fileName, lineNumber, expected, actual, mask, byteCount, text), testTerminator);
514 }
515 
assertEquals(bool failed,const char * expected,const char * actual,const char * text,const char * file,size_t line,const TestTerminator & testTerminator)516 void UtestShell::assertEquals(bool failed, const char* expected, const char* actual, const char* text, const char* file, size_t line, const TestTerminator& testTerminator)
517 {
518     getTestResult()->countCheck();
519     if (failed)
520         failWith(CheckEqualFailure(this, file, line, expected, actual, text), testTerminator);
521 }
522 
assertCompare(bool comparison,const char * checkString,const char * comparisonString,const char * text,const char * fileName,size_t lineNumber,const TestTerminator & testTerminator)523 void UtestShell::assertCompare(bool comparison, const char *checkString, const char *comparisonString, const char *text, const char *fileName, size_t lineNumber, const TestTerminator &testTerminator)
524 {
525     getTestResult()->countCheck();
526     if (!comparison)
527         failWith(ComparisonFailure(this, fileName, lineNumber, checkString, comparisonString, text), testTerminator);
528 }
529 
print(const char * text,const char * fileName,size_t lineNumber)530 void UtestShell::print(const char *text, const char* fileName, size_t lineNumber)
531 {
532     SimpleString stringToPrint = "\n";
533     stringToPrint += fileName;
534     stringToPrint += ":";
535     stringToPrint += StringFrom(lineNumber);
536     stringToPrint += " ";
537     stringToPrint += text;
538     getTestResult()->print(stringToPrint.asCharString());
539 }
540 
print(const SimpleString & text,const char * fileName,size_t lineNumber)541 void UtestShell::print(const SimpleString& text, const char* fileName, size_t lineNumber)
542 {
543     print(text.asCharString(), fileName, lineNumber);
544 }
545 
printVeryVerbose(const char * text)546 void UtestShell::printVeryVerbose(const char* text)
547 {
548     getTestResult()->printVeryVerbose(text);
549 }
550 
551 TestResult* UtestShell::testResult_ = NULLPTR;
552 UtestShell* UtestShell::currentTest_ = NULLPTR;
553 
setTestResult(TestResult * result)554 void UtestShell::setTestResult(TestResult* result)
555 {
556     testResult_ = result;
557 }
558 
setCurrentTest(UtestShell * test)559 void UtestShell::setCurrentTest(UtestShell* test)
560 {
561     currentTest_ = test;
562 }
563 
getTestResult()564 TestResult* UtestShell::getTestResult()
565 {
566     if (testResult_ == NULLPTR)
567         return &OutsideTestRunnerUTest::instance().getTestResult();
568     return testResult_;
569 }
570 
getCurrent()571 UtestShell* UtestShell::getCurrent()
572 {
573     if (currentTest_ == NULLPTR)
574         return &OutsideTestRunnerUTest::instance();
575     return currentTest_;
576 }
577 
578 
~ExecFunctionTestShell()579 ExecFunctionTestShell::~ExecFunctionTestShell()
580 {
581 }
582 
583 ////////////// Utest ////////////
584 
Utest()585 Utest::Utest()
586 {
587 }
588 
~Utest()589 Utest::~Utest()
590 {
591 }
592 
593 #if CPPUTEST_USE_STD_CPP_LIB
594 
run()595 void Utest::run()
596 {
597     UtestShell* current = UtestShell::getCurrent();
598     int jumpResult = 0;
599     try {
600         current->printVeryVerbose("\n-------- before setup: ");
601         jumpResult = PlatformSpecificSetJmp(helperDoTestSetup, this);
602         current->printVeryVerbose("\n-------- after  setup: ");
603 
604         if (jumpResult) {
605             current->printVeryVerbose("\n----------  before body: ");
606             PlatformSpecificSetJmp(helperDoTestBody, this);
607             current->printVeryVerbose("\n----------  after body: ");
608         }
609     }
610     catch (CppUTestFailedException&)
611     {
612         PlatformSpecificRestoreJumpBuffer();
613     }
614 
615     try {
616         current->printVeryVerbose("\n--------  before teardown: ");
617         PlatformSpecificSetJmp(helperDoTestTeardown, this);
618         current->printVeryVerbose("\n--------  after teardown: ");
619     }
620     catch (CppUTestFailedException&)
621     {
622         PlatformSpecificRestoreJumpBuffer();
623     }
624 
625 }
626 #else
627 
run()628 void Utest::run()
629 {
630     if (PlatformSpecificSetJmp(helperDoTestSetup, this)) {
631         PlatformSpecificSetJmp(helperDoTestBody, this);
632     }
633     PlatformSpecificSetJmp(helperDoTestTeardown, this);
634 }
635 
636 #endif
637 
setup()638 void Utest::setup()
639 {
640 }
641 
testBody()642 void Utest::testBody()
643 {
644 }
645 
teardown()646 void Utest::teardown()
647 {
648 }
649 
650 
651 /////////////////// Terminators
652 
~TestTerminator()653 TestTerminator::~TestTerminator()
654 {
655 }
656 
exitCurrentTest() const657 void NormalTestTerminator::exitCurrentTest() const
658 {
659     #if CPPUTEST_USE_STD_CPP_LIB
660         throw CppUTestFailedException();
661     #else
662         TestTerminatorWithoutExceptions().exitCurrentTest();
663     #endif
664 }
665 
~NormalTestTerminator()666 NormalTestTerminator::~NormalTestTerminator()
667 {
668 }
669 
exitCurrentTest() const670 void TestTerminatorWithoutExceptions::exitCurrentTest() const
671 {
672     PlatformSpecificLongJmp();
673 } // LCOV_EXCL_LINE
674 
~TestTerminatorWithoutExceptions()675 TestTerminatorWithoutExceptions::~TestTerminatorWithoutExceptions()
676 {
677 }
678 
679 //////////////////// ExecFunction
680 //
ExecFunction()681 ExecFunction::ExecFunction()
682 {
683 }
684 
~ExecFunction()685 ExecFunction::~ExecFunction()
686 {
687 }
688 
ExecFunctionWithoutParameters(void (* testFunction)())689 ExecFunctionWithoutParameters::ExecFunctionWithoutParameters(void(*testFunction)())
690     : testFunction_(testFunction)
691 {
692 }
693 
~ExecFunctionWithoutParameters()694 ExecFunctionWithoutParameters::~ExecFunctionWithoutParameters()
695 {
696 }
697 
exec()698 void ExecFunctionWithoutParameters::exec()
699 {
700     if (testFunction_)
701         testFunction_();
702 }
703 
704 //////////////////// ExecFunctionTest
705 
ExecFunctionTest(ExecFunctionTestShell * shell)706 ExecFunctionTest::ExecFunctionTest(ExecFunctionTestShell* shell)
707     : shell_(shell)
708 {
709 }
710 
testBody()711 void ExecFunctionTest::testBody()
712 {
713     if (shell_->testFunction_) shell_->testFunction_->exec();
714 }
715 
setup()716 void ExecFunctionTest::setup()
717 {
718     if (shell_->setup_) shell_->setup_();
719 }
720 
teardown()721 void ExecFunctionTest::teardown()
722 {
723     if (shell_->teardown_) shell_->teardown_();
724 }
725 
726 /////////////// IgnoredUtestShell /////////////
IgnoredUtestShell()727 IgnoredUtestShell::IgnoredUtestShell(): runIgnored_(false)
728 {
729 }
730 
IgnoredUtestShell(const char * groupName,const char * testName,const char * fileName,size_t lineNumber)731 IgnoredUtestShell::IgnoredUtestShell(const char* groupName, const char* testName, const char* fileName, size_t lineNumber) :
732    UtestShell(groupName, testName, fileName, lineNumber), runIgnored_(false)
733 {
734 }
735 
~IgnoredUtestShell()736 IgnoredUtestShell::~IgnoredUtestShell()
737 {
738 }
739 
willRun() const740 bool IgnoredUtestShell::willRun() const
741 {
742     if (runIgnored_) return UtestShell::willRun();
743 
744     return false;
745 }
746 
getMacroName() const747 SimpleString IgnoredUtestShell::getMacroName() const
748 {
749     if (runIgnored_) return "TEST";
750 
751     return "IGNORE_TEST";
752 }
753 
runOneTest(TestPlugin * plugin,TestResult & result)754 void IgnoredUtestShell::runOneTest(TestPlugin* plugin, TestResult& result)
755 {
756     if (runIgnored_)
757     {
758         UtestShell::runOneTest(plugin, result);
759         return;
760     }
761 
762     result.countIgnored();
763 }
764 
setRunIgnored()765 void IgnoredUtestShell::setRunIgnored()
766 {
767     runIgnored_ = true;
768 }
769 
770 //////////////////// UtestShellPointerArray
771 
UtestShellPointerArray(UtestShell * firstTest)772 UtestShellPointerArray::UtestShellPointerArray(UtestShell* firstTest)
773     : arrayOfTests_(NULLPTR), count_(0)
774 {
775     count_ = (firstTest) ? firstTest->countTests() : 0;
776     if (count_ == 0) return;
777 
778     arrayOfTests_ = new UtestShell*[count_];
779 
780     UtestShell*currentTest = firstTest;
781     for (size_t i = 0; i < count_; i++)
782     {
783         arrayOfTests_[i] = currentTest;
784         currentTest = currentTest->getNext();
785     }
786 }
787 
~UtestShellPointerArray()788 UtestShellPointerArray::~UtestShellPointerArray()
789 {
790     delete [] arrayOfTests_;
791 }
792 
swap(size_t index1,size_t index2)793 void UtestShellPointerArray::swap(size_t index1, size_t index2)
794 {
795         UtestShell* e2 = arrayOfTests_[index2];
796         UtestShell* e1 = arrayOfTests_[index1];
797         arrayOfTests_[index1] = e2;
798         arrayOfTests_[index2] = e1;
799 }
800 
shuffle(size_t seed)801 void UtestShellPointerArray::shuffle(size_t seed)
802 {
803     if (count_ == 0) return;
804 
805     PlatformSpecificSrand((unsigned int) seed);
806 
807     for (size_t i = count_ - 1; i >= 1; --i)
808     {
809         if (count_ == 0) return;
810 
811         const size_t j = ((size_t)PlatformSpecificRand()) % (i + 1); // distribution biased by modulo, but good enough for shuffling
812         swap(i, j);
813    }
814    relinkTestsInOrder();
815 }
816 
reverse()817 void UtestShellPointerArray::reverse()
818 {
819     if (count_ == 0) return;
820 
821     size_t halfCount = count_ / 2;
822     for (size_t i = 0; i < halfCount; i++)
823     {
824         size_t j = count_ - i - 1;
825         swap(i, j);
826    }
827    relinkTestsInOrder();
828 }
829 
relinkTestsInOrder()830 void UtestShellPointerArray::relinkTestsInOrder()
831 {
832     UtestShell *tests = NULLPTR;
833     for (size_t i = 0; i < count_; i++)
834         tests = arrayOfTests_[count_ - i - 1]->addTest(tests);
835 }
836 
getFirstTest() const837 UtestShell* UtestShellPointerArray::getFirstTest() const
838 {
839     return get(0);
840 }
841 
get(size_t index) const842 UtestShell* UtestShellPointerArray::get(size_t index) const
843 {
844     if (index >= count_) return NULLPTR;
845     return arrayOfTests_[index];
846 }
847 
848 
849 
850 ////////////// TestInstaller ////////////
851 
TestInstaller(UtestShell & shell,const char * groupName,const char * testName,const char * fileName,size_t lineNumber)852 TestInstaller::TestInstaller(UtestShell& shell, const char* groupName, const char* testName, const char* fileName, size_t lineNumber)
853 {
854     shell.setGroupName(groupName);
855     shell.setTestName(testName);
856     shell.setFileName(fileName);
857     shell.setLineNumber(lineNumber);
858     TestRegistry::getCurrentRegistry()->addTest(&shell);
859 }
860 
~TestInstaller()861 TestInstaller::~TestInstaller()
862 {
863 }
864 
unDo()865 void TestInstaller::unDo()
866 {
867     TestRegistry::getCurrentRegistry()->unDoLastAddTest();
868 }
869