1284990Scy//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
2284990Scy/* ==========================================
3284990Scy    Unity Project - A Test Framework for C
4284990Scy    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
5284990Scy    [Released under MIT License. Please refer to license.txt for details]
6284990Scy========================================== */
7284990Scy
8284990Scy#include <string.h>
9284990Scy#include <stdio.h>
10284990Scy#include "unity_fixture.h"
11284990Scy#include "unity_internals.h"
12284990Scy
13284990ScyUNITY_FIXTURE_T UnityFixture;
14284990Scy
15284990Scy//If you decide to use the function pointer approach.
16284990Scyint (*outputChar)(int) = putchar;
17284990Scy
18284990Scyint verbose = 0;
19284990Scy
20284990Scy
21284990Scystatic void announceTestRun(unsigned int runNumber)
22284990Scy{
23284990Scy    UnityPrint("Unity test run ");
24284990Scy    UnityPrintNumber(runNumber+1);
25284990Scy    UnityPrint(" of ");
26284990Scy    UnityPrintNumber(UnityFixture.RepeatCount);
27284990Scy    UNITY_OUTPUT_CHAR('\n');
28284990Scy}
29284990Scy
30284990Scyint UnityMain(int argc, const char* argv[], void (*runAllTests)(void))
31284990Scy{
32284990Scy    int result = UnityGetCommandLineOptions(argc, argv);
33284990Scy    unsigned int r;
34284990Scy    if (result != 0)
35284990Scy        return result;
36284990Scy
37284990Scy    for (r = 0; r < UnityFixture.RepeatCount; r++)
38284990Scy    {
39284990Scy        UnityBegin(argv[0]);
40284990Scy        announceTestRun(r);
41284990Scy        runAllTests();
42284990Scy        UNITY_OUTPUT_CHAR('\n');
43284990Scy        UnityEnd();
44284990Scy    }
45284990Scy
46284990Scy    return UnityFailureCount();
47284990Scy}
48284990Scy
49284990Scystatic int selected(const char * filter, const char * name)
50284990Scy{
51284990Scy    if (filter == 0)
52284990Scy        return 1;
53284990Scy    return strstr(name, filter) ? 1 : 0;
54284990Scy}
55284990Scy
56284990Scystatic int testSelected(const char* test)
57284990Scy{
58284990Scy    return selected(UnityFixture.NameFilter, test);
59284990Scy}
60284990Scy
61284990Scystatic int groupSelected(const char* group)
62284990Scy{
63284990Scy    return selected(UnityFixture.GroupFilter, group);
64284990Scy}
65284990Scy
66284990Scystatic void runTestCase(void)
67284990Scy{
68284990Scy
69284990Scy}
70284990Scy
71284990Scyvoid UnityTestRunner(unityfunction* setup,
72284990Scy        unityfunction* testBody,
73284990Scy        unityfunction* teardown,
74284990Scy        const char * printableName,
75284990Scy        const char * group,
76284990Scy        const char * name,
77284990Scy        const char * file, int line)
78284990Scy{
79284990Scy    if (testSelected(name) && groupSelected(group))
80284990Scy    {
81284990Scy        Unity.CurrentTestFailed = 0;
82284990Scy        Unity.TestFile = file;
83284990Scy        Unity.CurrentTestName = printableName;
84284990Scy        Unity.CurrentTestLineNumber = line;
85284990Scy        if (!UnityFixture.Verbose)
86284990Scy            UNITY_OUTPUT_CHAR('.');
87284990Scy        else
88284990Scy            UnityPrint(printableName);
89284990Scy
90284990Scy        Unity.NumberOfTests++;
91284990Scy        UnityMalloc_StartTest();
92284990Scy        UnityPointer_Init();
93284990Scy
94284990Scy        runTestCase();
95284990Scy        if (TEST_PROTECT())
96284990Scy        {
97284990Scy            setup();
98284990Scy            testBody();
99284990Scy        }
100284990Scy        if (TEST_PROTECT())
101284990Scy        {
102284990Scy            teardown();
103284990Scy        }
104284990Scy        if (TEST_PROTECT())
105284990Scy        {
106284990Scy            UnityPointer_UndoAllSets();
107284990Scy            if (!Unity.CurrentTestFailed)
108284990Scy                UnityMalloc_EndTest();
109284990Scy        }
110284990Scy        UnityConcludeFixtureTest();
111284990Scy    }
112284990Scy}
113284990Scy
114284990Scyvoid UnityIgnoreTest(const char * printableName)
115284990Scy{
116284990Scy    Unity.NumberOfTests++;
117284990Scy    Unity.CurrentTestIgnored = 1;
118284990Scy    if (!UnityFixture.Verbose)
119284990Scy        UNITY_OUTPUT_CHAR('!');
120284990Scy    else
121284990Scy        UnityPrint(printableName);
122284990Scy    UnityConcludeFixtureTest();
123284990Scy}
124284990Scy
125284990Scy
126284990Scy//-------------------------------------------------
127284990Scy//Malloc and free stuff
128284990Scy//
129284990Scy#define MALLOC_DONT_FAIL -1
130284990Scystatic int malloc_count;
131284990Scystatic int malloc_fail_countdown = MALLOC_DONT_FAIL;
132284990Scy
133284990Scyvoid UnityMalloc_StartTest(void)
134284990Scy{
135284990Scy    malloc_count = 0;
136284990Scy    malloc_fail_countdown = MALLOC_DONT_FAIL;
137284990Scy}
138284990Scy
139284990Scyvoid UnityMalloc_EndTest(void)
140284990Scy{
141284990Scy    malloc_fail_countdown = MALLOC_DONT_FAIL;
142284990Scy    if (malloc_count != 0)
143284990Scy    {
144284990Scy        TEST_FAIL_MESSAGE("This test leaks!");
145284990Scy    }
146284990Scy}
147284990Scy
148284990Scyvoid UnityMalloc_MakeMallocFailAfterCount(int countdown)
149284990Scy{
150284990Scy    malloc_fail_countdown = countdown;
151284990Scy}
152284990Scy
153284990Scy#ifdef malloc
154284990Scy#undef malloc
155284990Scy#endif
156284990Scy
157284990Scy#ifdef free
158284990Scy#undef free
159284990Scy#endif
160284990Scy
161284990Scy#ifdef calloc
162284990Scy#undef calloc
163284990Scy#endif
164284990Scy
165284990Scy#ifdef realloc
166284990Scy#undef realloc
167284990Scy#endif
168284990Scy
169284990Scy#include <stdlib.h>
170284990Scy#include <string.h>
171284990Scy
172284990Scytypedef struct GuardBytes
173284990Scy{
174284990Scy    size_t size;
175284990Scy    char guard[sizeof(size_t)];
176284990Scy} Guard;
177284990Scy
178284990Scy
179284990Scystatic const char * end = "END";
180284990Scy
181284990Scyvoid * unity_malloc(size_t size)
182284990Scy{
183284990Scy    char* mem;
184284990Scy    Guard* guard;
185284990Scy
186284990Scy    if (malloc_fail_countdown != MALLOC_DONT_FAIL)
187284990Scy    {
188284990Scy        if (malloc_fail_countdown == 0)
189284990Scy            return 0;
190284990Scy        malloc_fail_countdown--;
191284990Scy    }
192284990Scy
193284990Scy    malloc_count++;
194284990Scy
195284990Scy    guard = (Guard*)malloc(size + sizeof(Guard) + 4);
196284990Scy    guard->size = size;
197284990Scy    mem = (char*)&(guard[1]);
198284990Scy    memcpy(&mem[size], end, strlen(end) + 1);
199284990Scy
200284990Scy    return (void*)mem;
201284990Scy}
202284990Scy
203284990Scystatic int isOverrun(void * mem)
204284990Scy{
205284990Scy    Guard* guard = (Guard*)mem;
206284990Scy    char* memAsChar = (char*)mem;
207284990Scy    guard--;
208284990Scy
209284990Scy    return strcmp(&memAsChar[guard->size], end) != 0;
210284990Scy}
211284990Scy
212284990Scystatic void release_memory(void * mem)
213284990Scy{
214284990Scy    Guard* guard = (Guard*)mem;
215284990Scy    guard--;
216284990Scy
217284990Scy    malloc_count--;
218284990Scy    free(guard);
219284990Scy}
220284990Scy
221284990Scyvoid unity_free(void * mem)
222284990Scy{
223284990Scy    int overrun = isOverrun(mem);//strcmp(&memAsChar[guard->size], end) != 0;
224284990Scy    release_memory(mem);
225284990Scy    if (overrun)
226284990Scy    {
227284990Scy        TEST_FAIL_MESSAGE("Buffer overrun detected during free()");
228284990Scy    }
229284990Scy}
230284990Scy
231284990Scyvoid* unity_calloc(size_t num, size_t size)
232284990Scy{
233284990Scy    void* mem = unity_malloc(num * size);
234284990Scy    memset(mem, 0, num*size);
235284990Scy    return mem;
236284990Scy}
237284990Scy
238284990Scyvoid* unity_realloc(void * oldMem, size_t size)
239284990Scy{
240284990Scy    Guard* guard = (Guard*)oldMem;
241284990Scy//    char* memAsChar = (char*)oldMem;
242284990Scy    void* newMem;
243284990Scy
244284990Scy    if (oldMem == 0)
245284990Scy        return unity_malloc(size);
246284990Scy
247284990Scy    guard--;
248284990Scy    if (isOverrun(oldMem))
249284990Scy    {
250284990Scy        release_memory(oldMem);
251284990Scy        TEST_FAIL_MESSAGE("Buffer overrun detected during realloc()");
252284990Scy    }
253284990Scy
254284990Scy    if (size == 0)
255284990Scy    {
256284990Scy        release_memory(oldMem);
257284990Scy        return 0;
258284990Scy    }
259284990Scy
260284990Scy    if (guard->size >= size)
261284990Scy        return oldMem;
262284990Scy
263284990Scy    newMem = unity_malloc(size);
264284990Scy    memcpy(newMem, oldMem, guard->size);
265284990Scy    unity_free(oldMem);
266284990Scy    return newMem;
267284990Scy}
268284990Scy
269284990Scy
270284990Scy//--------------------------------------------------------
271284990Scy//Automatic pointer restoration functions
272284990Scytypedef struct _PointerPair
273284990Scy{
274284990Scy    struct _PointerPair * next;
275284990Scy    void ** pointer;
276284990Scy    void * old_value;
277284990Scy} PointerPair;
278284990Scy
279284990Scyenum {MAX_POINTERS=50};
280284990Scystatic PointerPair pointer_store[MAX_POINTERS];
281284990Scystatic int pointer_index = 0;
282284990Scy
283284990Scyvoid UnityPointer_Init(void)
284284990Scy{
285284990Scy    pointer_index = 0;
286284990Scy}
287284990Scy
288284990Scyvoid UnityPointer_Set(void ** pointer, void * newValue)
289284990Scy{
290284990Scy    if (pointer_index >= MAX_POINTERS)
291284990Scy        TEST_FAIL_MESSAGE("Too many pointers set");
292284990Scy
293284990Scy    pointer_store[pointer_index].pointer = pointer;
294284990Scy    pointer_store[pointer_index].old_value = *pointer;
295284990Scy    *pointer = newValue;
296284990Scy    pointer_index++;
297284990Scy}
298284990Scy
299284990Scyvoid UnityPointer_UndoAllSets(void)
300284990Scy{
301284990Scy    while (pointer_index > 0)
302284990Scy    {
303284990Scy        pointer_index--;
304284990Scy        *(pointer_store[pointer_index].pointer) =
305284990Scy        pointer_store[pointer_index].old_value;
306284990Scy
307284990Scy    }
308284990Scy}
309284990Scy
310284990Scyint UnityFailureCount(void)
311284990Scy{
312284990Scy    return Unity.TestFailures;
313284990Scy}
314284990Scy
315284990Scyint UnityGetCommandLineOptions(int argc, const char* argv[])
316284990Scy{
317284990Scy    int i;
318284990Scy    UnityFixture.Verbose = 0;
319284990Scy    UnityFixture.GroupFilter = 0;
320284990Scy    UnityFixture.NameFilter = 0;
321284990Scy    UnityFixture.RepeatCount = 1;
322284990Scy
323284990Scy    if (argc == 1)
324284990Scy        return 0;
325284990Scy
326284990Scy    for (i = 1; i < argc; )
327284990Scy    {
328284990Scy        if (strcmp(argv[i], "-v") == 0)
329284990Scy        {
330284990Scy            UnityFixture.Verbose = 1;
331284990Scy            i++;
332284990Scy        }
333284990Scy        else if (strcmp(argv[i], "-g") == 0)
334284990Scy        {
335284990Scy            i++;
336284990Scy            if (i >= argc)
337284990Scy                return 1;
338284990Scy            UnityFixture.GroupFilter = argv[i];
339284990Scy            i++;
340284990Scy        }
341284990Scy        else if (strcmp(argv[i], "-n") == 0)
342284990Scy        {
343284990Scy            i++;
344284990Scy            if (i >= argc)
345284990Scy                return 1;
346284990Scy            UnityFixture.NameFilter = argv[i];
347284990Scy            i++;
348284990Scy        }
349284990Scy        else if (strcmp(argv[i], "-r") == 0)
350284990Scy        {
351284990Scy            UnityFixture.RepeatCount = 2;
352284990Scy            i++;
353284990Scy            if (i < argc)
354284990Scy            {
355284990Scy                if (*(argv[i]) >= '0' && *(argv[i]) <= '9')
356284990Scy                {
357284990Scy                    UnityFixture.RepeatCount = atoi(argv[i]);
358284990Scy                    i++;
359284990Scy                }
360284990Scy            }
361284990Scy        } else {
362284990Scy            // ignore unknown parameter
363284990Scy            i++;
364284990Scy        }
365284990Scy    }
366284990Scy    return 0;
367284990Scy}
368284990Scy
369284990Scyvoid UnityConcludeFixtureTest(void)
370284990Scy{
371284990Scy    if (Unity.CurrentTestIgnored)
372284990Scy    {
373284990Scy        if (UnityFixture.Verbose)
374284990Scy        {
375284990Scy            UNITY_OUTPUT_CHAR('\n');
376284990Scy        }
377284990Scy        Unity.TestIgnores++;
378284990Scy    }
379284990Scy    else if (!Unity.CurrentTestFailed)
380284990Scy    {
381284990Scy        if (UnityFixture.Verbose)
382284990Scy        {
383284990Scy            UnityPrint(" PASS");
384284990Scy            UNITY_OUTPUT_CHAR('\n');
385284990Scy        }
386284990Scy    }
387284990Scy    else if (Unity.CurrentTestFailed)
388284990Scy    {
389284990Scy        Unity.TestFailures++;
390284990Scy    }
391284990Scy
392284990Scy    Unity.CurrentTestFailed = 0;
393284990Scy    Unity.CurrentTestIgnored = 0;
394284990Scy}
395