OSDN Git Service

add testCase null check
[ccunit/ccunit.git] / src / ccunit / CCUnitTestRunner.c
1 /* Copyright (C) 2003 TSUTSUMI Kikuo.
2    This file is part of the CCUnit Library.
3
4    The CCUnit Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public License
6    as published by the Free Software Foundation; either version 2.1 of
7    the License, or (at your option) any later version.
8
9    The CCUnit Library is distributed in the hope that it will be
10    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
11    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the CCUnit Library; see the file COPYING.LESSER.
16    If not, write to the Free Software Foundation, Inc., 59 Temple
17    Place - Suite 330, Boston, MA 02111-1307, USA.  
18 */
19
20 /*
21  * $Id$
22  */
23 /**@file
24  * TestRunner module implementation.
25  */
26 #include <stdio.h>
27 #include <ccunit/CCUnitTestRunner.h>
28
29 #if CCUNIT_TIME_WITH_SYS_TIME
30 #include <sys/time.h>
31 #endif
32
33 /** @addtogroup CCUnitTestRunner
34  * @{
35  */
36
37 /**
38  * receive startTest notification.
39  * @param listener notification listener.
40  * @param test starting test case
41  */
42 static void startTest (CCUnitTestListener* listener, CCUnitTestCase* test)
43 {
44   CCUnitTestRunner* runner = (CCUnitTestRunner*)listener;
45   fputc ('.', runner->ofp);
46 }
47
48 /**
49  * receive endTest notification.
50  * @param listener notification listener.
51  * @param test ended test case
52  */
53 static void endTest (CCUnitTestListener* listener, CCUnitTestCase* test)
54 {
55 }
56
57 /**
58  * receive addFailure notification.
59  * @param listener notification listener.
60  * @param failure failure information.
61  */
62 static void addFailure (CCUnitTestListener* listener, CCUnitTestFailure* failure)
63 {
64   CCUnitTestRunner* runner = (CCUnitTestRunner*)listener;
65   fputc ('F', runner->ofp);
66 }
67
68 /**
69  * Prints the header of the report.
70  * @param runner test runner.
71  * @param result test result.
72  */
73 static void printHeader (CCUnitTestRunner* runner, CCUnitTestResult* result)
74 {
75   FILE* ofp;
76   if (!runner)
77     return;
78   ofp = runner->ofp;
79   if (ccunit_wasSuccessful (result))
80     {
81       fputc ('\n', ofp);
82       fprintf (ofp, "OK (%lu tests)\n",
83                (unsigned long)ccunit_runCount (result));
84     }
85   else
86     {
87       fputc ('\n', ofp);
88       fprintf (ofp,
89                "FAILURES!!!\n"
90                "Test Results: \n"
91                "Run %lu, Failures %lu\n",
92                (unsigned long)ccunit_runCount (result),
93                (unsigned long)ccunit_failureCount (result));
94     }
95 }
96
97 /**
98  * Prints failures.
99  * @param runner test runner.
100  * @param result test result.
101  */
102 static void printFailures (CCUnitTestRunner* runner, CCUnitTestResult* result)
103 {
104   CCUnitListIterator* itor;
105   CCUnitTestFailure* f;
106   unsigned long num;
107   if (!runner || !result)
108     return;
109   num = ccunit_failureCount (result);
110   if (!num)
111     return;
112   if (num == 1)
113     fprintf (runner->ofp, "There was %lu failure:\n", num);
114   else
115     fprintf (runner->ofp, "There was %lu failures:\n", num);
116   itor = ccunit_failures (result);
117   while ((f = ccunit_nextListIterator (itor)) != NULL)
118     {
119       fprintf (runner->ofp, "%s:%u: %s:\n\t%s\n",
120                f->file, f->line,
121                f->testCase != NULL ? f->testCase->desc : "",
122                f->condstr);
123       if (f->expect || f->actual)
124         fprintf (runner->ofp, "\texpect: %s\n\tactual: %s\n", f->expect, f->actual);
125     }
126   ccunit_deleteListIterator (itor);
127 }
128
129 /**
130  * Prints failures.
131  * @param runner test runner
132  * @param result test result
133  */
134 static inline void print (CCUnitTestRunner* runner, CCUnitTestResult* result)
135 {
136   printHeader (runner, result);
137   printFailures (runner, result);
138 }
139
140 /**
141  * Runs a single test and collects its results.
142  * @param runner test runner
143  * @param suite test suite
144  * @return 0 if succeeded. -1 if error occurd.
145  */
146 static int doRun (CCUnitTestRunner* runner, CCUnitTestSuite* suite)
147 {
148   struct timeval startTime;
149   struct timeval endTime;
150   struct timeval runTime;
151   if (!runner || !suite)
152     return -1;
153   runner->result = ccunit_newTestResult ();
154   ccunit_addResultListener (runner->result, &runner->listener);
155   timerclear (&startTime);
156   timerclear (&endTime);
157   timerclear (&runTime);
158   gettimeofday (&startTime, NULL);
159   ccunit_runTestSuite (suite, runner->result);
160   gettimeofday (&endTime, NULL);
161   timersub (&endTime, &startTime, &runTime);
162   fprintf (runner->ofp,
163            "\n"
164            "Time: %lu.%06lu sec\n",
165            (unsigned long)runTime.tv_sec, (unsigned long)runTime.tv_usec);
166   print (runner, runner->result);
167   fputc ('\n', runner->ofp);
168   return ccunit_wasSuccessful (runner->result) ? 0 : -1;
169 }
170
171 CCUnitTestRunner* ccunit_newTestRunner (FILE* output)
172 {
173   CCUnitTestRunner* runner = calloc (1, sizeof (CCUnitTestRunner));
174   if (!runner)
175     return NULL;
176   runner->listener.startTest = startTest;
177   runner->listener.endTest = endTest;
178   runner->listener.addFailure = addFailure;
179   runner->ofp = !output ? stdout : output;
180   runner->run = doRun;
181   return runner;
182 }
183
184 void ccunit_deleteTestRunner (CCUnitTestRunner* runner)
185 {
186   if (!runner)
187     return;
188   ccunit_deleteTestResult (runner->result);
189   free (runner);
190 }
191
192 inline int ccunit_runTestRunner (CCUnitTestRunner* runner, CCUnitTestSuite* suite)
193 {
194   return runner->run (runner, suite);
195 }
196
197 inline CCUnitTestResult* ccunit_getResult (CCUnitTestRunner* runner)
198 {
199   return runner->result;
200 }
201
202 /** @} */