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 9

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

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 75
                     const char* file,
                     unsigned int line)
76 77 78 79 80 81 82 83 84
{
    if (testSelected(name) && groupSelected(group))
    {
        Unity.TestFile = file;
        Unity.CurrentTestName = printableName;
        Unity.CurrentTestLineNumber = line;
        if (!UnityFixture.Verbose)
            UNITY_OUTPUT_CHAR('.');
        else
85
        {
86
            UnityPrint(printableName);
87 88 89 90
        #ifndef UNITY_REPEAT_TEST_NAME
            Unity.CurrentTestName = NULL;
        #endif
        }
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

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

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

131

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

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

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

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

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

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

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


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

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

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

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

    return (void*)mem;
}

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

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

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

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

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

    if (mem == NULL)
    {
        return;
    }

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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