diff options
author | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-08-15 17:04:08 +0100 |
---|---|---|
committer | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-08-15 17:04:08 +0100 |
commit | 35a870a7a23c7d6076c658c1ec2122b642f264ed (patch) | |
tree | b9ce5b562cf1a297844a7983c6b3fe33bb536d23 /src/check_log.c | |
download | check-35a870a7a23c7d6076c658c1ec2122b642f264ed.tar.gz |
Tarball conversion
Diffstat (limited to 'src/check_log.c')
-rw-r--r-- | src/check_log.c | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/src/check_log.c b/src/check_log.c new file mode 100644 index 0000000..6176675 --- /dev/null +++ b/src/check_log.c @@ -0,0 +1,403 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "../lib/libcompat.h" + +#include <stdlib.h> +#include <stdio.h> +#include <check.h> +#if HAVE_SUBUNIT_CHILD_H +#include <subunit/child.h> +#endif + +#include "check_error.h" +#include "check_list.h" +#include "check_impl.h" +#include "check_log.h" +#include "check_print.h" +#include "check_str.h" + + +static void srunner_send_evt (SRunner *sr, void *obj, enum cl_event evt); + +void srunner_set_log (SRunner *sr, const char *fname) +{ + if (sr->log_fname) + return; + sr->log_fname = fname; +} + +int srunner_has_log (SRunner *sr) +{ + return sr->log_fname != NULL; +} + +const char *srunner_log_fname (SRunner *sr) +{ + return sr->log_fname; +} + + +void srunner_set_xml (SRunner *sr, const char *fname) +{ + if (sr->xml_fname) + return; + sr->xml_fname = fname; +} + +int srunner_has_xml (SRunner *sr) +{ + return sr->xml_fname != NULL; +} + +const char *srunner_xml_fname (SRunner *sr) +{ + return sr->xml_fname; +} + +void srunner_register_lfun (SRunner *sr, FILE *lfile, int close, + LFun lfun, enum print_output printmode) +{ + Log *l = emalloc (sizeof(Log)); + + if (printmode == CK_ENV) { + printmode = get_env_printmode(); + } + + l->lfile = lfile; + l->lfun = lfun; + l->close = close; + l->mode = printmode; + list_add_end (sr->loglst, l); + return; +} + +void log_srunner_start (SRunner *sr) +{ + srunner_send_evt (sr, NULL, CLSTART_SR); +} + +void log_srunner_end (SRunner *sr) +{ + srunner_send_evt (sr, NULL, CLEND_SR); +} + +void log_suite_start (SRunner *sr, Suite *s) +{ + srunner_send_evt (sr, s, CLSTART_S); +} + +void log_suite_end (SRunner *sr, Suite *s) +{ + srunner_send_evt (sr, s, CLEND_S); +} + +void log_test_start (SRunner *sr, TCase * tc, TF * tfun) +{ + char buffer[100]; + snprintf(buffer, 99, "%s:%s", tc->name, tfun->name); + srunner_send_evt (sr, buffer, CLSTART_T); +} + +void log_test_end (SRunner *sr, TestResult *tr) +{ + srunner_send_evt (sr, tr, CLEND_T); +} + +static void srunner_send_evt (SRunner *sr, void *obj, enum cl_event evt) +{ + List *l; + Log *lg; + l = sr->loglst; + for (list_front(l); !list_at_end(l); list_advance(l)) { + lg = list_val(l); + fflush(lg->lfile); + lg->lfun (sr, lg->lfile, lg->mode, obj, evt); + fflush(lg->lfile); + } +} + +void stdout_lfun (SRunner *sr, FILE *file, enum print_output printmode, + void *obj, enum cl_event evt) +{ + Suite *s; + + if (printmode == CK_ENV) { + printmode = get_env_printmode(); + } + + switch (evt) { + case CLINITLOG_SR: + break; + case CLENDLOG_SR: + break; + case CLSTART_SR: + if (printmode > CK_SILENT) { + fprintf(file, "Running suite(s):"); + } + break; + case CLSTART_S: + s = obj; + if (printmode > CK_SILENT) { + fprintf(file, " %s\n", s->name); + } + break; + case CLEND_SR: + if (printmode > CK_SILENT) { + /* we don't want a newline before printing here, newlines should + come after printing a string, not before. it's better to add + the newline above in CLSTART_S. + */ + srunner_fprint (file, sr, printmode); + } + break; + case CLEND_S: + s = obj; + break; + case CLSTART_T: + break; + case CLEND_T: + break; + default: + eprintf("Bad event type received in stdout_lfun", __FILE__, __LINE__); + } + + +} + +void lfile_lfun (SRunner *sr, FILE *file, enum print_output printmode CK_ATTRIBUTE_UNUSED, + void *obj, enum cl_event evt) +{ + TestResult *tr; + Suite *s; + + switch (evt) { + case CLINITLOG_SR: + break; + case CLENDLOG_SR: + break; + case CLSTART_SR: + break; + case CLSTART_S: + s = obj; + fprintf(file, "Running suite %s\n", s->name); + break; + case CLEND_SR: + fprintf (file, "Results for all suites run:\n"); + srunner_fprint (file, sr, CK_MINIMAL); + break; + case CLEND_S: + s = obj; + break; + case CLSTART_T: + break; + case CLEND_T: + tr = obj; + tr_fprint(file, tr, CK_VERBOSE); + break; + default: + eprintf("Bad event type received in lfile_lfun", __FILE__, __LINE__); + } + + +} + +void xml_lfun (SRunner *sr CK_ATTRIBUTE_UNUSED, FILE *file, enum print_output printmode CK_ATTRIBUTE_UNUSED, + void *obj, enum cl_event evt) +{ + TestResult *tr; + Suite *s; + static struct timeval inittv, endtv; + static char t[sizeof "yyyy-mm-dd hh:mm:ss"] = {0}; + + if (t[0] == 0) + { + struct tm now; + gettimeofday(&inittv, NULL); + localtime_r(&(inittv.tv_sec), &now); + strftime(t, sizeof("yyyy-mm-dd hh:mm:ss"), "%Y-%m-%d %H:%M:%S", &now); + } + + switch (evt) { + case CLINITLOG_SR: + fprintf(file, "<?xml version=\"1.0\"?>\n"); + fprintf(file, "<testsuites xmlns=\"http://check.sourceforge.net/ns\">\n"); + fprintf(file, " <datetime>%s</datetime>\n", t); + break; + case CLENDLOG_SR: + gettimeofday(&endtv, NULL); + fprintf(file, " <duration>%f</duration>\n", + (endtv.tv_sec + (float)(endtv.tv_usec)/1000000) - \ + (inittv.tv_sec + (float)(inittv.tv_usec/1000000))); + fprintf(file, "</testsuites>\n"); + break; + case CLSTART_SR: + break; + case CLSTART_S: + s = obj; + fprintf(file, " <suite>\n"); + fprintf(file, " <title>%s</title>\n", s->name); + break; + case CLEND_SR: + break; + case CLEND_S: + fprintf(file, " </suite>\n"); + s = obj; + break; + case CLSTART_T: + break; + case CLEND_T: + tr = obj; + tr_xmlprint(file, tr, CK_VERBOSE); + break; + default: + eprintf("Bad event type received in xml_lfun", __FILE__, __LINE__); + } + +} + +#if ENABLE_SUBUNIT +void subunit_lfun (SRunner *sr, FILE *file, enum print_output printmode, + void *obj, enum cl_event evt) +{ + TestResult *tr; + Suite *s; + char const * name; + + /* assert(printmode == CK_SUBUNIT); */ + + switch (evt) { + case CLINITLOG_SR: + break; + case CLENDLOG_SR: + break; + case CLSTART_SR: + break; + case CLSTART_S: + s = obj; + break; + case CLEND_SR: + if (printmode > CK_SILENT) { + fprintf (file, "\n"); + srunner_fprint (file, sr, printmode); + } + break; + case CLEND_S: + s = obj; + break; + case CLSTART_T: + name = obj; + subunit_test_start(name); + break; + case CLEND_T: + tr = obj; + { + char *name = ck_strdup_printf ("%s:%s", tr->tcname, tr->tname); + char *msg = tr_short_str (tr); + switch (tr->rtype) { + case CK_PASS: + subunit_test_pass(name); + break; + case CK_FAILURE: + subunit_test_fail(name, msg); + break; + case CK_ERROR: + subunit_test_error(name, msg); + break; + default: + eprintf("Bad result type in subunit_lfun", __FILE__, __LINE__); + free(name); + free(msg); + } + } + break; + default: + eprintf("Bad event type received in subunit_lfun", __FILE__, __LINE__); + } +} +#endif + +FILE *srunner_open_lfile (SRunner *sr) +{ + FILE *f = NULL; + if (srunner_has_log (sr)) { + f = fopen(sr->log_fname, "w"); + if (f == NULL) + eprintf ("Error in call to fopen while opening log file %s:", __FILE__, __LINE__ - 2, + sr->log_fname); + } + return f; +} + +FILE *srunner_open_xmlfile (SRunner *sr) +{ + FILE *f = NULL; + if (srunner_has_xml (sr)) { + f = fopen(sr->xml_fname, "w"); + if (f == NULL) + eprintf ("Error in call to fopen while opening xml file %s:", __FILE__, __LINE__ - 2, + sr->xml_fname); + } + return f; +} + +void srunner_init_logging (SRunner *sr, enum print_output print_mode) +{ + FILE *f; + sr->loglst = check_list_create(); +#if ENABLE_SUBUNIT + if (print_mode != CK_SUBUNIT) +#endif + srunner_register_lfun (sr, stdout, 0, stdout_lfun, print_mode); +#if ENABLE_SUBUNIT + else + srunner_register_lfun (sr, stdout, 0, subunit_lfun, print_mode); +#endif + f = srunner_open_lfile (sr); + if (f) { + srunner_register_lfun (sr, f, 1, lfile_lfun, print_mode); + } + f = srunner_open_xmlfile (sr); + if (f) { + srunner_register_lfun (sr, f, 2, xml_lfun, print_mode); + } + srunner_send_evt (sr, NULL, CLINITLOG_SR); +} + +void srunner_end_logging (SRunner *sr) +{ + List *l; + int rval; + + srunner_send_evt (sr, NULL, CLENDLOG_SR); + + l = sr->loglst; + for (list_front(l); !list_at_end(l); list_advance(l)) { + Log *lg = list_val(l); + if (lg->close) { + rval = fclose (lg->lfile); + if (rval != 0) + eprintf ("Error in call to fclose while closing log file:", __FILE__, __LINE__ - 2); + } + free (lg); + } + list_free(l); + sr->loglst = NULL; +} |