unity_fixture.c 9.9 KB
Newer Older
1 2 3 4 5 6 7
//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
/* ==========================================
    Unity Project - A Test Framework for C
    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
    [Released under MIT License. Please refer to license.txt for details]
========================================== */

8
#include <string.h>
9 10 11
#include "unity_fixture.h"
#include "unity_internals.h"

12
struct _UnityFixture UnityFixture;
13 14

//If you decide to use the function pointer approach.
15 16
//Build with -D UNITY_OUTPUT_CHAR=outputChar and include <stdio.h>
//int (*outputChar)(int) = putchar;
17

18
#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA)
19 20
void setUp(void)    { /*does nothing*/ }
void tearDown(void) { /*does nothing*/ }
21
#endif
22

23
static void announceTestRun(unsigned int runNumber)
24 25
{
    UnityPrint("Unity test run ");
26
    UnityPrintNumberUnsigned(runNumber+1);
27
    UnityPrint(" of ");
28
    UnityPrintNumberUnsigned(UnityFixture.RepeatCount);
29
    UNITY_PRINT_EOL();
30 31
}

32
int UnityMain(int argc, const char* argv[], void (*runAllTests)(void))
33 34
{
    int result = UnityGetCommandLineOptions(argc, argv);
35
    unsigned int r;
36 37 38 39 40
    if (result != 0)
        return result;

    for (r = 0; r < UnityFixture.RepeatCount; r++)
    {
41
        UnityBegin(argv[0]);
42
        announceTestRun(r);
43
        runAllTests();
44
        UNITY_PRINT_EOL();
45 46 47
        UnityEnd();
    }

48
    return (int)Unity.TestFailures;
49 50
}

51
static int selected(const char* filter, const char* name)
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
{
    if (filter == 0)
        return 1;
    return strstr(name, filter) ? 1 : 0;
}

static int testSelected(const char* test)
{
    return selected(UnityFixture.NameFilter, test);
}

static int groupSelected(const char* group)
{
    return selected(UnityFixture.GroupFilter, group);
}

void UnityTestRunner(unityfunction* setup,
69 70 71 72 73
                     unityfunction* testBody,
                     unityfunction* teardown,
                     const char* printableName,
                     const char* group,
                     const char* name,
74
                     const char* file, unsigned int line)
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
{
    if (testSelected(name) && groupSelected(group))
    {
        Unity.TestFile = file;
        Unity.CurrentTestName = printableName;
        Unity.CurrentTestLineNumber = line;
        if (!UnityFixture.Verbose)
            UNITY_OUTPUT_CHAR('.');
        else
            UnityPrint(printableName);

        Unity.NumberOfTests++;
        UnityMalloc_StartTest();
        UnityPointer_Init();

        if (TEST_PROTECT())
        {
            setup();
            testBody();
        }
        if (TEST_PROTECT())
        {
            teardown();
        }
        if (TEST_PROTECT())
        {
            UnityPointer_UndoAllSets();
            if (!Unity.CurrentTestFailed)
                UnityMalloc_EndTest();
        }
105
        UnityConcludeFixtureTest();
106 107 108
    }
}

109
void UnityIgnoreTest(const char* printableName, const char* group, const char* name)
110
{
111
    if (testSelected(name) && groupSelected(group))
112 113
    {
        Unity.NumberOfTests++;
114
        Unity.TestIgnores++;
115 116 117
        if (!UnityFixture.Verbose)
            UNITY_OUTPUT_CHAR('!');
        else
118
        {
119
            UnityPrint(printableName);
120 121
            UNITY_PRINT_EOL();
        }
122
    }
123 124
}

125 126 127 128 129 130 131 132

//-------------------------------------------------
//Malloc and free stuff
//
#define MALLOC_DONT_FAIL -1
static int malloc_count;
static int malloc_fail_countdown = MALLOC_DONT_FAIL;

133
void UnityMalloc_StartTest(void)
134 135 136 137 138
{
    malloc_count = 0;
    malloc_fail_countdown = MALLOC_DONT_FAIL;
}

