2 * Check: a unit test framework for C
3 * Copyright (C) 2001, 2002 Arien Malec
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
21 #include "libcompat.h"
23 #include <sys/types.h>
32 #include "internal-check.h"
33 #include "check_error.h"
34 #include "check_list.h"
35 #include "check_impl.h"
36 #include "check_msg.h"
37 #include "check_log.h"
56 /* all functions are defined in the same order they are declared.
57 functions that depend on forking are gathered all together.
58 non-static functions are at the end of the file. */
59 static void srunner_run_init (SRunner * sr, enum print_output print_mode);
60 static void srunner_run_end (SRunner * sr, enum print_output print_mode);
61 static void srunner_iterate_suites (SRunner * sr,
62 const char *sname, const char *tcname, enum print_output print_mode);
63 static void srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc);
64 static void srunner_add_failure (SRunner * sr, TestResult * tf);
65 static TestResult *srunner_run_setup (List * func_list,
66 enum fork_status fork_usage, const char *test_name, const char *setup_name);
67 static int srunner_run_unchecked_setup (SRunner * sr, TCase * tc);
68 static TestResult *tcase_run_checked_setup (SRunner * sr, TCase * tc);
69 static void srunner_run_teardown (List * fixture_list,
70 enum fork_status fork_usage);
71 static void srunner_run_unchecked_teardown (SRunner * sr, TCase * tc);
72 static void tcase_run_checked_teardown (TCase * tc);
73 static void srunner_run_tcase (SRunner * sr, TCase * tc);
74 static TestResult *tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tf,
76 static TestResult *receive_result_info_nofork (const char *tcname,
77 const char *tname, int iter, int duration);
78 static void set_nofork_info (TestResult * tr);
79 static char *pass_msg (void);
81 #if defined(HAVE_FORK) && HAVE_FORK==1
82 static TestResult *tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tf,
84 static TestResult *receive_result_info_fork (const char *tcname,
85 const char *tname, int iter,
86 int status, int expected_signal, signed char allowed_exit_value);
87 static void set_fork_info (TestResult * tr, int status, int expected_signal,
88 signed char allowed_exit_value);
89 static char *signal_msg (int sig);
90 static char *signal_error_msg (int signal_received, int signal_expected);
91 static char *exit_msg (int exitstatus);
92 static int waserror (int status, int expected_signal);
94 static int alarm_received;
95 static pid_t group_pid;
97 #if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
98 static struct sigaction old_action[3];
99 static struct sigaction new_action[3];
100 #endif /* HAVE_SIGACTION && HAVE_FORK */
102 static void CK_ATTRIBUTE_UNUSED
103 sig_handler (int sig_nr)
108 killpg (group_pid, SIGKILL);
116 if (sig_nr == SIGINT) {
119 } else { /* if (sig_nr == SIGTERM) */
125 killpg (group_pid, child_sig);
127 /* Restore old signal handler... */
128 sigaction (sig_nr, &old_action[idx], NULL);
130 /* ... and call it. POSIX says that calling killpg(0)
131 * does not necessarily mean to call it on the callers
133 own_group_pid = getpgrp ();
134 killpg (own_group_pid, sig_nr);
138 eprintf ("Unhandled signal: %d", __FILE__, __LINE__, sig_nr);
142 #endif /* HAVE_FORK */
147 srunner_run_init (SRunner * sr, enum print_output print_mode)
149 set_fork_status (srunner_fork_status (sr));
151 srunner_init_logging (sr, print_mode);
152 log_srunner_start (sr);
156 srunner_run_end (SRunner * sr, enum print_output CK_ATTRIBUTE_UNUSED print_mode)
158 log_srunner_end (sr);
159 srunner_end_logging (sr);
160 teardown_messaging ();
161 set_fork_status (CK_FORK);
165 srunner_iterate_suites (SRunner * sr,
166 const char *sname, const char *tcname,
167 enum print_output CK_ATTRIBUTE_UNUSED print_mode)
175 for (check_list_front (slst); !check_list_at_end (slst);
176 check_list_advance (slst)) {
177 Suite *s = (Suite *) check_list_val (slst);
179 if (((sname != NULL) && (strcmp (sname, s->name) != 0))
180 || ((tcname != NULL) && (!suite_tcase (s, tcname))))
183 log_suite_start (sr, s);
187 for (check_list_front (tcl); !check_list_at_end (tcl);
188 check_list_advance (tcl)) {
189 tc = (TCase *) check_list_val (tcl);
191 if ((tcname != NULL) && (strcmp (tcname, tc->name) != 0)) {
195 srunner_run_tcase (sr, tc);
198 log_suite_end (sr, s);
203 srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc)
207 TestResult *tr = NULL;
211 for (check_list_front (tfl); !check_list_at_end (tfl);
212 check_list_advance (tfl)) {
215 tfun = (TF *) check_list_val (tfl);
217 for (i = tfun->loop_start; i < tfun->loop_end; i++) {
218 log_test_start (sr, tc, tfun);
219 switch (srunner_fork_status (sr)) {
221 #if defined(HAVE_FORK) && HAVE_FORK==1
222 tr = tcase_run_tfun_fork (sr, tc, tfun, i);
223 #else /* HAVE_FORK */
224 eprintf ("This version does not support fork", __FILE__, __LINE__);
225 #endif /* HAVE_FORK */
228 tr = tcase_run_tfun_nofork (sr, tc, tfun, i);
232 eprintf ("Bad fork status in SRunner", __FILE__, __LINE__);
236 srunner_add_failure (sr, tr);
237 log_test_end (sr, tr);
244 srunner_add_failure (SRunner * sr, TestResult * tr)
246 check_list_add_end (sr->resultlst, tr);
247 sr->stats->n_checked++; /* count checks during setup, test, and teardown */
248 if (tr->rtype == CK_FAILURE)
249 sr->stats->n_failed++;
250 else if (tr->rtype == CK_ERROR)
251 sr->stats->n_errors++;
256 srunner_run_setup (List * fixture_list, enum fork_status fork_usage,
257 const char *test_name, const char *setup_name)
259 TestResult *tr = NULL;
260 Fixture *setup_fixture;
262 if (fork_usage == CK_FORK) {
263 send_ctx_info (CK_CTX_SETUP);
266 for (check_list_front (fixture_list); !check_list_at_end (fixture_list);
267 check_list_advance (fixture_list)) {
268 setup_fixture = (Fixture *) check_list_val (fixture_list);
270 if (fork_usage == CK_NOFORK) {
271 send_ctx_info (CK_CTX_SETUP);
273 if (0 == setjmp (error_jmp_buffer)) {
274 setup_fixture->fun ();
277 /* Stop the setup and return the failure in nofork mode. */
278 tr = receive_result_info_nofork (test_name, setup_name, 0, -1);
279 if (tr->rtype != CK_PASS) {
288 setup_fixture->fun ();
296 srunner_run_unchecked_setup (SRunner * sr, TCase * tc)
298 TestResult *tr = NULL;
301 set_fork_status (CK_NOFORK);
302 tr = srunner_run_setup (tc->unch_sflst, CK_NOFORK, tc->name,
304 set_fork_status (srunner_fork_status (sr));
306 if (tr != NULL && tr->rtype != CK_PASS) {
307 srunner_add_failure (sr, tr);
315 tcase_run_checked_setup (SRunner * sr, TCase * tc)
317 TestResult *tr = srunner_run_setup (tc->ch_sflst, srunner_fork_status (sr),
318 tc->name, "checked_setup");
324 srunner_run_teardown (List * fixture_list, enum fork_status fork_usage)
328 for (check_list_front (fixture_list); !check_list_at_end (fixture_list);
329 check_list_advance (fixture_list)) {
330 fixture = (Fixture *) check_list_val (fixture_list);
331 send_ctx_info (CK_CTX_TEARDOWN);
333 if (fork_usage == CK_NOFORK) {
334 if (0 == setjmp (error_jmp_buffer)) {
337 /* Abort the remaining teardowns */
347 srunner_run_unchecked_teardown (SRunner * sr, TCase * tc)
349 srunner_run_teardown (tc->unch_tflst, srunner_fork_status (sr));
353 tcase_run_checked_teardown (TCase * tc)
355 srunner_run_teardown (tc->ch_tflst, CK_NOFORK);
359 srunner_run_tcase (SRunner * sr, TCase * tc)
361 if (srunner_run_unchecked_setup (sr, tc)) {
362 srunner_iterate_tcase_tfuns (sr, tc);
363 srunner_run_unchecked_teardown (sr, tc);
368 tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tfun, int i)
371 struct timespec ts_start = { 0, 0 }, ts_end = {
374 tr = tcase_run_checked_setup (sr, tc);
376 clock_gettime (check_get_clockid (), &ts_start);
377 if (0 == setjmp (error_jmp_buffer)) {
380 clock_gettime (check_get_clockid (), &ts_end);
381 tcase_run_checked_teardown (tc);
382 return receive_result_info_nofork (tc->name, tfun->name, i,
383 DIFF_IN_USEC (ts_start, ts_end));
390 receive_result_info_nofork (const char *tcname,
391 const char *tname, int iter, int duration)
395 tr = receive_test_result (0);
397 eprintf ("Failed to receive test result", __FILE__, __LINE__);
402 tr->duration = duration;
403 set_nofork_info (tr);
410 set_nofork_info (TestResult * tr)
412 if (tr->msg == NULL) {
414 tr->msg = pass_msg ();
416 tr->rtype = CK_FAILURE;
423 return strdup ("Passed");
426 #if defined(HAVE_FORK) && HAVE_FORK==1
428 tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i)
433 struct timespec ts_start = { 0, 0 }, ts_end = {
437 struct itimerspec timer_spec;
443 eprintf ("Error in call to fork:", __FILE__, __LINE__ - 2);
446 group_pid = getpgrp ();
447 tr = tcase_run_checked_setup (sr, tc);
449 clock_gettime (check_get_clockid (), &ts_start);
451 clock_gettime (check_get_clockid (), &ts_end);
452 tcase_run_checked_teardown (tc);
453 send_duration_info (DIFF_IN_USEC (ts_start, ts_end));
461 if (timer_create (check_get_clockid (),
462 NULL /* fire SIGALRM if timer expires */ ,
464 /* Set the timer to fire once */
465 timer_spec.it_value = tc->timeout;
466 timer_spec.it_interval.tv_sec = 0;
467 timer_spec.it_interval.tv_nsec = 0;
468 if (timer_settime (timerid, 0, &timer_spec, NULL) == 0) {
470 pid_w = waitpid (pid, &status, 0);
474 eprintf ("Error in call to timer_settime:", __FILE__, __LINE__);
477 /* If the timer has not fired, disable it */
478 timer_delete (timerid);
480 eprintf ("Error in call to timer_create:", __FILE__, __LINE__);
483 killpg (pid, SIGKILL); /* Kill remaining processes. */
485 return receive_result_info_fork (tc->name, tfun->name, i, status,
486 tfun->signal, tfun->allowed_exit_value);
490 receive_result_info_fork (const char *tcname,
492 int iter, int status, int expected_signal, signed char allowed_exit_value)
496 tr = receive_test_result (waserror (status, expected_signal));
498 eprintf ("Failed to receive test result", __FILE__, __LINE__);
503 set_fork_info (tr, status, expected_signal, allowed_exit_value);
510 set_fork_info (TestResult * tr, int status, int signal_expected,
511 signed char allowed_exit_value)
513 int was_sig = WIFSIGNALED (status);
514 int was_exit = WIFEXITED (status);
515 signed char exit_status = WEXITSTATUS (status);
516 int signal_received = WTERMSIG (status);
519 if (signal_expected == signal_received) {
520 if (alarm_received) {
521 /* Got alarm instead of signal */
522 tr->rtype = CK_ERROR;
523 if (tr->msg != NULL) {
526 tr->msg = signal_error_msg (signal_received, signal_expected);
529 if (tr->msg != NULL) {
532 tr->msg = pass_msg ();
534 } else if (signal_expected != 0) {
535 /* signal received, but not the expected one */
536 tr->rtype = CK_ERROR;
537 if (tr->msg != NULL) {
540 tr->msg = signal_error_msg (signal_received, signal_expected);
542 /* signal received and none expected */
543 tr->rtype = CK_ERROR;
544 if (tr->msg != NULL) {
547 tr->msg = signal_msg (signal_received);
549 } else if (signal_expected == 0) {
550 if (was_exit && exit_status == allowed_exit_value) {
552 if (tr->msg != NULL) {
555 tr->msg = pass_msg ();
556 } else if (was_exit && exit_status != allowed_exit_value) {
557 if (tr->msg == NULL) { /* early exit */
558 tr->rtype = CK_ERROR;
559 tr->msg = exit_msg (exit_status);
561 tr->rtype = CK_FAILURE;
564 } else { /* a signal was expected and none raised */
566 if (tr->msg != NULL) {
569 tr->msg = exit_msg (exit_status);
570 tr->rtype = CK_FAILURE; /* normal exit status */
576 signal_msg (int signal)
578 char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
580 if (alarm_received) {
581 snprintf (msg, MSG_LEN, "Test timeout expired");
583 snprintf (msg, MSG_LEN, "Received signal %d (%s)",
584 signal, strsignal (signal));
590 signal_error_msg (int signal_received, int signal_expected)
594 char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
596 sig_r_str = strdup (strsignal (signal_received));
597 sig_e_str = strdup (strsignal (signal_expected));
598 if (alarm_received) {
599 snprintf (msg, MSG_LEN,
600 "Test timeout expired, expected signal %d (%s)",
601 signal_expected, sig_e_str);
603 snprintf (msg, MSG_LEN, "Received signal %d (%s), expected %d (%s)",
604 signal_received, sig_r_str, signal_expected, sig_e_str);
612 exit_msg (int exitval)
614 char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
616 snprintf (msg, MSG_LEN, "Early exit with return value %d", exitval);
621 waserror (int status, int signal_expected)
623 int was_sig = WIFSIGNALED (status);
624 int was_exit = WIFEXITED (status);
625 int exit_status = WEXITSTATUS (status);
626 int signal_received = WTERMSIG (status);
628 return ((was_sig && (signal_received != signal_expected)) ||
629 (was_exit && exit_status != 0));
631 #endif /* HAVE_FORK */
634 srunner_fork_status (SRunner * sr)
636 if (sr->fstat == CK_FORK_GETENV) {
637 char *env = getenv ("CK_FORK");
640 #if defined(HAVE_FORK) && HAVE_FORK==1
645 if (strcmp (env, "no") == 0)
648 #if defined(HAVE_FORK) && HAVE_FORK==1
650 #else /* HAVE_FORK */
651 eprintf ("This version does not support fork", __FILE__, __LINE__);
653 #endif /* HAVE_FORK */
660 srunner_set_fork_status (SRunner * sr, enum fork_status fstat)
662 #if !defined(HAVE_FORK) || HAVE_FORK==0
663 /* If fork() is unavailable, do not allow a fork mode to be set */
664 if (fstat != CK_NOFORK) {
665 eprintf ("This version does not support fork", __FILE__, __LINE__);
667 #endif /* ! HAVE_FORK */
672 srunner_run_all (SRunner * sr, enum print_output print_mode)
674 srunner_run (sr, NULL, /* All test suites. */
675 NULL, /* All test cases. */
680 srunner_run (SRunner * sr, const char *sname, const char *tcname,
681 enum print_output print_mode)
683 /* Get the selected test suite and test case from the
686 tcname = getenv ("CK_RUN_CASE");
688 sname = getenv ("CK_RUN_SUITE");
692 if (print_mode >= CK_LAST) {
693 eprintf ("Bad print_mode argument to srunner_run_all: %d",
694 __FILE__, __LINE__, print_mode);
696 #if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
697 memset (&new_action, 0, sizeof new_action);
698 new_action[0].sa_handler = sig_handler;
699 sigaction (SIGALRM, &new_action[0], &old_action[0]);
700 new_action[1].sa_handler = sig_handler;
701 sigaction (SIGINT, &new_action[1], &old_action[1]);
702 new_action[2].sa_handler = sig_handler;
703 sigaction (SIGTERM, &new_action[2], &old_action[2]);
704 #endif /* HAVE_SIGACTION && HAVE_FORK */
705 srunner_run_init (sr, print_mode);
706 srunner_iterate_suites (sr, sname, tcname, print_mode);
707 srunner_run_end (sr, print_mode);
708 #if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
709 sigaction (SIGALRM, &old_action[0], NULL);
710 sigaction (SIGINT, &old_action[1], NULL);
711 sigaction (SIGTERM, &old_action[2], NULL);
712 #endif /* HAVE_SIGACTION && HAVE_FORK */
718 #if defined(HAVE_FORK) && HAVE_FORK==1
721 /* Set the process to a process group to be able to kill it easily. */
723 setpgid (pid, group_pid);
726 #else /* HAVE_FORK */
727 eprintf ("This version does not support fork", __FILE__, __LINE__);
729 #endif /* HAVE_FORK */
733 check_waitpid_and_exit (pid_t pid CK_ATTRIBUTE_UNUSED)
735 #if defined(HAVE_FORK) && HAVE_FORK==1
741 pid_w = waitpid (pid, &status, 0);
744 if (waserror (status, 0)) {
749 #else /* HAVE_FORK */
750 eprintf ("This version does not support fork", __FILE__, __LINE__);
751 #endif /* HAVE_FORK */