mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 02:30:35 +00:00
0bb6d590cc
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
548 lines
12 KiB
C
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;
|
|
}
|