139
void UnityMalloc_EndTest(void)
140 141 142 143
{
    malloc_fail_countdown = MALLOC_DONT_FAIL;
    if (malloc_count != 0)
    {
144
        UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!");
145 146 147 148 149 150 151 152
    }
}

void UnityMalloc_MakeMallocFailAfterCount(int countdown)
{
    malloc_fail_countdown = countdown;
}

153 154
// These definitions are always included from unity_fixture_malloc_overrides.h
// We undef to use them or avoid conflict with <stdlib.h> per the C standard
155 156
#undef malloc
#undef free
@
@gageas 已提交
157 158 159
#undef calloc
#undef realloc

160 161
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES];
162
static size_t heap_index;
163
#else
164
#include <stdlib.h>
165
#endif
166 167 168

typedef struct GuardBytes
{
169
    size_t size;
170
    size_t guard_space;
171 172 173
} Guard;


174
static const char end[] = "END";
175

176
void* unity_malloc(size_t size)
177 178 179
{
    char* mem;
    Guard* guard;
180
    size_t total_size = size + sizeof(Guard) + sizeof(end);
181 182 183 184

    if (malloc_fail_countdown != MALLOC_DONT_FAIL)
    {
        if (malloc_fail_countdown == 0)
185
            return NULL;
186 187 188
        malloc_fail_countdown--;
    }

189
    if (size == 0) return NULL;
190 191 192 193 194 195 196 197 198 199 200 201 202
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
    if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES)
    {
        guard = NULL;
    }
    else
    {
        guard = (Guard*) &unity_heap[heap_index];
        heap_index += total_size;
    }
#else
    guard = (Guard*)UNITY_FIXTURE_MALLOC(total_size);
#endif
203
    if (guard == NULL) return NULL;
204
    malloc_count++;
205
    guard->size = size;
206
    guard->guard_space = 0;
207
    mem = (char*)&(guard[1]);
208
    memcpy(&mem[size], end, sizeof(end));
209 210 211 212

    return (void*)mem;
}

213
static int isOverrun(void* mem)
214 215 216 217
{
    Guard* guard = (Guard*)mem;
    char* memAsChar = (char*)mem;
    guard--;
218

219
    return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0;
220 221
}

222
static void release_memory(void* mem)
223 224 225 226 227
{
    Guard* guard = (Guard*)mem;
    guard--;

    malloc_count--;
228 229 230 231 232 233
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
    if (mem == unity_heap + heap_index - guard->size - sizeof(end))
    {
        heap_index -= (guard->size + sizeof(Guard) + sizeof(end));
    }
#else
234
    UNITY_FIXTURE_FREE(guard);
235
#endif
236 237
}

238
void unity_free(void* mem)
239
{
240 241 242 243 244 245 246
    int overrun;

    if (mem == NULL)
    {
        return;
    }

247
    overrun = isOverrun(mem);
248 249
    release_memory(mem);
    if (overrun)
250
    {
251
        UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()");
252 253 254 255 256 257
    }
}

void* unity_calloc(size_t num, size_t size)
{
    void* mem = unity_malloc(num * size);
258
    if (mem == NULL) return NULL;
259
    memset(mem, 0, num * size);
260 261 262
    return mem;
}

263
void* unity_realloc(void* oldMem, size_t size)
264 265 266 267
{
    Guard* guard = (Guard*)oldMem;
    void* newMem;

268
    if (oldMem == NULL) return unity_malloc(size);
269 270

    guard--;
271
    if (isOverrun(oldMem))
272
    {
273
        release_memory(oldMem);
274
        UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()");
275 276 277 278
    }

    if (size == 0)
    {
279
        release_memory(oldMem);
280
        return NULL;
281 282
    }

283
    if (guard->size >= size) return oldMem;
284

285 286 287 288 289 290 291 292
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC // Optimization if memory is expandable
    if (oldMem == unity_heap + heap_index - guard->size - sizeof(end) &&
        heap_index + size - guard->size <= UNITY_INTERNAL_HEAP_SIZE_BYTES)
    {
        release_memory(oldMem); // Not thread-safe, like unity_heap generally
        return unity_malloc(size); // No memcpy since data is in place
    }
#endif
293
    newMem = unity_malloc(size);
294
    if (newMem == NULL) return NULL; // Do not release old memory
295
    memcpy(newMem, oldMem, guard->size);
296
    release_memory(oldMem);
297 298 299 300 301 302
    return newMem;
}


