check: update internal libcheck to 0.9.8

This commit is contained in:
Tim-Philipp Müller 2009-12-17 20:09:48 +00:00
parent 5fde7d1ed0
commit 8e5f17d07f
14 changed files with 423 additions and 306 deletions

View file

@ -7,7 +7,7 @@ AC_MSG_NOTICE([Running check unit test framework checks now...])
CHECK_MAJOR_VERSION=0 CHECK_MAJOR_VERSION=0
CHECK_MINOR_VERSION=9 CHECK_MINOR_VERSION=9
CHECK_MICRO_VERSION=6 CHECK_MICRO_VERSION=8
CHECK_VERSION=$CHECK_MAJOR_VERSION.$CHECK_MINOR_VERSION.$CHECK_MICRO_VERSION CHECK_VERSION=$CHECK_MAJOR_VERSION.$CHECK_MINOR_VERSION.$CHECK_MICRO_VERSION
AC_SUBST(CHECK_MAJOR_VERSION) AC_SUBST(CHECK_MAJOR_VERSION)

View file

@ -18,7 +18,7 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#include "config.h" #include "../lib/libcompat.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -47,65 +47,6 @@ static void tr_init (TestResult * tr);
static void suite_free (Suite * s); static void suite_free (Suite * s);
static void tcase_free (TCase * tc); static void tcase_free (TCase * tc);
#if HAVE_CONFIG_H
#include <config.h>
#endif
#undef malloc
#undef realloc
#undef strsignal
#include <sys/types.h>
void *malloc (size_t n);
void *realloc (void *p, size_t n);
char *strsignal (int sig);
void *rpl_malloc (size_t n);
void *rpl_realloc (void *p, size_t n);
static const char *rpl_strsignal (int sig);
/* Allocate an N-byte block of memory from the heap. If N is zero,
allocate a 1-byte block. */
void *
rpl_malloc (size_t n)
{
if (n == 0)
n = 1;
return malloc (n);
}
/* AC_FUNC_REALLOC in configure defines realloc to rpl_realloc if
realloc(0,0) is NULL to make it GNU compatible and always return a
valid pointer, same for AC_FUNC_MALLOC, malloc, and rpl_malloc.
rpl means `replacement'.
If this ever turns out to be a problem, it might be easiest to just
kill the configure macro calls.
*/
void *
rpl_realloc (void *p, size_t n)
{
if (n == 0)
n = 1;
if (p == 0)
return malloc (n);
return realloc (p, n);
}
/* We simply don't have strsignal on some platforms. This function
should get used if AC_REPLACE_FUNCS([strsignal]) cannot find
something acceptable. Note that Gnulib has a much much much more
advanced version of strsignal, but we don't really care.
*/
static const char *
rpl_strsignal (int sig)
{
static char signame[40];
sprintf (signame, "SIG #%d", sig);
return signame;
}
Suite * Suite *
suite_create (const char *name) suite_create (const char *name)
{ {
@ -152,6 +93,14 @@ tcase_create (const char *name)
} }
} }
env = getenv ("CK_TIMEOUT_MULTIPLIER");
if (env != NULL) {
int tmp = atoi (env);
if (tmp >= 0) {
timeout = timeout * tmp;
}
}
tc->timeout = timeout; tc->timeout = timeout;
tc->tflst = check_list_create (); tc->tflst = check_list_create ();
tc->unch_sflst = check_list_create (); tc->unch_sflst = check_list_create ();
@ -189,8 +138,8 @@ suite_add_tcase (Suite * s, TCase * tc)
} }
void void
_tcase_add_test (TCase * tc, TFun fn, const char *name, int _signal, int start, _tcase_add_test (TCase * tc, TFun fn, const char *name, int _signal,
int end) int allowed_exit_value, int start, int end)
{ {
TF *tf; TF *tf;
if (tc == NULL || fn == NULL || name == NULL) if (tc == NULL || fn == NULL || name == NULL)
@ -200,6 +149,7 @@ _tcase_add_test (TCase * tc, TFun fn, const char *name, int _signal, int start,
tf->loop_start = start; tf->loop_start = start;
tf->loop_end = end; tf->loop_end = end;
tf->signal = _signal; /* 0 means no signal expected */ tf->signal = _signal; /* 0 means no signal expected */
tf->allowed_exit_value = allowed_exit_value; /* 0 is default successful exit */
tf->name = name; tf->name = name;
list_add_end (tc->tflst, tf); list_add_end (tc->tflst, tf);
} }
@ -249,12 +199,21 @@ tcase_add_fixture (TCase * tc, SFun setup, SFun teardown, int ischecked)
void void
tcase_set_timeout (TCase * tc, int timeout) tcase_set_timeout (TCase * tc, int timeout)
{ {
if (timeout >= 0) if (timeout >= 0) {
char *env = getenv ("CK_TIMEOUT_MULTIPLIER");
if (env != NULL) {
int tmp = atoi (env);
if (tmp >= 0) {
timeout = timeout * tmp;
}
}
tc->timeout = timeout; tc->timeout = timeout;
}
} }
void void
tcase_fn_start (const char *fname, const char *file, int line) tcase_fn_start (const char *fname CK_ATTRIBUTE_UNUSED, const char *file,
int line)
{ {
send_ctx_info (CK_CTX_TEST); send_ctx_info (CK_CTX_TEST);
send_loc_info (file, line); send_loc_info (file, line);
@ -283,8 +242,11 @@ _fail_unless (int result, const char *file, int line, const char *expr, ...)
vsnprintf (buf, BUFSIZ, msg, ap); vsnprintf (buf, BUFSIZ, msg, ap);
va_end (ap); va_end (ap);
send_failure_info (buf); send_failure_info (buf);
if (cur_fork_status () == CK_FORK) if (cur_fork_status () == CK_FORK) {
#ifdef _POSIX_VERSION
exit (1); exit (1);
#endif /* _POSIX_VERSION */
}
} }
} }

