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 
setUp(void)18 void setUp(void)    { /*does nothing*/ }
tearDown(void)19 void tearDown(void) { /*does nothing*/ }
20 
announceTestRun(unsigned int runNumber)21 static void announceTestRun(unsigned int runNumber)
22 {
23     UnityPrint("Unity test run ");
24     UnityPrintNumberUnsigned(runNumber+1);
25     UnityPrint(" of ");
26     UnityPrintNumberUnsigned(UnityFixture.RepeatCount);
27     UNITY_PRINT_EOL();
28 }
29 
UnityMain(int argc,const char * argv[],void (* runAllTests)(void))30 int UnityMain(int argc, const char* argv[], void (*runAllTests)(void))
31 {
32     int result = UnityGetCommandLineOptions(argc, argv);
33     unsigned int r;
34     if (result != 0)
35         return result;
36 
37     for (r = 0; r < UnityFixture.RepeatCount; r++)
38     {
39         UnityBegin(argv[0]);
40         announceTestRun(r);
41         runAllTests();
42         if (!UnityFixture.Verbose) UNITY_PRINT_EOL();
43         UnityEnd();
44     }
45 
46     return (int)Unity.TestFailures;
47 }
48 
selected(const char * filter,const char * name)49 static int selected(const char* filter, const char* name)
50 {
51     if (filter == 0)
52         return 1;
53     return strstr(name, filter) ? 1 : 0;
54 }
55 
testSelected(const char * test)56 static int testSelected(const char* test)
57 {
58     return selected(UnityFixture.NameFilter, test);
59 }
60 
groupSelected(const char * group)61 static int groupSelected(const char* group)
62 {
63     return selected(UnityFixture.GroupFilter, group);
64 }
65 
UnityTestRunner(unityfunction * setup,unityfunction * testBody,unityfunction * teardown,const char * printableName,const char * group,const char * name,const char * file,unsigned int line)66 void UnityTestRunner(unityfunction* setup,
67                      unityfunction* testBody,
68                      unityfunction* teardown,
69                      const char* printableName,
70                      const char* group,
71                      const char* name,
72                      const char* file,
73                      unsigned int line)
74 {
75     if (testSelected(name) && groupSelected(group))
76     {
77         Unity.TestFile = file;
78         Unity.CurrentTestName = printableName;
79         Unity.CurrentTestLineNumber = line;
80         if (UnityFixture.Verbose)
81         {
82             UnityPrint(printableName);
83         #ifndef UNITY_REPEAT_TEST_NAME
84             Unity.CurrentTestName = NULL;
85         #endif
86         }
87         else if (UnityFixture.Silent)
88         {
89             /* Do Nothing */
90         }
91         else
92         {
93             UNITY_OUTPUT_CHAR('.');
94         }
95 
96         Unity.NumberOfTests++;
97         UnityPointer_Init();
98 
99         UNITY_EXEC_TIME_START();
100 
101         if (TEST_PROTECT())
102         {
103             setup();
104             testBody();
105         }
106         if (TEST_PROTECT())
107         {
108             teardown();
109         }
110         if (TEST_PROTECT())
111         {
112             UnityPointer_UndoAllSets();
113         }
114         UnityConcludeFixtureTest();
115     }
116 }
117 
UnityIgnoreTest(const char * printableName,const char * group,const char * name)118 void UnityIgnoreTest(const char* printableName, const char* group, const char* name)
119 {
120     if (testSelected(name) && groupSelected(group))
121     {
122         Unity.NumberOfTests++;
123         Unity.TestIgnores++;
124         if (UnityFixture.Verbose)
125         {
126             UnityPrint(printableName);
127             UNITY_PRINT_EOL();
128         }
129         else if (UnityFixture.Silent)
130         {
131             /* Do Nothing */
132         }
133         else
134         {
135             UNITY_OUTPUT_CHAR('!');
136         }
137     }
138 }
139 
140 /*-------------------------------------------------------- */
141 /*Automatic pointer restoration functions */
142 struct PointerPair
143 {
144     void** pointer;
145     void* old_value;
146 };
147 
148 static struct PointerPair pointer_store[UNITY_MAX_POINTERS];
149 static int pointer_index = 0;
150 
UnityPointer_Init(void)151 void UnityPointer_Init(void)
152 {
153     pointer_index = 0;
154 }
155 
UnityPointer_Set(void ** pointer,void * newValue,UNITY_LINE_TYPE line)156 void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line)
157 {
158     if (pointer_index >= UNITY_MAX_POINTERS)
159     {
160         UNITY_TEST_FAIL(line, "Too many pointers set");
161     }
162     else
163     {
164         pointer_store[pointer_index].pointer = pointer;
165         pointer_store[pointer_index].old_value = *pointer;
166         *pointer = newValue;
167         pointer_index++;
168     }
169 }
170 
UnityPointer_UndoAllSets(void)171 void UnityPointer_UndoAllSets(void)
172 {
173     while (pointer_index > 0)
174     {
175         pointer_index--;
176         *(pointer_store[pointer_index].pointer) =
177             pointer_store[pointer_index].old_value;
178     }
179 }
180 
UnityGetCommandLineOptions(int argc,const char * argv[])181 int UnityGetCommandLineOptions(int argc, const char* argv[])
182 {
183     int i;
184     UnityFixture.Verbose = 0;
185     UnityFixture.Silent = 0;
186     UnityFixture.GroupFilter = 0;
187     UnityFixture.NameFilter = 0;
188     UnityFixture.RepeatCount = 1;
189 
190     if (argc == 1)
191         return 0;
192 
193     for (i = 1; i < argc; )
194     {
195         if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
196         {
197             /* Usage */
198             UnityPrint("Runs a series of unit tests.");
199             UNITY_PRINT_EOL();
200             UNITY_PRINT_EOL();
201             UnityPrint("When no flag is specified, all tests are run.");
202             UNITY_PRINT_EOL();
203             UNITY_PRINT_EOL();
204             UnityPrint("Optional flags:");
205             UNITY_PRINT_EOL();
206             UnityPrint("  -v          Verbose output: show all tests executed even if they pass");
207             UNITY_PRINT_EOL();
208             UnityPrint("  -s          Silent mode: minimal output showing only test failures");
209             UNITY_PRINT_EOL();
210             UnityPrint("  -g NAME     Only run tests in groups that contain the string NAME");
211             UNITY_PRINT_EOL();
212             UnityPrint("  -n NAME     Only run tests whose name contains the string NAME");
213             UNITY_PRINT_EOL();
214             UnityPrint("  -r NUMBER   Repeatedly run all tests NUMBER times");
215             UNITY_PRINT_EOL();
216             UnityPrint("  -h, --help  Display this help message");
217             UNITY_PRINT_EOL();
218             UNITY_PRINT_EOL();
219 #ifdef UNITY_CUSTOM_HELP_MSG
220             /* User-defined help message, e.g. to point to project-specific documentation */
221             UnityPrint(UNITY_CUSTOM_HELP_MSG);
222             UNITY_PRINT_EOL();
223 #else
224             /* Default help suffix if a custom one is not defined */
225             UnityPrint("More information about Unity: https://www.throwtheswitch.org/unity");
226             UNITY_PRINT_EOL();
227 #endif
228             return 1;  /* Exit without running the tests */
229         }
230         else if (strcmp(argv[i], "-v") == 0)
231         {
232             UnityFixture.Verbose = 1;
233             i++;
234         }
235         else if (strcmp(argv[i], "-s") == 0)
236         {
237             UnityFixture.Silent = 1;
238             i++;
239         }
240         else if (strcmp(argv[i], "-g") == 0)
241         {
242             i++;
243             if (i >= argc)
244                 return 1;
245             UnityFixture.GroupFilter = argv[i];
246             i++;
247         }
248         else if (strcmp(argv[i], "-n") == 0)
249         {
250             i++;
251             if (i >= argc)
252                 return 1;
253             UnityFixture.NameFilter = argv[i];
254             i++;
255         }
256         else if (strcmp(argv[i], "-r") == 0)
257         {
258             UnityFixture.RepeatCount = 2;
259             i++;
260             if (i < argc)
261             {
262                 if (*(argv[i]) >= '0' && *(argv[i]) <= '9')
263                 {
264                     unsigned int digit = 0;
265                     UnityFixture.RepeatCount = 0;
266                     while (argv[i][digit] >= '0' && argv[i][digit] <= '9')
267                     {
268                         UnityFixture.RepeatCount *= 10;
269                         UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0';
270                     }
271                     i++;
272                 }
273             }
274         }
275         else
276         {
277             /* ignore unknown parameter */
278             i++;
279         }
280     }
281     return 0;
282 }
283 
UnityConcludeFixtureTest(void)284 void UnityConcludeFixtureTest(void)
285 {
286     if (Unity.CurrentTestIgnored)
287     {
288         Unity.TestIgnores++;
289         UNITY_PRINT_EOL();
290     }
291     else if (!Unity.CurrentTestFailed)
292     {
293         if (UnityFixture.Verbose)
294         {
295             UnityPrint(" ");
296             UnityPrint(UnityStrPass);
297             UNITY_EXEC_TIME_STOP();
298             UNITY_PRINT_EXEC_TIME();
299             UNITY_PRINT_EOL();
300         }
301     }
302     else /* Unity.CurrentTestFailed */
303     {
304         Unity.TestFailures++;
305         UNITY_PRINT_EOL();
306     }
307 
308     Unity.CurrentTestFailed = 0;
309     Unity.CurrentTestIgnored = 0;
310 }
311