15ef283fcy//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
25ef283fcy/* ==========================================
35ef283fcy    Unity Project - A Test Framework for C
45ef283fcy    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
55ef283fcy    [Released under MIT License. Please refer to license.txt for details]
65ef283fcy========================================== */
75ef283fcy
85ef283fcy#include <string.h>
95ef283fcy#include <stdio.h>
105ef283fcy#include "unity_fixture.h"
115ef283fcy#include "unity_internals.h"
125ef283fcy
135ef283fcyUNITY_FIXTURE_T UnityFixture;
145ef283fcy
155ef283fcy//If you decide to use the function pointer approach.
165ef283fcyint (*outputChar)(int) = putchar;
175ef283fcy
185ef283fcyint verbose = 0;
195ef283fcy
205ef283fcy
215ef283fcystatic void announceTestRun(unsigned int runNumber)
225ef283fcy{
235ef283fcy    UnityPrint("Unity test run ");
245ef283fcy    UnityPrintNumber(runNumber+1);
255ef283fcy    UnityPrint(" of ");
265ef283fcy    UnityPrintNumber(UnityFixture.RepeatCount);
275ef283fcy    UNITY_OUTPUT_CHAR('\n');
285ef283fcy}
295ef283fcy
305ef283fcyint UnityMain(int argc, const char* argv[], void (*runAllTests)(void))
315ef283fcy{
325ef283fcy    int result = UnityGetCommandLineOptions(argc, argv);
335ef283fcy    unsigned int r;
345ef283fcy    if (result != 0)
355ef283fcy        return result;
365ef283fcy
375ef283fcy    for (r = 0; r < UnityFixture.RepeatCount; r++)
385ef283fcy    {
395ef283fcy        UnityBegin(argv[0]);
405ef283fcy        announceTestRun(r);
415ef283fcy        runAllTests();
425ef283fcy        UNITY_OUTPUT_CHAR('\n');
435ef283fcy        UnityEnd();
445ef283fcy    }
455ef283fcy
465ef283fcy    return UnityFailureCount();
475ef283fcy}
485ef283fcy
495ef283fcystatic int selected(const char * filter, const char * name)
505ef283fcy{
515ef283fcy    if (filter == 0)
525ef283fcy        return 1;
535ef283fcy    return strstr(name, filter) ? 1 : 0;
545ef283fcy}
555ef283fcy
565ef283fcystatic int testSelected(const char* test)
575ef283fcy{
585ef283fcy    return selected(UnityFixture.NameFilter, test);
595ef283fcy}
605ef283fcy
615ef283fcystatic int groupSelected(const char* group)
625ef283fcy{
635ef283fcy    return selected(UnityFixture.GroupFilter, group);
645ef283fcy}
655ef283fcy
665ef283fcystatic void runTestCase(void)
675ef283fcy{
685ef283fcy
695ef283fcy}
705ef283fcy
715ef283fcyvoid UnityTestRunner(unityfunction* setup,
725ef283fcy        unityfunction* testBody,
735ef283fcy        unityfunction* teardown,
745ef283fcy        const char * printableName,
755ef283fcy        const char * group,
765ef283fcy        const char * name,
775ef283fcy        const char * file, int line)
785ef283fcy{
795ef283fcy    if (testSelected(name) && groupSelected(group))
805ef283fcy    {
815ef283fcy        Unity.CurrentTestFailed = 0;
825ef283fcy        Unity.TestFile = file;
835ef283fcy        Unity.CurrentTestName = printableName;
845ef283fcy        Unity.CurrentTestLineNumber = line;
855ef283fcy        if (!UnityFixture.Verbose)
865ef283fcy            UNITY_OUTPUT_CHAR('.');
875ef283fcy        else
885ef283fcy            UnityPrint(printableName);
895ef283fcy
905ef283fcy        Unity.NumberOfTests++;
915ef283fcy        UnityMalloc_StartTest();
925ef283fcy        UnityPointer_Init();
935ef283fcy
945ef283fcy        runTestCase();
955ef283fcy        if (TEST_PROTECT())
965ef283fcy        {
975ef283fcy            setup();
985ef283fcy            testBody();
995ef283fcy        }
1005ef283fcy        if (TEST_PROTECT())
1015ef283fcy        {
1025ef283fcy            teardown();
1035ef283fcy        }
1045ef283fcy        if (TEST_PROTECT())
1055ef283fcy        {
1065ef283fcy            UnityPointer_UndoAllSets();
1075ef283fcy            if (!Unity.CurrentTestFailed)
1085ef283fcy                UnityMalloc_EndTest();
1095ef283fcy        }
1105ef283fcy        UnityConcludeFixtureTest();
1115ef283fcy    }
1125ef283fcy}
1135ef283fcy
1145ef283fcyvoid UnityIgnoreTest(const char * printableName)
1155ef283fcy{
1165ef283fcy    Unity.NumberOfTests++;
1175ef283fcy    Unity.CurrentTestIgnored = 1;
1185ef283fcy    if (!UnityFixture.Verbose)
1195ef283fcy        UNITY_OUTPUT_CHAR('!');
1205ef283fcy    else
1215ef283fcy        UnityPrint(printableName);
1225ef283fcy    UnityConcludeFixtureTest();
1235ef283fcy}
1245ef283fcy
1255ef283fcy
1265ef283fcy//-------------------------------------------------
1275ef283fcy//Malloc and free stuff
1285ef283fcy//
1295ef283fcy#define MALLOC_DONT_FAIL -1
1305ef283fcystatic int malloc_count;
1315ef283fcystatic int malloc_fail_countdown = MALLOC_DONT_FAIL;
1325ef283fcy
1335ef283fcyvoid UnityMalloc_StartTest(void)
1345ef283fcy{
1355ef283fcy    malloc_count = 0;
1365ef283fcy    malloc_fail_countdown = MALLOC_DONT_FAIL;
1375ef283fcy}
1385ef283fcy
1395ef283fcyvoid UnityMalloc_EndTest(void)
1405ef283fcy{
1415ef283fcy    malloc_fail_countdown = MALLOC_DONT_FAIL;
1425ef283fcy    if (malloc_count != 0)
1435ef283fcy    {
1445ef283fcy        TEST_FAIL_MESSAGE("This test leaks!");
1455ef283fcy    }
1465ef283fcy}
1475ef283fcy
1485ef283fcyvoid UnityMalloc_MakeMallocFailAfterCount(int countdown)
1495ef283fcy{
1505ef283fcy    malloc_fail_countdown = countdown;
1515ef283fcy}
1525ef283fcy
1535ef283fcy#ifdef malloc
1545ef283fcy#undef malloc
1555ef283fcy#endif
1565ef283fcy
1575ef283fcy#ifdef free
1585ef283fcy#undef free
1595ef283fcy#endif
1605ef283fcy
1615ef283fcy#ifdef calloc
1625ef283fcy#undef calloc
1635ef283fcy#endif
1645ef283fcy
1655ef283fcy#ifdef realloc
1665ef283fcy#undef realloc
1675ef283fcy#endif
1685ef283fcy
1695ef283fcy#include <stdlib.h>
1705ef283fcy#include <string.h>
1715ef283fcy
1725ef283fcytypedef struct GuardBytes
1735ef283fcy{
1745ef283fcy    size_t size;
1755ef283fcy    char guard[sizeof(size_t)];
1765ef283fcy} Guard;
1775ef283fcy
1785ef283fcy
1795ef283fcystatic const char * end = "END";
1805ef283fcy
1815ef283fcyvoid * unity_malloc(size_t size)
1825ef283fcy{
1835ef283fcy    char* mem;
1845ef283fcy    Guard* guard;
1855ef283fcy
1865ef283fcy    if (malloc_fail_countdown != MALLOC_DONT_FAIL)
1875ef283fcy    {
1885ef283fcy        if (malloc_fail_countdown == 0)
1895ef283fcy            return 0;
1905ef283fcy        malloc_fail_countdown--;
1915ef283fcy    }
1925ef283fcy
1935ef283fcy    malloc_count++;
1945ef283fcy
1955ef283fcy    guard = (Guard*)malloc(size + sizeof(Guard) + 4);
1965ef283fcy    guard->size = size;
1975ef283fcy    mem = (char*)&(guard[1]);
1985ef283fcy    memcpy(&mem[size], end, strlen(end) + 1);
1995ef283fcy
2005ef283fcy    return (void*)mem;
2015ef283fcy}
2025ef283fcy
2035ef283fcystatic int isOverrun(void * mem)
2045ef283fcy{
2055ef283fcy    Guard* guard = (Guard*)mem;
2065ef283fcy    char* memAsChar = (char*)mem;
2075ef283fcy    guard--;
2085ef283fcy
2095ef283fcy    return strcmp(&memAsChar[guard->size], end) != 0;
2105ef283fcy}
2115ef283fcy
2125ef283fcystatic void release_memory(void * mem)
2135ef283fcy{
2145ef283fcy    Guard* guard = (Guard*)mem;
2155ef283fcy    guard--;
2165ef283fcy
2175ef283fcy    malloc_count--;
2185ef283fcy    free(guard);
2195ef283fcy}
2205ef283fcy
2215ef283fcyvoid unity_free(void * mem)
2225ef283fcy{
2235ef283fcy    int overrun = isOverrun(mem);//strcmp(&memAsChar[guard->size], end) != 0;
2245ef283fcy    release_memory(mem);
2255ef283fcy    if (overrun)
2265ef283fcy    {
2275ef283fcy        TEST_FAIL_MESSAGE("Buffer overrun detected during free()");
2285ef283fcy    }
2295ef283fcy}
2305ef283fcy
2315ef283fcyvoid* unity_calloc(size_t num, size_t size)
2325ef283fcy{
2335ef283fcy    void* mem = unity_malloc(num * size);
2345ef283fcy    memset(mem, 0, num*size);
2355ef283fcy    return mem;
2365ef283fcy}
2375ef283fcy
2385ef283fcyvoid* unity_realloc(void * oldMem, size_t size)
2395ef283fcy{
2405ef283fcy    Guard* guard = (Guard*)oldMem;
2415ef283fcy//    char* memAsChar = (char*)oldMem;
2425ef283fcy    void* newMem;
2435ef283fcy
2445ef283fcy    if (oldMem == 0)
2455ef283fcy        return unity_malloc(size);
2465ef283fcy
2475ef283fcy    guard--;
2485ef283fcy    if (isOverrun(oldMem))
2495ef283fcy    {
2505ef283fcy        release_memory(oldMem);
2515ef283fcy        TEST_FAIL_MESSAGE("Buffer overrun detected during realloc()");
2525ef283fcy    }
2535ef283fcy
2545ef283fcy    if (size == 0)
2555ef283fcy    {
2565ef283fcy        release_memory(oldMem);
2575ef283fcy        return 0;
2585ef283fcy    }
2595ef283fcy
2605ef283fcy    if (guard->size >= size)
2615ef283fcy        return oldMem;
2625ef283fcy
2635ef283fcy    newMem = unity_malloc(size);
2645ef283fcy    memcpy(newMem, oldMem, guard->size);
2655ef283fcy    unity_free(oldMem);
2665ef283fcy    return newMem;
2675ef283fcy}
2685ef283fcy
2695ef283fcy
2705ef283fcy//--------------------------------------------------------
2715ef283fcy//Automatic pointer restoration functions
2725ef283fcytypedef struct _PointerPair
2735ef283fcy{
2745ef283fcy    struct _PointerPair * next;
2755ef283fcy    void ** pointer;
2765ef283fcy    void * old_value;
2775ef283fcy} PointerPair;
2785ef283fcy
2795ef283fcyenum {MAX_POINTERS=50};
2805ef283fcystatic PointerPair pointer_store[MAX_POINTERS];
2815ef283fcystatic int pointer_index = 0;
2825ef283fcy
2835ef283fcyvoid UnityPointer_Init(void)
2845ef283fcy{
2855ef283fcy    pointer_index = 0;
2865ef283fcy}
2875ef283fcy
2885ef283fcyvoid UnityPointer_Set(void ** pointer, void * newValue)
2895ef283fcy{
2905ef283fcy    if (pointer_index >= MAX_POINTERS)
2915ef283fcy        TEST_FAIL_MESSAGE("Too many pointers set");
2925ef283fcy
2935ef283fcy    pointer_store[pointer_index].pointer = pointer;
2945ef283fcy    pointer_store[pointer_index].old_value = *pointer;
2955ef283fcy    *pointer = newValue;
2965ef283fcy    pointer_index++;
2975ef283fcy}
2985ef283fcy
2995ef283fcyvoid UnityPointer_UndoAllSets(void)
3005ef283fcy{
3015ef283fcy    while (pointer_index > 0)
3025ef283fcy    {
3035ef283fcy        pointer_index--;
3045ef283fcy        *(pointer_store[pointer_index].pointer) =
3055ef283fcy        pointer_store[pointer_index].old_value;
3065ef283fcy
3075ef283fcy    }
3085ef283fcy}
3095ef283fcy
3105ef283fcyint UnityFailureCount(void)
3115ef283fcy{
3125ef283fcy    return Unity.TestFailures;
3135ef283fcy}
3145ef283fcy
3155ef283fcyint UnityGetCommandLineOptions(int argc, const char* argv[])
3165ef283fcy{
3175ef283fcy    int i;
3185ef283fcy    UnityFixture.Verbose = 0;
3195ef283fcy    UnityFixture.GroupFilter = 0;
3205ef283fcy    UnityFixture.NameFilter = 0;
3215ef283fcy    UnityFixture.RepeatCount = 1;
3225ef283fcy
3235ef283fcy    if (argc == 1)
3245ef283fcy        return 0;
3255ef283fcy
3265ef283fcy    for (i = 1; i < argc; )
3275ef283fcy    {
3285ef283fcy        if (strcmp(argv[i], "-v") == 0)
3295ef283fcy        {
3305ef283fcy            UnityFixture.Verbose = 1;
3315ef283fcy            i++;
3325ef283fcy        }
3335ef283fcy        else if (strcmp(argv[i], "-g") == 0)
3345ef283fcy        {
3355ef283fcy            i++;
3365ef283fcy            if (i >= argc)
3375ef283fcy                return 1;
3385ef283fcy            UnityFixture.GroupFilter = argv[i];
3395ef283fcy            i++;
3405ef283fcy        }
3415ef283fcy        else if (strcmp(argv[i], "-n") == 0)
3425ef283fcy        {
3435ef283fcy            i++;
3445ef283fcy            if (i >= argc)
3455ef283fcy                return 1;
3465ef283fcy            UnityFixture.NameFilter = argv[i];
3475ef283fcy            i++;
3485ef283fcy        }
3495ef283fcy        else if (strcmp(argv[i], "-r") == 0)
3505ef283fcy        {
3515ef283fcy            UnityFixture.RepeatCount = 2;
3525ef283fcy            i++;
3535ef283fcy            if (i < argc)
3545ef283fcy            {
3555ef283fcy                if (*(argv[i]) >= '0' && *(argv[i]) <= '9')
3565ef283fcy                {
3575ef283fcy                    UnityFixture.RepeatCount = atoi(argv[i]);
3585ef283fcy                    i++;
3595ef283fcy                }
3605ef283fcy            }
3615ef283fcy        } else {
3625ef283fcy            // ignore unknown parameter
3635ef283fcy            i++;
3645ef283fcy        }
3655ef283fcy    }
3665ef283fcy    return 0;
3675ef283fcy}
3685ef283fcy
3695ef283fcyvoid UnityConcludeFixtureTest(void)
3705ef283fcy{
3715ef283fcy    if (Unity.CurrentTestIgnored)
3725ef283fcy    {
3735ef283fcy        if (UnityFixture.Verbose)
3745ef283fcy        {
3755ef283fcy            UNITY_OUTPUT_CHAR('\n');
3765ef283fcy        }
3775ef283fcy        Unity.TestIgnores++;
3785ef283fcy    }
3795ef283fcy    else if (!Unity.CurrentTestFailed)
3805ef283fcy    {
3815ef283fcy        if (UnityFixture.Verbose)
3825ef283fcy        {
3835ef283fcy            UnityPrint(" PASS");
3845ef283fcy            UNITY_OUTPUT_CHAR('\n');
3855ef283fcy        }
3865ef283fcy    }
3875ef283fcy    else if (Unity.CurrentTestFailed)
3885ef283fcy    {
3895ef283fcy        Unity.TestFailures++;
3905ef283fcy    }
3915ef283fcy
3925ef283fcy    Unity.CurrentTestFailed = 0;
3935ef283fcy    Unity.CurrentTestIgnored = 0;
3945ef283fcy}
395