unity_fixture.c 10.0 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 _UnityFixture 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
        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

J
jsalling 已提交
126 127
/*------------------------------------------------- */
/* Malloc and free stuff */
128 129 130 131
#define MALLOC_DONT_FAIL -1
static int malloc_count;
static int malloc_fail_countdown = MALLOC_DONT_FAIL;

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

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

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

J
jsalling 已提交
152 153
/* 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 */
154 155
#undef malloc
#undef free
@
@gageas 已提交
156 157 158
#undef calloc
#undef realloc

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

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


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

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

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

188
    if (size == 0) return NULL;
189 190 191 192 193 194 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
    {
        guard = (Guard*) &unity_heap[heap_index];
        heap_index += total_size;
    }
#else
    guard = (Guard*)UNITY_FIXTURE_MALLOC(total_size);
#endif
202
    if (guard == NULL) return NULL;
203
    malloc_count++;
204
    guard->size = size;
205
    guard->guard_space = 0;
206
    mem = (char*)&(guard[1]);
207
    memcpy(&mem[size], end, sizeof(end));
208 209 210 211

    return (void*)mem;
}

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

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

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

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

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

    if (mem == NULL)
    {
        return;
    }

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

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

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

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

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

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

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

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


J
jsalling 已提交
300 301
/*-------------------------------------------------------- */
/*Automatic pointer restoration functions */
302
struct PointerPair
303
{
304 305
    void** pointer;
    void* old_value;
306
};
307

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

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

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

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

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

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

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