fork
Fork of cpputest by
Revision 1:4769360130ed, committed 2014-06-17
- Comitter:
- Rohit Grover
- Date:
- Tue Jun 17 15:52:54 2014 +0100
- Parent:
- 0:0b799af9d58e
- Child:
- 2:82161d9e7b36
- Commit message:
- updating to the latest version of cppUtest; tested against nordic's m-kit
Changed in this revision
--- a/include/CppUTest/CommandLineArguments.h Tue Jan 28 09:27:41 2014 +0000 +++ b/include/CppUTest/CommandLineArguments.h Tue Jun 17 15:52:54 2014 +0100 @@ -48,6 +48,7 @@ bool isJUnitOutput() const; bool isEclipseOutput() const; bool runTestsInSeperateProcess() const; + const SimpleString& getPackageName() const; const char* usage() const; private: @@ -65,6 +66,7 @@ TestFilter groupFilter_; TestFilter nameFilter_; OutputType outputType_; + SimpleString packageName_; SimpleString getParameterField(int ac, const char** av, int& i, const SimpleString& parameterName); void SetRepeatCount(int ac, const char** av, int& index); @@ -74,6 +76,7 @@ void SetStrictNameFilter(int ac, const char** av, int& index); void SetTestToRunBasedOnVerboseOutput(int ac, const char** av, int& index, const char* parameterName); bool SetOutputType(int ac, const char** av, int& index); + void SetPackageName(int ac, const char** av, int& index); CommandLineArguments(const CommandLineArguments&); CommandLineArguments& operator=(const CommandLineArguments&);
--- a/include/CppUTest/CppUTestConfig.h Tue Jan 28 09:27:41 2014 +0000
+++ b/include/CppUTest/CppUTestConfig.h Tue Jun 17 15:52:54 2014 +0100
@@ -62,8 +62,7 @@
#endif
#endif
-
-#if NEED_TO_ENABLE_CPP_SUPPORT /* disabled by default because mbed's
+#if NEED_TO_ENABLE_CPP_SUPPORT /* disabled by default because our
* toolchain doesn't support exceptions. */
/* Do we use Standard C++ or not? */
#ifndef CPPUTEST_USE_STD_CPP_LIB
@@ -124,17 +123,27 @@
#endif
#else
#define UT_THROW(exception)
- #define UT_NOTHROW
+ #ifdef __clang__
+ #define UT_NOTHROW throw()
+ #else
+ #define UT_NOTHROW
+ #endif
#endif
/*
- * CLang's operator delete requires an NOTHROW block. For now, when we use CLang, then have an empty exception specifier.
- * However, this ought to be done inside the configure.ac in the future.
+ * Visual C++ doesn't define __cplusplus as C++11 yet (201103), however it doesn't want the throw(exception) either, but
+ * it does want throw().
*/
-#ifdef __clang__
-#undef UT_NOTHROW
-#define UT_NOTHROW throw()
+#ifdef _MSC_VER
+ #undef UT_THROW
+ #define UT_THROW(exception)
+#endif
+
+#if defined(__cplusplus) && __cplusplus >= 201103L
+ #define DEFAULT_COPY_CONSTRUCTOR(classname) classname(const classname &) = default;
+#else
+ #define DEFAULT_COPY_CONSTRUCTOR(classname)
#endif
/*
@@ -163,7 +172,8 @@
#endif
#endif
-#if defined(__cplusplus) && __cplusplus >= 201103L
+/* Visual C++ 10.0+ (2010+) supports the override keyword, but doesn't define the C++ version as C++11 */
+#if defined(__cplusplus) && ((__cplusplus >= 201103L) || (defined(_MSC_VER) && (_MSC_VER >= 1600)))
#define _override override
#else
#define _override
--- a/include/CppUTest/JUnitTestOutput.h Tue Jan 28 09:27:41 2014 +0000 +++ b/include/CppUTest/JUnitTestOutput.h Tue Jun 17 15:52:54 2014 +0100 @@ -57,6 +57,7 @@ virtual void flush() _override; virtual SimpleString createFileName(const SimpleString& group); + void setPackageName(const SimpleString &package); protected:
--- a/include/CppUTest/MemoryLeakDetectorNewMacros.h Tue Jan 28 09:27:41 2014 +0000 +++ b/include/CppUTest/MemoryLeakDetectorNewMacros.h Tue Jun 17 15:52:54 2014 +0100 @@ -21,7 +21,8 @@ #include "CppUTestConfig.h" -#if CPPUTEST_USE_MEM_LEAK_DETECTION +/* Make sure that mem leak detection is on and that this is being included from a C++ file */ +#if CPPUTEST_USE_MEM_LEAK_DETECTION && defined(__cplusplus) /* This #ifndef prevents <new> from being included twice and enables the file to be included anywhere */ #ifndef CPPUTEST_USE_NEW_MACROS
--- a/include/CppUTest/MemoryLeakWarningPlugin.h Tue Jan 28 09:27:41 2014 +0000 +++ b/include/CppUTest/MemoryLeakWarningPlugin.h Tue Jun 17 15:52:54 2014 +0100 @@ -66,6 +66,7 @@ static void turnOffNewDeleteOverloads(); static void turnOnNewDeleteOverloads(); + static bool areNewDeleteOverloaded(); private: MemoryLeakDetector* memLeakDetector_; bool ignoreAllWarnings_;
--- a/include/CppUTest/PlatformSpecificFunctions_c.h Tue Jan 28 09:27:41 2014 +0000 +++ b/include/CppUTest/PlatformSpecificFunctions_c.h Tue Jun 17 15:52:54 2014 +0100 @@ -56,9 +56,6 @@ /* String operations */ int PlatformSpecificAtoI(const char*str); size_t PlatformSpecificStrLen(const char* str); -char* PlatformSpecificStrCat(char* s1, const char* s2); -char* PlatformSpecificStrCpy(char* s1, const char* s2); -char* PlatformSpecificStrNCpy(char* s1, const char* s2, size_t size); int PlatformSpecificStrCmp(const char* s1, const char* s2); int PlatformSpecificStrNCmp(const char* s1, const char* s2, size_t size); char* PlatformSpecificStrStr(const char* s1, const char* s2);
--- a/include/CppUTest/SimpleString.h Tue Jan 28 09:27:41 2014 +0000 +++ b/include/CppUTest/SimpleString.h Tue Jun 17 15:52:54 2014 +0100 @@ -90,13 +90,15 @@ static void setStringAllocator(TestMemoryAllocator* allocator); static char* allocStringBuffer(size_t size); + static char* StrNCpy(char* s1, const char* s2, size_t n); static void deallocStringBuffer(char* str); private: char *buffer_; static TestMemoryAllocator* stringAllocator_; - char* getEmptyString() const; + char* getEmptyString() const; + static char* copyToNewBuffer(const char* bufferToCopy, size_t bufferSize=0); }; class SimpleStringCollection @@ -124,15 +126,17 @@ SimpleString StringFrom(char value); SimpleString StringFrom(const char *value); SimpleString StringFromOrNull(const char * value); +SimpleString StringFrom(int value); +SimpleString StringFrom(unsigned int value); SimpleString StringFrom(long value); -SimpleString StringFrom(int value); +SimpleString StringFrom(unsigned long value); SimpleString HexStringFrom(long value); +SimpleString HexStringFrom(unsigned long value); SimpleString HexStringFrom(const void* value); SimpleString StringFrom(double value, int precision = 6); SimpleString StringFrom(const SimpleString& other); SimpleString StringFromFormat(const char* format, ...) __check_format__(printf, 1, 2); SimpleString VStringFromFormat(const char* format, va_list args); -SimpleString StringFrom(unsigned int value); #if CPPUTEST_USE_STD_CPP_LIB @@ -140,7 +144,6 @@ #include <stdint.h> SimpleString StringFrom(const std::string& other); -SimpleString StringFrom(unsigned long); #endif
--- a/include/CppUTest/TestFailure.h Tue Jan 28 09:27:41 2014 +0000
+++ b/include/CppUTest/TestFailure.h Tue Jun 17 15:52:54 2014 +0100
@@ -122,6 +122,12 @@
LongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, long expected, long actual);
};
+class UnsignedLongsEqualFailure : public TestFailure
+{
+public:
+ UnsignedLongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, unsigned long expected, unsigned long actual);
+};
+
class StringEqualFailure : public TestFailure
{
public:
--- a/include/CppUTest/TestPlugin.h Tue Jan 28 09:27:41 2014 +0000
+++ b/include/CppUTest/TestPlugin.h Tue Jun 17 15:52:54 2014 +0100
@@ -95,7 +95,7 @@
enum
{
- MAX_SET = 1024
+ MAX_SET = 16
};
};
--- a/include/CppUTest/TestResult.h Tue Jan 28 09:27:41 2014 +0000
+++ b/include/CppUTest/TestResult.h Tue Jun 17 15:52:54 2014 +0100
@@ -42,6 +42,7 @@
{
public:
TestResult(TestOutput&);
+ DEFAULT_COPY_CONSTRUCTOR(TestResult)
virtual ~TestResult();
virtual void testsStarted();
--- a/include/CppUTest/Utest.h Tue Jan 28 09:27:41 2014 +0000
+++ b/include/CppUTest/Utest.h Tue Jun 17 15:52:54 2014 +0100
@@ -111,7 +111,8 @@
virtual void assertCstrNoCaseEqual(const char *expected, const char *actual, const char *fileName, int lineNumber);
virtual void assertCstrContains(const char *expected, const char *actual, const char *fileName, int lineNumber);
virtual void assertCstrNoCaseContains(const char *expected, const char *actual, const char *fileName, int lineNumber);
- virtual void assertLongsEqual(long expected, long actual, const char *fileName, int lineNumber, const TestTerminator& testTerminator = NormalTestTerminator());
+ virtual void assertLongsEqual(long expected, long actual, const char *fileName, int lineNumber, const TestTerminator& testTerminator = NormalTestTerminator());
+ virtual void assertUnsignedLongsEqual(unsigned long expected, unsigned long actual, const char *fileName, int lineNumber, const TestTerminator& testTerminator = NormalTestTerminator());
virtual void assertPointersEqual(const void *expected, const void *actual, const char *fileName, int lineNumber);
virtual void assertDoublesEqual(double expected, double actual, double threshold, const char *fileName, int lineNumber, const TestTerminator& testTerminator = NormalTestTerminator());
virtual void assertEquals(bool failed, const char* expected, const char* actual, const char* file, int line, const TestTerminator& testTerminator = NormalTestTerminator());
--- a/include/CppUTest/UtestMacros.h Tue Jan 28 09:27:41 2014 +0000
+++ b/include/CppUTest/UtestMacros.h Tue Jun 17 15:52:54 2014 +0100
@@ -122,6 +122,10 @@
if ((expected) != (expected)) \
UtestShell::getCurrent()->print("WARNING:\n\tThe \"Expected Parameter\" parameter is evaluated multiple times resulting in different values.\n\tThus the value in the error message is probably incorrect.", file, line); \
UtestShell::getCurrent()->assertEquals(true, StringFrom(expected).asCharString(), StringFrom(actual).asCharString(), file, line); \
+ } \
+ else \
+ { \
+ UtestShell::getCurrent()->assertLongsEqual((long)0, (long)0, file, line); \
} }
//This check checks for char* string equality using strcmp.
@@ -154,9 +158,15 @@
#define LONGS_EQUAL(expected,actual)\
LONGS_EQUAL_LOCATION(expected,actual,__FILE__, __LINE__)
+#define UNSIGNED_LONGS_EQUAL(expected,actual)\
+ UNSIGNED_LONGS_EQUAL_LOCATION(expected,actual,__FILE__, __LINE__)
+
#define LONGS_EQUAL_LOCATION(expected,actual,file,line)\
{ UtestShell::getCurrent()->assertLongsEqual((long)expected, (long)actual, file, line); }
+#define UNSIGNED_LONGS_EQUAL_LOCATION(expected,actual,file,line)\
+ { UtestShell::getCurrent()->assertUnsignedLongsEqual((unsigned long)expected, (unsigned long)actual, file, line); }
+
#define BYTES_EQUAL(expected, actual)\
LONGS_EQUAL((expected) & 0xff,(actual) & 0xff)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/Platforms/armcc/Platform.h Tue Jun 17 15:52:54 2014 +0100 @@ -0,0 +1,6 @@ + +#ifndef PLATFORM_H_ +#define PLATFORM_H_ + +#endif /*PLATFORM_H_*/ +
--- a/src/CppUTest/CommandLineArguments.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/CommandLineArguments.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,179 +1,193 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/CommandLineArguments.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-
-CommandLineArguments::CommandLineArguments(int ac, const char** av) :
- ac_(ac), av_(av), verbose_(false), runTestsAsSeperateProcess_(false), repeat_(1), groupFilter_(""), nameFilter_(""), outputType_(OUTPUT_ECLIPSE)
-{
-}
-
-CommandLineArguments::~CommandLineArguments()
-{
-}
-
-bool CommandLineArguments::parse(TestPlugin* plugin)
-{
- bool correctParameters = true;
- for (int i = 1; i < ac_; i++) {
- SimpleString argument = av_[i];
- if (argument == "-v") verbose_ = true;
- else if (argument == "-p") runTestsAsSeperateProcess_ = true;
- else if (argument.startsWith("-r")) SetRepeatCount(ac_, av_, i);
- else if (argument.startsWith("-g")) SetGroupFilter(ac_, av_, i);
- else if (argument.startsWith("-sg")) SetStrictGroupFilter(ac_, av_, i);
- else if (argument.startsWith("-n")) SetNameFilter(ac_, av_, i);
- else if (argument.startsWith("-sn")) SetStrictNameFilter(ac_, av_, i);
- else if (argument.startsWith("TEST(")) SetTestToRunBasedOnVerboseOutput(ac_, av_, i, "TEST(");
- else if (argument.startsWith("IGNORE_TEST(")) SetTestToRunBasedOnVerboseOutput(ac_, av_, i, "IGNORE_TEST(");
- else if (argument.startsWith("-o")) correctParameters = SetOutputType(ac_, av_, i);
- else if (argument.startsWith("-p")) correctParameters = plugin->parseAllArguments(ac_, av_, i);
- else correctParameters = false;
-
- if (correctParameters == false) {
- return false;
- }
- }
- return true;
-}
-
-const char* CommandLineArguments::usage() const
-{
- return "usage [-v] [-r#] [-g|sg groupName] [-n|sn testName] [-o{normal, junit}]\n";
-}
-
-bool CommandLineArguments::isVerbose() const
-{
- return verbose_;
-}
-
-bool CommandLineArguments::runTestsInSeperateProcess() const
-{
- return runTestsAsSeperateProcess_;
-}
-
-
-int CommandLineArguments::getRepeatCount() const
-{
- return repeat_;
-}
-
-TestFilter CommandLineArguments::getGroupFilter() const
-{
- return groupFilter_;
-}
-
-TestFilter CommandLineArguments::getNameFilter() const
-{
- return nameFilter_;
-}
-
-void CommandLineArguments::SetRepeatCount(int ac, const char** av, int& i)
-{
- repeat_ = 0;
-
- SimpleString repeatParameter(av[i]);
- if (repeatParameter.size() > 2) repeat_ = PlatformSpecificAtoI(av[i] + 2);
- else if (i + 1 < ac) {
- repeat_ = PlatformSpecificAtoI(av[i + 1]);
- if (repeat_ != 0) i++;
- }
-
- if (0 == repeat_) repeat_ = 2;
-
-}
-
-SimpleString CommandLineArguments::getParameterField(int ac, const char** av, int& i, const SimpleString& parameterName)
-{
- size_t parameterLength = parameterName.size();
- SimpleString parameter(av[i]);
- if (parameter.size() > parameterLength) return av[i] + parameterLength;
- else if (i + 1 < ac) return av[++i];
- return "";
-}
-
-void CommandLineArguments::SetGroupFilter(int ac, const char** av, int& i)
-{
- groupFilter_ = TestFilter(getParameterField(ac, av, i, "-g"));
-}
-
-void CommandLineArguments::SetStrictGroupFilter(int ac, const char** av, int& i)
-{
- groupFilter_ = TestFilter(getParameterField(ac, av, i, "-sg"));
- groupFilter_.strictMatching();
-}
-
-void CommandLineArguments::SetNameFilter(int ac, const char** av, int& i)
-{
- nameFilter_ = getParameterField(ac, av, i, "-n");
-}
-
-void CommandLineArguments::SetStrictNameFilter(int ac, const char** av, int& index)
-{
- nameFilter_ = getParameterField(ac, av, index, "-sn");
- nameFilter_.strictMatching();
-}
-
-void CommandLineArguments::SetTestToRunBasedOnVerboseOutput(int ac, const char** av, int& index, const char* parameterName)
-{
- SimpleString wholename = getParameterField(ac, av, index, parameterName);
- SimpleString testname = wholename.subStringFromTill(',', ')');
- testname = testname.subString(2, testname.size());
- groupFilter_ = wholename.subStringFromTill(wholename.at(0), ',');
- nameFilter_ = testname;
- nameFilter_.strictMatching();
- groupFilter_.strictMatching();
-}
-
-bool CommandLineArguments::SetOutputType(int ac, const char** av, int& i)
-{
- SimpleString outputType = getParameterField(ac, av, i, "-o");
- if (outputType.size() == 0) return false;
-
- if (outputType == "normal" || outputType == "eclipse") {
- outputType_ = OUTPUT_ECLIPSE;
- return true;
- }
- if (outputType == "junit") {
- outputType_ = OUTPUT_JUNIT;
- return true;
- }
- return false;
-}
-
-bool CommandLineArguments::isEclipseOutput() const
-{
- return outputType_ == OUTPUT_ECLIPSE;
-}
-
-bool CommandLineArguments::isJUnitOutput() const
-{
- return outputType_ == OUTPUT_JUNIT;
-}
-
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/CommandLineArguments.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+
+CommandLineArguments::CommandLineArguments(int ac, const char** av) :
+ ac_(ac), av_(av), verbose_(false), runTestsAsSeperateProcess_(false), repeat_(1), groupFilter_(""), nameFilter_(""), outputType_(OUTPUT_ECLIPSE), packageName_("")
+{
+}
+
+CommandLineArguments::~CommandLineArguments()
+{
+}
+
+bool CommandLineArguments::parse(TestPlugin* plugin)
+{
+ bool correctParameters = true;
+ for (int i = 1; i < ac_; i++) {
+ SimpleString argument = av_[i];
+ if (argument == "-v") verbose_ = true;
+ else if (argument == "-p") runTestsAsSeperateProcess_ = true;
+ else if (argument.startsWith("-r")) SetRepeatCount(ac_, av_, i);
+ else if (argument.startsWith("-g")) SetGroupFilter(ac_, av_, i);
+ else if (argument.startsWith("-sg")) SetStrictGroupFilter(ac_, av_, i);
+ else if (argument.startsWith("-n")) SetNameFilter(ac_, av_, i);
+ else if (argument.startsWith("-sn")) SetStrictNameFilter(ac_, av_, i);
+ else if (argument.startsWith("TEST(")) SetTestToRunBasedOnVerboseOutput(ac_, av_, i, "TEST(");
+ else if (argument.startsWith("IGNORE_TEST(")) SetTestToRunBasedOnVerboseOutput(ac_, av_, i, "IGNORE_TEST(");
+ else if (argument.startsWith("-o")) correctParameters = SetOutputType(ac_, av_, i);
+ else if (argument.startsWith("-p")) correctParameters = plugin->parseAllArguments(ac_, av_, i);
+ else if (argument.startsWith("-k")) SetPackageName(ac_, av_, i);
+ else correctParameters = false;
+
+ if (correctParameters == false) {
+ return false;
+ }
+ }
+ return true;
+}
+
+const char* CommandLineArguments::usage() const
+{
+ return "usage [-v] [-r#] [-g|sg groupName] [-n|sn testName] [-o{normal, junit}] [-k packageName]\n";
+}
+
+bool CommandLineArguments::isVerbose() const
+{
+ return verbose_;
+}
+
+bool CommandLineArguments::runTestsInSeperateProcess() const
+{
+ return runTestsAsSeperateProcess_;
+}
+
+
+int CommandLineArguments::getRepeatCount() const
+{
+ return repeat_;
+}
+
+TestFilter CommandLineArguments::getGroupFilter() const
+{
+ return groupFilter_;
+}
+
+TestFilter CommandLineArguments::getNameFilter() const
+{
+ return nameFilter_;
+}
+
+void CommandLineArguments::SetRepeatCount(int ac, const char** av, int& i)
+{
+ repeat_ = 0;
+
+ SimpleString repeatParameter(av[i]);
+ if (repeatParameter.size() > 2) repeat_ = PlatformSpecificAtoI(av[i] + 2);
+ else if (i + 1 < ac) {
+ repeat_ = PlatformSpecificAtoI(av[i + 1]);
+ if (repeat_ != 0) i++;
+ }
+
+ if (0 == repeat_) repeat_ = 2;
+
+}
+
+SimpleString CommandLineArguments::getParameterField(int ac, const char** av, int& i, const SimpleString& parameterName)
+{
+ size_t parameterLength = parameterName.size();
+ SimpleString parameter(av[i]);
+ if (parameter.size() > parameterLength) return av[i] + parameterLength;
+ else if (i + 1 < ac) return av[++i];
+ return "";
+}
+
+void CommandLineArguments::SetGroupFilter(int ac, const char** av, int& i)
+{
+ groupFilter_ = TestFilter(getParameterField(ac, av, i, "-g"));
+}
+
+void CommandLineArguments::SetStrictGroupFilter(int ac, const char** av, int& i)
+{
+ groupFilter_ = TestFilter(getParameterField(ac, av, i, "-sg"));
+ groupFilter_.strictMatching();
+}
+
+void CommandLineArguments::SetNameFilter(int ac, const char** av, int& i)
+{
+ nameFilter_ = getParameterField(ac, av, i, "-n");
+}
+
+void CommandLineArguments::SetStrictNameFilter(int ac, const char** av, int& index)
+{
+ nameFilter_ = getParameterField(ac, av, index, "-sn");
+ nameFilter_.strictMatching();
+}
+
+void CommandLineArguments::SetTestToRunBasedOnVerboseOutput(int ac, const char** av, int& index, const char* parameterName)
+{
+ SimpleString wholename = getParameterField(ac, av, index, parameterName);
+ SimpleString testname = wholename.subStringFromTill(',', ')');
+ testname = testname.subString(2, testname.size());
+ groupFilter_ = wholename.subStringFromTill(wholename.at(0), ',');
+ nameFilter_ = testname;
+ nameFilter_.strictMatching();
+ groupFilter_.strictMatching();
+}
+
+void CommandLineArguments::SetPackageName(int ac, const char** av, int& i)
+{
+ SimpleString packageName = getParameterField(ac, av, i, "-k");
+ if (packageName.size() == 0) return;
+
+ packageName_ = packageName;
+}
+
+bool CommandLineArguments::SetOutputType(int ac, const char** av, int& i)
+{
+ SimpleString outputType = getParameterField(ac, av, i, "-o");
+ if (outputType.size() == 0) return false;
+
+ if (outputType == "normal" || outputType == "eclipse") {
+ outputType_ = OUTPUT_ECLIPSE;
+ return true;
+ }
+ if (outputType == "junit") {
+ outputType_ = OUTPUT_JUNIT;
+ return true;
+ }
+ return false;
+}
+
+bool CommandLineArguments::isEclipseOutput() const
+{
+ return outputType_ == OUTPUT_ECLIPSE;
+}
+
+bool CommandLineArguments::isJUnitOutput() const
+{
+ return outputType_ == OUTPUT_JUNIT;
+}
+
+const SimpleString& CommandLineArguments::getPackageName() const
+{
+ return packageName_;
+}
+
--- a/src/CppUTest/CommandLineTestRunner.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/CommandLineTestRunner.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,143 +1,146 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/CommandLineTestRunner.h"
-#include "CppUTest/TestOutput.h"
-#include "CppUTest/JUnitTestOutput.h"
-#include "CppUTest/TestRegistry.h"
-
-CommandLineTestRunner::CommandLineTestRunner(int ac, const char** av, TestOutput* output, TestRegistry* registry) :
- output_(output), jUnitOutput_(NULL), arguments_(NULL), registry_(registry)
-{
- arguments_ = new CommandLineArguments(ac, av);
-}
-
-CommandLineTestRunner::~CommandLineTestRunner()
-{
- delete arguments_;
- delete jUnitOutput_;
-}
-
-int CommandLineTestRunner::RunAllTests(int ac, char** av)
-{
- return RunAllTests(ac, const_cast<const char**> (av));
-}
-
-int CommandLineTestRunner::RunAllTests(int ac, const char** av)
-{
- int result = 0;
- ConsoleTestOutput output;
-
- MemoryLeakWarningPlugin memLeakWarn(DEF_PLUGIN_MEM_LEAK);
- memLeakWarn.destroyGlobalDetectorAndTurnOffMemoryLeakDetectionInDestructor(true);
- TestRegistry::getCurrentRegistry()->installPlugin(&memLeakWarn);
-
- {
- CommandLineTestRunner runner(ac, av, &output, TestRegistry::getCurrentRegistry());
- result = runner.runAllTestsMain();
- }
-
- if (result == 0) {
- output << memLeakWarn.FinalReport(0);
- }
- TestRegistry::getCurrentRegistry()->removePluginByName(DEF_PLUGIN_MEM_LEAK);
- return result;
-}
-
-int CommandLineTestRunner::runAllTestsMain()
-{
- int testResult = 0;
-
- SetPointerPlugin pPlugin(DEF_PLUGIN_SET_POINTER);
- registry_->installPlugin(&pPlugin);
-
- if (parseArguments(registry_->getFirstPlugin()))
- testResult = runAllTests();
-
- registry_->removePluginByName(DEF_PLUGIN_SET_POINTER);
- return testResult;
-}
-
-void CommandLineTestRunner::initializeTestRun()
-{
- registry_->groupFilter(arguments_->getGroupFilter());
- registry_->nameFilter(arguments_->getNameFilter());
- if (arguments_->isVerbose()) output_->verbose();
- if (arguments_->runTestsInSeperateProcess()) registry_->setRunTestsInSeperateProcess();
-}
-
-int CommandLineTestRunner::runAllTests()
-{
- initializeTestRun();
- int loopCount = 0;
- int failureCount = 0;
- int repeat_ = arguments_->getRepeatCount();
-
- while (loopCount++ < repeat_) {
- output_->printTestRun(loopCount, repeat_);
- TestResult tr(*output_);
- registry_->runAllTests(tr);
- failureCount += tr.getFailureCount();
- }
-
- return failureCount;
-}
-
-bool CommandLineTestRunner::parseArguments(TestPlugin* plugin)
-{
- if (arguments_->parse(plugin)) {
- if (arguments_->isJUnitOutput()) {
- output_ = jUnitOutput_ = new JUnitTestOutput;
- }
- return true;
- }
- else {
- output_->print(arguments_->usage());
- return false;
- }
-}
-
-bool CommandLineTestRunner::isVerbose()
-{
- return arguments_->isVerbose();
-}
-
-int CommandLineTestRunner::getRepeatCount()
-{
- return arguments_->getRepeatCount();
-}
-
-TestFilter CommandLineTestRunner::getGroupFilter()
-{
- return arguments_->getGroupFilter();
-}
-
-TestFilter CommandLineTestRunner::getNameFilter()
-{
- return arguments_->getNameFilter();
-}
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/CommandLineTestRunner.h"
+#include "CppUTest/TestOutput.h"
+#include "CppUTest/JUnitTestOutput.h"
+#include "CppUTest/TestRegistry.h"
+
+CommandLineTestRunner::CommandLineTestRunner(int ac, const char** av, TestOutput* output, TestRegistry* registry) :
+ output_(output), jUnitOutput_(NULL), arguments_(NULL), registry_(registry)
+{
+ arguments_ = new CommandLineArguments(ac, av);
+}
+
+CommandLineTestRunner::~CommandLineTestRunner()
+{
+ delete arguments_;
+ delete jUnitOutput_;
+}
+
+int CommandLineTestRunner::RunAllTests(int ac, char** av)
+{
+ return RunAllTests(ac, const_cast<const char**> (av));
+}
+
+int CommandLineTestRunner::RunAllTests(int ac, const char** av)
+{
+ int result = 0;
+ ConsoleTestOutput output;
+
+ // MemoryLeakWarningPlugin memLeakWarn(DEF_PLUGIN_MEM_LEAK);
+ // memLeakWarn.destroyGlobalDetectorAndTurnOffMemoryLeakDetectionInDestructor(true);
+ // TestRegistry::getCurrentRegistry()->installPlugin(&memLeakWarn);
+
+ {
+ CommandLineTestRunner runner(ac, av, &output, TestRegistry::getCurrentRegistry());
+ result = runner.runAllTestsMain();
+ }
+
+ // if (result == 0) {
+ // output << memLeakWarn.FinalReport(0);
+ // }
+ // TestRegistry::getCurrentRegistry()->removePluginByName(DEF_PLUGIN_MEM_LEAK);
+ return result;
+}
+
+int CommandLineTestRunner::runAllTestsMain()
+{
+ int testResult = 0;
+
+ SetPointerPlugin pPlugin(DEF_PLUGIN_SET_POINTER);
+ registry_->installPlugin(&pPlugin);
+
+ if (parseArguments(registry_->getFirstPlugin()))
+ testResult = runAllTests();
+
+ registry_->removePluginByName(DEF_PLUGIN_SET_POINTER);
+ return testResult;
+}
+
+void CommandLineTestRunner::initializeTestRun()
+{
+ registry_->groupFilter(arguments_->getGroupFilter());
+ registry_->nameFilter(arguments_->getNameFilter());
+ if (arguments_->isVerbose()) output_->verbose();
+ if (arguments_->runTestsInSeperateProcess()) registry_->setRunTestsInSeperateProcess();
+}
+
+int CommandLineTestRunner::runAllTests()
+{
+ initializeTestRun();
+ int loopCount = 0;
+ int failureCount = 0;
+ int repeat_ = arguments_->getRepeatCount();
+
+ while (loopCount++ < repeat_) {
+ output_->printTestRun(loopCount, repeat_);
+ TestResult tr(*output_);
+ registry_->runAllTests(tr);
+ failureCount += tr.getFailureCount();
+ }
+
+ return failureCount;
+}
+
+bool CommandLineTestRunner::parseArguments(TestPlugin* plugin)
+{
+ if (arguments_->parse(plugin)) {
+ if (arguments_->isJUnitOutput()) {
+ output_ = jUnitOutput_ = new JUnitTestOutput;
+ if (jUnitOutput_ != NULL) {
+ jUnitOutput_->setPackageName(arguments_->getPackageName());
+ }
+ }
+ return true;
+ }
+ else {
+ output_->print(arguments_->usage());
+ return false;
+ }
+}
+
+bool CommandLineTestRunner::isVerbose()
+{
+ return arguments_->isVerbose();
+}
+
+int CommandLineTestRunner::getRepeatCount()
+{
+ return arguments_->getRepeatCount();
+}
+
+TestFilter CommandLineTestRunner::getGroupFilter()
+{
+ return arguments_->getGroupFilter();
+}
+
+TestFilter CommandLineTestRunner::getNameFilter()
+{
+ return arguments_->getNameFilter();
+}
--- a/src/CppUTest/JUnitTestOutput.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/JUnitTestOutput.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,270 +1,280 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/JUnitTestOutput.h"
-#include "CppUTest/TestResult.h"
-#include "CppUTest/TestFailure.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-
-struct JUnitTestCaseResultNode
-{
- JUnitTestCaseResultNode() :
- execTime_(0), failure_(0), next_(0)
- {
- }
-
- SimpleString name_;
- long execTime_;
- TestFailure* failure_;
- JUnitTestCaseResultNode* next_;
-};
-
-struct JUnitTestGroupResult
-{
- JUnitTestGroupResult() :
- testCount_(0), failureCount_(0), startTime_(0), groupExecTime_(0), head_(0), tail_(0)
- {
- }
-
- int testCount_;
- int failureCount_;
- long startTime_;
- long groupExecTime_;
- SimpleString group_;
- JUnitTestCaseResultNode* head_;
- JUnitTestCaseResultNode* tail_;
-};
-
-struct JUnitTestOutputImpl
-{
- JUnitTestGroupResult results_;
- PlatformSpecificFile file_;
-};
-
-JUnitTestOutput::JUnitTestOutput() :
- impl_(new JUnitTestOutputImpl)
-{
-}
-
-JUnitTestOutput::~JUnitTestOutput()
-{
- resetTestGroupResult();
- delete impl_;
-}
-
-void JUnitTestOutput::resetTestGroupResult()
-{
- impl_->results_.testCount_ = 0;
- impl_->results_.failureCount_ = 0;
- impl_->results_.group_ = "";
- JUnitTestCaseResultNode* cur = impl_->results_.head_;
- while (cur) {
- JUnitTestCaseResultNode* tmp = cur->next_;
- ;
- if (cur->failure_) delete cur->failure_;
- delete cur;
- cur = tmp;
- }
- impl_->results_.head_ = 0;
- impl_->results_.tail_ = 0;
-}
-
-void JUnitTestOutput::printTestsStarted()
-{
-}
-
-void JUnitTestOutput::printCurrentGroupStarted(const UtestShell& /*test*/)
-{
-}
-
-void JUnitTestOutput::printCurrentTestEnded(const TestResult& result)
-{
- impl_->results_.tail_->execTime_
- = result.getCurrentTestTotalExecutionTime();
-}
-
-void JUnitTestOutput::printTestsEnded(const TestResult& /*result*/)
-{
-}
-
-void JUnitTestOutput::printCurrentGroupEnded(const TestResult& result)
-{
- impl_->results_.groupExecTime_ = result.getCurrentGroupTotalExecutionTime();
- writeTestGroupToFile();
- resetTestGroupResult();
-}
-
-void JUnitTestOutput::printCurrentTestStarted(const UtestShell& test)
-{
- impl_->results_.testCount_++;
- impl_->results_.group_ = test.getGroup();
- impl_->results_.startTime_ = GetPlatformSpecificTimeInMillis();
-
- if (impl_->results_.tail_ == 0) {
- impl_->results_.head_ = impl_->results_.tail_
- = new JUnitTestCaseResultNode;
- }
- else {
- impl_->results_.tail_->next_ = new JUnitTestCaseResultNode;
- impl_->results_.tail_ = impl_->results_.tail_->next_;
- }
- impl_->results_.tail_->name_ = test.getName();
-}
-
-SimpleString JUnitTestOutput::createFileName(const SimpleString& group)
-{
- SimpleString fileName = "cpputest_";
- fileName += group;
- fileName.replace('/', '_');
- fileName += ".xml";
- return fileName;
-}
-
-void JUnitTestOutput::writeXmlHeader()
-{
- writeToFile("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
-}
-
-void JUnitTestOutput::writeTestSuiteSummery()
-{
- SimpleString
- buf =
- StringFromFormat(
- "<testsuite errors=\"0\" failures=\"%d\" hostname=\"localhost\" name=\"%s\" tests=\"%d\" time=\"%d.%03d\" timestamp=\"%s\">\n",
- impl_->results_.failureCount_,
- impl_->results_.group_.asCharString(),
- impl_->results_.testCount_,
- (int) (impl_->results_.groupExecTime_ / 1000), (int) (impl_->results_.groupExecTime_ % 1000),
- GetPlatformSpecificTimeString());
- writeToFile(buf.asCharString());
-}
-
-void JUnitTestOutput::writeProperties()
-{
- writeToFile("<properties>\n");
- writeToFile("</properties>\n");
-}
-
-void JUnitTestOutput::writeTestCases()
-{
- JUnitTestCaseResultNode* cur = impl_->results_.head_;
- while (cur) {
- SimpleString buf = StringFromFormat(
- "<testcase classname=\"%s\" name=\"%s\" time=\"%d.%03d\">\n",
- impl_->results_.group_.asCharString(),
- cur->name_.asCharString(), (int) (cur->execTime_ / 1000), (int)(cur->execTime_ % 1000));
- writeToFile(buf.asCharString());
-
- if (cur->failure_) {
- writeFailure(cur);
- }
- writeToFile("</testcase>\n");
- cur = cur->next_;
- }
-}
-
-void JUnitTestOutput::writeFailure(JUnitTestCaseResultNode* node)
-{
- SimpleString message = node->failure_->getMessage().asCharString();
- message.replace('"', '\'');
- message.replace('<', '[');
- message.replace('>', ']');
- message.replace("&", "&");
- message.replace("\n", "{newline}");
- SimpleString buf = StringFromFormat(
- "<failure message=\"%s:%d: %s\" type=\"AssertionFailedError\">\n",
- node->failure_->getFileName().asCharString(),
- node->failure_->getFailureLineNumber(), message.asCharString());
- writeToFile(buf.asCharString());
- writeToFile("</failure>\n");
-}
-
-void JUnitTestOutput::writeFileEnding()
-{
- writeToFile("<system-out></system-out>\n");
- writeToFile("<system-err></system-err>\n");
- writeToFile("</testsuite>");
-}
-
-void JUnitTestOutput::writeTestGroupToFile()
-{
- openFileForWrite(createFileName(impl_->results_.group_));
- writeXmlHeader();
- writeTestSuiteSummery();
- writeProperties();
- writeTestCases();
- writeFileEnding();
- closeFile();
-}
-
-void JUnitTestOutput::verbose()
-{
-}
-
-void JUnitTestOutput::printBuffer(const char*)
-{
-}
-
-void JUnitTestOutput::print(const char*)
-{
-}
-
-void JUnitTestOutput::print(long)
-{
-}
-
-void JUnitTestOutput::print(const TestFailure& failure)
-{
- if (impl_->results_.tail_->failure_ == 0) {
- impl_->results_.failureCount_++;
- impl_->results_.tail_->failure_ = new TestFailure(failure);
- }
-}
-
-void JUnitTestOutput::printTestRun(int /*number*/, int /*total*/)
-{
-}
-
-void JUnitTestOutput::flush()
-{
-}
-
-void JUnitTestOutput::openFileForWrite(const SimpleString& fileName)
-{
- impl_->file_ = PlatformSpecificFOpen(fileName.asCharString(), "w");
-}
-
-void JUnitTestOutput::writeToFile(const SimpleString& buffer)
-{
- PlatformSpecificFPuts(buffer.asCharString(), impl_->file_);
-}
-
-void JUnitTestOutput::closeFile()
-{
- PlatformSpecificFClose(impl_->file_);
-}
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/JUnitTestOutput.h"
+#include "CppUTest/TestResult.h"
+#include "CppUTest/TestFailure.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+
+struct JUnitTestCaseResultNode
+{
+ JUnitTestCaseResultNode() :
+ execTime_(0), failure_(0), next_(0)
+ {
+ }
+
+ SimpleString name_;
+ long execTime_;
+ TestFailure* failure_;
+ JUnitTestCaseResultNode* next_;
+};
+
+struct JUnitTestGroupResult
+{
+ JUnitTestGroupResult() :
+ testCount_(0), failureCount_(0), startTime_(0), groupExecTime_(0), head_(0), tail_(0)
+ {
+ }
+
+ int testCount_;
+ int failureCount_;
+ long startTime_;
+ long groupExecTime_;
+ SimpleString group_;
+ JUnitTestCaseResultNode* head_;
+ JUnitTestCaseResultNode* tail_;
+};
+
+struct JUnitTestOutputImpl
+{
+ JUnitTestGroupResult results_;
+ PlatformSpecificFile file_;
+ SimpleString package_;
+};
+
+JUnitTestOutput::JUnitTestOutput() :
+ impl_(new JUnitTestOutputImpl)
+{
+}
+
+JUnitTestOutput::~JUnitTestOutput()
+{
+ resetTestGroupResult();
+ delete impl_;
+}
+
+void JUnitTestOutput::resetTestGroupResult()
+{
+ impl_->results_.testCount_ = 0;
+ impl_->results_.failureCount_ = 0;
+ impl_->results_.group_ = "";
+ JUnitTestCaseResultNode* cur = impl_->results_.head_;
+ while (cur) {
+ JUnitTestCaseResultNode* tmp = cur->next_;
+ ;
+ delete cur->failure_;
+ delete cur;
+ cur = tmp;
+ }
+ impl_->results_.head_ = 0;
+ impl_->results_.tail_ = 0;
+}
+
+void JUnitTestOutput::printTestsStarted()
+{
+}
+
+void JUnitTestOutput::printCurrentGroupStarted(const UtestShell& /*test*/)
+{
+}
+
+void JUnitTestOutput::printCurrentTestEnded(const TestResult& result)
+{
+ impl_->results_.tail_->execTime_
+ = result.getCurrentTestTotalExecutionTime();
+}
+
+void JUnitTestOutput::printTestsEnded(const TestResult& /*result*/)
+{
+}
+
+void JUnitTestOutput::printCurrentGroupEnded(const TestResult& result)
+{
+ impl_->results_.groupExecTime_ = result.getCurrentGroupTotalExecutionTime();
+ writeTestGroupToFile();
+ resetTestGroupResult();
+}
+
+void JUnitTestOutput::printCurrentTestStarted(const UtestShell& test)
+{
+ impl_->results_.testCount_++;
+ impl_->results_.group_ = test.getGroup();
+ impl_->results_.startTime_ = GetPlatformSpecificTimeInMillis();
+
+ if (impl_->results_.tail_ == 0) {
+ impl_->results_.head_ = impl_->results_.tail_
+ = new JUnitTestCaseResultNode;
+ }
+ else {
+ impl_->results_.tail_->next_ = new JUnitTestCaseResultNode;
+ impl_->results_.tail_ = impl_->results_.tail_->next_;
+ }
+ impl_->results_.tail_->name_ = test.getName();
+}
+
+SimpleString JUnitTestOutput::createFileName(const SimpleString& group)
+{
+ SimpleString fileName = "cpputest_";
+ fileName += group;
+ fileName.replace('/', '_');
+ fileName += ".xml";
+ return fileName;
+}
+
+void JUnitTestOutput::setPackageName(const SimpleString& package)
+{
+ if (impl_ != NULL) {
+ impl_->package_ = package;
+ }
+}
+
+void JUnitTestOutput::writeXmlHeader()
+{
+ writeToFile("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
+}
+
+void JUnitTestOutput::writeTestSuiteSummery()
+{
+ SimpleString
+ buf =
+ StringFromFormat(
+ "<testsuite errors=\"0\" failures=\"%d\" hostname=\"localhost\" name=\"%s\" tests=\"%d\" time=\"%d.%03d\" timestamp=\"%s\">\n",
+ impl_->results_.failureCount_,
+ impl_->results_.group_.asCharString(),
+ impl_->results_.testCount_,
+ (int) (impl_->results_.groupExecTime_ / 1000), (int) (impl_->results_.groupExecTime_ % 1000),
+ GetPlatformSpecificTimeString());
+ writeToFile(buf.asCharString());
+}
+
+void JUnitTestOutput::writeProperties()
+{
+ writeToFile("<properties>\n");
+ writeToFile("</properties>\n");
+}
+
+void JUnitTestOutput::writeTestCases()
+{
+ JUnitTestCaseResultNode* cur = impl_->results_.head_;
+ while (cur) {
+ SimpleString buf = StringFromFormat(
+ "<testcase classname=\"%s%s%s\" name=\"%s\" time=\"%d.%03d\">\n",
+ impl_->package_.asCharString(),
+ impl_->package_.isEmpty() == true ? "" : ".",
+ impl_->results_.group_.asCharString(),
+ cur->name_.asCharString(), (int) (cur->execTime_ / 1000), (int)(cur->execTime_ % 1000));
+ writeToFile(buf.asCharString());
+
+ if (cur->failure_) {
+ writeFailure(cur);
+ }
+ writeToFile("</testcase>\n");
+ cur = cur->next_;
+ }
+}
+
+void JUnitTestOutput::writeFailure(JUnitTestCaseResultNode* node)
+{
+ SimpleString message = node->failure_->getMessage().asCharString();
+ message.replace('"', '\'');
+ message.replace('<', '[');
+ message.replace('>', ']');
+ message.replace("&", "&");
+ message.replace("\n", "{newline}");
+ SimpleString buf = StringFromFormat(
+ "<failure message=\"%s:%d: %s\" type=\"AssertionFailedError\">\n",
+ node->failure_->getFileName().asCharString(),
+ node->failure_->getFailureLineNumber(), message.asCharString());
+ writeToFile(buf.asCharString());
+ writeToFile("</failure>\n");
+}
+
+void JUnitTestOutput::writeFileEnding()
+{
+ writeToFile("<system-out></system-out>\n");
+ writeToFile("<system-err></system-err>\n");
+ writeToFile("</testsuite>");
+}
+
+void JUnitTestOutput::writeTestGroupToFile()
+{
+ openFileForWrite(createFileName(impl_->results_.group_));
+ writeXmlHeader();
+ writeTestSuiteSummery();
+ writeProperties();
+ writeTestCases();
+ writeFileEnding();
+ closeFile();
+}
+
+void JUnitTestOutput::verbose()
+{
+}
+
+void JUnitTestOutput::printBuffer(const char*)
+{
+}
+
+void JUnitTestOutput::print(const char*)
+{
+}
+
+void JUnitTestOutput::print(long)
+{
+}
+
+void JUnitTestOutput::print(const TestFailure& failure)
+{
+ if (impl_->results_.tail_->failure_ == 0) {
+ impl_->results_.failureCount_++;
+ impl_->results_.tail_->failure_ = new TestFailure(failure);
+ }
+}
+
+void JUnitTestOutput::printTestRun(int /*number*/, int /*total*/)
+{
+}
+
+void JUnitTestOutput::flush()
+{
+}
+
+void JUnitTestOutput::openFileForWrite(const SimpleString& fileName)
+{
+ impl_->file_ = PlatformSpecificFOpen(fileName.asCharString(), "w");
+}
+
+void JUnitTestOutput::writeToFile(const SimpleString& buffer)
+{
+ PlatformSpecificFPuts(buffer.asCharString(), impl_->file_);
+}
+
+void JUnitTestOutput::closeFile()
+{
+ PlatformSpecificFClose(impl_->file_);
+}
--- a/src/CppUTest/MemoryLeakDetector.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/MemoryLeakDetector.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,621 +1,621 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/MemoryLeakDetector.h"
-#include "CppUTest/TestMemoryAllocator.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-
-#define UNKNOWN ((char*)("<unknown>"))
-
-SimpleStringBuffer::SimpleStringBuffer() :
- positions_filled_(0), write_limit_(SIMPLE_STRING_BUFFER_LEN-1)
-{
-}
-
-void SimpleStringBuffer::clear()
-{
- positions_filled_ = 0;
- buffer_[0] = '\0';
-}
-
-void SimpleStringBuffer::add(const char* format, ...)
-{
- int count = 0;
- size_t positions_left = write_limit_ - positions_filled_;
- if (positions_left <= 0) return;
-
- va_list arguments;
- va_start(arguments, format);
- count = PlatformSpecificVSNprintf(buffer_ + positions_filled_, positions_left+1, format, arguments);
- if (count > 0) positions_filled_ += (size_t) count;
- if (positions_filled_ > write_limit_) positions_filled_ = write_limit_;
- va_end(arguments);
-}
-
-char* SimpleStringBuffer::toString()
-{
- return buffer_;
-}
-
-void SimpleStringBuffer::setWriteLimit(size_t write_limit)
-{
- write_limit_ = write_limit;
- if (write_limit_ > SIMPLE_STRING_BUFFER_LEN-1)
- write_limit_ = SIMPLE_STRING_BUFFER_LEN-1;
-}
-void SimpleStringBuffer::resetWriteLimit()
-{
- write_limit_ = SIMPLE_STRING_BUFFER_LEN-1;
-}
-
-bool SimpleStringBuffer::reachedItsCapacity()
-{
- return positions_filled_ >= write_limit_;
-}
-
-////////////////////////
-
-#define MEM_LEAK_TOO_MUCH "\netc etc etc etc. !!!! Too much memory leaks to report. Bailing out\n"
-#define MEM_LEAK_FOOTER "Total number of leaks: "
-#define MEM_LEAK_ADDITION_MALLOC_WARNING "NOTE:\n" \
- "\tMemory leak reports about malloc and free can be caused by allocating using the cpputest version of malloc,\n" \
- "\tbut deallocate using the standard free.\n" \
- "\tIf this is the case, check whether your malloc/free replacements are working (#define malloc cpputest_malloc etc).\n"
-
-MemoryLeakOutputStringBuffer::MemoryLeakOutputStringBuffer()
- : total_leaks_(0), giveWarningOnUsingMalloc_(false)
-{
-}
-
-void MemoryLeakOutputStringBuffer::addAllocationLocation(const char* allocationFile, int allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator)
-{
- outputBuffer_.add(" allocated at file: %s line: %d size: %lu type: %s\n", allocationFile, allocationLineNumber, (unsigned long) allocationSize, allocator->alloc_name());
-}
-
-void MemoryLeakOutputStringBuffer::addDeallocationLocation(const char* freeFile, int freeLineNumber, TestMemoryAllocator* allocator)
-{
- outputBuffer_.add(" deallocated at file: %s line: %d type: %s\n", freeFile, freeLineNumber, allocator->free_name());
-}
-
-void MemoryLeakOutputStringBuffer::addNoMemoryLeaksMessage()
-{
- outputBuffer_.add("No memory leaks were detected.");
-}
-
-void MemoryLeakOutputStringBuffer::startMemoryLeakReporting()
-{
- giveWarningOnUsingMalloc_ = false;
- total_leaks_ = 0;
-
- size_t memory_leak_normal_footer_size = sizeof(MEM_LEAK_FOOTER) + 10 + sizeof(MEM_LEAK_TOO_MUCH); /* the number of leaks */
- size_t memory_leak_foot_size_with_malloc_warning = memory_leak_normal_footer_size + sizeof(MEM_LEAK_ADDITION_MALLOC_WARNING);
-
- outputBuffer_.setWriteLimit(SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN - memory_leak_foot_size_with_malloc_warning);
-}
-
-void MemoryLeakOutputStringBuffer::reportMemoryLeak(MemoryLeakDetectorNode* leak)
-{
- if (total_leaks_ == 0) {
- addMemoryLeakHeader();
- }
-
- total_leaks_++;
- outputBuffer_.add("Alloc num (%u) Leak size: %lu Allocated at: %s and line: %d. Type: \"%s\"\n\t Memory: <%p> Content: \"%.15s\"\n",
- leak->number_, (unsigned long) leak->size_, leak->file_, leak->line_, leak->allocator_->alloc_name(), leak->memory_, leak->memory_);
-
- if (PlatformSpecificStrCmp(leak->allocator_->alloc_name(), "malloc") == 0)
- giveWarningOnUsingMalloc_ = true;
-}
-
-void MemoryLeakOutputStringBuffer::stopMemoryLeakReporting()
-{
- if (total_leaks_ == 0) {
- addNoMemoryLeaksMessage();
- return;
- }
-
- bool buffer_reached_its_capacity = outputBuffer_.reachedItsCapacity();
- outputBuffer_.resetWriteLimit();
-
- if (buffer_reached_its_capacity)
- addErrorMessageForTooMuchLeaks();
-
- addMemoryLeakFooter(total_leaks_);
-
- if (giveWarningOnUsingMalloc_)
- addWarningForUsingMalloc();
-
-}
-
-void MemoryLeakOutputStringBuffer::addMemoryLeakHeader()
-{
- outputBuffer_.add("Memory leak(s) found.\n");
-}
-
-void MemoryLeakOutputStringBuffer::addErrorMessageForTooMuchLeaks()
-{
- outputBuffer_.add(MEM_LEAK_TOO_MUCH);
-}
-
-void MemoryLeakOutputStringBuffer::addMemoryLeakFooter(int amountOfLeaks)
-{
- outputBuffer_.add("%s %d\n", MEM_LEAK_FOOTER, amountOfLeaks);
-}
-
-void MemoryLeakOutputStringBuffer::addWarningForUsingMalloc()
-{
- outputBuffer_.add(MEM_LEAK_ADDITION_MALLOC_WARNING);
-}
-
-void MemoryLeakOutputStringBuffer::reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
-{
- reportFailure("Deallocating non-allocated memory\n", "<unknown>", 0, 0, NullUnknownAllocator::defaultAllocator(), freeFile, freeLine, freeAllocator, reporter);
-}
-
-void MemoryLeakOutputStringBuffer::reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
-{
- reportFailure("Allocation/deallocation type mismatch\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter);
-}
-
-void MemoryLeakOutputStringBuffer::reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
-{
- reportFailure("Memory corruption (written out of bounds?)\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter);
-}
-
-void MemoryLeakOutputStringBuffer::reportFailure(const char* message, const char* allocFile, int allocLine, size_t allocSize, TestMemoryAllocator* allocAllocator, const char* freeFile, int freeLine,
- TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
-{
- outputBuffer_.add("%s", message);
- addAllocationLocation(allocFile, allocLine, allocSize, allocAllocator);
- addDeallocationLocation(freeFile, freeLine, freeAllocator);
- reporter->fail(toString());
-}
-
-
-char* MemoryLeakOutputStringBuffer::toString()
-{
- return outputBuffer_.toString();
-}
-
-void MemoryLeakOutputStringBuffer::clear()
-{
- outputBuffer_.clear();
-}
-
-////////////////////////
-
-void MemoryLeakDetectorNode::init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, const char* file, int line)
-{
- number_ = number;
- memory_ = memory;
- size_ = size;
- allocator_ = allocator;
- period_ = period;
- file_ = file;
- line_ = line;
-}
-
-///////////////////////
-
-bool MemoryLeakDetectorList::isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period)
-{
- return period == mem_leak_period_all || node->period_ == period || (node->period_ != mem_leak_period_disabled && period == mem_leak_period_enabled);
-}
-
-void MemoryLeakDetectorList::clearAllAccounting(MemLeakPeriod period)
-{
- MemoryLeakDetectorNode* cur = head_;
- MemoryLeakDetectorNode* prev = 0;
-
- while (cur) {
- if (isInPeriod(cur, period)) {
- if (prev) {
- prev->next_ = cur->next_;
- cur = prev;
- }
- else {
- head_ = cur->next_;
- cur = head_;
- continue;
- }
- }
- prev = cur;
- cur = cur->next_;
- }
-}
-
-void MemoryLeakDetectorList::addNewNode(MemoryLeakDetectorNode* node)
-{
- node->next_ = head_;
- head_ = node;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorList::removeNode(char* memory)
-{
- MemoryLeakDetectorNode* cur = head_;
- MemoryLeakDetectorNode* prev = 0;
- while (cur) {
- if (cur->memory_ == memory) {
- if (prev) {
- prev->next_ = cur->next_;
- return cur;
- }
- else {
- head_ = cur->next_;
- return cur;
- }
- }
- prev = cur;
- cur = cur->next_;
- }
- return 0;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorList::retrieveNode(char* memory)
-{
- MemoryLeakDetectorNode* cur = head_;
- while (cur) {
- if (cur->memory_ == memory)
- return cur;
- cur = cur->next_;
- }
- return NULL;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorList::getLeakFrom(MemoryLeakDetectorNode* node, MemLeakPeriod period)
-{
- for (MemoryLeakDetectorNode* cur = node; cur; cur = cur->next_)
- if (isInPeriod(cur, period)) return cur;
- return 0;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeak(MemLeakPeriod period)
-{
- return getLeakFrom(head_, period);
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorList::getNextLeak(MemoryLeakDetectorNode* node, MemLeakPeriod period)
-{
- return getLeakFrom(node->next_, period);
-}
-
-int MemoryLeakDetectorList::getTotalLeaks(MemLeakPeriod period)
-{
- int total_leaks = 0;
- for (MemoryLeakDetectorNode* node = head_; node; node = node->next_) {
- if (isInPeriod(node, period)) total_leaks++;
- }
- return total_leaks;
-}
-
-bool MemoryLeakDetectorList::hasLeaks(MemLeakPeriod period)
-{
- for (MemoryLeakDetectorNode* node = head_; node; node = node->next_)
- if (isInPeriod(node, period)) return true;
- return false;
-}
-
-/////////////////////////////////////////////////////////////
-
-unsigned long MemoryLeakDetectorTable::hash(char* memory)
-{
- return (unsigned long)((size_t)memory % hash_prime);
-}
-
-void MemoryLeakDetectorTable::clearAllAccounting(MemLeakPeriod period)
-{
- for (int i = 0; i < hash_prime; i++)
- table_[i].clearAllAccounting(period);
-}
-
-void MemoryLeakDetectorTable::addNewNode(MemoryLeakDetectorNode* node)
-{
- table_[hash(node->memory_)].addNewNode(node);
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorTable::removeNode(char* memory)
-{
- return table_[hash(memory)].removeNode(memory);
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorTable::retrieveNode(char* memory)
-{
- return table_[hash(memory)].retrieveNode(memory);
-}
-
-bool MemoryLeakDetectorTable::hasLeaks(MemLeakPeriod period)
-{
- for (int i = 0; i < hash_prime; i++)
- if (table_[i].hasLeaks(period)) return true;
- return false;
-}
-
-int MemoryLeakDetectorTable::getTotalLeaks(MemLeakPeriod period)
-{
- int total_leaks = 0;
- for (int i = 0; i < hash_prime; i++)
- total_leaks += table_[i].getTotalLeaks(period);
- return total_leaks;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorTable::getFirstLeak(MemLeakPeriod period)
-{
- for (int i = 0; i < hash_prime; i++) {
- MemoryLeakDetectorNode* node = table_[i].getFirstLeak(period);
- if (node) return node;
- }
- return 0;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeak(MemoryLeakDetectorNode* leak, MemLeakPeriod period)
-{
- unsigned long i = hash(leak->memory_);
- MemoryLeakDetectorNode* node = table_[i].getNextLeak(leak, period);
- if (node) return node;
-
- for (++i; i < hash_prime; i++) {
- node = table_[i].getFirstLeak(period);
- if (node) return node;
- }
- return 0;
-}
-
-/////////////////////////////////////////////////////////////
-
-MemoryLeakDetector::MemoryLeakDetector(MemoryLeakFailure* reporter)
-{
- doAllocationTypeChecking_ = true;
- allocationSequenceNumber_ = 1;
- current_period_ = mem_leak_period_disabled;
- reporter_ = reporter;
- outputBuffer_ = MemoryLeakOutputStringBuffer();
- memoryTable_ = MemoryLeakDetectorTable();
-}
-
-void MemoryLeakDetector::clearAllAccounting(MemLeakPeriod period)
-{
- memoryTable_.clearAllAccounting(period);
-}
-
-void MemoryLeakDetector::startChecking()
-{
- outputBuffer_.clear();
- current_period_ = mem_leak_period_checking;
-}
-
-void MemoryLeakDetector::stopChecking()
-{
- current_period_ = mem_leak_period_enabled;
-}
-
-void MemoryLeakDetector::enable()
-{
- current_period_ = mem_leak_period_enabled;
-}
-
-void MemoryLeakDetector::disable()
-{
- current_period_ = mem_leak_period_disabled;
-}
-
-void MemoryLeakDetector::disableAllocationTypeChecking()
-{
- doAllocationTypeChecking_ = false;
-}
-
-void MemoryLeakDetector::enableAllocationTypeChecking()
-{
- doAllocationTypeChecking_ = true;
-}
-
-unsigned MemoryLeakDetector::getCurrentAllocationNumber()
-{
- return allocationSequenceNumber_;
-}
-
-static size_t calculateVoidPointerAlignedSize(size_t size)
-{
- return (sizeof(void*) - (size % sizeof(void*))) + size;
-}
-
-size_t MemoryLeakDetector::sizeOfMemoryWithCorruptionInfo(size_t size)
-{
- return calculateVoidPointerAlignedSize(size + memory_corruption_buffer_size);
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetector::getNodeFromMemoryPointer(char* memory, size_t memory_size)
-{
- return (MemoryLeakDetectorNode*) (void*) (memory + sizeOfMemoryWithCorruptionInfo(memory_size));
-}
-
-void MemoryLeakDetector::storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, int line)
-{
- node->init(new_memory, allocationSequenceNumber_++, size, allocator, current_period_, file, line);
- addMemoryCorruptionInformation(node->memory_ + node->size_);
- memoryTable_.addNewNode(node);
-}
-
-char* MemoryLeakDetector::reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately)
-{
- char* new_memory = reallocateMemoryWithAccountingInformation(allocator, memory, size, file, line, allocatNodesSeperately);
- if (new_memory == NULL) return NULL;
-
- MemoryLeakDetectorNode *node = createMemoryLeakAccountingInformation(allocator, size, new_memory, allocatNodesSeperately);
- storeLeakInformation(node, new_memory, size, allocator, file, line);
- return node->memory_;
-}
-
-void MemoryLeakDetector::invalidateMemory(char* memory)
-{
- MemoryLeakDetectorNode* node = memoryTable_.retrieveNode(memory);
- if (node)
- PlatformSpecificMemset(memory, 0xCD, node->size_);
-}
-
-void MemoryLeakDetector::addMemoryCorruptionInformation(char* memory)
-{
- memory[0] = 'B';
- memory[1] = 'A';
- memory[2] = 'S';
-}
-
-bool MemoryLeakDetector::validMemoryCorruptionInformation(char* memory)
-{
- return memory[0] == 'B' && memory[1] == 'A' && memory[2] == 'S';
-}
-
-bool MemoryLeakDetector::matchingAllocation(TestMemoryAllocator *alloc_allocator, TestMemoryAllocator *free_allocator)
-{
- if (alloc_allocator == free_allocator) return true;
- if (!doAllocationTypeChecking_) return true;
- return free_allocator->isOfEqualType(alloc_allocator);
-}
-
-void MemoryLeakDetector::checkForCorruption(MemoryLeakDetectorNode* node, const char* file, int line, TestMemoryAllocator* allocator, bool allocateNodesSeperately)
-{
- if (!matchingAllocation(node->allocator_, allocator))
- outputBuffer_.reportAllocationDeallocationMismatchFailure(node, file, line, allocator, reporter_);
- else if (!validMemoryCorruptionInformation(node->memory_ + node->size_))
- outputBuffer_.reportMemoryCorruptionFailure(node, file, line, allocator, reporter_);
- else if (allocateNodesSeperately)
- allocator->freeMemoryLeakNode((char*) node);
-}
-
-char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, bool allocatNodesSeperately)
-{
- return allocMemory(allocator, size, UNKNOWN, 0, allocatNodesSeperately);
-}
-
-char* MemoryLeakDetector::allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately)
-{
- if (allocatNodesSeperately) return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size), file, line);
- else return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode), file, line);
-}
-
-char* MemoryLeakDetector::reallocateMemoryWithAccountingInformation(TestMemoryAllocator* /*allocator*/, char* memory, size_t size, const char* /*file*/, int /*line*/, bool allocatNodesSeperately)
-{
- if (allocatNodesSeperately) return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size));
- else return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode));
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetector::createMemoryLeakAccountingInformation(TestMemoryAllocator* allocator, size_t size, char* memory, bool allocatNodesSeperately)
-{
- if (allocatNodesSeperately) return (MemoryLeakDetectorNode*) (void*) allocator->allocMemoryLeakNode(sizeof(MemoryLeakDetectorNode));
- else return getNodeFromMemoryPointer(memory, size);
-}
-
-char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately)
-{
- /* With malloc, it is harder to guarantee that the allocator free is called.
- * This is because operator new is overloaded via linker symbols, but malloc just via #defines.
- * If the same allocation is used and the wrong free is called, it will deallocate the memory leak information
- * without the memory leak detector ever noticing it!
- * So, for malloc, we'll allocate the memory separately so we can detect this and give a proper error.
- */
-
- char* memory = allocateMemoryWithAccountingInformation(allocator, size, file, line, allocatNodesSeperately);
- if (memory == NULL) return NULL;
- MemoryLeakDetectorNode* node = createMemoryLeakAccountingInformation(allocator, size, memory, allocatNodesSeperately);
-
- storeLeakInformation(node, memory, size, allocator, file, line);
- return node->memory_;
-}
-
-void MemoryLeakDetector::removeMemoryLeakInformationWithoutCheckingOrDeallocatingTheMemoryButDeallocatingTheAccountInformation(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately)
-{
- MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory);
- if (allocatNodesSeperately) allocator->freeMemoryLeakNode( (char*) node);
-}
-
-void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, int line, bool allocatNodesSeperately)
-{
- if (memory == 0) return;
-
- MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory);
- if (node == NULL) {
- outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_);
- return;
- }
- if (!allocator->hasBeenDestroyed()) {
- checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
- allocator->free_memory((char*) memory, file, line);
- }
-}
-
-void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately)
-{
- deallocMemory(allocator, (char*) memory, UNKNOWN, 0, allocatNodesSeperately);
-}
-
-char* MemoryLeakDetector::reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately)
-{
- if (memory) {
- MemoryLeakDetectorNode* node = memoryTable_.removeNode(memory);
- if (node == NULL) {
- outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_);
- return NULL;
- }
- checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
- }
- return reallocateMemoryAndLeakInformation(allocator, memory, size, file, line, allocatNodesSeperately);
-}
-
-void MemoryLeakDetector::ConstructMemoryLeakReport(MemLeakPeriod period)
-{
- MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(period);
-
- outputBuffer_.startMemoryLeakReporting();
-
- while (leak) {
- outputBuffer_.reportMemoryLeak(leak);
- leak = memoryTable_.getNextLeak(leak, period);
- }
-
- outputBuffer_.stopMemoryLeakReporting();
-}
-
-const char* MemoryLeakDetector::report(MemLeakPeriod period)
-{
- outputBuffer_.clear();
- ConstructMemoryLeakReport(period);
-
- return outputBuffer_.toString();
-}
-
-void MemoryLeakDetector::markCheckingPeriodLeaksAsNonCheckingPeriod()
-{
- MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(mem_leak_period_checking);
- while (leak) {
- if (leak->period_ == mem_leak_period_checking) leak->period_ = mem_leak_period_enabled;
- leak = memoryTable_.getNextLeak(leak, mem_leak_period_checking);
- }
-}
-
-int MemoryLeakDetector::totalMemoryLeaks(MemLeakPeriod period)
-{
- return memoryTable_.getTotalLeaks(period);
-}
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/MemoryLeakDetector.h"
+#include "CppUTest/TestMemoryAllocator.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+
+#define UNKNOWN ((char*)("<unknown>"))
+
+SimpleStringBuffer::SimpleStringBuffer() :
+ positions_filled_(0), write_limit_(SIMPLE_STRING_BUFFER_LEN-1)
+{
+}
+
+void SimpleStringBuffer::clear()
+{
+ positions_filled_ = 0;
+ buffer_[0] = '\0';
+}
+
+void SimpleStringBuffer::add(const char* format, ...)
+{
+ int count = 0;
+ size_t positions_left = write_limit_ - positions_filled_;
+ if (positions_left <= 0) return;
+
+ va_list arguments;
+ va_start(arguments, format);
+ count = PlatformSpecificVSNprintf(buffer_ + positions_filled_, positions_left+1, format, arguments);
+ if (count > 0) positions_filled_ += (size_t) count;
+ if (positions_filled_ > write_limit_) positions_filled_ = write_limit_;
+ va_end(arguments);
+}
+
+char* SimpleStringBuffer::toString()
+{
+ return buffer_;
+}
+
+void SimpleStringBuffer::setWriteLimit(size_t write_limit)
+{
+ write_limit_ = write_limit;
+ if (write_limit_ > SIMPLE_STRING_BUFFER_LEN-1)
+ write_limit_ = SIMPLE_STRING_BUFFER_LEN-1;
+}
+void SimpleStringBuffer::resetWriteLimit()
+{
+ write_limit_ = SIMPLE_STRING_BUFFER_LEN-1;
+}
+
+bool SimpleStringBuffer::reachedItsCapacity()
+{
+ return positions_filled_ >= write_limit_;
+}
+
+////////////////////////
+
+#define MEM_LEAK_TOO_MUCH "\netc etc etc etc. !!!! Too much memory leaks to report. Bailing out\n"
+#define MEM_LEAK_FOOTER "Total number of leaks: "
+#define MEM_LEAK_ADDITION_MALLOC_WARNING "NOTE:\n" \
+ "\tMemory leak reports about malloc and free can be caused by allocating using the cpputest version of malloc,\n" \
+ "\tbut deallocate using the standard free.\n" \
+ "\tIf this is the case, check whether your malloc/free replacements are working (#define malloc cpputest_malloc etc).\n"
+
+MemoryLeakOutputStringBuffer::MemoryLeakOutputStringBuffer()
+ : total_leaks_(0), giveWarningOnUsingMalloc_(false)
+{
+}
+
+void MemoryLeakOutputStringBuffer::addAllocationLocation(const char* allocationFile, int allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator)
+{
+ outputBuffer_.add(" allocated at file: %s line: %d size: %lu type: %s\n", allocationFile, allocationLineNumber, (unsigned long) allocationSize, allocator->alloc_name());
+}
+
+void MemoryLeakOutputStringBuffer::addDeallocationLocation(const char* freeFile, int freeLineNumber, TestMemoryAllocator* allocator)
+{
+ outputBuffer_.add(" deallocated at file: %s line: %d type: %s\n", freeFile, freeLineNumber, allocator->free_name());
+}
+
+void MemoryLeakOutputStringBuffer::addNoMemoryLeaksMessage()
+{
+ outputBuffer_.add("No memory leaks were detected.");
+}
+
+void MemoryLeakOutputStringBuffer::startMemoryLeakReporting()
+{
+ giveWarningOnUsingMalloc_ = false;
+ total_leaks_ = 0;
+
+ size_t memory_leak_normal_footer_size = sizeof(MEM_LEAK_FOOTER) + 10 + sizeof(MEM_LEAK_TOO_MUCH); /* the number of leaks */
+ size_t memory_leak_foot_size_with_malloc_warning = memory_leak_normal_footer_size + sizeof(MEM_LEAK_ADDITION_MALLOC_WARNING);
+
+ outputBuffer_.setWriteLimit(SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN - memory_leak_foot_size_with_malloc_warning);
+}
+
+void MemoryLeakOutputStringBuffer::reportMemoryLeak(MemoryLeakDetectorNode* leak)
+{
+ if (total_leaks_ == 0) {
+ addMemoryLeakHeader();
+ }
+
+ total_leaks_++;
+ outputBuffer_.add("Alloc num (%u) Leak size: %lu Allocated at: %s and line: %d. Type: \"%s\"\n\t Memory: <%p> Content: \"%.15s\"\n",
+ leak->number_, (unsigned long) leak->size_, leak->file_, leak->line_, leak->allocator_->alloc_name(), leak->memory_, leak->memory_);
+
+ if (PlatformSpecificStrCmp(leak->allocator_->alloc_name(), "malloc") == 0)
+ giveWarningOnUsingMalloc_ = true;
+}
+
+void MemoryLeakOutputStringBuffer::stopMemoryLeakReporting()
+{
+ if (total_leaks_ == 0) {
+ addNoMemoryLeaksMessage();
+ return;
+ }
+
+ bool buffer_reached_its_capacity = outputBuffer_.reachedItsCapacity();
+ outputBuffer_.resetWriteLimit();
+
+ if (buffer_reached_its_capacity)
+ addErrorMessageForTooMuchLeaks();
+
+ addMemoryLeakFooter(total_leaks_);
+
+ if (giveWarningOnUsingMalloc_)
+ addWarningForUsingMalloc();
+
+}
+
+void MemoryLeakOutputStringBuffer::addMemoryLeakHeader()
+{
+ outputBuffer_.add("Memory leak(s) found.\n");
+}
+
+void MemoryLeakOutputStringBuffer::addErrorMessageForTooMuchLeaks()
+{
+ outputBuffer_.add(MEM_LEAK_TOO_MUCH);
+}
+
+void MemoryLeakOutputStringBuffer::addMemoryLeakFooter(int amountOfLeaks)
+{
+ outputBuffer_.add("%s %d\n", MEM_LEAK_FOOTER, amountOfLeaks);
+}
+
+void MemoryLeakOutputStringBuffer::addWarningForUsingMalloc()
+{
+ outputBuffer_.add(MEM_LEAK_ADDITION_MALLOC_WARNING);
+}
+
+void MemoryLeakOutputStringBuffer::reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+{
+ reportFailure("Deallocating non-allocated memory\n", "<unknown>", 0, 0, NullUnknownAllocator::defaultAllocator(), freeFile, freeLine, freeAllocator, reporter);
+}
+
+void MemoryLeakOutputStringBuffer::reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+{
+ reportFailure("Allocation/deallocation type mismatch\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter);
+}
+
+void MemoryLeakOutputStringBuffer::reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+{
+ reportFailure("Memory corruption (written out of bounds?)\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter);
+}
+
+void MemoryLeakOutputStringBuffer::reportFailure(const char* message, const char* allocFile, int allocLine, size_t allocSize, TestMemoryAllocator* allocAllocator, const char* freeFile, int freeLine,
+ TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+{
+ outputBuffer_.add("%s", message);
+ addAllocationLocation(allocFile, allocLine, allocSize, allocAllocator);
+ addDeallocationLocation(freeFile, freeLine, freeAllocator);
+ reporter->fail(toString());
+}
+
+
+char* MemoryLeakOutputStringBuffer::toString()
+{
+ return outputBuffer_.toString();
+}
+
+void MemoryLeakOutputStringBuffer::clear()
+{
+ outputBuffer_.clear();
+}
+
+////////////////////////
+
+void MemoryLeakDetectorNode::init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, const char* file, int line)
+{
+ number_ = number;
+ memory_ = memory;
+ size_ = size;
+ allocator_ = allocator;
+ period_ = period;
+ file_ = file;
+ line_ = line;
+}
+
+///////////////////////
+
+bool MemoryLeakDetectorList::isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period)
+{
+ return period == mem_leak_period_all || node->period_ == period || (node->period_ != mem_leak_period_disabled && period == mem_leak_period_enabled);
+}
+
+void MemoryLeakDetectorList::clearAllAccounting(MemLeakPeriod period)
+{
+ MemoryLeakDetectorNode* cur = head_;
+ MemoryLeakDetectorNode* prev = 0;
+
+ while (cur) {
+ if (isInPeriod(cur, period)) {
+ if (prev) {
+ prev->next_ = cur->next_;
+ cur = prev;
+ }
+ else {
+ head_ = cur->next_;
+ cur = head_;
+ continue;
+ }
+ }
+ prev = cur;
+ cur = cur->next_;
+ }
+}
+
+void MemoryLeakDetectorList::addNewNode(MemoryLeakDetectorNode* node)
+{
+ node->next_ = head_;
+ head_ = node;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::removeNode(char* memory)
+{
+ MemoryLeakDetectorNode* cur = head_;
+ MemoryLeakDetectorNode* prev = 0;
+ while (cur) {
+ if (cur->memory_ == memory) {
+ if (prev) {
+ prev->next_ = cur->next_;
+ return cur;
+ }
+ else {
+ head_ = cur->next_;
+ return cur;
+ }
+ }
+ prev = cur;
+ cur = cur->next_;
+ }
+ return 0;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::retrieveNode(char* memory)
+{
+ MemoryLeakDetectorNode* cur = head_;
+ while (cur) {
+ if (cur->memory_ == memory)
+ return cur;
+ cur = cur->next_;
+ }
+ return NULL;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::getLeakFrom(MemoryLeakDetectorNode* node, MemLeakPeriod period)
+{
+ for (MemoryLeakDetectorNode* cur = node; cur; cur = cur->next_)
+ if (isInPeriod(cur, period)) return cur;
+ return 0;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeak(MemLeakPeriod period)
+{
+ return getLeakFrom(head_, period);
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::getNextLeak(MemoryLeakDetectorNode* node, MemLeakPeriod period)
+{
+ return getLeakFrom(node->next_, period);
+}
+
+int MemoryLeakDetectorList::getTotalLeaks(MemLeakPeriod period)
+{
+ int total_leaks = 0;
+ for (MemoryLeakDetectorNode* node = head_; node; node = node->next_) {
+ if (isInPeriod(node, period)) total_leaks++;
+ }
+ return total_leaks;
+}
+
+bool MemoryLeakDetectorList::hasLeaks(MemLeakPeriod period)
+{
+ for (MemoryLeakDetectorNode* node = head_; node; node = node->next_)
+ if (isInPeriod(node, period)) return true;
+ return false;
+}
+
+/////////////////////////////////////////////////////////////
+
+unsigned long MemoryLeakDetectorTable::hash(char* memory)
+{
+ return (unsigned long)((size_t)memory % hash_prime);
+}
+
+void MemoryLeakDetectorTable::clearAllAccounting(MemLeakPeriod period)
+{
+ for (int i = 0; i < hash_prime; i++)
+ table_[i].clearAllAccounting(period);
+}
+
+void MemoryLeakDetectorTable::addNewNode(MemoryLeakDetectorNode* node)
+{
+ table_[hash(node->memory_)].addNewNode(node);
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorTable::removeNode(char* memory)
+{
+ return table_[hash(memory)].removeNode(memory);
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorTable::retrieveNode(char* memory)
+{
+ return table_[hash(memory)].retrieveNode(memory);
+}
+
+bool MemoryLeakDetectorTable::hasLeaks(MemLeakPeriod period)
+{
+ for (int i = 0; i < hash_prime; i++)
+ if (table_[i].hasLeaks(period)) return true;
+ return false;
+}
+
+int MemoryLeakDetectorTable::getTotalLeaks(MemLeakPeriod period)
+{
+ int total_leaks = 0;
+ for (int i = 0; i < hash_prime; i++)
+ total_leaks += table_[i].getTotalLeaks(period);
+ return total_leaks;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorTable::getFirstLeak(MemLeakPeriod period)
+{
+ for (int i = 0; i < hash_prime; i++) {
+ MemoryLeakDetectorNode* node = table_[i].getFirstLeak(period);
+ if (node) return node;
+ }
+ return 0;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeak(MemoryLeakDetectorNode* leak, MemLeakPeriod period)
+{
+ unsigned long i = hash(leak->memory_);
+ MemoryLeakDetectorNode* node = table_[i].getNextLeak(leak, period);
+ if (node) return node;
+
+ for (++i; i < hash_prime; i++) {
+ node = table_[i].getFirstLeak(period);
+ if (node) return node;
+ }
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////
+
+MemoryLeakDetector::MemoryLeakDetector(MemoryLeakFailure* reporter)
+{
+ doAllocationTypeChecking_ = true;
+ allocationSequenceNumber_ = 1;
+ current_period_ = mem_leak_period_disabled;
+ reporter_ = reporter;
+ outputBuffer_ = MemoryLeakOutputStringBuffer();
+ memoryTable_ = MemoryLeakDetectorTable();
+}
+
+void MemoryLeakDetector::clearAllAccounting(MemLeakPeriod period)
+{
+ memoryTable_.clearAllAccounting(period);
+}
+
+void MemoryLeakDetector::startChecking()
+{
+ outputBuffer_.clear();
+ current_period_ = mem_leak_period_checking;
+}
+
+void MemoryLeakDetector::stopChecking()
+{
+ current_period_ = mem_leak_period_enabled;
+}
+
+void MemoryLeakDetector::enable()
+{
+ current_period_ = mem_leak_period_enabled;
+}
+
+void MemoryLeakDetector::disable()
+{
+ current_period_ = mem_leak_period_disabled;
+}
+
+void MemoryLeakDetector::disableAllocationTypeChecking()
+{
+ doAllocationTypeChecking_ = false;
+}
+
+void MemoryLeakDetector::enableAllocationTypeChecking()
+{
+ doAllocationTypeChecking_ = true;
+}
+
+unsigned MemoryLeakDetector::getCurrentAllocationNumber()
+{
+ return allocationSequenceNumber_;
+}
+
+static size_t calculateVoidPointerAlignedSize(size_t size)
+{
+ return (sizeof(void*) - (size % sizeof(void*))) + size;
+}
+
+size_t MemoryLeakDetector::sizeOfMemoryWithCorruptionInfo(size_t size)
+{
+ return calculateVoidPointerAlignedSize(size + memory_corruption_buffer_size);
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetector::getNodeFromMemoryPointer(char* memory, size_t memory_size)
+{
+ return (MemoryLeakDetectorNode*) (void*) (memory + sizeOfMemoryWithCorruptionInfo(memory_size));
+}
+
+void MemoryLeakDetector::storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, int line)
+{
+ node->init(new_memory, allocationSequenceNumber_++, size, allocator, current_period_, file, line);
+ addMemoryCorruptionInformation(node->memory_ + node->size_);
+ memoryTable_.addNewNode(node);
+}
+
+char* MemoryLeakDetector::reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately)
+{
+ char* new_memory = reallocateMemoryWithAccountingInformation(allocator, memory, size, file, line, allocatNodesSeperately);
+ if (new_memory == NULL) return NULL;
+
+ MemoryLeakDetectorNode *node = createMemoryLeakAccountingInformation(allocator, size, new_memory, allocatNodesSeperately);
+ storeLeakInformation(node, new_memory, size, allocator, file, line);
+ return node->memory_;
+}
+
+void MemoryLeakDetector::invalidateMemory(char* memory)
+{
+ MemoryLeakDetectorNode* node = memoryTable_.retrieveNode(memory);
+ if (node)
+ PlatformSpecificMemset(memory, 0xCD, node->size_);
+}
+
+void MemoryLeakDetector::addMemoryCorruptionInformation(char* memory)
+{
+ memory[0] = 'B';
+ memory[1] = 'A';
+ memory[2] = 'S';
+}
+
+bool MemoryLeakDetector::validMemoryCorruptionInformation(char* memory)
+{
+ return memory[0] == 'B' && memory[1] == 'A' && memory[2] == 'S';
+}
+
+bool MemoryLeakDetector::matchingAllocation(TestMemoryAllocator *alloc_allocator, TestMemoryAllocator *free_allocator)
+{
+ if (alloc_allocator == free_allocator) return true;
+ if (!doAllocationTypeChecking_) return true;
+ return free_allocator->isOfEqualType(alloc_allocator);
+}
+
+void MemoryLeakDetector::checkForCorruption(MemoryLeakDetectorNode* node, const char* file, int line, TestMemoryAllocator* allocator, bool allocateNodesSeperately)
+{
+ if (!matchingAllocation(node->allocator_, allocator))
+ outputBuffer_.reportAllocationDeallocationMismatchFailure(node, file, line, allocator, reporter_);
+ else if (!validMemoryCorruptionInformation(node->memory_ + node->size_))
+ outputBuffer_.reportMemoryCorruptionFailure(node, file, line, allocator, reporter_);
+ else if (allocateNodesSeperately)
+ allocator->freeMemoryLeakNode((char*) node);
+}
+
+char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, bool allocatNodesSeperately)
+{
+ return allocMemory(allocator, size, UNKNOWN, 0, allocatNodesSeperately);
+}
+
+char* MemoryLeakDetector::allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately)
+{
+ if (allocatNodesSeperately) return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size), file, line);
+ else return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode), file, line);
+}
+
+char* MemoryLeakDetector::reallocateMemoryWithAccountingInformation(TestMemoryAllocator* /*allocator*/, char* memory, size_t size, const char* /*file*/, int /*line*/, bool allocatNodesSeperately)
+{
+ if (allocatNodesSeperately) return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size));
+ else return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode));
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetector::createMemoryLeakAccountingInformation(TestMemoryAllocator* allocator, size_t size, char* memory, bool allocatNodesSeperately)
+{
+ if (allocatNodesSeperately) return (MemoryLeakDetectorNode*) (void*) allocator->allocMemoryLeakNode(sizeof(MemoryLeakDetectorNode));
+ else return getNodeFromMemoryPointer(memory, size);
+}
+
+char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately)
+{
+ /* With malloc, it is harder to guarantee that the allocator free is called.
+ * This is because operator new is overloaded via linker symbols, but malloc just via #defines.
+ * If the same allocation is used and the wrong free is called, it will deallocate the memory leak information
+ * without the memory leak detector ever noticing it!
+ * So, for malloc, we'll allocate the memory separately so we can detect this and give a proper error.
+ */
+
+ char* memory = allocateMemoryWithAccountingInformation(allocator, size, file, line, allocatNodesSeperately);
+ if (memory == NULL) return NULL;
+ MemoryLeakDetectorNode* node = createMemoryLeakAccountingInformation(allocator, size, memory, allocatNodesSeperately);
+
+ storeLeakInformation(node, memory, size, allocator, file, line);
+ return node->memory_;
+}
+
+void MemoryLeakDetector::removeMemoryLeakInformationWithoutCheckingOrDeallocatingTheMemoryButDeallocatingTheAccountInformation(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately)
+{
+ MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory);
+ if (allocatNodesSeperately) allocator->freeMemoryLeakNode( (char*) node);
+}
+
+void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, int line, bool allocatNodesSeperately)
+{
+ if (memory == 0) return;
+
+ MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory);
+ if (node == NULL) {
+ outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_);
+ return;
+ }
+ if (!allocator->hasBeenDestroyed()) {
+ checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
+ allocator->free_memory((char*) memory, file, line);
+ }
+}
+
+void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately)
+{
+ deallocMemory(allocator, (char*) memory, UNKNOWN, 0, allocatNodesSeperately);
+}
+
+char* MemoryLeakDetector::reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately)
+{
+ if (memory) {
+ MemoryLeakDetectorNode* node = memoryTable_.removeNode(memory);
+ if (node == NULL) {
+ outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_);
+ return NULL;
+ }
+ checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
+ }
+ return reallocateMemoryAndLeakInformation(allocator, memory, size, file, line, allocatNodesSeperately);
+}
+
+void MemoryLeakDetector::ConstructMemoryLeakReport(MemLeakPeriod period)
+{
+ MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(period);
+
+ outputBuffer_.startMemoryLeakReporting();
+
+ while (leak) {
+ outputBuffer_.reportMemoryLeak(leak);
+ leak = memoryTable_.getNextLeak(leak, period);
+ }
+
+ outputBuffer_.stopMemoryLeakReporting();
+}
+
+const char* MemoryLeakDetector::report(MemLeakPeriod period)
+{
+ outputBuffer_.clear();
+ ConstructMemoryLeakReport(period);
+
+ return outputBuffer_.toString();
+}
+
+void MemoryLeakDetector::markCheckingPeriodLeaksAsNonCheckingPeriod()
+{
+ MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(mem_leak_period_checking);
+ while (leak) {
+ if (leak->period_ == mem_leak_period_checking) leak->period_ = mem_leak_period_enabled;
+ leak = memoryTable_.getNextLeak(leak, mem_leak_period_checking);
+ }
+}
+
+int MemoryLeakDetector::totalMemoryLeaks(MemLeakPeriod period)
+{
+ return memoryTable_.getTotalLeaks(period);
+}
--- a/src/CppUTest/MemoryLeakWarningPlugin.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/MemoryLeakWarningPlugin.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,454 +1,464 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/MemoryLeakWarningPlugin.h"
-#include "CppUTest/MemoryLeakDetector.h"
-#include "CppUTest/TestMemoryAllocator.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-
-/********** Enabling and disabling for C also *********/
-
-#if CPPUTEST_USE_MEM_LEAK_DETECTION
-
-static void* mem_leak_malloc(size_t size, const char* file, int line)
-{
- return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentMallocAllocator(), size, file, line, true);
-}
-
-static void mem_leak_free(void* buffer, const char* file, int line)
-{
- MemoryLeakWarningPlugin::getGlobalDetector()->invalidateMemory((char*) buffer);
- MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(getCurrentMallocAllocator(), (char*) buffer, file, line, true);
-}
-
-static void* mem_leak_realloc(void* memory, size_t size, const char* file, int line)
-{
- return MemoryLeakWarningPlugin::getGlobalDetector()->reallocMemory(getCurrentMallocAllocator(), (char*) memory, size, file, line, true);
-}
-
-#endif
-
-static void* normal_malloc(size_t size, const char*, int)
-{
- return PlatformSpecificMalloc(size);
-}
-
-static void* normal_realloc(void* memory, size_t size, const char*, int)
-{
- return PlatformSpecificRealloc(memory, size);
-}
-
-static void normal_free(void* buffer, const char*, int)
-{
- PlatformSpecificFree(buffer);
-}
-
-#if CPPUTEST_USE_MEM_LEAK_DETECTION
-static void *(*malloc_fptr)(size_t size, const char* file, int line) = mem_leak_malloc;
-static void (*free_fptr)(void* mem, const char* file, int line) = mem_leak_free;
-static void*(*realloc_fptr)(void* memory, size_t size, const char* file, int line) = mem_leak_realloc;
-#else
-static void *(*malloc_fptr)(size_t size, const char* file, int line) = normal_malloc;
-static void (*free_fptr)(void* mem, const char* file, int line) = normal_free;
-static void*(*realloc_fptr)(void* memory, size_t size, const char* file, int line) = normal_realloc;
-#endif
-
-void* cpputest_malloc_location_with_leak_detection(size_t size, const char* file, int line)
-{
- return malloc_fptr(size, file, line);
-}
-
-void* cpputest_realloc_location_with_leak_detection(void* memory, size_t size, const char* file, int line)
-{
- return realloc_fptr(memory, size, file, line);
-}
-
-void cpputest_free_location_with_leak_detection(void* buffer, const char* file, int line)
-{
- free_fptr(buffer, file, line);
-}
-
-/********** C++ *************/
-
-#if CPPUTEST_USE_MEM_LEAK_DETECTION
-#undef new
-
-#if CPPUTEST_USE_STD_CPP_LIB
-#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory) if (memory == NULL) throw std::bad_alloc();
-#else
-#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory)
-#endif
-
-static void* mem_leak_operator_new (size_t size) UT_THROW(std::bad_alloc)
-{
- void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
- UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
- return memory;
-}
-
-static void* mem_leak_operator_new_nothrow (size_t size) UT_NOTHROW
-{
- return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
-}
-
-static void* mem_leak_operator_new_debug (size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
-{
- void *memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size, (char*) file, line);
- UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
- return memory;
-}
-
-static void* mem_leak_operator_new_array (size_t size) UT_THROW(std::bad_alloc)
-{
- void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
- UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
- return memory;
-}
-
-static void* mem_leak_operator_new_array_nothrow (size_t size) UT_NOTHROW
-{
- return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
-}
-
-static void* mem_leak_operator_new_array_debug (size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
-{
- void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size, (char*) file, line);
- UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
- return memory;
-}
-
-static void mem_leak_operator_delete (void* mem) UT_NOTHROW
-{
- MemoryLeakWarningPlugin::getGlobalDetector()->invalidateMemory((char*) mem);
- MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(getCurrentNewAllocator(), (char*) mem);
-}
-
-static void mem_leak_operator_delete_array (void* mem) UT_NOTHROW
-{
- MemoryLeakWarningPlugin::getGlobalDetector()->invalidateMemory((char*) mem);
- MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(getCurrentNewArrayAllocator(), (char*) mem);
-}
-
-static void* normal_operator_new (size_t size) UT_THROW(std::bad_alloc)
-{
- void* memory = PlatformSpecificMalloc(size);
- UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
- return memory;
-}
-
-static void* normal_operator_new_nothrow (size_t size) UT_NOTHROW
-{
- return PlatformSpecificMalloc(size);
-}
-
-static void* normal_operator_new_debug (size_t size, const char* /*file*/, int /*line*/) UT_THROW(std::bad_alloc)
-{
- void* memory = PlatformSpecificMalloc(size);
- UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
- return memory;
-}
-
-static void* normal_operator_new_array (size_t size) UT_THROW(std::bad_alloc)
-{
- void* memory = PlatformSpecificMalloc(size);
- UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
- return memory;
-}
-
-static void* normal_operator_new_array_nothrow (size_t size) UT_NOTHROW
-{
- return PlatformSpecificMalloc(size);
-}
-
-static void* normal_operator_new_array_debug (size_t size, const char* /*file*/, int /*line*/) UT_THROW(std::bad_alloc)
-{
- void* memory = PlatformSpecificMalloc(size);
- UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
- return memory;
-}
-
-static void normal_operator_delete (void* mem) UT_NOTHROW
-{
- PlatformSpecificFree(mem);
-}
-
-static void normal_operator_delete_array (void* mem) UT_NOTHROW
-{
- PlatformSpecificFree(mem);
-}
-
-static void *(*operator_new_fptr)(size_t size) UT_THROW(std::bad_alloc) = mem_leak_operator_new;
-static void *(*operator_new_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_nothrow;
-static void *(*operator_new_debug_fptr)(size_t size, const char* file, int line) UT_THROW(std::bad_alloc) = mem_leak_operator_new_debug;
-static void *(*operator_new_array_fptr)(size_t size) UT_THROW(std::bad_alloc) = mem_leak_operator_new_array;
-static void *(*operator_new_array_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_array_nothrow;
-static void *(*operator_new_array_debug_fptr)(size_t size, const char* file, int line) UT_THROW(std::bad_alloc) = mem_leak_operator_new_array_debug;
-static void (*operator_delete_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete;
-static void (*operator_delete_array_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete_array;
-
-void* operator new(size_t size) UT_THROW(std::bad_alloc)
-{
- return operator_new_fptr(size);
-}
-
-void* operator new(size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
-{
- return operator_new_debug_fptr(size, file, line);
-}
-
-void operator delete(void* mem) UT_NOTHROW
-{
- operator_delete_fptr(mem);
-}
-
-void operator delete(void* mem, const char*, int) UT_NOTHROW
-{
- operator_delete_fptr(mem);
-}
-
-void* operator new[](size_t size) UT_THROW(std::bad_alloc)
-{
- return operator_new_array_fptr(size);
-}
-
-void* operator new [](size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
-{
- return operator_new_array_debug_fptr(size, file, line);
-}
-
-void operator delete[](void* mem) UT_NOTHROW
-{
- operator_delete_array_fptr(mem);
-}
-
-void operator delete[](void* mem, const char*, int) UT_NOTHROW
-{
- operator_delete_array_fptr(mem);
-}
-
-
-#if CPPUTEST_USE_STD_CPP_LIB
-
-void* operator new(size_t size, const std::nothrow_t&) UT_NOTHROW
-{
- return operator_new_nothrow_fptr(size);
-}
-
-void* operator new[](size_t size, const std::nothrow_t&) UT_NOTHROW
-{
- return operator_new_array_nothrow_fptr(size);
-}
-
-#else
-
-/* Have a similar method. This avoid unused operator_new_nothrow_fptr warning */
-
-extern void* operator_new_nothrow(size_t size) UT_NOTHROW;
-extern void* operator_new_array_nothrow(size_t size) UT_NOTHROW;
-
-void* operator_new_nothrow(size_t size) UT_NOTHROW
-{
- return operator_new_nothrow_fptr(size);
-}
-
-void* operator_new_array_nothrow(size_t size) UT_NOTHROW
-{
- return operator_new_array_nothrow_fptr(size);
-}
-
-#endif
-#endif
-
-void MemoryLeakWarningPlugin::turnOffNewDeleteOverloads()
-{
-#if CPPUTEST_USE_MEM_LEAK_DETECTION
- operator_new_fptr = normal_operator_new;
- operator_new_nothrow_fptr = normal_operator_new_nothrow;
- operator_new_debug_fptr = normal_operator_new_debug;
- operator_new_array_fptr = normal_operator_new_array;
- operator_new_array_nothrow_fptr = normal_operator_new_array_nothrow;
- operator_new_array_debug_fptr = normal_operator_new_array_debug;
- operator_delete_fptr = normal_operator_delete;
- operator_delete_array_fptr = normal_operator_delete_array;
- malloc_fptr = normal_malloc;
- realloc_fptr = normal_realloc;
- free_fptr = normal_free;
-
-#endif
-}
-
-void MemoryLeakWarningPlugin::turnOnNewDeleteOverloads()
-{
-#if CPPUTEST_USE_MEM_LEAK_DETECTION
- operator_new_fptr = mem_leak_operator_new;
- operator_new_nothrow_fptr = mem_leak_operator_new_nothrow;
- operator_new_debug_fptr = mem_leak_operator_new_debug;
- operator_new_array_fptr = mem_leak_operator_new_array;
- operator_new_array_nothrow_fptr = mem_leak_operator_new_array_nothrow;
- operator_new_array_debug_fptr = mem_leak_operator_new_array_debug;
- operator_delete_fptr = mem_leak_operator_delete;
- operator_delete_array_fptr = mem_leak_operator_delete_array;
- malloc_fptr = mem_leak_malloc;
- realloc_fptr = mem_leak_realloc;
- free_fptr = mem_leak_free;
-#endif
-}
-
-void crash_on_allocation_number(unsigned alloc_number)
-{
- static CrashOnAllocationAllocator crashAllocator;
- crashAllocator.setNumberToCrashOn(alloc_number);
- setCurrentMallocAllocator(&crashAllocator);
- setCurrentNewAllocator(&crashAllocator);
- setCurrentNewArrayAllocator(&crashAllocator);
-}
-
-class MemoryLeakWarningReporter: public MemoryLeakFailure
-{
-public:
- virtual ~MemoryLeakWarningReporter()
- {
- }
-
- virtual void fail(char* fail_string)
- {
- UtestShell* currentTest = UtestShell::getCurrent();
- currentTest->failWith(FailFailure(currentTest, currentTest->getName().asCharString(), currentTest->getLineNumber(), fail_string), TestTerminatorWithoutExceptions());
- }
-};
-
-static MemoryLeakFailure* globalReporter = 0;
-static MemoryLeakDetector* globalDetector = 0;
-
-MemoryLeakDetector* MemoryLeakWarningPlugin::getGlobalDetector()
-{
- if (globalDetector == 0) {
- turnOffNewDeleteOverloads();
-
- globalReporter = new MemoryLeakWarningReporter;
- globalDetector = new MemoryLeakDetector(globalReporter);
-
- turnOnNewDeleteOverloads();
- }
- return globalDetector;
-}
-
-MemoryLeakFailure* MemoryLeakWarningPlugin::getGlobalFailureReporter()
-{
- return globalReporter;
-}
-
-void MemoryLeakWarningPlugin::destroyGlobalDetectorAndTurnOffMemoryLeakDetectionInDestructor(bool des)
-{
- destroyGlobalDetectorAndTurnOfMemoryLeakDetectionInDestructor_ = des;
-}
-
-void MemoryLeakWarningPlugin::setGlobalDetector(MemoryLeakDetector* detector, MemoryLeakFailure* reporter)
-{
- globalDetector = detector;
- globalReporter = reporter;
-}
-
-void MemoryLeakWarningPlugin::destroyGlobalDetector()
-{
- turnOffNewDeleteOverloads();
- delete globalDetector;
- delete globalReporter;
- globalDetector = NULL;
-}
-
-
-MemoryLeakWarningPlugin* MemoryLeakWarningPlugin::firstPlugin_ = 0;
-
-MemoryLeakWarningPlugin* MemoryLeakWarningPlugin::getFirstPlugin()
-{
- return firstPlugin_;
-}
-
-MemoryLeakDetector* MemoryLeakWarningPlugin::getMemoryLeakDetector()
-{
- return memLeakDetector_;
-}
-
-void MemoryLeakWarningPlugin::ignoreAllLeaksInTest()
-{
- ignoreAllWarnings_ = true;
-}
-
-void MemoryLeakWarningPlugin::expectLeaksInTest(int n)
-{
- expectedLeaks_ = n;
-}
-
-MemoryLeakWarningPlugin::MemoryLeakWarningPlugin(const SimpleString& name, MemoryLeakDetector* localDetector) :
- TestPlugin(name), ignoreAllWarnings_(false), destroyGlobalDetectorAndTurnOfMemoryLeakDetectionInDestructor_(false), expectedLeaks_(0)
-{
- if (firstPlugin_ == 0) firstPlugin_ = this;
-
- if (localDetector) memLeakDetector_ = localDetector;
- else memLeakDetector_ = getGlobalDetector();
-
- memLeakDetector_->enable();
-}
-
-MemoryLeakWarningPlugin::~MemoryLeakWarningPlugin()
-{
- if (destroyGlobalDetectorAndTurnOfMemoryLeakDetectionInDestructor_) {
- MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
- MemoryLeakWarningPlugin::destroyGlobalDetector();
- }
-}
-
-void MemoryLeakWarningPlugin::preTestAction(UtestShell& /*test*/, TestResult& result)
-{
- memLeakDetector_->startChecking();
- failureCount_ = result.getFailureCount();
-}
-
-void MemoryLeakWarningPlugin::postTestAction(UtestShell& test, TestResult& result)
-{
- memLeakDetector_->stopChecking();
- int leaks = memLeakDetector_->totalMemoryLeaks(mem_leak_period_checking);
-
- if (!ignoreAllWarnings_ && expectedLeaks_ != leaks && failureCount_ == result.getFailureCount()) {
- TestFailure f(&test, memLeakDetector_->report(mem_leak_period_checking));
- result.addFailure(f);
- }
- memLeakDetector_->markCheckingPeriodLeaksAsNonCheckingPeriod();
- ignoreAllWarnings_ = false;
- expectedLeaks_ = 0;
-}
-
-const char* MemoryLeakWarningPlugin::FinalReport(int toBeDeletedLeaks)
-{
- int leaks = memLeakDetector_->totalMemoryLeaks(mem_leak_period_enabled);
- if (leaks != toBeDeletedLeaks) return memLeakDetector_->report(mem_leak_period_enabled);
- return "";
-}
-
-
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/MemoryLeakWarningPlugin.h"
+#include "CppUTest/MemoryLeakDetector.h"
+#include "CppUTest/TestMemoryAllocator.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+
+/********** Enabling and disabling for C also *********/
+
+#if CPPUTEST_USE_MEM_LEAK_DETECTION
+
+static void* mem_leak_malloc(size_t size, const char* file, int line)
+{
+ return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentMallocAllocator(), size, file, line, true);
+}
+
+static void mem_leak_free(void* buffer, const char* file, int line)
+{
+ MemoryLeakWarningPlugin::getGlobalDetector()->invalidateMemory((char*) buffer);
+ MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(getCurrentMallocAllocator(), (char*) buffer, file, line, true);
+}
+
+static void* mem_leak_realloc(void* memory, size_t size, const char* file, int line)
+{
+ return MemoryLeakWarningPlugin::getGlobalDetector()->reallocMemory(getCurrentMallocAllocator(), (char*) memory, size, file, line, true);
+}
+
+#endif
+
+static void* normal_malloc(size_t size, const char*, int)
+{
+ return PlatformSpecificMalloc(size);
+}
+
+static void* normal_realloc(void* memory, size_t size, const char*, int)
+{
+ return PlatformSpecificRealloc(memory, size);
+}
+
+static void normal_free(void* buffer, const char*, int)
+{
+ PlatformSpecificFree(buffer);
+}
+
+#if CPPUTEST_USE_MEM_LEAK_DETECTION
+static void *(*malloc_fptr)(size_t size, const char* file, int line) = mem_leak_malloc;
+static void (*free_fptr)(void* mem, const char* file, int line) = mem_leak_free;
+static void*(*realloc_fptr)(void* memory, size_t size, const char* file, int line) = mem_leak_realloc;
+#else
+static void *(*malloc_fptr)(size_t size, const char* file, int line) = normal_malloc;
+static void (*free_fptr)(void* mem, const char* file, int line) = normal_free;
+static void*(*realloc_fptr)(void* memory, size_t size, const char* file, int line) = normal_realloc;
+#endif
+
+void* cpputest_malloc_location_with_leak_detection(size_t size, const char* file, int line)
+{
+ return malloc_fptr(size, file, line);
+}
+
+void* cpputest_realloc_location_with_leak_detection(void* memory, size_t size, const char* file, int line)
+{
+ return realloc_fptr(memory, size, file, line);
+}
+
+void cpputest_free_location_with_leak_detection(void* buffer, const char* file, int line)
+{
+ free_fptr(buffer, file, line);
+}
+
+/********** C++ *************/
+
+#if CPPUTEST_USE_MEM_LEAK_DETECTION
+#undef new
+
+#if CPPUTEST_USE_STD_CPP_LIB
+#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory) if (memory == NULL) throw std::bad_alloc();
+#else
+#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory)
+#endif
+
+static void* mem_leak_operator_new (size_t size) UT_THROW(std::bad_alloc)
+{
+ void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
+ UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
+ return memory;
+}
+
+static void* mem_leak_operator_new_nothrow (size_t size) UT_NOTHROW
+{
+ return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
+}
+
+static void* mem_leak_operator_new_debug (size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
+{
+ void *memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size, (char*) file, line);
+ UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
+ return memory;
+}
+
+static void* mem_leak_operator_new_array (size_t size) UT_THROW(std::bad_alloc)
+{
+ void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
+ UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
+ return memory;
+}
+
+static void* mem_leak_operator_new_array_nothrow (size_t size) UT_NOTHROW
+{
+ return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
+}
+
+static void* mem_leak_operator_new_array_debug (size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
+{
+ void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size, (char*) file, line);
+ UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
+ return memory;
+}
+
+static void mem_leak_operator_delete (void* mem) UT_NOTHROW
+{
+ MemoryLeakWarningPlugin::getGlobalDetector()->invalidateMemory((char*) mem);
+ MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(getCurrentNewAllocator(), (char*) mem);
+}
+
+static void mem_leak_operator_delete_array (void* mem) UT_NOTHROW
+{
+ MemoryLeakWarningPlugin::getGlobalDetector()->invalidateMemory((char*) mem);
+ MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(getCurrentNewArrayAllocator(), (char*) mem);
+}
+
+static void* normal_operator_new (size_t size) UT_THROW(std::bad_alloc)
+{
+ void* memory = PlatformSpecificMalloc(size);
+ UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
+ return memory;
+}
+
+static void* normal_operator_new_nothrow (size_t size) UT_NOTHROW
+{
+ return PlatformSpecificMalloc(size);
+}
+
+static void* normal_operator_new_debug (size_t size, const char* /*file*/, int /*line*/) UT_THROW(std::bad_alloc)
+{
+ void* memory = PlatformSpecificMalloc(size);
+ UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
+ return memory;
+}
+
+static void* normal_operator_new_array (size_t size) UT_THROW(std::bad_alloc)
+{
+ void* memory = PlatformSpecificMalloc(size);
+ UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
+ return memory;
+}
+
+static void* normal_operator_new_array_nothrow (size_t size) UT_NOTHROW
+{
+ return PlatformSpecificMalloc(size);
+}
+
+static void* normal_operator_new_array_debug (size_t size, const char* /*file*/, int /*line*/) UT_THROW(std::bad_alloc)
+{
+ void* memory = PlatformSpecificMalloc(size);
+ UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
+ return memory;
+}
+
+static void normal_operator_delete (void* mem) UT_NOTHROW
+{
+ PlatformSpecificFree(mem);
+}
+
+static void normal_operator_delete_array (void* mem) UT_NOTHROW
+{
+ PlatformSpecificFree(mem);
+}
+
+static void *(*operator_new_fptr)(size_t size) UT_THROW(std::bad_alloc) = mem_leak_operator_new;
+static void *(*operator_new_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_nothrow;
+static void *(*operator_new_debug_fptr)(size_t size, const char* file, int line) UT_THROW(std::bad_alloc) = mem_leak_operator_new_debug;
+static void *(*operator_new_array_fptr)(size_t size) UT_THROW(std::bad_alloc) = mem_leak_operator_new_array;
+static void *(*operator_new_array_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_array_nothrow;
+static void *(*operator_new_array_debug_fptr)(size_t size, const char* file, int line) UT_THROW(std::bad_alloc) = mem_leak_operator_new_array_debug;
+static void (*operator_delete_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete;
+static void (*operator_delete_array_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete_array;
+
+void* operator new(size_t size) UT_THROW(std::bad_alloc)
+{
+ return operator_new_fptr(size);
+}
+
+void* operator new(size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
+{
+ return operator_new_debug_fptr(size, file, line);
+}
+
+void operator delete(void* mem) UT_NOTHROW
+{
+ operator_delete_fptr(mem);
+}
+
+void operator delete(void* mem, const char*, int) UT_NOTHROW
+{
+ operator_delete_fptr(mem);
+}
+
+void* operator new[](size_t size) UT_THROW(std::bad_alloc)
+{
+ return operator_new_array_fptr(size);
+}
+
+void* operator new [](size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
+{
+ return operator_new_array_debug_fptr(size, file, line);
+}
+
+void operator delete[](void* mem) UT_NOTHROW
+{
+ operator_delete_array_fptr(mem);
+}
+
+void operator delete[](void* mem, const char*, int) UT_NOTHROW
+{
+ operator_delete_array_fptr(mem);
+}
+
+
+#if CPPUTEST_USE_STD_CPP_LIB
+
+void* operator new(size_t size, const std::nothrow_t&) UT_NOTHROW
+{
+ return operator_new_nothrow_fptr(size);
+}
+
+void* operator new[](size_t size, const std::nothrow_t&) UT_NOTHROW
+{
+ return operator_new_array_nothrow_fptr(size);
+}
+
+#else
+
+/* Have a similar method. This avoid unused operator_new_nothrow_fptr warning */
+
+extern void* operator_new_nothrow(size_t size) UT_NOTHROW;
+extern void* operator_new_array_nothrow(size_t size) UT_NOTHROW;
+
+void* operator_new_nothrow(size_t size) UT_NOTHROW
+{
+ return operator_new_nothrow_fptr(size);
+}
+
+void* operator_new_array_nothrow(size_t size) UT_NOTHROW
+{
+ return operator_new_array_nothrow_fptr(size);
+}
+
+#endif
+#endif
+
+void MemoryLeakWarningPlugin::turnOffNewDeleteOverloads()
+{
+#if CPPUTEST_USE_MEM_LEAK_DETECTION
+ operator_new_fptr = normal_operator_new;
+ operator_new_nothrow_fptr = normal_operator_new_nothrow;
+ operator_new_debug_fptr = normal_operator_new_debug;
+ operator_new_array_fptr = normal_operator_new_array;
+ operator_new_array_nothrow_fptr = normal_operator_new_array_nothrow;
+ operator_new_array_debug_fptr = normal_operator_new_array_debug;
+ operator_delete_fptr = normal_operator_delete;
+ operator_delete_array_fptr = normal_operator_delete_array;
+ malloc_fptr = normal_malloc;
+ realloc_fptr = normal_realloc;
+ free_fptr = normal_free;
+
+#endif
+}
+
+void MemoryLeakWarningPlugin::turnOnNewDeleteOverloads()
+{
+#if CPPUTEST_USE_MEM_LEAK_DETECTION
+ operator_new_fptr = mem_leak_operator_new;
+ operator_new_nothrow_fptr = mem_leak_operator_new_nothrow;
+ operator_new_debug_fptr = mem_leak_operator_new_debug;
+ operator_new_array_fptr = mem_leak_operator_new_array;
+ operator_new_array_nothrow_fptr = mem_leak_operator_new_array_nothrow;
+ operator_new_array_debug_fptr = mem_leak_operator_new_array_debug;
+ operator_delete_fptr = mem_leak_operator_delete;
+ operator_delete_array_fptr = mem_leak_operator_delete_array;
+ malloc_fptr = mem_leak_malloc;
+ realloc_fptr = mem_leak_realloc;
+ free_fptr = mem_leak_free;
+#endif
+}
+
+bool MemoryLeakWarningPlugin::areNewDeleteOverloaded()
+{
+#if CPPUTEST_USE_MEM_LEAK_DETECTION
+ return operator_new_fptr == mem_leak_operator_new;
+#else
+ return false;
+#endif
+}
+
+void crash_on_allocation_number(unsigned alloc_number)
+{
+ static CrashOnAllocationAllocator crashAllocator;
+ crashAllocator.setNumberToCrashOn(alloc_number);
+ setCurrentMallocAllocator(&crashAllocator);
+ setCurrentNewAllocator(&crashAllocator);
+ setCurrentNewArrayAllocator(&crashAllocator);
+}
+
+class MemoryLeakWarningReporter: public MemoryLeakFailure
+{
+public:
+ virtual ~MemoryLeakWarningReporter()
+ {
+ }
+
+ virtual void fail(char* fail_string)
+ {
+ UtestShell* currentTest = UtestShell::getCurrent();
+ currentTest->failWith(FailFailure(currentTest, currentTest->getName().asCharString(), currentTest->getLineNumber(), fail_string), TestTerminatorWithoutExceptions());
+ }
+};
+
+static MemoryLeakFailure* globalReporter = 0;
+static MemoryLeakDetector* globalDetector = 0;
+
+MemoryLeakDetector* MemoryLeakWarningPlugin::getGlobalDetector()
+{
+ if (globalDetector == 0) {
+ bool newDeleteOverloaded = areNewDeleteOverloaded();
+ turnOffNewDeleteOverloads();
+
+ globalReporter = new MemoryLeakWarningReporter;
+ globalDetector = new MemoryLeakDetector(globalReporter);
+
+ if (newDeleteOverloaded) turnOnNewDeleteOverloads();
+ }
+ return globalDetector;
+}
+
+MemoryLeakFailure* MemoryLeakWarningPlugin::getGlobalFailureReporter()
+{
+ return globalReporter;
+}
+
+void MemoryLeakWarningPlugin::destroyGlobalDetectorAndTurnOffMemoryLeakDetectionInDestructor(bool des)
+{
+ destroyGlobalDetectorAndTurnOfMemoryLeakDetectionInDestructor_ = des;
+}
+
+void MemoryLeakWarningPlugin::setGlobalDetector(MemoryLeakDetector* detector, MemoryLeakFailure* reporter)
+{
+ globalDetector = detector;
+ globalReporter = reporter;
+}
+
+void MemoryLeakWarningPlugin::destroyGlobalDetector()
+{
+ turnOffNewDeleteOverloads();
+ delete globalDetector;
+ delete globalReporter;
+ globalDetector = NULL;
+}
+
+
+MemoryLeakWarningPlugin* MemoryLeakWarningPlugin::firstPlugin_ = 0;
+
+MemoryLeakWarningPlugin* MemoryLeakWarningPlugin::getFirstPlugin()
+{
+ return firstPlugin_;
+}
+
+MemoryLeakDetector* MemoryLeakWarningPlugin::getMemoryLeakDetector()
+{
+ return memLeakDetector_;
+}
+
+void MemoryLeakWarningPlugin::ignoreAllLeaksInTest()
+{
+ ignoreAllWarnings_ = true;
+}
+
+void MemoryLeakWarningPlugin::expectLeaksInTest(int n)
+{
+ expectedLeaks_ = n;
+}
+
+MemoryLeakWarningPlugin::MemoryLeakWarningPlugin(const SimpleString& name, MemoryLeakDetector* localDetector) :
+ TestPlugin(name), ignoreAllWarnings_(false), destroyGlobalDetectorAndTurnOfMemoryLeakDetectionInDestructor_(false), expectedLeaks_(0)
+{
+ if (firstPlugin_ == 0) firstPlugin_ = this;
+
+ if (localDetector) memLeakDetector_ = localDetector;
+ else memLeakDetector_ = getGlobalDetector();
+
+ memLeakDetector_->enable();
+}
+
+MemoryLeakWarningPlugin::~MemoryLeakWarningPlugin()
+{
+ if (destroyGlobalDetectorAndTurnOfMemoryLeakDetectionInDestructor_) {
+ MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
+ MemoryLeakWarningPlugin::destroyGlobalDetector();
+ }
+}
+
+void MemoryLeakWarningPlugin::preTestAction(UtestShell& /*test*/, TestResult& result)
+{
+ memLeakDetector_->startChecking();
+ failureCount_ = result.getFailureCount();
+}
+
+void MemoryLeakWarningPlugin::postTestAction(UtestShell& test, TestResult& result)
+{
+ memLeakDetector_->stopChecking();
+ int leaks = memLeakDetector_->totalMemoryLeaks(mem_leak_period_checking);
+
+ if (!ignoreAllWarnings_ && expectedLeaks_ != leaks && failureCount_ == result.getFailureCount()) {
+ TestFailure f(&test, memLeakDetector_->report(mem_leak_period_checking));
+ result.addFailure(f);
+ }
+ memLeakDetector_->markCheckingPeriodLeaksAsNonCheckingPeriod();
+ ignoreAllWarnings_ = false;
+ expectedLeaks_ = 0;
+}
+
+const char* MemoryLeakWarningPlugin::FinalReport(int toBeDeletedLeaks)
+{
+ int leaks = memLeakDetector_->totalMemoryLeaks(mem_leak_period_enabled);
+ if (leaks != toBeDeletedLeaks) return memLeakDetector_->report(mem_leak_period_enabled);
+ return "";
+}
+
+
--- a/src/CppUTest/SimpleString.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/SimpleString.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,515 +1,538 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/SimpleString.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-#include "CppUTest/TestMemoryAllocator.h"
-
-
-TestMemoryAllocator* SimpleString::stringAllocator_ = NULL;
-
-TestMemoryAllocator* SimpleString::getStringAllocator()
-{
- if (stringAllocator_ == NULL)
- return defaultNewArrayAllocator();
- return stringAllocator_;
-}
-
-void SimpleString::setStringAllocator(TestMemoryAllocator* allocator)
-{
- stringAllocator_ = allocator;
-}
-
-/* Avoid using the memory leak detector INSIDE SimpleString as its used inside the detector */
-char* SimpleString::allocStringBuffer(size_t _size)
-{
- return getStringAllocator()->alloc_memory(_size, __FILE__, __LINE__);
-}
-
-void SimpleString::deallocStringBuffer(char* str)
-{
- getStringAllocator()->free_memory(str, __FILE__, __LINE__);
-}
-
-char* SimpleString::getEmptyString() const
-{
- char* empty = allocStringBuffer(1);
- empty[0] = '\0';
- return empty;
-}
-SimpleString::SimpleString(const char *otherBuffer)
-{
- if (otherBuffer == 0) {
- buffer_ = getEmptyString();
- }
- else {
- size_t len = PlatformSpecificStrLen(otherBuffer) + 1;
- buffer_ = allocStringBuffer(len);
- PlatformSpecificStrCpy(buffer_, otherBuffer);
- }
-}
-
-SimpleString::SimpleString(const char *other, size_t repeatCount)
-{
- size_t len = PlatformSpecificStrLen(other) * repeatCount + 1;
- buffer_ = allocStringBuffer(len);
- char* next = buffer_;
- for (size_t i = 0; i < repeatCount; i++) {
- PlatformSpecificStrCpy(next, other);
- next += PlatformSpecificStrLen(other);
- }
- *next = 0;
-
-}
-SimpleString::SimpleString(const SimpleString& other)
-{
- size_t len = other.size() + 1;
- buffer_ = allocStringBuffer(len);
- PlatformSpecificStrCpy(buffer_, other.buffer_);
-}
-
-SimpleString& SimpleString::operator=(const SimpleString& other)
-{
- if (this != &other) {
- deallocStringBuffer(buffer_);
- size_t len = other.size() + 1;
- buffer_ = allocStringBuffer(len);
- PlatformSpecificStrCpy(buffer_, other.buffer_);
- }
- return *this;
-}
-
-bool SimpleString::contains(const SimpleString& other) const
-{
- //strstr on some machines does not handle ""
- //the right way. "" should be found in any string
- if (PlatformSpecificStrLen(other.buffer_) == 0) return true;
- else if (PlatformSpecificStrLen(buffer_) == 0) return false;
- else return PlatformSpecificStrStr(buffer_, other.buffer_) != 0;
-}
-
-bool SimpleString::containsNoCase(const SimpleString& other) const
-{
- return toLower().contains(other.toLower());
-}
-
-
-bool SimpleString::startsWith(const SimpleString& other) const
-{
- if (PlatformSpecificStrLen(other.buffer_) == 0) return true;
- else if (PlatformSpecificStrLen(buffer_) == 0) return false;
- else return PlatformSpecificStrStr(buffer_, other.buffer_) == buffer_;
-}
-
-bool SimpleString::endsWith(const SimpleString& other) const
-{
- size_t buffer_length = PlatformSpecificStrLen(buffer_);
- size_t other_buffer_length = PlatformSpecificStrLen(other.buffer_);
- if (other_buffer_length == 0) return true;
- if (buffer_length == 0) return false;
- if (buffer_length < other_buffer_length) return false;
- return PlatformSpecificStrCmp(buffer_ + buffer_length - other_buffer_length, other.buffer_) == 0;
-}
-
-size_t SimpleString::count(const SimpleString& substr) const
-{
- size_t num = 0;
- char* str = buffer_;
- while ((str = PlatformSpecificStrStr(str, substr.buffer_))) {
- num++;
- str++;
- }
- return num;
-}
-
-void SimpleString::split(const SimpleString& delimiter, SimpleStringCollection& col) const
-{
- size_t num = count(delimiter);
- size_t extraEndToken = (endsWith(delimiter)) ? 0 : 1U;
- col.allocate(num + extraEndToken);
-
- char* str = buffer_;
- char* prev;
- for (size_t i = 0; i < num; ++i) {
- prev = str;
- str = PlatformSpecificStrStr(str, delimiter.buffer_) + 1;
- size_t len = (size_t) (str - prev);
- char* sub = allocStringBuffer(len + 1);
- PlatformSpecificStrNCpy(sub, prev, len);
- sub[len] = '\0';
- col[i] = sub;
- deallocStringBuffer(sub);
- }
- if (extraEndToken) {
- col[num] = str;
- }
-}
-
-void SimpleString::replace(char to, char with)
-{
- size_t s = size();
- for (size_t i = 0; i < s; i++) {
- if (buffer_[i] == to) buffer_[i] = with;
- }
-}
-
-void SimpleString::replace(const char* to, const char* with)
-{
- size_t c = count(to);
- size_t len = size();
- size_t tolen = PlatformSpecificStrLen(to);
- size_t withlen = PlatformSpecificStrLen(with);
-
- size_t newsize = len + (withlen * c) - (tolen * c) + 1;
-
- if (newsize) {
- char* newbuf = allocStringBuffer(newsize);
- for (size_t i = 0, j = 0; i < len;) {
- if (PlatformSpecificStrNCmp(&buffer_[i], to, tolen) == 0) {
- PlatformSpecificStrNCpy(&newbuf[j], with, withlen);
- j += withlen;
- i += tolen;
- }
- else {
- newbuf[j] = buffer_[i];
- j++;
- i++;
- }
- }
- deallocStringBuffer(buffer_);
- buffer_ = newbuf;
- buffer_[newsize - 1] = '\0';
- }
- else {
- buffer_ = getEmptyString();
- buffer_[0] = '\0';
- }
-}
-
-SimpleString SimpleString::toLower() const
-{
- SimpleString str(*this);
-
- size_t str_size = str.size();
- for (size_t i = 0; i < str_size; i++)
- str.buffer_[i] = PlatformSpecificToLower(str.buffer_[i]);
-
- return str;
-}
-
-const char *SimpleString::asCharString() const
-{
- return buffer_;
-}
-
-size_t SimpleString::size() const
-{
- return PlatformSpecificStrLen(buffer_);
-}
-
-bool SimpleString::isEmpty() const
-{
- return size() == 0;
-}
-
-
-
-SimpleString::~SimpleString()
-{
- deallocStringBuffer(buffer_);
-}
-
-bool operator==(const SimpleString& left, const SimpleString& right)
-{
- return 0 == PlatformSpecificStrCmp(left.asCharString(), right.asCharString());
-}
-
-bool SimpleString::equalsNoCase(const SimpleString& str) const
-{
- return toLower() == str.toLower();
-}
-
-
-bool operator!=(const SimpleString& left, const SimpleString& right)
-{
- return !(left == right);
-}
-
-SimpleString SimpleString::operator+(const SimpleString& rhs)
-{
- SimpleString t(buffer_);
- t += rhs.buffer_;
- return t;
-}
-
-SimpleString& SimpleString::operator+=(const SimpleString& rhs)
-{
- return operator+=(rhs.buffer_);
-}
-
-SimpleString& SimpleString::operator+=(const char* rhs)
-{
- size_t len = this->size() + PlatformSpecificStrLen(rhs) + 1;
- char* tbuffer = allocStringBuffer(len);
- PlatformSpecificStrCpy(tbuffer, this->buffer_);
- PlatformSpecificStrCat(tbuffer, rhs);
- deallocStringBuffer(buffer_);
- buffer_ = tbuffer;
- return *this;
-}
-
-void SimpleString::padStringsToSameLength(SimpleString& str1, SimpleString& str2, char padCharacter)
-{
- if (str1.size() > str2.size()) {
- padStringsToSameLength(str2, str1, padCharacter);
- return;
- }
-
- char pad[2];
- pad[0] = padCharacter;
- pad[1] = 0;
- str1 = SimpleString(pad, str2.size() - str1.size()) + str1;
-}
-
-SimpleString SimpleString::subString(size_t beginPos, size_t amount) const
-{
- if (beginPos > size()-1) return "";
-
- SimpleString newString = buffer_ + beginPos;
-
- if (newString.size() > amount)
- newString.buffer_[amount] = '\0';
-
- return newString;
-}
-
-char SimpleString::at(int pos) const
-{
- return buffer_[pos];
-}
-
-int SimpleString::find(char ch) const
-{
- return findFrom(0, ch);
-}
-
-int SimpleString::findFrom(size_t starting_position, char ch) const
-{
- size_t length = size();
- for (size_t i = starting_position; i < length; i++)
- if (buffer_[i] == ch) return (int) i;
- return -1;
-}
-
-SimpleString SimpleString::subStringFromTill(char startChar, char lastExcludedChar) const
-{
- int beginPos = find(startChar);
- if (beginPos < 0) return "";
-
- int endPos = findFrom((size_t)beginPos, lastExcludedChar);
- if (endPos == -1) return subString((size_t)beginPos, size());
-
- return subString((size_t)beginPos, (size_t) (endPos - beginPos));
-}
-
-
-void SimpleString::copyToBuffer(char* bufferToCopy, size_t bufferSize) const
-{
- if (bufferToCopy == NULL || bufferSize == 0) return;
-
- size_t sizeToCopy = (bufferSize-1 < size()) ? bufferSize-1 : size();
-
- PlatformSpecificStrNCpy(bufferToCopy, buffer_, sizeToCopy);
- bufferToCopy[sizeToCopy] = '\0';
-
-}
-
-SimpleString StringFrom(bool value)
-{
- return SimpleString(StringFromFormat("%s", value ? "true" : "false"));
-}
-
-SimpleString StringFrom(const char *value)
-{
- return SimpleString(value);
-}
-
-SimpleString StringFromOrNull(const char * expected)
-{
- return (expected) ? StringFrom(expected) : "(null)";
-}
-
-SimpleString StringFrom(int value)
-{
- return StringFromFormat("%d", value);
-}
-
-SimpleString StringFrom(long value)
-{
- return StringFromFormat("%ld", value);
-}
-
-SimpleString StringFrom(const void* value)
-{
- return SimpleString("0x") + HexStringFrom(value);
-}
-
-SimpleString HexStringFrom(long value)
-{
- return StringFromFormat("%lx", value);
-}
-
-static long convertPointerToLongValue(const void* value)
-{
- /*
- * This way of converting also can convert a 64bit pointer in a 32bit integer by truncating.
- * This isn't the right way to convert pointers values and need to change by implementing a
- * proper portable way to convert pointers to strings.
- */
- long* long_value = (long*) &value;
- return *long_value;
-}
-
-SimpleString HexStringFrom(const void* value)
-{
- return StringFromFormat("%lx", convertPointerToLongValue(value));
-}
-
-SimpleString StringFrom(double value, int precision)
-{
- return StringFromFormat("%.*g", precision, value);
-}
-
-SimpleString StringFrom(char value)
-{
- return StringFromFormat("%c", value);
-}
-
-SimpleString StringFrom(const SimpleString& value)
-{
- return SimpleString(value);
-}
-
-SimpleString StringFromFormat(const char* format, ...)
-{
- SimpleString resultString;
- va_list arguments;
- va_start(arguments, format);
-
- resultString = VStringFromFormat(format, arguments);
- va_end(arguments);
- return resultString;
-}
-
-SimpleString StringFrom(unsigned int i)
-{
- return StringFromFormat("%10u (0x%08x)", i, i);
-}
-
-#if CPPUTEST_USE_STD_CPP_LIB
-
-#include <string>
-
-SimpleString StringFrom(const std::string& value)
-{
- return SimpleString(value.c_str());
-}
-
-SimpleString StringFrom(unsigned long i)
-{
- return StringFromFormat("%lu (0x%lx)", i, i);
-}
-
-#endif
-
-//Kludge to get a va_copy in VC++ V6
-#ifndef va_copy
-#define va_copy(copy, original) copy = original;
-#endif
-
-SimpleString VStringFromFormat(const char* format, va_list args)
-{
- va_list argsCopy;
- va_copy(argsCopy, args);
- enum
- {
- sizeOfdefaultBuffer = 100
- };
- char defaultBuffer[sizeOfdefaultBuffer];
- SimpleString resultString;
-
- size_t size = (size_t)PlatformSpecificVSNprintf(defaultBuffer, sizeOfdefaultBuffer, format, args);
- if (size < sizeOfdefaultBuffer) {
- resultString = SimpleString(defaultBuffer);
- }
- else {
- size_t newBufferSize = size + 1;
- char* newBuffer = SimpleString::allocStringBuffer(newBufferSize);
- PlatformSpecificVSNprintf(newBuffer, newBufferSize, format, argsCopy);
- resultString = SimpleString(newBuffer);
-
- SimpleString::deallocStringBuffer(newBuffer);
- }
- va_end(argsCopy);
- return resultString;
-}
-
-SimpleStringCollection::SimpleStringCollection()
-{
- collection_ = 0;
- size_ = 0;
-}
-
-void SimpleStringCollection::allocate(size_t _size)
-{
- if (collection_) delete[] collection_;
-
- size_ = _size;
- collection_ = new SimpleString[size_];
-}
-
-SimpleStringCollection::~SimpleStringCollection()
-{
- delete[] (collection_);
-}
-
-size_t SimpleStringCollection::size() const
-{
- return size_;
-}
-
-SimpleString& SimpleStringCollection::operator[](size_t index)
-{
- if (index >= size_) {
- empty_ = "";
- return empty_;
- }
-
- return collection_[index];
-}
-
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/SimpleString.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+#include "CppUTest/TestMemoryAllocator.h"
+
+
+TestMemoryAllocator* SimpleString::stringAllocator_ = NULL;
+
+TestMemoryAllocator* SimpleString::getStringAllocator()
+{
+ if (stringAllocator_ == NULL)
+ return defaultNewArrayAllocator();
+ return stringAllocator_;
+}
+
+void SimpleString::setStringAllocator(TestMemoryAllocator* allocator)
+{
+ stringAllocator_ = allocator;
+}
+
+/* Avoid using the memory leak detector INSIDE SimpleString as its used inside the detector */
+char* SimpleString::allocStringBuffer(size_t _size)
+{
+ return getStringAllocator()->alloc_memory(_size, __FILE__, __LINE__);
+}
+
+void SimpleString::deallocStringBuffer(char* str)
+{
+ getStringAllocator()->free_memory(str, __FILE__, __LINE__);
+}
+
+char* SimpleString::getEmptyString() const
+{
+ char* empty = allocStringBuffer(1);
+ empty[0] = '\0';
+ return empty;
+}
+
+char* SimpleString::StrNCpy(char* s1, const char* s2, size_t n)
+{
+ char* result = s1;
+
+ if((NULL == s1) || (0 == n)) return result;
+
+ while ((*s1++ = *s2++) && --n != 0)
+ ;
+ return result;
+}
+
+SimpleString::SimpleString(const char *otherBuffer)
+{
+ if (otherBuffer == 0) {
+ buffer_ = getEmptyString();
+ }
+ else {
+ buffer_ = copyToNewBuffer(otherBuffer);
+ }
+}
+
+SimpleString::SimpleString(const char *other, size_t repeatCount)
+{
+ size_t otherStringLength = PlatformSpecificStrLen(other);
+ size_t len = otherStringLength * repeatCount + 1;
+ buffer_ = allocStringBuffer(len);
+ char* next = buffer_;
+ for (size_t i = 0; i < repeatCount; i++) {
+ StrNCpy(next, other, otherStringLength + 1);
+ next += otherStringLength;
+ }
+ *next = 0;
+}
+
+SimpleString::SimpleString(const SimpleString& other)
+{
+ buffer_ = copyToNewBuffer(other.buffer_);
+}
+
+SimpleString& SimpleString::operator=(const SimpleString& other)
+{
+ if (this != &other) {
+ deallocStringBuffer(buffer_);
+ buffer_ = copyToNewBuffer(other.buffer_);
+ }
+ return *this;
+}
+
+bool SimpleString::contains(const SimpleString& other) const
+{
+ //strstr on some machines does not handle ""
+ //the right way. "" should be found in any string
+ if (PlatformSpecificStrLen(other.buffer_) == 0) return true;
+ else if (PlatformSpecificStrLen(buffer_) == 0) return false;
+ else return PlatformSpecificStrStr(buffer_, other.buffer_) != 0;
+}
+
+bool SimpleString::containsNoCase(const SimpleString& other) const
+{
+ return toLower().contains(other.toLower());
+}
+
+
+bool SimpleString::startsWith(const SimpleString& other) const
+{
+ if (PlatformSpecificStrLen(other.buffer_) == 0) return true;
+ else if (PlatformSpecificStrLen(buffer_) == 0) return false;
+ else return PlatformSpecificStrStr(buffer_, other.buffer_) == buffer_;
+}
+
+bool SimpleString::endsWith(const SimpleString& other) const
+{
+ size_t buffer_length = PlatformSpecificStrLen(buffer_);
+ size_t other_buffer_length = PlatformSpecificStrLen(other.buffer_);
+ if (other_buffer_length == 0) return true;
+ if (buffer_length == 0) return false;
+ if (buffer_length < other_buffer_length) return false;
+ return PlatformSpecificStrCmp(buffer_ + buffer_length - other_buffer_length, other.buffer_) == 0;
+}
+
+size_t SimpleString::count(const SimpleString& substr) const
+{
+ size_t num = 0;
+ char* str = buffer_;
+ while ((str = PlatformSpecificStrStr(str, substr.buffer_))) {
+ num++;
+ str++;
+ }
+ return num;
+}
+
+void SimpleString::split(const SimpleString& delimiter, SimpleStringCollection& col) const
+{
+ size_t num = count(delimiter);
+ size_t extraEndToken = (endsWith(delimiter)) ? 0 : 1U;
+ col.allocate(num + extraEndToken);
+
+ char* str = buffer_;
+ char* prev;
+ for (size_t i = 0; i < num; ++i) {
+ prev = str;
+ str = PlatformSpecificStrStr(str, delimiter.buffer_) + 1;
+ size_t len = (size_t) (str - prev) + 1;
+ col[i].buffer_ = copyToNewBuffer(prev, len);
+ }
+ if (extraEndToken) {
+ col[num] = str;
+ }
+}
+
+void SimpleString::replace(char to, char with)
+{
+ size_t s = size();
+ for (size_t i = 0; i < s; i++) {
+ if (buffer_[i] == to) buffer_[i] = with;
+ }
+}
+
+void SimpleString::replace(const char* to, const char* with)
+{
+ size_t c = count(to);
+ size_t len = size();
+ size_t tolen = PlatformSpecificStrLen(to);
+ size_t withlen = PlatformSpecificStrLen(with);
+
+ size_t newsize = len + (withlen * c) - (tolen * c) + 1;
+
+ if (newsize) {
+ char* newbuf = allocStringBuffer(newsize);
+ for (size_t i = 0, j = 0; i < len;) {
+ if (PlatformSpecificStrNCmp(&buffer_[i], to, tolen) == 0) {
+ StrNCpy(&newbuf[j], with, withlen + 1);
+ j += withlen;
+ i += tolen;
+ }
+ else {
+ newbuf[j] = buffer_[i];
+ j++;
+ i++;
+ }
+ }
+ deallocStringBuffer(buffer_);
+ buffer_ = newbuf;
+ buffer_[newsize - 1] = '\0';
+ }
+ else {
+ buffer_ = getEmptyString();
+ buffer_[0] = '\0';
+ }
+}
+
+SimpleString SimpleString::toLower() const
+{
+ SimpleString str(*this);
+
+ size_t str_size = str.size();
+ for (size_t i = 0; i < str_size; i++)
+ str.buffer_[i] = PlatformSpecificToLower(str.buffer_[i]);
+
+ return str;
+}
+
+const char *SimpleString::asCharString() const
+{
+ return buffer_;
+}
+
+size_t SimpleString::size() const
+{
+ return PlatformSpecificStrLen(buffer_);
+}
+
+bool SimpleString::isEmpty() const
+{
+ return size() == 0;
+}
+
+
+
+SimpleString::~SimpleString()
+{
+ deallocStringBuffer(buffer_);
+}
+
+bool operator==(const SimpleString& left, const SimpleString& right)
+{
+ return 0 == PlatformSpecificStrCmp(left.asCharString(), right.asCharString());
+}
+
+bool SimpleString::equalsNoCase(const SimpleString& str) const
+{
+ return toLower() == str.toLower();
+}
+
+
+bool operator!=(const SimpleString& left, const SimpleString& right)
+{
+ return !(left == right);
+}
+
+SimpleString SimpleString::operator+(const SimpleString& rhs)
+{
+ SimpleString t(buffer_);
+ t += rhs.buffer_;
+ return t;
+}
+
+SimpleString& SimpleString::operator+=(const SimpleString& rhs)
+{
+ return operator+=(rhs.buffer_);
+}
+
+SimpleString& SimpleString::operator+=(const char* rhs)
+{
+ size_t originalSize = this->size();
+ size_t additionalStringSize = PlatformSpecificStrLen(rhs) + 1;
+ size_t sizeOfNewString = originalSize + additionalStringSize;
+ char* tbuffer = copyToNewBuffer(this->buffer_, sizeOfNewString);
+ StrNCpy(tbuffer + originalSize, rhs, additionalStringSize);
+ deallocStringBuffer(this->buffer_);
+ this->buffer_ = tbuffer;
+ return *this;
+}
+
+void SimpleString::padStringsToSameLength(SimpleString& str1, SimpleString& str2, char padCharacter)
+{
+ if (str1.size() > str2.size()) {
+ padStringsToSameLength(str2, str1, padCharacter);
+ return;
+ }
+
+ char pad[2];
+ pad[0] = padCharacter;
+ pad[1] = 0;
+ str1 = SimpleString(pad, str2.size() - str1.size()) + str1;
+}
+
+SimpleString SimpleString::subString(size_t beginPos, size_t amount) const
+{
+ if (beginPos > size()-1) return "";
+
+ SimpleString newString = buffer_ + beginPos;
+
+ if (newString.size() > amount)
+ newString.buffer_[amount] = '\0';
+
+ return newString;
+}
+
+char SimpleString::at(int pos) const
+{
+ return buffer_[pos];
+}
+
+int SimpleString::find(char ch) const
+{
+ return findFrom(0, ch);
+}
+
+int SimpleString::findFrom(size_t starting_position, char ch) const
+{
+ size_t length = size();
+ for (size_t i = starting_position; i < length; i++)
+ if (buffer_[i] == ch) return (int) i;
+ return -1;
+}
+
+SimpleString SimpleString::subStringFromTill(char startChar, char lastExcludedChar) const
+{
+ int beginPos = find(startChar);
+ if (beginPos < 0) return "";
+
+ int endPos = findFrom((size_t)beginPos, lastExcludedChar);
+ if (endPos == -1) return subString((size_t)beginPos, size());
+
+ return subString((size_t)beginPos, (size_t) (endPos - beginPos));
+}
+
+char* SimpleString::copyToNewBuffer(const char* bufferToCopy, size_t bufferSize)
+{
+ if(bufferSize == 0) bufferSize = PlatformSpecificStrLen(bufferToCopy) + 1;
+
+ char* newBuffer = allocStringBuffer(bufferSize);
+ StrNCpy(newBuffer, bufferToCopy, bufferSize);
+ newBuffer[bufferSize-1] = '\0';
+ return newBuffer;
+}
+
+void SimpleString::copyToBuffer(char* bufferToCopy, size_t bufferSize) const
+{
+ if (bufferToCopy == NULL || bufferSize == 0) return;
+
+ size_t sizeToCopy = (bufferSize-1 < size()) ? bufferSize : size();
+
+ StrNCpy(bufferToCopy, buffer_, sizeToCopy);
+ bufferToCopy[sizeToCopy] = '\0';
+}
+
+SimpleString StringFrom(bool value)
+{
+ return SimpleString(StringFromFormat("%s", value ? "true" : "false"));
+}
+
+SimpleString StringFrom(const char *value)
+{
+ return SimpleString(value);
+}
+
+SimpleString StringFromOrNull(const char * expected)
+{
+ return (expected) ? StringFrom(expected) : "(null)";
+}
+
+SimpleString StringFrom(int value)
+{
+ return StringFromFormat("%d", value);
+}
+
+SimpleString StringFrom(long value)
+{
+ return StringFromFormat("%ld", value);
+}
+
+SimpleString StringFrom(const void* value)
+{
+ return SimpleString("0x") + HexStringFrom(value);
+}
+
+SimpleString HexStringFrom(long value)
+{
+ return StringFromFormat("%lx", value);
+}
+
+SimpleString HexStringFrom(unsigned long value)
+{
+ return StringFromFormat("%lx", value);
+}
+
+static long convertPointerToLongValue(const void* value)
+{
+ /*
+ * This way of converting also can convert a 64bit pointer in a 32bit integer by truncating.
+ * This isn't the right way to convert pointers values and need to change by implementing a
+ * proper portable way to convert pointers to strings.
+ */
+ long* long_value = (long*) &value;
+ return *long_value;
+}
+
+SimpleString HexStringFrom(const void* value)
+{
+ return StringFromFormat("%lx", convertPointerToLongValue(value));
+}
+
+SimpleString StringFrom(double value, int precision)
+{
+ return StringFromFormat("%.*g", precision, value);
+}
+
+SimpleString StringFrom(char value)
+{
+ return StringFromFormat("%c", value);
+}
+
+SimpleString StringFrom(const SimpleString& value)
+{
+ return SimpleString(value);
+}
+
+SimpleString StringFromFormat(const char* format, ...)
+{
+ SimpleString resultString;
+ va_list arguments;
+ va_start(arguments, format);
+
+ resultString = VStringFromFormat(format, arguments);
+ va_end(arguments);
+ return resultString;
+}
+
+SimpleString StringFrom(unsigned int i)
+{
+ return StringFromFormat("%10u (0x%08x)", i, i);
+}
+
+#if CPPUTEST_USE_STD_CPP_LIB
+
+#include <string>
+
+SimpleString StringFrom(const std::string& value)
+{
+ return SimpleString(value.c_str());
+}
+
+SimpleString StringFrom(unsigned long i)
+{
+ return StringFromFormat("%lu (0x%lx)", i, i);
+}
+
+#else
+
+SimpleString StringFrom(unsigned long value)
+{
+ return StringFromFormat("%lu", value);
+}
+
+#endif
+
+//Kludge to get a va_copy in VC++ V6
+#ifndef va_copy
+#define va_copy(copy, original) copy = original;
+#endif
+
+SimpleString VStringFromFormat(const char* format, va_list args)
+{
+ va_list argsCopy;
+ va_copy(argsCopy, args);
+ enum
+ {
+ sizeOfdefaultBuffer = 100
+ };
+ char defaultBuffer[sizeOfdefaultBuffer];
+ SimpleString resultString;
+
+ size_t size = (size_t)PlatformSpecificVSNprintf(defaultBuffer, sizeOfdefaultBuffer, format, args);
+ if (size < sizeOfdefaultBuffer) {
+ resultString = SimpleString(defaultBuffer);
+ }
+ else {
+ size_t newBufferSize = size + 1;
+ char* newBuffer = SimpleString::allocStringBuffer(newBufferSize);
+ PlatformSpecificVSNprintf(newBuffer, newBufferSize, format, argsCopy);
+ resultString = SimpleString(newBuffer);
+
+ SimpleString::deallocStringBuffer(newBuffer);
+ }
+ va_end(argsCopy);
+ return resultString;
+}
+
+SimpleStringCollection::SimpleStringCollection()
+{
+ collection_ = 0;
+ size_ = 0;
+}
+
+void SimpleStringCollection::allocate(size_t _size)
+{
+ delete[] collection_;
+
+ size_ = _size;
+ collection_ = new SimpleString[size_];
+}
+
+SimpleStringCollection::~SimpleStringCollection()
+{
+ delete[] (collection_);
+}
+
+size_t SimpleStringCollection::size() const
+{
+ return size_;
+}
+
+SimpleString& SimpleStringCollection::operator[](size_t index)
+{
+ if (index >= size_) {
+ empty_ = "";
+ return empty_;
+ }
+
+ return collection_[index];
+}
--- a/src/CppUTest/TestFailure.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/TestFailure.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,252 +1,267 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/TestFailure.h"
-#include "CppUTest/TestOutput.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-
-static SimpleString removeAllPrintableCharactersFrom(const SimpleString& str)
-{
- size_t bufferSize = str.size()+1;
- char* buffer = (char*) PlatformSpecificMalloc(bufferSize);
- str.copyToBuffer(buffer, bufferSize);
-
- for (size_t i = 0; i < bufferSize-1; i++)
- if (buffer[i] != '\t' && buffer[i] != '\n')
- buffer[i] = ' ';
-
- SimpleString result(buffer);
- PlatformSpecificFree(buffer);
- return result;
-}
-
-static SimpleString addMarkerToString(const SimpleString& str, int markerPos)
-{
- size_t bufferSize = str.size()+1;
- char* buffer = (char*) PlatformSpecificMalloc(bufferSize);
- str.copyToBuffer(buffer, bufferSize);
-
- buffer[markerPos] = '^';
-
- SimpleString result(buffer);
- PlatformSpecificFree(buffer);
- return result;
-
-}
-
-TestFailure::TestFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& theMessage) :
- testName_(test->getFormattedName()), fileName_(fileName), lineNumber_(lineNumber), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_(theMessage)
-{
-}
-
-TestFailure::TestFailure(UtestShell* test, const SimpleString& theMessage) :
- testName_(test->getFormattedName()), fileName_(test->getFile()), lineNumber_(test->getLineNumber()), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_(theMessage)
-{
-}
-
-TestFailure::TestFailure(UtestShell* test, const char* fileName, int lineNum) :
- testName_(test->getFormattedName()), fileName_(fileName), lineNumber_(lineNum), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_("no message")
-{
-}
-
-TestFailure::TestFailure(const TestFailure& f) :
- testName_(f.testName_), fileName_(f.fileName_), lineNumber_(f.lineNumber_), testFileName_(f.testFileName_), testLineNumber_(f.testLineNumber_), message_(f.message_)
-{
-}
-
-
-TestFailure::~TestFailure()
-{
-}
-
-SimpleString TestFailure::getFileName() const
-{
- return fileName_;
-}
-
-SimpleString TestFailure::getTestFileName() const
-{
- return testFileName_;
-}
-
-SimpleString TestFailure::getTestName() const
-{
- return testName_;
-}
-
-int TestFailure::getFailureLineNumber() const
-{
- return lineNumber_;
-}
-
-int TestFailure::getTestLineNumber() const
-{
- return testLineNumber_;
-}
-
-SimpleString TestFailure::getMessage() const
-{
- return message_;
-}
-
-bool TestFailure::isOutsideTestFile() const
-{
- return testFileName_ != fileName_;
-}
-
-bool TestFailure::isInHelperFunction() const
-{
- return lineNumber_ < testLineNumber_;
-}
-
-SimpleString TestFailure::createButWasString(const SimpleString& expected, const SimpleString& actual)
-{
- return StringFromFormat("expected <%s>\n\tbut was <%s>", expected.asCharString(), actual.asCharString());
-}
-
-SimpleString TestFailure::createDifferenceAtPosString(const SimpleString& actual, size_t position)
-{
- SimpleString result;
- const size_t extraCharactersWindow = 20;
- const size_t halfOfExtraCharactersWindow = extraCharactersWindow / 2;
-
- SimpleString paddingForPreventingOutOfBounds (" ", halfOfExtraCharactersWindow);
- SimpleString actualString = paddingForPreventingOutOfBounds + actual + paddingForPreventingOutOfBounds;
- SimpleString differentString = StringFromFormat("difference starts at position %lu at: <", (unsigned long) position);
-
- result += "\n";
- result += StringFromFormat("\t%s%s>\n", differentString.asCharString(), actualString.subString(position, extraCharactersWindow).asCharString());
-
- SimpleString markString = actualString.subString(position, halfOfExtraCharactersWindow+1);
- markString = removeAllPrintableCharactersFrom(markString);
- markString = addMarkerToString(markString, halfOfExtraCharactersWindow);
-
- result += StringFromFormat("\t%s%s", SimpleString(" ", differentString.size()).asCharString(), markString.asCharString());
- return result;
-}
-
-EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual) :
- TestFailure(test, fileName, lineNumber)
-{
- message_ = createButWasString(StringFromOrNull(expected), StringFromOrNull(actual));
-}
-
-EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual)
- : TestFailure(test, fileName, lineNumber)
-{
- message_ = createButWasString(expected, actual);
-}
-
-static SimpleString StringFromOrNan(double d)
-{
- if (PlatformSpecificIsNan(d))
- return "Nan - Not a number";
- return StringFrom(d);
-}
-
-DoublesEqualFailure::DoublesEqualFailure(UtestShell* test, const char* fileName, int lineNumber, double expected, double actual, double threshold) : TestFailure(test, fileName, lineNumber)
-{
- message_ = createButWasString(StringFromOrNan(expected), StringFromOrNan(actual));
- message_ += " threshold used was <";
- message_ += StringFromOrNan(threshold);
- message_ += ">";
-
- if (PlatformSpecificIsNan(expected) || PlatformSpecificIsNan(actual) || PlatformSpecificIsNan(threshold))
- message_ += "\n\tCannot make comparisons with Nan";
-}
-
-CheckEqualFailure::CheckEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual) : TestFailure(test, fileName, lineNumber)
-{
- size_t failStart;
- for (failStart = 0; actual.asCharString()[failStart] == expected.asCharString()[failStart]; failStart++)
- ;
- message_ = createButWasString(expected, actual);
- message_ += createDifferenceAtPosString(actual, failStart);
-
-}
-
-ContainsFailure::ContainsFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual) :
- TestFailure(test, fileName, lineNumber)
-{
- message_ = StringFromFormat("actual <%s>\n\tdid not contain <%s>", actual.asCharString(), expected.asCharString());
-}
-
-CheckFailure::CheckFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& checkString, const SimpleString& conditionString, const SimpleString& text) : TestFailure(test, fileName, lineNumber)
-{
- message_ = "";
- if (!text.isEmpty()) {
- message_ += "Message: ";
- message_ += text;
- message_ += "\n\t";
- }
- message_ += checkString;
- message_ += "(";
- message_ += conditionString;
- message_ += ") failed";
-}
-
-FailFailure::FailFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& message) : TestFailure(test, fileName, lineNumber)
-{
- message_ = message;
-}
-
-LongsEqualFailure::LongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, long expected, long actual) : TestFailure(test, fileName, lineNumber)
-{
- SimpleString aDecimal = StringFrom(actual);
- SimpleString aHex = HexStringFrom(actual);
- SimpleString eDecimal = StringFrom(expected);
- SimpleString eHex = HexStringFrom(expected);
-
- SimpleString::padStringsToSameLength(aDecimal, eDecimal, ' ');
- SimpleString::padStringsToSameLength(aHex, eHex, '0');
-
- SimpleString actualReported = aDecimal + " 0x" + aHex;
- SimpleString expectedReported = eDecimal + " 0x" + eHex;
- message_ = createButWasString(expectedReported, actualReported);
-}
-
-
-StringEqualFailure::StringEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual) : TestFailure(test, fileName, lineNumber)
-{
- size_t failStart;
- for (failStart = 0; actual[failStart] == expected[failStart]; failStart++)
- ;
- message_ = createButWasString(expected, actual);
- message_ += createDifferenceAtPosString(actual, failStart);
-}
-
-StringEqualNoCaseFailure::StringEqualNoCaseFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual) : TestFailure(test, fileName, lineNumber)
-{
- size_t failStart;
- for (failStart = 0; PlatformSpecificToLower(actual[failStart]) == PlatformSpecificToLower(expected[failStart]); failStart++)
- ;
- message_ = createButWasString(expected, actual);
- message_ += createDifferenceAtPosString(actual, failStart);
-}
-
-
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/TestFailure.h"
+#include "CppUTest/TestOutput.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+
+static SimpleString removeAllPrintableCharactersFrom(const SimpleString& str)
+{
+ size_t bufferSize = str.size()+1;
+ char* buffer = (char*) PlatformSpecificMalloc(bufferSize);
+ str.copyToBuffer(buffer, bufferSize);
+
+ for (size_t i = 0; i < bufferSize-1; i++)
+ if (buffer[i] != '\t' && buffer[i] != '\n')
+ buffer[i] = ' ';
+
+ SimpleString result(buffer);
+ PlatformSpecificFree(buffer);
+ return result;
+}
+
+static SimpleString addMarkerToString(const SimpleString& str, int markerPos)
+{
+ size_t bufferSize = str.size()+1;
+ char* buffer = (char*) PlatformSpecificMalloc(bufferSize);
+ str.copyToBuffer(buffer, bufferSize);
+
+ buffer[markerPos] = '^';
+
+ SimpleString result(buffer);
+ PlatformSpecificFree(buffer);
+ return result;
+
+}
+
+TestFailure::TestFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& theMessage) :
+ testName_(test->getFormattedName()), fileName_(fileName), lineNumber_(lineNumber), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_(theMessage)
+{
+}
+
+TestFailure::TestFailure(UtestShell* test, const SimpleString& theMessage) :
+ testName_(test->getFormattedName()), fileName_(test->getFile()), lineNumber_(test->getLineNumber()), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_(theMessage)
+{
+}
+
+TestFailure::TestFailure(UtestShell* test, const char* fileName, int lineNum) :
+ testName_(test->getFormattedName()), fileName_(fileName), lineNumber_(lineNum), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_("no message")
+{
+}
+
+TestFailure::TestFailure(const TestFailure& f) :
+ testName_(f.testName_), fileName_(f.fileName_), lineNumber_(f.lineNumber_), testFileName_(f.testFileName_), testLineNumber_(f.testLineNumber_), message_(f.message_)
+{
+}
+
+
+TestFailure::~TestFailure()
+{
+}
+
+SimpleString TestFailure::getFileName() const
+{
+ return fileName_;
+}
+
+SimpleString TestFailure::getTestFileName() const
+{
+ return testFileName_;
+}
+
+SimpleString TestFailure::getTestName() const
+{
+ return testName_;
+}
+
+int TestFailure::getFailureLineNumber() const
+{
+ return lineNumber_;
+}
+
+int TestFailure::getTestLineNumber() const
+{
+ return testLineNumber_;
+}
+
+SimpleString TestFailure::getMessage() const
+{
+ return message_;
+}
+
+bool TestFailure::isOutsideTestFile() const
+{
+ return testFileName_ != fileName_;
+}
+
+bool TestFailure::isInHelperFunction() const
+{
+ return lineNumber_ < testLineNumber_;
+}
+
+SimpleString TestFailure::createButWasString(const SimpleString& expected, const SimpleString& actual)
+{
+ return StringFromFormat("expected <%s>\n\tbut was <%s>", expected.asCharString(), actual.asCharString());
+}
+
+SimpleString TestFailure::createDifferenceAtPosString(const SimpleString& actual, size_t position)
+{
+ SimpleString result;
+ const size_t extraCharactersWindow = 20;
+ const size_t halfOfExtraCharactersWindow = extraCharactersWindow / 2;
+
+ SimpleString paddingForPreventingOutOfBounds (" ", halfOfExtraCharactersWindow);
+ SimpleString actualString = paddingForPreventingOutOfBounds + actual + paddingForPreventingOutOfBounds;
+ SimpleString differentString = StringFromFormat("difference starts at position %lu at: <", (unsigned long) position);
+
+ result += "\n";
+ result += StringFromFormat("\t%s%s>\n", differentString.asCharString(), actualString.subString(position, extraCharactersWindow).asCharString());
+
+ SimpleString markString = actualString.subString(position, halfOfExtraCharactersWindow+1);
+ markString = removeAllPrintableCharactersFrom(markString);
+ markString = addMarkerToString(markString, halfOfExtraCharactersWindow);
+
+ result += StringFromFormat("\t%s%s", SimpleString(" ", differentString.size()).asCharString(), markString.asCharString());
+ return result;
+}
+
+EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual) :
+ TestFailure(test, fileName, lineNumber)
+{
+ message_ = createButWasString(StringFromOrNull(expected), StringFromOrNull(actual));
+}
+
+EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual)
+ : TestFailure(test, fileName, lineNumber)
+{
+ message_ = createButWasString(expected, actual);
+}
+
+static SimpleString StringFromOrNan(double d)
+{
+ if (PlatformSpecificIsNan(d))
+ return "Nan - Not a number";
+ return StringFrom(d);
+}
+
+DoublesEqualFailure::DoublesEqualFailure(UtestShell* test, const char* fileName, int lineNumber, double expected, double actual, double threshold) : TestFailure(test, fileName, lineNumber)
+{
+ message_ = createButWasString(StringFromOrNan(expected), StringFromOrNan(actual));
+ message_ += " threshold used was <";
+ message_ += StringFromOrNan(threshold);
+ message_ += ">";
+
+ if (PlatformSpecificIsNan(expected) || PlatformSpecificIsNan(actual) || PlatformSpecificIsNan(threshold))
+ message_ += "\n\tCannot make comparisons with Nan";
+}
+
+CheckEqualFailure::CheckEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual) : TestFailure(test, fileName, lineNumber)
+{
+ size_t failStart;
+ for (failStart = 0; actual.asCharString()[failStart] == expected.asCharString()[failStart]; failStart++)
+ ;
+ message_ = createButWasString(expected, actual);
+ message_ += createDifferenceAtPosString(actual, failStart);
+
+}
+
+ContainsFailure::ContainsFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual) :
+ TestFailure(test, fileName, lineNumber)
+{
+ message_ = StringFromFormat("actual <%s>\n\tdid not contain <%s>", actual.asCharString(), expected.asCharString());
+}
+
+CheckFailure::CheckFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& checkString, const SimpleString& conditionString, const SimpleString& text) : TestFailure(test, fileName, lineNumber)
+{
+ message_ = "";
+ if (!text.isEmpty()) {
+ message_ += "Message: ";
+ message_ += text;
+ message_ += "\n\t";
+ }
+ message_ += checkString;
+ message_ += "(";
+ message_ += conditionString;
+ message_ += ") failed";
+}
+
+FailFailure::FailFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& message) : TestFailure(test, fileName, lineNumber)
+{
+ message_ = message;
+}
+
+LongsEqualFailure::LongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, long expected, long actual) : TestFailure(test, fileName, lineNumber)
+{
+ SimpleString aDecimal = StringFrom(actual);
+ SimpleString aHex = HexStringFrom(actual);
+ SimpleString eDecimal = StringFrom(expected);
+ SimpleString eHex = HexStringFrom(expected);
+
+ SimpleString::padStringsToSameLength(aDecimal, eDecimal, ' ');
+ SimpleString::padStringsToSameLength(aHex, eHex, '0');
+
+ SimpleString actualReported = aDecimal + " 0x" + aHex;
+ SimpleString expectedReported = eDecimal + " 0x" + eHex;
+ message_ = createButWasString(expectedReported, actualReported);
+}
+
+UnsignedLongsEqualFailure::UnsignedLongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, unsigned long expected, unsigned long actual) : TestFailure(test, fileName, lineNumber)
+{
+ SimpleString aDecimal = StringFrom(actual);
+ SimpleString aHex = HexStringFrom(actual);
+ SimpleString eDecimal = StringFrom(expected);
+ SimpleString eHex = HexStringFrom(expected);
+
+ SimpleString::padStringsToSameLength(aDecimal, eDecimal, ' ');
+ SimpleString::padStringsToSameLength(aHex, eHex, '0');
+
+ SimpleString actualReported = aDecimal + " 0x" + aHex;
+ SimpleString expectedReported = eDecimal + " 0x" + eHex;
+ message_ = createButWasString(expectedReported, actualReported);
+}
+
+
+StringEqualFailure::StringEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual) : TestFailure(test, fileName, lineNumber)
+{
+ size_t failStart;
+ for (failStart = 0; actual[failStart] == expected[failStart]; failStart++)
+ ;
+ message_ = createButWasString(expected, actual);
+ message_ += createDifferenceAtPosString(actual, failStart);
+}
+
+StringEqualNoCaseFailure::StringEqualNoCaseFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual) : TestFailure(test, fileName, lineNumber)
+{
+ size_t failStart;
+ for (failStart = 0; PlatformSpecificToLower(actual[failStart]) == PlatformSpecificToLower(expected[failStart]); failStart++)
+ ;
+ message_ = createButWasString(expected, actual);
+ message_ += createDifferenceAtPosString(actual, failStart);
+}
+
+
--- a/src/CppUTest/TestHarness_c.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/TestHarness_c.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,164 +1,164 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/MemoryLeakDetector.h"
-#include "CppUTest/TestMemoryAllocator.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-#include "CppUTest/TestHarness_c.h"
-
-extern "C"
-{
-
-
-void CHECK_EQUAL_C_INT_LOCATION(int expected, int actual, const char* fileName, int lineNumber)
-{
- UtestShell::getCurrent()->assertLongsEqual((long)expected, (long)actual, fileName, lineNumber, TestTerminatorWithoutExceptions());
-}
-
-void CHECK_EQUAL_C_REAL_LOCATION(double expected, double actual, double threshold, const char* fileName, int lineNumber)
-{
- UtestShell::getCurrent()->assertDoublesEqual(expected, actual, threshold, fileName, lineNumber, TestTerminatorWithoutExceptions());
-}
-
-void CHECK_EQUAL_C_CHAR_LOCATION(char expected, char actual, const char* fileName, int lineNumber)
-{
- UtestShell::getCurrent()->assertEquals(((expected) != (actual)), StringFrom(expected).asCharString(), StringFrom(actual).asCharString(), fileName, lineNumber, TestTerminatorWithoutExceptions());
-}
-
-void CHECK_EQUAL_C_STRING_LOCATION(const char* expected, const char* actual, const char* fileName, int lineNumber)
-{
- UtestShell::getCurrent()->assertCstrEqual(expected, actual, fileName, lineNumber, TestTerminatorWithoutExceptions());
-}
-
-void FAIL_TEXT_C_LOCATION(const char* text, const char* fileName, int lineNumber)
-{
- UtestShell::getCurrent()->fail(text, fileName, lineNumber, TestTerminatorWithoutExceptions());
-}
-
-void FAIL_C_LOCATION(const char* fileName, int lineNumber)
-{
- UtestShell::getCurrent()->fail("", fileName, lineNumber, TestTerminatorWithoutExceptions());
-}
-
-void CHECK_C_LOCATION(int condition, const char* conditionString, const char* fileName, int lineNumber)
-{
- UtestShell::getCurrent()->assertTrue(condition != 0, "CHECK_C", conditionString, fileName, lineNumber, TestTerminatorWithoutExceptions());
-}
-
-enum { NO_COUNTDOWN = -1, OUT_OF_MEMORRY = 0 };
-static int malloc_out_of_memory_counter = NO_COUNTDOWN;
-static int malloc_count = 0;
-
-void cpputest_malloc_count_reset(void)
-{
- malloc_count = 0;
-}
-
-int cpputest_malloc_get_count()
-{
- return malloc_count;
-}
-
-void cpputest_malloc_set_out_of_memory()
-{
- setCurrentMallocAllocator(NullUnknownAllocator::defaultAllocator());
-}
-
-void cpputest_malloc_set_not_out_of_memory()
-{
- malloc_out_of_memory_counter = NO_COUNTDOWN;
- setCurrentMallocAllocatorToDefault();
-}
-
-void cpputest_malloc_set_out_of_memory_countdown(int count)
-{
- malloc_out_of_memory_counter = count;
- if (malloc_out_of_memory_counter == OUT_OF_MEMORRY)
- cpputest_malloc_set_out_of_memory();
-}
-
-void* cpputest_malloc(size_t size)
-{
- return cpputest_malloc_location(size, "<unknown>", 0);
-}
-
-void* cpputest_calloc(size_t num, size_t size)
-{
- return cpputest_calloc_location(num, size, "<unknown>", 0);
-}
-
-void* cpputest_realloc(void* ptr, size_t size)
-{
- return cpputest_realloc_location(ptr, size, "<unknown>", 0);
-}
-
-void cpputest_free(void* buffer)
-{
- cpputest_free_location(buffer, "<unknown>", 0);
-}
-
-static void countdown()
-{
- if (malloc_out_of_memory_counter <= NO_COUNTDOWN)
- return;
-
- if (malloc_out_of_memory_counter == OUT_OF_MEMORRY)
- return;
-
- malloc_out_of_memory_counter--;
-
- if (malloc_out_of_memory_counter == OUT_OF_MEMORRY)
- cpputest_malloc_set_out_of_memory();
-}
-
-void* cpputest_malloc_location(size_t size, const char* file, int line)
-{
- countdown();
- malloc_count++;
- return cpputest_malloc_location_with_leak_detection(size, file, line);
-}
-
-void* cpputest_calloc_location(size_t num, size_t size, const char* file, int line)
-{
- void* mem = cpputest_malloc_location(num * size, file, line);
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/MemoryLeakDetector.h"
+#include "CppUTest/TestMemoryAllocator.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+#include "CppUTest/TestHarness_c.h"
+
+extern "C"
+{
+
+
+void CHECK_EQUAL_C_INT_LOCATION(int expected, int actual, const char* fileName, int lineNumber)
+{
+ UtestShell::getCurrent()->assertLongsEqual((long)expected, (long)actual, fileName, lineNumber, TestTerminatorWithoutExceptions());
+}
+
+void CHECK_EQUAL_C_REAL_LOCATION(double expected, double actual, double threshold, const char* fileName, int lineNumber)
+{
+ UtestShell::getCurrent()->assertDoublesEqual(expected, actual, threshold, fileName, lineNumber, TestTerminatorWithoutExceptions());
+}
+
+void CHECK_EQUAL_C_CHAR_LOCATION(char expected, char actual, const char* fileName, int lineNumber)
+{
+ UtestShell::getCurrent()->assertEquals(((expected) != (actual)), StringFrom(expected).asCharString(), StringFrom(actual).asCharString(), fileName, lineNumber, TestTerminatorWithoutExceptions());
+}
+
+void CHECK_EQUAL_C_STRING_LOCATION(const char* expected, const char* actual, const char* fileName, int lineNumber)
+{
+ UtestShell::getCurrent()->assertCstrEqual(expected, actual, fileName, lineNumber, TestTerminatorWithoutExceptions());
+}
+
+void FAIL_TEXT_C_LOCATION(const char* text, const char* fileName, int lineNumber)
+{
+ UtestShell::getCurrent()->fail(text, fileName, lineNumber, TestTerminatorWithoutExceptions());
+}
+
+void FAIL_C_LOCATION(const char* fileName, int lineNumber)
+{
+ UtestShell::getCurrent()->fail("", fileName, lineNumber, TestTerminatorWithoutExceptions());
+}
+
+void CHECK_C_LOCATION(int condition, const char* conditionString, const char* fileName, int lineNumber)
+{
+ UtestShell::getCurrent()->assertTrue(condition != 0, "CHECK_C", conditionString, fileName, lineNumber, TestTerminatorWithoutExceptions());
+}
+
+enum { NO_COUNTDOWN = -1, OUT_OF_MEMORRY = 0 };
+static int malloc_out_of_memory_counter = NO_COUNTDOWN;
+static int malloc_count = 0;
+
+void cpputest_malloc_count_reset(void)
+{
+ malloc_count = 0;
+}
+
+int cpputest_malloc_get_count()
+{
+ return malloc_count;
+}
+
+void cpputest_malloc_set_out_of_memory()
+{
+ setCurrentMallocAllocator(NullUnknownAllocator::defaultAllocator());
+}
+
+void cpputest_malloc_set_not_out_of_memory()
+{
+ malloc_out_of_memory_counter = NO_COUNTDOWN;
+ setCurrentMallocAllocatorToDefault();
+}
+
+void cpputest_malloc_set_out_of_memory_countdown(int count)
+{
+ malloc_out_of_memory_counter = count;
+ if (malloc_out_of_memory_counter == OUT_OF_MEMORRY)
+ cpputest_malloc_set_out_of_memory();
+}
+
+void* cpputest_malloc(size_t size)
+{
+ return cpputest_malloc_location(size, "<unknown>", 0);
+}
+
+void* cpputest_calloc(size_t num, size_t size)
+{
+ return cpputest_calloc_location(num, size, "<unknown>", 0);
+}
+
+void* cpputest_realloc(void* ptr, size_t size)
+{
+ return cpputest_realloc_location(ptr, size, "<unknown>", 0);
+}
+
+void cpputest_free(void* buffer)
+{
+ cpputest_free_location(buffer, "<unknown>", 0);
+}
+
+static void countdown()
+{
+ if (malloc_out_of_memory_counter <= NO_COUNTDOWN)
+ return;
+
+ if (malloc_out_of_memory_counter == OUT_OF_MEMORRY)
+ return;
+
+ malloc_out_of_memory_counter--;
+
+ if (malloc_out_of_memory_counter == OUT_OF_MEMORRY)
+ cpputest_malloc_set_out_of_memory();
+}
+
+void* cpputest_malloc_location(size_t size, const char* file, int line)
+{
+ countdown();
+ malloc_count++;
+ return cpputest_malloc_location_with_leak_detection(size, file, line);
+}
+
+void* cpputest_calloc_location(size_t num, size_t size, const char* file, int line)
+{
+ void* mem = cpputest_malloc_location(num * size, file, line);
if (mem)
- PlatformSpecificMemset(mem, 0, num*size);
- return mem;
-}
-
-void* cpputest_realloc_location(void* memory, size_t size, const char* file, int line)
-{
- return cpputest_realloc_location_with_leak_detection(memory, size, file, line);
-}
-
-void cpputest_free_location(void* buffer, const char* file, int line)
-{
- cpputest_free_location_with_leak_detection(buffer, file, line);
-}
-
-}
+ PlatformSpecificMemset(mem, 0, num*size);
+ return mem;
+}
+
+void* cpputest_realloc_location(void* memory, size_t size, const char* file, int line)
+{
+ return cpputest_realloc_location_with_leak_detection(memory, size, file, line);
+}
+
+void cpputest_free_location(void* buffer, const char* file, int line)
+{
+ cpputest_free_location_with_leak_detection(buffer, file, line);
+}
+
+}
--- a/src/CppUTest/TestMemoryAllocator.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/TestMemoryAllocator.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,204 +1,204 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/TestMemoryAllocator.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-#include "CppUTest/MemoryLeakDetector.h"
-
-static char* checkedMalloc(size_t size)
-{
- char* mem = (char*) PlatformSpecificMalloc(size);
- if (mem == 0)
- FAIL("malloc returned null pointer");
- return mem;
-}
-
-static TestMemoryAllocator* currentNewAllocator = 0;
-static TestMemoryAllocator* currentNewArrayAllocator = 0;
-static TestMemoryAllocator* currentMallocAllocator = 0;
-
-void setCurrentNewAllocator(TestMemoryAllocator* allocator)
-{
- currentNewAllocator = allocator;
-}
-
-TestMemoryAllocator* getCurrentNewAllocator()
-{
- if (currentNewAllocator == 0) setCurrentNewAllocatorToDefault();
- return currentNewAllocator;
-}
-
-void setCurrentNewAllocatorToDefault()
-{
- currentNewAllocator = defaultNewAllocator();
-}
-
-TestMemoryAllocator* defaultNewAllocator()
-{
- static TestMemoryAllocator allocator("Standard New Allocator", "new", "delete");
- return &allocator;
-}
-
-void setCurrentNewArrayAllocator(TestMemoryAllocator* allocator)
-{
- currentNewArrayAllocator = allocator;
-}
-
-TestMemoryAllocator* getCurrentNewArrayAllocator()
-{
- if (currentNewArrayAllocator == 0) setCurrentNewArrayAllocatorToDefault();
- return currentNewArrayAllocator;
-}
-
-void setCurrentNewArrayAllocatorToDefault()
-{
- currentNewArrayAllocator = defaultNewArrayAllocator();
-}
-
-TestMemoryAllocator* defaultNewArrayAllocator()
-{
- static TestMemoryAllocator allocator("Standard New [] Allocator", "new []", "delete []");
- return &allocator;
-}
-
-void setCurrentMallocAllocator(TestMemoryAllocator* allocator)
-{
- currentMallocAllocator = allocator;
-}
-
-TestMemoryAllocator* getCurrentMallocAllocator()
-{
- if (currentMallocAllocator == 0) setCurrentMallocAllocatorToDefault();
- return currentMallocAllocator;
-}
-
-void setCurrentMallocAllocatorToDefault()
-{
- currentMallocAllocator = defaultMallocAllocator();
-}
-
-TestMemoryAllocator* defaultMallocAllocator()
-{
- static TestMemoryAllocator allocator("Standard Malloc Allocator", "malloc", "free");
- return &allocator;
-}
-
-/////////////////////////////////////////////
-
-TestMemoryAllocator::TestMemoryAllocator(const char* name_str, const char* alloc_name_str, const char* free_name_str)
- : name_(name_str), alloc_name_(alloc_name_str), free_name_(free_name_str), hasBeenDestroyed_(false)
-{
-}
-
-TestMemoryAllocator::~TestMemoryAllocator()
-{
- hasBeenDestroyed_ = true;
-}
-
-bool TestMemoryAllocator::hasBeenDestroyed()
-{
- return hasBeenDestroyed_;
-}
-
-bool TestMemoryAllocator::isOfEqualType(TestMemoryAllocator* allocator)
-{
- return PlatformSpecificStrCmp(this->name(), allocator->name()) == 0;
-}
-
-char* TestMemoryAllocator::allocMemoryLeakNode(size_t size)
-{
- return alloc_memory(size, "MemoryLeakNode", 1);
-}
-
-void TestMemoryAllocator::freeMemoryLeakNode(char* memory)
-{
- free_memory(memory, "MemoryLeakNode", 1);
-}
-
-char* TestMemoryAllocator::alloc_memory(size_t size, const char*, int)
-{
- return checkedMalloc(size);
-}
-
-void TestMemoryAllocator::free_memory(char* memory, const char*, int)
-{
- PlatformSpecificFree(memory);
-}
-const char* TestMemoryAllocator::name()
-{
- return name_;
-}
-
-const char* TestMemoryAllocator::alloc_name()
-{
- return alloc_name_;
-}
-
-const char* TestMemoryAllocator::free_name()
-{
- return free_name_;
-}
-
-CrashOnAllocationAllocator::CrashOnAllocationAllocator() : allocationToCrashOn_(0)
-{
-}
-
-void CrashOnAllocationAllocator::setNumberToCrashOn(unsigned allocationToCrashOn)
-{
- allocationToCrashOn_ = allocationToCrashOn;
-}
-
-char* CrashOnAllocationAllocator::alloc_memory(size_t size, const char* file, int line)
-{
- if (MemoryLeakWarningPlugin::getGlobalDetector()->getCurrentAllocationNumber() == allocationToCrashOn_)
- UT_CRASH();
-
- return TestMemoryAllocator::alloc_memory(size, file, line);
-}
-
-
-char* NullUnknownAllocator::alloc_memory(size_t /*size*/, const char*, int)
-{
- return 0;
-}
-
-void NullUnknownAllocator::free_memory(char* /*memory*/, const char*, int)
-{
-}
-
-NullUnknownAllocator::NullUnknownAllocator()
- : TestMemoryAllocator("Null Allocator", "unknown", "unknown")
-{
-}
-
-
-TestMemoryAllocator* NullUnknownAllocator::defaultAllocator()
-{
- static NullUnknownAllocator allocator;
- return &allocator;
-}
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/TestMemoryAllocator.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+#include "CppUTest/MemoryLeakDetector.h"
+
+static char* checkedMalloc(size_t size)
+{
+ char* mem = (char*) PlatformSpecificMalloc(size);
+ if (mem == 0)
+ FAIL("malloc returned null pointer");
+ return mem;
+}
+
+static TestMemoryAllocator* currentNewAllocator = 0;
+static TestMemoryAllocator* currentNewArrayAllocator = 0;
+static TestMemoryAllocator* currentMallocAllocator = 0;
+
+void setCurrentNewAllocator(TestMemoryAllocator* allocator)
+{
+ currentNewAllocator = allocator;
+}
+
+TestMemoryAllocator* getCurrentNewAllocator()
+{
+ if (currentNewAllocator == 0) setCurrentNewAllocatorToDefault();
+ return currentNewAllocator;
+}
+
+void setCurrentNewAllocatorToDefault()
+{
+ currentNewAllocator = defaultNewAllocator();
+}
+
+TestMemoryAllocator* defaultNewAllocator()
+{
+ static TestMemoryAllocator allocator("Standard New Allocator", "new", "delete");
+ return &allocator;
+}
+
+void setCurrentNewArrayAllocator(TestMemoryAllocator* allocator)
+{
+ currentNewArrayAllocator = allocator;
+}
+
+TestMemoryAllocator* getCurrentNewArrayAllocator()
+{
+ if (currentNewArrayAllocator == 0) setCurrentNewArrayAllocatorToDefault();
+ return currentNewArrayAllocator;
+}
+
+void setCurrentNewArrayAllocatorToDefault()
+{
+ currentNewArrayAllocator = defaultNewArrayAllocator();
+}
+
+TestMemoryAllocator* defaultNewArrayAllocator()
+{
+ static TestMemoryAllocator allocator("Standard New [] Allocator", "new []", "delete []");
+ return &allocator;
+}
+
+void setCurrentMallocAllocator(TestMemoryAllocator* allocator)
+{
+ currentMallocAllocator = allocator;
+}
+
+TestMemoryAllocator* getCurrentMallocAllocator()
+{
+ if (currentMallocAllocator == 0) setCurrentMallocAllocatorToDefault();
+ return currentMallocAllocator;
+}
+
+void setCurrentMallocAllocatorToDefault()
+{
+ currentMallocAllocator = defaultMallocAllocator();
+}
+
+TestMemoryAllocator* defaultMallocAllocator()
+{
+ static TestMemoryAllocator allocator("Standard Malloc Allocator", "malloc", "free");
+ return &allocator;
+}
+
+/////////////////////////////////////////////
+
+TestMemoryAllocator::TestMemoryAllocator(const char* name_str, const char* alloc_name_str, const char* free_name_str)
+ : name_(name_str), alloc_name_(alloc_name_str), free_name_(free_name_str), hasBeenDestroyed_(false)
+{
+}
+
+TestMemoryAllocator::~TestMemoryAllocator()
+{
+ hasBeenDestroyed_ = true;
+}
+
+bool TestMemoryAllocator::hasBeenDestroyed()
+{
+ return hasBeenDestroyed_;
+}
+
+bool TestMemoryAllocator::isOfEqualType(TestMemoryAllocator* allocator)
+{
+ return PlatformSpecificStrCmp(this->name(), allocator->name()) == 0;
+}
+
+char* TestMemoryAllocator::allocMemoryLeakNode(size_t size)
+{
+ return alloc_memory(size, "MemoryLeakNode", 1);
+}
+
+void TestMemoryAllocator::freeMemoryLeakNode(char* memory)
+{
+ free_memory(memory, "MemoryLeakNode", 1);
+}
+
+char* TestMemoryAllocator::alloc_memory(size_t size, const char*, int)
+{
+ return checkedMalloc(size);
+}
+
+void TestMemoryAllocator::free_memory(char* memory, const char*, int)
+{
+ PlatformSpecificFree(memory);
+}
+const char* TestMemoryAllocator::name()
+{
+ return name_;
+}
+
+const char* TestMemoryAllocator::alloc_name()
+{
+ return alloc_name_;
+}
+
+const char* TestMemoryAllocator::free_name()
+{
+ return free_name_;
+}
+
+CrashOnAllocationAllocator::CrashOnAllocationAllocator() : allocationToCrashOn_(0)
+{
+}
+
+void CrashOnAllocationAllocator::setNumberToCrashOn(unsigned allocationToCrashOn)
+{
+ allocationToCrashOn_ = allocationToCrashOn;
+}
+
+char* CrashOnAllocationAllocator::alloc_memory(size_t size, const char* file, int line)
+{
+ if (MemoryLeakWarningPlugin::getGlobalDetector()->getCurrentAllocationNumber() == allocationToCrashOn_)
+ UT_CRASH();
+
+ return TestMemoryAllocator::alloc_memory(size, file, line);
+}
+
+
+char* NullUnknownAllocator::alloc_memory(size_t /*size*/, const char*, int)
+{
+ return 0;
+}
+
+void NullUnknownAllocator::free_memory(char* /*memory*/, const char*, int)
+{
+}
+
+NullUnknownAllocator::NullUnknownAllocator()
+ : TestMemoryAllocator("Null Allocator", "unknown", "unknown")
+{
+}
+
+
+TestMemoryAllocator* NullUnknownAllocator::defaultAllocator()
+{
+ static NullUnknownAllocator allocator;
+ return &allocator;
+}
--- a/src/CppUTest/TestOutput.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/TestOutput.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,253 +1,253 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/TestOutput.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-
-TestOutput::WorkingEnvironment TestOutput::workingEnvironment_ = TestOutput::detectEnvironment;
-
-void TestOutput::setWorkingEnvironment(TestOutput::WorkingEnvironment workEnvironment)
-{
- workingEnvironment_ = workEnvironment;
-}
-
-TestOutput::WorkingEnvironment TestOutput::getWorkingEnvironment()
-{
- if (workingEnvironment_ == TestOutput::detectEnvironment)
- return PlatformSpecificGetWorkingEnvironment();
- return workingEnvironment_;
-}
-
-
-TestOutput::TestOutput() :
- dotCount_(0), verbose_(false), progressIndication_(".")
-{
-}
-
-TestOutput::~TestOutput()
-{
-}
-
-void TestOutput::verbose()
-{
- verbose_ = true;
-}
-
-void TestOutput::print(const char* str)
-{
- printBuffer(str);
-}
-
-void TestOutput::print(long n)
-{
- print(StringFrom(n).asCharString());
-}
-
-void TestOutput::printDouble(double d)
-{
- print(StringFrom(d).asCharString());
-}
-
-void TestOutput::printHex(long n)
-{
- print(HexStringFrom(n).asCharString());
-}
-
-TestOutput& operator<<(TestOutput& p, const char* s)
-{
- p.print(s);
- return p;
-}
-
-TestOutput& operator<<(TestOutput& p, long int i)
-{
- p.print(i);
- return p;
-}
-
-void TestOutput::printCurrentTestStarted(const UtestShell& test)
-{
- if (verbose_) print(test.getFormattedName().asCharString());
-}
-
-void TestOutput::printCurrentTestEnded(const TestResult& res)
-{
- if (verbose_) {
- print(" - ");
- print(res.getCurrentTestTotalExecutionTime());
- print(" ms\n");
- }
- else {
- printProgressIndicator();
- }
-}
-
-void TestOutput::printProgressIndicator()
-{
- print(progressIndication_);
- if (++dotCount_ % 50 == 0) print("\n");
-}
-
-void TestOutput::setProgressIndicator(const char* indicator)
-{
- progressIndication_ = indicator;
-}
-
-void TestOutput::printTestsStarted()
-{
-}
-
-void TestOutput::printCurrentGroupStarted(const UtestShell& /*test*/)
-{
-}
-
-void TestOutput::printCurrentGroupEnded(const TestResult& /*res*/)
-{
-}
-
-void TestOutput::flush()
-{
-}
-
-void TestOutput::printTestsEnded(const TestResult& result)
-{
- if (result.getFailureCount() > 0) {
- print("\nErrors (");
- print(result.getFailureCount());
- print(" failures, ");
- }
- else {
- print("\nOK (");
- }
- print(result.getTestCount());
- print(" tests, ");
- print(result.getRunCount());
- print(" ran, ");
- print(result.getCheckCount());
- print(" checks, ");
- print(result.getIgnoredCount());
- print(" ignored, ");
- print(result.getFilteredOutCount());
- print(" filtered out, ");
- print(result.getTotalExecutionTime());
- print(" ms)\n\n");
-}
-
-void TestOutput::printTestRun(int number, int total)
-{
- if (total > 1) {
- print("Test run ");
- print(number);
- print(" of ");
- print(total);
- print("\n");
- }
-}
-
-void TestOutput::print(const TestFailure& failure)
-{
- if (failure.isOutsideTestFile() || failure.isInHelperFunction())
- printFileAndLineForTestAndFailure(failure);
- else
- printFileAndLineForFailure(failure);
-
- printFailureMessage(failure.getMessage());
-}
-
-void TestOutput::printFileAndLineForTestAndFailure(const TestFailure& failure)
-{
- printErrorInFileOnLineFormattedForWorkingEnvironment(failure.getTestFileName(), failure.getTestLineNumber());
- printFailureInTest(failure.getTestName());
- printErrorInFileOnLineFormattedForWorkingEnvironment(failure.getFileName(), failure.getFailureLineNumber());
-}
-
-void TestOutput::printFileAndLineForFailure(const TestFailure& failure)
-{
- printErrorInFileOnLineFormattedForWorkingEnvironment(failure.getFileName(), failure.getFailureLineNumber());
- printFailureInTest(failure.getTestName());
-}
-
-void TestOutput::printFailureInTest(SimpleString testName)
-{
- print(" Failure in ");
- print(testName.asCharString());
-}
-
-void TestOutput::printFailureMessage(SimpleString reason)
-{
- print("\n");
- print("\t");
- print(reason.asCharString());
- print("\n\n");
-}
-
-void TestOutput::printErrorInFileOnLineFormattedForWorkingEnvironment(SimpleString file, int lineNumber)
-{
- if (TestOutput::getWorkingEnvironment() == TestOutput::vistualStudio)
- printVistualStudioErrorInFileOnLine(file, lineNumber);
- else
- printEclipseErrorInFileOnLine(file, lineNumber);
-}
-
-void TestOutput::printEclipseErrorInFileOnLine(SimpleString file, int lineNumber)
-{
- print("\n");
- print(file.asCharString());
- print(":");
- print(lineNumber);
- print(":");
- print(" error:");
-}
-
-void TestOutput::printVistualStudioErrorInFileOnLine(SimpleString file, int lineNumber)
-{
- print("\n");
- print(file.asCharString());
- print("(");
- print(lineNumber);
- print("):");
- print(" error:");
-}
-
-void ConsoleTestOutput::printBuffer(const char* s)
-{
- while (*s) {
- PlatformSpecificPutchar(*s);
- s++;
- }
- flush();
-}
-
-void ConsoleTestOutput::flush()
-{
- PlatformSpecificFlush();
-}
-
-StringBufferTestOutput::~StringBufferTestOutput()
-{
-}
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/TestOutput.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+
+TestOutput::WorkingEnvironment TestOutput::workingEnvironment_ = TestOutput::detectEnvironment;
+
+void TestOutput::setWorkingEnvironment(TestOutput::WorkingEnvironment workEnvironment)
+{
+ workingEnvironment_ = workEnvironment;
+}
+
+TestOutput::WorkingEnvironment TestOutput::getWorkingEnvironment()
+{
+ if (workingEnvironment_ == TestOutput::detectEnvironment)
+ return PlatformSpecificGetWorkingEnvironment();
+ return workingEnvironment_;
+}
+
+
+TestOutput::TestOutput() :
+ dotCount_(0), verbose_(false), progressIndication_(".")
+{
+}
+
+TestOutput::~TestOutput()
+{
+}
+
+void TestOutput::verbose()
+{
+ verbose_ = true;
+}
+
+void TestOutput::print(const char* str)
+{
+ printBuffer(str);
+}
+
+void TestOutput::print(long n)
+{
+ print(StringFrom(n).asCharString());
+}
+
+void TestOutput::printDouble(double d)
+{
+ print(StringFrom(d).asCharString());
+}
+
+void TestOutput::printHex(long n)
+{
+ print(HexStringFrom(n).asCharString());
+}
+
+TestOutput& operator<<(TestOutput& p, const char* s)
+{
+ p.print(s);
+ return p;
+}
+
+TestOutput& operator<<(TestOutput& p, long int i)
+{
+ p.print(i);
+ return p;
+}
+
+void TestOutput::printCurrentTestStarted(const UtestShell& test)
+{
+ if (verbose_) print(test.getFormattedName().asCharString());
+}
+
+void TestOutput::printCurrentTestEnded(const TestResult& res)
+{
+ if (verbose_) {
+ print(" - ");
+ print(res.getCurrentTestTotalExecutionTime());
+ print(" ms\n");
+ }
+ else {
+ printProgressIndicator();
+ }
+}
+
+void TestOutput::printProgressIndicator()
+{
+ print(progressIndication_);
+ if (++dotCount_ % 50 == 0) print("\n");
+}
+
+void TestOutput::setProgressIndicator(const char* indicator)
+{
+ progressIndication_ = indicator;
+}
+
+void TestOutput::printTestsStarted()
+{
+}
+
+void TestOutput::printCurrentGroupStarted(const UtestShell& /*test*/)
+{
+}
+
+void TestOutput::printCurrentGroupEnded(const TestResult& /*res*/)
+{
+}
+
+void TestOutput::flush()
+{
+}
+
+void TestOutput::printTestsEnded(const TestResult& result)
+{
+ if (result.getFailureCount() > 0) {
+ print("\nErrors (");
+ print(result.getFailureCount());
+ print(" failures, ");
+ }
+ else {
+ print("\nOK (");
+ }
+ print(result.getTestCount());
+ print(" tests, ");
+ print(result.getRunCount());
+ print(" ran, ");
+ print(result.getCheckCount());
+ print(" checks, ");
+ print(result.getIgnoredCount());
+ print(" ignored, ");
+ print(result.getFilteredOutCount());
+ print(" filtered out, ");
+ print(result.getTotalExecutionTime());
+ print(" ms)\n\n");
+}
+
+void TestOutput::printTestRun(int number, int total)
+{
+ if (total > 1) {
+ print("Test run ");
+ print(number);
+ print(" of ");
+ print(total);
+ print("\n");
+ }
+}
+
+void TestOutput::print(const TestFailure& failure)
+{
+ if (failure.isOutsideTestFile() || failure.isInHelperFunction())
+ printFileAndLineForTestAndFailure(failure);
+ else
+ printFileAndLineForFailure(failure);
+
+ printFailureMessage(failure.getMessage());
+}
+
+void TestOutput::printFileAndLineForTestAndFailure(const TestFailure& failure)
+{
+ printErrorInFileOnLineFormattedForWorkingEnvironment(failure.getTestFileName(), failure.getTestLineNumber());
+ printFailureInTest(failure.getTestName());
+ printErrorInFileOnLineFormattedForWorkingEnvironment(failure.getFileName(), failure.getFailureLineNumber());
+}
+
+void TestOutput::printFileAndLineForFailure(const TestFailure& failure)
+{
+ printErrorInFileOnLineFormattedForWorkingEnvironment(failure.getFileName(), failure.getFailureLineNumber());
+ printFailureInTest(failure.getTestName());
+}
+
+void TestOutput::printFailureInTest(SimpleString testName)
+{
+ print(" Failure in ");
+ print(testName.asCharString());
+}
+
+void TestOutput::printFailureMessage(SimpleString reason)
+{
+ print("\n");
+ print("\t");
+ print(reason.asCharString());
+ print("\n\n");
+}
+
+void TestOutput::printErrorInFileOnLineFormattedForWorkingEnvironment(SimpleString file, int lineNumber)
+{
+ if (TestOutput::getWorkingEnvironment() == TestOutput::vistualStudio)
+ printVistualStudioErrorInFileOnLine(file, lineNumber);
+ else
+ printEclipseErrorInFileOnLine(file, lineNumber);
+}
+
+void TestOutput::printEclipseErrorInFileOnLine(SimpleString file, int lineNumber)
+{
+ print("\n");
+ print(file.asCharString());
+ print(":");
+ print(lineNumber);
+ print(":");
+ print(" error:");
+}
+
+void TestOutput::printVistualStudioErrorInFileOnLine(SimpleString file, int lineNumber)
+{
+ print("\n");
+ print(file.asCharString());
+ print("(");
+ print(lineNumber);
+ print("):");
+ print(" error:");
+}
+
+void ConsoleTestOutput::printBuffer(const char* s)
+{
+ while (*s) {
+ PlatformSpecificPutchar(*s);
+ s++;
+ }
+ flush();
+}
+
+void ConsoleTestOutput::flush()
+{
+ PlatformSpecificFlush();
+}
+
+StringBufferTestOutput::~StringBufferTestOutput()
+{
+}
--- a/src/CppUTest/TestPlugin.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/TestPlugin.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,173 +1,173 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/TestPlugin.h"
-
-TestPlugin::TestPlugin(const SimpleString& name) :
- next_(NullTestPlugin::instance()), name_(name), enabled_(true)
-{
-}
-
-TestPlugin::TestPlugin(TestPlugin* next) :
- next_(next), name_("null"), enabled_(true)
-{
-}
-
-TestPlugin::~TestPlugin()
-{
-}
-
-TestPlugin* TestPlugin::addPlugin(TestPlugin* plugin)
-{
- next_ = plugin;
- return this;
-}
-
-void TestPlugin::runAllPreTestAction(UtestShell& test, TestResult& result)
-{
- if (enabled_) preTestAction(test, result);
- next_->runAllPreTestAction(test, result);
-}
-
-void TestPlugin::runAllPostTestAction(UtestShell& test, TestResult& result)
-{
- next_ ->runAllPostTestAction(test, result);
- if (enabled_) postTestAction(test, result);
-}
-
-bool TestPlugin::parseAllArguments(int ac, char** av, int index)
-{
- return parseAllArguments(ac, const_cast<const char**> (av), index);
-}
-
-bool TestPlugin::parseAllArguments(int ac, const char** av, int index)
-{
- if (parseArguments(ac, av, index)) return true;
- if (next_) return next_->parseAllArguments(ac, av, index);
- return false;
-}
-
-const SimpleString& TestPlugin::getName()
-{
- return name_;
-}
-
-TestPlugin* TestPlugin::getPluginByName(const SimpleString& name)
-{
- if (name == name_) return this;
- if (next_) return next_->getPluginByName(name);
- return (next_);
-}
-
-TestPlugin* TestPlugin::getNext()
-{
- return next_;
-}
-TestPlugin* TestPlugin::removePluginByName(const SimpleString& name)
-{
- TestPlugin* removed = 0;
- if (next_ && next_->getName() == name) {
- removed = next_;
- next_ = next_->next_;
- }
- return removed;
-}
-
-void TestPlugin::disable()
-{
- enabled_ = false;
-}
-
-void TestPlugin::enable()
-{
- enabled_ = true;
-}
-
-bool TestPlugin::isEnabled()
-{
- return enabled_;
-}
-
-struct cpputest_pair
-{
- void **orig;
- void *orig_value;
-};
-
-//////// SetPlugin
-
-static int pointerTableIndex;
-static cpputest_pair setlist[SetPointerPlugin::MAX_SET];
-
-SetPointerPlugin::SetPointerPlugin(const SimpleString& name) :
- TestPlugin(name)
-{
- pointerTableIndex = 0;
-}
-
-SetPointerPlugin::~SetPointerPlugin()
-{
-}
-
-void CppUTestStore(void**function)
-{
- if (pointerTableIndex >= SetPointerPlugin::MAX_SET) {
- FAIL("Maximum number of function pointers installed!");
- }
- setlist[pointerTableIndex].orig_value = *function;
- setlist[pointerTableIndex].orig = function;
- pointerTableIndex++;
-}
-
-void SetPointerPlugin::postTestAction(UtestShell& /*test*/, TestResult& /*result*/)
-{
- for (int i = pointerTableIndex - 1; i >= 0; i--)
- *((void**) setlist[i].orig) = setlist[i].orig_value;
- pointerTableIndex = 0;
-}
-
-//////// NullPlugin
-
-NullTestPlugin::NullTestPlugin() :
- TestPlugin(0)
-{
-}
-
-NullTestPlugin* NullTestPlugin::instance()
-{
- static NullTestPlugin _instance;
- return &_instance;
-}
-
-void NullTestPlugin::runAllPreTestAction(UtestShell&, TestResult&)
-{
-}
-
-void NullTestPlugin::runAllPostTestAction(UtestShell&, TestResult&)
-{
-}
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/TestPlugin.h"
+
+TestPlugin::TestPlugin(const SimpleString& name) :
+ next_(NullTestPlugin::instance()), name_(name), enabled_(true)
+{
+}
+
+TestPlugin::TestPlugin(TestPlugin* next) :
+ next_(next), name_("null"), enabled_(true)
+{
+}
+
+TestPlugin::~TestPlugin()
+{
+}
+
+TestPlugin* TestPlugin::addPlugin(TestPlugin* plugin)
+{
+ next_ = plugin;
+ return this;
+}
+
+void TestPlugin::runAllPreTestAction(UtestShell& test, TestResult& result)
+{
+ if (enabled_) preTestAction(test, result);
+ next_->runAllPreTestAction(test, result);
+}
+
+void TestPlugin::runAllPostTestAction(UtestShell& test, TestResult& result)
+{
+ next_ ->runAllPostTestAction(test, result);
+ if (enabled_) postTestAction(test, result);
+}
+
+bool TestPlugin::parseAllArguments(int ac, char** av, int index)
+{
+ return parseAllArguments(ac, const_cast<const char**> (av), index);
+}
+
+bool TestPlugin::parseAllArguments(int ac, const char** av, int index)
+{
+ if (parseArguments(ac, av, index)) return true;
+ if (next_) return next_->parseAllArguments(ac, av, index);
+ return false;
+}
+
+const SimpleString& TestPlugin::getName()
+{
+ return name_;
+}
+
+TestPlugin* TestPlugin::getPluginByName(const SimpleString& name)
+{
+ if (name == name_) return this;
+ if (next_) return next_->getPluginByName(name);
+ return (next_);
+}
+
+TestPlugin* TestPlugin::getNext()
+{
+ return next_;
+}
+TestPlugin* TestPlugin::removePluginByName(const SimpleString& name)
+{
+ TestPlugin* removed = 0;
+ if (next_ && next_->getName() == name) {
+ removed = next_;
+ next_ = next_->next_;
+ }
+ return removed;
+}
+
+void TestPlugin::disable()
+{
+ enabled_ = false;
+}
+
+void TestPlugin::enable()
+{
+ enabled_ = true;
+}
+
+bool TestPlugin::isEnabled()
+{
+ return enabled_;
+}
+
+struct cpputest_pair
+{
+ void **orig;
+ void *orig_value;
+};
+
+//////// SetPlugin
+
+static int pointerTableIndex;
+static cpputest_pair setlist[SetPointerPlugin::MAX_SET];
+
+SetPointerPlugin::SetPointerPlugin(const SimpleString& name) :
+ TestPlugin(name)
+{
+ pointerTableIndex = 0;
+}
+
+SetPointerPlugin::~SetPointerPlugin()
+{
+}
+
+void CppUTestStore(void**function)
+{
+ if (pointerTableIndex >= SetPointerPlugin::MAX_SET) {
+ FAIL("Maximum number of function pointers installed!");
+ }
+ setlist[pointerTableIndex].orig_value = *function;
+ setlist[pointerTableIndex].orig = function;
+ pointerTableIndex++;
+}
+
+void SetPointerPlugin::postTestAction(UtestShell& /*test*/, TestResult& /*result*/)
+{
+ for (int i = pointerTableIndex - 1; i >= 0; i--)
+ *((void**) setlist[i].orig) = setlist[i].orig_value;
+ pointerTableIndex = 0;
+}
+
+//////// NullPlugin
+
+NullTestPlugin::NullTestPlugin() :
+ TestPlugin(0)
+{
+}
+
+NullTestPlugin* NullTestPlugin::instance()
+{
+ static NullTestPlugin _instance;
+ return &_instance;
+}
+
+void NullTestPlugin::runAllPreTestAction(UtestShell&, TestResult&)
+{
+}
+
+void NullTestPlugin::runAllPostTestAction(UtestShell&, TestResult&)
+{
+}
--- a/src/CppUTest/TestRegistry.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/TestRegistry.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,216 +1,216 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/TestRegistry.h"
-
-TestRegistry::TestRegistry() :
- tests_(&NullTestShell::instance()), firstPlugin_(NullTestPlugin::instance()), runInSeperateProcess_(false)
-{
-}
-
-TestRegistry::~TestRegistry()
-{
-}
-
-void TestRegistry::addTest(UtestShell *test)
-{
- tests_ = test->addTest(tests_);
-}
-
-void TestRegistry::runAllTests(TestResult& result)
-{
- bool groupStart = true;
-
- result.testsStarted();
- for (UtestShell *test = tests_; !test->isNull(); test = test->getNext()) {
- if (runInSeperateProcess_) test->setRunInSeperateProcess();
-
- if (groupStart) {
- result.currentGroupStarted(test);
- groupStart = false;
- }
-
- result.setProgressIndicator(test->getProgressIndicator());
- result.countTest();
- if (testShouldRun(test, result)) {
- result.currentTestStarted(test);
- test->runOneTest(firstPlugin_, result);
- result.currentTestEnded(test);
- }
-
- if (endOfGroup(test)) {
- groupStart = true;
- result.currentGroupEnded(test);
- }
- }
- result.testsEnded();
-}
-
-bool TestRegistry::endOfGroup(UtestShell* test)
-{
- return (test->isNull() || test->getGroup() != test->getNext()->getGroup());
-}
-
-int TestRegistry::countTests()
-{
- return tests_->countTests();
-}
-
-TestRegistry* TestRegistry::currentRegistry_ = 0;
-
-TestRegistry* TestRegistry::getCurrentRegistry()
-{
- static TestRegistry registry;
- return (currentRegistry_ == 0) ? ®istry : currentRegistry_;
-}
-
-void TestRegistry::setCurrentRegistry(TestRegistry* registry)
-{
- currentRegistry_ = registry;
-}
-
-void TestRegistry::unDoLastAddTest()
-{
- tests_ = tests_->getNext();
-
-}
-
-void TestRegistry::nameFilter(const TestFilter& f)
-{
- nameFilter_ = f;
-}
-
-void TestRegistry::groupFilter(const TestFilter& f)
-{
- groupFilter_ = f;
-}
-
-TestFilter TestRegistry::getGroupFilter()
-{
- return groupFilter_;
-}
-
-TestFilter TestRegistry::getNameFilter()
-{
- return nameFilter_;
-}
-
-void TestRegistry::setRunTestsInSeperateProcess()
-{
- runInSeperateProcess_ = true;
-}
-
-
-bool TestRegistry::testShouldRun(UtestShell* test, TestResult& result)
-{
- if (test->shouldRun(groupFilter_, nameFilter_)) return true;
- else {
- result.countFilteredOut();
- return false;
- }
-}
-
-void TestRegistry::resetPlugins()
-{
- firstPlugin_ = NullTestPlugin::instance();
-}
-
-void TestRegistry::installPlugin(TestPlugin* plugin)
-{
- firstPlugin_ = plugin->addPlugin(firstPlugin_);
-}
-
-TestPlugin* TestRegistry::getFirstPlugin()
-{
- return firstPlugin_;
-}
-
-TestPlugin* TestRegistry::getPluginByName(const SimpleString& name)
-{
- return firstPlugin_->getPluginByName(name);
-}
-
-void TestRegistry::removePluginByName(const SimpleString& name)
-{
- if (firstPlugin_->removePluginByName(name) == firstPlugin_) firstPlugin_ = firstPlugin_->getNext();
- if (firstPlugin_->getName() == name) firstPlugin_ = firstPlugin_->getNext();
- firstPlugin_->removePluginByName(name);
-}
-
-int TestRegistry::countPlugins()
-{
- int count = 0;
- for (TestPlugin* plugin = firstPlugin_; plugin != NullTestPlugin::instance(); plugin = plugin->getNext())
- count++;
- return count;
-}
-
-
-UtestShell* TestRegistry::getFirstTest()
-{
- return tests_;
-}
-
-UtestShell* TestRegistry::getLastTest()
-{
- UtestShell* current = tests_;
- while (!current->getNext()->isNull())
- current = current->getNext();
- return current;
-}
-
-UtestShell* TestRegistry::getTestWithNext(UtestShell* test)
-{
- UtestShell* current = tests_;
- while (!current->getNext()->isNull() && current->getNext() != test)
- current = current->getNext();
- return current;
-}
-
-UtestShell* TestRegistry::findTestWithName(const SimpleString& name)
-{
- UtestShell* current = tests_;
- while (!current->isNull()) {
- if (current->getName() == name)
- return current;
- current = current->getNext();
- }
- return NULL;
-}
-
-UtestShell* TestRegistry::findTestWithGroup(const SimpleString& group)
-{
- UtestShell* current = tests_;
- while (!current->isNull()) {
- if (current->getGroup() == group)
- return current;
- current = current->getNext();
- }
- return NULL;
-}
-
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/TestRegistry.h"
+
+TestRegistry::TestRegistry() :
+ tests_(&NullTestShell::instance()), firstPlugin_(NullTestPlugin::instance()), runInSeperateProcess_(false)
+{
+}
+
+TestRegistry::~TestRegistry()
+{
+}
+
+void TestRegistry::addTest(UtestShell *test)
+{
+ tests_ = test->addTest(tests_);
+}
+
+void TestRegistry::runAllTests(TestResult& result)
+{
+ bool groupStart = true;
+
+ result.testsStarted();
+ for (UtestShell *test = tests_; !test->isNull(); test = test->getNext()) {
+ if (runInSeperateProcess_) test->setRunInSeperateProcess();
+
+ if (groupStart) {
+ result.currentGroupStarted(test);
+ groupStart = false;
+ }
+
+ result.setProgressIndicator(test->getProgressIndicator());
+ result.countTest();
+ if (testShouldRun(test, result)) {
+ result.currentTestStarted(test);
+ test->runOneTest(firstPlugin_, result);
+ result.currentTestEnded(test);
+ }
+
+ if (endOfGroup(test)) {
+ groupStart = true;
+ result.currentGroupEnded(test);
+ }
+ }
+ result.testsEnded();
+}
+
+bool TestRegistry::endOfGroup(UtestShell* test)
+{
+ return (test->isNull() || test->getGroup() != test->getNext()->getGroup());
+}
+
+int TestRegistry::countTests()
+{
+ return tests_->countTests();
+}
+
+TestRegistry* TestRegistry::currentRegistry_ = 0;
+
+TestRegistry* TestRegistry::getCurrentRegistry()
+{
+ static TestRegistry registry;
+ return (currentRegistry_ == 0) ? ®istry : currentRegistry_;
+}
+
+void TestRegistry::setCurrentRegistry(TestRegistry* registry)
+{
+ currentRegistry_ = registry;
+}
+
+void TestRegistry::unDoLastAddTest()
+{
+ tests_ = tests_->getNext();
+
+}
+
+void TestRegistry::nameFilter(const TestFilter& f)
+{
+ nameFilter_ = f;
+}
+
+void TestRegistry::groupFilter(const TestFilter& f)
+{
+ groupFilter_ = f;
+}
+
+TestFilter TestRegistry::getGroupFilter()
+{
+ return groupFilter_;
+}
+
+TestFilter TestRegistry::getNameFilter()
+{
+ return nameFilter_;
+}
+
+void TestRegistry::setRunTestsInSeperateProcess()
+{
+ runInSeperateProcess_ = true;
+}
+
+
+bool TestRegistry::testShouldRun(UtestShell* test, TestResult& result)
+{
+ if (test->shouldRun(groupFilter_, nameFilter_)) return true;
+ else {
+ result.countFilteredOut();
+ return false;
+ }
+}
+
+void TestRegistry::resetPlugins()
+{
+ firstPlugin_ = NullTestPlugin::instance();
+}
+
+void TestRegistry::installPlugin(TestPlugin* plugin)
+{
+ firstPlugin_ = plugin->addPlugin(firstPlugin_);
+}
+
+TestPlugin* TestRegistry::getFirstPlugin()
+{
+ return firstPlugin_;
+}
+
+TestPlugin* TestRegistry::getPluginByName(const SimpleString& name)
+{
+ return firstPlugin_->getPluginByName(name);
+}
+
+void TestRegistry::removePluginByName(const SimpleString& name)
+{
+ if (firstPlugin_->removePluginByName(name) == firstPlugin_) firstPlugin_ = firstPlugin_->getNext();
+ if (firstPlugin_->getName() == name) firstPlugin_ = firstPlugin_->getNext();
+ firstPlugin_->removePluginByName(name);
+}
+
+int TestRegistry::countPlugins()
+{
+ int count = 0;
+ for (TestPlugin* plugin = firstPlugin_; plugin != NullTestPlugin::instance(); plugin = plugin->getNext())
+ count++;
+ return count;
+}
+
+
+UtestShell* TestRegistry::getFirstTest()
+{
+ return tests_;
+}
+
+UtestShell* TestRegistry::getLastTest()
+{
+ UtestShell* current = tests_;
+ while (!current->getNext()->isNull())
+ current = current->getNext();
+ return current;
+}
+
+UtestShell* TestRegistry::getTestWithNext(UtestShell* test)
+{
+ UtestShell* current = tests_;
+ while (!current->getNext()->isNull() && current->getNext() != test)
+ current = current->getNext();
+ return current;
+}
+
+UtestShell* TestRegistry::findTestWithName(const SimpleString& name)
+{
+ UtestShell* current = tests_;
+ while (!current->isNull()) {
+ if (current->getName() == name)
+ return current;
+ current = current->getNext();
+ }
+ return NULL;
+}
+
+UtestShell* TestRegistry::findTestWithGroup(const SimpleString& group)
+{
+ UtestShell* current = tests_;
+ while (!current->isNull()) {
+ if (current->getGroup() == group)
+ return current;
+ current = current->getNext();
+ }
+ return NULL;
+}
+
--- a/src/CppUTest/TestResult.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/TestResult.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -1,142 +1,142 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/TestResult.h"
-#include "CppUTest/TestFailure.h"
-#include "CppUTest/TestOutput.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-
-TestResult::TestResult(TestOutput& p) :
- output_(p), testCount_(0), runCount_(0), checkCount_(0), failureCount_(0), filteredOutCount_(0), ignoredCount_(0), totalExecutionTime_(0), timeStarted_(0), currentTestTimeStarted_(0),
- currentTestTotalExecutionTime_(0), currentGroupTimeStarted_(0), currentGroupTotalExecutionTime_(0)
-{
-}
-
-void TestResult::setProgressIndicator(const char* indicator)
-{
- output_.setProgressIndicator(indicator);
-}
-
-TestResult::~TestResult()
-{
-}
-
-void TestResult::currentGroupStarted(UtestShell* test)
-{
- output_.printCurrentGroupStarted(*test);
- currentGroupTimeStarted_ = GetPlatformSpecificTimeInMillis();
-}
-
-void TestResult::currentGroupEnded(UtestShell* /*test*/)
-{
- currentGroupTotalExecutionTime_ = GetPlatformSpecificTimeInMillis() - currentGroupTimeStarted_;
- output_.printCurrentGroupEnded(*this);
-}
-
-void TestResult::currentTestStarted(UtestShell* test)
-{
- output_.printCurrentTestStarted(*test);
- currentTestTimeStarted_ = GetPlatformSpecificTimeInMillis();
-}
-
-void TestResult::print(const char* text)
-{
- output_.print(text);
-}
-
-void TestResult::currentTestEnded(UtestShell* /*test*/)
-{
- currentTestTotalExecutionTime_ = GetPlatformSpecificTimeInMillis() - currentTestTimeStarted_;
- output_.printCurrentTestEnded(*this);
-
-}
-
-void TestResult::addFailure(const TestFailure& failure)
-{
- output_.print(failure);
- failureCount_++;
-}
-
-void TestResult::countTest()
-{
- testCount_++;
-}
-
-void TestResult::countRun()
-{
- runCount_++;
-}
-
-void TestResult::countCheck()
-{
- checkCount_++;
-}
-
-void TestResult::countFilteredOut()
-{
- filteredOutCount_++;
-}
-
-void TestResult::countIgnored()
-{
- ignoredCount_++;
-}
-
-void TestResult::testsStarted()
-{
- timeStarted_ = GetPlatformSpecificTimeInMillis();
- output_.printTestsStarted();
-}
-
-void TestResult::testsEnded()
-{
- long timeEnded = GetPlatformSpecificTimeInMillis();
- totalExecutionTime_ = timeEnded - timeStarted_;
- output_.printTestsEnded(*this);
-}
-
-long TestResult::getTotalExecutionTime() const
-{
- return totalExecutionTime_;
-}
-
-void TestResult::setTotalExecutionTime(long exTime)
-{
- totalExecutionTime_ = exTime;
-}
-
-long TestResult::getCurrentTestTotalExecutionTime() const
-{
- return currentTestTotalExecutionTime_;
-}
-
-long TestResult::getCurrentGroupTotalExecutionTime() const
-{
- return currentGroupTotalExecutionTime_;
-}
-
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/TestResult.h"
+#include "CppUTest/TestFailure.h"
+#include "CppUTest/TestOutput.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+
+TestResult::TestResult(TestOutput& p) :
+ output_(p), testCount_(0), runCount_(0), checkCount_(0), failureCount_(0), filteredOutCount_(0), ignoredCount_(0), totalExecutionTime_(0), timeStarted_(0), currentTestTimeStarted_(0),
+ currentTestTotalExecutionTime_(0), currentGroupTimeStarted_(0), currentGroupTotalExecutionTime_(0)
+{
+}
+
+void TestResult::setProgressIndicator(const char* indicator)
+{
+ output_.setProgressIndicator(indicator);
+}
+
+TestResult::~TestResult()
+{
+}
+
+void TestResult::currentGroupStarted(UtestShell* test)
+{
+ output_.printCurrentGroupStarted(*test);
+ currentGroupTimeStarted_ = GetPlatformSpecificTimeInMillis();
+}
+
+void TestResult::currentGroupEnded(UtestShell* /*test*/)
+{
+ currentGroupTotalExecutionTime_ = GetPlatformSpecificTimeInMillis() - currentGroupTimeStarted_;
+ output_.printCurrentGroupEnded(*this);
+}
+
+void TestResult::currentTestStarted(UtestShell* test)
+{
+ output_.printCurrentTestStarted(*test);
+ currentTestTimeStarted_ = GetPlatformSpecificTimeInMillis();
+}
+
+void TestResult::print(const char* text)
+{
+ output_.print(text);
+}
+
+void TestResult::currentTestEnded(UtestShell* /*test*/)
+{
+ currentTestTotalExecutionTime_ = GetPlatformSpecificTimeInMillis() - currentTestTimeStarted_;
+ output_.printCurrentTestEnded(*this);
+
+}
+
+void TestResult::addFailure(const TestFailure& failure)
+{
+ output_.print(failure);
+ failureCount_++;
+}
+
+void TestResult::countTest()
+{
+ testCount_++;
+}
+
+void TestResult::countRun()
+{
+ runCount_++;
+}
+
+void TestResult::countCheck()
+{
+ checkCount_++;
+}
+
+void TestResult::countFilteredOut()
+{
+ filteredOutCount_++;
+}
+
+void TestResult::countIgnored()
+{
+ ignoredCount_++;
+}
+
+void TestResult::testsStarted()
+{
+ timeStarted_ = GetPlatformSpecificTimeInMillis();
+ output_.printTestsStarted();
+}
+
+void TestResult::testsEnded()
+{
+ long timeEnded = GetPlatformSpecificTimeInMillis();
+ totalExecutionTime_ = timeEnded - timeStarted_;
+ output_.printTestsEnded(*this);
+}
+
+long TestResult::getTotalExecutionTime() const
+{
+ return totalExecutionTime_;
+}
+
+void TestResult::setTotalExecutionTime(long exTime)
+{
+ totalExecutionTime_ = exTime;
+}
+
+long TestResult::getCurrentTestTotalExecutionTime() const
+{
+ return currentTestTotalExecutionTime_;
+}
+
+long TestResult::getCurrentGroupTotalExecutionTime() const
+{
+ return currentGroupTotalExecutionTime_;
+}
+
--- a/src/CppUTest/Utest.cpp Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/Utest.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -393,6 +393,13 @@
failWith(LongsEqualFailure (this, fileName, lineNumber, expected, actual), testTerminator);
}
+void UtestShell::assertUnsignedLongsEqual(unsigned long expected, unsigned long actual, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+{
+ getTestResult()->countCheck();
+ if (expected != actual)
+ failWith(UnsignedLongsEqualFailure (this, fileName, lineNumber, expected, actual), testTerminator);
+}
+
void UtestShell::assertPointersEqual(const void* expected, const void* actual, const char* fileName, int lineNumber)
{
getTestResult()->countCheck();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Platforms/armcc/UtestPlatform.cpp Tue Jun 17 15:52:54 2014 +0100
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cstdlib>
+#include "CppUTest/TestHarness.h"
+#undef malloc
+#undef free
+#undef calloc
+#undef realloc
+
+#define far // eliminate "meaningless type qualifier" warning
+#include "CppUTest/TestRegistry.h"
+#include <time.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+
+#include "CppUTest/PlatformSpecificFunctions.h"
+
+static jmp_buf test_exit_jmp_buf[2];
+static int jmp_buf_index = 0;
+
+/* The ARMCC compiler will compile this function with C++ linkage, unless
+ * we specifically tell it to use C linkage again, in the function definiton.
+ */
+extern "C" int PlatformSpecificSetJmp(void (*function) (void* data), void* data)
+{
+ if (0 == setjmp(test_exit_jmp_buf[jmp_buf_index])) {
+ jmp_buf_index++;
+ function(data);
+ jmp_buf_index--;
+ return 1;
+ }
+ return 0;
+}
+
+void PlatformSpecificLongJmp()
+{
+ jmp_buf_index--;
+ longjmp(test_exit_jmp_buf[jmp_buf_index], 1);
+}
+
+void PlatformSpecificRestoreJumpBuffer()
+{
+ jmp_buf_index--;
+}
+
+void PlatformSpecificRunTestInASeperateProcess(UtestShell* shell, TestPlugin* plugin, TestResult* result)
+{
+ printf("-p isn' implemented for armcc. Running inside the process\b");
+ shell->runOneTest(plugin, *result);
+}
+
+TestOutput::WorkingEnvironment PlatformSpecificGetWorkingEnvironment()
+{
+ return TestOutput::eclipse;
+}
+
+///////////// Time in millis
+/*
+* In Keil MDK-ARM, clock() default implementation used semihosting.
+* Resolutions is user adjustable (1 ms for now)
+*/
+static long TimeInMillisImplementation()
+{
+ clock_t t = clock();
+ return t;
+}
+
+static long (*timeInMillisFp) () = TimeInMillisImplementation;
+
+long GetPlatformSpecificTimeInMillis()
+{
+ return timeInMillisFp();
+}
+
+/* The ARMCC compiler will compile this function with C++ linkage, unless
+ * we specifically tell it to use C linkage again, in the function definiton.
+ */
+extern "C" void SetPlatformSpecificTimeInMillisMethod(long (*platformSpecific) ())
+{
+ timeInMillisFp = (platformSpecific == 0) ? TimeInMillisImplementation : platformSpecific;
+}
+
+///////////// Time in String
+
+static const char* TimeStringImplementation()
+{
+ time_t tm = time(NULL);
+ return ctime(&tm);
+}
+
+static const char* (*timeStringFp) () = TimeStringImplementation;
+
+const char* GetPlatformSpecificTimeString()
+{
+ return timeStringFp();
+}
+
+/* The ARMCC compiler will compile this function with C++ linkage, unless
+ * we specifically tell it to use C linkage again, in the function definiton.
+ */
+extern "C" void SetPlatformSpecificTimeStringMethod(const char* (*platformMethod) ())
+{
+ timeStringFp = (platformMethod == 0) ? TimeStringImplementation : platformMethod;
+}
+
+int PlatformSpecificAtoI(const char* str)
+{
+ return atoi(str);
+}
+
+size_t PlatformSpecificStrLen(const char* str)
+{
+ return strlen(str);
+}
+
+int PlatformSpecificStrCmp(const char* s1, const char* s2)
+{
+ return strcmp(s1, s2);
+}
+
+int PlatformSpecificStrNCmp(const char* s1, const char* s2, size_t size)
+{
+ return strncmp(s1, s2, size);
+}
+
+char* PlatformSpecificStrStr(const char* s1, const char* s2)
+{
+ return strstr((char*)s1, (char*)s2);
+}
+
+/* The ARMCC compiler will compile this function with C++ linkage, unless
+ * we specifically tell it to use C linkage again, in the function definiton.
+ */
+// extern "C" int PlatformSpecificVSNprintf(char *str, size_t size, const char* format, va_list args)
+int PlatformSpecificVSNprintf(char *str, size_t size, const char* format, va_list args)
+{
+ return vsnprintf( str, size, format, args);
+}
+
+char PlatformSpecificToLower(char c)
+{
+ return tolower(c);
+}
+
+PlatformSpecificFile PlatformSpecificFOpen(const char* filename, const char* flag)
+{
+ return fopen(filename, flag);
+}
+
+
+void PlatformSpecificFPuts(const char* str, PlatformSpecificFile file)
+{
+ fputs(str, (FILE*)file);
+}
+
+void PlatformSpecificFClose(PlatformSpecificFile file)
+{
+ fclose((FILE*)file);
+}
+
+void PlatformSpecificFlush()
+{
+ fflush(stdout);
+}
+
+#include "Serial.h"
+using namespace mbed;
+
+int PlatformSpecificPutchar(int c)
+{
+ /* Please modify this block for test results to be reported as
+ * console output. The following is a sample implementation using a
+ * Serial object connected to the console. */
+#define NEED_TEST_REPORT_AS_CONSOLE_OUTPUT 1
+#if NEED_TEST_REPORT_AS_CONSOLE_OUTPUT
+ extern Serial console;
+
+ #define NEED_LINE_FEED_IN_ADDITION_TO_NEWLINE 1
+ #if NEED_LINE_FEED_IN_ADDITION_TO_NEWLINE
+ /* CppUTest emits \n line terminators in its reports; some terminals
+ * need the linefeed (\r) in addition. */
+ if (c == '\n') {
+ console.putc('\r');
+ }
+ #endif /* #if NEED_LINE_FEED_IN_ADDITION_TO_NEWLINE */
+
+ return (console.putc(c));
+#else /* NEED_TEST_REPORT_AS_CONSOLE_OUTPUT */
+ return (0);
+#endif /* NEED_TEST_REPORT_AS_CONSOLE_OUTPUT */
+}
+
+void* PlatformSpecificMalloc(size_t size)
+{
+ return malloc(size);
+}
+
+void* PlatformSpecificRealloc (void* memory, size_t size)
+{
+ return realloc(memory, size);
+}
+
+void PlatformSpecificFree(void* memory)
+{
+ free(memory);
+}
+
+void* PlatformSpecificMemCpy(void* s1, const void* s2, size_t size)
+{
+ return memcpy(s1, s2, size);
+}
+
+void* PlatformSpecificMemset(void* mem, int c, size_t size)
+{
+ return memset(mem, c, size);
+}
+
+double PlatformSpecificFabs(double d)
+{
+ return fabs(d);
+}
+
+int PlatformSpecificIsNan(double d)
+{
+ return isnan(d);
+}
--- a/src/Platforms/mbed/UtestPlatform.cpp Tue Jan 28 09:27:41 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,312 +0,0 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-#include <setjmp.h>
-#include <ctype.h>
-#include "platform.h"
-
-#include "mbed.h"
-#include "Serial.h"
-#include "error.h"
-
-#include "CppUTest/TestHarness.h"
-
-#include "CppUTest/TestRegistry.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-
-static jmp_buf test_exit_jmp_buf[10];
-static int jmp_buf_index = 0;
-
-int
-PlatformSpecificSetJmp(void (* function) (void* data), void* data)
-{
- if (0 == setjmp(test_exit_jmp_buf[jmp_buf_index])) {
- jmp_buf_index++;
- function(data);
- jmp_buf_index--;
- return (1);
- }
- return (0);
-}
-
-void
-PlatformSpecificLongJmp()
-{
- jmp_buf_index--;
- longjmp(test_exit_jmp_buf[jmp_buf_index], 1);
-}
-
-void
-PlatformSpecificRestoreJumpBuffer()
-{
- jmp_buf_index = 0;
- memset(test_exit_jmp_buf, 0, sizeof(test_exit_jmp_buf));
-}
-
-void
-PlatformSpecificRunTestInASeperateProcess(UtestShell* shell,
- TestPlugin* plugin,
- TestResult* result)
-{
- (void) shell;
- (void) plugin;
- (void) result;
-
- /* To be implemented */
- error("PlatformSpecificRunTestInASeperateProcess not implemented, but called");
-}
-
-long
-GetPlatformSpecificTimeInMillis()
-{
- /* To be implemented */
- return (0);
-}
-
-void
-SetPlatformSpecificTimeInMillisMethod(long (* platformSpecific) ())
-{
- (void) platformSpecific;
-
- /* To be implemented */
- error("SetPlatformSpecificTimeInMillisMethod not implemented, but called");
-}
-
-TestOutput::WorkingEnvironment
-PlatformSpecificGetWorkingEnvironment()
-{
- return (TestOutput::eclipse);
-}
-
-///////////// Time in String
-
-const char*
-GetPlatformSpecificTimeString()
-{
- /* To be implemented */
- error("GetPlatformSpecificTimeString not implemented, but called");
-
- return (NULL);
-}
-
-void
-SetPlatformSpecificTimeStringMethod(const char* (* platformMethod) ())
-{
- (void) platformMethod;
-
- /* To be implemented */
- error("SetPlatformSpecificTimeStringMethod not implemented, but called");
-}
-
-int
-PlatformSpecificAtoI(const char* str)
-{
- return (atoi(str));
-}
-
-size_t
-PlatformSpecificStrLen(const char* str)
-{
- return (strlen(str));
-}
-
-char*
-PlatformSpecificStrCat(char* s1, const char* s2)
-{
- return (strcat(s1, s2));
-}
-
-char*
-PlatformSpecificStrCpy(char* s1, const char* s2)
-{
- return (strcpy(s1, s2));
-}
-
-char*
-PlatformSpecificStrNCpy(char* s1, const char* s2, size_t size)
-{
- return (strncpy(s1, s2, size));
-}
-
-int
-PlatformSpecificStrCmp(const char* s1, const char* s2)
-{
- return (strcmp(s1, s2));
-}
-
-int
-PlatformSpecificStrNCmp(const char* s1, const char* s2, size_t size)
-{
- return (strncmp(s1, s2, size));
-}
-
-char*
-PlatformSpecificStrStr(const char* s1, const char* s2)
-{
- return ((char*) strstr(s1, s2));
-}
-
-int
-PlatformSpecificVSNprintf(char* str,
- size_t size,
- const char* format,
- va_list args)
-{
- return (vsnprintf( str, size, format, args));
-}
-
-char
-PlatformSpecificToLower(char c)
-{
- return ((char) tolower((char) c));
-}
-
-PlatformSpecificFile
-PlatformSpecificFOpen(const char* filename, const char* flag)
-{
- (void) filename;
- (void) flag;
-
- /* To be implemented */
- error("PlatformSpecificFOpen not implemented, but called");
-
- return (NULL);
-}
-
-void
-PlatformSpecificFPuts(const char* str, PlatformSpecificFile file)
-{
- (void) str;
- (void) file;
-
- /* To be implemented */
- error("PlatformSpecificFPuts not implemented, but called");
-}
-
-void
-PlatformSpecificFClose(PlatformSpecificFile file)
-{
- (void) file;
-
- /* To be implemented */
- error("PlatformSpecificFClose not implemented, but called");
-}
-
-void
-PlatformSpecificFlush()
-{
-}
-
-int
-PlatformSpecificPutchar(int c)
-{
- /* Please modify this block for test results to be reported as
- * console output. The following is a sample implementation using a
- * Serial object connected to the console. */
-#define NEED_TEST_REPORT_AS_CONSOLE_OUTPUT 1
-#if NEED_TEST_REPORT_AS_CONSOLE_OUTPUT
- extern Serial console;
-
- #define NEED_LINE_FEED_IN_ADDITION_TO_NEWLINE 1
- #if NEED_LINE_FEED_IN_ADDITION_TO_NEWLINE
- /* CppUTest emits \n line terminators in its reports; some terminals
- * need the linefeed (\r) in addition. */
- if (c == '\n') {
- console.putc('\r');
- }
- #endif /* #if NEED_LINE_FEED_IN_ADDITION_TO_NEWLINE */
-
- return (console.putc(c));
-#else /* NEED_TEST_REPORT_AS_CONSOLE_OUTPUT */
- return (0);
-#endif /* NEED_TEST_REPORT_AS_CONSOLE_OUTPUT */
-}
-
-void*
-PlatformSpecificMalloc(size_t size)
-{
- return (malloc(size));
-}
-
-void*
-PlatformSpecificRealloc (void* memory, size_t size)
-{
- (void) memory;
- (void) size;
-
- /* To be implemented */
- error("PlatformSpecificRealloc not implemented, but called");
- return (NULL);
-}
-
-void
-PlatformSpecificFree(void* memory)
-{
- free(memory);
-}
-
-void*
-PlatformSpecificMemCpy(void* s1, const void* s2, size_t size)
-{
- (void) size;
- (void) s1;
- (void) s2;
-
- /* To be implemented */
- error("PlatformSpecificMemCpy not implemented, but called");
-
- return (NULL);
-}
-
-void*
-PlatformSpecificMemset(void* mem, int c, size_t size)
-{
- return (memset(mem, c, size));
-}
-
-double
-PlatformSpecificFabs(double d)
-{
- (void) d;
-
- /* To be implemented */
- error("PlatformSpecificFabs not implemented, but called");
-
- return (0.0);
-}
-
-int
-PlatformSpecificIsNan(double d)
-{
- (void) d;
-
- /* To be implemented */
- error("PlatformSpecificIsNan not implemented, but called");
-
- return (0);
-}
