From 382767f5c80bb3f0ffd2a65535db40e4fb9439c4 Mon Sep 17 00:00:00 2001 From: hugo303 Date: Mon, 8 Nov 2004 14:40:05 +0000 Subject: [PATCH] Added support for testing on expected signals. git-svn-id: svn+ssh://svn.code.sf.net/p/check/code/trunk@196 64e312b2-a51f-0410-8e61-82d0ca0eb02a --- check/ChangeLog | 8 ++++ check/src/check.c | 3 +- check/src/check.h.in | 10 +++-- check/src/check_impl.h | 1 + check/src/check_run.c | 84 ++++++++++++++++++++++++++++-------------- 5 files changed, 75 insertions(+), 31 deletions(-) diff --git a/check/ChangeLog b/check/ChangeLog index 6f9a66c..09c26c3 100644 --- a/check/ChangeLog +++ b/check/ChangeLog @@ -1,3 +1,11 @@ +2004-11-08 hugo303 + + * src/check.c, src/check.h.in, src/check_impl.h, src/check_run.c, + tests/check_check_master.c, tests/check_check_sub.c: + Added support for testing on expected signals. Implementation + courtesy of Lucas Di Pentima and Cesar Ballardini. Also cleaned + up the test verification to simplify merging of new tests. + 2004-11-04 hugo303 * src/check.c, src/check_list.c, src/check_list.h, src/check_log.c, diff --git a/check/src/check.c b/check/src/check.c index 57939c7..ade673d 100644 --- a/check/src/check.c +++ b/check/src/check.c @@ -108,13 +108,14 @@ void suite_add_tcase (Suite *s, TCase *tc) list_add_end (s->tclst, tc); } -void _tcase_add_test (TCase *tc, TFun fn, const char *name) +void _tcase_add_test (TCase *tc, TFun fn, const char *name, int signal) { TF * tf; if (tc == NULL || fn == NULL || name == NULL) return; tf = emalloc (sizeof(TF)); /* freed in tcase_free */ tf->fn = fn; + tf->signal = signal; /* 0 means no signal expected */ tf->name = name; list_add_end (tc->tflst, tf); } diff --git a/check/src/check.h.in b/check/src/check.h.in index 07c893b..d96091b 100644 --- a/check/src/check.h.in +++ b/check/src/check.h.in @@ -101,11 +101,14 @@ TCase *tcase_create (const char *name); /* Add a test function to a test case (macro version) */ -#define tcase_add_test(tc,tf) _tcase_add_test(tc,tf,"" # tf "") +#define tcase_add_test(tc,tf) tcase_add_test_raise_signal(tc,tf,0) + +#define tcase_add_test_raise_signal(tc,tf,signal) \ + _tcase_add_test((tc),(tf),"" # tf "",(signal)) /* Add a test function to a test case (function version -- use this when the macro won't work */ -void _tcase_add_test (TCase *tc, TFun tf, const char *fname); +void _tcase_add_test (TCase *tc, TFun tf, const char *fname, int signal); /* Add unchecked fixture setup/teardown functions to a test case @@ -183,7 +186,8 @@ void _mark_point (const char *file, int line); enum test_result { CK_PASS, /* Test passed*/ CK_FAILURE, /* Test completed but failed */ - CK_ERROR /* Test failed to complete (signal or non-zero early exit) */ + CK_ERROR /* Test failed to complete + (unexpected signal or non-zero early exit) */ }; /* Specifies the how much output an SRunner should produce */ diff --git a/check/src/check_impl.h b/check/src/check_impl.h index 9f19c09..6cab655 100644 --- a/check/src/check_impl.h +++ b/check/src/check_impl.h @@ -36,6 +36,7 @@ typedef struct TF { TFun fn; const char *name; + int signal; } TF; struct Suite { diff --git a/check/src/check_run.c b/check/src/check_run.c index 31ca4ee..f49eb39 100644 --- a/check/src/check_run.c +++ b/check/src/check_run.c @@ -64,15 +64,17 @@ static void srunner_add_failure (SRunner *sr, TestResult *tf); static TestResult *tcase_run_tfun_fork (SRunner *sr, TCase *tc, TF *tf); static TestResult *tcase_run_tfun_nofork (SRunner *sr, TCase *tc, TF *tf); static TestResult *receive_result_info_fork (const char *tcname, - const char *tname, int status); + const char *tname, + int status, int expected_signal); static TestResult *receive_result_info_nofork (const char *tcname, const char *tname); -static void set_fork_info (TestResult *tr, int status); +static void set_fork_info (TestResult *tr, int status, int expected_signal); static void set_nofork_info (TestResult *tr); static char *signal_msg (int sig); +static char *signal_error_msg (int signal_received, int signal_expected); static char *pass_msg (void); static char *exit_msg (int exitstatus); -static int waserror (int status); +static int waserror (int status, int expected_signal); #define MSG_LEN 100 @@ -271,26 +273,25 @@ static void srunner_run_unchecked_teardown (SRunner *sr, TCase *tc) static void 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_run_unchecked_teardown (sr, tc); + srunner_run_unchecked_teardown(sr, tc); } } static TestResult *receive_result_info_fork (const char *tcname, - const char *tname, int status) + const char *tname, + int status, int expected_signal) { TestResult *tr; - tr = receive_test_result (get_recv_key(), waserror(status)); + tr = receive_test_result(get_recv_key(), + waserror(status, expected_signal)); if (tr == NULL) eprintf("Failed to receive test result", __FILE__, __LINE__); tr->tcname = tcname; tr->tname = tname; - set_fork_info(tr, status); + set_fork_info(tr, status, expected_signal); return tr; } @@ -310,24 +311,43 @@ static TestResult *receive_result_info_nofork (const char *tcname, return tr; } -static void set_fork_info (TestResult *tr, int status) +static void set_fork_info (TestResult *tr, int status, int signal_expected) { int was_sig = WIFSIGNALED(status); int was_exit = WIFEXITED(status); int exit_status = WEXITSTATUS(status); + int signal_received = WTERMSIG(status); if (was_sig) { - tr->rtype = CK_ERROR; - tr->msg = signal_msg(WTERMSIG(status)); - } else if (was_exit && exit_status == 0) { - tr->rtype = CK_PASS; - tr->msg = pass_msg(); - } else if (was_exit && exit_status != 0) { - if (tr->msg == NULL) { /* early exit */ + if (signal_expected == signal_received) { + tr->rtype = CK_PASS; + tr->msg = pass_msg(); + } else if (signal_expected != 0) { /* signal received, but no the expected one */ + tr->rtype = CK_ERROR; + tr->msg = signal_error_msg(signal_received, signal_expected); + } else { /* signal received and none expected */ tr->rtype = CK_ERROR; + tr->msg = signal_msg(signal_received); + } + } else if (signal_expected == 0) { + if (was_exit && exit_status == 0) { + tr->rtype = CK_PASS; + tr->msg = pass_msg(); + } else if (was_exit && exit_status != 0) { + if (tr->msg == NULL) { /* early exit */ + tr->rtype = CK_ERROR; + tr->msg = exit_msg(exit_status); + } else { + tr->rtype = CK_FAILURE; + } + } + } else { /* a signal was expected and none raised */ + if (was_exit) { tr->msg = exit_msg(exit_status); - } else { - tr->rtype = CK_FAILURE; + if (exit_status == 0) + tr->rtype = CK_FAILURE; /* normal exit status */ + else + tr->rtype = CK_FAILURE; /* early exit */ } } } @@ -364,15 +384,23 @@ static TestResult *tcase_run_tfun_fork (SRunner *sr, TCase *tc, TF *tfun) pid = fork(); if (pid == -1) - eprintf ("Unable to fork:",__FILE__,__LINE__); + eprintf("Unable to fork:",__FILE__,__LINE__); if (pid == 0) { - tcase_run_checked_setup (sr, tc); + tcase_run_checked_setup(sr, tc); tfun->fn(); - tcase_run_checked_teardown (tc); + tcase_run_checked_teardown(tc); exit(EXIT_SUCCESS); } (void) wait(&status); - return receive_result_info_fork (tc->name, tfun->name, status); + return receive_result_info_fork(tc->name, tfun->name, status, tfun->signal); +} + +static char *signal_error_msg (int signal_received, int signal_expected) +{ + char *msg = emalloc (MSG_LEN); /* free'd by caller */ + snprintf (msg, MSG_LEN, "Error: Received signal %d, expected %d", + signal_received, signal_expected); + return msg; } static char *signal_msg (int signal) @@ -416,11 +444,13 @@ void srunner_set_fork_status (SRunner *sr, enum fork_status fstat) sr->fstat = fstat; } -static int waserror (int status) +static int waserror (int status, int signal_expected) { int was_sig = WIFSIGNALED (status); int was_exit = WIFEXITED (status); int exit_status = WEXITSTATUS (status); + int signal_received = WTERMSIG(status); - return (was_sig || (was_exit && exit_status != 0)); + return ((was_sig && (signal_received != signal_expected)) || + (was_exit && exit_status != 0)); } -- 2.40.0