//--------------------------------------------------------
//Automatic pointer restoration functions
303
struct PointerPair
304
{
305 306
    void** pointer;
    void* old_value;
307
};
308

309 310
enum { MAX_POINTERS = 50 };
static struct PointerPair pointer_store[MAX_POINTERS];
311 312
static int pointer_index = 0;

313
void UnityPointer_Init(void)
314 315 316 317
{
    pointer_index = 0;
}

318
void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line)
319 320
{
    if (pointer_index >= MAX_POINTERS)
321
    {
322
        UNITY_TEST_FAIL(line, "Too many pointers set");
323 324 325 326 327 328 329 330
    }
    else
    {
        pointer_store[pointer_index].pointer = pointer;
        pointer_store[pointer_index].old_value = *pointer;
        *pointer = newValue;
        pointer_index++;
    }
331 332
}

333
void UnityPointer_UndoAllSets(void)
334 335 336 337 338
{
    while (pointer_index > 0)
    {
        pointer_index--;
        *(pointer_store[pointer_index].pointer) =
339
            pointer_store[pointer_index].old_value;
340 341 342
    }
}

343
int UnityGetCommandLineOptions(int argc, const char* argv[])
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
{
    int i;
    UnityFixture.Verbose = 0;
    UnityFixture.GroupFilter = 0;
    UnityFixture.NameFilter = 0;
    UnityFixture.RepeatCount = 1;

    if (argc == 1)
        return 0;

    for (i = 1; i < argc; )
    {
        if (strcmp(argv[i], "-v") == 0)
        {
            UnityFixture.Verbose = 1;
            i++;
        }
        else if (strcmp(argv[i], "-g") == 0)
        {
            i++;
            if (i >= argc)
                return 1;
            UnityFixture.GroupFilter = argv[i];
            i++;
        }
        else if (strcmp(argv[i], "-n") == 0)
        {
            i++;
            if (i >= argc)
                return 1;
            UnityFixture.NameFilter = argv[i];
            i++;
        }
        else if (strcmp(argv[i], "-r") == 0)
        {
            UnityFixture.RepeatCount = 2;
            i++;
            if (i < argc)
            {
                if (*(argv[i]) >= '0' && *(argv[i]) <= '9')
                {
385 386 387 388 389 390 391
                    unsigned int digit = 0;
                    UnityFixture.RepeatCount = 0;
                    while (argv[i][digit] >= '0' && argv[i][digit] <= '9')
                    {
                        UnityFixture.RepeatCount *= 10;
                        UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0';
                    }
392 393 394
                    i++;
                }
            }
395 396 397
        } else {
            // ignore unknown parameter
            i++;
398 399 400 401 402
        }
    }
    return 0;
}

403
void UnityConcludeFixtureTest(void)
404 405 406 407
{
    if (Unity.CurrentTestIgnored)
    {
        Unity.TestIgnores++;
408
        UNITY_PRINT_EOL();
409 410 411 412 413 414
    }
    else if (!Unity.CurrentTestFailed)
    {
        if (UnityFixture.Verbose)
        {
            UnityPrint(" PASS");
415
            UNITY_PRINT_EOL();
416 417
        }
    }
418
    else // Unity.CurrentTestFailed
419 420
    {
        Unity.TestFailures++;
421
        UNITY_PRINT_EOL();
422 423 424 425 426
    }

    Unity.CurrentTestFailed = 0;
    Unity.CurrentTestIgnored = 0;
}