CppUTest is a C /C++ based unit xUnit test framework for unit testing and for test-driving your code.

CppUTest

Where to find more information

Getting test reports on the console

You may need to tailor the file src/Platforms/mbed/UtestPlatform.cpp to your needs. In particular, if you want console output, you might want to look at the function PlatformSpecificPutchar().

Quick introduction (some code!)

To write your first test, all you need is a new cpp file with a TEST_GROUP and a TEST, like:

#include "CppUTest/TestHarness.h"

TEST_GROUP(FirstTestGroup)
{
};

TEST(FirstTestGroup, FirstTest)
{
   FAIL("Fail me!");
}

This test will fail.

You can add new tests to the test group by just writing more tests in the file, like this:

TEST(FirstTestGroup, SecondTest)
{
   STRCMP_EQUAL("hello", "world");
   LONGS_EQUAL(1, 2);
   CHECK(false);
}

You do need to trigger the tests from somewhere in your program. It could look something like:

#include "CppUTest/TestRegistry.h"
#include "CppUTest/CommandLineTestRunner.h"

int main(int ac, char** av)
{
    ....
    unsigned failureCount = 0;
    {
        ConsoleTestOutput output;
        CommandLineTestRunner runner(ac, av, &output, TestRegistry::getCurrentRegistry());
        failureCount = runner.runAllTestsMain();
    }

    if (failureCount == 0) {
        console.printf("PASSED\r\n");
    }
    ...
}

For more information, We’d recommend to read the manual or, even better, check some existing tests such as SimpleStringTest or (a bit more complicated) MemoryLeakDetectorTest or the mocking tests or just check out the Cheat Sheet.