View file

@ -131,7 +131,11 @@ TCase * CK_EXPORT tcase_create (const char *name);
/* Add a test function with signal handling to a test case (macro version) */ /* Add a test function with signal handling to a test case (macro version) */
#define tcase_add_test_raise_signal(tc,tf,signal) \ #define tcase_add_test_raise_signal(tc,tf,signal) \
_tcase_add_test((tc),(tf),"" # tf "",(signal), 0, 1) _tcase_add_test((tc),(tf),"" # tf "",(signal), 0, 0, 1)
/* Add a test function with an expected exit value to a test case (macro version) */
#define tcase_add_exit_test(tc, tf, expected_exit_value) \
_tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),0,1)
/* Add a looping test function to a test case (macro version) /* Add a looping test function to a test case (macro version)
@ -140,18 +144,22 @@ TCase * CK_EXPORT tcase_create (const char *name);
available in the test. available in the test.
*/ */
#define tcase_add_loop_test(tc,tf,s,e) \ #define tcase_add_loop_test(tc,tf,s,e) \
_tcase_add_test((tc),(tf),"" # tf "",0,(s),(e)) _tcase_add_test((tc),(tf),"" # tf "",0,0,(s),(e))
/* Signal version of loop test. /* Signal version of loop test.
FIXME: add a test case; this is untested as part of Check's tests. FIXME: add a test case; this is untested as part of Check's tests.
*/ */
#define tcase_add_loop_test_raise_signal(tc,tf,signal,s,e) \ #define tcase_add_loop_test_raise_signal(tc,tf,signal,s,e) \
_tcase_add_test((tc),(tf),"" # tf "",(signal),(s),(e)) _tcase_add_test((tc),(tf),"" # tf "",(signal),0,(s),(e))
/* allowed exit value version of loop test. */
#define tcase_add_loop_exit_test(tc,tf,expected_exit_value,s,e) \
_tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),(s),(e))
/* Add a test function to a test case /* Add a test function to a test case
(function version -- use this when the macro won't work (function version -- use this when the macro won't work
*/ */
void CK_EXPORT _tcase_add_test (TCase *tc, TFun tf, const char *fname, int _signal, int start, int end); void CK_EXPORT _tcase_add_test (TCase *tc, TFun tf, const char *fname, int _signal, int allowed_exit_value, int start, int end);
/* Add unchecked fixture setup/teardown functions to a test case /* Add unchecked fixture setup/teardown functions to a test case
@ -197,7 +205,7 @@ void CK_EXPORT tcase_fn_start (const char *fname, const char *file, int line);
One must use braces within a START_/END_ pair to declare new variables One must use braces within a START_/END_ pair to declare new variables
*/ */
#define START_TEST(__testname)\ #define START_TEST(__testname)\
static void __testname (int CK_ATTRIBUTE_UNUSED _i)\ static void __testname (int _i CK_ATTRIBUTE_UNUSED)\
{\ {\
tcase_fn_start (""# __testname, __FILE__, __LINE__); tcase_fn_start (""# __testname, __FILE__, __LINE__);
@ -272,6 +280,9 @@ enum print_output {
CK_NORMAL, /* All failed tests */ CK_NORMAL, /* All failed tests */
CK_VERBOSE, /* All tests */ CK_VERBOSE, /* All tests */
CK_ENV, /* Look at environment var */ CK_ENV, /* Look at environment var */
#if @ENABLE_SUBUNIT@
CK_SUBUNIT, /* Run as a subunit child process */
#endif
CK_LAST CK_LAST
}; };

View file

@ -18,7 +18,7 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#include "config.h" #include "../lib/libcompat.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>

View file

@ -33,6 +33,7 @@ typedef struct TF {
int loop_end; int loop_end;
const char *name; const char *name;
int signal; int signal;
unsigned char allowed_exit_value;
} TF; } TF;
struct Suite { struct Suite {
@ -83,6 +84,7 @@ enum cl_event {
CLSTART_S, CLSTART_S,
CLEND_SR, CLEND_SR,
CLEND_S, CLEND_S,
CLSTART_T, /* A test case is about to run */
CLEND_T CLEND_T
}; };

View file

@ -18,7 +18,7 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#include "config.h" #include "../lib/libcompat.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View file

@ -18,19 +18,21 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#include "config.h" #include "../lib/libcompat.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <check.h> #include <check.h>
#if HAVE_SUBUNIT_CHILD_H
#include <subunit/child.h>
#endif
#include "check_error.h" #include "check_error.h"
#include "check_list.h" #include "check_list.h"
#include "check_impl.h" #include "check_impl.h"
#include "check_log.h" #include "check_log.h"
#include "check_print.h" #include "check_print.h"
#include "check_str.h"
static void srunner_send_evt (SRunner * sr, void *obj, enum cl_event evt); static void srunner_send_evt (SRunner * sr, void *obj, enum cl_event evt);
@ -118,6 +120,14 @@ log_suite_end (SRunner * sr, Suite * s)
srunner_send_evt (sr, s, CLEND_S); srunner_send_evt (sr, s, CLEND_S);
} }
void
log_test_start (SRunner * sr, TCase * tc, TF * tfun)
{
char buffer[100];
snprintf (buffer, 99, "%s:%s", tc->name, tfun->name);
srunner_send_evt (sr, buffer, CLSTART_T);
}
void void
log_test_end (SRunner * sr, TestResult * tr) log_test_end (SRunner * sr, TestResult * tr)
{ {
@ -142,7 +152,6 @@ void
stdout_lfun (SRunner * sr, FILE * file, enum print_output printmode, stdout_lfun (SRunner * sr, FILE * file, enum print_output printmode,
void *obj, enum cl_event evt) void *obj, enum cl_event evt)
{ {
TestResult *tr;
Suite *s; Suite *s;
if (printmode == CK_ENV) { if (printmode == CK_ENV) {
@ -177,8 +186,9 @@ stdout_lfun (SRunner * sr, FILE * file, enum print_output printmode,
case CLEND_S: case CLEND_S:
s = obj; s = obj;
break; break;
case CLSTART_T:
break;
case CLEND_T: case CLEND_T:
tr = obj;
break; break;
default: default:
eprintf ("Bad event type received in stdout_lfun", __FILE__, __LINE__); eprintf ("Bad event type received in stdout_lfun", __FILE__, __LINE__);
@ -188,8 +198,9 @@ stdout_lfun (SRunner * sr, FILE * file, enum print_output printmode,
} }
void void
lfile_lfun (SRunner * sr, FILE * file, enum print_output printmode, lfile_lfun (SRunner * sr, FILE * file,
void *obj, enum cl_event evt) enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj,
enum cl_event evt)
{ {
TestResult *tr; TestResult *tr;
Suite *s; Suite *s;
@ -212,20 +223,23 @@ lfile_lfun (SRunner * sr, FILE * file, enum print_output printmode,
case CLEND_S: case CLEND_S:
s = obj; s = obj;
break; break;
case CLSTART_T:
break;
case CLEND_T: case CLEND_T:
tr = obj; tr = obj;
tr_fprint (file, tr, CK_VERBOSE); tr_fprint (file, tr, CK_VERBOSE);
break; break;
default: default:
eprintf ("Bad event type received in stdout_lfun", __FILE__, __LINE__); eprintf ("Bad event type received in lfile_lfun", __FILE__, __LINE__);
} }
} }
void void
xml_lfun (SRunner * sr, FILE * file, enum print_output printmode, xml_lfun (SRunner * sr CK_ATTRIBUTE_UNUSED, FILE * file,
void *obj, enum cl_event evt) enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj,
enum cl_event evt)
{ {
TestResult *tr; TestResult *tr;
Suite *s; Suite *s;
@ -266,6 +280,8 @@ xml_lfun (SRunner * sr, FILE * file, enum print_output printmode,
fprintf (file, " </suite>\n"); fprintf (file, " </suite>\n");
s = obj; s = obj;
break; break;
case CLSTART_T:
break;
case CLEND_T: case CLEND_T:
tr = obj; tr = obj;
tr_xmlprint (file, tr, CK_VERBOSE); tr_xmlprint (file, tr, CK_VERBOSE);
@ -276,6 +292,67 @@ xml_lfun (SRunner * sr, FILE * file, enum print_output printmode,
} }
#if ENABLE_SUBUNIT
void
subunit_lfun (SRunner * sr, FILE * file, enum print_output printmode,
void *obj, enum cl_event evt)
{
TestResult *tr;
Suite *s;
char const *name;
/* assert(printmode == CK_SUBUNIT); */
switch (evt) {
case CLINITLOG_SR:
break;
case CLENDLOG_SR:
break;
case CLSTART_SR:
break;
case CLSTART_S:
s = obj;
break;
case CLEND_SR:
if (printmode > CK_SILENT) {
fprintf (file, "\n");
srunner_fprint (file, sr, printmode);
}
break;
case CLEND_S:
s = obj;
break;
case CLSTART_T:
name = obj;
subunit_test_start (name);
break;
case CLEND_T:
tr = obj;
{
char *name = ck_strdup_printf ("%s:%s", tr->tcname, tr->tname);
char *msg = tr_short_str (tr);
switch (tr->rtype) {
case CK_PASS:
subunit_test_pass (name);
break;
case CK_FAILURE:
subunit_test_fail (name, msg);
break;
case CK_ERROR:
subunit_test_error (name, msg);
break;
default:
eprintf ("Bad result type in subunit_lfun", __FILE__, __LINE__);
free (name);
free (msg);
}
}
break;
default:
eprintf ("Bad event type received in subunit_lfun", __FILE__, __LINE__);
}
}
#endif
FILE * FILE *
srunner_open_lfile (SRunner * sr) srunner_open_lfile (SRunner * sr)
@ -308,7 +385,14 @@ srunner_init_logging (SRunner * sr, enum print_output print_mode)
{ {
FILE *f; FILE *f;
sr->loglst = check_list_create (); sr->loglst = check_list_create ();
srunner_register_lfun (sr, stdout, 0, stdout_lfun, print_mode); #if ENABLE_SUBUNIT
if (print_mode != CK_SUBUNIT)
#endif
srunner_register_lfun (sr, stdout, 0, stdout_lfun, print_mode);
#if ENABLE_SUBUNIT
else
srunner_register_lfun (sr, stdout, 0, subunit_lfun, print_mode);
#endif
f = srunner_open_lfile (sr); f = srunner_open_lfile (sr);
if (f) { if (f) {
srunner_register_lfun (sr, f, 1, lfile_lfun, print_mode); srunner_register_lfun (sr, f, 1, lfile_lfun, print_mode);

View file

@ -26,6 +26,7 @@ void log_srunner_end (SRunner *sr);
void log_suite_start (SRunner *sr, Suite *s); void log_suite_start (SRunner *sr, Suite *s);
void log_suite_end (SRunner *sr, Suite *s); void log_suite_end (SRunner *sr, Suite *s);
void log_test_end (SRunner *sr, TestResult *tr); 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 stdout_lfun (SRunner *sr, FILE *file, enum print_output,
void *obj, enum cl_event evt); void *obj, enum cl_event evt);
@ -36,6 +37,9 @@ void lfile_lfun (SRunner *sr, FILE *file, enum print_output,
void xml_lfun (SRunner *sr, FILE *file, enum print_output, void xml_lfun (SRunner *sr, FILE *file, enum print_output,
void *obj, enum cl_event evt); void *obj, enum cl_event evt);
void subunit_lfun (SRunner *sr, FILE *file, enum print_output,
void *obj, enum cl_event evt);
void srunner_register_lfun (SRunner *sr, FILE *lfile, int close, void srunner_register_lfun (SRunner *sr, FILE *lfile, int close,
LFun lfun, enum print_output); LFun lfun, enum print_output);

View file

@ -18,10 +18,9 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#include "config.h" #include "../lib/libcompat.h"
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
@ -73,7 +72,7 @@ get_pipe (void)
if (send_file1 != 0) { if (send_file1 != 0) {
return send_file1; return send_file1;
} }
printf ("send_file1=%p,send_file2=%p", send_file1, send_file2);
eprintf ("No messaging setup", __FILE__, __LINE__); eprintf ("No messaging setup", __FILE__, __LINE__);
return NULL; return NULL;

View file

@ -18,26 +18,23 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#include "config.h" #include "../lib/libcompat.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_STDINT_H
#include <unistd.h> #include <stdint.h>
#endif #endif
#include "_stdint.h"
#include "check.h" #include "check.h"
#include "check_error.h" #include "check_error.h"
#include "check_list.h" #include "check_list.h"
#include "check_impl.h" #include "check_impl.h"
#include "check_pack.h" #include "check_pack.h"
#ifdef HAVE_PTHREAD_H #ifdef HAVE_PTHREAD
#include <pthread.h>
pthread_mutex_t lock_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t lock_mutex = PTHREAD_MUTEX_INITIALIZER;
#else #else
#define pthread_mutex_lock(arg) #define pthread_mutex_lock(arg)
@ -271,7 +268,7 @@ check_type (int type, const char *file, int line)
eprintf ("Bad message type arg %d", file, line, type); eprintf ("Bad message type arg %d", file, line, type);
} }
#ifdef HAVE_PTHREAD_H #ifdef HAVE_PTHREAD
pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER;
#endif #endif

View file

@ -18,8 +18,7 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#define _GNU_SOURCE #include "../lib/libcompat.h"
#include "config.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -57,6 +56,11 @@ srunner_fprint (FILE * file, SRunner * sr, enum print_output print_mode)
static void static void
srunner_fprint_summary (FILE * file, SRunner * sr, enum print_output print_mode) srunner_fprint_summary (FILE * file, SRunner * sr, enum print_output print_mode)
{ {
#if ENABLE_SUBUNIT
if (print_mode == CK_SUBUNIT)
return;
#endif
if (print_mode >= CK_MINIMAL) { if (print_mode >= CK_MINIMAL) {
char *str; char *str;
@ -72,6 +76,11 @@ srunner_fprint_results (FILE * file, SRunner * sr, enum print_output print_mode)
{ {
List *resultlst; List *resultlst;
#if ENABLE_SUBUNIT
if (print_mode == CK_SUBUNIT)
return;
#endif
resultlst = sr->resultlst; resultlst = sr->resultlst;
for (list_front (resultlst); !list_at_end (resultlst); for (list_front (resultlst); !list_at_end (resultlst);
@ -98,7 +107,8 @@ tr_fprint (FILE * file, TestResult * tr, enum print_output print_mode)
} }
void void
tr_xmlprint (FILE * file, TestResult * tr, enum print_output print_mode) tr_xmlprint (FILE * file, TestResult * tr,
enum print_output print_mode CK_ATTRIBUTE_UNUSED)
{ {
char result[10]; char result[10];
char *path_name; char *path_name;

View file

@ -18,12 +18,9 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#define _GNU_SOURCE #include "../lib/libcompat.h"
#include "config.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -53,38 +50,44 @@ enum tf_type
CK_NOFORK_FIXTURE 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_init (SRunner * sr, enum print_output print_mode);
static void srunner_run_end (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, enum print_output print_mode);
static void srunner_run_tcase (SRunner * sr, TCase * tc);
static int srunner_run_unchecked_setup (SRunner * sr, TCase * tc);
static void srunner_run_unchecked_teardown (SRunner * sr, TCase * tc);
static TestResult *tcase_run_checked_setup (SRunner * sr, TCase * tc);
static void tcase_run_checked_teardown (TCase * tc);
static void srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc); static void srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc);
static void srunner_add_failure (SRunner * sr, TestResult * tf); static void srunner_add_failure (SRunner * sr, TestResult * tf);
static TestResult *tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tf, static int srunner_run_unchecked_setup (SRunner * sr, TCase * tc);
int i); 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 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, static TestResult *tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tf,
int i); int i);
static TestResult *receive_result_info_fork (const char *tcname,
const char *tname, int iter, int status, int expected_signal);
static TestResult *receive_result_info_nofork (const char *tcname, static TestResult *receive_result_info_nofork (const char *tcname,
const char *tname, int iter); const char *tname, int iter);
static void set_fork_info (TestResult * tr, int status, int expected_signal);
static void set_nofork_info (TestResult * tr); static void set_nofork_info (TestResult * tr);
static char *pass_msg (void);
#ifdef _POSIX_VERSION
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);
static void set_fork_info (TestResult * tr, int status, int expected_signal,
unsigned char allowed_exit_value);
static char *signal_msg (int sig); static char *signal_msg (int sig);
static char *signal_error_msg (int signal_received, int signal_expected); static char *signal_error_msg (int signal_received, int signal_expected);
static char *pass_msg (void);
static char *exit_msg (int exitstatus); static char *exit_msg (int exitstatus);
static int waserror (int status, int expected_signal); static int waserror (int status, int expected_signal);
#define MSG_LEN 100
static int alarm_received; static int alarm_received;
static pid_t group_pid; static pid_t group_pid;
static void static void CK_ATTRIBUTE_UNUSED
sig_handler (int sig_nr) sig_handler (int sig_nr)
{ {
switch (sig_nr) { switch (sig_nr) {
@ -97,6 +100,9 @@ sig_handler (int sig_nr)
break; break;
} }
} }
#endif /* _POSIX_VERSION */
#define MSG_LEN 100
static void static void
srunner_run_init (SRunner * sr, enum print_output print_mode) srunner_run_init (SRunner * sr, enum print_output print_mode)
@ -108,7 +114,7 @@ srunner_run_init (SRunner * sr, enum print_output print_mode)
} }
static void static void
srunner_run_end (SRunner * sr, enum print_output print_mode) srunner_run_end (SRunner * sr, enum print_output CK_ATTRIBUTE_UNUSED print_mode)
{ {
log_srunner_end (sr); log_srunner_end (sr);
srunner_end_logging (sr); srunner_end_logging (sr);
@ -117,7 +123,8 @@ srunner_run_end (SRunner * sr, enum print_output print_mode)
} }
static void static void
srunner_iterate_suites (SRunner * sr, enum print_output print_mode) srunner_iterate_suites (SRunner * sr,
enum print_output CK_ATTRIBUTE_UNUSED print_mode)
{ {
List *slst; List *slst;
List *tcl; List *tcl;
@ -141,39 +148,6 @@ srunner_iterate_suites (SRunner * sr, enum print_output print_mode)
} }
} }
void
srunner_run_all (SRunner * sr, enum print_output print_mode)
{
struct sigaction old_action;
struct sigaction new_action;
if (sr == NULL)
return;
if (print_mode >= CK_LAST) {
eprintf ("Bad print_mode argument to srunner_run_all: %d",
__FILE__, __LINE__, print_mode);
}
memset (&new_action, 0, sizeof new_action);
new_action.sa_handler = sig_handler;
sigaction (SIGALRM, &new_action, &old_action);
srunner_run_init (sr, print_mode);
srunner_iterate_suites (sr, print_mode);
srunner_run_end (sr, print_mode);
sigaction (SIGALRM, &old_action, NULL);
}
static void
srunner_add_failure (SRunner * sr, TestResult * tr)
{
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++;
else if (tr->rtype == CK_ERROR)
sr->stats->n_errors++;
}
static void static void
srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc) srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc)
{ {
@ -188,9 +162,14 @@ srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc)
tfun = list_val (tfl); tfun = list_val (tfl);
for (i = tfun->loop_start; i < tfun->loop_end; i++) { for (i = tfun->loop_start; i < tfun->loop_end; i++) {
log_test_start (sr, tc, tfun);
switch (srunner_fork_status (sr)) { switch (srunner_fork_status (sr)) {
case CK_FORK: case CK_FORK:
#ifdef _POSIX_VERSION
tr = tcase_run_tfun_fork (sr, tc, tfun, i); tr = tcase_run_tfun_fork (sr, tc, tfun, i);
#else /* _POSIX_VERSION */
eprintf ("This version does not support fork", __FILE__, __LINE__);
#endif /* _POSIX_VERSION */
break; break;
case CK_NOFORK: case CK_NOFORK:
tr = tcase_run_tfun_nofork (sr, tc, tfun, i); tr = tcase_run_tfun_nofork (sr, tc, tfun, i);
@ -204,6 +183,18 @@ srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc)
} }
} }
static void
srunner_add_failure (SRunner * sr, TestResult * tr)
{
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++;
else if (tr->rtype == CK_ERROR)
sr->stats->n_errors++;
}
static int static int
srunner_run_unchecked_setup (SRunner * sr, TCase * tc) srunner_run_unchecked_setup (SRunner * sr, TCase * tc)
{ {
@ -275,37 +266,27 @@ tcase_run_checked_setup (SRunner * sr, TCase * tc)
} }
static void static void
tcase_run_checked_teardown (TCase * tc) srunner_run_teardown (List * l)
{ {
List *l;
Fixture *f; Fixture *f;
l = tc->ch_tflst;
send_ctx_info (CK_CTX_TEARDOWN);
for (list_front (l); !list_at_end (l); list_advance (l)) { for (list_front (l); !list_at_end (l); list_advance (l)) {
f = list_val (l); f = list_val (l);
send_ctx_info (CK_CTX_TEARDOWN);
f->fun (); f->fun ();
} }
} }
static void static void
srunner_run_unchecked_teardown (SRunner * sr, TCase * tc) srunner_run_unchecked_teardown (TCase * tc)
{ {
List *l; srunner_run_teardown (tc->unch_tflst);
Fixture *f; }
set_fork_status (CK_NOFORK); static void
l = tc->unch_tflst; tcase_run_checked_teardown (TCase * tc)
{
for (list_front (l); !list_at_end (l); list_advance (l)) { srunner_run_teardown (tc->ch_tflst);
f = list_val (l);
send_ctx_info (CK_CTX_TEARDOWN);
f->fun ();
}
set_fork_status (srunner_fork_status (sr));
} }
static void static void
@ -313,23 +294,21 @@ srunner_run_tcase (SRunner * sr, TCase * tc)
{ {
if (srunner_run_unchecked_setup (sr, tc)) { if (srunner_run_unchecked_setup (sr, tc)) {
srunner_iterate_tcase_tfuns (sr, tc); srunner_iterate_tcase_tfuns (sr, tc);
srunner_run_unchecked_teardown (sr, tc); srunner_run_unchecked_teardown (tc);
} }
} }
static TestResult * static TestResult *
receive_result_info_fork (const char *tcname, tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tfun, int i)
const char *tname, int iter, int status, int expected_signal)
{ {
TestResult *tr; TestResult *tr;
tr = receive_test_result (waserror (status, expected_signal)); tr = tcase_run_checked_setup (sr, tc);
if (tr == NULL) if (tr == NULL) {
eprintf ("Failed to receive test result", __FILE__, __LINE__); tfun->fn (i);
tr->tcname = tcname; tcase_run_checked_teardown (tc);
tr->tname = tname; return receive_result_info_nofork (tc->name, tfun->name, i);
tr->iter = iter; }
set_fork_info (tr, status, expected_signal);
return tr; return tr;
} }
@ -351,7 +330,79 @@ receive_result_info_nofork (const char *tcname, const char *tname, int iter)
} }
static void static void
set_fork_info (TestResult * tr, int status, int signal_expected) set_nofork_info (TestResult * tr)
{
if (tr->msg == NULL) {
tr->rtype = CK_PASS;
tr->msg = pass_msg ();
} else {
tr->rtype = CK_FAILURE;
}
}
static char *
pass_msg (void)
{
char *msg = emalloc (sizeof ("Passed"));
strcpy (msg, "Passed");
return msg;
}
#ifdef _POSIX_VERSION
static TestResult *
tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i)
{
pid_t pid_w;
pid_t pid;
int status = 0;
pid = fork ();
if (pid == -1)
eprintf ("Error in call to fork:", __FILE__, __LINE__ - 2);
if (pid == 0) {
setpgid (0, 0);
group_pid = getpgrp ();
tcase_run_checked_setup (sr, tc);
tfun->fn (i);
tcase_run_checked_teardown (tc);
exit (EXIT_SUCCESS);
} else {
group_pid = pid;
}
alarm_received = 0;
alarm (tc->timeout);
do {
pid_w = waitpid (pid, &status, 0);
} while (pid_w == -1);
killpg (pid, SIGKILL); /* Kill remaining processes. */
return receive_result_info_fork (tc->name, tfun->name, i, status,
tfun->signal, tfun->allowed_exit_value);
}
static TestResult *
receive_result_info_fork (const char *tcname,
const char *tname,
int iter, int status, int expected_signal, unsigned char allowed_exit_value)
{
TestResult *tr;
tr = receive_test_result (waserror (status, expected_signal));
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);
return tr;
}
static void
set_fork_info (TestResult * tr, int status, int signal_expected,
unsigned char allowed_exit_value)
{ {
int was_sig = WIFSIGNALED (status); int was_sig = WIFSIGNALED (status);
int was_exit = WIFEXITED (status); int was_exit = WIFEXITED (status);
@ -378,10 +429,10 @@ set_fork_info (TestResult * tr, int status, int signal_expected)
tr->msg = signal_msg (signal_received); tr->msg = signal_msg (signal_received);
} }
} else if (signal_expected == 0) { } else if (signal_expected == 0) {
if (was_exit && exit_status == 0) { if (was_exit && exit_status == allowed_exit_value) {
tr->rtype = CK_PASS; tr->rtype = CK_PASS;
tr->msg = pass_msg (); tr->msg = pass_msg ();
} else if (was_exit && exit_status != 0) { } else if (was_exit && exit_status != allowed_exit_value) {
if (tr->msg == NULL) { /* early exit */ if (tr->msg == NULL) { /* early exit */
tr->rtype = CK_ERROR; tr->rtype = CK_ERROR;
tr->msg = exit_msg (exit_status); tr->msg = exit_msg (exit_status);
@ -392,7 +443,7 @@ set_fork_info (TestResult * tr, int status, int signal_expected)
} else { /* a signal was expected and none raised */ } else { /* a signal was expected and none raised */
if (was_exit) { if (was_exit) {
tr->msg = exit_msg (exit_status); tr->msg = exit_msg (exit_status);
if (exit_status == 0) if (exit_status == allowed_exit_value)
tr->rtype = CK_FAILURE; /* normal exit status */ tr->rtype = CK_FAILURE; /* normal exit status */
else else
tr->rtype = CK_FAILURE; /* early exit */ tr->rtype = CK_FAILURE; /* early exit */
@ -400,63 +451,17 @@ set_fork_info (TestResult * tr, int status, int signal_expected)
} }
} }
static void static char *
set_nofork_info (TestResult * tr) signal_msg (int signal)
{ {
if (tr->msg == NULL) { char *msg = emalloc (MSG_LEN); /* free'd by caller */
tr->rtype = CK_PASS; if (alarm_received) {
tr->msg = pass_msg (); snprintf (msg, MSG_LEN, "Test timeout expired");
} else { } else {
tr->rtype = CK_FAILURE; snprintf (msg, MSG_LEN, "Received signal %d (%s)",
signal, strsignal (signal));
} }
} return msg;
static TestResult *
tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tfun, int i)
{
TestResult *tr;
tr = tcase_run_checked_setup (sr, tc);
if (tr == NULL) {
tfun->fn (i);
tcase_run_checked_teardown (tc);
return receive_result_info_nofork (tc->name, tfun->name, i);
}
return tr;
}
static TestResult *
tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i)
{
pid_t pid_w;
pid_t pid;
int status = 0;
pid = fork ();
if (pid == -1)
eprintf ("Error in call to fork:", __FILE__, __LINE__ - 2);
if (pid == 0) {
setpgid (0, 0);
group_pid = getpgrp ();
tcase_run_checked_setup (sr, tc);
tfun->fn (i);
tcase_run_checked_teardown (tc);
exit (EXIT_SUCCESS);
} else {
group_pid = pid;
}
alarm_received = 0;
alarm (tc->timeout);
do {
pid_w = waitpid (pid, &status, 0);
} while (pid_w == -1);
killpg (pid, SIGKILL); /* Kill remaining processes. */
return receive_result_info_fork (tc->name, tfun->name, i, status,
tfun->signal);
} }
static char * static char *
@ -479,19 +484,6 @@ signal_error_msg (int signal_received, int signal_expected)
return msg; return msg;
} }
static char *
signal_msg (int signal)
{
char *msg = emalloc (MSG_LEN); /* free'd by caller */
if (alarm_received) {
snprintf (msg, MSG_LEN, "Test timeout expired");
} else {
snprintf (msg, MSG_LEN, "Received signal %d (%s)",
signal, strsignal (signal));
}
return msg;
}
static char * static char *
exit_msg (int exitval) exit_msg (int exitval)
{ {
@ -500,60 +492,6 @@ exit_msg (int exitval)
return msg; return msg;
} }
static char *
pass_msg (void)
{
char *msg = emalloc (sizeof ("Passed"));
strcpy (msg, "Passed");
return msg;
}
enum fork_status
srunner_fork_status (SRunner * sr)
{
if (sr->fstat == CK_FORK_GETENV) {
char *env = getenv ("CK_FORK");
if (env == NULL)
return CK_FORK;
if (strcmp (env, "no") == 0)
return CK_NOFORK;
else
return CK_FORK;
} else
return sr->fstat;
}
void
srunner_set_fork_status (SRunner * sr, enum fork_status fstat)
{
sr->fstat = fstat;
}
pid_t
check_fork (void)
{
pid_t pid = fork ();
/* Set the process to a process group to be able to kill it easily. */
setpgid (pid, group_pid);
return pid;
}
void
check_waitpid_and_exit (pid_t pid)
{
pid_t pid_w;
int status;
if (pid > 0) {
do {
pid_w = waitpid (pid, &status, 0);
} while (pid_w == -1);
if (waserror (status, 0))
exit (EXIT_FAILURE);
}
exit (EXIT_SUCCESS);
}
static int static int
waserror (int status, int signal_expected) waserror (int status, int signal_expected)
{ {
@ -565,3 +503,93 @@ waserror (int status, int signal_expected)
return ((was_sig && (signal_received != signal_expected)) || return ((was_sig && (signal_received != signal_expected)) ||
(was_exit && exit_status != 0)); (was_exit && exit_status != 0));
} }
#endif /* _POSIX_VERSION */
enum fork_status
srunner_fork_status (SRunner * sr)
{
if (sr->fstat == CK_FORK_GETENV) {
char *env = getenv ("CK_FORK");
if (env == NULL)
return CK_FORK;
if (strcmp (env, "no") == 0)
return CK_NOFORK;
else {
#ifdef _POSIX_VERSION
return CK_FORK;
#else /* _POSIX_VERSION */
eprintf ("This version does not support fork", __FILE__, __LINE__);
return CK_NOFORK;
#endif /* _POSIX_VERSION */
}
} else
return sr->fstat;
}
void
srunner_set_fork_status (SRunner * sr, enum fork_status fstat)
{
sr->fstat = fstat;
}
void
srunner_run_all (SRunner * sr, enum print_output print_mode)
{
#ifdef _POSIX_VERSION
struct sigaction old_action;
struct sigaction new_action;
#endif /* _POSIX_VERSION */
if (sr == NULL)
return;
if (print_mode >= CK_LAST) {
eprintf ("Bad print_mode argument to srunner_run_all: %d",
__FILE__, __LINE__, print_mode);
}
#ifdef _POSIX_VERSION
memset (&new_action, 0, sizeof new_action);
new_action.sa_handler = sig_handler;
sigaction (SIGALRM, &new_action, &old_action);
#endif /* _POSIX_VERSION */
srunner_run_init (sr, print_mode);
srunner_iterate_suites (sr, print_mode);
srunner_run_end (sr, print_mode);
#ifdef _POSIX_VERSION
sigaction (SIGALRM, &old_action, NULL);
#endif /* _POSIX_VERSION */
}
pid_t
check_fork (void)
{
#ifdef _POSIX_VERSION
pid_t pid = fork ();
/* Set the process to a process group to be able to kill it easily. */
setpgid (pid, group_pid);
return pid;
#else /* _POSIX_VERSION */
eprintf ("This version does not support fork", __FILE__, __LINE__);
return 0;
#endif /* _POSIX_VERSION */
}
void
check_waitpid_and_exit (pid_t pid CK_ATTRIBUTE_UNUSED)
{
#ifdef _POSIX_VERSION
pid_t pid_w;
int status;
if (pid > 0) {
do {
pid_w = waitpid (pid, &status, 0);
} while (pid_w == -1);
if (waserror (status, 0)) {
exit (EXIT_FAILURE);
}
}
exit (EXIT_SUCCESS);
#else /* _POSIX_VERSION */
eprintf ("This version does not support fork", __FILE__, __LINE__);
#endif /* _POSIX_VERSION */
}

View file

@ -18,7 +18,7 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#include "config.h" #include "../lib/libcompat.h"
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
@ -47,6 +47,20 @@ tr_str (TestResult * tr)
return rstr; return rstr;
} }
char *
tr_short_str (TestResult * tr)
{
const char *exact_msg;
char *rstr;
exact_msg = (tr->rtype == CK_ERROR) ? "(after this point) " : "";
rstr = ck_strdup_printf ("%s:%d: %s%s",
tr->file, tr->line, exact_msg, tr->msg);
return rstr;
}
char * char *
sr_stat_str (SRunner * sr) sr_stat_str (SRunner * sr)
{ {

View file

@ -25,6 +25,12 @@
value has been malloc'd, and must be freed by the caller */ 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);
/* Return a string representation of the given SRunner's run /* Return a string representation of the given SRunner's run
statistics (% passed, num run, passed, errors, failures). Return statistics (% passed, num run, passed, errors, failures). Return
value has been malloc'd, and must be freed by the caller value has been malloc'd, and must be freed by the caller