1 /*
2 * CUnit - A Unit testing framework library for C.
3 * Copyright (C) 2004-2006 Jerry St.Clair, Anil Kumar
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /*
21 * Implementation for basic test runner interface.
22 *
23 * 11-Aug-2004 Initial implementation of basic test runner interface. (JDS)
24 *
25 * 8-Jan-2005 Fixed reporting bug (bug report cunit-Bugs-1093861). (JDS)
26 *
27 * 30-Apr-2005 Added notification of suite cleanup failure. (JDS)
28 *
29 * 02-May-2006 Added internationalization hooks. (JDS)
30 */
31
32 /** @file
33 * Basic interface with output to stdout.
34 */
35 /** @addtogroup Basic
36 * @{
37 */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <ctype.h>
42 #include <assert.h>
43 #include <string.h>
44
45 #include "CUnit.h"
46 #include "TestDB.h"
47 #include "Util.h"
48 #include "TestRun.h"
49 #include "Basic.h"
50 #include "CUnit_intl.h"
51
52 /*=================================================================
53 * Global/Static Definitions
54 *=================================================================*/
55 /** Pointer to the currently running suite. */
56 static CU_pSuite f_pRunningSuite = NULL;
57 /** Current run mode. */
58 static CU_BasicRunMode f_run_mode = CU_BRM_NORMAL;
59
60 /*=================================================================
61 * Forward declaration of module functions *
62 *=================================================================*/
63 static CU_ErrorCode basic_initialize(void);
64 static CU_ErrorCode basic_run_all_tests(CU_pTestRegistry pRegistry);
65 static CU_ErrorCode basic_run_suite(CU_pSuite pSuite);
66 static CU_ErrorCode basic_run_single_test(CU_pSuite pSuite, CU_pTest pTest);
67
68 static void basic_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite);
69 static void basic_test_complete_message_handler(const CU_pTest pTest, const CU_pSuite pSuite, const CU_pFailureRecord pFailureList);
70 static void basic_all_tests_complete_message_handler(const CU_pFailureRecord pFailure);
71 static void basic_suite_init_failure_message_handler(const CU_pSuite pSuite);
72 static void basic_suite_cleanup_failure_message_handler(const CU_pSuite pSuite);
73
74 /*=================================================================
75 * Public Interface functions
76 *=================================================================*/
CU_basic_run_tests(void)77 CU_ErrorCode CU_basic_run_tests(void)
78 {
79 CU_ErrorCode error;
80
81 if (NULL == CU_get_registry()) {
82 if (CU_BRM_SILENT != f_run_mode)
83 fprintf(stderr, "\n\n%s\n", _("FATAL ERROR - Test registry is not initialized."));
84 error = CUE_NOREGISTRY;
85 }
86 else if (CUE_SUCCESS == (error = basic_initialize()))
87 error = basic_run_all_tests(NULL);
88
89 return error;
90 }
91
92 /*------------------------------------------------------------------------*/
CU_basic_run_suite(CU_pSuite pSuite)93 CU_ErrorCode CU_basic_run_suite(CU_pSuite pSuite)
94 {
95 CU_ErrorCode error;
96
97 if (NULL == pSuite)
98 error = CUE_NOSUITE;
99 else if (CUE_SUCCESS == (error = basic_initialize()))
100 error = basic_run_suite(pSuite);
101
102 return error;
103 }
104
105 /*------------------------------------------------------------------------*/
CU_basic_run_test(CU_pSuite pSuite,CU_pTest pTest)106 CU_ErrorCode CU_basic_run_test(CU_pSuite pSuite, CU_pTest pTest)
107 {
108 CU_ErrorCode error;
109
110 if (NULL == pSuite)
111 error = CUE_NOSUITE;
112 else if (NULL == pTest)
113 error = CUE_NOTEST;
114 else if (CUE_SUCCESS == (error = basic_initialize()))
115 error = basic_run_single_test(pSuite, pTest);
116
117 return error;
118 }
119
120 /*------------------------------------------------------------------------*/
CU_basic_set_mode(CU_BasicRunMode mode)121 void CU_basic_set_mode(CU_BasicRunMode mode)
122 {
123 f_run_mode = mode;
124 }
125
126 /*------------------------------------------------------------------------*/
CU_basic_get_mode(void)127 CU_BasicRunMode CU_basic_get_mode(void)
128 {
129 return f_run_mode;
130 }
131
132 /*------------------------------------------------------------------------*/
CU_basic_show_failures(CU_pFailureRecord pFailure)133 void CU_basic_show_failures(CU_pFailureRecord pFailure)
134 {
135 int i;
136
137 for (i = 1 ; (NULL != pFailure) ; pFailure = pFailure->pNext, i++) {
138 fprintf(stdout, "\n %d. %s:%u - %s", i,
139 (NULL != pFailure->strFileName) ? pFailure->strFileName : "",
140 pFailure->uiLineNumber,
141 (NULL != pFailure->strCondition) ? pFailure->strCondition : "");
142 }
143 }
144
145 /*=================================================================
146 * Static module functions
147 *=================================================================*/
148 /** Performs inialization actions for the basic interface.
149 * This includes setting output to unbuffered, printing a
150 * welcome message, and setting the test run handlers.
151 * @return An error code indicating the framework error condition.
152 */
basic_initialize(void)153 static CU_ErrorCode basic_initialize(void)
154 {
155 /* Unbuffered output so everything reaches the screen */
156 setvbuf(stdout, NULL, _IONBF, 0);
157 setvbuf(stderr, NULL, _IONBF, 0);
158
159 CU_set_error(CUE_SUCCESS);
160
161 if (CU_BRM_SILENT != f_run_mode)
162 fprintf(stdout, "\n\n %s" CU_VERSION
163 "\n %s\n\n",
164 _("CUnit - A unit testing framework for C - Version "),
165 _("http://cunit.sourceforge.net/"));
166
167 CU_set_test_start_handler(basic_test_start_message_handler);
168 CU_set_test_complete_handler(basic_test_complete_message_handler);
169 CU_set_all_test_complete_handler(basic_all_tests_complete_message_handler);
170 CU_set_suite_init_failure_handler(basic_suite_init_failure_message_handler);
171 CU_set_suite_cleanup_failure_handler(basic_suite_cleanup_failure_message_handler);
172
173 return CU_get_error();
174 }
175
176 /*------------------------------------------------------------------------*/
177 /** Runs all tests within the basic interface.
178 * If non-NULL, the test registry is changed to the specified registry
179 * before running the tests, and reset to the original registry when
180 * done. If NULL, the default CUnit test registry will be used.
181 * @param pRegistry The CU_pTestRegistry containing the tests
182 * to be run. If NULL, use the default registry.
183 * @return An error code indicating the error status
184 * during the test run.
185 */
basic_run_all_tests(CU_pTestRegistry pRegistry)186 static CU_ErrorCode basic_run_all_tests(CU_pTestRegistry pRegistry)
187 {
188 CU_pTestRegistry pOldRegistry = NULL;
189 CU_ErrorCode result;
190
191 f_pRunningSuite = NULL;
192
193 if (NULL != pRegistry)
194 pOldRegistry = CU_set_registry(pRegistry);
195 result = CU_run_all_tests();
196 if (NULL != pRegistry)
197 CU_set_registry(pOldRegistry);
198 return result;
199 }
200
201 /*------------------------------------------------------------------------*/
202 /** Runs a specified suite within the basic interface.
203 * @param pSuite The suite to be run (non-NULL).
204 * @return An error code indicating the error status
205 * during the test run.
206 */
basic_run_suite(CU_pSuite pSuite)207 static CU_ErrorCode basic_run_suite(CU_pSuite pSuite)
208 {
209 f_pRunningSuite = NULL;
210 return CU_run_suite(pSuite);
211 }
212
213 /*------------------------------------------------------------------------*/
214 /** Runs a single test for the specified suite within
215 * the console interface.
216 * @param pSuite The suite containing the test to be run (non-NULL).
217 * @param pTest The test to be run (non-NULL).
218 * @return An error code indicating the error status
219 * during the test run.
220 */
basic_run_single_test(CU_pSuite pSuite,CU_pTest pTest)221 static CU_ErrorCode basic_run_single_test(CU_pSuite pSuite, CU_pTest pTest)
222 {
223 f_pRunningSuite = NULL;
224 return CU_run_test(pSuite, pTest);
225 }
226
227 /*------------------------------------------------------------------------*/
228 /** Handler function called at start of each test.
229 * @param pTest The test being run.
230 * @param pSuite The suite containing the test.
231 */
basic_test_start_message_handler(const CU_pTest pTest,const CU_pSuite pSuite)232 static void basic_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite)
233 {
234 assert(NULL != pSuite);
235 assert(NULL != pTest);
236
237 if (CU_BRM_VERBOSE == f_run_mode) {
238 assert(NULL != pTest->pName);
239 if ((NULL == f_pRunningSuite) || (f_pRunningSuite != pSuite)) {
240 assert(NULL != pSuite->pName);
241 fprintf(stdout, "\n%s: %s", _("Suite"), pSuite->pName);
242 fprintf(stdout, "\n %s: %s ...", _("Test"), pTest->pName);
243 f_pRunningSuite = pSuite;
244 }
245 else {
246 fprintf(stdout, "\n %s: %s ...", _("Test"), pTest->pName);
247 }
248 }
249 }
250
251 /*------------------------------------------------------------------------*/
252 /** Handler function called at completion of each test.
253 * @param pTest The test being run.
254 * @param pSuite The suite containing the test.
255 * @param pFailure Pointer to the 1st failure record for this test.
256 */
basic_test_complete_message_handler(const CU_pTest pTest,const CU_pSuite pSuite,const CU_pFailureRecord pFailureList)257 static void basic_test_complete_message_handler(const CU_pTest pTest,
258 const CU_pSuite pSuite,
259 const CU_pFailureRecord pFailureList)
260 {
261 CU_pFailureRecord pFailure = pFailureList;
262 int i;
263
264 assert(NULL != pSuite);
265 assert(NULL != pTest);
266
267 if (NULL == pFailure) {
268 if (CU_BRM_VERBOSE == f_run_mode) {
269 fprintf(stdout, _("passed"));
270 }
271 }
272 else {
273 switch (f_run_mode) {
274 case CU_BRM_VERBOSE:
275 fprintf(stdout, _("FAILED"));
276 break;
277 case CU_BRM_NORMAL:
278 assert(NULL != pSuite->pName);
279 assert(NULL != pTest->pName);
280 fprintf(stdout, _("\nSuite %s, Test %s had failures:"), pSuite->pName, pTest->pName);
281 break;
282 default: /* gcc wants all enums covered. ok. */
283 break;
284 }
285 if (CU_BRM_SILENT != f_run_mode) {
286 for (i = 1 ; (NULL != pFailure) ; pFailure = pFailure->pNext, i++) {
287 fprintf(stdout, "\n %d. %s:%u - %s", i,
288 (NULL != pFailure->strFileName) ? pFailure->strFileName : "",
289 pFailure->uiLineNumber,
290 (NULL != pFailure->strCondition) ? pFailure->strCondition : "");
291 }
292 }
293 }
294 }
295
296 /*------------------------------------------------------------------------*/
297 /** Handler function called at completion of all tests in a suite.
298 * @param pFailure Pointer to the test failure record list.
299 */
basic_all_tests_complete_message_handler(const CU_pFailureRecord pFailure)300 static void basic_all_tests_complete_message_handler(const CU_pFailureRecord pFailure)
301 {
302 CU_UNREFERENCED_PARAMETER(pFailure); /* not used in basic interface */
303 printf("\n\n");
304 CU_print_run_results(stdout);
305 printf("\n");
306 }
307
308 /*------------------------------------------------------------------------*/
309 /** Handler function called when suite initialization fails.
310 * @param pSuite The suite for which initialization failed.
311 */
basic_suite_init_failure_message_handler(const CU_pSuite pSuite)312 static void basic_suite_init_failure_message_handler(const CU_pSuite pSuite)
313 {
314 assert(NULL != pSuite);
315 assert(NULL != pSuite->pName);
316
317 if (CU_BRM_SILENT != f_run_mode)
318 fprintf(stdout, _("\nWARNING - Suite initialization failed for '%s'."), pSuite->pName);
319 }
320
321 /*------------------------------------------------------------------------*/
322 /** Handler function called when suite cleanup fails.
323 * @param pSuite The suite for which cleanup failed.
324 */
basic_suite_cleanup_failure_message_handler(const CU_pSuite pSuite)325 static void basic_suite_cleanup_failure_message_handler(const CU_pSuite pSuite)
326 {
327 assert(NULL != pSuite);
328 assert(NULL != pSuite->pName);
329
330 if (CU_BRM_SILENT != f_run_mode)
331 fprintf(stdout, _("\nWARNING - Suite cleanup failed for '%s'."), pSuite->pName);
332 }
333
334 /** @} */
335