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