Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:0b799af9d58e, committed 2014-01-28
- Comitter:
- rgrover1
- Date:
- Tue Jan 28 09:27:41 2014 +0000
- Child:
- 1:4769360130ed
- Commit message:
- CppUTest unit test framework.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/CommandLineArguments.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#ifndef D_CommandLineArguments_H
+#define D_CommandLineArguments_H
+
+#include "SimpleString.h"
+#include "TestOutput.h"
+#include "TestFilter.h"
+
+class TestPlugin;
+
+class CommandLineArguments
+{
+public:
+ explicit CommandLineArguments(int ac, const char** av);
+ virtual ~CommandLineArguments();
+
+ bool parse(TestPlugin* plugin);
+ bool isVerbose() const;
+ int getRepeatCount() const;
+ TestFilter getGroupFilter() const;
+ TestFilter getNameFilter() const;
+ bool isJUnitOutput() const;
+ bool isEclipseOutput() const;
+ bool runTestsInSeperateProcess() const;
+ const char* usage() const;
+
+private:
+
+ enum OutputType
+ {
+ OUTPUT_ECLIPSE, OUTPUT_JUNIT
+ };
+ int ac_;
+ const char** av_;
+
+ bool verbose_;
+ bool runTestsAsSeperateProcess_;
+ int repeat_;
+ TestFilter groupFilter_;
+ TestFilter nameFilter_;
+ OutputType outputType_;
+
+ SimpleString getParameterField(int ac, const char** av, int& i, const SimpleString& parameterName);
+ void SetRepeatCount(int ac, const char** av, int& index);
+ void SetGroupFilter(int ac, const char** av, int& index);
+ void SetStrictGroupFilter(int ac, const char** av, int& index);
+ void SetNameFilter(int ac, const char** av, int& index);
+ 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);
+
+ CommandLineArguments(const CommandLineArguments&);
+ CommandLineArguments& operator=(const CommandLineArguments&);
+
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/CommandLineTestRunner.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#ifndef D_CommandLineTestRunner_H
+#define D_CommandLineTestRunner_H
+
+#include "TestHarness.h"
+#include "TestOutput.h"
+#include "CommandLineArguments.h"
+#include "TestFilter.h"
+
+class JUnitTestOutput;
+class TestRegistry;
+
+#define DEF_PLUGIN_MEM_LEAK "MemoryLeakPlugin"
+#define DEF_PLUGIN_SET_POINTER "SetPointerPlugin"
+
+class CommandLineTestRunner
+{
+public:
+ enum OutputType
+ {
+ OUTPUT_NORMAL, OUTPUT_JUNIT
+ };
+
+ static int RunAllTests(int ac, const char** av);
+ static int RunAllTests(int ac, char** av);
+ CommandLineTestRunner(int ac, const char** av, TestOutput*, TestRegistry* registry);
+
+ virtual ~CommandLineTestRunner();
+ int runAllTestsMain();
+
+private:
+ TestOutput* output_;
+ JUnitTestOutput* jUnitOutput_;
+ CommandLineArguments* arguments_;
+ TestRegistry* registry_;
+
+ bool parseArguments(TestPlugin*);
+ int runAllTests();
+ void initializeTestRun();
+ bool isVerbose();
+ int getRepeatCount();
+ TestFilter getGroupFilter();
+ TestFilter getNameFilter();
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/CppUTest/CppUTestConfig.h Tue Jan 28 09:27:41 2014 +0000 @@ -0,0 +1,175 @@ +/* + * 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. + */ + + +#ifndef CPPUTESTCONFIG_H_ +#define CPPUTESTCONFIG_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * This file is added for some specific CppUTest configurations that earlier were spread out into multiple files. + * + * The goal of this file is to stay really small and not to include other things, but mainly to remove duplication + * from other files and resolve dependencies in #includes. + * + */ + +/* + * Lib C dependencies that are currently still left: + * + * stdarg.h -> We use formatting functions and va_list requires to include stdarg.h in SimpleString + * stdlib.h -> The TestHarness_c.h includes this to try to avoid conflicts in its malloc #define. This dependency can + * easily be removed by not enabling the MALLOC overrides. + * + * Lib C++ dependencies are all under the CPPUTEST_USE_STD_CPP_LIB. + * The only dependency is to <new> which has the bad_alloc struct + * + */ + +/* Do we use Standard C or not? When doing Kernel development, standard C usage is out. */ +#ifndef CPPUTEST_USE_STD_C_LIB + #ifdef CPPUTEST_STD_C_LIB_DISABLED + #define CPPUTEST_USE_STD_C_LIB 0 + #else + #define CPPUTEST_USE_STD_C_LIB 1 + #endif +#endif + + +#if NEED_TO_ENABLE_CPP_SUPPORT /* disabled by default because mbed's + * toolchain doesn't support exceptions. */ + /* Do we use Standard C++ or not? */ + #ifndef CPPUTEST_USE_STD_CPP_LIB + #ifdef CPPUTEST_STD_CPP_LIB_DISABLED + #define CPPUTEST_USE_STD_CPP_LIB 0 + #else + #define CPPUTEST_USE_STD_CPP_LIB 1 + #endif + #endif +#endif /* #if NEED_TO_ENABLE_CPP_SUPPORT */ + +/* Is memory leak detection enabled? + * Controls the override of the global operator new/deleted and malloc/free. + * Without this, there will be no memory leak detection in C/C++. +*/ +#if NEED_TO_ENABLE_MEMORY_LEAK_DETECTION + #ifndef CPPUTEST_USE_MEM_LEAK_DETECTION + #ifdef CPPUTEST_MEM_LEAK_DETECTION_DISABLED + #define CPPUTEST_USE_MEM_LEAK_DETECTION 0 + #else + #define CPPUTEST_USE_MEM_LEAK_DETECTION 1 + #endif + #endif +#endif /* #if NEED_TO_ENABLE_MEMORY_LEAK_DETECTION */ + +/* Create a __no_return__ macro, which is used to flag a function as not returning. + * Used for functions that always throws for instance. + * + * This is needed for compiling with clang, without breaking other compilers. + */ +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif + +#if __has_attribute(noreturn) + #define __no_return__ __attribute__((noreturn)) +#else + #define __no_return__ +#endif + +#if __has_attribute(format) + #define __check_format__(type, format_parameter, other_parameters) __attribute__ ((format (type, format_parameter, other_parameters))) +#else + #define __check_format__(type, format_parameter, other_parameters) /* type, format_parameter, other_parameters */ +#endif + +/* + * When we don't link Standard C++, then we won't throw exceptions as we assume the compiler might not support that! + */ + +#if CPPUTEST_USE_STD_CPP_LIB + #if defined(__cplusplus) && __cplusplus >= 201103L + #define UT_THROW(exception) + #define UT_NOTHROW noexcept + #else + #define UT_THROW(exception) throw (exception) + #define UT_NOTHROW throw() + #endif +#else + #define UT_THROW(exception) + #define UT_NOTHROW +#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. + */ + +#ifdef __clang__ +#undef UT_NOTHROW +#define UT_NOTHROW throw() +#endif + +/* + * g++-4.7 with stdc++11 enabled On MacOSX! will have a different exception specifier for operator new (and thank you!) + * I assume they'll fix this in the future, but for now, we'll change that here. + * (This should perhaps also be done in the configure.ac) + */ + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#ifdef __APPLE__ +#ifdef _GLIBCXX_THROW +#undef UT_THROW +#define UT_THROW(exception) _GLIBCXX_THROW(exception) +#endif +#endif +#endif + +/* + * Detection of different 64 bit environments + */ + +#if defined(__LP64__) || defined(_LP64) || (defined(__WORDSIZE) && (__WORDSIZE == 64 )) || defined(__x86_64) || defined(_WIN64) +#define CPPUTEST_64BIT +#if defined(_WIN64) +#define CPPUTEST_64BIT_32BIT_LONGS +#endif +#endif + +#if defined(__cplusplus) && __cplusplus >= 201103L +#define _override override +#else +#define _override +#endif + +/* Should be the only #include here. Standard C library wrappers */ +#include "StandardCLibrary.h" + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/JUnitTestOutput.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#ifndef D_JUnitTestOutput_h
+#define D_JUnitTestOutput_h
+
+#include "TestOutput.h"
+#include "SimpleString.h"
+
+struct JUnitTestOutputImpl;
+struct JUnitTestCaseResultNode;
+
+class JUnitTestOutput: public TestOutput
+{
+public:
+ JUnitTestOutput();
+ virtual ~JUnitTestOutput();
+
+ virtual void printTestsStarted() _override;
+ virtual void printTestsEnded(const TestResult& result) _override;
+ virtual void printCurrentTestStarted(const UtestShell& test) _override;
+ virtual void printCurrentTestEnded(const TestResult& res) _override;
+ virtual void printCurrentGroupStarted(const UtestShell& test) _override;
+ virtual void printCurrentGroupEnded(const TestResult& res) _override;
+
+ virtual void verbose() _override;
+ virtual void printBuffer(const char*) _override;
+ virtual void print(const char*) _override;
+ virtual void print(long) _override;
+ virtual void print(const TestFailure& failure) _override;
+ virtual void printTestRun(int number, int total) _override;
+
+ virtual void flush() _override;
+
+ virtual SimpleString createFileName(const SimpleString& group);
+
+protected:
+
+ JUnitTestOutputImpl* impl_;
+ void resetTestGroupResult();
+
+ virtual void openFileForWrite(const SimpleString& fileName);
+ virtual void writeTestGroupToFile();
+ virtual void writeToFile(const SimpleString& buffer);
+ virtual void closeFile();
+
+ virtual void writeXmlHeader();
+ virtual void writeTestSuiteSummery();
+ virtual void writeProperties();
+ virtual void writeTestCases();
+ virtual void writeFailure(JUnitTestCaseResultNode* node);
+ virtual void writeFileEnding();
+
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/MemoryLeakDetector.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,252 @@
+/*
+ * 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.
+ */
+
+#ifndef D_MemoryLeakDetector_h
+#define D_MemoryLeakDetector_h
+
+enum MemLeakPeriod
+{
+ mem_leak_period_all,
+ mem_leak_period_disabled,
+ mem_leak_period_enabled,
+ mem_leak_period_checking
+};
+
+class TestMemoryAllocator;
+
+class MemoryLeakFailure
+{
+public:
+ virtual ~MemoryLeakFailure()
+ {
+ }
+
+ virtual void fail(char* fail_string)=0;
+};
+
+struct SimpleStringBuffer
+{
+ enum
+ {
+ SIMPLE_STRING_BUFFER_LEN = 4096
+ };
+
+ SimpleStringBuffer();
+ void clear();
+ void add(const char* format, ...) __check_format__(printf, 2, 3);
+ char* toString();
+
+ void setWriteLimit(size_t write_limit);
+ void resetWriteLimit();
+ bool reachedItsCapacity();
+private:
+ char buffer_[SIMPLE_STRING_BUFFER_LEN];
+ size_t positions_filled_;
+ size_t write_limit_;
+};
+
+struct MemoryLeakDetectorNode;
+
+class MemoryLeakOutputStringBuffer
+{
+public:
+ MemoryLeakOutputStringBuffer();
+
+ void clear();
+
+ void startMemoryLeakReporting();
+ void stopMemoryLeakReporting();
+
+ void reportMemoryLeak(MemoryLeakDetectorNode* leak);
+
+ void reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
+ void reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
+ void reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
+ char* toString();
+
+private:
+ void addAllocationLocation(const char* allocationFile, int allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator);
+ void addDeallocationLocation(const char* freeFile, int freeLineNumber, TestMemoryAllocator* allocator);
+
+ void addMemoryLeakHeader();
+ void addMemoryLeakFooter(int totalAmountOfLeaks);
+ void addWarningForUsingMalloc();
+ void addNoMemoryLeaksMessage();
+ void addErrorMessageForTooMuchLeaks();
+
+private:
+
+ int total_leaks_;
+ bool giveWarningOnUsingMalloc_;
+
+ void reportFailure(const char* message, const char* allocFile,
+ int allocLine, size_t allocSize,
+ TestMemoryAllocator* allocAllocator, const char* freeFile,
+ int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
+
+ SimpleStringBuffer outputBuffer_;
+};
+
+struct MemoryLeakDetectorNode
+{
+ MemoryLeakDetectorNode() :
+ size_(0), number_(0), memory_(0), file_(0), line_(0), allocator_(0), period_(mem_leak_period_enabled), next_(0)
+ {
+ }
+
+ void init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, const char* file, int line);
+
+ size_t size_;
+ unsigned number_;
+ char* memory_;
+ const char* file_;
+ int line_;
+ TestMemoryAllocator* allocator_;
+ MemLeakPeriod period_;
+
+private:
+ friend struct MemoryLeakDetectorList;
+ MemoryLeakDetectorNode* next_;
+};
+
+struct MemoryLeakDetectorList
+{
+ MemoryLeakDetectorList() :
+ head_(0)
+ {}
+
+ void addNewNode(MemoryLeakDetectorNode* node);
+ MemoryLeakDetectorNode* retrieveNode(char* memory);
+ MemoryLeakDetectorNode* removeNode(char* memory);
+
+ MemoryLeakDetectorNode* getFirstLeak(MemLeakPeriod period);
+ MemoryLeakDetectorNode* getNextLeak(MemoryLeakDetectorNode* node,
+ MemLeakPeriod period);
+ MemoryLeakDetectorNode* getLeakFrom(MemoryLeakDetectorNode* node,
+ MemLeakPeriod period);
+
+ int getTotalLeaks(MemLeakPeriod period);
+ bool hasLeaks(MemLeakPeriod period);
+ void clearAllAccounting(MemLeakPeriod period);
+
+ bool isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period);
+
+private:
+ MemoryLeakDetectorNode* head_;
+};
+
+struct MemoryLeakDetectorTable
+{
+ void clearAllAccounting(MemLeakPeriod period);
+
+ void addNewNode(MemoryLeakDetectorNode* node);
+ MemoryLeakDetectorNode* retrieveNode(char* memory);
+ MemoryLeakDetectorNode* removeNode(char* memory);
+
+ bool hasLeaks(MemLeakPeriod period);
+ int getTotalLeaks(MemLeakPeriod period);
+
+ MemoryLeakDetectorNode* getFirstLeak(MemLeakPeriod period);
+ MemoryLeakDetectorNode* getNextLeak(MemoryLeakDetectorNode* leak,
+ MemLeakPeriod period);
+
+private:
+ unsigned long hash(char* memory);
+
+ enum
+ {
+ hash_prime = MEMORY_LEAK_HASH_TABLE_SIZE
+ };
+ MemoryLeakDetectorList table_[hash_prime];
+};
+
+class MemoryLeakDetector
+{
+public:
+ MemoryLeakDetector(MemoryLeakFailure* reporter);
+ virtual ~MemoryLeakDetector()
+ {
+ }
+
+ void enable();
+ void disable();
+
+ void disableAllocationTypeChecking();
+ void enableAllocationTypeChecking();
+
+ void startChecking();
+ void stopChecking();
+
+ const char* report(MemLeakPeriod period);
+ void markCheckingPeriodLeaksAsNonCheckingPeriod();
+ int totalMemoryLeaks(MemLeakPeriod period);
+ void clearAllAccounting(MemLeakPeriod period);
+
+ char* allocMemory(TestMemoryAllocator* allocator, size_t size, bool allocatNodesSeperately = false);
+ char* allocMemory(TestMemoryAllocator* allocator, size_t size,
+ const char* file, int line, bool allocatNodesSeperately = false);
+ void deallocMemory(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately = false);
+ void deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, int line, bool allocatNodesSeperately = false);
+ char* reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately = false);
+
+ void invalidateMemory(char* memory);
+ void removeMemoryLeakInformationWithoutCheckingOrDeallocatingTheMemoryButDeallocatingTheAccountInformation(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately);
+ enum
+ {
+ memory_corruption_buffer_size = 3
+ };
+
+ unsigned getCurrentAllocationNumber();
+private:
+ MemoryLeakFailure* reporter_;
+ MemLeakPeriod current_period_;
+ MemoryLeakOutputStringBuffer outputBuffer_;
+ MemoryLeakDetectorTable memoryTable_;
+ bool doAllocationTypeChecking_;
+ unsigned allocationSequenceNumber_;
+
+ char* allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately);
+ char* reallocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately);
+ MemoryLeakDetectorNode* createMemoryLeakAccountingInformation(TestMemoryAllocator* allocator, size_t size, char* memory, bool allocatNodesSeperately);
+
+
+ bool validMemoryCorruptionInformation(char* memory);
+ bool matchingAllocation(TestMemoryAllocator *alloc_allocator, TestMemoryAllocator *free_allocator);
+
+ void storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, int line);
+ void ConstructMemoryLeakReport(MemLeakPeriod period);
+
+ size_t sizeOfMemoryWithCorruptionInfo(size_t size);
+ MemoryLeakDetectorNode* getNodeFromMemoryPointer(char* memory, size_t size);
+
+ char* reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately);
+
+ void addMemoryCorruptionInformation(char* memory);
+ void checkForCorruption(MemoryLeakDetectorNode* node, const char* file, int line, TestMemoryAllocator* allocator, bool allocateNodesSeperately);
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/MemoryLeakDetectorMallocMacros.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,56 @@
+
+/*
+ * This file can be used to get extra debugging information about memory leaks in your production code.
+ * It defines a preprocessor macro for malloc. This will pass additional information to the
+ * malloc and this will give the line/file information of the memory leaks in your code.
+ *
+ * You can use this by including this file to all your production code. When using gcc, you can use
+ * the -include file to do this for you.
+ *
+ */
+
+#include "CppUTestConfig.h"
+
+#if CPPUTEST_USE_MEM_LEAK_DETECTION
+
+/* This prevents the declaration from done twice and makes sure the file only #defines malloc, so it can be included anywhere */
+#ifndef CPPUTEST_USE_MALLOC_MACROS
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern void* cpputest_malloc_location(size_t size, const char* file, int line);
+extern void* cpputest_calloc_location(size_t count, size_t size, const char* file, int line);
+extern void* cpputest_realloc_location(void *, size_t, const char* file, int line);
+extern void cpputest_free_location(void* buffer, const char* file, int line);
+
+#ifdef __cplusplus
+}
+#endif
+
+extern void crash_on_allocation_number(unsigned number);
+
+#endif
+
+/* NOTE on strdup!
+ *
+ * strdup was implemented earlier, however it is *not* an Standard C function but a POSIX function.
+ * Because of that, it can lead to portability issues by providing more than is available on the local platform.
+ * For that reason, strdup is *not* implemented as a macro. If you still want to use it, an easy implementation would be:
+ *
+ * size_t length = 1 + strlen(str);
+ * char* result = (char*) cpputest_malloc_location(length, file, line);
+ * memcpy(result, str, length);
+ * return result;
+ *
+ */
+
+#define malloc(a) cpputest_malloc_location(a, __FILE__, __LINE__)
+#define calloc(a, b) cpputest_calloc_location(a, b, __FILE__, __LINE__)
+#define realloc(a, b) cpputest_realloc_location(a, b, __FILE__, __LINE__)
+#define free(a) cpputest_free_location(a, __FILE__, __LINE__)
+
+#define CPPUTEST_USE_MALLOC_MACROS 1
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/CppUTest/MemoryLeakDetectorNewMacros.h Tue Jan 28 09:27:41 2014 +0000 @@ -0,0 +1,51 @@ + +/* + * This file can be used to get extra debugging information about memory leaks in your production code. + * It defines a preprocessor macro for operator new. This will pass additional information to the + * operator new and this will give the line/file information of the memory leaks in your code. + * + * You can use this by including this file to all your production code. When using gcc, you can use + * the -include file to do this for you. + * + * Warning: Using the new macro can cause a conflict with newly declared operator news. This can be + * resolved by: + * 1. #undef operator new before including this file + * 2. Including the files that override operator new before this file. + * This can be done by creating your own NewMacros.h file that includes your operator new overrides + * and THEN this file. + * + * STL (or StdC++ lib) also does overrides for operator new. Therefore, you'd need to include the STL + * files *before* this file too. + * + */ + +#include "CppUTestConfig.h" + +#if CPPUTEST_USE_MEM_LEAK_DETECTION + +/* This #ifndef prevents <new> from being included twice and enables the file to be included anywhere */ +#ifndef CPPUTEST_USE_NEW_MACROS + + #if CPPUTEST_USE_STD_CPP_LIB + #include <new> + #include <memory> + #include <string> + #endif + + void* operator new(size_t size, const char* file, int line) UT_THROW (std::bad_alloc); + void* operator new[](size_t size, const char* file, int line) UT_THROW (std::bad_alloc); + void* operator new(size_t size) UT_THROW(std::bad_alloc); + void* operator new[](size_t size) UT_THROW(std::bad_alloc); + + void operator delete(void* mem) UT_NOTHROW; + void operator delete[](void* mem) UT_NOTHROW; + void operator delete(void* mem, const char* file, int line) UT_NOTHROW; + void operator delete[](void* mem, const char* file, int line) UT_NOTHROW; + +#endif + +#define new new(__FILE__, __LINE__) + +#define CPPUTEST_USE_NEW_MACROS 1 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/MemoryLeakWarningPlugin.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#ifndef D_MemoryLeakWarningPlugin_h
+#define D_MemoryLeakWarningPlugin_h
+
+#include "TestPlugin.h"
+#include "MemoryLeakDetectorNewMacros.h"
+
+#define IGNORE_ALL_LEAKS_IN_TEST() MemoryLeakWarningPlugin::getFirstPlugin()->ignoreAllLeaksInTest();
+#define EXPECT_N_LEAKS(n) MemoryLeakWarningPlugin::getFirstPlugin()->expectLeaksInTest(n);
+
+extern void crash_on_allocation_number(unsigned alloc_number);
+
+class MemoryLeakDetector;
+class MemoryLeakFailure;
+
+class MemoryLeakWarningPlugin: public TestPlugin
+{
+public:
+ MemoryLeakWarningPlugin(const SimpleString& name, MemoryLeakDetector* localDetector = 0);
+ virtual ~MemoryLeakWarningPlugin();
+
+ virtual void preTestAction(UtestShell& test, TestResult& result) _override;
+ virtual void postTestAction(UtestShell& test, TestResult& result) _override;
+
+ virtual const char* FinalReport(int toBeDeletedLeaks = 0);
+
+ void ignoreAllLeaksInTest();
+ void expectLeaksInTest(int n);
+
+ void destroyGlobalDetectorAndTurnOffMemoryLeakDetectionInDestructor(bool des);
+
+ MemoryLeakDetector* getMemoryLeakDetector();
+
+ static MemoryLeakWarningPlugin* getFirstPlugin();
+
+ static MemoryLeakDetector* getGlobalDetector();
+ static MemoryLeakFailure* getGlobalFailureReporter();
+ static void setGlobalDetector(MemoryLeakDetector* detector, MemoryLeakFailure* reporter);
+ static void destroyGlobalDetector();
+
+ static void turnOffNewDeleteOverloads();
+ static void turnOnNewDeleteOverloads();
+private:
+ MemoryLeakDetector* memLeakDetector_;
+ bool ignoreAllWarnings_;
+ bool destroyGlobalDetectorAndTurnOfMemoryLeakDetectionInDestructor_;
+ int expectedLeaks_;
+ int failureCount_;
+
+ static MemoryLeakWarningPlugin* firstPlugin_;
+};
+
+extern void* cpputest_malloc_location_with_leak_detection(size_t size, const char* file, int line);
+extern void* cpputest_realloc_location_with_leak_detection(void* memory, size_t size, const char* file, int line);
+extern void cpputest_free_location_with_leak_detection(void* buffer, const char* file, int line);
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/CppUTest/PlatformSpecificFunctions.h Tue Jan 28 09:27:41 2014 +0000 @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#ifndef PLATFORMSPECIFICFUNCTIONS_H_ +#define PLATFORMSPECIFICFUNCTIONS_H_ + +#include "CppUTest/TestOutput.h" +TestOutput::WorkingEnvironment PlatformSpecificGetWorkingEnvironment(); + +void PlatformSpecificRunTestInASeperateProcess(UtestShell* shell, TestPlugin* plugin, TestResult* result); + +/* Platform specific interface we use in order to minimize dependencies with LibC. + * This enables porting to different embedded platforms. + * + */ + +#include "CppUTest/PlatformSpecificFunctions_c.h" + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/PlatformSpecificFunctions_c.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+/******************************************************************************
+ *
+ * PlatformSpecificFunctions_c.H
+ *
+ * Provides an interface for when working with pure C
+ *
+ *******************************************************************************/
+
+
+#ifndef PLATFORMSPECIFICFUNCTIONS_C_H_
+#define PLATFORMSPECIFICFUNCTIONS_C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Jumping operations. They manage their own jump buffers */
+int PlatformSpecificSetJmp(void (*function) (void*), void* data);
+void PlatformSpecificLongJmp(void);
+void PlatformSpecificRestoreJumpBuffer(void);
+
+/* Time operations */
+long GetPlatformSpecificTimeInMillis(void);
+void SetPlatformSpecificTimeInMillisMethod(long(*platformSpecific)(void));
+
+const char* GetPlatformSpecificTimeString(void);
+void SetPlatformSpecificTimeStringMethod(const char* (*platformMethod)(void));
+
+/* 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);
+
+int PlatformSpecificVSNprintf(char *str, size_t size, const char* format,
+ va_list va_args_list);
+
+char PlatformSpecificToLower(char c);
+
+/* Misc */
+double PlatformSpecificFabs(double d);
+int PlatformSpecificIsNan(double d);
+int PlatformSpecificAtExit(void(*func)(void));
+
+/* IO operations */
+typedef void* PlatformSpecificFile;
+
+PlatformSpecificFile PlatformSpecificFOpen(const char* filename,
+ const char* flag);
+void PlatformSpecificFPuts(const char* str, PlatformSpecificFile file);
+void PlatformSpecificFClose(PlatformSpecificFile file);
+
+int PlatformSpecificPutchar(int c);
+void PlatformSpecificFlush(void);
+
+/* Dynamic Memory operations */
+void* PlatformSpecificMalloc(size_t size);
+void* PlatformSpecificRealloc(void* memory, size_t size);
+void PlatformSpecificFree(void* memory);
+void* PlatformSpecificMemCpy(void* s1, const void* s2, size_t size);
+void* PlatformSpecificMemset(void* mem, int c, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PLATFORMSPECIFICFUNCTIONS_C_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/SimpleString.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// SIMPLESTRING.H
+//
+// One of the design goals of CppUnitLite is to compilation with very old C++
+// compilers. For that reason, the simple string class that provides
+// only the operations needed in CppUnitLite.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef D_SimpleString_h
+#define D_SimpleString_h
+
+#include "StandardCLibrary.h"
+
+class SimpleStringCollection;
+class TestMemoryAllocator;
+
+class SimpleString
+{
+ friend bool operator==(const SimpleString& left, const SimpleString& right);
+ friend bool operator!=(const SimpleString& left, const SimpleString& right);
+
+public:
+ SimpleString(const char *value = "");
+ SimpleString(const char *value, size_t repeatCount);
+ SimpleString(const SimpleString& other);
+ ~SimpleString();
+
+ SimpleString& operator=(const SimpleString& other);
+ SimpleString operator+(const SimpleString&);
+ SimpleString& operator+=(const SimpleString&);
+ SimpleString& operator+=(const char*);
+
+ char at(int pos) const;
+ int find(char ch) const;
+ int findFrom(size_t starting_position, char ch) const;
+ bool contains(const SimpleString& other) const;
+ bool containsNoCase(const SimpleString& other) const;
+ bool startsWith(const SimpleString& other) const;
+ bool endsWith(const SimpleString& other) const;
+ void split(const SimpleString& split,
+ SimpleStringCollection& outCollection) const;
+ bool equalsNoCase(const SimpleString& str) const;
+
+ size_t count(const SimpleString& str) const;
+
+ void replace(char to, char with);
+ void replace(const char* to, const char* with);
+
+ SimpleString toLower() const;
+ SimpleString subString(size_t beginPos, size_t amount) const;
+ SimpleString subStringFromTill(char startChar, char lastExcludedChar) const;
+ void copyToBuffer(char* buffer, size_t bufferSize) const;
+
+ const char *asCharString() const;
+ size_t size() const;
+ bool isEmpty() const;
+
+ static void padStringsToSameLength(SimpleString& str1, SimpleString& str2, char ch);
+
+ static TestMemoryAllocator* getStringAllocator();
+ static void setStringAllocator(TestMemoryAllocator* allocator);
+
+ static char* allocStringBuffer(size_t size);
+ static void deallocStringBuffer(char* str);
+private:
+ char *buffer_;
+
+ static TestMemoryAllocator* stringAllocator_;
+
+ char* getEmptyString() const;
+};
+
+class SimpleStringCollection
+{
+public:
+ SimpleStringCollection();
+ ~SimpleStringCollection();
+
+ void allocate(size_t size);
+
+ size_t size() const;
+ SimpleString& operator[](size_t index);
+
+private:
+ SimpleString* collection_;
+ SimpleString empty_;
+ size_t size_;
+
+ void operator =(SimpleStringCollection&);
+ SimpleStringCollection(SimpleStringCollection&);
+};
+
+SimpleString StringFrom(bool value);
+SimpleString StringFrom(const void* value);
+SimpleString StringFrom(char value);
+SimpleString StringFrom(const char *value);
+SimpleString StringFromOrNull(const char * value);
+SimpleString StringFrom(long value);
+SimpleString StringFrom(int value);
+SimpleString HexStringFrom(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
+
+#include <string>
+#include <stdint.h>
+
+SimpleString StringFrom(const std::string& other);
+SimpleString StringFrom(unsigned long);
+
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/CppUTest/StandardCLibrary.h Tue Jan 28 09:27:41 2014 +0000 @@ -0,0 +1,68 @@ + +#ifndef STANDARDCLIBRARY_H_ +#define STANDARDCLIBRARY_H_ + +#include "CppUTestConfig.h" + +#if CPPUTEST_USE_STD_C_LIB + +/* Needed for size_t */ +#include <stddef.h> + +/* Sometimes the C++ library does an #undef in stdlib of malloc and free. We want to prevent that */ +#ifdef __cplusplus + #if CPPUTEST_USE_STD_CPP_LIB + #include <cstdlib> + #endif +#endif + +/* Needed for malloc */ +#include <stdlib.h> + +/* Needed for ... */ +#include <stdarg.h> + +#else + +#ifdef __KERNEL__ + +/* Unfinished and not working! Hacking hacking hacking. Why bother make the header files C++ safe! */ +#define false kernel_false +#define true kernel_true +#define bool kernel_bool +#define new kernel_new +#define _Bool int +#include <linux/acpi.h> +#include <linux/types.h> +#undef false +#undef true +#undef bool +#undef new + +#else + +/* + * #warning "These definitions in StandardCLibrary.h are pure (educated, from linux kernel) guesses at the moment. Replace with your platform includes." + * Not on as warning are as errors :P + */ + +#ifdef __SIZE_TYPE__ +typedef __SIZE_TYPE__ size_t; +#else +typedef long unsigned int size_t; +#endif + +typedef char* va_list; +#define NULL (0) +extern void* malloc(size_t); +extern void free(void *); + +#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd))) +#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,sizeof(int)-1)))) +#define va_end(ap) (void) 0 + +#endif + +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/TestFailure.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Failure is a class which holds information for a specific
+// test failure. It can be overriden for more complex failure messages
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef D_TestFailure_H
+#define D_TestFailure_H
+
+#include "SimpleString.h"
+
+class UtestShell;
+class TestOutput;
+
+class TestFailure
+{
+
+public:
+ TestFailure(UtestShell*, const char* fileName, int lineNumber,
+ const SimpleString& theMessage);
+ TestFailure(UtestShell*, const SimpleString& theMessage);
+ TestFailure(UtestShell*, const char* fileName, int lineNumber);
+ TestFailure(const TestFailure&);
+ virtual ~TestFailure();
+
+ virtual SimpleString getFileName() const;
+ virtual SimpleString getTestName() const;
+ virtual int getFailureLineNumber() const;
+ virtual SimpleString getMessage() const;
+ virtual SimpleString getTestFileName() const;
+ virtual int getTestLineNumber() const;
+ bool isOutsideTestFile() const;
+ bool isInHelperFunction() const;
+
+
+protected:
+
+ SimpleString createButWasString(const SimpleString& expected, const SimpleString& actual);
+ SimpleString createDifferenceAtPosString(const SimpleString& actual, size_t position);
+
+ SimpleString testName_;
+ SimpleString fileName_;
+ int lineNumber_;
+ SimpleString testFileName_;
+ int testLineNumber_;
+ SimpleString message_;
+
+ TestFailure& operator=(const TestFailure&);
+
+};
+
+class EqualsFailure: public TestFailure
+{
+public:
+ EqualsFailure(UtestShell*, const char* fileName, int lineNumber, const char* expected, const char* actual);
+ EqualsFailure(UtestShell*, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual);
+};
+
+class DoublesEqualFailure: public TestFailure
+{
+public:
+ DoublesEqualFailure(UtestShell*, const char* fileName, int lineNumber, double expected, double actual, double threshold);
+};
+
+class CheckEqualFailure : public TestFailure
+{
+public:
+ CheckEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual);
+};
+
+class ContainsFailure: public TestFailure
+{
+public:
+ ContainsFailure(UtestShell*, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual);
+
+};
+
+class CheckFailure : public TestFailure
+{
+public:
+ CheckFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& checkString, const SimpleString& conditionString, const SimpleString& textString = "");
+};
+
+class FailFailure : public TestFailure
+{
+public:
+ FailFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& message);
+};
+
+class LongsEqualFailure : public TestFailure
+{
+public:
+ LongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, long expected, long actual);
+};
+
+class StringEqualFailure : public TestFailure
+{
+public:
+ StringEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual);
+};
+
+class StringEqualNoCaseFailure : public TestFailure
+{
+public:
+ StringEqualNoCaseFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual);
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/TestFilter.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef TESTFILTER_H_
+#define TESTFILTER_H_
+
+#include "SimpleString.h"
+
+class TestFilter
+{
+public:
+
+ TestFilter();
+ TestFilter(const char* filter);
+ TestFilter(const SimpleString& filter);
+
+ bool match(const SimpleString& name) const;
+
+ void strictMatching();
+
+ bool operator==(const TestFilter& filter) const;
+ bool operator!=(const TestFilter& filter) const;
+
+ SimpleString asString() const;
+private:
+ SimpleString filter_;
+ bool strictMatching_;
+};
+
+SimpleString StringFrom(const TestFilter& filter);
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/CppUTest/TestHarness.h Tue Jan 28 09:27:41 2014 +0000 @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#ifndef D_TestHarness_h +#define D_TestHarness_h + +#include "CppUTestConfig.h" + +/* original value was 9973 which works well with large programs. Now set to smaller since it takes + * a lot of memory in embedded apps. Change it if you experience the memory leak detector to be slow. + */ + +#define MEMORY_LEAK_HASH_TABLE_SIZE 73 + +#include "Utest.h" +#include "UtestMacros.h" +#include "SimpleString.h" +#include "TestResult.h" +#include "TestFailure.h" +#include "TestPlugin.h" +#include "MemoryLeakWarningPlugin.h" +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/TestHarness_c.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+/******************************************************************************
+ *
+ * Provides an interface for when working with pure C
+ *
+ *******************************************************************************/
+
+#ifndef D_TestHarness_c_h
+#define D_TestHarness_c_h
+
+#include "CppUTestConfig.h"
+
+#define CHECK_EQUAL_C_INT(expected,actual) \
+ CHECK_EQUAL_C_INT_LOCATION(expected,actual,__FILE__,__LINE__)
+
+#define CHECK_EQUAL_C_REAL(expected,actual,threshold) \
+ CHECK_EQUAL_C_REAL_LOCATION(expected,actual,threshold,__FILE__,__LINE__)
+
+#define CHECK_EQUAL_C_CHAR(expected,actual) \
+ CHECK_EQUAL_C_CHAR_LOCATION(expected,actual,__FILE__,__LINE__)
+
+#define CHECK_EQUAL_C_STRING(expected,actual) \
+ CHECK_EQUAL_C_STRING_LOCATION(expected,actual,__FILE__,__LINE__)
+
+#define FAIL_TEXT_C(text) \
+ FAIL_TEXT_C_LOCATION(text,__FILE__,__LINE__)
+
+#define FAIL_C() \
+ FAIL_C_LOCATION(__FILE__,__LINE__)
+
+#define CHECK_C(condition) \
+ CHECK_C_LOCATION(condition, #condition, __FILE__,__LINE__)
+
+
+/******************************************************************************
+ *
+ * TEST macros for in C.
+ *
+ *******************************************************************************/
+
+/* For use in C file */
+#define TEST_GROUP_C_SETUP(group_name) \
+ extern void group_##group_name##_setup_wrapper_c(void); \
+ void group_##group_name##_setup_wrapper_c()
+
+#define TEST_GROUP_C_TEARDOWN(group_name) \
+ extern void group_##group_name##_teardown_wrapper_c(void); \
+ void group_##group_name##_teardown_wrapper_c()
+
+#define TEST_C(group_name, test_name) \
+ extern void test_##group_name##_##test_name##_wrapper_c(void);\
+ void test_##group_name##_##test_name##_wrapper_c()
+
+
+/* For use in C++ file */
+
+#define TEST_GROUP_C(group_name) \
+ extern "C" { \
+ extern void group_##group_name##_setup_wrapper_c(void); \
+ extern void group_##group_name##_teardown_wrapper_c(void); \
+ } \
+ TEST_GROUP(group_name)
+
+#define TEST_GROUP_C_SETUP_WRAPPER(group_name) \
+ void setup() { \
+ group_##group_name##_setup_wrapper_c(); \
+ }
+
+#define TEST_GROUP_C_TEARDOWN_WRAPPER(group_name) \
+ void teardown() { \
+ group_##group_name##_teardown_wrapper_c(); \
+ }
+
+#define TEST_GROUP_C_WRAPPER(group_name, test_name) \
+ extern "C" { \
+ extern void test_##group_name##_##test_name##_wrapper_c(); \
+ } \
+ TEST(group_name, test_name) { \
+ test_##group_name##_##test_name##_wrapper_c(); \
+ }
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/* CHECKS that can be used from C code */
+extern void CHECK_EQUAL_C_INT_LOCATION(int expected, int actual,
+ const char* fileName, int lineNumber);
+extern void CHECK_EQUAL_C_REAL_LOCATION(double expected, double actual,
+ double threshold, const char* fileName, int lineNumber);
+extern void CHECK_EQUAL_C_CHAR_LOCATION(char expected, char actual,
+ const char* fileName, int lineNumber);
+extern void CHECK_EQUAL_C_STRING_LOCATION(const char* expected,
+ const char* actual, const char* fileName, int lineNumber);
+extern void FAIL_TEXT_C_LOCATION(const char* text, const char* fileName,
+ int lineNumber);
+extern void FAIL_C_LOCATION(const char* fileName, int lineNumber);
+extern void CHECK_C_LOCATION(int condition, const char* conditionString,
+ const char* fileName, int lineNumber);
+
+extern void* cpputest_malloc(size_t size);
+extern void* cpputest_calloc(size_t num, size_t size);
+extern void* cpputest_realloc(void* ptr, size_t size);
+extern void cpputest_free(void* buffer);
+
+extern void* cpputest_malloc_location(size_t size, const char* file, int line);
+extern void* cpputest_calloc_location(size_t num, size_t size,
+ const char* file, int line);
+extern void* cpputest_realloc_location(void* memory, size_t size,
+ const char* file, int line);
+extern void cpputest_free_location(void* buffer, const char* file, int line);
+
+void cpputest_malloc_set_out_of_memory(void);
+void cpputest_malloc_set_not_out_of_memory(void);
+void cpputest_malloc_set_out_of_memory_countdown(int);
+void cpputest_malloc_count_reset(void);
+int cpputest_malloc_get_count(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*
+ * Small additional macro for unused arguments. This is common when stubbing, but in C you cannot remove the
+ * name of the parameter (as in C++).
+ */
+
+#ifndef PUNUSED
+#if defined(__GNUC__)
+# define PUNUSED(x) PUNUSED_ ##x __attribute__((unused))
+#else
+# define PUNUSED(x) x
+#endif
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/TestMemoryAllocator.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+#ifndef D_TestMemoryAllocator_h
+#define D_TestMemoryAllocator_h
+
+struct MemoryLeakNode;
+class TestMemoryAllocator;
+
+extern void setCurrentNewAllocator(TestMemoryAllocator* allocator);
+extern TestMemoryAllocator* getCurrentNewAllocator();
+extern void setCurrentNewAllocatorToDefault();
+extern TestMemoryAllocator* defaultNewAllocator();
+
+extern void setCurrentNewArrayAllocator(TestMemoryAllocator* allocator);
+extern TestMemoryAllocator* getCurrentNewArrayAllocator();
+extern void setCurrentNewArrayAllocatorToDefault();
+extern TestMemoryAllocator* defaultNewArrayAllocator();
+
+extern void setCurrentMallocAllocator(TestMemoryAllocator* allocator);
+extern TestMemoryAllocator* getCurrentMallocAllocator();
+extern void setCurrentMallocAllocatorToDefault();
+extern TestMemoryAllocator* defaultMallocAllocator();
+
+class TestMemoryAllocator
+{
+public:
+ TestMemoryAllocator(const char* name_str = "generic", const char* alloc_name_str = "alloc", const char* free_name_str = "free");
+ virtual ~TestMemoryAllocator();
+ bool hasBeenDestroyed();
+
+ virtual char* alloc_memory(size_t size, const char* file, int line);
+ virtual void free_memory(char* memory, const char* file, int line);
+
+ virtual const char* name();
+ virtual const char* alloc_name();
+ virtual const char* free_name();
+
+ virtual bool isOfEqualType(TestMemoryAllocator* allocator);
+
+ virtual char* allocMemoryLeakNode(size_t size);
+ virtual void freeMemoryLeakNode(char* memory);
+
+protected:
+
+ const char* name_;
+ const char* alloc_name_;
+ const char* free_name_;
+
+ bool hasBeenDestroyed_;
+};
+
+class CrashOnAllocationAllocator : public TestMemoryAllocator
+{
+ unsigned allocationToCrashOn_;
+public:
+ CrashOnAllocationAllocator();
+
+ virtual void setNumberToCrashOn(unsigned allocationToCrashOn);
+
+ virtual char* alloc_memory(size_t size, const char* file, int line) _override;
+};
+
+
+class NullUnknownAllocator: public TestMemoryAllocator
+{
+public:
+ NullUnknownAllocator();
+ virtual char* alloc_memory(size_t size, const char* file, int line) _override;
+ virtual void free_memory(char* memory, const char* file, int line) _override;
+
+ static TestMemoryAllocator* defaultAllocator();
+};
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/TestOutput.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+#ifndef D_TestOutput_h
+#define D_TestOutput_h
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// This is a minimal printer inteface.
+// We kept streams out too keep footprint small, and so the test
+// harness could be used with less capable compilers so more
+// platforms could use this test harness
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class UtestShell;
+class TestFailure;
+class TestResult;
+
+class TestOutput
+{
+public:
+ explicit TestOutput();
+ virtual ~TestOutput();
+
+ virtual void printTestsStarted();
+ virtual void printTestsEnded(const TestResult& result);
+ virtual void printCurrentTestStarted(const UtestShell& test);
+ virtual void printCurrentTestEnded(const TestResult& res);
+ virtual void printCurrentGroupStarted(const UtestShell& test);
+ virtual void printCurrentGroupEnded(const TestResult& res);
+
+ virtual void verbose();
+ virtual void printBuffer(const char*)=0;
+ virtual void print(const char*);
+ virtual void print(long);
+ virtual void printDouble(double);
+ virtual void printHex(long);
+ virtual void print(const TestFailure& failure);
+ virtual void printTestRun(int number, int total);
+ virtual void setProgressIndicator(const char*);
+
+ virtual void flush();
+
+ enum WorkingEnvironment {vistualStudio, eclipse, detectEnvironment};
+
+ static void setWorkingEnvironment(WorkingEnvironment workEnvironment);
+ static WorkingEnvironment getWorkingEnvironment();
+
+protected:
+
+ virtual void printEclipseErrorInFileOnLine(SimpleString file, int lineNumber);
+ virtual void printVistualStudioErrorInFileOnLine(SimpleString file, int lineNumber);
+
+ virtual void printProgressIndicator();
+ void printFileAndLineForTestAndFailure(const TestFailure& failure);
+ void printFileAndLineForFailure(const TestFailure& failure);
+ void printFailureInTest(SimpleString testName);
+ void printFailureMessage(SimpleString reason);
+ void printErrorInFileOnLineFormattedForWorkingEnvironment(SimpleString testFile, int lineNumber);
+
+ TestOutput(const TestOutput&);
+ TestOutput& operator=(const TestOutput&);
+
+ int dotCount_;
+ bool verbose_;
+ const char* progressIndication_;
+
+ static WorkingEnvironment workingEnvironment_;
+};
+
+TestOutput& operator<<(TestOutput&, const char*);
+TestOutput& operator<<(TestOutput&, long);
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// ConsoleTestOutput.h
+//
+// Printf Based Solution
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class ConsoleTestOutput: public TestOutput
+{
+public:
+ explicit ConsoleTestOutput()
+ {
+ }
+ virtual ~ConsoleTestOutput()
+ {
+ }
+
+ virtual void printBuffer(const char* s) _override;
+ virtual void flush() _override;
+
+private:
+ ConsoleTestOutput(const ConsoleTestOutput&);
+ ConsoleTestOutput& operator=(const ConsoleTestOutput&);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// StringBufferTestOutput.h
+//
+// TestOutput for test purposes
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+class StringBufferTestOutput: public TestOutput
+{
+public:
+ explicit StringBufferTestOutput()
+ {
+ }
+
+ virtual ~StringBufferTestOutput();
+
+ void printBuffer(const char* s) _override
+ {
+ output += s;
+ }
+
+ void flush() _override
+ {
+ output = "";
+ }
+
+ const SimpleString& getOutput()
+ {
+ return output;
+ }
+
+private:
+ SimpleString output;
+
+ StringBufferTestOutput(const StringBufferTestOutput&);
+ StringBufferTestOutput& operator=(const StringBufferTestOutput&);
+
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/TestPlugin.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#ifndef D_TestPlugin_h
+#define D_TestPlugin_h
+
+class UtestShell;
+class TestResult;
+
+class TestPlugin
+{
+public:
+
+ TestPlugin(const SimpleString& name);
+ virtual ~TestPlugin();
+
+ virtual void preTestAction(UtestShell&, TestResult&)
+ {
+ }
+
+ virtual void postTestAction(UtestShell&, TestResult&)
+ {
+ }
+
+ virtual bool parseArguments(int /* ac */, const char** /* av */, int /* index */ )
+ {
+ return false;
+ }
+
+ virtual void runAllPreTestAction(UtestShell&, TestResult&);
+ virtual void runAllPostTestAction(UtestShell&, TestResult&);
+ virtual bool parseAllArguments(int ac, const char** av, int index);
+ virtual bool parseAllArguments(int ac, char** av, int index);
+
+ virtual TestPlugin* addPlugin(TestPlugin*);
+ virtual TestPlugin* removePluginByName(const SimpleString& name);
+ virtual TestPlugin* getNext();
+
+ virtual void disable();
+ virtual void enable();
+ virtual bool isEnabled();
+
+ const SimpleString& getName();
+ TestPlugin* getPluginByName(const SimpleString& name);
+
+protected:
+ TestPlugin(TestPlugin* next_);
+
+private:
+ TestPlugin* next_;
+ SimpleString name_;
+ bool enabled_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// SetPointerPlugin
+//
+// This is a very small plugin_ that resets pointers to their original value.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+extern void CppUTestStore(void **location);
+
+class SetPointerPlugin: public TestPlugin
+{
+public:
+ SetPointerPlugin(const SimpleString& name);
+ virtual ~SetPointerPlugin();
+ virtual void postTestAction(UtestShell&, TestResult&) _override;
+
+ enum
+ {
+ MAX_SET = 1024
+ };
+};
+
+#define UT_PTR_SET(a, b) { CppUTestStore( (void**)&a ); a = b; }
+
+///////////// Null Plugin
+
+class NullTestPlugin: public TestPlugin
+{
+public:
+
+ NullTestPlugin();
+ virtual ~NullTestPlugin()
+ {
+ }
+
+ virtual void runAllPreTestAction(UtestShell& test, TestResult& result) _override;
+ virtual void runAllPostTestAction(UtestShell& test, TestResult& result) _override;
+
+ static NullTestPlugin* instance();
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/TestRegistry.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// TestRegistry is a collection of tests that can be run
+//
+
+#ifndef D_TestRegistry_h
+#define D_TestRegistry_h
+
+#include "SimpleString.h"
+#include "TestFilter.h"
+
+class UtestShell;
+class TestResult;
+class TestPlugin;
+
+class TestRegistry
+{
+public:
+ TestRegistry();
+ virtual ~TestRegistry();
+
+ virtual void addTest(UtestShell *test);
+ virtual void unDoLastAddTest();
+ virtual int countTests();
+ virtual void runAllTests(TestResult& result);
+ virtual void nameFilter(const TestFilter& filter);
+ virtual void groupFilter(const TestFilter& filter);
+
+ virtual void installPlugin(TestPlugin* plugin);
+ virtual void resetPlugins();
+ virtual TestPlugin* getFirstPlugin();
+ virtual TestPlugin* getPluginByName(const SimpleString& name);
+ virtual void removePluginByName(const SimpleString& name);
+ virtual int countPlugins();
+
+ TestFilter getGroupFilter();
+ TestFilter getNameFilter();
+
+ virtual UtestShell* getFirstTest();
+ virtual UtestShell* getLastTest();
+ virtual UtestShell* getTestWithNext(UtestShell* test);
+
+ virtual UtestShell* findTestWithName(const SimpleString& name);
+ virtual UtestShell* findTestWithGroup(const SimpleString& name);
+
+ static TestRegistry* getCurrentRegistry();
+ virtual void setCurrentRegistry(TestRegistry* registry);
+
+ virtual void setRunTestsInSeperateProcess();
+private:
+
+ bool testShouldRun(UtestShell* test, TestResult& result);
+ bool endOfGroup(UtestShell* test);
+
+ UtestShell * tests_;
+ TestFilter nameFilter_;
+ TestFilter groupFilter_;
+ TestPlugin* firstPlugin_;
+ static TestRegistry* currentRegistry_;
+ bool runInSeperateProcess_;
+
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/TestResult.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// A TestResult is a collection of the history of some test runs. Right now
+// it just collects failures. Really it just prints the failures.
+//
+
+#ifndef D_TestResult_h
+#define D_TestResult_h
+
+class TestFailure;
+class TestOutput;
+class UtestShell;
+
+class TestResult
+{
+public:
+ TestResult(TestOutput&);
+ virtual ~TestResult();
+
+ virtual void testsStarted();
+ virtual void testsEnded();
+ virtual void currentGroupStarted(UtestShell* test);
+ virtual void currentGroupEnded(UtestShell* test);
+ virtual void currentTestStarted(UtestShell* test);
+ virtual void currentTestEnded(UtestShell* test);
+
+ virtual void countTest();
+ virtual void countRun();
+ virtual void countCheck();
+ virtual void countFilteredOut();
+ virtual void countIgnored();
+ virtual void addFailure(const TestFailure& failure);
+ virtual void print(const char* text);
+ virtual void setProgressIndicator(const char*);
+
+ int getTestCount() const
+ {
+ return testCount_;
+ }
+ int getRunCount() const
+ {
+ return runCount_;
+ }
+ int getCheckCount() const
+ {
+ return checkCount_;
+ }
+ int getFilteredOutCount() const
+ {
+ return filteredOutCount_;
+ }
+ int getIgnoredCount() const
+ {
+ return ignoredCount_;
+ }
+ int getFailureCount() const
+ {
+ return failureCount_;
+ }
+
+ long getTotalExecutionTime() const;
+ void setTotalExecutionTime(long exTime);
+
+ long getCurrentTestTotalExecutionTime() const;
+ long getCurrentGroupTotalExecutionTime() const;
+private:
+
+ TestOutput& output_;
+ int testCount_;
+ int runCount_;
+ int checkCount_;
+ int failureCount_;
+ int filteredOutCount_;
+ int ignoredCount_;
+ long totalExecutionTime_;
+ long timeStarted_;
+ long currentTestTimeStarted_;
+ long currentTestTotalExecutionTime_;
+ long currentGroupTimeStarted_;
+ long currentGroupTotalExecutionTime_;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/TestTestingFixture.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+#ifndef D_TestTestingFixture_H
+#define D_TestTestingFixture_H
+
+#include "TestRegistry.h"
+#include "TestOutput.h"
+
+class TestTestingFixture
+{
+public:
+
+ TestTestingFixture()
+ {
+ output_ = new StringBufferTestOutput();
+ result_ = new TestResult(*output_);
+ genTest_ = new ExecFunctionTestShell();
+ registry_ = new TestRegistry();
+
+ registry_->setCurrentRegistry(registry_);
+ registry_->addTest(genTest_);
+ }
+
+ virtual ~TestTestingFixture()
+ {
+ registry_->setCurrentRegistry(0);
+ delete registry_;
+ delete result_;
+ delete output_;
+ delete genTest_;
+ }
+
+ void addTest(UtestShell * test)
+ {
+ registry_->addTest(test);
+ }
+
+ void setTestFunction(void(*testFunction)())
+ {
+ genTest_->testFunction_ = testFunction;
+ }
+
+ void setSetup(void(*setupFunction)())
+ {
+ genTest_->setup_ = setupFunction;
+ }
+
+ void setTeardown(void(*teardownFunction)())
+ {
+ genTest_->teardown_ = teardownFunction;
+ }
+
+ void runAllTests()
+ {
+ registry_->runAllTests(*result_);
+ }
+
+ int getFailureCount()
+ {
+ return result_->getFailureCount();
+ }
+
+ int getCheckCount()
+ {
+ return result_->getCheckCount();
+ }
+
+ int getIgnoreCount()
+ {
+ return result_->getIgnoredCount();
+ }
+
+ bool hasTestFailed()
+ {
+ return genTest_->hasFailed();
+ }
+
+
+ void assertPrintContains(const SimpleString& contains)
+ {
+ assertPrintContains(output_, contains);
+ }
+
+ static void assertPrintContains(StringBufferTestOutput* output,
+ const SimpleString& contains)
+ {
+ STRCMP_CONTAINS(contains.asCharString(), output->getOutput().asCharString());
+
+ }
+
+ TestRegistry* registry_;
+ ExecFunctionTestShell* genTest_;
+ StringBufferTestOutput* output_;
+ TestResult * result_;
+};
+
+class SetBooleanOnDestructorCall
+{
+ bool& booleanToSet_;
+public:
+ SetBooleanOnDestructorCall(bool& booleanToSet) : booleanToSet_(booleanToSet)
+ {
+ }
+
+ virtual ~SetBooleanOnDestructorCall()
+ {
+ booleanToSet_ = true;
+ }
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/Utest.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,269 @@
+/*
+ * 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.
+ */
+
+// This file contains the Test class along with the macros which make effective
+// in the harness.
+
+#ifndef D_UTest_h
+#define D_UTest_h
+
+#include "SimpleString.h"
+
+class TestResult;
+class TestPlugin;
+class TestFailure;
+class TestFilter;
+class TestTerminator;
+
+extern bool doubles_equal(double d1, double d2, double threshold);
+
+//////////////////// Utest
+
+class UtestShell;
+
+class Utest
+{
+public:
+ Utest();
+ virtual ~Utest();
+ virtual void run();
+
+ virtual void setup();
+ virtual void teardown();
+ virtual void testBody();
+};
+
+//////////////////// TestTerminator
+
+class TestTerminator
+{
+public:
+ virtual void exitCurrentTest() const=0;
+ virtual ~TestTerminator();
+};
+
+class NormalTestTerminator : public TestTerminator
+{
+public:
+ virtual void exitCurrentTest() const _override;
+ virtual ~NormalTestTerminator();
+};
+
+class TestTerminatorWithoutExceptions : public TestTerminator
+{
+public:
+ virtual void exitCurrentTest() const _override;
+ virtual ~TestTerminatorWithoutExceptions();
+};
+
+//////////////////// UtestShell
+
+class UtestShell
+{
+public:
+ static UtestShell *getCurrent();
+
+public:
+ UtestShell(const char* groupName, const char* testName, const char* fileName, int lineNumber);
+ virtual ~UtestShell();
+
+ virtual UtestShell* addTest(UtestShell* test);
+ virtual UtestShell *getNext() const;
+ virtual bool isNull() const;
+ virtual int countTests();
+
+ bool shouldRun(const TestFilter& groupFilter, const TestFilter& nameFilter) const;
+ const SimpleString getName() const;
+ const SimpleString getGroup() const;
+ virtual SimpleString getFormattedName() const;
+ const SimpleString getFile() const;
+ int getLineNumber() const;
+ virtual const char *getProgressIndicator() const;
+ virtual bool hasFailed() const;
+
+ virtual void assertTrue(bool condition, const char *checkString, const char *conditionString, const char *fileName, int lineNumber, const TestTerminator& testTerminator = NormalTestTerminator());
+ virtual void assertTrueText(bool condition, const char *checkString, const char *conditionString, const char* text, const char *fileName, int lineNumber, const TestTerminator& testTerminator = NormalTestTerminator());
+ virtual void assertCstrEqual(const char *expected, const char *actual, const char *fileName, int lineNumber, const TestTerminator& testTerminator = NormalTestTerminator());
+ 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 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());
+ virtual void fail(const char *text, const char *fileName, int lineNumber, const TestTerminator& testTerminator = NormalTestTerminator());
+
+ virtual void print(const char *text, const char *fileName, int lineNumber);
+ virtual void print(const SimpleString & text, const char *fileName, int lineNumber);
+
+ void setFileName(const char *fileName);
+ void setLineNumber(int lineNumber);
+ void setGroupName(const char *groupName);
+ void setTestName(const char *testName);
+
+ static void crash();
+ static void setCrashMethod(void (*crashme)());
+ static void resetCrashMethod();
+
+ virtual bool isRunInSeperateProcess() const;
+ virtual void setRunInSeperateProcess();
+
+ virtual Utest* createTest();
+ virtual void destroyTest(Utest* test);
+
+ virtual void runOneTest(TestPlugin* plugin, TestResult& result);
+ virtual void runOneTestInCurrentProcess(TestPlugin *plugin, TestResult & result);
+
+ virtual void failWith(const TestFailure& failure);
+ virtual void failWith(const TestFailure& failure, const TestTerminator& terminator);
+
+protected:
+ UtestShell();
+ UtestShell(const char *groupName, const char *testName, const char *fileName, int lineNumber, UtestShell *nextTest);
+
+ virtual SimpleString getMacroName() const;
+ TestResult *getTestResult();
+private:
+ const char *group_;
+ const char *name_;
+ const char *file_;
+ int lineNumber_;
+ UtestShell *next_;
+ bool isRunAsSeperateProcess_;
+ bool hasFailed_;
+
+ void setTestResult(TestResult* result);
+ void setCurrentTest(UtestShell* test);
+
+ static UtestShell* currentTest_;
+ static TestResult* testResult_;
+
+};
+
+//////////////////// NullTest
+
+class NullTestShell: public UtestShell
+{
+public:
+ explicit NullTestShell();
+ explicit NullTestShell(const char* fileName, int lineNumber);
+ virtual ~NullTestShell();
+
+ void testBody();
+
+ static NullTestShell& instance();
+
+ virtual int countTests() _override;
+ virtual UtestShell*getNext() const _override;
+ virtual bool isNull() const _override;
+private:
+
+ NullTestShell(const NullTestShell&);
+ NullTestShell& operator=(const NullTestShell&);
+
+};
+
+//////////////////// ExecFunctionTest
+
+class ExecFunctionTestShell;
+
+class ExecFunctionTest : public Utest
+{
+public:
+ ExecFunctionTest(ExecFunctionTestShell* shell);
+ void testBody();
+ virtual void setup() _override;
+ virtual void teardown() _override;
+private:
+ ExecFunctionTestShell* shell_;
+};
+
+//////////////////// ExecFunctionTestShell
+
+class ExecFunctionTestShell: public UtestShell
+{
+public:
+ void (*setup_)();
+ void (*teardown_)();
+ void (*testFunction_)();
+
+ ExecFunctionTestShell(void(*set)() = 0, void(*tear)() = 0) :
+ UtestShell("Generic", "Generic", "Generic", 1), setup_(set), teardown_(
+ tear), testFunction_(0)
+ {
+ }
+ Utest* createTest() { return new ExecFunctionTest(this); }
+ virtual ~ExecFunctionTestShell();
+};
+
+//////////////////// CppUTestFailedException
+
+class CppUTestFailedException
+{
+public:
+ int dummy_;
+};
+
+//////////////////// IgnoredTest
+
+class IgnoredUtestShell : public UtestShell
+{
+public:
+ IgnoredUtestShell();
+ virtual ~IgnoredUtestShell();
+ explicit IgnoredUtestShell(const char* groupName, const char* testName,
+ const char* fileName, int lineNumber);
+ virtual const char* getProgressIndicator() const;
+ protected: virtual SimpleString getMacroName() const _override;
+ virtual void runOneTest(TestPlugin* plugin, TestResult& result) _override;
+
+private:
+
+ IgnoredUtestShell(const IgnoredUtestShell&);
+ IgnoredUtestShell& operator=(const IgnoredUtestShell&);
+
+};
+
+//////////////////// TestInstaller
+
+class TestInstaller
+{
+public:
+ explicit TestInstaller(UtestShell& shell, const char* groupName, const char* testName,
+ const char* fileName, int lineNumber);
+ virtual ~TestInstaller();
+
+ void unDo();
+
+private:
+
+ TestInstaller(const TestInstaller&);
+ TestInstaller& operator=(const TestInstaller&);
+
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CppUTest/UtestMacros.h Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,219 @@
+/*
+ * 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.
+ */
+
+#ifndef D_UTestMacros_h
+#define D_UTestMacros_h
+
+/*! \brief Define a group of tests
+ *
+ * All tests in a TEST_GROUP share the same setup()
+ * and teardown(). setup() is run before the opening
+ * curly brace of each TEST and teardown() is
+ * called after the closing curly brace of TEST.
+ *
+ */
+
+
+#define TEST_GROUP_BASE(testGroup, baseclass) \
+ extern int externTestGroup##testGroup; \
+ int externTestGroup##testGroup = 0; \
+ struct TEST_GROUP_##CppUTestGroup##testGroup : public baseclass
+
+#define TEST_BASE(testBaseClass) \
+ struct testBaseClass : public Utest
+
+#define TEST_GROUP(testGroup) \
+ TEST_GROUP_BASE(testGroup, Utest)
+
+#define TEST_SETUP() \
+ virtual void setup()
+
+#define TEST_TEARDOWN() \
+ virtual void teardown()
+
+#define TEST(testGroup, testName) \
+ /* External declarations for strict compilers */ \
+ class TEST_##testGroup##_##testName##_TestShell; \
+ extern TEST_##testGroup##_##testName##_TestShell TEST_##testGroup##_##testName##_TestShell_instance; \
+ \
+ class TEST_##testGroup##_##testName##_Test : public TEST_GROUP_##CppUTestGroup##testGroup \
+{ public: TEST_##testGroup##_##testName##_Test () : TEST_GROUP_##CppUTestGroup##testGroup () {} \
+ void testBody(); }; \
+ class TEST_##testGroup##_##testName##_TestShell : public UtestShell { \
+ virtual Utest* createTest() _override { return new TEST_##testGroup##_##testName##_Test; } \
+ } TEST_##testGroup##_##testName##_TestShell_instance; \
+ static TestInstaller TEST_##testGroup##_##testName##_Installer(TEST_##testGroup##_##testName##_TestShell_instance, #testGroup, #testName, __FILE__,__LINE__); \
+ void TEST_##testGroup##_##testName##_Test::testBody()
+
+#define IGNORE_TEST(testGroup, testName)\
+ /* External declarations for strict compilers */ \
+ class IGNORE##testGroup##_##testName##_TestShell; \
+ extern IGNORE##testGroup##_##testName##_TestShell IGNORE##testGroup##_##testName##_TestShell_instance; \
+ \
+ class IGNORE##testGroup##_##testName##_Test : public TEST_GROUP_##CppUTestGroup##testGroup \
+{ public: IGNORE##testGroup##_##testName##_Test () : TEST_GROUP_##CppUTestGroup##testGroup () {} \
+ public: void testBodyThatNeverRuns (); }; \
+ class IGNORE##testGroup##_##testName##_TestShell : public IgnoredUtestShell { \
+ virtual Utest* createTest() _override { return new IGNORE##testGroup##_##testName##_Test; } \
+ } IGNORE##testGroup##_##testName##_TestShell_instance; \
+ static TestInstaller TEST_##testGroup##testName##_Installer(IGNORE##testGroup##_##testName##_TestShell_instance, #testGroup, #testName, __FILE__,__LINE__); \
+ void IGNORE##testGroup##_##testName##_Test::testBodyThatNeverRuns ()
+
+#define IMPORT_TEST_GROUP(testGroup) \
+ extern int externTestGroup##testGroup;\
+ extern int* p##testGroup; \
+ int* p##testGroup = &externTestGroup##testGroup
+
+// Different checking macros
+
+#define CHECK(condition)\
+ CHECK_LOCATION_TRUE(condition, "CHECK", #condition, __FILE__, __LINE__)
+
+#define CHECK_TEXT(condition, text) \
+ CHECK_LOCATION_TEXT(condition, "CHECK", #condition, text, __FILE__, __LINE__)
+
+#define CHECK_TRUE(condition)\
+ CHECK_LOCATION_TRUE(condition, "CHECK_TRUE", #condition, __FILE__, __LINE__)
+
+#define CHECK_FALSE(condition)\
+ CHECK_LOCATION_FALSE(condition, "CHECK_FALSE", #condition, __FILE__, __LINE__)
+
+#define CHECK_LOCATION_TEXT(condition, checkString, conditionString, text, file, line) \
+ { UtestShell::getCurrent()->assertTrueText((condition) != 0, checkString, conditionString, text, file, line); }
+
+#define CHECK_LOCATION_TRUE(condition, checkString, conditionString, file, line)\
+ { UtestShell::getCurrent()->assertTrue((condition) != 0, checkString, conditionString, file, line); }
+
+#define CHECK_LOCATION_FALSE(condition, checkString, conditionString, file, line)\
+ { UtestShell::getCurrent()->assertTrue((condition) == 0, checkString, conditionString, file, line); }
+
+//This check needs the operator!=(), and a StringFrom(YourType) function
+#define CHECK_EQUAL(expected,actual)\
+ CHECK_EQUAL_LOCATION(expected, actual, __FILE__, __LINE__)
+
+#define CHECK_EQUAL_LOCATION(expected,actual, file, line)\
+ { if ((expected) != (actual)) { \
+ if ((actual) != (actual)) \
+ UtestShell::getCurrent()->print("WARNING:\n\tThe \"Actual Parameter\" parameter is evaluated multiple times resulting in different values.\n\tThus the value in the error message is probably incorrect.", file, line); \
+ 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); \
+ } }
+
+//This check checks for char* string equality using strcmp.
+//This makes up for the fact that CHECK_EQUAL only compares the pointers to char*'s
+#define STRCMP_EQUAL(expected,actual)\
+ STRCMP_EQUAL_LOCATION(expected, actual, __FILE__, __LINE__)
+
+#define STRCMP_EQUAL_LOCATION(expected,actual, file, line)\
+ { UtestShell::getCurrent()->assertCstrEqual(expected, actual, file, line); }
+
+#define STRCMP_NOCASE_EQUAL(expected,actual)\
+ STRCMP_NOCASE_EQUAL_LOCATION(expected, actual, __FILE__, __LINE__)
+
+#define STRCMP_NOCASE_EQUAL_LOCATION(expected,actual, file, line)\
+ { UtestShell::getCurrent()->assertCstrNoCaseEqual(expected, actual, file, line); }
+
+#define STRCMP_CONTAINS(expected,actual)\
+ STRCMP_CONTAINS_LOCATION(expected, actual, __FILE__, __LINE__)
+
+#define STRCMP_CONTAINS_LOCATION(expected,actual, file, line)\
+ { UtestShell::getCurrent()->assertCstrContains(expected, actual, file, line); }
+
+#define STRCMP_NOCASE_CONTAINS(expected,actual)\
+ STRCMP_NOCASE_CONTAINS_LOCATION(expected, actual, __FILE__, __LINE__)
+
+#define STRCMP_NOCASE_CONTAINS_LOCATION(expected,actual, file, line)\
+ { UtestShell::getCurrent()->assertCstrNoCaseContains(expected, actual, file, line); }
+
+//Check two long integers for equality
+#define LONGS_EQUAL(expected,actual)\
+ 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 BYTES_EQUAL(expected, actual)\
+ LONGS_EQUAL((expected) & 0xff,(actual) & 0xff)
+
+#define POINTERS_EQUAL(expected, actual)\
+ POINTERS_EQUAL_LOCATION((expected),(actual), __FILE__, __LINE__)
+
+#define POINTERS_EQUAL_LOCATION(expected,actual,file,line)\
+ { UtestShell::getCurrent()->assertPointersEqual((void *)expected, (void *)actual, file, line); }
+
+//Check two doubles for equality within a tolerance threshold
+#define DOUBLES_EQUAL(expected,actual,threshold)\
+ DOUBLES_EQUAL_LOCATION(expected,actual,threshold,__FILE__,__LINE__)
+
+#define DOUBLES_EQUAL_LOCATION(expected,actual,threshold,file,line)\
+ { UtestShell::getCurrent()->assertDoublesEqual(expected, actual, threshold, file, line); }
+
+//Fail if you get to this macro
+//The macro FAIL may already be taken, so allow FAIL_TEST too
+#ifndef FAIL
+#define FAIL(text)\
+ FAIL_LOCATION(text, __FILE__,__LINE__)
+
+#define FAIL_LOCATION(text, file, line)\
+ { UtestShell::getCurrent()->fail(text, file, line); }
+#endif
+
+#define FAIL_TEST(text)\
+ FAIL_TEST_LOCATION(text, __FILE__,__LINE__)
+
+#define FAIL_TEST_LOCATION(text, file,line)\
+ { UtestShell::getCurrent()->fail(text, file, line); }
+
+#define UT_PRINT_LOCATION(text, file, line) \
+ { UtestShell::getCurrent()->print(text, file, line); }
+
+#define UT_PRINT(text) \
+ UT_PRINT_LOCATION(text, __FILE__, __LINE__)
+
+#if CPPUTEST_USE_STD_CPP_LIB
+#define CHECK_THROWS(expected, expression) \
+ { \
+ SimpleString msg("expected to throw "#expected "\nbut threw nothing"); \
+ bool caught_expected = false; \
+ try { \
+ (expression); \
+ } catch(const expected &) { \
+ caught_expected = true; \
+ } catch(...) { \
+ msg = "expected to throw " #expected "\nbut threw a different type"; \
+ } \
+ if (!caught_expected) { \
+ UtestShell::getCurrent()->fail(msg.asCharString(), __FILE__, __LINE__); \
+ } \
+ }
+#endif /* CPPUTEST_USE_STD_CPP_LIB */
+
+#define UT_CRASH() { UtestShell::crash(); }
+#define RUN_ALL_TESTS(ac, av) CommandLineTestRunner::RunAllTests(ac, av)
+
+#endif /*D_UTestMacros_h*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/CommandLineArguments.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,179 @@
+/*
+ * 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;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/CommandLineTestRunner.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,143 @@
+/*
+ * 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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/JUnitTestOutput.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,270 @@
+/*
+ * 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_);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/MemoryLeakDetector.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +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);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/MemoryLeakWarningPlugin.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,454 @@
+/*
+ * 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 "";
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/SimpleString.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,515 @@
+/*
+ * 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];
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/TestFailure.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,252 @@
+/*
+ * 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);
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/TestFilter.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,79 @@
+/*
+ * 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/CppUTestConfig.h"
+#include "CppUTest/TestFilter.h"
+
+TestFilter::TestFilter() : strictMatching_(false)
+{
+}
+
+TestFilter::TestFilter(const SimpleString& filter) : strictMatching_(false)
+{
+ filter_ = filter;
+}
+
+TestFilter::TestFilter(const char* filter) : strictMatching_(false)
+{
+ filter_ = filter;
+}
+
+void TestFilter::strictMatching()
+{
+ strictMatching_ = true;
+}
+
+bool TestFilter::match(const SimpleString& name) const
+{
+ if (strictMatching_)
+ return name == filter_;
+ return name.contains(filter_);
+}
+
+bool TestFilter::operator==(const TestFilter& filter) const
+{
+ return (filter_ == filter.filter_ && strictMatching_ == filter.strictMatching_);
+}
+
+bool TestFilter::operator!=(const TestFilter& filter) const
+{
+ return !(filter == *this);
+}
+
+SimpleString TestFilter::asString() const
+{
+ SimpleString textFilter = StringFromFormat("TestFilter: \"%s\"", filter_.asCharString());
+ if (strictMatching_)
+ textFilter += " with strict matching";
+ return textFilter;
+}
+
+SimpleString StringFrom(const TestFilter& filter)
+{
+ return filter.asString();
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/TestHarness_c.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +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);
+ 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);
+}
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/TestMemoryAllocator.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/TestOutput.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +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()
+{
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/TestPlugin.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +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&)
+{
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/TestRegistry.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +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;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/TestResult.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +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_;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/Utest.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,660 @@
+/*
+ * 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"
+#include "CppUTest/PlatformSpecificFunctions.h"
+#include "CppUTest/TestOutput.h"
+
+bool doubles_equal(double d1, double d2, double threshold)
+{
+ if (PlatformSpecificIsNan(d1) || PlatformSpecificIsNan(d2) || PlatformSpecificIsNan(threshold))
+ return false;
+ return PlatformSpecificFabs(d1 - d2) <= threshold;
+}
+
+/* Sometimes stubs use the CppUTest assertions.
+ * Its not correct to do so, but this small helper class will prevent a segmentation fault and instead
+ * will give an error message and also the file/line of the check that was executed outside the tests.
+ */
+class OutsideTestRunnerUTest: public UtestShell
+{
+public:
+ static OutsideTestRunnerUTest& instance();
+ virtual TestResult& getTestResult()
+ {
+ return defaultTestResult;
+ }
+ virtual void exitCurrentTest()
+ {
+ }
+ virtual ~OutsideTestRunnerUTest()
+ {
+ }
+private:
+ OutsideTestRunnerUTest() :
+ UtestShell("\n\t NOTE: Assertion happened without being in a test run (perhaps in main?)", "\n\t Something is very wrong. Check this assertion and fix", "unknown file", 0),
+ defaultTestResult(defaultOutput)
+ {
+ }
+ ConsoleTestOutput defaultOutput;
+ TestResult defaultTestResult;
+};
+
+OutsideTestRunnerUTest& OutsideTestRunnerUTest::instance()
+{
+ static OutsideTestRunnerUTest instance_;
+ return instance_;
+}
+
+/*
+ * Below helpers are used for the PlatformSpecificSetJmp and LongJmp. They pass a method for what needs to happen after
+ * the jump, so that the stack stays right.
+ *
+ */
+
+extern "C" {
+
+ static void helperDoTestSetup(void* data)
+ {
+ ((Utest*)data)->setup();
+ }
+
+ static void helperDoTestBody(void* data)
+ {
+ ((Utest*)data)->testBody();
+ }
+
+ static void helperDoTestTeardown(void* data)
+ {
+ ((Utest*)data)->teardown();
+ }
+
+ struct HelperTestRunInfo
+ {
+ HelperTestRunInfo(UtestShell* shell, TestPlugin* plugin, TestResult* result) : shell_(shell), plugin_(plugin), result_(result){}
+
+ UtestShell* shell_;
+ TestPlugin* plugin_;
+ TestResult* result_;
+ };
+
+ static void helperDoRunOneTestInCurrentProcess(void* data)
+ {
+ HelperTestRunInfo* runInfo = (HelperTestRunInfo*) data;
+
+ UtestShell* shell = runInfo->shell_;
+ TestPlugin* plugin = runInfo->plugin_;
+ TestResult* result = runInfo->result_;
+
+ shell->runOneTestInCurrentProcess(plugin, *result);
+ }
+
+ static void helperDoRunOneTestSeperateProcess(void* data)
+ {
+ HelperTestRunInfo* runInfo = (HelperTestRunInfo*) data;
+
+ UtestShell* shell = runInfo->shell_;
+ TestPlugin* plugin = runInfo->plugin_;
+ TestResult* result = runInfo->result_;
+ PlatformSpecificRunTestInASeperateProcess(shell, plugin, result);
+ }
+
+}
+
+/******************************** */
+
+UtestShell::UtestShell() :
+ group_("UndefinedTestGroup"), name_("UndefinedTest"), file_("UndefinedFile"), lineNumber_(0), next_(&NullTestShell::instance()), isRunAsSeperateProcess_(false), hasFailed_(false)
+{
+}
+
+UtestShell::UtestShell(const char* groupName, const char* testName, const char* fileName, int lineNumber) :
+ group_(groupName), name_(testName), file_(fileName), lineNumber_(lineNumber), next_(&NullTestShell::instance()), isRunAsSeperateProcess_(false), hasFailed_(false)
+{
+}
+
+UtestShell::UtestShell(const char* groupName, const char* testName, const char* fileName, int lineNumber, UtestShell* nextTest) :
+ group_(groupName), name_(testName), file_(fileName), lineNumber_(lineNumber), next_(nextTest), isRunAsSeperateProcess_(false), hasFailed_(false)
+{
+}
+
+UtestShell::~UtestShell()
+{
+}
+
+static void defaultCrashMethod()
+{
+ UtestShell* ptr = (UtestShell*) 0x0; ptr->countTests();
+}
+
+static void (*pleaseCrashMeRightNow) () = defaultCrashMethod;
+
+void UtestShell::setCrashMethod(void (*crashme)())
+{
+ pleaseCrashMeRightNow = crashme;
+}
+
+void UtestShell::resetCrashMethod()
+{
+ pleaseCrashMeRightNow = defaultCrashMethod;
+}
+
+void UtestShell::crash()
+{
+ pleaseCrashMeRightNow();
+}
+
+void UtestShell::runOneTest(TestPlugin* plugin, TestResult& result)
+{
+ HelperTestRunInfo runInfo(this, plugin, &result);
+ if (isRunInSeperateProcess())
+ PlatformSpecificSetJmp(helperDoRunOneTestSeperateProcess, &runInfo);
+ else
+ PlatformSpecificSetJmp(helperDoRunOneTestInCurrentProcess, &runInfo);
+}
+
+Utest* UtestShell::createTest()
+{
+ return new Utest();
+}
+
+void UtestShell::destroyTest(Utest* test)
+{
+ delete test;
+}
+
+void UtestShell::runOneTestInCurrentProcess(TestPlugin* plugin, TestResult& result)
+{
+ plugin->runAllPreTestAction(*this, result);
+
+ //save test context, so that test class can be tested
+ UtestShell* savedTest = UtestShell::getCurrent();
+ TestResult* savedResult = UtestShell::getTestResult();
+
+ result.countRun();
+ UtestShell::setTestResult(&result);
+ UtestShell::setCurrentTest(this);
+
+ Utest* testToRun = createTest();
+ testToRun->run();
+ destroyTest(testToRun);
+
+ UtestShell::setCurrentTest(savedTest);
+ UtestShell::setTestResult(savedResult);
+
+ plugin->runAllPostTestAction(*this, result);
+}
+
+UtestShell *UtestShell::getNext() const
+{
+ return next_;
+}
+
+UtestShell* UtestShell::addTest(UtestShell *test)
+{
+ next_ = test;
+ return this;
+}
+
+int UtestShell::countTests()
+{
+ return next_->countTests() + 1;
+}
+
+bool UtestShell::isNull() const
+{
+ return false;
+}
+
+SimpleString UtestShell::getMacroName() const
+{
+ return "TEST";
+}
+
+const SimpleString UtestShell::getName() const
+{
+ return SimpleString(name_);
+}
+
+const SimpleString UtestShell::getGroup() const
+{
+ return SimpleString(group_);
+}
+
+SimpleString UtestShell::getFormattedName() const
+{
+ SimpleString formattedName(getMacroName());
+ formattedName += "(";
+ formattedName += group_;
+ formattedName += ", ";
+ formattedName += name_;
+ formattedName += ")";
+
+ return formattedName;
+}
+
+bool UtestShell::hasFailed() const
+{
+ return hasFailed_;
+}
+
+const char* UtestShell::getProgressIndicator() const
+{
+ return ".";
+}
+
+bool UtestShell::isRunInSeperateProcess() const
+{
+ return isRunAsSeperateProcess_;
+}
+
+void UtestShell::setRunInSeperateProcess()
+{
+ isRunAsSeperateProcess_ = true;
+}
+
+
+void UtestShell::setFileName(const char* fileName)
+{
+ file_ = fileName;
+}
+
+void UtestShell::setLineNumber(int lineNumber)
+{
+ lineNumber_ = lineNumber;
+}
+
+void UtestShell::setGroupName(const char* groupName)
+{
+ group_ = groupName;
+}
+
+void UtestShell::setTestName(const char* testName)
+{
+ name_ = testName;
+}
+
+const SimpleString UtestShell::getFile() const
+{
+ return SimpleString(file_);
+}
+
+int UtestShell::getLineNumber() const
+{
+ return lineNumber_;
+}
+
+bool UtestShell::shouldRun(const TestFilter& groupFilter, const TestFilter& nameFilter) const
+{
+ if (groupFilter.match(group_) && nameFilter.match(name_)) return true;
+
+ return false;
+}
+
+void UtestShell::failWith(const TestFailure& failure)
+{
+ failWith(failure, NormalTestTerminator());
+}
+
+void UtestShell::failWith(const TestFailure& failure, const TestTerminator& terminator)
+{
+ hasFailed_ = true;
+ getTestResult()->addFailure(failure);
+ terminator.exitCurrentTest();
+}
+
+void UtestShell::assertTrue(bool condition, const char * checkString, const char* conditionString, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+{
+ assertTrueText(condition, checkString, conditionString, "", fileName, lineNumber, testTerminator);
+}
+
+void UtestShell::assertTrueText(bool condition, const char *checkString, const char *conditionString, const char* text, const char *fileName, int lineNumber, const TestTerminator& testTerminator)
+{
+ getTestResult()->countCheck();
+ if (!condition)
+ failWith(CheckFailure(this, fileName, lineNumber, checkString, conditionString, text), testTerminator);
+}
+
+void UtestShell::fail(const char *text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+{
+ getTestResult()->countCheck();
+ failWith(FailFailure(this, fileName, lineNumber, text), testTerminator);
+}
+
+void UtestShell::assertCstrEqual(const char* expected, const char* actual, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+{
+ getTestResult()->countCheck();
+ if (actual == 0 && expected == 0) return;
+ if (actual == 0 || expected == 0)
+ failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual), testTerminator);
+ if (PlatformSpecificStrCmp(expected, actual) != 0)
+ failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual), testTerminator);
+}
+
+void UtestShell::assertCstrNoCaseEqual(const char* expected, const char* actual, const char* fileName, int lineNumber)
+{
+ getTestResult()->countCheck();
+ if (actual == 0 && expected == 0) return;
+ if (actual == 0 || expected == 0)
+ failWith(StringEqualNoCaseFailure(this, fileName, lineNumber, expected, actual));
+ if (!SimpleString(expected).equalsNoCase(actual))
+ failWith(StringEqualNoCaseFailure(this, fileName, lineNumber, expected, actual));
+}
+
+void UtestShell::assertCstrContains(const char* expected, const char* actual, const char* fileName, int lineNumber)
+{
+ getTestResult()->countCheck();
+ if (actual == 0 && expected == 0) return;
+ if(actual == 0 || expected == 0)
+ failWith(ContainsFailure(this, fileName, lineNumber, expected, actual));
+ if (!SimpleString(actual).contains(expected))
+ failWith(ContainsFailure(this, fileName, lineNumber, expected, actual));
+}
+
+void UtestShell::assertCstrNoCaseContains(const char* expected, const char* actual, const char* fileName, int lineNumber)
+{
+ getTestResult()->countCheck();
+ if (actual == 0 && expected == 0) return;
+ if(actual == 0 || expected == 0)
+ failWith(ContainsFailure(this, fileName, lineNumber, expected, actual));
+ if (!SimpleString(actual).containsNoCase(expected))
+ failWith(ContainsFailure(this, fileName, lineNumber, expected, actual));
+}
+
+void UtestShell::assertLongsEqual(long expected, long actual, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+{
+ getTestResult()->countCheck();
+ if (expected != actual)
+ failWith(LongsEqualFailure (this, fileName, lineNumber, expected, actual), testTerminator);
+}
+
+void UtestShell::assertPointersEqual(const void* expected, const void* actual, const char* fileName, int lineNumber)
+{
+ getTestResult()->countCheck();
+ if (expected != actual)
+ failWith(EqualsFailure(this, fileName, lineNumber, StringFrom(expected), StringFrom(actual)));
+}
+
+void UtestShell::assertDoublesEqual(double expected, double actual, double threshold, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+{
+ getTestResult()->countCheck();
+ if (!doubles_equal(expected, actual, threshold))
+ failWith(DoublesEqualFailure(this, fileName, lineNumber, expected, actual, threshold), testTerminator);
+}
+
+void UtestShell::assertEquals(bool failed, const char* expected, const char* actual, const char* file, int line, const TestTerminator& testTerminator)
+{
+ getTestResult()->countCheck();
+ if (failed)
+ failWith(CheckEqualFailure(this, file, line, expected, actual), testTerminator);
+}
+
+
+void UtestShell::print(const char *text, const char* fileName, int lineNumber)
+{
+ SimpleString stringToPrint = "\n";
+ stringToPrint += fileName;
+ stringToPrint += ":";
+ stringToPrint += StringFrom(lineNumber);
+ stringToPrint += " ";
+ stringToPrint += text;
+ getTestResult()->print(stringToPrint.asCharString());
+}
+
+void UtestShell::print(const SimpleString& text, const char* fileName, int lineNumber)
+{
+ print(text.asCharString(), fileName, lineNumber);
+}
+
+TestResult* UtestShell::testResult_ = NULL;
+UtestShell* UtestShell::currentTest_ = NULL;
+
+void UtestShell::setTestResult(TestResult* result)
+{
+ testResult_ = result;
+}
+
+void UtestShell::setCurrentTest(UtestShell* test)
+{
+ currentTest_ = test;
+}
+
+TestResult* UtestShell::getTestResult()
+{
+ if (testResult_ == NULL)
+ return &OutsideTestRunnerUTest::instance().getTestResult();
+ return testResult_;
+}
+
+UtestShell* UtestShell::getCurrent()
+{
+ if (currentTest_ == NULL)
+ return &OutsideTestRunnerUTest::instance();
+ return currentTest_;
+}
+
+
+ExecFunctionTestShell::~ExecFunctionTestShell()
+{
+}
+
+////////////// Utest ////////////
+
+Utest::Utest()
+{
+}
+
+Utest::~Utest()
+{
+}
+
+#if CPPUTEST_USE_STD_CPP_LIB
+
+void Utest::run()
+{
+ try {
+ if (PlatformSpecificSetJmp(helperDoTestSetup, this)) {
+ PlatformSpecificSetJmp(helperDoTestBody, this);
+ }
+ }
+ catch (CppUTestFailedException&)
+ {
+ PlatformSpecificRestoreJumpBuffer();
+ }
+
+ try {
+ PlatformSpecificSetJmp(helperDoTestTeardown, this);
+ }
+ catch (CppUTestFailedException&)
+ {
+ PlatformSpecificRestoreJumpBuffer();
+ }
+
+}
+#else
+
+void Utest::run()
+{
+ if (PlatformSpecificSetJmp(helperDoTestSetup, this)) {
+ PlatformSpecificSetJmp(helperDoTestBody, this);
+ }
+ PlatformSpecificSetJmp(helperDoTestTeardown, this);
+}
+
+#endif
+
+void Utest::setup()
+{
+}
+
+void Utest::testBody()
+{
+}
+
+void Utest::teardown()
+{
+}
+
+
+////////////// NullTestShell ////////////
+
+
+NullTestShell::NullTestShell() :
+ UtestShell("NullGroup", "NullName", "NullFile", -1, 0)
+{
+}
+
+NullTestShell::NullTestShell(const char* fileName, int lineNumber) :
+ UtestShell("NullGroup", "NullName", fileName, lineNumber, 0)
+{
+}
+
+NullTestShell::~NullTestShell()
+{
+}
+
+NullTestShell& NullTestShell::instance()
+{
+ static NullTestShell _instance;
+ return _instance;
+}
+
+int NullTestShell::countTests()
+{
+ return 0;
+}
+
+UtestShell* NullTestShell::getNext() const
+{
+ return &instance();
+}
+
+bool NullTestShell::isNull() const
+{
+ return true;
+}
+
+void NullTestShell::testBody()
+{
+}
+
+
+/////////////////// Terminators
+
+TestTerminator::~TestTerminator()
+{
+}
+
+void NormalTestTerminator::exitCurrentTest() const
+{
+ #if CPPUTEST_USE_STD_CPP_LIB
+ throw CppUTestFailedException();
+ #else
+ TestTerminatorWithoutExceptions().exitCurrentTest();
+ #endif
+}
+
+NormalTestTerminator::~NormalTestTerminator()
+{
+}
+
+void TestTerminatorWithoutExceptions::exitCurrentTest() const
+{
+ PlatformSpecificLongJmp();
+}
+
+TestTerminatorWithoutExceptions::~TestTerminatorWithoutExceptions()
+{
+}
+
+//////////////////// ExecFunctionTest
+
+ExecFunctionTest::ExecFunctionTest(ExecFunctionTestShell* shell)
+ : shell_(shell)
+{
+}
+
+void ExecFunctionTest::testBody()
+{
+ if (shell_->testFunction_) shell_->testFunction_();
+}
+
+void ExecFunctionTest::setup()
+{
+ if (shell_->setup_) shell_->setup_();
+}
+
+void ExecFunctionTest::teardown()
+{
+ if (shell_->teardown_) shell_->teardown_();
+}
+
+/////////////// IgnoredUtestShell /////////////
+IgnoredUtestShell::IgnoredUtestShell()
+{
+}
+
+IgnoredUtestShell::~IgnoredUtestShell()
+{
+}
+
+const char* IgnoredUtestShell::getProgressIndicator() const
+{
+ return "!";
+}
+
+SimpleString IgnoredUtestShell::getMacroName() const
+{
+ return "IGNORE_TEST";
+}
+
+void IgnoredUtestShell::runOneTest(TestPlugin* /* plugin */, TestResult& result)
+{
+ result.countIgnored();
+}
+
+
+////////////// TestInstaller ////////////
+
+TestInstaller::TestInstaller(UtestShell& shell, const char* groupName, const char* testName, const char* fileName, int lineNumber)
+{
+ shell.setGroupName(groupName);
+ shell.setTestName(testName);
+ shell.setFileName(fileName);
+ shell.setLineNumber(lineNumber);
+ TestRegistry::getCurrentRegistry()->addTest(&shell);
+}
+
+TestInstaller::~TestInstaller()
+{
+}
+
+void TestInstaller::unDo()
+{
+ TestRegistry::getCurrentRegistry()->unDoLastAddTest();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Platforms/mbed/UtestPlatform.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,312 @@
+/*
+ * 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);
+}