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