gstreamer/libs/gst/check/libcheck/check_log.c
Nirbheek Chauhan 0bb6d590cc libcheck: port to latest check git
Upstream seems to have stopped doing releases, but we need to update for better
Windows and Visual Studio support.

This patch only updates the libcheck sources and ignores the compatibility
sources for now.

https://bugzilla.gnome.org/show_bug.cgi?id=775870
2016-12-09 15:31:01 +05:30

548 lines
12 KiB
C

/*
* 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., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "libcompat/libcompat.h"
#include <stdlib.h>
#include <stdio.h>
#include <internal-check.h>
#if ENABLE_SUBUNIT
#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"
/*
* If a log file is specified to be "-", then instead of
* opening a file the log output is printed to stdout.
*/
#define STDOUT_OVERRIDE_LOG_FILE_NAME "-"
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 srunner_log_fname (sr) != NULL;
}
const char *
srunner_log_fname (SRunner * sr)
{
/* check if log filename have been set explicitly */
if (sr->log_fname != NULL)
return sr->log_fname;
return getenv ("CK_LOG_FILE_NAME");
}
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 srunner_xml_fname (sr) != NULL;
}
const char *
srunner_xml_fname (SRunner * sr)
{
/* check if XML log filename have been set explicitly */
if (sr->xml_fname != NULL) {
return sr->xml_fname;
}
return getenv ("CK_XML_LOG_FILE_NAME");
}
void
srunner_set_tap (SRunner * sr, const char *fname)
{
if (sr->tap_fname)
return;
sr->tap_fname = fname;
}
int
srunner_has_tap (SRunner * sr)
{
return srunner_tap_fname (sr) != NULL;
}
const char *
srunner_tap_fname (SRunner * sr)
{
/* check if tap log filename have been set explicitly */
if (sr->tap_fname != NULL) {
return sr->tap_fname;
}
return getenv ("CK_TAP_LOG_FILE_NAME");
}
void
srunner_register_lfun (SRunner * sr, FILE * lfile, int close,
LFun lfun, enum print_output printmode)
{
Log *l = (Log *) emalloc (sizeof (Log));
if (printmode == CK_ENV) {
printmode = get_env_printmode ();
}
l->lfile = lfile;
l->lfun = lfun;
l->close = close;
l->mode = printmode;
check_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 (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
lg = (Log *) check_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;
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 = (Suite *) 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:
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 = (Suite *) 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:
break;
case CLSTART_T:
break;
case CLEND_T:
tr = (TestResult *) 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 timespec ts_start = { 0, 0 };
static char t[sizeof "yyyy-mm-dd hh:mm:ss"] = { 0 };
if (t[0] == 0) {
struct timeval inittv;
struct tm now;
gettimeofday (&inittv, NULL);
clock_gettime (check_get_clockid (), &ts_start);
if (localtime_r ((const time_t *) &(inittv.tv_sec), &now) != NULL) {
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,
"<?xml-stylesheet type=\"text/xsl\" href=\"http://check.sourceforge.net/xml/check_unittest.xslt\"?>\n");
fprintf (file,
"<testsuites xmlns=\"http://check.sourceforge.net/ns\">\n");
fprintf (file, " <datetime>%s</datetime>\n", t);
break;
case CLENDLOG_SR:
{
struct timespec ts_end = { 0, 0 };
unsigned long duration;
/* calculate time the test were running */
clock_gettime (check_get_clockid (), &ts_end);
duration = (unsigned long) DIFF_IN_USEC (ts_start, ts_end);
fprintf (file, " <duration>%lu.%06lu</duration>\n",
duration / US_PER_SEC, duration % US_PER_SEC);
fprintf (file, "</testsuites>\n");
}
break;
case CLSTART_SR:
break;
case CLSTART_S:
s = (Suite *) obj;
fprintf (file, " <suite>\n");
fprintf (file, " <title>");
fprint_xml_esc (file, s->name);
fprintf (file, "</title>\n");
break;
case CLEND_SR:
break;
case CLEND_S:
fprintf (file, " </suite>\n");
break;
case CLSTART_T:
break;
case CLEND_T:
tr = (TestResult *) obj;
tr_xmlprint (file, tr, CK_VERBOSE);
break;
default:
eprintf ("Bad event type received in xml_lfun", __FILE__, __LINE__);
}
}
void
tap_lfun (SRunner * sr CK_ATTRIBUTE_UNUSED, FILE * file,
enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj,
enum cl_event evt)
{
TestResult *tr;
static int num_tests_run = 0;
switch (evt) {
case CLINITLOG_SR:
/* As this is a new log file, reset the number of tests executed */
num_tests_run = 0;
break;
case CLENDLOG_SR:
/* Output the test plan as the last line */
fprintf (file, "1..%d\n", num_tests_run);
fflush (file);
break;
case CLSTART_SR:
break;
case CLSTART_S:
break;
case CLEND_SR:
break;
case CLEND_S:
break;
case CLSTART_T:
break;
case CLEND_T:
/* Print the test result to the tap file */
num_tests_run += 1;
tr = (TestResult *) obj;
fprintf (file, "%s %d - %s:%s:%s: %s\n",
tr->rtype == CK_PASS ? "ok" : "not ok", num_tests_run,
tr->file, tr->tcname, tr->tname, tr->msg);
fflush (file);
break;
default:
eprintf ("Bad event type received in tap_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;
char const *name;
/* assert(printmode == CK_SUBUNIT); */
switch (evt) {
case CLINITLOG_SR:
break;
case CLENDLOG_SR:
break;
case CLSTART_SR:
break;
case CLSTART_S:
break;
case CLEND_SR:
if (printmode > CK_SILENT) {
fprintf (file, "\n");
srunner_fprint (file, sr, printmode);
}
break;
case CLEND_S:
break;
case CLSTART_T:
name = (const char *) obj;
subunit_test_start (name);
break;
case CLEND_T:
tr = (TestResult *) 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;
case CK_TEST_RESULT_INVALID:
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
static FILE *
srunner_open_file (const char *filename)
{
FILE *f = NULL;
if (strcmp (filename, STDOUT_OVERRIDE_LOG_FILE_NAME) == 0) {
f = stdout;
} else {
f = fopen (filename, "w");
if (f == NULL) {
eprintf ("Error in call to fopen while opening file %s:", __FILE__,
__LINE__ - 2, filename);
}
}
return f;
}
FILE *
srunner_open_lfile (SRunner * sr)
{
FILE *f = NULL;
if (srunner_has_log (sr)) {
f = srunner_open_file (srunner_log_fname (sr));
}
return f;
}
FILE *
srunner_open_xmlfile (SRunner * sr)
{
FILE *f = NULL;
if (srunner_has_xml (sr)) {
f = srunner_open_file (srunner_xml_fname (sr));
}
return f;
}
FILE *
srunner_open_tapfile (SRunner * sr)
{
FILE *f = NULL;
if (srunner_has_tap (sr)) {
f = srunner_open_file (srunner_tap_fname (sr));
}
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, f != stdout, lfile_lfun, print_mode);
}
f = srunner_open_xmlfile (sr);
if (f) {
srunner_register_lfun (sr, f, f != stdout, xml_lfun, print_mode);
}
f = srunner_open_tapfile (sr);
if (f) {
srunner_register_lfun (sr, f, f != stdout, tap_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 (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
Log *lg = (Log *) check_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);
}
check_list_free (l);
sr->loglst = NULL;
}