1130812Smarcel//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
2130812Smarcel/* ==========================================
3130812Smarcel    Unity Project - A Test Framework for C
4130812Smarcel    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
5130812Smarcel    [Released under MIT License. Please refer to license.txt for details]
6130812Smarcel========================================== */
7130812Smarcel
8130812Smarcel#include <string.h>
9130812Smarcel#include <stdio.h>
10130812Smarcel#include "unity_fixture.h"
11130812Smarcel#include "unity_internals.h"
12130812Smarcel
13130812SmarcelUNITY_FIXTURE_T UnityFixture;
14130812Smarcel
15130812Smarcel//If you decide to use the function pointer approach.
16130812Smarcelint (*outputChar)(int) = putchar;
17130812Smarcel
18130812Smarcelint verbose = 0;
19130812Smarcel
20130812Smarcel
21130812Smarcelstatic void announceTestRun(unsigned int runNumber)
22130812Smarcel{
23130812Smarcel    UnityPrint("Unity test run ");
24130812Smarcel    UnityPrintNumber(runNumber+1);
25130812Smarcel    UnityPrint(" of ");
26130812Smarcel    UnityPrintNumber(UnityFixture.RepeatCount);
27130812Smarcel    UNITY_OUTPUT_CHAR('\n');
28130812Smarcel}
29130812Smarcel
30130812Smarcelint UnityMain(int argc, const char* argv[], void (*runAllTests)(void))
31130812Smarcel{
32130812Smarcel    int result = UnityGetCommandLineOptions(argc, argv);
33130812Smarcel    unsigned int r;
34130812Smarcel    if (result != 0)
35130812Smarcel        return result;
36130812Smarcel
37130812Smarcel    for (r = 0; r < UnityFixture.RepeatCount; r++)
38130812Smarcel    {
39130812Smarcel        UnityBegin(argv[0]);
40130812Smarcel        announceTestRun(r);
41130812Smarcel        runAllTests();
42130812Smarcel        UNITY_OUTPUT_CHAR('\n');
43130812Smarcel        UnityEnd();
44130812Smarcel    }
45130812Smarcel
46130812Smarcel    return UnityFailureCount();
47130812Smarcel}
48130812Smarcel
49130812Smarcelstatic int selected(const char * filter, const char * name)
50130812Smarcel{
51130812Smarcel    if (filter == 0)
52130812Smarcel        return 1;
53130812Smarcel    return strstr(name, filter) ? 1 : 0;
54130812Smarcel}
55130812Smarcel
56130812Smarcelstatic int testSelected(const char* test)
57130812Smarcel{
58130812Smarcel    return selected(UnityFixture.NameFilter, test);
59130812Smarcel}
60130812Smarcel
61130812Smarcelstatic int groupSelected(const char* group)
62130812Smarcel{
63130812Smarcel    return selected(UnityFixture.GroupFilter, group);
64130812Smarcel}
65130812Smarcel
66130812Smarcelstatic void runTestCase(void)
67130812Smarcel{
68130812Smarcel
69130812Smarcel}
70130812Smarcel
71130812Smarcelvoid UnityTestRunner(unityfunction* setup,
72130812Smarcel        unityfunction* testBody,
73130812Smarcel        unityfunction* teardown,
74130812Smarcel        const char * printableName,
75130812Smarcel        const char * group,
76130812Smarcel        const char * name,
77130812Smarcel        const char * file, int line)
78130812Smarcel{
79130812Smarcel    if (testSelected(name) && groupSelected(group))
80130812Smarcel    {
81130812Smarcel        Unity.CurrentTestFailed = 0;
82130812Smarcel        Unity.TestFile = file;
83130812Smarcel        Unity.CurrentTestName = printableName;
84130812Smarcel        Unity.CurrentTestLineNumber = line;
85130812Smarcel        if (!UnityFixture.Verbose)
86130812Smarcel            UNITY_OUTPUT_CHAR('.');
87130812Smarcel        else
88130812Smarcel            UnityPrint(printableName);
89130812Smarcel
90130812Smarcel        Unity.NumberOfTests++;
91130812Smarcel        UnityMalloc_StartTest();
92130812Smarcel        UnityPointer_Init();
93130812Smarcel
94130812Smarcel        runTestCase();
95130812Smarcel        if (TEST_PROTECT())
96130812Smarcel        {
97130812Smarcel            setup();
98130812Smarcel            testBody();
99130812Smarcel        }
100130812Smarcel        if (TEST_PROTECT())
101130812Smarcel        {
102130812Smarcel            teardown();
103130812Smarcel        }
104130812Smarcel        if (TEST_PROTECT())
105130812Smarcel        {
106130812Smarcel            UnityPointer_UndoAllSets();
107130812Smarcel            if (!Unity.CurrentTestFailed)
108130812Smarcel                UnityMalloc_EndTest();
109130812Smarcel        }
110130812Smarcel        UnityConcludeFixtureTest();
111130812Smarcel    }
112130812Smarcel}
113130812Smarcel
114130812Smarcelvoid UnityIgnoreTest(const char * printableName)
115130812Smarcel{
116130812Smarcel    Unity.NumberOfTests++;
117130812Smarcel    Unity.CurrentTestIgnored = 1;
118130812Smarcel    if (!UnityFixture.Verbose)
119130812Smarcel        UNITY_OUTPUT_CHAR('!');
120130812Smarcel    else
121130812Smarcel        UnityPrint(printableName);
122130812Smarcel    UnityConcludeFixtureTest();
123130812Smarcel}
124130812Smarcel
125130812Smarcel
126130812Smarcel//-------------------------------------------------
127130812Smarcel//Malloc and free stuff
128130812Smarcel//
129130812Smarcel#define MALLOC_DONT_FAIL -1
130130812Smarcelstatic int malloc_count;
131130812Smarcelstatic int malloc_fail_countdown = MALLOC_DONT_FAIL;
132130812Smarcel
133130812Smarcelvoid UnityMalloc_StartTest(void)
134130812Smarcel{
135130812Smarcel    malloc_count = 0;
136130812Smarcel    malloc_fail_countdown = MALLOC_DONT_FAIL;
137130812Smarcel}
138130812Smarcel
139130812Smarcelvoid UnityMalloc_EndTest(void)
140130812Smarcel{
141130812Smarcel    malloc_fail_countdown = MALLOC_DONT_FAIL;
142130812Smarcel    if (malloc_count != 0)
143130812Smarcel    {
144130812Smarcel        TEST_FAIL_MESSAGE("This test leaks!");
145130812Smarcel    }
146130812Smarcel}
147130812Smarcel
148130812Smarcelvoid UnityMalloc_MakeMallocFailAfterCount(int countdown)
149130812Smarcel{
150130812Smarcel    malloc_fail_countdown = countdown;
151130812Smarcel}
152130812Smarcel
153130812Smarcel#ifdef malloc
154130812Smarcel#undef malloc
155130812Smarcel#endif
156130812Smarcel
157130812Smarcel#ifdef free
158130812Smarcel#undef free
159130812Smarcel#endif
160130812Smarcel
161130812Smarcel#ifdef calloc
162130812Smarcel#undef calloc
163130812Smarcel#endif
164130812Smarcel
165130812Smarcel#ifdef realloc
166130812Smarcel#undef realloc
167130812Smarcel#endif
168130812Smarcel
169130812Smarcel#include <stdlib.h>
170130812Smarcel#include <string.h>
171130812Smarcel
172130812Smarceltypedef struct GuardBytes
173130812Smarcel{
174130812Smarcel    size_t size;
175130812Smarcel    char guard[sizeof(size_t)];
176130812Smarcel} Guard;
177130812Smarcel
178130812Smarcel
179static const char * end = "END";
180
181void * unity_malloc(size_t size)
182{
183    char* mem;
184    Guard* guard;
185
186    if (malloc_fail_countdown != MALLOC_DONT_FAIL)
187    {
188        if (malloc_fail_countdown == 0)
189            return 0;
190        malloc_fail_countdown--;
191    }
192
193    malloc_count++;
194
195    guard = (Guard*)malloc(size + sizeof(Guard) + 4);
196    guard->size = size;
197    mem = (char*)&(guard[1]);
198    memcpy(&mem[size], end, strlen(end) + 1);
199
200    return (void*)mem;
201}
202
203static int isOverrun(void * mem)
204{
205    Guard* guard = (Guard*)mem;
206    char* memAsChar = (char*)mem;
207    guard--;
208
209    return strcmp(&memAsChar[guard->size], end) != 0;
210}
211
212static void release_memory(void * mem)
213{
214    Guard* guard = (Guard*)mem;
215    guard--;
216
217    malloc_count--;
218    free(guard);
219}
220
221void unity_free(void * mem)
222{
223    int overrun = isOverrun(mem);//strcmp(&memAsChar[guard->size], end) != 0;
224    release_memory(mem);
225    if (overrun)
226    {
227        TEST_FAIL_MESSAGE("Buffer overrun detected during free()");
228    }
229}
230
231void* unity_calloc(size_t num, size_t size)
232{
233    void* mem = unity_malloc(num * size);
234    memset(mem, 0, num*size);
235    return mem;
236}
237
238void* unity_realloc(void * oldMem, size_t size)
239{
240    Guard* guard = (Guard*)oldMem;
241//    char* memAsChar = (char*)oldMem;
242    void* newMem;
243
244    if (oldMem == 0)
245        return unity_malloc(size);
246
247    guard--;
248    if (isOverrun(oldMem))
249    {
250        release_memory(oldMem);
251        TEST_FAIL_MESSAGE("Buffer overrun detected during realloc()");
252    }
253
254    if (size == 0)
255    {
256        release_memory(oldMem);
257        return 0;
258    }
259
260    if (guard->size >= size)
261        return oldMem;
262
263    newMem = unity_malloc(size);
264    memcpy(newMem, oldMem, guard->size);
265    unity_free(oldMem);
266    return newMem;
267}
268
269
270//--------------------------------------------------------
271//Automatic pointer restoration functions
272typedef struct _PointerPair
273{
274    struct _PointerPair * next;
275    void ** pointer;
276    void * old_value;
277} PointerPair;
278
279enum {MAX_POINTERS=50};
280static PointerPair pointer_store[MAX_POINTERS];
281static int pointer_index = 0;
282
283void UnityPointer_Init(void)
284{
285    pointer_index = 0;
286}
287
288void UnityPointer_Set(void ** pointer, void * newValue)
289{
290    if (pointer_index >= MAX_POINTERS)
291        TEST_FAIL_MESSAGE("Too many pointers set");
292
293    pointer_store[pointer_index].pointer = pointer;
294    pointer_store[pointer_index].old_value = *pointer;
295    *pointer = newValue;
296    pointer_index++;
297}
298
299void UnityPointer_UndoAllSets(void)
300{
301    while (pointer_index > 0)
302    {
303        pointer_index--;
304        *(pointer_store[pointer_index].pointer) =
305        pointer_store[pointer_index].old_value;
306
307    }
308}
309
310int UnityFailureCount(void)
311{
312    return Unity.TestFailures;
313}
314
315int UnityGetCommandLineOptions(int argc, const char* argv[])
316{
317    int i;
318    UnityFixture.Verbose = 0;
319    UnityFixture.GroupFilter = 0;
320    UnityFixture.NameFilter = 0;
321    UnityFixture.RepeatCount = 1;
322
323    if (argc == 1)
324        return 0;
325
326    for (i = 1; i < argc; )
327    {
328        if (strcmp(argv[i], "-v") == 0)
329        {
330            UnityFixture.Verbose = 1;
331            i++;
332        }
333        else if (strcmp(argv[i], "-g") == 0)
334        {
335            i++;
336            if (i >= argc)
337                return 1;
338            UnityFixture.GroupFilter = argv[i];
339            i++;
340        }
341        else if (strcmp(argv[i], "-n") == 0)
342        {
343            i++;
344            if (i >= argc)
345                return 1;
346            UnityFixture.NameFilter = argv[i];
347            i++;
348        }
349        else if (strcmp(argv[i], "-r") == 0)
350        {
351            UnityFixture.RepeatCount = 2;
352            i++;
353            if (i < argc)
354            {
355                if (*(argv[i]) >= '0' && *(argv[i]) <= '9')
356                {
357                    UnityFixture.RepeatCount = atoi(argv[i]);
358                    i++;
359                }
360            }
361        } else {
362            // ignore unknown parameter
363            i++;
364        }
365    }
366    return 0;
367}
368
369void UnityConcludeFixtureTest(void)
370{
371    if (Unity.CurrentTestIgnored)
372    {
373        if (UnityFixture.Verbose)
374        {
375            UNITY_OUTPUT_CHAR('\n');
376        }
377        Unity.TestIgnores++;
378    }
379    else if (!Unity.CurrentTestFailed)
380    {
381        if (UnityFixture.Verbose)
382        {
383            UnityPrint(" PASS");
384            UNITY_OUTPUT_CHAR('\n');
385        }
386    }
387    else if (Unity.CurrentTestFailed)
388    {
389        Unity.TestFailures++;
390    }
391
392    Unity.CurrentTestFailed = 0;
393    Unity.CurrentTestIgnored = 0;
394}
395