unity_fixture.c 10.1 KB
Newer Older
J
jsalling 已提交
1 2 3 4 5 6
/* 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]
 * ========================================== */
7

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

12
struct UNITY_FIXTURE_T UnityFixture;
13

J
jsalling 已提交
14 15 16
/* If you decide to use the function pointer approach.
 * 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
        if (!UnityFixture.Verbose) 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
{
    if (testSelected(name) && groupSelected(group))
    {
        Unity.TestFile = file;
        Unity.CurrentTestName = printableName;
        Unity.CurrentTestLineNumber = line;
        if (!UnityFixture.Verbose)
            UNITY_OUTPUT_CHAR('.');
        else
84
        {
85
            UnityPrint(printableName);
86 87 88 89
        #ifndef UNITY_REPEAT_TEST_NAME
            Unity.CurrentTestName = NULL;
        #endif
        }
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

        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();
        }
110
        UnityConcludeFixtureTest();
111 112 113
    }
}

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

130

J
jsalling 已提交
131 132
/*------------------------------------------------- */
/* Malloc and free stuff */
133 134 135 136
#define MALLOC_DONT_FAIL -1
static int malloc_count;
static int malloc_fail_countdown = MALLOC_DONT_FAIL;

137
void UnityMalloc_StartTest(void)
138 139 140 141 142
{
    malloc_count = 0;
    malloc_fail_countdown = MALLOC_DONT_FAIL;
}

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

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

J
jsalling 已提交
157 158
/* 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 */
159 160
#undef malloc
#undef free
@
@gageas 已提交
161 162 163
#undef calloc
#undef realloc

164 165
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES];
166
static size_t heap_index;
167
#else
168
#include <stdlib.h>
169
#endif
170 171 172

typedef struct GuardBytes
{
173
    size_t size;
174
    size_t guard_space;
175 176 177
} Guard;


178
static const char end[] = "END";
179

180
void* unity_malloc(size_t size)
181 182 183
{
    char* mem;
    Guard* guard;
184
    size_t total_size = size + sizeof(Guard) + sizeof(end);
185 186 187 188

    if (malloc_fail_countdown != MALLOC_DONT_FAIL)
    {
        if (malloc_fail_countdown == 0)
189
            return NULL;
190 191 192
        malloc_fail_countdown--;
    }

193
    if (size == 0) return NULL;
194 195 196 197 198 199 200 201 202 203 204 205 206
#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
207
    if (guard == NULL) return NULL;
208
    malloc_count++;
209
    guard->size = size;
210
    guard->guard_space = 0;
211
    mem = (char*)&(guard[1]);
212
    memcpy(&mem[size], end, sizeof(end));
213 214 215 216

    return (void*)mem;
}

217
static int isOverrun(void* mem)
218 219 220 221
{
    Guard* guard = (Guard*)mem;
    char* memAsChar = (char*)mem;
    guard--;
222

223
    return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0;
224 225
}

226
static void release_memory(void* mem)
227 228 229 230 231
{
    Guard* guard = (Guard*)mem;
    guard--;

    malloc_count--;
232 233 234 235 236 237
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
    if (mem == unity_heap + heap_index - guard->size - sizeof(end))
    {
        heap_index -= (guard->size + sizeof(Guard) + sizeof(end));
    }
#else
238
    UNITY_FIXTURE_FREE(guard);
239
#endif
240 241
}

242
void unity_free(void* mem)
243
{
244 245 246 247 248 249 250
    int overrun;

    if (mem == NULL)
    {
        return;
    }

251
    overrun = isOverrun(mem);
252 253
    release_memory(mem);
    if (overrun)
254
    {
255
        UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()");
256 257 258 259 260 261
    }
}

void* unity_calloc(size_t num, size_t size)
{
    void* mem = unity_malloc(num * size);
262
    if (mem == NULL) return NULL;
263
    memset(mem, 0, num * size);
264 265 266
    return mem;
}

267
void* unity_realloc(void* oldMem, size_t size)
268 269 270 271
{
    Guard* guard = (Guard*)oldMem;
    void* newMem;

272
    if (oldMem == NULL) return unity_malloc(size);
273 274

    guard--;
275
    if (isOverrun(oldMem))
276
    {
277
        release_memory(oldMem);
278
        UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()");
279 280 281 282
    }

    if (size == 0)
    {
283
        release_memory(oldMem);
284
        return NULL;
285 286
    }

287
    if (guard->size >= size) return oldMem;
288

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


J
jsalling 已提交
305 306
/*-------------------------------------------------------- */
/*Automatic pointer restoration functions */
307
struct PointerPair
308
{
309 310
    void** pointer;
    void* old_value;
311
};
312

313
static struct PointerPair pointer_store[UNITY_MAX_POINTERS];
314 315
static int pointer_index = 0;

316
void UnityPointer_Init(void)
317 318 319 320
{
    pointer_index = 0;
}

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

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

346
int UnityGetCommandLineOptions(int argc, const char* argv[])
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 385 386 387
{
    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')
                {
388 389 390 391 392 393 394
                    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';
                    }
395 396 397
                    i++;
                }
            }
398
        } else {
J
jsalling 已提交
399
            /* ignore unknown parameter */
400
            i++;
401 402 403 404 405
        }
    }
    return 0;
}

406
void UnityConcludeFixtureTest(void)
407 408 409 410
{
    if (Unity.CurrentTestIgnored)
    {
        Unity.TestIgnores++;
411
        UNITY_PRINT_EOL();
412 413 414 415 416 417
    }
    else if (!Unity.CurrentTestFailed)
    {
        if (UnityFixture.Verbose)
        {
            UnityPrint(" PASS");
418
            UNITY_PRINT_EOL();
419 420
        }
    }
J
jsalling 已提交
421
    else /* Unity.CurrentTestFailed */
422 423
    {
        Unity.TestFailures++;
424
        UNITY_PRINT_EOL();
425 426 427 428 429
    }

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