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, Boston,
21 #include "libcompat/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,
63 const char *include_tags,
64 const char *exclude_tags, enum print_output print_mode);
65 static void srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc);
66 static void srunner_add_failure (SRunner * sr, TestResult * tf);
67 static TestResult *srunner_run_setup (List * func_list,
68 enum fork_status fork_usage, const char *test_name, const char *setup_name);
69 static int srunner_run_unchecked_setup (SRunner * sr, TCase * tc);
70 static TestResult *tcase_run_checked_setup (SRunner * sr, TCase * tc);
71 static void srunner_run_teardown (List * fixture_list,
72 enum fork_status fork_usage);
73 static void srunner_run_unchecked_teardown (SRunner * sr, TCase * tc);
74 static void tcase_run_checked_teardown (TCase * tc);
75 static void srunner_run_tcase (SRunner * sr, TCase * tc);
76 static TestResult *tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tf,
78 static TestResult *receive_result_info_nofork (const char *tcname,
79 const char *tname, int iter, int duration);
80 static void set_nofork_info (TestResult * tr);
81 static char *pass_msg (void);
83 #if defined(HAVE_FORK) && HAVE_FORK==1
84 static TestResult *tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tf,
86 static TestResult *receive_result_info_fork (const char *tcname,
87 const char *tname, int iter,
88 int status, int expected_signal, signed char allowed_exit_value);
89 static void set_fork_info (TestResult * tr, int status, int expected_signal,
90 signed char allowed_exit_value);
91 static char *signal_msg (int sig);
92 static char *signal_error_msg (int signal_received, int signal_expected);
93 static char *exit_msg (int exitstatus);
94 static int waserror (int status, int expected_signal);
96 static int alarm_received;
97 static pid_t group_pid;
98 static struct sigaction sigint_old_action;
99 static struct sigaction sigterm_old_action;
101 static void CK_ATTRIBUTE_UNUSED
102 sig_handler (int sig_nr)
107 killpg (group_pid, SIGKILL);
113 int child_sig = SIGTERM;
115 if (sig_nr == SIGINT) {
117 sigaction (SIGINT, &sigint_old_action, NULL);
119 sigaction (SIGTERM, &sigterm_old_action, NULL);
122 killpg (group_pid, child_sig);
124 /* POSIX says that calling killpg(0)
125 * does not necessarily mean to call it on the callers
127 own_group_pid = getpgrp ();
128 killpg (own_group_pid, sig_nr);
132 eprintf ("Unhandled signal: %d", __FILE__, __LINE__, sig_nr);
136 #endif /* HAVE_FORK */
141 srunner_run_init (SRunner * sr, enum print_output print_mode)
143 set_fork_status (srunner_fork_status (sr));
145 srunner_init_logging (sr, print_mode);
146 log_srunner_start (sr);
150 srunner_run_end (SRunner * sr, enum print_output CK_ATTRIBUTE_UNUSED print_mode)
152 log_srunner_end (sr);
153 srunner_end_logging (sr);
154 teardown_messaging ();
155 set_fork_status (CK_FORK);
159 srunner_iterate_suites (SRunner * sr,
160 const char *sname, const char *tcname,
161 const char *include_tags,
162 const char *exclude_tags, enum print_output CK_ATTRIBUTE_UNUSED print_mode)
164 List *include_tag_lst;
165 List *exclude_tag_lst;
172 include_tag_lst = tag_string_to_list (include_tags);
173 exclude_tag_lst = tag_string_to_list (exclude_tags);
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)) {
194 if (include_tags != NULL) {
195 if (!tcase_matching_tag (tc, include_tag_lst)) {
199 if (exclude_tags != NULL) {
200 if (tcase_matching_tag (tc, exclude_tag_lst)) {
205 srunner_run_tcase (sr, tc);
208 log_suite_end (sr, s);
211 check_list_apply (include_tag_lst, free);
212 check_list_apply (exclude_tag_lst, free);
213 check_list_free (include_tag_lst);
214 check_list_free (exclude_tag_lst);
218 srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc)
222 TestResult *tr = NULL;
226 for (check_list_front (tfl); !check_list_at_end (tfl);
227 check_list_advance (tfl)) {
230 tfun = (TF *) check_list_val (tfl);
232 for (i = tfun->loop_start; i < tfun->loop_end; i++) {
233 log_test_start (sr, tc, tfun);
234 switch (srunner_fork_status (sr)) {
236 #if defined(HAVE_FORK) && HAVE_FORK==1
237 tr = tcase_run_tfun_fork (sr, tc, tfun, i);
238 #else /* HAVE_FORK */
239 eprintf ("This version does not support fork", __FILE__, __LINE__);
240 #endif /* HAVE_FORK */
243 tr = tcase_run_tfun_nofork (sr, tc, tfun, i);
247 eprintf ("Bad fork status in SRunner", __FILE__, __LINE__);
251 srunner_add_failure (sr, tr);
252 log_test_end (sr, tr);
259 srunner_add_failure (SRunner * sr, TestResult * tr)
261 check_list_add_end (sr->resultlst, tr);
262 sr->stats->n_checked++; /* count checks during setup, test, and teardown */
263 if (tr->rtype == CK_FAILURE)
264 sr->stats->n_failed++;
265 else if (tr->rtype == CK_ERROR)
266 sr->stats->n_errors++;
271 srunner_run_setup (List * fixture_list, enum fork_status fork_usage,
272 const char *test_name, const char *setup_name)
274 TestResult *tr = NULL;
275 Fixture *setup_fixture;
277 if (fork_usage == CK_FORK) {
278 send_ctx_info (CK_CTX_SETUP);
281 for (check_list_front (fixture_list); !check_list_at_end (fixture_list);
282 check_list_advance (fixture_list)) {
283 setup_fixture = (Fixture *) check_list_val (fixture_list);
285 if (fork_usage == CK_NOFORK) {
286 send_ctx_info (CK_CTX_SETUP);
288 if (0 == setjmp (error_jmp_buffer)) {
289 setup_fixture->fun ();
292 /* Stop the setup and return the failure in nofork mode. */
293 tr = receive_result_info_nofork (test_name, setup_name, 0, -1);
294 if (tr->rtype != CK_PASS) {
303 setup_fixture->fun ();
311 srunner_run_unchecked_setup (SRunner * sr, TCase * tc)
313 TestResult *tr = NULL;
316 set_fork_status (CK_NOFORK);
317 tr = srunner_run_setup (tc->unch_sflst, CK_NOFORK, tc->name,
319 set_fork_status (srunner_fork_status (sr));
321 if (tr != NULL && tr->rtype != CK_PASS) {
322 srunner_add_failure (sr, tr);
330 tcase_run_checked_setup (SRunner * sr, TCase * tc)
332 TestResult *tr = srunner_run_setup (tc->ch_sflst, srunner_fork_status (sr),
333 tc->name, "checked_setup");
339 srunner_run_teardown (List * fixture_list, enum fork_status fork_usage)
343 for (check_list_front (fixture_list); !check_list_at_end (fixture_list);
344 check_list_advance (fixture_list)) {
345 fixture = (Fixture *) check_list_val (fixture_list);
346 send_ctx_info (CK_CTX_TEARDOWN);
348 if (fork_usage == CK_NOFORK) {
349 if (0 == setjmp (error_jmp_buffer)) {
352 /* Abort the remaining teardowns */
362 srunner_run_unchecked_teardown (SRunner * sr, TCase * tc)
364 srunner_run_teardown (tc->unch_tflst, srunner_fork_status (sr));
368 tcase_run_checked_teardown (TCase * tc)
370 srunner_run_teardown (tc->ch_tflst, CK_NOFORK);
374 srunner_run_tcase (SRunner * sr, TCase * tc)
376 if (srunner_run_unchecked_setup (sr, tc)) {
377 srunner_iterate_tcase_tfuns (sr, tc);
378 srunner_run_unchecked_teardown (sr, tc);
383 tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tfun, int i)
386 struct timespec ts_start = { 0, 0 }, ts_end = {
389 tr = tcase_run_checked_setup (sr, tc);
391 clock_gettime (check_get_clockid (), &ts_start);
392 if (0 == setjmp (error_jmp_buffer)) {
395 clock_gettime (check_get_clockid (), &ts_end);
396 tcase_run_checked_teardown (tc);
397 return receive_result_info_nofork (tc->name, tfun->name, i,
398 DIFF_IN_USEC (ts_start, ts_end));
405 receive_result_info_nofork (const char *tcname,
406 const char *tname, int iter, int duration)
410 tr = receive_test_result (0);
412 eprintf ("Failed to receive test result", __FILE__, __LINE__);
417 tr->duration = duration;
418 set_nofork_info (tr);
425 set_nofork_info (TestResult * tr)
427 if (tr->msg == NULL) {
429 tr->msg = pass_msg ();
431 tr->rtype = CK_FAILURE;
438 return strdup ("Passed");
441 #if defined(HAVE_FORK) && HAVE_FORK==1
443 tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i)
448 struct timespec ts_start = { 0, 0 }, ts_end = {
452 struct itimerspec timer_spec;
458 eprintf ("Error in call to fork:", __FILE__, __LINE__ - 2);
461 group_pid = getpgrp ();
462 tr = tcase_run_checked_setup (sr, tc);
464 clock_gettime (check_get_clockid (), &ts_start);
466 clock_gettime (check_get_clockid (), &ts_end);
467 tcase_run_checked_teardown (tc);
468 send_duration_info (DIFF_IN_USEC (ts_start, ts_end));
476 if (timer_create (check_get_clockid (),
477 NULL /* fire SIGALRM if timer expires */ ,
479 /* Set the timer to fire once */
480 timer_spec.it_value = tc->timeout;
481 timer_spec.it_interval.tv_sec = 0;
482 timer_spec.it_interval.tv_nsec = 0;
483 if (timer_settime (timerid, 0, &timer_spec, NULL) == 0) {
485 pid_w = waitpid (pid, &status, 0);
489 eprintf ("Error in call to timer_settime:", __FILE__, __LINE__);
492 /* If the timer has not fired, disable it */
493 timer_delete (timerid);
495 eprintf ("Error in call to timer_create:", __FILE__, __LINE__);
498 killpg (pid, SIGKILL); /* Kill remaining processes. */
500 return receive_result_info_fork (tc->name, tfun->name, i, status,
501 tfun->signal, tfun->allowed_exit_value);
505 receive_result_info_fork (const char *tcname,
507 int iter, int status, int expected_signal, signed char allowed_exit_value)
511 tr = receive_test_result (waserror (status, expected_signal));
513 eprintf ("Failed to receive test result", __FILE__, __LINE__);
518 set_fork_info (tr, status, expected_signal, allowed_exit_value);
525 set_fork_info (TestResult * tr, int status, int signal_expected,
526 signed char allowed_exit_value)
528 int was_sig = WIFSIGNALED (status);
529 int was_exit = WIFEXITED (status);
530 signed char exit_status = WEXITSTATUS (status);
531 int signal_received = WTERMSIG (status);
534 if (signal_expected == signal_received) {
535 if (alarm_received) {
536 /* Got alarm instead of signal */
537 tr->rtype = CK_ERROR;
538 if (tr->msg != NULL) {
541 tr->msg = signal_error_msg (signal_received, signal_expected);
544 if (tr->msg != NULL) {
547 tr->msg = pass_msg ();
549 } else if (signal_expected != 0) {
550 /* signal received, but not the expected one */
551 tr->rtype = CK_ERROR;
552 if (tr->msg != NULL) {
555 tr->msg = signal_error_msg (signal_received, signal_expected);
557 /* signal received and none expected */
558 tr->rtype = CK_ERROR;
559 if (tr->msg != NULL) {
562 tr->msg = signal_msg (signal_received);
564 } else if (signal_expected == 0) {
565 if (was_exit && exit_status == allowed_exit_value) {
567 if (tr->msg != NULL) {
570 tr->msg = pass_msg ();
571 } else if (was_exit && exit_status != allowed_exit_value) {
572 if (tr->msg == NULL) { /* early exit */
573 tr->rtype = CK_ERROR;
574 tr->msg = exit_msg (exit_status);
576 tr->rtype = CK_FAILURE;
579 } else { /* a signal was expected and none raised */
581 if (tr->msg != NULL) {
584 tr->msg = exit_msg (exit_status);
585 tr->rtype = CK_FAILURE; /* normal exit status */
591 signal_msg (int signal)
593 char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
595 if (alarm_received) {
596 snprintf (msg, MSG_LEN, "Test timeout expired");
598 snprintf (msg, MSG_LEN, "Received signal %d (%s)",
599 signal, strsignal (signal));
605 signal_error_msg (int signal_received, int signal_expected)
609 char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
611 sig_r_str = strdup (strsignal (signal_received));
612 sig_e_str = strdup (strsignal (signal_expected));
613 if (alarm_received) {
614 snprintf (msg, MSG_LEN,
615 "Test timeout expired, expected signal %d (%s)",
616 signal_expected, sig_e_str);
618 snprintf (msg, MSG_LEN, "Received signal %d (%s), expected %d (%s)",
619 signal_received, sig_r_str, signal_expected, sig_e_str);
627 exit_msg (int exitval)
629 char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */
631 snprintf (msg, MSG_LEN, "Early exit with return value %d", exitval);
636 waserror (int status, int signal_expected)
638 int was_sig = WIFSIGNALED (status);
639 int was_exit = WIFEXITED (status);
640 int exit_status = WEXITSTATUS (status);
641 int signal_received = WTERMSIG (status);
643 return ((was_sig && (signal_received != signal_expected)) ||
644 (was_exit && exit_status != 0));
646 #endif /* HAVE_FORK */
649 srunner_fork_status (SRunner * sr)
651 if (sr->fstat == CK_FORK_GETENV) {
652 char *env = getenv ("CK_FORK");
655 #if defined(HAVE_FORK) && HAVE_FORK==1
660 if (strcmp (env, "no") == 0)
663 #if defined(HAVE_FORK) && HAVE_FORK==1
665 #else /* HAVE_FORK */
666 eprintf ("This version does not support fork", __FILE__, __LINE__);
667 /* Ignoring, as Check is not compiled with fork support. */
669 #endif /* HAVE_FORK */
676 srunner_set_fork_status (SRunner * sr, enum fork_status fstat)
678 #if !defined(HAVE_FORK) || HAVE_FORK==0
679 /* If fork() is unavailable, do not allow a fork mode to be set */
680 if (fstat != CK_NOFORK) {
681 eprintf ("This version does not support fork", __FILE__, __LINE__);
682 /* Overriding, as Check is not compiled with fork support. */
685 #endif /* ! HAVE_FORK */
690 srunner_run_all (SRunner * sr, enum print_output print_mode)
692 srunner_run (sr, NULL, /* All test suites. */
693 NULL, /* All test cases. */
698 srunner_run_tagged (SRunner * sr, const char *sname, const char *tcname,
699 const char *include_tags, const char *exclude_tags,
700 enum print_output print_mode)
702 #if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
703 static struct sigaction sigalarm_old_action;
704 static struct sigaction sigalarm_new_action;
705 static struct sigaction sigint_new_action;
706 static struct sigaction sigterm_new_action;
707 #endif /* HAVE_SIGACTION && HAVE_FORK */
709 /* Get the selected test suite and test case from the
712 tcname = getenv ("CK_RUN_CASE");
714 sname = getenv ("CK_RUN_SUITE");
716 include_tags = getenv ("CK_INCLUDE_TAGS");
718 exclude_tags = getenv ("CK_EXCLUDE_TAGS");
722 if (print_mode >= CK_LAST) {
723 eprintf ("Bad print_mode argument to srunner_run_all: %d",
724 __FILE__, __LINE__, print_mode);
726 #if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
727 memset (&sigalarm_new_action, 0, sizeof (sigalarm_new_action));
728 sigalarm_new_action.sa_handler = sig_handler;
729 sigaction (SIGALRM, &sigalarm_new_action, &sigalarm_old_action);
731 memset (&sigint_new_action, 0, sizeof (sigint_new_action));
732 sigint_new_action.sa_handler = sig_handler;
733 sigaction (SIGINT, &sigint_new_action, &sigint_old_action);
735 memset (&sigterm_new_action, 0, sizeof (sigterm_new_action));
736 sigterm_new_action.sa_handler = sig_handler;
737 sigaction (SIGTERM, &sigterm_new_action, &sigterm_old_action);
738 #endif /* HAVE_SIGACTION && HAVE_FORK */
739 srunner_run_init (sr, print_mode);
740 srunner_iterate_suites (sr, sname, tcname, include_tags, exclude_tags,
742 srunner_run_end (sr, print_mode);
743 #if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
744 sigaction (SIGALRM, &sigalarm_old_action, NULL);
745 sigaction (SIGINT, &sigint_old_action, NULL);
746 sigaction (SIGTERM, &sigterm_old_action, NULL);
747 #endif /* HAVE_SIGACTION && HAVE_FORK */
751 srunner_run (SRunner * sr, const char *sname, const char *tcname,
752 enum print_output print_mode)
754 srunner_run_tagged (sr, sname, tcname, NULL, NULL, print_mode);
760 #if defined(HAVE_FORK) && HAVE_FORK==1
763 /* Set the process to a process group to be able to kill it easily. */
765 setpgid (pid, group_pid);
768 #else /* HAVE_FORK */
769 eprintf ("This version does not support fork", __FILE__, __LINE__);
771 #endif /* HAVE_FORK */
775 check_waitpid_and_exit (pid_t pid CK_ATTRIBUTE_UNUSED)
777 #if defined(HAVE_FORK) && HAVE_FORK==1
783 pid_w = waitpid (pid, &status, 0);
786 if (waserror (status, 0)) {
791 #else /* HAVE_FORK */
792 eprintf ("This version does not support fork", __FILE__, __LINE__);
793 /* Ignoring, as Check is not compiled with fork support. */
795 #endif /* HAVE_FORK */