1 /* Copyright (c) 2010 James Grenning and Contributed to Unity Project
2  * ==========================================
3  *  Unity Project - A Test Framework for C
4  *  Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
5  *  [Released under MIT License. Please refer to license.txt for details]
6  * ========================================== */
7 
8 #include "unity_fixture.h"
9 #include "unity_internals.h"
10 #include <string.h>
11 
12 struct UNITY_FIXTURE_T UnityFixture;
13 
14 /* If you decide to use the function pointer approach.
15  * Build with -D UNITY_OUTPUT_CHAR=outputChar and include <stdio.h>
16  * int (*outputChar)(int) = putchar; */
17 
18 #if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA)
setUp(void)19 void setUp(void)    { /*does nothing*/ }
tearDown(void)20 void tearDown(void) { /*does nothing*/ }
21 #endif
22 
announceTestRun(unsigned int runNumber)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 
UnityMain(int argc,const char * argv[],void (* runAllTests)(void))32 int UnityMain(int argc, const char* argv[], void (*runAllTests)(void))
33 {
34     int result = UnityGetCommandLineOptions(argc, argv);
35     unsigned int r;
36     if (result != 0)
37         return result;
38 
39     for (r = 0; r < UnityFixture.RepeatCount; r++)
40     {
41         UnityBegin(argv[0]);
42         announceTestRun(r);
43         runAllTests();
44         if (!UnityFixture.Verbose) UNITY_PRINT_EOL();
45         UnityEnd();
46     }
47 
48     return (int)Unity.TestFailures;
49 }
50 
selected(const char * filter,const char * name)51 static int selected(const char* filter, const char* name)
52 {
53     if (filter == 0)
54         return 1;
55     return strstr(name, filter) ? 1 : 0;
56 }
57 
testSelected(const char * test)58 static int testSelected(const char* test)
59 {
60     return selected(UnityFixture.NameFilter, test);
61 }
62 
groupSelected(const char * group)63 static int groupSelected(const char* group)
64 {
65     return selected(UnityFixture.GroupFilter, group);
66 }
67 
UnityTestRunner(unityfunction * setup,unityfunction * testBody,unityfunction * teardown,const char * printableName,const char * group,const char * name,const char * file,unsigned int line)68 void UnityTestRunner(unityfunction* setup,
69                      unityfunction* testBody,
70                      unityfunction* teardown,
71                      const char* printableName,
72                      const char* group,
73                      const char* name,
74                      const char* file,
75                      unsigned int line)
76 {
77     if (testSelected(name) && groupSelected(group))
78     {
79         Unity.TestFile = file;
80         Unity.CurrentTestName = printableName;
81         Unity.CurrentTestLineNumber = line;
82         if (!UnityFixture.Verbose)
83             UNITY_OUTPUT_CHAR('.');
84         else
85         {
86             UnityPrint(printableName);
87         #ifndef UNITY_REPEAT_TEST_NAME
88             Unity.CurrentTestName = NULL;
89         #endif
90         }
91 
92         Unity.NumberOfTests++;
93         UnityMalloc_StartTest();
94         UnityPointer_Init();
95 
96         if (TEST_PROTECT())
97         {
98             setup();
99             testBody();
100         }
101         if (TEST_PROTECT())
102         {
103             teardown();
104         }
105         if (TEST_PROTECT())
106         {
107             UnityPointer_UndoAllSets();
108             if (!Unity.CurrentTestFailed)
109                 UnityMalloc_EndTest();
110         }
111         UnityConcludeFixtureTest();
112     }
113 }
114 
UnityIgnoreTest(const char * printableName,const char * group,const char * name)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         if (!UnityFixture.Verbose)
122             UNITY_OUTPUT_CHAR('!');
123         else
124         {
125             UnityPrint(printableName);
126             UNITY_PRINT_EOL();
127         }
128     }
129 }
130 
131 
132 /*------------------------------------------------- */
133 /* Malloc and free stuff */
134 #define MALLOC_DONT_FAIL -1
135 static int malloc_count;
136 static int malloc_fail_countdown = MALLOC_DONT_FAIL;
137 
UnityMalloc_StartTest(void)138 void UnityMalloc_StartTest(void)
139 {
140     malloc_count = 0;
141     malloc_fail_countdown = MALLOC_DONT_FAIL;
142 }
143 
UnityMalloc_EndTest(void)144 void UnityMalloc_EndTest(void)
145 {
146     malloc_fail_countdown = MALLOC_DONT_FAIL;
147     if (malloc_count != 0)
148     {
149         UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!");
150     }
151 }
152 
UnityMalloc_MakeMallocFailAfterCount(int countdown)153 void UnityMalloc_MakeMallocFailAfterCount(int countdown)
154 {
155     malloc_fail_countdown = countdown;
156 }
157 
158 /* These definitions are always included from unity_fixture_malloc_overrides.h */
159 /* We undef to use them or avoid conflict with <stdlib.h> per the C standard */
160 #undef malloc
161 #undef free
162 #undef calloc
163 #undef realloc
164 
165 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
166 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 typedef struct GuardBytes
173 {
174     size_t size;
175     size_t guard_space;
176 } Guard;
177 
178 
179 static const char end[] = "END";
180 
unity_malloc(size_t size)181 void* unity_malloc(size_t size)
182 {
183     char* mem;
184     Guard* guard;
185     size_t total_size = size + sizeof(Guard) + sizeof(end);
186 
187     if (malloc_fail_countdown != MALLOC_DONT_FAIL)
188     {
189         if (malloc_fail_countdown == 0)
190             return NULL;
191         malloc_fail_countdown--;
192     }
193 
194     if (size == 0) return NULL;
195 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
196     if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES)
197     {
198         guard = NULL;
199     }
200     else
201     {
202         guard = (Guard*)&unity_heap[heap_index];
203         heap_index += total_size;
204     }
205 #else
206     guard = (Guard*)UNITY_FIXTURE_MALLOC(total_size);
207 #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     return (void*)mem;
216 }
217 
isOverrun(void * mem)218 static int isOverrun(void* mem)
219 {
220     Guard* guard = (Guard*)mem;
221     char* memAsChar = (char*)mem;
222     guard--;
223 
224     return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0;
225 }
226 
release_memory(void * mem)227 static void release_memory(void* mem)
228 {
229     Guard* guard = (Guard*)mem;
230     guard--;
231 
232     malloc_count--;
233 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
234     if (mem == unity_heap + heap_index - guard->size - sizeof(end))
235     {
236         heap_index -= (guard->size + sizeof(Guard) + sizeof(end));
237     }
238 #else
239     UNITY_FIXTURE_FREE(guard);
240 #endif
241 }
242 
unity_free(void * mem)243 void unity_free(void* mem)
244 {
245     int overrun;
246 
247     if (mem == NULL)
248     {
249         return;
250     }
251 
252     overrun = isOverrun(mem);
253     release_memory(mem);
254     if (overrun)
255     {
256         UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()");
257     }
258 }
259 
unity_calloc(size_t num,size_t size)260 void* unity_calloc(size_t num, size_t size)
261 {
262     void* mem = unity_malloc(num * size);
263     if (mem == NULL) return NULL;
264     memset(mem, 0, num * size);
265     return mem;
266 }
267 
unity_realloc(void * oldMem,size_t size)268 void* unity_realloc(void* oldMem, size_t size)
269 {
270     Guard* guard = (Guard*)oldMem;
271     void* newMem;
272 
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     if (size == 0)
283     {
284         release_memory(oldMem);
285         return NULL;
286     }
287 
288     if (guard->size >= size) return oldMem;
289 
290 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC /* Optimization if memory is expandable */
291     if (oldMem == unity_heap + heap_index - guard->size - sizeof(end) &&
292         heap_index + size - guard->size <= UNITY_INTERNAL_HEAP_SIZE_BYTES)
293     {
294         release_memory(oldMem);    /* Not thread-safe, like unity_heap generally */
295         return unity_malloc(size); /* No memcpy since data is in place */
296     }
297 #endif
298     newMem = unity_malloc(size);
299     if (newMem == NULL) return NULL; /* Do not release old memory */
300     memcpy(newMem, oldMem, guard->size);
301     release_memory(oldMem);
302     return newMem;
303 }
304 
305 
306 /*-------------------------------------------------------- */
307 /*Automatic pointer restoration functions */
308 struct PointerPair
309 {
310     void** pointer;
311     void* old_value;
312 };
313 
314 static struct PointerPair pointer_store[UNITY_MAX_POINTERS];
315 static int pointer_index = 0;
316 
UnityPointer_Init(void)317 void UnityPointer_Init(void)
318 {
319     pointer_index = 0;
320 }
321 
UnityPointer_Set(void ** pointer,void * newValue,UNITY_LINE_TYPE line)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     else
329     {
330         pointer_store[pointer_index].pointer = pointer;
331         pointer_store[pointer_index].old_value = *pointer;
332         *pointer = newValue;
333         pointer_index++;
334     }
335 }
336 
UnityPointer_UndoAllSets(void)337 void UnityPointer_UndoAllSets(void)
338 {
339     while (pointer_index > 0)
340     {
341         pointer_index--;
342         *(pointer_store[pointer_index].pointer) =
343             pointer_store[pointer_index].old_value;
344     }
345 }
346 
UnityGetCommandLineOptions(int argc,const char * argv[])347 int UnityGetCommandLineOptions(int argc, const char* argv[])
348 {
349     int i;
350     UnityFixture.Verbose = 0;
351     UnityFixture.GroupFilter = 0;
352     UnityFixture.NameFilter = 0;
353     UnityFixture.RepeatCount = 1;
354 
355     if (argc == 1)
356         return 0;
357 
358     for (i = 1; i < argc; )
359     {
360         if (strcmp(argv[i], "-v") == 0)
361         {
362             UnityFixture.Verbose = 1;
363             i++;
364         }
365         else if (strcmp(argv[i], "-g") == 0)
366         {
367             i++;
368             if (i >= argc)
369                 return 1;
370             UnityFixture.GroupFilter = argv[i];
371             i++;
372         }
373         else if (strcmp(argv[i], "-n") == 0)
374         {
375             i++;
376             if (i >= argc)
377                 return 1;
378             UnityFixture.NameFilter = argv[i];
379             i++;
380         }
381         else if (strcmp(argv[i], "-r") == 0)
382         {
383             UnityFixture.RepeatCount = 2;
384             i++;
385             if (i < argc)
386             {
387                 if (*(argv[i]) >= '0' && *(argv[i]) <= '9')
388                 {
389                     unsigned int digit = 0;
390                     UnityFixture.RepeatCount = 0;
391                     while (argv[i][digit] >= '0' && argv[i][digit] <= '9')
392                     {
393                         UnityFixture.RepeatCount *= 10;
394                         UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0';
395                     }
396                     i++;
397                 }
398             }
399         }
400         else
401         {
402             /* ignore unknown parameter */
403             i++;
404         }
405     }
406     return 0;
407 }
408 
UnityConcludeFixtureTest(void)409 void UnityConcludeFixtureTest(void)
410 {
411     if (Unity.CurrentTestIgnored)
412     {
413         Unity.TestIgnores++;
414         UNITY_PRINT_EOL();
415     }
416     else if (!Unity.CurrentTestFailed)
417     {
418         if (UnityFixture.Verbose)
419         {
420             UnityPrint(" PASS");
421             UNITY_PRINT_EOL();
422         }
423     }
424     else /* Unity.CurrentTestFailed */
425     {
426         Unity.TestFailures++;
427         UNITY_PRINT_EOL();
428     }
429 
430     Unity.CurrentTestFailed = 0;
431     Unity.CurrentTestIgnored = 0;
432 }
433