mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
check: Import version 0.9.14
This lifts the files almost verbatim (the changes being running though gst-indent and fixing the FSF address) from the upstream respository. Therefore this commit reverts some GStreamer-specific patches to check that will be reintroduced next. Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727826
This commit is contained in:
parent
f1c2cd60c3
commit
f1df7aba8f
27 changed files with 2571 additions and 805 deletions
8
libs/gst/check/libcheck/alarm.c
Normal file
8
libs/gst/check/libcheck/alarm.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include "libcompat.h"
|
||||
|
||||
unsigned int
|
||||
alarm (unsigned int seconds CK_ATTRIBUTE_UNUSED)
|
||||
{
|
||||
assert (0);
|
||||
return 0;
|
||||
}
|
|
@ -18,12 +18,13 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "../lib/libcompat.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "check.h"
|
||||
#include "check_error.h"
|
||||
|
@ -31,14 +32,18 @@
|
|||
#include "check_impl.h"
|
||||
#include "check_msg.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h> /* for _POSIX_VERSION */
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_TIMEOUT
|
||||
#define DEFAULT_TIMEOUT 4
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When a process exits either normally, with exit(), or
|
||||
* by an uncaught signal, The lower 0x377 bits are passed
|
||||
* to the parent. Of those, only the lower 8 bits are
|
||||
* returned by the WEXITSTATUS() macro.
|
||||
*/
|
||||
#define WEXITSTATUS_MASK 0xFF
|
||||
|
||||
int check_major_version = CHECK_MAJOR_VERSION;
|
||||
int check_minor_version = CHECK_MINOR_VERSION;
|
||||
int check_micro_version = CHECK_MICRO_VERSION;
|
||||
|
@ -55,7 +60,8 @@ Suite *
|
|||
suite_create (const char *name)
|
||||
{
|
||||
Suite *s;
|
||||
s = emalloc (sizeof (Suite)); /* freed in suite_free */
|
||||
|
||||
s = (Suite *) emalloc (sizeof (Suite)); /* freed in suite_free */
|
||||
if (name == NULL)
|
||||
s->name = "";
|
||||
else
|
||||
|
@ -64,17 +70,37 @@ suite_create (const char *name)
|
|||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
suite_tcase (Suite * s, const char *tcname)
|
||||
{
|
||||
List *l;
|
||||
TCase *tc;
|
||||
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
|
||||
l = s->tclst;
|
||||
for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
|
||||
tc = (TCase *) check_list_val (l);
|
||||
if (strcmp (tcname, tc->name) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
suite_free (Suite * s)
|
||||
{
|
||||
List *l;
|
||||
|
||||
if (s == NULL)
|
||||
return;
|
||||
l = s->tclst;
|
||||
for (list_front (l); !list_at_end (l); list_advance (l)) {
|
||||
tcase_free (list_val (l));
|
||||
for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
|
||||
tcase_free ((TCase *) check_list_val (l));
|
||||
}
|
||||
list_free (s->tclst);
|
||||
check_list_free (s->tclst);
|
||||
free (s);
|
||||
}
|
||||
|
||||
|
@ -82,8 +108,10 @@ TCase *
|
|||
tcase_create (const char *name)
|
||||
{
|
||||
char *env;
|
||||
int timeout = DEFAULT_TIMEOUT;
|
||||
TCase *tc = emalloc (sizeof (TCase)); /*freed in tcase_free */
|
||||
double timeout_sec = DEFAULT_TIMEOUT;
|
||||
|
||||
TCase *tc = (TCase *) emalloc (sizeof (TCase)); /*freed in tcase_free */
|
||||
|
||||
if (name == NULL)
|
||||
tc->name = "";
|
||||
else
|
||||
|
@ -91,21 +119,28 @@ tcase_create (const char *name)
|
|||
|
||||
env = getenv ("CK_DEFAULT_TIMEOUT");
|
||||
if (env != NULL) {
|
||||
int tmp = atoi (env);
|
||||
if (tmp >= 0) {
|
||||
timeout = tmp;
|
||||
char *endptr = NULL;
|
||||
double tmp = strtod (env, &endptr);
|
||||
|
||||
if (tmp >= 0 && endptr != env && (*endptr) == '\0') {
|
||||
timeout_sec = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
env = getenv ("CK_TIMEOUT_MULTIPLIER");
|
||||
if (env != NULL) {
|
||||
int tmp = atoi (env);
|
||||
if (tmp >= 0) {
|
||||
timeout = timeout * tmp;
|
||||
char *endptr = NULL;
|
||||
double tmp = strtod (env, &endptr);
|
||||
|
||||
if (tmp >= 0 && endptr != env && (*endptr) == '\0') {
|
||||
timeout_sec = timeout_sec * tmp;
|
||||
}
|
||||
}
|
||||
|
||||
tc->timeout = timeout;
|
||||
tc->timeout.tv_sec = (time_t) floor (timeout_sec);
|
||||
tc->timeout.tv_nsec =
|
||||
(long) ((timeout_sec - floor (timeout_sec)) * (double) NANOS_PER_SECONDS);
|
||||
|
||||
tc->tflst = check_list_create ();
|
||||
tc->unch_sflst = check_list_create ();
|
||||
tc->ch_sflst = check_list_create ();
|
||||
|
@ -119,16 +154,16 @@ tcase_create (const char *name)
|
|||
static void
|
||||
tcase_free (TCase * tc)
|
||||
{
|
||||
list_apply (tc->tflst, free);
|
||||
list_apply (tc->unch_sflst, free);
|
||||
list_apply (tc->ch_sflst, free);
|
||||
list_apply (tc->unch_tflst, free);
|
||||
list_apply (tc->ch_tflst, free);
|
||||
list_free (tc->tflst);
|
||||
list_free (tc->unch_sflst);
|
||||
list_free (tc->ch_sflst);
|
||||
list_free (tc->unch_tflst);
|
||||
list_free (tc->ch_tflst);
|
||||
check_list_apply (tc->tflst, free);
|
||||
check_list_apply (tc->unch_sflst, free);
|
||||
check_list_apply (tc->ch_sflst, free);
|
||||
check_list_apply (tc->unch_tflst, free);
|
||||
check_list_apply (tc->ch_tflst, free);
|
||||
check_list_free (tc->tflst);
|
||||
check_list_free (tc->unch_sflst);
|
||||
check_list_free (tc->ch_sflst);
|
||||
check_list_free (tc->unch_tflst);
|
||||
check_list_free (tc->ch_tflst);
|
||||
|
||||
free (tc);
|
||||
}
|
||||
|
@ -138,7 +173,7 @@ suite_add_tcase (Suite * s, TCase * tc)
|
|||
{
|
||||
if (s == NULL || tc == NULL)
|
||||
return;
|
||||
list_add_end (s->tclst, tc);
|
||||
check_list_add_end (s->tclst, tc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -146,23 +181,25 @@ _tcase_add_test (TCase * tc, TFun fn, const char *name, int _signal,
|
|||
int allowed_exit_value, int start, int end)
|
||||
{
|
||||
TF *tf;
|
||||
|
||||
if (tc == NULL || fn == NULL || name == NULL)
|
||||
return;
|
||||
tf = emalloc (sizeof (TF)); /* freed in tcase_free */
|
||||
tf = (TF *) emalloc (sizeof (TF)); /* freed in tcase_free */
|
||||
tf->fn = fn;
|
||||
tf->loop_start = start;
|
||||
tf->loop_end = end;
|
||||
tf->signal = _signal; /* 0 means no signal expected */
|
||||
tf->allowed_exit_value = allowed_exit_value; /* 0 is default successful exit */
|
||||
tf->allowed_exit_value = (WEXITSTATUS_MASK & allowed_exit_value); /* 0 is default successful exit */
|
||||
tf->name = name;
|
||||
list_add_end (tc->tflst, tf);
|
||||
check_list_add_end (tc->tflst, tf);
|
||||
}
|
||||
|
||||
static Fixture *
|
||||
fixture_create (SFun fun, int ischecked)
|
||||
{
|
||||
Fixture *f;
|
||||
f = emalloc (sizeof (Fixture));
|
||||
|
||||
f = (Fixture *) emalloc (sizeof (Fixture));
|
||||
f->fun = fun;
|
||||
f->ischecked = ischecked;
|
||||
|
||||
|
@ -186,33 +223,48 @@ tcase_add_fixture (TCase * tc, SFun setup, SFun teardown, int ischecked)
|
|||
{
|
||||
if (setup) {
|
||||
if (ischecked)
|
||||
list_add_end (tc->ch_sflst, fixture_create (setup, ischecked));
|
||||
check_list_add_end (tc->ch_sflst, fixture_create (setup, ischecked));
|
||||
else
|
||||
list_add_end (tc->unch_sflst, fixture_create (setup, ischecked));
|
||||
check_list_add_end (tc->unch_sflst, fixture_create (setup, ischecked));
|
||||
}
|
||||
|
||||
/* Add teardowns at front so they are run in reverse order. */
|
||||
if (teardown) {
|
||||
if (ischecked)
|
||||
list_add_front (tc->ch_tflst, fixture_create (teardown, ischecked));
|
||||
check_list_add_front (tc->ch_tflst, fixture_create (teardown, ischecked));
|
||||
else
|
||||
list_add_front (tc->unch_tflst, fixture_create (teardown, ischecked));
|
||||
check_list_add_front (tc->unch_tflst,
|
||||
fixture_create (teardown, ischecked));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tcase_set_timeout (TCase * tc, int timeout)
|
||||
tcase_set_timeout (TCase * tc, double timeout)
|
||||
{
|
||||
#if defined(HAVE_FORK)
|
||||
if (timeout >= 0) {
|
||||
char *env = getenv ("CK_TIMEOUT_MULTIPLIER");
|
||||
|
||||
if (env != NULL) {
|
||||
int tmp = atoi (env);
|
||||
if (tmp >= 0) {
|
||||
char *endptr = NULL;
|
||||
double tmp = strtod (env, &endptr);
|
||||
|
||||
if (tmp >= 0 && endptr != env && (*endptr) == '\0') {
|
||||
timeout = timeout * tmp;
|
||||
}
|
||||
}
|
||||
tc->timeout = timeout;
|
||||
|
||||
tc->timeout.tv_sec = (time_t) floor (timeout);
|
||||
tc->timeout.tv_nsec =
|
||||
(long) ((timeout - floor (timeout)) * (double) NANOS_PER_SECONDS);
|
||||
}
|
||||
#else
|
||||
(void) tc;
|
||||
(void) timeout;
|
||||
eprintf
|
||||
("This version does not support timeouts, as fork is not supported",
|
||||
__FILE__, __LINE__);
|
||||
#endif /* HAVE_FORK */
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -230,44 +282,57 @@ _mark_point (const char *file, int line)
|
|||
}
|
||||
|
||||
void
|
||||
_fail_unless (int result, const char *file, int line, const char *expr, ...)
|
||||
_ck_assert_failed (const char *file, int line, const char *expr, ...)
|
||||
{
|
||||
const char *msg;
|
||||
va_list ap;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
send_loc_info (file, line);
|
||||
if (!result) {
|
||||
va_list ap;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
va_start (ap, expr);
|
||||
msg = (const char *) va_arg (ap, char *);
|
||||
if (msg == NULL)
|
||||
msg = expr;
|
||||
vsnprintf (buf, BUFSIZ, msg, ap);
|
||||
va_end (ap);
|
||||
send_failure_info (buf);
|
||||
if (cur_fork_status () == CK_FORK) {
|
||||
#ifdef _POSIX_VERSION
|
||||
_exit (1);
|
||||
#endif /* _POSIX_VERSION */
|
||||
}
|
||||
va_start (ap, expr);
|
||||
msg = (const char *) va_arg (ap, char *);
|
||||
|
||||
if (msg == NULL)
|
||||
msg = expr;
|
||||
vsnprintf (buf, BUFSIZ, msg, ap);
|
||||
va_end (ap);
|
||||
send_failure_info (buf);
|
||||
if (cur_fork_status () == CK_FORK) {
|
||||
#if defined(HAVE_FORK) && HAVE_FORK==1
|
||||
_exit (1);
|
||||
#endif /* HAVE_FORK */
|
||||
} else {
|
||||
longjmp (error_jmp_buffer, 1);
|
||||
}
|
||||
}
|
||||
|
||||
SRunner *
|
||||
srunner_create (Suite * s)
|
||||
{
|
||||
SRunner *sr = emalloc (sizeof (SRunner)); /* freed in srunner_free */
|
||||
SRunner *sr = (SRunner *) emalloc (sizeof (SRunner)); /* freed in srunner_free */
|
||||
|
||||
sr->slst = check_list_create ();
|
||||
if (s != NULL)
|
||||
list_add_end (sr->slst, s);
|
||||
sr->stats = emalloc (sizeof (TestStats)); /* freed in srunner_free */
|
||||
check_list_add_end (sr->slst, s);
|
||||
sr->stats = (TestStats *) emalloc (sizeof (TestStats)); /* freed in srunner_free */
|
||||
sr->stats->n_checked = sr->stats->n_failed = sr->stats->n_errors = 0;
|
||||
sr->resultlst = check_list_create ();
|
||||
sr->log_fname = NULL;
|
||||
sr->xml_fname = NULL;
|
||||
sr->tap_fname = NULL;
|
||||
sr->loglst = NULL;
|
||||
|
||||
#if defined(HAVE_FORK)
|
||||
sr->fstat = CK_FORK_GETENV;
|
||||
#else
|
||||
/*
|
||||
* Overriding the default of running tests in fork mode,
|
||||
* as this system does not have fork()
|
||||
*/
|
||||
sr->fstat = CK_NOFORK;
|
||||
#endif /* HAVE_FORK */
|
||||
|
||||
return sr;
|
||||
}
|
||||
|
||||
|
@ -277,7 +342,7 @@ srunner_add_suite (SRunner * sr, Suite * s)
|
|||
if (s == NULL)
|
||||
return;
|
||||
|
||||
list_add_end (sr->slst, s);
|
||||
check_list_add_end (sr->slst, s);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -285,24 +350,23 @@ srunner_free (SRunner * sr)
|
|||
{
|
||||
List *l;
|
||||
TestResult *tr;
|
||||
|
||||
if (sr == NULL)
|
||||
return;
|
||||
|
||||
free (sr->stats);
|
||||
l = sr->slst;
|
||||
for (list_front (l); !list_at_end (l); list_advance (l)) {
|
||||
suite_free (list_val (l));
|
||||
for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
|
||||
suite_free ((Suite *) check_list_val (l));
|
||||
}
|
||||
list_free (sr->slst);
|
||||
check_list_free (sr->slst);
|
||||
|
||||
l = sr->resultlst;
|
||||
for (list_front (l); !list_at_end (l); list_advance (l)) {
|
||||
tr = list_val (l);
|
||||
free (tr->file);
|
||||
free (tr->msg);
|
||||
free (tr);
|
||||
for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) {
|
||||
tr = (TestResult *) check_list_val (l);
|
||||
tr_free (tr);
|
||||
}
|
||||
list_free (sr->resultlst);
|
||||
check_list_free (sr->resultlst);
|
||||
|
||||
free (sr);
|
||||
}
|
||||
|
@ -325,11 +389,16 @@ srunner_failures (SRunner * sr)
|
|||
int i = 0;
|
||||
TestResult **trarray;
|
||||
List *rlst;
|
||||
trarray = malloc (sizeof (trarray[0]) * srunner_ntests_failed (sr));
|
||||
|
||||
trarray =
|
||||
(TestResult **) emalloc (sizeof (trarray[0]) *
|
||||
srunner_ntests_failed (sr));
|
||||
|
||||
rlst = sr->resultlst;
|
||||
for (list_front (rlst); !list_at_end (rlst); list_advance (rlst)) {
|
||||
TestResult *tr = list_val (rlst);
|
||||
for (check_list_front (rlst); !check_list_at_end (rlst);
|
||||
check_list_advance (rlst)) {
|
||||
TestResult *tr = (TestResult *) check_list_val (rlst);
|
||||
|
||||
if (non_pass (tr->rtype))
|
||||
trarray[i++] = tr;
|
||||
|
||||
|
@ -344,11 +413,13 @@ srunner_results (SRunner * sr)
|
|||
TestResult **trarray;
|
||||
List *rlst;
|
||||
|
||||
trarray = malloc (sizeof (trarray[0]) * srunner_ntests_run (sr));
|
||||
trarray =
|
||||
(TestResult **) emalloc (sizeof (trarray[0]) * srunner_ntests_run (sr));
|
||||
|
||||
rlst = sr->resultlst;
|
||||
for (list_front (rlst); !list_at_end (rlst); list_advance (rlst)) {
|
||||
trarray[i++] = list_val (rlst);
|
||||
for (check_list_front (rlst); !check_list_at_end (rlst);
|
||||
check_list_advance (rlst)) {
|
||||
trarray[i++] = (TestResult *) check_list_val (rlst);
|
||||
}
|
||||
return trarray;
|
||||
}
|
||||
|
@ -364,17 +435,11 @@ tr_create (void)
|
|||
{
|
||||
TestResult *tr;
|
||||
|
||||
tr = emalloc (sizeof (TestResult));
|
||||
tr = (TestResult *) emalloc (sizeof (TestResult));
|
||||
tr_init (tr);
|
||||
return tr;
|
||||
}
|
||||
|
||||
void
|
||||
tr_reset (TestResult * tr)
|
||||
{
|
||||
tr_init (tr);
|
||||
}
|
||||
|
||||
static void
|
||||
tr_init (TestResult * tr)
|
||||
{
|
||||
|
@ -385,6 +450,15 @@ tr_init (TestResult * tr)
|
|||
tr->file = NULL;
|
||||
tr->tcname = NULL;
|
||||
tr->tname = NULL;
|
||||
tr->duration = -1;
|
||||
}
|
||||
|
||||
void
|
||||
tr_free (TestResult * tr)
|
||||
{
|
||||
free (tr->file);
|
||||
free (tr->msg);
|
||||
free (tr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -424,7 +498,7 @@ tr_tcname (TestResult * tr)
|
|||
return tr->tcname;
|
||||
}
|
||||
|
||||
static int _fstat = CK_FORK;
|
||||
static enum fork_status _fstat = CK_FORK;
|
||||
|
||||
void
|
||||
set_fork_status (enum fork_status fstat)
|
||||
|
@ -440,3 +514,41 @@ cur_fork_status (void)
|
|||
{
|
||||
return _fstat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not all systems support the same clockid_t's. This call checks
|
||||
* if the CLOCK_MONOTONIC clockid_t is valid. If so, that is returned,
|
||||
* otherwise, CLOCK_REALTIME is returned.
|
||||
*
|
||||
* The clockid_t that was found to work on the first call is
|
||||
* cached for subsequent calls.
|
||||
*/
|
||||
clockid_t
|
||||
check_get_clockid ()
|
||||
{
|
||||
static clockid_t clockid = -1;
|
||||
|
||||
if (clockid == -1) {
|
||||
/*
|
||||
* Only check if we have librt available. Otherwise, the clockid
|
||||
* will be ignored anyway, as the clock_gettime() and
|
||||
* timer_create() functions will be re-implemented in libcompat.
|
||||
* Worse, if librt and alarm() are unavailable, this check
|
||||
* will result in an assert(0).
|
||||
*/
|
||||
#ifdef HAVE_LIBRT
|
||||
timer_t timerid;
|
||||
|
||||
if (timer_create (CLOCK_MONOTONIC, NULL, &timerid) == 0) {
|
||||
timer_delete (timerid);
|
||||
clockid = CLOCK_MONOTONIC;
|
||||
} else {
|
||||
clockid = CLOCK_REALTIME;
|
||||
}
|
||||
#else
|
||||
clockid = CLOCK_MONOTONIC;
|
||||
#endif
|
||||
}
|
||||
|
||||
return clockid;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,22 +18,29 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "../lib/libcompat.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "check_error.h"
|
||||
|
||||
/**
|
||||
* Storage for setjmp/longjmp context information used in NOFORK mode
|
||||
*/
|
||||
jmp_buf error_jmp_buffer;
|
||||
|
||||
|
||||
/* FIXME: including a colon at the end is a bad way to indicate an error */
|
||||
void
|
||||
eprintf (const char *fmt, const char *file, int line, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
fflush (stderr);
|
||||
|
||||
fprintf (stderr, "%s:%d: ", file, line);
|
||||
|
@ -53,6 +60,7 @@ void *
|
|||
emalloc (size_t n)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = malloc (n);
|
||||
if (p == NULL)
|
||||
eprintf ("malloc of %u bytes failed:", __FILE__, __LINE__ - 2, n);
|
||||
|
@ -63,6 +71,7 @@ void *
|
|||
erealloc (void *ptr, size_t n)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = realloc (ptr, n);
|
||||
if (p == NULL)
|
||||
eprintf ("realloc of %u bytes failed:", __FILE__, __LINE__ - 2, n);
|
||||
|
|
|
@ -21,13 +21,20 @@
|
|||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
|
||||
#include "../lib/libcompat.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
extern jmp_buf error_jmp_buffer;
|
||||
|
||||
/* Include stdlib.h beforehand */
|
||||
|
||||
/* Print error message and die
|
||||
If fmt ends in colon, include system error information */
|
||||
void eprintf (const char *fmt, const char *file, int line,...);
|
||||
void
|
||||
eprintf (const char *fmt, const char *file, int line, ...)
|
||||
CK_ATTRIBUTE_NORETURN;
|
||||
/* malloc or die */
|
||||
void *emalloc(size_t n);
|
||||
void *erealloc(void *, size_t n);
|
||||
void *emalloc (size_t n);
|
||||
void *erealloc (void *, size_t n);
|
||||
|
||||
#endif /*ERROR_H*/
|
||||
#endif /*ERROR_H */
|
||||
|
|
|
@ -21,24 +21,33 @@
|
|||
#ifndef CHECK_IMPL_H
|
||||
#define CHECK_IMPL_H
|
||||
|
||||
|
||||
/* This header should be included by any module that needs
|
||||
to know the implementation details of the check structures
|
||||
Include stdio.h & list.h before this header
|
||||
Include stdio.h, time.h, & list.h before this header
|
||||
*/
|
||||
|
||||
typedef struct TF {
|
||||
#define US_PER_SEC 1000000
|
||||
#define NANOS_PER_SECONDS 1000000000
|
||||
|
||||
/** calculate the difference in useconds out of two "struct timespec"s */
|
||||
#define DIFF_IN_USEC(begin, end) \
|
||||
( (((end).tv_sec - (begin).tv_sec) * US_PER_SEC) + \
|
||||
((end).tv_nsec/1000) - ((begin).tv_nsec/1000) )
|
||||
|
||||
typedef struct TF
|
||||
{
|
||||
TFun fn;
|
||||
int loop_start;
|
||||
int loop_end;
|
||||
const char *name;
|
||||
int signal;
|
||||
unsigned char allowed_exit_value;
|
||||
signed char allowed_exit_value;
|
||||
} TF;
|
||||
|
||||
struct Suite {
|
||||
struct Suite
|
||||
{
|
||||
const char *name;
|
||||
List *tclst; /* List of test cases */
|
||||
List *tclst; /* List of test cases */
|
||||
};
|
||||
|
||||
typedef struct Fixture
|
||||
|
@ -47,71 +56,82 @@ typedef struct Fixture
|
|||
SFun fun;
|
||||
} Fixture;
|
||||
|
||||
struct TCase {
|
||||
struct TCase
|
||||
{
|
||||
const char *name;
|
||||
int timeout;
|
||||
List *tflst; /* list of test functions */
|
||||
struct timespec timeout;
|
||||
List *tflst; /* list of test functions */
|
||||
List *unch_sflst;
|
||||
List *unch_tflst;
|
||||
List *ch_sflst;
|
||||
List *ch_tflst;
|
||||
};
|
||||
|
||||
typedef struct TestStats {
|
||||
typedef struct TestStats
|
||||
{
|
||||
int n_checked;
|
||||
int n_failed;
|
||||
int n_errors;
|
||||
} TestStats;
|
||||
|
||||
struct TestResult {
|
||||
enum test_result rtype; /* Type of result */
|
||||
enum ck_result_ctx ctx; /* When the result occurred */
|
||||
char *file; /* File where the test occured */
|
||||
int line; /* Line number where the test occurred */
|
||||
int iter; /* The iteration value for looping tests */
|
||||
const char *tcname; /* Test case that generated the result */
|
||||
const char *tname; /* Test that generated the result */
|
||||
char *msg; /* Failure message */
|
||||
struct TestResult
|
||||
{
|
||||
enum test_result rtype; /* Type of result */
|
||||
enum ck_result_ctx ctx; /* When the result occurred */
|
||||
char *file; /* File where the test occured */
|
||||
int line; /* Line number where the test occurred */
|
||||
int iter; /* The iteration value for looping tests */
|
||||
int duration; /* duration of this test in microseconds */
|
||||
const char *tcname; /* Test case that generated the result */
|
||||
const char *tname; /* Test that generated the result */
|
||||
char *msg; /* Failure message */
|
||||
};
|
||||
|
||||
TestResult *tr_create(void);
|
||||
void tr_reset(TestResult *tr);
|
||||
TestResult *tr_create (void);
|
||||
void tr_reset (TestResult * tr);
|
||||
void tr_free (TestResult * tr);
|
||||
|
||||
enum cl_event {
|
||||
CLINITLOG_SR,
|
||||
CLENDLOG_SR,
|
||||
CLSTART_SR,
|
||||
CLSTART_S,
|
||||
CLEND_SR,
|
||||
CLEND_S,
|
||||
CLSTART_T, /* A test case is about to run */
|
||||
CLEND_T
|
||||
enum cl_event
|
||||
{
|
||||
CLINITLOG_SR, /* Initialize log file */
|
||||
CLENDLOG_SR, /* Tests are complete */
|
||||
CLSTART_SR, /* Suite runner start */
|
||||
CLSTART_S, /* Suite start */
|
||||
CLEND_SR, /* Suite runner end */
|
||||
CLEND_S, /* Suite end */
|
||||
CLSTART_T, /* A test case is about to run */
|
||||
CLEND_T /* Test case end */
|
||||
};
|
||||
|
||||
typedef void (*LFun) (SRunner *, FILE*, enum print_output,
|
||||
void *, enum cl_event);
|
||||
typedef void (*LFun) (SRunner *, FILE *, enum print_output,
|
||||
void *, enum cl_event);
|
||||
|
||||
typedef struct Log {
|
||||
typedef struct Log
|
||||
{
|
||||
FILE *lfile;
|
||||
LFun lfun;
|
||||
int close;
|
||||
enum print_output mode;
|
||||
} Log;
|
||||
|
||||
struct SRunner {
|
||||
List *slst; /* List of Suite objects */
|
||||
TestStats *stats; /* Run statistics */
|
||||
List *resultlst; /* List of unit test results */
|
||||
const char *log_fname; /* name of log file */
|
||||
const char *xml_fname; /* name of xml output file */
|
||||
List *loglst; /* list of Log objects */
|
||||
enum fork_status fstat; /* controls if suites are forked or not
|
||||
NOTE: Don't use this value directly,
|
||||
instead use srunner_fork_status */
|
||||
struct SRunner
|
||||
{
|
||||
List *slst; /* List of Suite objects */
|
||||
TestStats *stats; /* Run statistics */
|
||||
List *resultlst; /* List of unit test results */
|
||||
const char *log_fname; /* name of log file */
|
||||
const char *xml_fname; /* name of xml output file */
|
||||
const char *tap_fname; /* name of tap output file */
|
||||
List *loglst; /* list of Log objects */
|
||||
enum fork_status fstat; /* controls if suites are forked or not
|
||||
NOTE: Don't use this value directly,
|
||||
instead use srunner_fork_status */
|
||||
};
|
||||
|
||||
|
||||
void set_fork_status(enum fork_status fstat);
|
||||
void set_fork_status (enum fork_status fstat);
|
||||
enum fork_status cur_fork_status (void);
|
||||
|
||||
clockid_t check_get_clockid (void);
|
||||
|
||||
#endif /* CHECK_IMPL_H */
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "../lib/libcompat.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -35,11 +35,11 @@ enum
|
|||
|
||||
struct List
|
||||
{
|
||||
int n_elts;
|
||||
int max_elts;
|
||||
unsigned int n_elts;
|
||||
unsigned int max_elts;
|
||||
int current; /* pointer to the current node */
|
||||
int last; /* pointer to the node before END */
|
||||
const void **data;
|
||||
void **data;
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -47,7 +47,8 @@ maybe_grow (List * lp)
|
|||
{
|
||||
if (lp->n_elts >= lp->max_elts) {
|
||||
lp->max_elts *= LGROW;
|
||||
lp->data = erealloc (lp->data, lp->max_elts * sizeof (lp->data[0]));
|
||||
lp->data =
|
||||
(void **) erealloc (lp->data, lp->max_elts * sizeof (lp->data[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,16 +56,17 @@ List *
|
|||
check_list_create (void)
|
||||
{
|
||||
List *lp;
|
||||
lp = emalloc (sizeof (List));
|
||||
|
||||
lp = (List *) emalloc (sizeof (List));
|
||||
lp->n_elts = 0;
|
||||
lp->max_elts = LINIT;
|
||||
lp->data = emalloc (sizeof (lp->data[0]) * LINIT);
|
||||
lp->data = (void **) emalloc (sizeof (lp->data[0]) * LINIT);
|
||||
lp->current = lp->last = -1;
|
||||
return lp;
|
||||
}
|
||||
|
||||
void
|
||||
list_add_front (List * lp, const void *val)
|
||||
check_list_add_front (List * lp, void *val)
|
||||
{
|
||||
if (lp == NULL)
|
||||
return;
|
||||
|
@ -77,7 +79,7 @@ list_add_front (List * lp, const void *val)
|
|||
}
|
||||
|
||||
void
|
||||
list_add_end (List * lp, const void *val)
|
||||
check_list_add_end (List * lp, void *val)
|
||||
{
|
||||
if (lp == NULL)
|
||||
return;
|
||||
|
@ -89,7 +91,7 @@ list_add_end (List * lp, const void *val)
|
|||
}
|
||||
|
||||
int
|
||||
list_at_end (List * lp)
|
||||
check_list_at_end (List * lp)
|
||||
{
|
||||
if (lp->current == -1)
|
||||
return 1;
|
||||
|
@ -98,7 +100,7 @@ list_at_end (List * lp)
|
|||
}
|
||||
|
||||
void
|
||||
list_front (List * lp)
|
||||
check_list_front (List * lp)
|
||||
{
|
||||
if (lp->current == -1)
|
||||
return;
|
||||
|
@ -107,7 +109,7 @@ list_front (List * lp)
|
|||
|
||||
|
||||
void
|
||||
list_free (List * lp)
|
||||
check_list_free (List * lp)
|
||||
{
|
||||
if (lp == NULL)
|
||||
return;
|
||||
|
@ -117,34 +119,34 @@ list_free (List * lp)
|
|||
}
|
||||
|
||||
void *
|
||||
list_val (List * lp)
|
||||
check_list_val (List * lp)
|
||||
{
|
||||
if (lp == NULL)
|
||||
return NULL;
|
||||
if (lp->current == -1 || lp->current > lp->last)
|
||||
return NULL;
|
||||
|
||||
return (void *) lp->data[lp->current];
|
||||
return lp->data[lp->current];
|
||||
}
|
||||
|
||||
void
|
||||
list_advance (List * lp)
|
||||
check_list_advance (List * lp)
|
||||
{
|
||||
if (lp == NULL)
|
||||
return;
|
||||
if (list_at_end (lp))
|
||||
if (check_list_at_end (lp))
|
||||
return;
|
||||
lp->current++;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
list_apply (List * lp, void (*fp) (void *))
|
||||
check_list_apply (List * lp, void (*fp) (void *))
|
||||
{
|
||||
if (lp == NULL || fp == NULL)
|
||||
return;
|
||||
|
||||
for (list_front (lp); !list_at_end (lp); list_advance (lp))
|
||||
fp (list_val (lp));
|
||||
for (check_list_front (lp); !check_list_at_end (lp); check_list_advance (lp))
|
||||
fp (check_list_val (lp));
|
||||
|
||||
}
|
||||
|
|
|
@ -24,33 +24,33 @@
|
|||
typedef struct List List;
|
||||
|
||||
/* Create an empty list */
|
||||
List * check_list_create (void);
|
||||
List *check_list_create (void);
|
||||
|
||||
/* Is list at end? */
|
||||
int list_at_end (List * lp);
|
||||
int check_list_at_end (List * lp);
|
||||
|
||||
/* Position list at front */
|
||||
void list_front(List *lp);
|
||||
void check_list_front (List * lp);
|
||||
|
||||
/* Add a value to the front of the list,
|
||||
positioning newly added value as current value.
|
||||
More expensive than list_add_end, as it uses memmove. */
|
||||
void list_add_front (List *lp, const void *val);
|
||||
void check_list_add_front (List * lp, void *val);
|
||||
|
||||
/* Add a value to the end of the list,
|
||||
positioning newly added value as current value */
|
||||
void list_add_end (List *lp, const void *val);
|
||||
void check_list_add_end (List * lp, void *val);
|
||||
|
||||
/* Give the value of the current node */
|
||||
void *list_val (List * lp);
|
||||
void *check_list_val (List * lp);
|
||||
|
||||
/* Position the list at the next node */
|
||||
void list_advance (List * lp);
|
||||
void check_list_advance (List * lp);
|
||||
|
||||
/* Free a list, but don't free values */
|
||||
void list_free (List * lp);
|
||||
void check_list_free (List * lp);
|
||||
|
||||
void list_apply (List *lp, void (*fp) (void *));
|
||||
void check_list_apply (List * lp, void (*fp) (void *));
|
||||
|
||||
|
||||
#endif /* CHECK_LIST_H */
|
||||
|
|
|
@ -18,16 +18,12 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "../lib/libcompat.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <check.h>
|
||||
#if HAVE_SUBUNIT_CHILD_H
|
||||
#if ENABLE_SUBUNIT
|
||||
#include <subunit/child.h>
|
||||
#endif
|
||||
|
||||
|
@ -38,20 +34,11 @@
|
|||
#include "check_print.h"
|
||||
#include "check_str.h"
|
||||
|
||||
/* localtime_r is apparently not available on Windows */
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
static struct tm *
|
||||
localtime_r (const time_t * clock, struct tm *result)
|
||||
{
|
||||
struct tm *now = localtime (clock);
|
||||
if (now == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
*result = *now;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif /* HAVE_DECL_LOCALTIME_R */
|
||||
/*
|
||||
* 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);
|
||||
|
||||
|
@ -66,13 +53,17 @@ srunner_set_log (SRunner * sr, const char *fname)
|
|||
int
|
||||
srunner_has_log (SRunner * sr)
|
||||
{
|
||||
return sr->log_fname != NULL;
|
||||
return srunner_log_fname (sr) != NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
srunner_log_fname (SRunner * sr)
|
||||
{
|
||||
return sr->log_fname;
|
||||
/* check if log filename have been set explicitly */
|
||||
if (sr->log_fname != NULL)
|
||||
return sr->log_fname;
|
||||
|
||||
return getenv ("CK_LOG_FILE_NAME");
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,20 +78,50 @@ srunner_set_xml (SRunner * sr, const char *fname)
|
|||
int
|
||||
srunner_has_xml (SRunner * sr)
|
||||
{
|
||||
return sr->xml_fname != NULL;
|
||||
return srunner_xml_fname (sr) != NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
srunner_xml_fname (SRunner * sr)
|
||||
{
|
||||
return sr->xml_fname;
|
||||
/* 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 = emalloc (sizeof (Log));
|
||||
Log *l = (Log *) emalloc (sizeof (Log));
|
||||
|
||||
if (printmode == CK_ENV) {
|
||||
printmode = get_env_printmode ();
|
||||
|
@ -110,7 +131,7 @@ srunner_register_lfun (SRunner * sr, FILE * lfile, int close,
|
|||
l->lfun = lfun;
|
||||
l->close = close;
|
||||
l->mode = printmode;
|
||||
list_add_end (sr->loglst, l);
|
||||
check_list_add_end (sr->loglst, l);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -142,6 +163,7 @@ 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);
|
||||
}
|
||||
|
@ -157,9 +179,10 @@ 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);
|
||||
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);
|
||||
|
@ -172,10 +195,6 @@ stdout_lfun (SRunner * sr, FILE * file, enum print_output printmode,
|
|||
{
|
||||
Suite *s;
|
||||
|
||||
if (printmode == CK_ENV) {
|
||||
printmode = get_env_printmode ();
|
||||
}
|
||||
|
||||
switch (evt) {
|
||||
case CLINITLOG_SR:
|
||||
break;
|
||||
|
@ -187,7 +206,7 @@ stdout_lfun (SRunner * sr, FILE * file, enum print_output printmode,
|
|||
}
|
||||
break;
|
||||
case CLSTART_S:
|
||||
s = obj;
|
||||
s = (Suite *) obj;
|
||||
if (printmode > CK_SILENT) {
|
||||
fprintf (file, " %s\n", s->name);
|
||||
}
|
||||
|
@ -202,7 +221,6 @@ stdout_lfun (SRunner * sr, FILE * file, enum print_output printmode,
|
|||
}
|
||||
break;
|
||||
case CLEND_S:
|
||||
s = obj;
|
||||
break;
|
||||
case CLSTART_T:
|
||||
break;
|
||||
|
@ -231,7 +249,7 @@ lfile_lfun (SRunner * sr, FILE * file,
|
|||
case CLSTART_SR:
|
||||
break;
|
||||
case CLSTART_S:
|
||||
s = obj;
|
||||
s = (Suite *) obj;
|
||||
fprintf (file, "Running suite %s\n", s->name);
|
||||
break;
|
||||
case CLEND_SR:
|
||||
|
@ -239,12 +257,11 @@ lfile_lfun (SRunner * sr, FILE * file,
|
|||
srunner_fprint (file, sr, CK_MINIMAL);
|
||||
break;
|
||||
case CLEND_S:
|
||||
s = obj;
|
||||
break;
|
||||
case CLSTART_T:
|
||||
break;
|
||||
case CLEND_T:
|
||||
tr = obj;
|
||||
tr = (TestResult *) obj;
|
||||
tr_fprint (file, tr, CK_VERBOSE);
|
||||
break;
|
||||
default:
|
||||
|
@ -261,47 +278,60 @@ xml_lfun (SRunner * sr CK_ATTRIBUTE_UNUSED, FILE * file,
|
|||
{
|
||||
TestResult *tr;
|
||||
Suite *s;
|
||||
static struct timeval inittv, endtv;
|
||||
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);
|
||||
localtime_r (&(inittv.tv_sec), &now);
|
||||
strftime (t, sizeof ("yyyy-mm-dd hh:mm:ss"), "%Y-%m-%d %H:%M:%S", &now);
|
||||
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:
|
||||
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)));
|
||||
{
|
||||
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 = obj;
|
||||
s = (Suite *) obj;
|
||||
fprintf (file, " <suite>\n");
|
||||
fprintf (file, " <title>%s</title>\n", s->name);
|
||||
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");
|
||||
s = obj;
|
||||
break;
|
||||
case CLSTART_T:
|
||||
break;
|
||||
case CLEND_T:
|
||||
tr = obj;
|
||||
tr = (TestResult *) obj;
|
||||
tr_xmlprint (file, tr, CK_VERBOSE);
|
||||
break;
|
||||
default:
|
||||
|
@ -310,13 +340,55 @@ xml_lfun (SRunner * sr CK_ATTRIBUTE_UNUSED, FILE * file,
|
|||
|
||||
}
|
||||
|
||||
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;
|
||||
Suite *s;
|
||||
char const *name;
|
||||
|
||||
/* assert(printmode == CK_SUBUNIT); */
|
||||
|
@ -329,7 +401,6 @@ subunit_lfun (SRunner * sr, FILE * file, enum print_output printmode,
|
|||
case CLSTART_SR:
|
||||
break;
|
||||
case CLSTART_S:
|
||||
s = obj;
|
||||
break;
|
||||
case CLEND_SR:
|
||||
if (printmode > CK_SILENT) {
|
||||
|
@ -338,17 +409,17 @@ subunit_lfun (SRunner * sr, FILE * file, enum print_output printmode,
|
|||
}
|
||||
break;
|
||||
case CLEND_S:
|
||||
s = obj;
|
||||
break;
|
||||
case CLSTART_T:
|
||||
name = obj;
|
||||
name = (const char *) obj;
|
||||
subunit_test_start (name);
|
||||
break;
|
||||
case CLEND_T:
|
||||
tr = obj;
|
||||
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);
|
||||
|
@ -359,6 +430,7 @@ subunit_lfun (SRunner * sr, FILE * file, enum print_output printmode,
|
|||
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);
|
||||
|
@ -372,15 +444,30 @@ subunit_lfun (SRunner * sr, FILE * file, enum print_output printmode,
|
|||
}
|
||||
#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 = 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);
|
||||
f = srunner_open_file (srunner_log_fname (sr));
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
@ -389,11 +476,20 @@ 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);
|
||||
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;
|
||||
}
|
||||
|
@ -402,6 +498,7 @@ 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)
|
||||
|
@ -413,11 +510,15 @@ srunner_init_logging (SRunner * sr, enum print_output print_mode)
|
|||
#endif
|
||||
f = srunner_open_lfile (sr);
|
||||
if (f) {
|
||||
srunner_register_lfun (sr, f, 1, lfile_lfun, print_mode);
|
||||
srunner_register_lfun (sr, f, f != stdout, lfile_lfun, print_mode);
|
||||
}
|
||||
f = srunner_open_xmlfile (sr);
|
||||
if (f) {
|
||||
srunner_register_lfun (sr, f, 2, xml_lfun, print_mode);
|
||||
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);
|
||||
}
|
||||
|
@ -431,16 +532,17 @@ srunner_end_logging (SRunner * sr)
|
|||
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);
|
||||
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);
|
||||
eprintf ("Error in call to fclose while closing log file:",
|
||||
__FILE__, __LINE__ - 2);
|
||||
}
|
||||
free (lg);
|
||||
}
|
||||
list_free (l);
|
||||
check_list_free (l);
|
||||
sr->loglst = NULL;
|
||||
}
|
||||
|
|
|
@ -21,31 +21,35 @@
|
|||
#ifndef CHECK_LOG_H
|
||||
#define CHECK_LOG_H
|
||||
|
||||
void log_srunner_start (SRunner *sr);
|
||||
void log_srunner_end (SRunner *sr);
|
||||
void log_suite_start (SRunner *sr, Suite *s);
|
||||
void log_suite_end (SRunner *sr, Suite *s);
|
||||
void log_test_end (SRunner *sr, TestResult *tr);
|
||||
void log_test_start (SRunner *sr, TCase *tc, TF *tfun);
|
||||
void log_srunner_start (SRunner * sr);
|
||||
void log_srunner_end (SRunner * sr);
|
||||
void log_suite_start (SRunner * sr, Suite * s);
|
||||
void log_suite_end (SRunner * sr, Suite * s);
|
||||
void log_test_end (SRunner * sr, TestResult * tr);
|
||||
void log_test_start (SRunner * sr, TCase * tc, TF * tfun);
|
||||
|
||||
void stdout_lfun (SRunner *sr, FILE *file, enum print_output,
|
||||
void *obj, enum cl_event evt);
|
||||
void stdout_lfun (SRunner * sr, FILE * file, enum print_output,
|
||||
void *obj, enum cl_event evt);
|
||||
|
||||
void lfile_lfun (SRunner *sr, FILE *file, enum print_output,
|
||||
void *obj, enum cl_event evt);
|
||||
void lfile_lfun (SRunner * sr, FILE * file, enum print_output,
|
||||
void *obj, enum cl_event evt);
|
||||
|
||||
void xml_lfun (SRunner *sr, FILE *file, enum print_output,
|
||||
void *obj, enum cl_event evt);
|
||||
void xml_lfun (SRunner * sr, FILE * file, enum print_output,
|
||||
void *obj, enum cl_event evt);
|
||||
|
||||
void subunit_lfun (SRunner *sr, FILE *file, enum print_output,
|
||||
void *obj, enum cl_event evt);
|
||||
void tap_lfun (SRunner * sr, FILE * file, enum print_output,
|
||||
void *obj, enum cl_event evt);
|
||||
|
||||
void srunner_register_lfun (SRunner *sr, FILE *lfile, int close,
|
||||
LFun lfun, enum print_output);
|
||||
void subunit_lfun (SRunner * sr, FILE * file, enum print_output,
|
||||
void *obj, enum cl_event evt);
|
||||
|
||||
FILE *srunner_open_lfile (SRunner *sr);
|
||||
FILE *srunner_open_xmlfile (SRunner *sr);
|
||||
void srunner_init_logging (SRunner *sr, enum print_output print_mode);
|
||||
void srunner_end_logging (SRunner *sr);
|
||||
void srunner_register_lfun (SRunner * sr, FILE * lfile, int close,
|
||||
LFun lfun, enum print_output);
|
||||
|
||||
FILE *srunner_open_lfile (SRunner * sr);
|
||||
FILE *srunner_open_xmlfile (SRunner * sr);
|
||||
FILE *srunner_open_tapfile (SRunner * sr);
|
||||
void srunner_init_logging (SRunner * sr, enum print_output print_mode);
|
||||
void srunner_end_logging (SRunner * sr);
|
||||
|
||||
#endif /* CHECK_LOG_H */
|
||||
|
|
|
@ -18,12 +18,9 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "../lib/libcompat.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
@ -34,6 +31,7 @@
|
|||
#include "check_impl.h"
|
||||
#include "check_msg.h"
|
||||
#include "check_pack.h"
|
||||
#include "check_str.h"
|
||||
|
||||
|
||||
/* 'Pipe' is implemented as a temporary file to overcome message
|
||||
|
@ -57,7 +55,9 @@
|
|||
*/
|
||||
|
||||
static FILE *send_file1;
|
||||
static char *send_file1_name;
|
||||
static FILE *send_file2;
|
||||
static char *send_file2_name;
|
||||
|
||||
static FILE *get_pipe (void);
|
||||
static void setup_pipe (void);
|
||||
|
@ -86,8 +86,18 @@ send_failure_info (const char *msg)
|
|||
{
|
||||
FailMsg fmsg;
|
||||
|
||||
fmsg.msg = (char *) msg;
|
||||
ppack (fileno (get_pipe ()), CK_MSG_FAIL, (CheckMsg *) & fmsg);
|
||||
fmsg.msg = strdup (msg);
|
||||
ppack (get_pipe (), CK_MSG_FAIL, (CheckMsg *) & fmsg);
|
||||
free (fmsg.msg);
|
||||
}
|
||||
|
||||
void
|
||||
send_duration_info (int duration)
|
||||
{
|
||||
DurationMsg dmsg;
|
||||
|
||||
dmsg.duration = duration;
|
||||
ppack (get_pipe (), CK_MSG_DURATION, (CheckMsg *) & dmsg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -95,9 +105,10 @@ send_loc_info (const char *file, int line)
|
|||
{
|
||||
LocMsg lmsg;
|
||||
|
||||
lmsg.file = (char *) file;
|
||||
lmsg.file = strdup (file);
|
||||
lmsg.line = line;
|
||||
ppack (fileno (get_pipe ()), CK_MSG_LOC, (CheckMsg *) & lmsg);
|
||||
ppack (get_pipe (), CK_MSG_LOC, (CheckMsg *) & lmsg);
|
||||
free (lmsg.file);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -106,7 +117,7 @@ send_ctx_info (enum ck_result_ctx ctx)
|
|||
CtxMsg cmsg;
|
||||
|
||||
cmsg.ctx = ctx;
|
||||
ppack (fileno (get_pipe ()), CK_MSG_CTX, (CheckMsg *) & cmsg);
|
||||
ppack (get_pipe (), CK_MSG_CTX, (CheckMsg *) & cmsg);
|
||||
}
|
||||
|
||||
TestResult *
|
||||
|
@ -117,10 +128,17 @@ receive_test_result (int waserror)
|
|||
TestResult *result;
|
||||
|
||||
fp = get_pipe ();
|
||||
if (fp == NULL)
|
||||
if (fp == NULL) {
|
||||
eprintf ("Error in call to get_pipe", __FILE__, __LINE__ - 2);
|
||||
}
|
||||
|
||||
rewind (fp);
|
||||
rmsg = punpack (fileno (fp));
|
||||
rmsg = punpack (fp);
|
||||
|
||||
if (rmsg == NULL) {
|
||||
eprintf ("Error in call to punpack", __FILE__, __LINE__ - 4);
|
||||
}
|
||||
|
||||
teardown_pipe ();
|
||||
setup_pipe ();
|
||||
|
||||
|
@ -156,7 +174,7 @@ construct_test_result (RcvMsg * rmsg, int waserror)
|
|||
tr = tr_create ();
|
||||
|
||||
if (rmsg->msg != NULL || waserror) {
|
||||
tr->ctx = (cur_fork_status () == CK_FORK) ? rmsg->lastctx : rmsg->failctx;
|
||||
tr->ctx = rmsg->lastctx;
|
||||
tr->msg = rmsg->msg;
|
||||
rmsg->msg = NULL;
|
||||
tr_set_loc_by_ctx (tr, tr->ctx, rmsg);
|
||||
|
@ -167,6 +185,7 @@ construct_test_result (RcvMsg * rmsg, int waserror)
|
|||
} else {
|
||||
tr->ctx = CK_CTX_TEST;
|
||||
tr->msg = NULL;
|
||||
tr->duration = rmsg->duration;
|
||||
tr_set_loc_by_ctx (tr, CK_CTX_TEST, rmsg);
|
||||
}
|
||||
|
||||
|
@ -185,16 +204,67 @@ teardown_messaging (void)
|
|||
teardown_pipe ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a temporary file.
|
||||
*
|
||||
* If the file could be unlinked upon creation, the name
|
||||
* of the file is not returned via 'name'. However, if the
|
||||
* file could not be unlinked, the name is returned,
|
||||
* expecting the caller to both delete the file and
|
||||
* free the 'name' field after the file is closed.
|
||||
*/
|
||||
FILE *
|
||||
open_tmp_file (char **name)
|
||||
{
|
||||
FILE *file;
|
||||
|
||||
*name = NULL;
|
||||
|
||||
/* Windows does not like tmpfile(). This is likely because tmpfile()
|
||||
* call unlink() on the file before returning it, to make sure the
|
||||
* file is deleted when it is closed. The unlink() call also fails
|
||||
* on Windows if the file is still open. */
|
||||
/* also note that mkstemp is apparently a C90 replacement for tmpfile */
|
||||
/* perhaps all we need to do on Windows is set TMPDIR to whatever is
|
||||
stored in TEMP for tmpfile to work */
|
||||
/* and finally, the "b" from "w+b" is ignored on OS X, not sure about WIN32 */
|
||||
|
||||
file = tmpfile ();
|
||||
if (file == NULL) {
|
||||
char *tmp = getenv ("TEMP");
|
||||
char *tmp_file = tempnam (tmp, "check_");
|
||||
|
||||
/*
|
||||
* Note, tempnam is not enough to get a unique name. Between
|
||||
* getting the name and opening the file, something else also
|
||||
* calling tempnam() could get the same name. It has been observed
|
||||
* on MinGW-w64 builds on Wine that this exact thing happens
|
||||
* if multiple instances of a unit tests are running concurrently.
|
||||
* To prevent two concurrent unit tests from getting the same file,
|
||||
* we append the pid to the file. The pid should be unique on the
|
||||
* system.
|
||||
*/
|
||||
char *uniq_tmp_file = ck_strdup_printf ("%s.%d", tmp_file, getpid ());
|
||||
|
||||
file = fopen (uniq_tmp_file, "w+b");
|
||||
*name = uniq_tmp_file;
|
||||
free (tmp_file);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_pipe (void)
|
||||
{
|
||||
if (send_file1 != 0) {
|
||||
if (send_file2 != 0)
|
||||
eprintf ("Only one nesting of suite runs supported", __FILE__, __LINE__);
|
||||
send_file2 = tmpfile ();
|
||||
} else {
|
||||
send_file1 = tmpfile ();
|
||||
if (send_file1 == NULL) {
|
||||
send_file1 = open_tmp_file (&send_file1_name);
|
||||
return;
|
||||
}
|
||||
if (send_file2 == NULL) {
|
||||
send_file2 = open_tmp_file (&send_file2_name);
|
||||
return;
|
||||
}
|
||||
eprintf ("Only one nesting of suite runs supported", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -203,9 +273,19 @@ teardown_pipe (void)
|
|||
if (send_file2 != 0) {
|
||||
fclose (send_file2);
|
||||
send_file2 = 0;
|
||||
if (send_file2_name != NULL) {
|
||||
unlink (send_file2_name);
|
||||
free (send_file2_name);
|
||||
send_file2_name = NULL;
|
||||
}
|
||||
} else if (send_file1 != 0) {
|
||||
fclose (send_file1);
|
||||
send_file1 = 0;
|
||||
if (send_file1_name != NULL) {
|
||||
unlink (send_file1_name);
|
||||
free (send_file1_name);
|
||||
send_file1_name = NULL;
|
||||
}
|
||||
} else {
|
||||
eprintf ("No messaging setup", __FILE__, __LINE__);
|
||||
}
|
||||
|
|
|
@ -24,13 +24,16 @@
|
|||
|
||||
/* Functions implementing messaging during test runs */
|
||||
|
||||
void send_failure_info(const char *msg);
|
||||
void send_loc_info(const char *file, int line);
|
||||
void send_ctx_info(enum ck_result_ctx ctx);
|
||||
void send_failure_info (const char *msg);
|
||||
void send_loc_info (const char *file, int line);
|
||||
void send_ctx_info (enum ck_result_ctx ctx);
|
||||
void send_duration_info (int duration);
|
||||
|
||||
TestResult *receive_test_result(int waserror);
|
||||
TestResult *receive_test_result (int waserror);
|
||||
|
||||
void setup_messaging(void);
|
||||
void teardown_messaging(void);
|
||||
void setup_messaging (void);
|
||||
void teardown_messaging (void);
|
||||
|
||||
FILE *open_tmp_file (char **name);
|
||||
|
||||
#endif /*CHECK_MSG_NEW_H */
|
||||
|
|
|
@ -18,32 +18,37 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "../lib/libcompat.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "_stdint.h"
|
||||
|
||||
#include "check.h"
|
||||
#include "check_error.h"
|
||||
#include "check_list.h"
|
||||
#include "check_impl.h"
|
||||
#include "check_pack.h"
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <pthread.h>
|
||||
pthread_mutex_t lock_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#else
|
||||
#ifndef HAVE_PTHREAD
|
||||
#define pthread_mutex_lock(arg)
|
||||
#define pthread_mutex_unlock(arg)
|
||||
#define pthread_cleanup_push(f,a) {
|
||||
#define pthread_cleanup_pop(e) }
|
||||
#endif
|
||||
|
||||
/* Maximum size for one message in the message stream. */
|
||||
#define CK_MAX_MSG_SIZE 8192
|
||||
/* This is used to implement a sliding window on the receiving
|
||||
* side. When sending messages, we assure that no single message
|
||||
* is bigger than this (actually we check against CK_MAX_MSG_SIZE/2).
|
||||
* The usual size for a message is less than 80 bytes.
|
||||
* All this is done instead of the previous approach to allocate (actually
|
||||
* continuously reallocate) one big chunk for the whole message stream.
|
||||
* Problems were seen in the wild with up to 4 GB reallocations.
|
||||
*/
|
||||
|
||||
|
||||
/* typedef an unsigned int that has at least 4 bytes */
|
||||
typedef uint32_t ck_uint32;
|
||||
|
||||
|
@ -56,15 +61,17 @@ static char *upack_str (char **buf);
|
|||
static int pack_ctx (char **buf, CtxMsg * cmsg);
|
||||
static int pack_loc (char **buf, LocMsg * lmsg);
|
||||
static int pack_fail (char **buf, FailMsg * fmsg);
|
||||
static int pack_duration (char **buf, DurationMsg * fmsg);
|
||||
static void upack_ctx (char **buf, CtxMsg * cmsg);
|
||||
static void upack_loc (char **buf, LocMsg * lmsg);
|
||||
static void upack_fail (char **buf, FailMsg * fmsg);
|
||||
static void upack_duration (char **buf, DurationMsg * fmsg);
|
||||
|
||||
static void check_type (int type, const char *file, int line);
|
||||
static enum ck_msg_type upack_type (char **buf);
|
||||
static void pack_type (char **buf, enum ck_msg_type type);
|
||||
|
||||
static int read_buf (int fdes, char **buf);
|
||||
static int read_buf (FILE * fdes, int size, char *buf);
|
||||
static int get_result (char *buf, RcvMsg * rmsg);
|
||||
static void rcvmsg_update_ctx (RcvMsg * rmsg, enum ck_result_ctx ctx);
|
||||
static void rcvmsg_update_loc (RcvMsg * rmsg, const char *file, int line);
|
||||
|
@ -77,13 +84,15 @@ typedef void (*upfun) (char **, CheckMsg *);
|
|||
static pfun pftab[] = {
|
||||
(pfun) pack_ctx,
|
||||
(pfun) pack_fail,
|
||||
(pfun) pack_loc
|
||||
(pfun) pack_loc,
|
||||
(pfun) pack_duration
|
||||
};
|
||||
|
||||
static upfun upftab[] = {
|
||||
(upfun) upack_ctx,
|
||||
(upfun) upack_fail,
|
||||
(upfun) upack_loc
|
||||
(upfun) upack_loc,
|
||||
(upfun) upack_duration
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -103,7 +112,6 @@ int
|
|||
upack (char *buf, CheckMsg * msg, enum ck_msg_type *type)
|
||||
{
|
||||
char *obuf;
|
||||
int nread;
|
||||
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
@ -116,8 +124,7 @@ upack (char *buf, CheckMsg * msg, enum ck_msg_type *type)
|
|||
|
||||
upftab[*type] (&buf, msg);
|
||||
|
||||
nread = buf - obuf;
|
||||
return nread;
|
||||
return buf - obuf;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -126,10 +133,10 @@ pack_int (char **buf, int val)
|
|||
unsigned char *ubuf = (unsigned char *) *buf;
|
||||
ck_uint32 uval = val;
|
||||
|
||||
ubuf[0] = (uval >> 24) & 0xFF;
|
||||
ubuf[1] = (uval >> 16) & 0xFF;
|
||||
ubuf[2] = (uval >> 8) & 0xFF;
|
||||
ubuf[3] = uval & 0xFF;
|
||||
ubuf[0] = (unsigned char) ((uval >> 24) & 0xFF);
|
||||
ubuf[1] = (unsigned char) ((uval >> 16) & 0xFF);
|
||||
ubuf[2] = (unsigned char) ((uval >> 8) & 0xFF);
|
||||
ubuf[3] = (unsigned char) (uval & 0xFF);
|
||||
|
||||
*buf += 4;
|
||||
}
|
||||
|
@ -140,7 +147,9 @@ upack_int (char **buf)
|
|||
unsigned char *ubuf = (unsigned char *) *buf;
|
||||
ck_uint32 uval;
|
||||
|
||||
uval = ((ubuf[0] << 24) | (ubuf[1] << 16) | (ubuf[2] << 8) | ubuf[3]);
|
||||
uval =
|
||||
(ck_uint32) ((ubuf[0] << 24) | (ubuf[1] << 16) | (ubuf[2] << 8) |
|
||||
ubuf[3]);
|
||||
|
||||
*buf += 4;
|
||||
|
||||
|
@ -174,12 +183,12 @@ upack_str (char **buf)
|
|||
strsz = upack_int (buf);
|
||||
|
||||
if (strsz > 0) {
|
||||
val = emalloc (strsz + 1);
|
||||
val = (char *) emalloc (strsz + 1);
|
||||
memcpy (val, *buf, strsz);
|
||||
val[strsz] = 0;
|
||||
*buf += strsz;
|
||||
} else {
|
||||
val = emalloc (1);
|
||||
val = (char *) emalloc (1);
|
||||
*val = 0;
|
||||
}
|
||||
|
||||
|
@ -206,7 +215,7 @@ pack_ctx (char **buf, CtxMsg * cmsg)
|
|||
int len;
|
||||
|
||||
len = 4 + 4;
|
||||
*buf = ptr = emalloc (len);
|
||||
*buf = ptr = (char *) emalloc (len);
|
||||
|
||||
pack_type (&ptr, CK_MSG_CTX);
|
||||
pack_int (&ptr, (int) cmsg->ctx);
|
||||
|
@ -217,7 +226,28 @@ pack_ctx (char **buf, CtxMsg * cmsg)
|
|||
static void
|
||||
upack_ctx (char **buf, CtxMsg * cmsg)
|
||||
{
|
||||
cmsg->ctx = upack_int (buf);
|
||||
cmsg->ctx = (enum ck_result_ctx) upack_int (buf);
|
||||
}
|
||||
|
||||
static int
|
||||
pack_duration (char **buf, DurationMsg * cmsg)
|
||||
{
|
||||
char *ptr;
|
||||
int len;
|
||||
|
||||
len = 4 + 4;
|
||||
*buf = ptr = (char *) emalloc (len);
|
||||
|
||||
pack_type (&ptr, CK_MSG_DURATION);
|
||||
pack_int (&ptr, cmsg->duration);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void
|
||||
upack_duration (char **buf, DurationMsg * cmsg)
|
||||
{
|
||||
cmsg->duration = upack_int (buf);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -227,7 +257,7 @@ pack_loc (char **buf, LocMsg * lmsg)
|
|||
int len;
|
||||
|
||||
len = 4 + 4 + (lmsg->file ? strlen (lmsg->file) : 0) + 4;
|
||||
*buf = ptr = emalloc (len);
|
||||
*buf = ptr = (char *) emalloc (len);
|
||||
|
||||
pack_type (&ptr, CK_MSG_LOC);
|
||||
pack_str (&ptr, lmsg->file);
|
||||
|
@ -250,7 +280,7 @@ pack_fail (char **buf, FailMsg * fmsg)
|
|||
int len;
|
||||
|
||||
len = 4 + 4 + (fmsg->msg ? strlen (fmsg->msg) : 0);
|
||||
*buf = ptr = emalloc (len);
|
||||
*buf = ptr = (char *) emalloc (len);
|
||||
|
||||
pack_type (&ptr, CK_MSG_FAIL);
|
||||
pack_str (&ptr, fmsg->msg);
|
||||
|
@ -272,54 +302,52 @@ check_type (int type, const char *file, int line)
|
|||
}
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t ck_mutex_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static void
|
||||
ppack_cleanup (void *mutex)
|
||||
{
|
||||
pthread_mutex_unlock ((pthread_mutex_t *) mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ppack (int fdes, enum ck_msg_type type, CheckMsg * msg)
|
||||
ppack (FILE * fdes, enum ck_msg_type type, CheckMsg * msg)
|
||||
{
|
||||
char *buf;
|
||||
char *buf = NULL;
|
||||
int n;
|
||||
ssize_t r;
|
||||
|
||||
n = pack (type, &buf, msg);
|
||||
pthread_mutex_lock (&mutex_lock);
|
||||
r = write (fdes, buf, n);
|
||||
pthread_mutex_unlock (&mutex_lock);
|
||||
if (r == -1)
|
||||
eprintf ("Error in call to write:", __FILE__, __LINE__ - 2);
|
||||
/* Keep it on the safe side to not send too much data. */
|
||||
if (n > (CK_MAX_MSG_SIZE / 2))
|
||||
eprintf ("Message string too long", __FILE__, __LINE__ - 2);
|
||||
|
||||
pthread_cleanup_push (ppack_cleanup, &ck_mutex_lock);
|
||||
pthread_mutex_lock (&ck_mutex_lock);
|
||||
r = fwrite (buf, 1, n, fdes);
|
||||
fflush (fdes);
|
||||
pthread_mutex_unlock (&ck_mutex_lock);
|
||||
pthread_cleanup_pop (0);
|
||||
if (r != n)
|
||||
eprintf ("Error in call to fwrite:", __FILE__, __LINE__ - 2);
|
||||
|
||||
free (buf);
|
||||
}
|
||||
|
||||
static int
|
||||
read_buf (int fdes, char **buf)
|
||||
read_buf (FILE * fdes, int size, char *buf)
|
||||
{
|
||||
char *readloc;
|
||||
int n;
|
||||
int nread = 0;
|
||||
int size = 1;
|
||||
int grow = 2;
|
||||
|
||||
*buf = emalloc (size);
|
||||
readloc = *buf;
|
||||
while (1) {
|
||||
n = read (fdes, readloc, size - nread);
|
||||
if (n == 0)
|
||||
break;
|
||||
if (n == -1)
|
||||
eprintf ("Error in call to read:", __FILE__, __LINE__ - 4);
|
||||
n = fread (buf, 1, size, fdes);
|
||||
|
||||
nread += n;
|
||||
size *= grow;
|
||||
*buf = erealloc (*buf, size);
|
||||
readloc = *buf + nread;
|
||||
if (ferror (fdes)) {
|
||||
eprintf ("Error in call to fread:", __FILE__, __LINE__ - 4);
|
||||
}
|
||||
|
||||
return nread;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_result (char *buf, RcvMsg * rmsg)
|
||||
{
|
||||
|
@ -333,23 +361,29 @@ get_result (char *buf, RcvMsg * rmsg)
|
|||
|
||||
if (type == CK_MSG_CTX) {
|
||||
CtxMsg *cmsg = (CtxMsg *) & msg;
|
||||
|
||||
rcvmsg_update_ctx (rmsg, cmsg->ctx);
|
||||
} else if (type == CK_MSG_LOC) {
|
||||
LocMsg *lmsg = (LocMsg *) & msg;
|
||||
|
||||
if (rmsg->failctx == CK_CTX_INVALID) {
|
||||
rcvmsg_update_loc (rmsg, lmsg->file, lmsg->line);
|
||||
}
|
||||
free (lmsg->file);
|
||||
} else if (type == CK_MSG_FAIL) {
|
||||
FailMsg *fmsg = (FailMsg *) & msg;
|
||||
|
||||
if (rmsg->msg == NULL) {
|
||||
rmsg->msg = emalloc (strlen (fmsg->msg) + 1);
|
||||
strcpy (rmsg->msg, fmsg->msg);
|
||||
rmsg->msg = strdup (fmsg->msg);
|
||||
rmsg->failctx = rmsg->lastctx;
|
||||
} else {
|
||||
/* Skip subsequent failure messages, only happens for CK_NOFORK */
|
||||
}
|
||||
free (fmsg->msg);
|
||||
} else if (type == CK_MSG_DURATION) {
|
||||
DurationMsg *cmsg = (DurationMsg *) & msg;
|
||||
|
||||
rmsg->duration = cmsg->duration;
|
||||
} else
|
||||
check_type (type, __FILE__, __LINE__);
|
||||
|
||||
|
@ -375,10 +409,11 @@ rcvmsg_create (void)
|
|||
{
|
||||
RcvMsg *rmsg;
|
||||
|
||||
rmsg = emalloc (sizeof (RcvMsg));
|
||||
rmsg = (RcvMsg *) emalloc (sizeof (RcvMsg));
|
||||
rmsg->lastctx = CK_CTX_INVALID;
|
||||
rmsg->failctx = CK_CTX_INVALID;
|
||||
rmsg->msg = NULL;
|
||||
rmsg->duration = -1;
|
||||
reset_rcv_test (rmsg);
|
||||
reset_rcv_fixture (rmsg);
|
||||
return rmsg;
|
||||
|
@ -406,40 +441,47 @@ rcvmsg_update_ctx (RcvMsg * rmsg, enum ck_result_ctx ctx)
|
|||
static void
|
||||
rcvmsg_update_loc (RcvMsg * rmsg, const char *file, int line)
|
||||
{
|
||||
int flen = strlen (file);
|
||||
|
||||
if (rmsg->lastctx == CK_CTX_TEST) {
|
||||
free (rmsg->test_file);
|
||||
rmsg->test_line = line;
|
||||
rmsg->test_file = emalloc (flen + 1);
|
||||
strcpy (rmsg->test_file, file);
|
||||
rmsg->test_file = strdup (file);
|
||||
} else {
|
||||
free (rmsg->fixture_file);
|
||||
rmsg->fixture_line = line;
|
||||
rmsg->fixture_file = emalloc (flen + 1);
|
||||
strcpy (rmsg->fixture_file, file);
|
||||
rmsg->fixture_file = strdup (file);
|
||||
}
|
||||
}
|
||||
|
||||
RcvMsg *
|
||||
punpack (int fdes)
|
||||
punpack (FILE * fdes)
|
||||
{
|
||||
int nread, n;
|
||||
int nread, nparse, n;
|
||||
char *buf;
|
||||
char *obuf;
|
||||
RcvMsg *rmsg;
|
||||
|
||||
nread = read_buf (fdes, &buf);
|
||||
obuf = buf;
|
||||
rmsg = rcvmsg_create ();
|
||||
|
||||
while (nread > 0) {
|
||||
/* Allcate a buffer */
|
||||
buf = (char *) emalloc (CK_MAX_MSG_SIZE);
|
||||
/* Fill the buffer from the file */
|
||||
nread = read_buf (fdes, CK_MAX_MSG_SIZE, buf);
|
||||
nparse = nread;
|
||||
/* While not all parsed */
|
||||
while (nparse > 0) {
|
||||
/* Parse one message */
|
||||
n = get_result (buf, rmsg);
|
||||
nread -= n;
|
||||
buf += n;
|
||||
nparse -= n;
|
||||
/* Move remaining data in buffer to the beginning */
|
||||
memmove (buf, buf + n, nparse);
|
||||
/* If EOF has not been seen */
|
||||
if (nread > 0) {
|
||||
/* Read more data into empty space at end of the buffer */
|
||||
nread = read_buf (fdes, n, buf + nparse);
|
||||
nparse += nread;
|
||||
}
|
||||
}
|
||||
free (buf);
|
||||
|
||||
free (obuf);
|
||||
if (rmsg->lastctx == CK_CTX_INVALID) {
|
||||
free (rmsg);
|
||||
rmsg = NULL;
|
||||
|
|
|
@ -22,10 +22,12 @@
|
|||
#define CHECK_PACK_H
|
||||
|
||||
|
||||
enum ck_msg_type {
|
||||
enum ck_msg_type
|
||||
{
|
||||
CK_MSG_CTX,
|
||||
CK_MSG_FAIL,
|
||||
CK_MSG_LOC,
|
||||
CK_MSG_DURATION,
|
||||
CK_MSG_LAST
|
||||
};
|
||||
|
||||
|
@ -45,11 +47,17 @@ typedef struct FailMsg
|
|||
char *msg;
|
||||
} FailMsg;
|
||||
|
||||
typedef struct DurationMsg
|
||||
{
|
||||
int duration;
|
||||
} DurationMsg;
|
||||
|
||||
typedef union
|
||||
{
|
||||
CtxMsg ctx_msg;
|
||||
CtxMsg ctx_msg;
|
||||
FailMsg fail_msg;
|
||||
LocMsg loc_msg;
|
||||
LocMsg loc_msg;
|
||||
DurationMsg duration_msg;
|
||||
} CheckMsg;
|
||||
|
||||
typedef struct RcvMsg
|
||||
|
@ -61,16 +69,16 @@ typedef struct RcvMsg
|
|||
char *test_file;
|
||||
int test_line;
|
||||
char *msg;
|
||||
int duration;
|
||||
} RcvMsg;
|
||||
|
||||
void rcvmsg_free (RcvMsg *rmsg);
|
||||
void rcvmsg_free (RcvMsg * rmsg);
|
||||
|
||||
|
||||
int pack (enum ck_msg_type type, char **buf, CheckMsg *msg);
|
||||
int upack (char *buf, CheckMsg *msg, enum ck_msg_type *type);
|
||||
|
||||
void ppack (int fdes, enum ck_msg_type type, CheckMsg *msg);
|
||||
RcvMsg *punpack (int fdes);
|
||||
int pack (enum ck_msg_type type, char **buf, CheckMsg * msg);
|
||||
int upack (char *buf, CheckMsg * msg, enum ck_msg_type *type);
|
||||
|
||||
void ppack (FILE * fdes, enum ck_msg_type type, CheckMsg * msg);
|
||||
RcvMsg *punpack (FILE * fdes);
|
||||
|
||||
#endif /*CHECK_PACK_H */
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "../lib/libcompat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -83,30 +83,16 @@ srunner_fprint_results (FILE * file, SRunner * sr, enum print_output print_mode)
|
|||
|
||||
resultlst = sr->resultlst;
|
||||
|
||||
for (list_front (resultlst); !list_at_end (resultlst);
|
||||
list_advance (resultlst)) {
|
||||
TestResult *tr = list_val (resultlst);
|
||||
for (check_list_front (resultlst); !check_list_at_end (resultlst);
|
||||
check_list_advance (resultlst)) {
|
||||
TestResult *tr = (TestResult *) check_list_val (resultlst);
|
||||
|
||||
tr_fprint (file, tr, print_mode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
tr_fprint (FILE * file, TestResult * tr, enum print_output print_mode)
|
||||
{
|
||||
if (print_mode == CK_ENV) {
|
||||
print_mode = get_env_printmode ();
|
||||
}
|
||||
|
||||
if ((print_mode >= CK_VERBOSE && tr->rtype == CK_PASS) ||
|
||||
(tr->rtype != CK_PASS && print_mode >= CK_NORMAL)) {
|
||||
char *trstr = tr_str (tr);
|
||||
fprintf (file, "%s\n", trstr);
|
||||
free (trstr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fprint_xml_esc (FILE * file, const char *str)
|
||||
{
|
||||
for (; *str != '\0'; str++) {
|
||||
|
@ -138,24 +124,40 @@ fprint_xml_esc (FILE * file, const char *str)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
tr_fprint (FILE * file, TestResult * tr, enum print_output print_mode)
|
||||
{
|
||||
if (print_mode == CK_ENV) {
|
||||
print_mode = get_env_printmode ();
|
||||
}
|
||||
|
||||
if ((print_mode >= CK_VERBOSE && tr->rtype == CK_PASS) ||
|
||||
(tr->rtype != CK_PASS && print_mode >= CK_NORMAL)) {
|
||||
char *trstr = tr_str (tr);
|
||||
|
||||
fprintf (file, "%s\n", trstr);
|
||||
free (trstr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tr_xmlprint (FILE * file, TestResult * tr,
|
||||
enum print_output print_mode CK_ATTRIBUTE_UNUSED)
|
||||
{
|
||||
char result[10];
|
||||
char *path_name;
|
||||
char *file_name;
|
||||
char *slash;
|
||||
char *path_name = NULL;
|
||||
char *file_name = NULL;
|
||||
char *slash = NULL;
|
||||
|
||||
switch (tr->rtype) {
|
||||
case CK_PASS:
|
||||
strcpy (result, "success");
|
||||
snprintf (result, sizeof (result), "%s", "success");
|
||||
break;
|
||||
case CK_FAILURE:
|
||||
strcpy (result, "failure");
|
||||
snprintf (result, sizeof (result), "%s", "failure");
|
||||
break;
|
||||
case CK_ERROR:
|
||||
strcpy (result, "error");
|
||||
snprintf (result, sizeof (result), "%s", "error");
|
||||
break;
|
||||
case CK_TEST_RESULT_INVALID:
|
||||
default:
|
||||
|
@ -163,22 +165,33 @@ tr_xmlprint (FILE * file, TestResult * tr,
|
|||
break;
|
||||
}
|
||||
|
||||
slash = strrchr (tr->file, '/');
|
||||
if (slash == NULL) {
|
||||
path_name = (char *) ".";
|
||||
file_name = tr->file;
|
||||
} else {
|
||||
path_name = strdup (tr->file);
|
||||
path_name[slash - tr->file] = 0; /* Terminate the temporary string. */
|
||||
file_name = slash + 1;
|
||||
if (tr->file) {
|
||||
slash = strrchr (tr->file, '/');
|
||||
if (slash == NULL) {
|
||||
slash = strrchr (tr->file, '\\');
|
||||
}
|
||||
|
||||
if (slash == NULL) {
|
||||
path_name = strdup (".");
|
||||
file_name = tr->file;
|
||||
} else {
|
||||
path_name = strdup (tr->file);
|
||||
path_name[slash - tr->file] = 0; /* Terminate the temporary string. */
|
||||
file_name = slash + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fprintf (file, " <test result=\"%s\">\n", result);
|
||||
fprintf (file, " <path>%s</path>\n", path_name);
|
||||
fprintf (file, " <fn>%s:%d</fn>\n", file_name, tr->line);
|
||||
fprintf (file, " <path>%s</path>\n",
|
||||
(path_name == NULL ? "" : path_name));
|
||||
fprintf (file, " <fn>%s:%d</fn>\n",
|
||||
(file_name == NULL ? "" : file_name), tr->line);
|
||||
fprintf (file, " <id>%s</id>\n", tr->tname);
|
||||
fprintf (file, " <iteration>%d</iteration>\n", tr->iter);
|
||||
fprintf (file, " <duration>%d.%06d</duration>\n",
|
||||
tr->duration < 0 ? -1 : tr->duration / US_PER_SEC,
|
||||
tr->duration < 0 ? 0 : tr->duration % US_PER_SEC);
|
||||
fprintf (file, " <description>");
|
||||
fprint_xml_esc (file, tr->tcname);
|
||||
fprintf (file, "</description>\n");
|
||||
|
@ -187,15 +200,14 @@ tr_xmlprint (FILE * file, TestResult * tr,
|
|||
fprintf (file, "</message>\n");
|
||||
fprintf (file, " </test>\n");
|
||||
|
||||
if (slash != NULL) {
|
||||
free (path_name);
|
||||
}
|
||||
free (path_name);
|
||||
}
|
||||
|
||||
enum print_output
|
||||
get_env_printmode (void)
|
||||
{
|
||||
char *env = getenv ("CK_VERBOSITY");
|
||||
|
||||
if (env == NULL)
|
||||
return CK_NORMAL;
|
||||
if (strcmp (env, "silent") == 0)
|
||||
|
|
|
@ -21,9 +21,11 @@
|
|||
#ifndef CHECK_PRINT_H
|
||||
#define CHECK_PRINT_H
|
||||
|
||||
void tr_fprint (FILE *file, TestResult *tr, enum print_output print_mode);
|
||||
void tr_xmlprint (FILE *file, TestResult *tr, enum print_output print_mode);
|
||||
void srunner_fprint (FILE *file, SRunner *sr, enum print_output print_mode);
|
||||
/* escape XML special characters (" ' < > &) in str and print to file */
|
||||
void fprint_xml_esc (FILE * file, const char *str);
|
||||
void tr_fprint (FILE * file, TestResult * tr, enum print_output print_mode);
|
||||
void tr_xmlprint (FILE * file, TestResult * tr, enum print_output print_mode);
|
||||
void srunner_fprint (FILE * file, SRunner * sr, enum print_output print_mode);
|
||||
enum print_output get_env_printmode (void);
|
||||
|
||||
|
||||
|
|
|
@ -18,20 +18,16 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "../lib/libcompat.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "check.h"
|
||||
#include "check_error.h"
|
||||
|
@ -56,35 +52,40 @@ enum tf_type
|
|||
CK_NOFORK_FIXTURE
|
||||
};
|
||||
|
||||
|
||||
/* all functions are defined in the same order they are declared.
|
||||
functions that depend on forking are gathered all together.
|
||||
non-static functions are at the end of the file. */
|
||||
static void srunner_run_init (SRunner * sr, enum print_output print_mode);
|
||||
static void srunner_run_end (SRunner * sr, enum print_output print_mode);
|
||||
static void srunner_iterate_suites (SRunner * sr, enum print_output print_mode);
|
||||
static void srunner_iterate_suites (SRunner * sr,
|
||||
const char *sname, const char *tcname, enum print_output print_mode);
|
||||
static void srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc);
|
||||
static void srunner_add_failure (SRunner * sr, TestResult * tf);
|
||||
static TestResult *srunner_run_setup (List * func_list,
|
||||
enum fork_status fork_usage, const char *test_name, const char *setup_name);
|
||||
static int srunner_run_unchecked_setup (SRunner * sr, TCase * tc);
|
||||
static TestResult *tcase_run_checked_setup (SRunner * sr, TCase * tc);
|
||||
static void srunner_run_teardown (List * l);
|
||||
static void srunner_run_unchecked_teardown (TCase * tc);
|
||||
static void srunner_run_teardown (List * fixture_list,
|
||||
enum fork_status fork_usage);
|
||||
static void srunner_run_unchecked_teardown (SRunner * sr, TCase * tc);
|
||||
static void tcase_run_checked_teardown (TCase * tc);
|
||||
static void srunner_run_tcase (SRunner * sr, TCase * tc);
|
||||
static TestResult *tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tf,
|
||||
int i);
|
||||
static TestResult *receive_result_info_nofork (const char *tcname,
|
||||
const char *tname, int iter);
|
||||
const char *tname, int iter, int duration);
|
||||
static void set_nofork_info (TestResult * tr);
|
||||
static char *pass_msg (void);
|
||||
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(HAVE_FORK) && HAVE_FORK==1
|
||||
static TestResult *tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tf,
|
||||
int i);
|
||||
static TestResult *receive_result_info_fork (const char *tcname,
|
||||
const char *tname, int iter, int status, int expected_signal,
|
||||
unsigned char allowed_exit_value);
|
||||
const char *tname, int iter,
|
||||
int status, int expected_signal, signed char allowed_exit_value);
|
||||
static void set_fork_info (TestResult * tr, int status, int expected_signal,
|
||||
unsigned char allowed_exit_value);
|
||||
signed char allowed_exit_value);
|
||||
static char *signal_msg (int sig);
|
||||
static char *signal_error_msg (int signal_received, int signal_expected);
|
||||
static char *exit_msg (int exitstatus);
|
||||
|
@ -106,7 +107,7 @@ sig_handler (int sig_nr)
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif /* _POSIX_VERSION */
|
||||
#endif /* HAVE_FORK */
|
||||
|
||||
#define MSG_LEN 100
|
||||
|
||||
|
@ -130,6 +131,7 @@ srunner_run_end (SRunner * sr, enum print_output CK_ATTRIBUTE_UNUSED print_mode)
|
|||
|
||||
static void
|
||||
srunner_iterate_suites (SRunner * sr,
|
||||
const char *sname, const char *tcname,
|
||||
enum print_output CK_ATTRIBUTE_UNUSED print_mode)
|
||||
{
|
||||
List *slst;
|
||||
|
@ -138,15 +140,26 @@ srunner_iterate_suites (SRunner * sr,
|
|||
|
||||
slst = sr->slst;
|
||||
|
||||
for (list_front (slst); !list_at_end (slst); list_advance (slst)) {
|
||||
Suite *s = list_val (slst);
|
||||
for (check_list_front (slst); !check_list_at_end (slst);
|
||||
check_list_advance (slst)) {
|
||||
Suite *s = (Suite *) check_list_val (slst);
|
||||
|
||||
if (((sname != NULL) && (strcmp (sname, s->name) != 0))
|
||||
|| ((tcname != NULL) && (!suite_tcase (s, tcname))))
|
||||
continue;
|
||||
|
||||
log_suite_start (sr, s);
|
||||
|
||||
tcl = s->tclst;
|
||||
|
||||
for (list_front (tcl); !list_at_end (tcl); list_advance (tcl)) {
|
||||
tc = list_val (tcl);
|
||||
for (check_list_front (tcl); !check_list_at_end (tcl);
|
||||
check_list_advance (tcl)) {
|
||||
tc = (TCase *) check_list_val (tcl);
|
||||
|
||||
if ((tcname != NULL) && (strcmp (tcname, tc->name) != 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
srunner_run_tcase (sr, tc);
|
||||
}
|
||||
|
||||
|
@ -163,28 +176,34 @@ srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc)
|
|||
|
||||
tfl = tc->tflst;
|
||||
|
||||
for (list_front (tfl); !list_at_end (tfl); list_advance (tfl)) {
|
||||
for (check_list_front (tfl); !check_list_at_end (tfl);
|
||||
check_list_advance (tfl)) {
|
||||
int i;
|
||||
tfun = list_val (tfl);
|
||||
|
||||
tfun = (TF *) check_list_val (tfl);
|
||||
|
||||
for (i = tfun->loop_start; i < tfun->loop_end; i++) {
|
||||
log_test_start (sr, tc, tfun);
|
||||
switch (srunner_fork_status (sr)) {
|
||||
case CK_FORK:
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(HAVE_FORK) && HAVE_FORK==1
|
||||
tr = tcase_run_tfun_fork (sr, tc, tfun, i);
|
||||
#else /* _POSIX_VERSION */
|
||||
#else /* HAVE_FORK */
|
||||
eprintf ("This version does not support fork", __FILE__, __LINE__);
|
||||
#endif /* _POSIX_VERSION */
|
||||
#endif /* HAVE_FORK */
|
||||
break;
|
||||
case CK_NOFORK:
|
||||
tr = tcase_run_tfun_nofork (sr, tc, tfun, i);
|
||||
break;
|
||||
case CK_FORK_GETENV:
|
||||
default:
|
||||
eprintf ("Bad fork status in SRunner", __FILE__, __LINE__);
|
||||
}
|
||||
srunner_add_failure (sr, tr);
|
||||
log_test_end (sr, tr);
|
||||
|
||||
if (NULL != tr) {
|
||||
srunner_add_failure (sr, tr);
|
||||
log_test_end (sr, tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +211,7 @@ srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc)
|
|||
static void
|
||||
srunner_add_failure (SRunner * sr, TestResult * tr)
|
||||
{
|
||||
list_add_end (sr->resultlst, tr);
|
||||
check_list_add_end (sr->resultlst, tr);
|
||||
sr->stats->n_checked++; /* count checks during setup, test, and teardown */
|
||||
if (tr->rtype == CK_FAILURE)
|
||||
sr->stats->n_failed++;
|
||||
|
@ -201,62 +220,30 @@ srunner_add_failure (SRunner * sr, TestResult * tr)
|
|||
|
||||
}
|
||||
|
||||
static int
|
||||
srunner_run_unchecked_setup (SRunner * sr, TCase * tc)
|
||||
{
|
||||
TestResult *tr;
|
||||
List *l;
|
||||
Fixture *f;
|
||||
int rval = 1;
|
||||
|
||||
set_fork_status (CK_NOFORK);
|
||||
|
||||
l = tc->unch_sflst;
|
||||
|
||||
for (list_front (l); !list_at_end (l); list_advance (l)) {
|
||||
send_ctx_info (CK_CTX_SETUP);
|
||||
f = list_val (l);
|
||||
f->fun ();
|
||||
|
||||
tr = receive_result_info_nofork (tc->name, "unchecked_setup", 0);
|
||||
|
||||
if (tr->rtype != CK_PASS) {
|
||||
srunner_add_failure (sr, tr);
|
||||
rval = 0;
|
||||
break;
|
||||
}
|
||||
free (tr->file);
|
||||
free (tr->msg);
|
||||
free (tr);
|
||||
}
|
||||
|
||||
set_fork_status (srunner_fork_status (sr));
|
||||
return rval;
|
||||
}
|
||||
|
||||
static TestResult *
|
||||
tcase_run_checked_setup (SRunner * sr, TCase * tc)
|
||||
srunner_run_setup (List * fixture_list, enum fork_status fork_usage,
|
||||
const char *test_name, const char *setup_name)
|
||||
{
|
||||
TestResult *tr = NULL;
|
||||
List *l;
|
||||
Fixture *f;
|
||||
enum fork_status fstat = srunner_fork_status (sr);
|
||||
Fixture *setup_fixture;
|
||||
|
||||
l = tc->ch_sflst;
|
||||
if (fstat == CK_FORK) {
|
||||
if (fork_usage == CK_FORK) {
|
||||
send_ctx_info (CK_CTX_SETUP);
|
||||
}
|
||||
|
||||
for (list_front (l); !list_at_end (l); list_advance (l)) {
|
||||
if (fstat == CK_NOFORK) {
|
||||
send_ctx_info (CK_CTX_SETUP);
|
||||
}
|
||||
f = list_val (l);
|
||||
f->fun ();
|
||||
for (check_list_front (fixture_list); !check_list_at_end (fixture_list);
|
||||
check_list_advance (fixture_list)) {
|
||||
setup_fixture = (Fixture *) check_list_val (fixture_list);
|
||||
|
||||
/* Stop the setup and return the failure if nofork mode. */
|
||||
if (fstat == CK_NOFORK) {
|
||||
tr = receive_result_info_nofork (tc->name, "checked_setup", 0);
|
||||
if (fork_usage == CK_NOFORK) {
|
||||
send_ctx_info (CK_CTX_SETUP);
|
||||
|
||||
if (0 == setjmp (error_jmp_buffer)) {
|
||||
setup_fixture->fun ();
|
||||
}
|
||||
|
||||
/* Stop the setup and return the failure in nofork mode. */
|
||||
tr = receive_result_info_nofork (test_name, setup_name, 0, -1);
|
||||
if (tr->rtype != CK_PASS) {
|
||||
break;
|
||||
}
|
||||
|
@ -265,34 +252,75 @@ tcase_run_checked_setup (SRunner * sr, TCase * tc)
|
|||
free (tr->msg);
|
||||
free (tr);
|
||||
tr = NULL;
|
||||
} else {
|
||||
setup_fixture->fun ();
|
||||
}
|
||||
}
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
static void
|
||||
srunner_run_teardown (List * l)
|
||||
static int
|
||||
srunner_run_unchecked_setup (SRunner * sr, TCase * tc)
|
||||
{
|
||||
Fixture *f;
|
||||
TestResult *tr = NULL;
|
||||
int rval = 1;
|
||||
|
||||
for (list_front (l); !list_at_end (l); list_advance (l)) {
|
||||
f = list_val (l);
|
||||
set_fork_status (CK_NOFORK);
|
||||
tr = srunner_run_setup (tc->unch_sflst, CK_NOFORK, tc->name,
|
||||
"unchecked_setup");
|
||||
set_fork_status (srunner_fork_status (sr));
|
||||
|
||||
if (tr != NULL && tr->rtype != CK_PASS) {
|
||||
srunner_add_failure (sr, tr);
|
||||
rval = 0;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static TestResult *
|
||||
tcase_run_checked_setup (SRunner * sr, TCase * tc)
|
||||
{
|
||||
TestResult *tr = srunner_run_setup (tc->ch_sflst, srunner_fork_status (sr),
|
||||
tc->name, "checked_setup");
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
static void
|
||||
srunner_run_teardown (List * fixture_list, enum fork_status fork_usage)
|
||||
{
|
||||
Fixture *fixture;
|
||||
|
||||
for (check_list_front (fixture_list); !check_list_at_end (fixture_list);
|
||||
check_list_advance (fixture_list)) {
|
||||
fixture = (Fixture *) check_list_val (fixture_list);
|
||||
send_ctx_info (CK_CTX_TEARDOWN);
|
||||
f->fun ();
|
||||
|
||||
if (fork_usage == CK_NOFORK) {
|
||||
if (0 == setjmp (error_jmp_buffer)) {
|
||||
fixture->fun ();
|
||||
} else {
|
||||
/* Abort the remaining teardowns */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fixture->fun ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
srunner_run_unchecked_teardown (TCase * tc)
|
||||
srunner_run_unchecked_teardown (SRunner * sr, TCase * tc)
|
||||
{
|
||||
srunner_run_teardown (tc->unch_tflst);
|
||||
srunner_run_teardown (tc->unch_tflst, srunner_fork_status (sr));
|
||||
}
|
||||
|
||||
static void
|
||||
tcase_run_checked_teardown (TCase * tc)
|
||||
{
|
||||
srunner_run_teardown (tc->ch_tflst);
|
||||
srunner_run_teardown (tc->ch_tflst, CK_NOFORK);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -300,7 +328,7 @@ srunner_run_tcase (SRunner * sr, TCase * tc)
|
|||
{
|
||||
if (srunner_run_unchecked_setup (sr, tc)) {
|
||||
srunner_iterate_tcase_tfuns (sr, tc);
|
||||
srunner_run_unchecked_teardown (tc);
|
||||
srunner_run_unchecked_teardown (sr, tc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,29 +336,40 @@ static TestResult *
|
|||
tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tfun, int i)
|
||||
{
|
||||
TestResult *tr;
|
||||
struct timespec ts_start = { 0, 0 }, ts_end = {
|
||||
0, 0};
|
||||
|
||||
tr = tcase_run_checked_setup (sr, tc);
|
||||
if (tr == NULL) {
|
||||
tfun->fn (i);
|
||||
clock_gettime (check_get_clockid (), &ts_start);
|
||||
if (0 == setjmp (error_jmp_buffer)) {
|
||||
tfun->fn (i);
|
||||
}
|
||||
clock_gettime (check_get_clockid (), &ts_end);
|
||||
tcase_run_checked_teardown (tc);
|
||||
return receive_result_info_nofork (tc->name, tfun->name, i);
|
||||
return receive_result_info_nofork (tc->name, tfun->name, i,
|
||||
DIFF_IN_USEC (ts_start, ts_end));
|
||||
}
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
static TestResult *
|
||||
receive_result_info_nofork (const char *tcname, const char *tname, int iter)
|
||||
receive_result_info_nofork (const char *tcname,
|
||||
const char *tname, int iter, int duration)
|
||||
{
|
||||
TestResult *tr;
|
||||
|
||||
tr = receive_test_result (0);
|
||||
if (tr == NULL)
|
||||
if (tr == NULL) {
|
||||
eprintf ("Failed to receive test result", __FILE__, __LINE__);
|
||||
tr->tcname = tcname;
|
||||
tr->tname = tname;
|
||||
tr->iter = iter;
|
||||
set_nofork_info (tr);
|
||||
} else {
|
||||
tr->tcname = tcname;
|
||||
tr->tname = tname;
|
||||
tr->iter = iter;
|
||||
tr->duration = duration;
|
||||
set_nofork_info (tr);
|
||||
}
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
@ -349,18 +388,23 @@ set_nofork_info (TestResult * tr)
|
|||
static char *
|
||||
pass_msg (void)
|
||||
{
|
||||
char *msg = emalloc (sizeof ("Passed"));
|
||||
strcpy (msg, "Passed");
|
||||
return msg;
|
||||
return strdup ("Passed");
|
||||
}
|
||||
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(HAVE_FORK) && HAVE_FORK==1
|
||||
static TestResult *
|
||||
tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i)
|
||||
{
|
||||
pid_t pid_w;
|
||||
pid_t pid;
|
||||
int status = 0;
|
||||
struct timespec ts_start = { 0, 0 }, ts_end = {
|
||||
0, 0};
|
||||
|
||||
timer_t timerid;
|
||||
struct itimerspec timer_spec;
|
||||
TestResult *tr;
|
||||
|
||||
|
||||
pid = fork ();
|
||||
if (pid == -1)
|
||||
|
@ -368,19 +412,41 @@ tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i)
|
|||
if (pid == 0) {
|
||||
setpgid (0, 0);
|
||||
group_pid = getpgrp ();
|
||||
tcase_run_checked_setup (sr, tc);
|
||||
tr = tcase_run_checked_setup (sr, tc);
|
||||
free (tr);
|
||||
clock_gettime (check_get_clockid (), &ts_start);
|
||||
tfun->fn (i);
|
||||
clock_gettime (check_get_clockid (), &ts_end);
|
||||
tcase_run_checked_teardown (tc);
|
||||
send_duration_info (DIFF_IN_USEC (ts_start, ts_end));
|
||||
exit (EXIT_SUCCESS);
|
||||
} else {
|
||||
group_pid = pid;
|
||||
}
|
||||
|
||||
alarm_received = 0;
|
||||
alarm (tc->timeout);
|
||||
do {
|
||||
pid_w = waitpid (pid, &status, 0);
|
||||
} while (pid_w == -1);
|
||||
|
||||
if (timer_create (check_get_clockid (),
|
||||
NULL /* fire SIGALRM if timer expires */ ,
|
||||
&timerid) == 0) {
|
||||
/* Set the timer to fire once */
|
||||
timer_spec.it_value = tc->timeout;
|
||||
timer_spec.it_interval.tv_sec = 0;
|
||||
timer_spec.it_interval.tv_nsec = 0;
|
||||
if (timer_settime (timerid, 0, &timer_spec, NULL) == 0) {
|
||||
do {
|
||||
pid_w = waitpid (pid, &status, 0);
|
||||
}
|
||||
while (pid_w == -1);
|
||||
} else {
|
||||
eprintf ("Error in call to timer_settime:", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
/* If the timer has not fired, disable it */
|
||||
timer_delete (timerid);
|
||||
} else {
|
||||
eprintf ("Error in call to timer_create:", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
killpg (pid, SIGKILL); /* Kill remaining processes. */
|
||||
|
||||
|
@ -391,28 +457,30 @@ tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i)
|
|||
static TestResult *
|
||||
receive_result_info_fork (const char *tcname,
|
||||
const char *tname,
|
||||
int iter, int status, int expected_signal, unsigned char allowed_exit_value)
|
||||
int iter, int status, int expected_signal, signed char allowed_exit_value)
|
||||
{
|
||||
TestResult *tr;
|
||||
|
||||
tr = receive_test_result (waserror (status, expected_signal));
|
||||
if (tr == NULL)
|
||||
if (tr == NULL) {
|
||||
eprintf ("Failed to receive test result", __FILE__, __LINE__);
|
||||
tr->tcname = tcname;
|
||||
tr->tname = tname;
|
||||
tr->iter = iter;
|
||||
set_fork_info (tr, status, expected_signal, allowed_exit_value);
|
||||
} else {
|
||||
tr->tcname = tcname;
|
||||
tr->tname = tname;
|
||||
tr->iter = iter;
|
||||
set_fork_info (tr, status, expected_signal, allowed_exit_value);
|
||||
}
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
static void
|
||||
set_fork_info (TestResult * tr, int status, int signal_expected,
|
||||
unsigned char allowed_exit_value)
|
||||
signed char allowed_exit_value)
|
||||
{
|
||||
int was_sig = WIFSIGNALED (status);
|
||||
int was_exit = WIFEXITED (status);
|
||||
int exit_status = WEXITSTATUS (status);
|
||||
signed char exit_status = WEXITSTATUS (status);
|
||||
int signal_received = WTERMSIG (status);
|
||||
|
||||
if (was_sig) {
|
||||
|
@ -420,23 +488,38 @@ set_fork_info (TestResult * tr, int status, int signal_expected,
|
|||
if (alarm_received) {
|
||||
/* Got alarm instead of signal */
|
||||
tr->rtype = CK_ERROR;
|
||||
if (tr->msg != NULL) {
|
||||
free (tr->msg);
|
||||
}
|
||||
tr->msg = signal_error_msg (signal_received, signal_expected);
|
||||
} else {
|
||||
tr->rtype = CK_PASS;
|
||||
if (tr->msg != NULL) {
|
||||
free (tr->msg);
|
||||
}
|
||||
tr->msg = pass_msg ();
|
||||
}
|
||||
} else if (signal_expected != 0) {
|
||||
/* signal received, but not the expected one */
|
||||
tr->rtype = CK_ERROR;
|
||||
if (tr->msg != NULL) {
|
||||
free (tr->msg);
|
||||
}
|
||||
tr->msg = signal_error_msg (signal_received, signal_expected);
|
||||
} else {
|
||||
/* signal received and none expected */
|
||||
tr->rtype = CK_ERROR;
|
||||
if (tr->msg != NULL) {
|
||||
free (tr->msg);
|
||||
}
|
||||
tr->msg = signal_msg (signal_received);
|
||||
}
|
||||
} else if (signal_expected == 0) {
|
||||
if (was_exit && exit_status == allowed_exit_value) {
|
||||
tr->rtype = CK_PASS;
|
||||
if (tr->msg != NULL) {
|
||||
free (tr->msg);
|
||||
}
|
||||
tr->msg = pass_msg ();
|
||||
} else if (was_exit && exit_status != allowed_exit_value) {
|
||||
if (tr->msg == NULL) { /* early exit */
|
||||
|
@ -448,11 +531,15 @@ set_fork_info (TestResult * tr, int status, int signal_expected,
|
|||
}
|
||||
} else { /* a signal was expected and none raised */
|
||||
if (was_exit) {
|
||||
if (tr->msg != NULL) {
|
||||
free (tr->msg);
|
||||
}
|
||||
tr->msg = exit_msg (exit_status);
|
||||
if (exit_status == allowed_exit_value)
|
||||
if (exit_status == allowed_exit_value) {
|
||||
tr->rtype = CK_FAILURE; /* normal exit status */
|
||||
else
|
||||
} else {
|
||||
tr->rtype = CK_FAILURE; /* early exit */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -460,7 +547,8 @@ set_fork_info (TestResult * tr, int status, int signal_expected,
|
|||
static char *
|
||||
signal_msg (int signal)
|
||||
{
|
||||
char *msg = emalloc (MSG_LEN); /* free'd by caller */
|
||||
char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
|
||||
|
||||
if (alarm_received) {
|
||||
snprintf (msg, MSG_LEN, "Test timeout expired");
|
||||
} else {
|
||||
|
@ -475,11 +563,13 @@ signal_error_msg (int signal_received, int signal_expected)
|
|||
{
|
||||
char *sig_r_str;
|
||||
char *sig_e_str;
|
||||
char *msg = emalloc (MSG_LEN); /* free'd by caller */
|
||||
char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
|
||||
|
||||
sig_r_str = strdup (strsignal (signal_received));
|
||||
sig_e_str = strdup (strsignal (signal_expected));
|
||||
if (alarm_received) {
|
||||
snprintf (msg, MSG_LEN, "Test timeout expired, expected signal %d (%s)",
|
||||
snprintf (msg, MSG_LEN,
|
||||
"Test timeout expired, expected signal %d (%s)",
|
||||
signal_expected, sig_e_str);
|
||||
} else {
|
||||
snprintf (msg, MSG_LEN, "Received signal %d (%s), expected %d (%s)",
|
||||
|
@ -493,7 +583,8 @@ signal_error_msg (int signal_received, int signal_expected)
|
|||
static char *
|
||||
exit_msg (int exitval)
|
||||
{
|
||||
char *msg = emalloc (MSG_LEN); /* free'd by caller */
|
||||
char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
|
||||
|
||||
snprintf (msg, MSG_LEN, "Early exit with return value %d", exitval);
|
||||
return msg;
|
||||
}
|
||||
|
@ -509,24 +600,29 @@ waserror (int status, int signal_expected)
|
|||
return ((was_sig && (signal_received != signal_expected)) ||
|
||||
(was_exit && exit_status != 0));
|
||||
}
|
||||
#endif /* _POSIX_VERSION */
|
||||
#endif /* HAVE_FORK */
|
||||
|
||||
enum fork_status
|
||||
srunner_fork_status (SRunner * sr)
|
||||
{
|
||||
if (sr->fstat == CK_FORK_GETENV) {
|
||||
char *env = getenv ("CK_FORK");
|
||||
|
||||
if (env == NULL)
|
||||
#if defined(HAVE_FORK) && HAVE_FORK==1
|
||||
return CK_FORK;
|
||||
#else
|
||||
return CK_NOFORK;
|
||||
#endif
|
||||
if (strcmp (env, "no") == 0)
|
||||
return CK_NOFORK;
|
||||
else {
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(HAVE_FORK) && HAVE_FORK==1
|
||||
return CK_FORK;
|
||||
#else /* _POSIX_VERSION */
|
||||
#else /* HAVE_FORK */
|
||||
eprintf ("This version does not support fork", __FILE__, __LINE__);
|
||||
return CK_NOFORK;
|
||||
#endif /* _POSIX_VERSION */
|
||||
#endif /* HAVE_FORK */
|
||||
}
|
||||
} else
|
||||
return sr->fstat;
|
||||
|
@ -535,16 +631,38 @@ srunner_fork_status (SRunner * sr)
|
|||
void
|
||||
srunner_set_fork_status (SRunner * sr, enum fork_status fstat)
|
||||
{
|
||||
#if !defined(HAVE_FORK) || HAVE_FORK==0
|
||||
/* If fork() is unavailable, do not allow a fork mode to be set */
|
||||
if (fstat != CK_NOFORK) {
|
||||
eprintf ("This version does not support fork", __FILE__, __LINE__);
|
||||
}
|
||||
#endif /* ! HAVE_FORK */
|
||||
sr->fstat = fstat;
|
||||
}
|
||||
|
||||
void
|
||||
srunner_run_all (SRunner * sr, enum print_output print_mode)
|
||||
{
|
||||
#ifdef _POSIX_VERSION
|
||||
srunner_run (sr, NULL, /* All test suites. */
|
||||
NULL, /* All test cases. */
|
||||
print_mode);
|
||||
}
|
||||
|
||||
void
|
||||
srunner_run (SRunner * sr, const char *sname, const char *tcname,
|
||||
enum print_output print_mode)
|
||||
{
|
||||
#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
|
||||
struct sigaction old_action;
|
||||
struct sigaction new_action;
|
||||
#endif /* _POSIX_VERSION */
|
||||
#endif /* HAVE_SIGACTION && HAVE_FORK */
|
||||
|
||||
/* Get the selected test suite and test case from the
|
||||
environment. */
|
||||
if (!tcname)
|
||||
tcname = getenv ("CK_RUN_CASE");
|
||||
if (!sname)
|
||||
sname = getenv ("CK_RUN_SUITE");
|
||||
|
||||
if (sr == NULL)
|
||||
return;
|
||||
|
@ -552,50 +670,54 @@ srunner_run_all (SRunner * sr, enum print_output print_mode)
|
|||
eprintf ("Bad print_mode argument to srunner_run_all: %d",
|
||||
__FILE__, __LINE__, print_mode);
|
||||
}
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
|
||||
memset (&new_action, 0, sizeof new_action);
|
||||
new_action.sa_handler = sig_handler;
|
||||
sigaction (SIGALRM, &new_action, &old_action);
|
||||
#endif /* _POSIX_VERSION */
|
||||
#endif /* HAVE_SIGACTION && HAVE_FORK */
|
||||
srunner_run_init (sr, print_mode);
|
||||
srunner_iterate_suites (sr, print_mode);
|
||||
srunner_iterate_suites (sr, sname, tcname, print_mode);
|
||||
srunner_run_end (sr, print_mode);
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
|
||||
sigaction (SIGALRM, &old_action, NULL);
|
||||
#endif /* _POSIX_VERSION */
|
||||
#endif /* HAVE_SIGACTION && HAVE_FORK */
|
||||
}
|
||||
|
||||
pid_t
|
||||
check_fork (void)
|
||||
{
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(HAVE_FORK) && HAVE_FORK==1
|
||||
pid_t pid = fork ();
|
||||
|
||||
/* Set the process to a process group to be able to kill it easily. */
|
||||
setpgid (pid, group_pid);
|
||||
if (pid >= 0) {
|
||||
setpgid (pid, group_pid);
|
||||
}
|
||||
return pid;
|
||||
#else /* _POSIX_VERSION */
|
||||
#else /* HAVE_FORK */
|
||||
eprintf ("This version does not support fork", __FILE__, __LINE__);
|
||||
return 0;
|
||||
#endif /* _POSIX_VERSION */
|
||||
#endif /* HAVE_FORK */
|
||||
}
|
||||
|
||||
void
|
||||
check_waitpid_and_exit (pid_t pid CK_ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(HAVE_FORK) && HAVE_FORK==1
|
||||
pid_t pid_w;
|
||||
int status;
|
||||
|
||||
if (pid > 0) {
|
||||
do {
|
||||
pid_w = waitpid (pid, &status, 0);
|
||||
} while (pid_w == -1);
|
||||
}
|
||||
while (pid_w == -1);
|
||||
if (waserror (status, 0)) {
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
exit (EXIT_SUCCESS);
|
||||
#else /* _POSIX_VERSION */
|
||||
#else /* HAVE_FORK */
|
||||
eprintf ("This version does not support fork", __FILE__, __LINE__);
|
||||
#endif /* _POSIX_VERSION */
|
||||
#endif /* HAVE_FORK */
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "../lib/libcompat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -79,11 +79,12 @@ char *
|
|||
ck_strdup_printf (const char *fmt, ...)
|
||||
{
|
||||
/* Guess we need no more than 100 bytes. */
|
||||
int n, size = 100;
|
||||
int n;
|
||||
size_t size = 100;
|
||||
char *p;
|
||||
va_list ap;
|
||||
|
||||
p = emalloc (size);
|
||||
p = (char *) emalloc (size);
|
||||
|
||||
while (1) {
|
||||
/* Try to print in the allocated space. */
|
||||
|
@ -91,16 +92,16 @@ ck_strdup_printf (const char *fmt, ...)
|
|||
n = vsnprintf (p, size, fmt, ap);
|
||||
va_end (ap);
|
||||
/* If that worked, return the string. */
|
||||
if (n > -1 && n < size)
|
||||
if (n > -1 && n < (int) size)
|
||||
return p;
|
||||
|
||||
/* Else try again with more space. */
|
||||
if (n > -1) /* C99 conform vsnprintf() */
|
||||
size = n + 1; /* precisely what is needed */
|
||||
size = (size_t) n + 1; /* precisely what is needed */
|
||||
else /* glibc 2.0 */
|
||||
size *= 2; /* twice the old size */
|
||||
|
||||
p = erealloc (p, size);
|
||||
p = (char *) erealloc (p, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,6 +109,7 @@ static const char *
|
|||
tr_type_str (TestResult * tr)
|
||||
{
|
||||
const char *str = NULL;
|
||||
|
||||
if (tr->ctx == CK_CTX_TEST) {
|
||||
if (tr->rtype == CK_PASS)
|
||||
str = "P";
|
||||
|
|
|
@ -23,19 +23,19 @@
|
|||
|
||||
/* Return a string representation of the given TestResult. Return
|
||||
value has been malloc'd, and must be freed by the caller */
|
||||
char *tr_str (TestResult *tr);
|
||||
char *tr_str (TestResult * tr);
|
||||
|
||||
/* Return a string representation of the given TestResult message
|
||||
without the test id or result type. This is suitable for separate
|
||||
formatting of the test and the message. Return value has been
|
||||
malloc'd, and must be freed by the caller */
|
||||
char *tr_short_str (TestResult *tr);
|
||||
char *tr_short_str (TestResult * tr);
|
||||
|
||||
/* Return a string representation of the given SRunner's run
|
||||
statistics (% passed, num run, passed, errors, failures). Return
|
||||
value has been malloc'd, and must be freed by the caller
|
||||
*/
|
||||
char *sr_stat_str (SRunner *sr);
|
||||
char *sr_stat_str (SRunner * sr);
|
||||
|
||||
char *ck_strdup_printf (const char *fmt, ...);
|
||||
|
||||
|
|
65
libs/gst/check/libcheck/clock_gettime.c
Normal file
65
libs/gst/check/libcheck/clock_gettime.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include "libcompat.h"
|
||||
|
||||
#ifdef __MACH__
|
||||
#include <mach/clock.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define NANOSECONDS_PER_SECOND 1000000000
|
||||
|
||||
|
||||
|
||||
int
|
||||
clock_gettime (clockid_t clk_id CK_ATTRIBUTE_UNUSED, struct timespec *ts)
|
||||
{
|
||||
|
||||
#ifdef __MACH__
|
||||
/* OS X does not have clock_gettime, use mach_absolute_time */
|
||||
|
||||
static mach_timebase_info_data_t sTimebaseInfo;
|
||||
uint64_t rawTime;
|
||||
uint64_t nanos;
|
||||
|
||||
rawTime = mach_absolute_time ();
|
||||
|
||||
/*
|
||||
* OS X has a function to convert abs time to nano seconds: AbsoluteToNanoseconds
|
||||
* However, the function may not be available as we may not have
|
||||
* access to CoreServices. Because of this, we convert the abs time
|
||||
* to nano seconds manually.
|
||||
*/
|
||||
|
||||
/*
|
||||
* First grab the time base used on the system, if this is the first
|
||||
* time we are being called. We can check if the value is uninitialized,
|
||||
* as the denominator will be zero.
|
||||
*/
|
||||
if (sTimebaseInfo.denom == 0) {
|
||||
(void) mach_timebase_info (&sTimebaseInfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the conversion. We hope that the multiplication doesn't
|
||||
* overflow; the price you pay for working in fixed point.
|
||||
*/
|
||||
nanos = rawTime * sTimebaseInfo.numer / sTimebaseInfo.denom;
|
||||
|
||||
/*
|
||||
* Fill in the timespec container
|
||||
*/
|
||||
ts->tv_sec = nanos / NANOSECONDS_PER_SECOND;
|
||||
ts->tv_nsec = nanos - (ts->tv_sec * NANOSECONDS_PER_SECOND);
|
||||
#else
|
||||
/*
|
||||
* As there is no function to fall back onto to get the current
|
||||
* time, zero out the time so the caller will have a sane value.
|
||||
*/
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 0;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
15
libs/gst/check/libcheck/libcompat.c
Normal file
15
libs/gst/check/libcheck/libcompat.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include "libcompat.h"
|
||||
|
||||
/* silence warnings about an empty library */
|
||||
void
|
||||
ck_do_nothing (void)
|
||||
{
|
||||
assert (0);
|
||||
|
||||
/*
|
||||
* to silence warning about this function actually
|
||||
* returning, but being marked as noreturn. assert()
|
||||
* must be marked as a function that returns.
|
||||
*/
|
||||
exit (1);
|
||||
}
|
213
libs/gst/check/libcheck/libcompat.h
Normal file
213
libs/gst/check/libcheck/libcompat.h
Normal file
|
@ -0,0 +1,213 @@
|
|||
#ifndef LIBCOMPAT_H
|
||||
#define LIBCOMPAT_H
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
#define GCC_VERSION_AT_LEAST(major, minor) \
|
||||
((__GNUC__ > (major)) || \
|
||||
(__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
|
||||
#else
|
||||
#define GCC_VERSION_AT_LEAST(major, minor) 0
|
||||
#endif
|
||||
|
||||
#if GCC_VERSION_AT_LEAST(2,95)
|
||||
#define CK_ATTRIBUTE_UNUSED __attribute__ ((unused))
|
||||
#else
|
||||
#define CK_ATTRIBUTE_UNUSED
|
||||
#endif /* GCC 2.95 */
|
||||
|
||||
#if GCC_VERSION_AT_LEAST(2,5)
|
||||
#define CK_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
|
||||
#else
|
||||
#define CK_ATTRIBUTE_NORETURN
|
||||
#endif /* GCC 2.5 */
|
||||
|
||||
/*
|
||||
* Used for MSVC to create the export attribute
|
||||
* CK_DLL_EXP is defined during the compilation of the library
|
||||
* on the command line.
|
||||
*/
|
||||
#ifndef CK_DLL_EXP
|
||||
#define CK_DLL_EXP
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
#include <WinSock2.h> /* struct timeval, API used in gettimeofday implementation */
|
||||
#include <io.h> /* read, write */
|
||||
#include <process.h> /* getpid */
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/* defines size_t */
|
||||
#include <sys/types.h>
|
||||
|
||||
/* provides assert */
|
||||
#include <assert.h>
|
||||
|
||||
/* defines FILE */
|
||||
#include <stdio.h>
|
||||
|
||||
/* defines exit() */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* provides localtime and struct tm */
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif /* !HAVE_SYS_TIME_H */
|
||||
#include <time.h>
|
||||
|
||||
/* declares fork(), _POSIX_VERSION. according to Autoconf.info,
|
||||
unistd.h defines _POSIX_VERSION if the system is POSIX-compliant,
|
||||
so we will use this as a test for all things uniquely provided by
|
||||
POSIX like sigaction() and fork() */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
/* declares pthread_create and friends */
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* replacement functions for broken originals */
|
||||
#if !HAVE_DECL_ALARM
|
||||
CK_DLL_EXP unsigned int alarm (unsigned int seconds);
|
||||
#endif /* !HAVE_DECL_ALARM */
|
||||
|
||||
#if !HAVE_MALLOC
|
||||
CK_DLL_EXP void *rpl_malloc (size_t n);
|
||||
#endif /* !HAVE_MALLOC */
|
||||
|
||||
#if !HAVE_REALLOC
|
||||
CK_DLL_EXP void *rpl_realloc (void *p, size_t n);
|
||||
#endif /* !HAVE_REALLOC */
|
||||
|
||||
#if !HAVE_GETPID && HAVE__GETPID
|
||||
#define getpid _getpid
|
||||
#endif /* !HAVE_GETPID && HAVE__GETPID */
|
||||
|
||||
#if !HAVE_GETTIMEOFDAY
|
||||
CK_DLL_EXP int gettimeofday (struct timeval *tv, void *tz);
|
||||
#endif /* !HAVE_GETTIMEOFDAY */
|
||||
|
||||
#if !HAVE_DECL_LOCALTIME_R
|
||||
#if !defined(localtime_r)
|
||||
CK_DLL_EXP struct tm *localtime_r (const time_t * clock, struct tm *result);
|
||||
#endif
|
||||
#endif /* !HAVE_DECL_LOCALTIME_R */
|
||||
|
||||
#if !HAVE_DECL_STRDUP && !HAVE__STRDUP
|
||||
CK_DLL_EXP char *strdup (const char *str);
|
||||
#elif !HAVE_DECL_STRDUP && HAVE__STRDUP
|
||||
#define strdup _strdup
|
||||
#endif /* !HAVE_DECL_STRDUP && HAVE__STRDUP */
|
||||
|
||||
#if !HAVE_DECL_STRSIGNAL
|
||||
CK_DLL_EXP const char *strsignal (int sig);
|
||||
#endif /* !HAVE_DECL_STRSIGNAL */
|
||||
|
||||
/*
|
||||
* On systems where clock_gettime() is not available, or
|
||||
* on systems where some clocks may not be supported, the
|
||||
* definition for CLOCK_MONOTONIC and CLOCK_REALTIME may not
|
||||
* be available. These should define which type of clock
|
||||
* clock_gettime() should use. We define it here if it is
|
||||
* not defined simply so the reimplementation can ignore it.
|
||||
*
|
||||
* We set the values of these clocks to some (hopefully)
|
||||
* invalid value, to avoid the case where we define a
|
||||
* clock with a valid value, and unintentionally use
|
||||
* an actual good clock by accident.
|
||||
*/
|
||||
#ifndef CLOCK_MONOTONIC
|
||||
#define CLOCK_MONOTONIC -1
|
||||
#endif
|
||||
#ifndef CLOCK_REALTIME
|
||||
#define CLOCK_REALTIME -1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LIBRT
|
||||
|
||||
#ifdef STRUCT_TIMESPEC_DEFINITION_MISSING
|
||||
/*
|
||||
* The following structure is defined in POSIX 1003.1 for times
|
||||
* specified in seconds and nanoseconds. If it is not defined in
|
||||
* time.g, then we need to define it here
|
||||
*/
|
||||
struct timespec
|
||||
{
|
||||
time_t tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
#endif /* STRUCT_TIMESPEC_DEFINITION_MISSING */
|
||||
|
||||
#ifdef STRUCT_ITIMERSPEC_DEFINITION_MISSING
|
||||
/*
|
||||
* The following structure is defined in POSIX.1b for timer start values and intervals.
|
||||
* If it is not defined in time.h, then we need to define it here.
|
||||
*/
|
||||
struct itimerspec
|
||||
{
|
||||
struct timespec it_interval;
|
||||
struct timespec it_value;
|
||||
};
|
||||
#endif /* STRUCT_ITIMERSPEC_DEFINITION_MISSING */
|
||||
|
||||
/*
|
||||
* Do a simple forward declaration in case the struct is not defined.
|
||||
* In the versions of timer_create in libcompat, sigevent is never
|
||||
* used.
|
||||
*/
|
||||
struct sigevent;
|
||||
|
||||
CK_DLL_EXP int clock_gettime (clockid_t clk_id, struct timespec *ts);
|
||||
CK_DLL_EXP int timer_create (clockid_t clockid, struct sigevent *sevp,
|
||||
timer_t * timerid);
|
||||
CK_DLL_EXP int timer_settime (timer_t timerid, int flags,
|
||||
const struct itimerspec *new_value, struct itimerspec *old_value);
|
||||
CK_DLL_EXP int timer_delete (timer_t timerid);
|
||||
#endif /* HAVE_LIBRT */
|
||||
|
||||
/*
|
||||
* The following checks are to determine if the system's
|
||||
* snprintf (or its variants) should be replaced with
|
||||
* the C99 compliant version in libcompat.
|
||||
*/
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#if HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
|
||||
#if !HAVE_VSNPRINTF
|
||||
CK_DLL_EXP int rpl_vsnprintf (char *, size_t, const char *, va_list);
|
||||
|
||||
#define vsnprintf rpl_vsnprintf
|
||||
#endif
|
||||
#if !HAVE_SNPRINTF
|
||||
CK_DLL_EXP int rpl_snprintf (char *, size_t, const char *, ...);
|
||||
|
||||
#define snprintf rpl_snprintf
|
||||
#endif
|
||||
#endif /* HAVE_STDARG_H */
|
||||
|
||||
#if !HAVE_GETLINE
|
||||
CK_DLL_EXP ssize_t getline (char **lineptr, size_t * n, FILE * stream);
|
||||
#endif
|
||||
|
||||
/* silence warnings about an empty library */
|
||||
CK_DLL_EXP void
|
||||
ck_do_nothing (void)
|
||||
CK_ATTRIBUTE_NORETURN;
|
||||
|
||||
#endif /* !LIBCOMPAT_H */
|
19
libs/gst/check/libcheck/localtime_r.c
Normal file
19
libs/gst/check/libcheck/localtime_r.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "libcompat.h"
|
||||
|
||||
#if !defined(localtime_r)
|
||||
|
||||
struct tm *
|
||||
localtime_r (const time_t * clock, struct tm *result)
|
||||
{
|
||||
struct tm *now = localtime (clock);
|
||||
|
||||
if (now == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
*result = *now;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* !defined(localtime_r) */
|
10
libs/gst/check/libcheck/strsignal.c
Normal file
10
libs/gst/check/libcheck/strsignal.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include "libcompat.h"
|
||||
|
||||
const char *
|
||||
strsignal (int sig)
|
||||
{
|
||||
static char signame[40];
|
||||
|
||||
sprintf (signame, "SIG #%d", sig);
|
||||
return signame;
|
||||
}
|
15
libs/gst/check/libcheck/timer_create.c
Normal file
15
libs/gst/check/libcheck/timer_create.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include "libcompat.h"
|
||||
|
||||
int
|
||||
timer_create (clockid_t clockid CK_ATTRIBUTE_UNUSED,
|
||||
struct sigevent *sevp CK_ATTRIBUTE_UNUSED,
|
||||
timer_t * timerid CK_ATTRIBUTE_UNUSED)
|
||||
{
|
||||
/*
|
||||
* The create function does nothing. timer_settime will use
|
||||
* alarm to set the timer, and timer_delete will stop the
|
||||
* alarm
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
33
libs/gst/check/libcheck/timer_delete.c
Normal file
33
libs/gst/check/libcheck/timer_delete.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "libcompat.h"
|
||||
|
||||
int
|
||||
timer_delete (timer_t timerid CK_ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifdef HAVE_SETITIMER
|
||||
/*
|
||||
* If the system does not have timer_settime() but does have
|
||||
* setitimer() use that instead of alarm().
|
||||
*/
|
||||
struct itimerval interval;
|
||||
|
||||
/*
|
||||
* Setting values to '0' results in disabling the running timer.
|
||||
*/
|
||||
interval.it_value.tv_sec = 0;
|
||||
interval.it_value.tv_usec = 0;
|
||||
interval.it_interval.tv_sec = 0;
|
||||
interval.it_interval.tv_usec = 0;
|
||||
|
||||
return setitimer (ITIMER_REAL, &interval, NULL);
|
||||
#else
|
||||
/*
|
||||
* There is only one timer, that used by alarm.
|
||||
* Setting alarm(0) will not set a new alarm, and
|
||||
* will kill the previous timer.
|
||||
*/
|
||||
|
||||
alarm (0);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
37
libs/gst/check/libcheck/timer_settime.c
Normal file
37
libs/gst/check/libcheck/timer_settime.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "libcompat.h"
|
||||
|
||||
int
|
||||
timer_settime (timer_t timerid CK_ATTRIBUTE_UNUSED,
|
||||
int flags CK_ATTRIBUTE_UNUSED,
|
||||
const struct itimerspec *new_value,
|
||||
struct itimerspec *old_value CK_ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifdef HAVE_SETITIMER
|
||||
/*
|
||||
* If the system does not have timer_settime() but does have
|
||||
* setitimer() use that instead of alarm().
|
||||
*/
|
||||
struct itimerval interval;
|
||||
|
||||
interval.it_value.tv_sec = new_value->it_value.tv_sec;
|
||||
interval.it_value.tv_usec = new_value->it_value.tv_nsec / 1000;
|
||||
interval.it_interval.tv_sec = new_value->it_interval.tv_sec;
|
||||
interval.it_interval.tv_usec = new_value->it_interval.tv_nsec / 1000;
|
||||
|
||||
return setitimer (ITIMER_REAL, &interval, NULL);
|
||||
#else
|
||||
int seconds = new_value->it_value.tv_sec;
|
||||
|
||||
/*
|
||||
* As the alarm() call has only second precision, if the caller
|
||||
* specifies partial seconds, we round up to the nearest second.
|
||||
*/
|
||||
if (new_value->it_value.tv_nsec > 0) {
|
||||
seconds += 1;
|
||||
}
|
||||
|
||||
alarm (seconds);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
Loading…
Reference in a new issue