2 * Check: a unit test framework for C
3 * Copyright (C) 2001, 2002 Arien Malec
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
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 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
25 #ifdef HAVE_SYS_TIME_H
30 #if HAVE_SUBUNIT_CHILD_H
31 #include <subunit/child.h>
34 #include "check_error.h"
35 #include "check_list.h"
36 #include "check_impl.h"
37 #include "check_log.h"
38 #include "check_print.h"
39 #include "check_str.h"
41 /* localtime_r is apparently not available on Windows */
42 #ifndef HAVE_LOCALTIME_R
44 localtime_r (const time_t * clock, struct tm *result)
46 struct tm *now = localtime (clock);
54 #endif /* HAVE_DECL_LOCALTIME_R */
56 static void srunner_send_evt (SRunner * sr, void *obj, enum cl_event evt);
59 srunner_set_log (SRunner * sr, const char *fname)
63 sr->log_fname = fname;
67 srunner_has_log (SRunner * sr)
69 return sr->log_fname != NULL;
73 srunner_log_fname (SRunner * sr)
80 srunner_set_xml (SRunner * sr, const char *fname)
84 sr->xml_fname = fname;
88 srunner_has_xml (SRunner * sr)
90 return sr->xml_fname != NULL;
94 srunner_xml_fname (SRunner * sr)
100 srunner_register_lfun (SRunner * sr, FILE * lfile, int close,
101 LFun lfun, enum print_output printmode)
103 Log *l = emalloc (sizeof (Log));
105 if (printmode == CK_ENV) {
106 printmode = get_env_printmode ();
113 list_add_end (sr->loglst, l);
118 log_srunner_start (SRunner * sr)
120 srunner_send_evt (sr, NULL, CLSTART_SR);
124 log_srunner_end (SRunner * sr)
126 srunner_send_evt (sr, NULL, CLEND_SR);
130 log_suite_start (SRunner * sr, Suite * s)
132 srunner_send_evt (sr, s, CLSTART_S);
136 log_suite_end (SRunner * sr, Suite * s)
138 srunner_send_evt (sr, s, CLEND_S);
142 log_test_start (SRunner * sr, TCase * tc, TF * tfun)
145 snprintf (buffer, 99, "%s:%s", tc->name, tfun->name);
146 srunner_send_evt (sr, buffer, CLSTART_T);
150 log_test_end (SRunner * sr, TestResult * tr)
152 srunner_send_evt (sr, tr, CLEND_T);
156 srunner_send_evt (SRunner * sr, void *obj, enum cl_event evt)
161 for (list_front (l); !list_at_end (l); list_advance (l)) {
164 lg->lfun (sr, lg->lfile, lg->mode, obj, evt);
170 stdout_lfun (SRunner * sr, FILE * file, enum print_output printmode,
171 void *obj, enum cl_event evt)
175 if (printmode == CK_ENV) {
176 printmode = get_env_printmode ();
185 if (printmode > CK_SILENT) {
186 fprintf (file, "Running suite(s):");
191 if (printmode > CK_SILENT) {
192 fprintf (file, " %s\n", s->name);
196 if (printmode > CK_SILENT) {
197 /* we don't want a newline before printing here, newlines should
198 come after printing a string, not before. it's better to add
199 the newline above in CLSTART_S.
201 srunner_fprint (file, sr, printmode);
212 eprintf ("Bad event type received in stdout_lfun", __FILE__, __LINE__);
219 lfile_lfun (SRunner * sr, FILE * file,
220 enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj,
235 fprintf (file, "Running suite %s\n", s->name);
238 fprintf (file, "Results for all suites run:\n");
239 srunner_fprint (file, sr, CK_MINIMAL);
248 tr_fprint (file, tr, CK_VERBOSE);
251 eprintf ("Bad event type received in lfile_lfun", __FILE__, __LINE__);
258 xml_lfun (SRunner * sr CK_ATTRIBUTE_UNUSED, FILE * file,
259 enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj,
264 static struct timeval inittv, endtv;
265 static char t[sizeof "yyyy-mm-dd hh:mm:ss"] = { 0 };
269 gettimeofday (&inittv, NULL);
270 localtime_r (&(inittv.tv_sec), &now);
271 strftime (t, sizeof ("yyyy-mm-dd hh:mm:ss"), "%Y-%m-%d %H:%M:%S", &now);
276 fprintf (file, "<?xml version=\"1.0\"?>\n");
278 "<testsuites xmlns=\"http://check.sourceforge.net/ns\">\n");
279 fprintf (file, " <datetime>%s</datetime>\n", t);
282 gettimeofday (&endtv, NULL);
283 fprintf (file, " <duration>%f</duration>\n",
284 (endtv.tv_sec + (float) (endtv.tv_usec) / 1000000) -
285 (inittv.tv_sec + (float) (inittv.tv_usec / 1000000)));
286 fprintf (file, "</testsuites>\n");
292 fprintf (file, " <suite>\n");
293 fprintf (file, " <title>%s</title>\n", s->name);
298 fprintf (file, " </suite>\n");
305 tr_xmlprint (file, tr, CK_VERBOSE);
308 eprintf ("Bad event type received in xml_lfun", __FILE__, __LINE__);
315 subunit_lfun (SRunner * sr, FILE * file, enum print_output printmode,
316 void *obj, enum cl_event evt)
322 /* assert(printmode == CK_SUBUNIT); */
335 if (printmode > CK_SILENT) {
336 fprintf (file, "\n");
337 srunner_fprint (file, sr, printmode);
345 subunit_test_start (name);
350 char *name = ck_strdup_printf ("%s:%s", tr->tcname, tr->tname);
351 char *msg = tr_short_str (tr);
354 subunit_test_pass (name);
357 subunit_test_fail (name, msg);
360 subunit_test_error (name, msg);
363 eprintf ("Bad result type in subunit_lfun", __FILE__, __LINE__);
370 eprintf ("Bad event type received in subunit_lfun", __FILE__, __LINE__);
376 srunner_open_lfile (SRunner * sr)
379 if (srunner_has_log (sr)) {
380 f = fopen (sr->log_fname, "w");
382 eprintf ("Error in call to fopen while opening log file %s:", __FILE__,
383 __LINE__ - 2, sr->log_fname);
389 srunner_open_xmlfile (SRunner * sr)
392 if (srunner_has_xml (sr)) {
393 f = fopen (sr->xml_fname, "w");
395 eprintf ("Error in call to fopen while opening xml file %s:", __FILE__,
396 __LINE__ - 2, sr->xml_fname);
402 srunner_init_logging (SRunner * sr, enum print_output print_mode)
405 sr->loglst = check_list_create ();
407 if (print_mode != CK_SUBUNIT)
409 srunner_register_lfun (sr, stdout, 0, stdout_lfun, print_mode);
412 srunner_register_lfun (sr, stdout, 0, subunit_lfun, print_mode);
414 f = srunner_open_lfile (sr);
416 srunner_register_lfun (sr, f, 1, lfile_lfun, print_mode);
418 f = srunner_open_xmlfile (sr);
420 srunner_register_lfun (sr, f, 2, xml_lfun, print_mode);
422 srunner_send_evt (sr, NULL, CLINITLOG_SR);
426 srunner_end_logging (SRunner * sr)
431 srunner_send_evt (sr, NULL, CLENDLOG_SR);
434 for (list_front (l); !list_at_end (l); list_advance (l)) {
435 Log *lg = list_val (l);
437 rval = fclose (lg->lfile);
439 eprintf ("Error in call to fclose while closing log file:", __FILE__,