Committer:
rgrover1
Date:
Tue Jan 28 09:27:41 2014 +0000
Revision:
0:0b799af9d58e
CppUTest unit test framework.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 0:0b799af9d58e 1 /*
rgrover1 0:0b799af9d58e 2 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
rgrover1 0:0b799af9d58e 3 * All rights reserved.
rgrover1 0:0b799af9d58e 4 *
rgrover1 0:0b799af9d58e 5 * Redistribution and use in source and binary forms, with or without
rgrover1 0:0b799af9d58e 6 * modification, are permitted provided that the following conditions are met:
rgrover1 0:0b799af9d58e 7 * * Redistributions of source code must retain the above copyright
rgrover1 0:0b799af9d58e 8 * notice, this list of conditions and the following disclaimer.
rgrover1 0:0b799af9d58e 9 * * Redistributions in binary form must reproduce the above copyright
rgrover1 0:0b799af9d58e 10 * notice, this list of conditions and the following disclaimer in the
rgrover1 0:0b799af9d58e 11 * documentation and/or other materials provided with the distribution.
rgrover1 0:0b799af9d58e 12 * * Neither the name of the <organization> nor the
rgrover1 0:0b799af9d58e 13 * names of its contributors may be used to endorse or promote products
rgrover1 0:0b799af9d58e 14 * derived from this software without specific prior written permission.
rgrover1 0:0b799af9d58e 15 *
rgrover1 0:0b799af9d58e 16 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
rgrover1 0:0b799af9d58e 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
rgrover1 0:0b799af9d58e 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
rgrover1 0:0b799af9d58e 19 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
rgrover1 0:0b799af9d58e 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
rgrover1 0:0b799af9d58e 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
rgrover1 0:0b799af9d58e 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
rgrover1 0:0b799af9d58e 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
rgrover1 0:0b799af9d58e 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
rgrover1 0:0b799af9d58e 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
rgrover1 0:0b799af9d58e 26 */
rgrover1 0:0b799af9d58e 27
rgrover1 0:0b799af9d58e 28 #ifndef D_MemoryLeakDetector_h
rgrover1 0:0b799af9d58e 29 #define D_MemoryLeakDetector_h
rgrover1 0:0b799af9d58e 30
rgrover1 0:0b799af9d58e 31 enum MemLeakPeriod
rgrover1 0:0b799af9d58e 32 {
rgrover1 0:0b799af9d58e 33 mem_leak_period_all,
rgrover1 0:0b799af9d58e 34 mem_leak_period_disabled,
rgrover1 0:0b799af9d58e 35 mem_leak_period_enabled,
rgrover1 0:0b799af9d58e 36 mem_leak_period_checking
rgrover1 0:0b799af9d58e 37 };
rgrover1 0:0b799af9d58e 38
rgrover1 0:0b799af9d58e 39 class TestMemoryAllocator;
rgrover1 0:0b799af9d58e 40
rgrover1 0:0b799af9d58e 41 class MemoryLeakFailure
rgrover1 0:0b799af9d58e 42 {
rgrover1 0:0b799af9d58e 43 public:
rgrover1 0:0b799af9d58e 44 virtual ~MemoryLeakFailure()
rgrover1 0:0b799af9d58e 45 {
rgrover1 0:0b799af9d58e 46 }
rgrover1 0:0b799af9d58e 47
rgrover1 0:0b799af9d58e 48 virtual void fail(char* fail_string)=0;
rgrover1 0:0b799af9d58e 49 };
rgrover1 0:0b799af9d58e 50
rgrover1 0:0b799af9d58e 51 struct SimpleStringBuffer
rgrover1 0:0b799af9d58e 52 {
rgrover1 0:0b799af9d58e 53 enum
rgrover1 0:0b799af9d58e 54 {
rgrover1 0:0b799af9d58e 55 SIMPLE_STRING_BUFFER_LEN = 4096
rgrover1 0:0b799af9d58e 56 };
rgrover1 0:0b799af9d58e 57
rgrover1 0:0b799af9d58e 58 SimpleStringBuffer();
rgrover1 0:0b799af9d58e 59 void clear();
rgrover1 0:0b799af9d58e 60 void add(const char* format, ...) __check_format__(printf, 2, 3);
rgrover1 0:0b799af9d58e 61 char* toString();
rgrover1 0:0b799af9d58e 62
rgrover1 0:0b799af9d58e 63 void setWriteLimit(size_t write_limit);
rgrover1 0:0b799af9d58e 64 void resetWriteLimit();
rgrover1 0:0b799af9d58e 65 bool reachedItsCapacity();
rgrover1 0:0b799af9d58e 66 private:
rgrover1 0:0b799af9d58e 67 char buffer_[SIMPLE_STRING_BUFFER_LEN];
rgrover1 0:0b799af9d58e 68 size_t positions_filled_;
rgrover1 0:0b799af9d58e 69 size_t write_limit_;
rgrover1 0:0b799af9d58e 70 };
rgrover1 0:0b799af9d58e 71
rgrover1 0:0b799af9d58e 72 struct MemoryLeakDetectorNode;
rgrover1 0:0b799af9d58e 73
rgrover1 0:0b799af9d58e 74 class MemoryLeakOutputStringBuffer
rgrover1 0:0b799af9d58e 75 {
rgrover1 0:0b799af9d58e 76 public:
rgrover1 0:0b799af9d58e 77 MemoryLeakOutputStringBuffer();
rgrover1 0:0b799af9d58e 78
rgrover1 0:0b799af9d58e 79 void clear();
rgrover1 0:0b799af9d58e 80
rgrover1 0:0b799af9d58e 81 void startMemoryLeakReporting();
rgrover1 0:0b799af9d58e 82 void stopMemoryLeakReporting();
rgrover1 0:0b799af9d58e 83
rgrover1 0:0b799af9d58e 84 void reportMemoryLeak(MemoryLeakDetectorNode* leak);
rgrover1 0:0b799af9d58e 85
rgrover1 0:0b799af9d58e 86 void reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
rgrover1 0:0b799af9d58e 87 void reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
rgrover1 0:0b799af9d58e 88 void reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
rgrover1 0:0b799af9d58e 89 char* toString();
rgrover1 0:0b799af9d58e 90
rgrover1 0:0b799af9d58e 91 private:
rgrover1 0:0b799af9d58e 92 void addAllocationLocation(const char* allocationFile, int allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator);
rgrover1 0:0b799af9d58e 93 void addDeallocationLocation(const char* freeFile, int freeLineNumber, TestMemoryAllocator* allocator);
rgrover1 0:0b799af9d58e 94
rgrover1 0:0b799af9d58e 95 void addMemoryLeakHeader();
rgrover1 0:0b799af9d58e 96 void addMemoryLeakFooter(int totalAmountOfLeaks);
rgrover1 0:0b799af9d58e 97 void addWarningForUsingMalloc();
rgrover1 0:0b799af9d58e 98 void addNoMemoryLeaksMessage();
rgrover1 0:0b799af9d58e 99 void addErrorMessageForTooMuchLeaks();
rgrover1 0:0b799af9d58e 100
rgrover1 0:0b799af9d58e 101 private:
rgrover1 0:0b799af9d58e 102
rgrover1 0:0b799af9d58e 103 int total_leaks_;
rgrover1 0:0b799af9d58e 104 bool giveWarningOnUsingMalloc_;
rgrover1 0:0b799af9d58e 105
rgrover1 0:0b799af9d58e 106 void reportFailure(const char* message, const char* allocFile,
rgrover1 0:0b799af9d58e 107 int allocLine, size_t allocSize,
rgrover1 0:0b799af9d58e 108 TestMemoryAllocator* allocAllocator, const char* freeFile,
rgrover1 0:0b799af9d58e 109 int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
rgrover1 0:0b799af9d58e 110
rgrover1 0:0b799af9d58e 111 SimpleStringBuffer outputBuffer_;
rgrover1 0:0b799af9d58e 112 };
rgrover1 0:0b799af9d58e 113
rgrover1 0:0b799af9d58e 114 struct MemoryLeakDetectorNode
rgrover1 0:0b799af9d58e 115 {
rgrover1 0:0b799af9d58e 116 MemoryLeakDetectorNode() :
rgrover1 0:0b799af9d58e 117 size_(0), number_(0), memory_(0), file_(0), line_(0), allocator_(0), period_(mem_leak_period_enabled), next_(0)
rgrover1 0:0b799af9d58e 118 {
rgrover1 0:0b799af9d58e 119 }
rgrover1 0:0b799af9d58e 120
rgrover1 0:0b799af9d58e 121 void init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, const char* file, int line);
rgrover1 0:0b799af9d58e 122
rgrover1 0:0b799af9d58e 123 size_t size_;
rgrover1 0:0b799af9d58e 124 unsigned number_;
rgrover1 0:0b799af9d58e 125 char* memory_;
rgrover1 0:0b799af9d58e 126 const char* file_;
rgrover1 0:0b799af9d58e 127 int line_;
rgrover1 0:0b799af9d58e 128 TestMemoryAllocator* allocator_;
rgrover1 0:0b799af9d58e 129 MemLeakPeriod period_;
rgrover1 0:0b799af9d58e 130
rgrover1 0:0b799af9d58e 131 private:
rgrover1 0:0b799af9d58e 132 friend struct MemoryLeakDetectorList;
rgrover1 0:0b799af9d58e 133 MemoryLeakDetectorNode* next_;
rgrover1 0:0b799af9d58e 134 };
rgrover1 0:0b799af9d58e 135
rgrover1 0:0b799af9d58e 136 struct MemoryLeakDetectorList
rgrover1 0:0b799af9d58e 137 {
rgrover1 0:0b799af9d58e 138 MemoryLeakDetectorList() :
rgrover1 0:0b799af9d58e 139 head_(0)
rgrover1 0:0b799af9d58e 140 {}
rgrover1 0:0b799af9d58e 141
rgrover1 0:0b799af9d58e 142 void addNewNode(MemoryLeakDetectorNode* node);
rgrover1 0:0b799af9d58e 143 MemoryLeakDetectorNode* retrieveNode(char* memory);
rgrover1 0:0b799af9d58e 144 MemoryLeakDetectorNode* removeNode(char* memory);
rgrover1 0:0b799af9d58e 145
rgrover1 0:0b799af9d58e 146 MemoryLeakDetectorNode* getFirstLeak(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 147 MemoryLeakDetectorNode* getNextLeak(MemoryLeakDetectorNode* node,
rgrover1 0:0b799af9d58e 148 MemLeakPeriod period);
rgrover1 0:0b799af9d58e 149 MemoryLeakDetectorNode* getLeakFrom(MemoryLeakDetectorNode* node,
rgrover1 0:0b799af9d58e 150 MemLeakPeriod period);
rgrover1 0:0b799af9d58e 151
rgrover1 0:0b799af9d58e 152 int getTotalLeaks(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 153 bool hasLeaks(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 154 void clearAllAccounting(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 155
rgrover1 0:0b799af9d58e 156 bool isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period);
rgrover1 0:0b799af9d58e 157
rgrover1 0:0b799af9d58e 158 private:
rgrover1 0:0b799af9d58e 159 MemoryLeakDetectorNode* head_;
rgrover1 0:0b799af9d58e 160 };
rgrover1 0:0b799af9d58e 161
rgrover1 0:0b799af9d58e 162 struct MemoryLeakDetectorTable
rgrover1 0:0b799af9d58e 163 {
rgrover1 0:0b799af9d58e 164 void clearAllAccounting(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 165
rgrover1 0:0b799af9d58e 166 void addNewNode(MemoryLeakDetectorNode* node);
rgrover1 0:0b799af9d58e 167 MemoryLeakDetectorNode* retrieveNode(char* memory);
rgrover1 0:0b799af9d58e 168 MemoryLeakDetectorNode* removeNode(char* memory);
rgrover1 0:0b799af9d58e 169
rgrover1 0:0b799af9d58e 170 bool hasLeaks(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 171 int getTotalLeaks(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 172
rgrover1 0:0b799af9d58e 173 MemoryLeakDetectorNode* getFirstLeak(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 174 MemoryLeakDetectorNode* getNextLeak(MemoryLeakDetectorNode* leak,
rgrover1 0:0b799af9d58e 175 MemLeakPeriod period);
rgrover1 0:0b799af9d58e 176
rgrover1 0:0b799af9d58e 177 private:
rgrover1 0:0b799af9d58e 178 unsigned long hash(char* memory);
rgrover1 0:0b799af9d58e 179
rgrover1 0:0b799af9d58e 180 enum
rgrover1 0:0b799af9d58e 181 {
rgrover1 0:0b799af9d58e 182 hash_prime = MEMORY_LEAK_HASH_TABLE_SIZE
rgrover1 0:0b799af9d58e 183 };
rgrover1 0:0b799af9d58e 184 MemoryLeakDetectorList table_[hash_prime];
rgrover1 0:0b799af9d58e 185 };
rgrover1 0:0b799af9d58e 186
rgrover1 0:0b799af9d58e 187 class MemoryLeakDetector
rgrover1 0:0b799af9d58e 188 {
rgrover1 0:0b799af9d58e 189 public:
rgrover1 0:0b799af9d58e 190 MemoryLeakDetector(MemoryLeakFailure* reporter);
rgrover1 0:0b799af9d58e 191 virtual ~MemoryLeakDetector()
rgrover1 0:0b799af9d58e 192 {
rgrover1 0:0b799af9d58e 193 }
rgrover1 0:0b799af9d58e 194
rgrover1 0:0b799af9d58e 195 void enable();
rgrover1 0:0b799af9d58e 196 void disable();
rgrover1 0:0b799af9d58e 197
rgrover1 0:0b799af9d58e 198 void disableAllocationTypeChecking();
rgrover1 0:0b799af9d58e 199 void enableAllocationTypeChecking();
rgrover1 0:0b799af9d58e 200
rgrover1 0:0b799af9d58e 201 void startChecking();
rgrover1 0:0b799af9d58e 202 void stopChecking();
rgrover1 0:0b799af9d58e 203
rgrover1 0:0b799af9d58e 204 const char* report(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 205 void markCheckingPeriodLeaksAsNonCheckingPeriod();
rgrover1 0:0b799af9d58e 206 int totalMemoryLeaks(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 207 void clearAllAccounting(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 208
rgrover1 0:0b799af9d58e 209 char* allocMemory(TestMemoryAllocator* allocator, size_t size, bool allocatNodesSeperately = false);
rgrover1 0:0b799af9d58e 210 char* allocMemory(TestMemoryAllocator* allocator, size_t size,
rgrover1 0:0b799af9d58e 211 const char* file, int line, bool allocatNodesSeperately = false);
rgrover1 0:0b799af9d58e 212 void deallocMemory(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately = false);
rgrover1 0:0b799af9d58e 213 void deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, int line, bool allocatNodesSeperately = false);
rgrover1 0:0b799af9d58e 214 char* reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately = false);
rgrover1 0:0b799af9d58e 215
rgrover1 0:0b799af9d58e 216 void invalidateMemory(char* memory);
rgrover1 0:0b799af9d58e 217 void removeMemoryLeakInformationWithoutCheckingOrDeallocatingTheMemoryButDeallocatingTheAccountInformation(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately);
rgrover1 0:0b799af9d58e 218 enum
rgrover1 0:0b799af9d58e 219 {
rgrover1 0:0b799af9d58e 220 memory_corruption_buffer_size = 3
rgrover1 0:0b799af9d58e 221 };
rgrover1 0:0b799af9d58e 222
rgrover1 0:0b799af9d58e 223 unsigned getCurrentAllocationNumber();
rgrover1 0:0b799af9d58e 224 private:
rgrover1 0:0b799af9d58e 225 MemoryLeakFailure* reporter_;
rgrover1 0:0b799af9d58e 226 MemLeakPeriod current_period_;
rgrover1 0:0b799af9d58e 227 MemoryLeakOutputStringBuffer outputBuffer_;
rgrover1 0:0b799af9d58e 228 MemoryLeakDetectorTable memoryTable_;
rgrover1 0:0b799af9d58e 229 bool doAllocationTypeChecking_;
rgrover1 0:0b799af9d58e 230 unsigned allocationSequenceNumber_;
rgrover1 0:0b799af9d58e 231
rgrover1 0:0b799af9d58e 232 char* allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately);
rgrover1 0:0b799af9d58e 233 char* reallocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately);
rgrover1 0:0b799af9d58e 234 MemoryLeakDetectorNode* createMemoryLeakAccountingInformation(TestMemoryAllocator* allocator, size_t size, char* memory, bool allocatNodesSeperately);
rgrover1 0:0b799af9d58e 235
rgrover1 0:0b799af9d58e 236
rgrover1 0:0b799af9d58e 237 bool validMemoryCorruptionInformation(char* memory);
rgrover1 0:0b799af9d58e 238 bool matchingAllocation(TestMemoryAllocator *alloc_allocator, TestMemoryAllocator *free_allocator);
rgrover1 0:0b799af9d58e 239
rgrover1 0:0b799af9d58e 240 void storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, int line);
rgrover1 0:0b799af9d58e 241 void ConstructMemoryLeakReport(MemLeakPeriod period);
rgrover1 0:0b799af9d58e 242
rgrover1 0:0b799af9d58e 243 size_t sizeOfMemoryWithCorruptionInfo(size_t size);
rgrover1 0:0b799af9d58e 244 MemoryLeakDetectorNode* getNodeFromMemoryPointer(char* memory, size_t size);
rgrover1 0:0b799af9d58e 245
rgrover1 0:0b799af9d58e 246 char* reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately);
rgrover1 0:0b799af9d58e 247
rgrover1 0:0b799af9d58e 248 void addMemoryCorruptionInformation(char* memory);
rgrover1 0:0b799af9d58e 249 void checkForCorruption(MemoryLeakDetectorNode* node, const char* file, int line, TestMemoryAllocator* allocator, bool allocateNodesSeperately);
rgrover1 0:0b799af9d58e 250 };
rgrover1 0:0b799af9d58e 251
rgrover1 0:0b799af9d58e 252 #endif