"Fossies" - the Fresh Open Source Software Archive

Member "gstreamer-1.16.1/libs/gst/check/libcheck/check_run.c" (19 Apr 2019, 21298 Bytes) of package /linux/misc/gstreamer-1.16.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "check_run.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Check: a unit test framework for C
    3  * Copyright (C) 2001, 2002 Arien Malec
    4  *
    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.
    9  *
   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.
   14  *
   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,
   18  * MA 02110-1301, USA.
   19  */
   20 
   21 #include "libcompat/libcompat.h"
   22 
   23 #include <sys/types.h>
   24 #include <time.h>
   25 #include <stdlib.h>
   26 #include <stdio.h>
   27 #include <string.h>
   28 #include <stdarg.h>
   29 #include <signal.h>
   30 #include <setjmp.h>
   31 
   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"
   38 
   39 enum rinfo
   40 {
   41   CK_R_SIG,
   42   CK_R_PASS,
   43   CK_R_EXIT,
   44   CK_R_FAIL_TEST,
   45   CK_R_FAIL_FIXTURE
   46 };
   47 
   48 enum tf_type
   49 {
   50   CK_FORK_TEST,
   51   CK_NOFORK_TEST,
   52   CK_NOFORK_FIXTURE
   53 };
   54 
   55 
   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,
   77     int i);
   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);
   82 
   83 #if defined(HAVE_FORK) && HAVE_FORK==1
   84 static TestResult *tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tf,
   85     int i);
   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);
   95 
   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;
  100 
  101 static void CK_ATTRIBUTE_UNUSED
  102 sig_handler (int sig_nr)
  103 {
  104   switch (sig_nr) {
  105     case SIGALRM:
  106       alarm_received = 1;
  107       killpg (group_pid, SIGKILL);
  108       break;
  109     case SIGTERM:
  110     case SIGINT:
  111     {
  112       pid_t own_group_pid;
  113       int child_sig = SIGTERM;
  114 
  115       if (sig_nr == SIGINT) {
  116         child_sig = SIGKILL;
  117         sigaction (SIGINT, &sigint_old_action, NULL);
  118       } else {
  119         sigaction (SIGTERM, &sigterm_old_action, NULL);
  120       }
  121 
  122       killpg (group_pid, child_sig);
  123 
  124       /* POSIX says that calling killpg(0)
  125        * does not necessarily mean to call it on the callers
  126        * group pid! */
  127       own_group_pid = getpgrp ();
  128       killpg (own_group_pid, sig_nr);
  129       break;
  130     }
  131     default:
  132       eprintf ("Unhandled signal: %d", __FILE__, __LINE__, sig_nr);
  133       break;
  134   }
  135 }
  136 #endif /* HAVE_FORK */
  137 
  138 #define MSG_LEN 100
  139 
  140 static void
  141 srunner_run_init (SRunner * sr, enum print_output print_mode)
  142 {
  143   set_fork_status (srunner_fork_status (sr));
  144   setup_messaging ();
  145   srunner_init_logging (sr, print_mode);
  146   log_srunner_start (sr);
  147 }
  148 
  149 static void
  150 srunner_run_end (SRunner * sr, enum print_output CK_ATTRIBUTE_UNUSED print_mode)
  151 {
  152   log_srunner_end (sr);
  153   srunner_end_logging (sr);
  154   teardown_messaging ();
  155   set_fork_status (CK_FORK);
  156 }
  157 
  158 static void
  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)
  163 {
  164   List *include_tag_lst;
  165   List *exclude_tag_lst;
  166   List *slst;
  167   List *tcl;
  168   TCase *tc;
  169 
  170   slst = sr->slst;
  171 
  172   include_tag_lst = tag_string_to_list (include_tags);
  173   exclude_tag_lst = tag_string_to_list (exclude_tags);
  174 
  175   for (check_list_front (slst); !check_list_at_end (slst);
  176       check_list_advance (slst)) {
  177     Suite *s = (Suite *) check_list_val (slst);
  178 
  179     if (((sname != NULL) && (strcmp (sname, s->name) != 0))
  180         || ((tcname != NULL) && (!suite_tcase (s, tcname))))
  181       continue;
  182 
  183     log_suite_start (sr, s);
  184 
  185     tcl = s->tclst;
  186 
  187     for (check_list_front (tcl); !check_list_at_end (tcl);
  188         check_list_advance (tcl)) {
  189       tc = (TCase *) check_list_val (tcl);
  190 
  191       if ((tcname != NULL) && (strcmp (tcname, tc->name) != 0)) {
  192         continue;
  193       }
  194       if (include_tags != NULL) {
  195         if (!tcase_matching_tag (tc, include_tag_lst)) {
  196           continue;
  197         }
  198       }
  199       if (exclude_tags != NULL) {
  200         if (tcase_matching_tag (tc, exclude_tag_lst)) {
  201           continue;
  202         }
  203       }
  204 
  205       srunner_run_tcase (sr, tc);
  206     }
  207 
  208     log_suite_end (sr, s);
  209   }
  210 
  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);
  215 }
  216 
  217 static void
  218 srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc)
  219 {
  220   List *tfl;
  221   TF *tfun;
  222   TestResult *tr = NULL;
  223 
  224   tfl = tc->tflst;
  225 
  226   for (check_list_front (tfl); !check_list_at_end (tfl);
  227       check_list_advance (tfl)) {
  228     int i;
  229 
  230     tfun = (TF *) check_list_val (tfl);
  231 
  232     for (i = tfun->loop_start; i < tfun->loop_end; i++) {
  233       log_test_start (sr, tc, tfun);
  234       switch (srunner_fork_status (sr)) {
  235         case CK_FORK:
  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 */
  241           break;
  242         case CK_NOFORK:
  243           tr = tcase_run_tfun_nofork (sr, tc, tfun, i);
  244           break;
  245         case CK_FORK_GETENV:
  246         default:
  247           eprintf ("Bad fork status in SRunner", __FILE__, __LINE__);
  248       }
  249 
  250       if (NULL != tr) {
  251         srunner_add_failure (sr, tr);
  252         log_test_end (sr, tr);
  253       }
  254     }
  255   }
  256 }
  257 
  258 static void
  259 srunner_add_failure (SRunner * sr, TestResult * tr)
  260 {
  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++;
  267 
  268 }
  269 
  270 static TestResult *
  271 srunner_run_setup (List * fixture_list, enum fork_status fork_usage,
  272     const char *test_name, const char *setup_name)
  273 {
  274   TestResult *tr = NULL;
  275   Fixture *setup_fixture;
  276 
  277   if (fork_usage == CK_FORK) {
  278     send_ctx_info (CK_CTX_SETUP);
  279   }
  280 
  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);
  284 
  285     if (fork_usage == CK_NOFORK) {
  286       send_ctx_info (CK_CTX_SETUP);
  287 
  288       if (0 == setjmp (error_jmp_buffer)) {
  289         setup_fixture->fun ();
  290       }
  291 
  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) {
  295         break;
  296       }
  297 
  298       free (tr->file);
  299       free (tr->msg);
  300       free (tr);
  301       tr = NULL;
  302     } else {
  303       setup_fixture->fun ();
  304     }
  305   }
  306 
  307   return tr;
  308 }
  309 
  310 static int
  311 srunner_run_unchecked_setup (SRunner * sr, TCase * tc)
  312 {
  313   TestResult *tr = NULL;
  314   int rval = 1;
  315 
  316   set_fork_status (CK_NOFORK);
  317   tr = srunner_run_setup (tc->unch_sflst, CK_NOFORK, tc->name,
  318       "unchecked_setup");
  319   set_fork_status (srunner_fork_status (sr));
  320 
  321   if (tr != NULL && tr->rtype != CK_PASS) {
  322     srunner_add_failure (sr, tr);
  323     rval = 0;
  324   }
  325 
  326   return rval;
  327 }
  328 
  329 static TestResult *
  330 tcase_run_checked_setup (SRunner * sr, TCase * tc)
  331 {
  332   TestResult *tr = srunner_run_setup (tc->ch_sflst, srunner_fork_status (sr),
  333       tc->name, "checked_setup");
  334 
  335   return tr;
  336 }
  337 
  338 static void
  339 srunner_run_teardown (List * fixture_list, enum fork_status fork_usage)
  340 {
  341   Fixture *fixture;
  342 
  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);
  347 
  348     if (fork_usage == CK_NOFORK) {
  349       if (0 == setjmp (error_jmp_buffer)) {
  350         fixture->fun ();
  351       } else {
  352         /* Abort the remaining teardowns */
  353         break;
  354       }
  355     } else {
  356       fixture->fun ();
  357     }
  358   }
  359 }
  360 
  361 static void
  362 srunner_run_unchecked_teardown (SRunner * sr, TCase * tc)
  363 {
  364   srunner_run_teardown (tc->unch_tflst, srunner_fork_status (sr));
  365 }
  366 
  367 static void
  368 tcase_run_checked_teardown (TCase * tc)
  369 {
  370   srunner_run_teardown (tc->ch_tflst, CK_NOFORK);
  371 }
  372 
  373 static void
  374 srunner_run_tcase (SRunner * sr, TCase * tc)
  375 {
  376   if (srunner_run_unchecked_setup (sr, tc)) {
  377     srunner_iterate_tcase_tfuns (sr, tc);
  378     srunner_run_unchecked_teardown (sr, tc);
  379   }
  380 }
  381 
  382 static TestResult *
  383 tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tfun, int i)
  384 {
  385   TestResult *tr;
  386   struct timespec ts_start = { 0, 0 }, ts_end = {
  387   0, 0};
  388 
  389   tr = tcase_run_checked_setup (sr, tc);
  390   if (tr == NULL) {
  391     clock_gettime (check_get_clockid (), &ts_start);
  392     if (0 == setjmp (error_jmp_buffer)) {
  393       tfun->fn (i);
  394     }
  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));
  399   }
  400 
  401   return tr;
  402 }
  403 
  404 static TestResult *
  405 receive_result_info_nofork (const char *tcname,
  406     const char *tname, int iter, int duration)
  407 {
  408   TestResult *tr;
  409 
  410   tr = receive_test_result (0);
  411   if (tr == NULL) {
  412     eprintf ("Failed to receive test result", __FILE__, __LINE__);
  413   } else {
  414     tr->tcname = tcname;
  415     tr->tname = tname;
  416     tr->iter = iter;
  417     tr->duration = duration;
  418     set_nofork_info (tr);
  419   }
  420 
  421   return tr;
  422 }
  423 
  424 static void
  425 set_nofork_info (TestResult * tr)
  426 {
  427   if (tr->msg == NULL) {
  428     tr->rtype = CK_PASS;
  429     tr->msg = pass_msg ();
  430   } else {
  431     tr->rtype = CK_FAILURE;
  432   }
  433 }
  434 
  435 static char *
  436 pass_msg (void)
  437 {
  438   return strdup ("Passed");
  439 }
  440 
  441 #if defined(HAVE_FORK) && HAVE_FORK==1
  442 static TestResult *
  443 tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i)
  444 {
  445   pid_t pid_w;
  446   pid_t pid;
  447   int status = 0;
  448   struct timespec ts_start = { 0, 0 }, ts_end = {
  449   0, 0};
  450 
  451   timer_t timerid;
  452   struct itimerspec timer_spec;
  453   TestResult *tr;
  454 
  455 
  456   pid = fork ();
  457   if (pid == -1)
  458     eprintf ("Error in call to fork:", __FILE__, __LINE__ - 2);
  459   if (pid == 0) {
  460     setpgid (0, 0);
  461     group_pid = getpgrp ();
  462     tr = tcase_run_checked_setup (sr, tc);
  463     free (tr);
  464     clock_gettime (check_get_clockid (), &ts_start);
  465     tfun->fn (i);
  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));
  469     exit (EXIT_SUCCESS);
  470   } else {
  471     group_pid = pid;
  472   }
  473 
  474   alarm_received = 0;
  475 
  476   if (timer_create (check_get_clockid (),
  477           NULL /* fire SIGALRM if timer expires */ ,
  478           &timerid) == 0) {
  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) {
  484       do {
  485         pid_w = waitpid (pid, &status, 0);
  486       }
  487       while (pid_w == -1);
  488     } else {
  489       eprintf ("Error in call to timer_settime:", __FILE__, __LINE__);
  490     }
  491 
  492     /* If the timer has not fired, disable it */
  493     timer_delete (timerid);
  494   } else {
  495     eprintf ("Error in call to timer_create:", __FILE__, __LINE__);
  496   }
  497 
  498   killpg (pid, SIGKILL);        /* Kill remaining processes. */
  499 
  500   return receive_result_info_fork (tc->name, tfun->name, i, status,
  501       tfun->signal, tfun->allowed_exit_value);
  502 }
  503 
  504 static TestResult *
  505 receive_result_info_fork (const char *tcname,
  506     const char *tname,
  507     int iter, int status, int expected_signal, signed char allowed_exit_value)
  508 {
  509   TestResult *tr;
  510 
  511   tr = receive_test_result (waserror (status, expected_signal));
  512   if (tr == NULL) {
  513     eprintf ("Failed to receive test result", __FILE__, __LINE__);
  514   } else {
  515     tr->tcname = tcname;
  516     tr->tname = tname;
  517     tr->iter = iter;
  518     set_fork_info (tr, status, expected_signal, allowed_exit_value);
  519   }
  520 
  521   return tr;
  522 }
  523 
  524 static void
  525 set_fork_info (TestResult * tr, int status, int signal_expected,
  526     signed char allowed_exit_value)
  527 {
  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);
  532 
  533   if (was_sig) {
  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) {
  539           free (tr->msg);
  540         }
  541         tr->msg = signal_error_msg (signal_received, signal_expected);
  542       } else {
  543         tr->rtype = CK_PASS;
  544         if (tr->msg != NULL) {
  545           free (tr->msg);
  546         }
  547         tr->msg = pass_msg ();
  548       }
  549     } else if (signal_expected != 0) {
  550       /* signal received, but not the expected one */
  551       tr->rtype = CK_ERROR;
  552       if (tr->msg != NULL) {
  553         free (tr->msg);
  554       }
  555       tr->msg = signal_error_msg (signal_received, signal_expected);
  556     } else {
  557       /* signal received and none expected */
  558       tr->rtype = CK_ERROR;
  559       if (tr->msg != NULL) {
  560         free (tr->msg);
  561       }
  562       tr->msg = signal_msg (signal_received);
  563     }
  564   } else if (signal_expected == 0) {
  565     if (was_exit && exit_status == allowed_exit_value) {
  566       tr->rtype = CK_PASS;
  567       if (tr->msg != NULL) {
  568         free (tr->msg);
  569       }
  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);
  575       } else {
  576         tr->rtype = CK_FAILURE;
  577       }
  578     }
  579   } else {                      /* a signal was expected and none raised */
  580     if (was_exit) {
  581       if (tr->msg != NULL) {
  582         free (tr->msg);
  583       }
  584       tr->msg = exit_msg (exit_status);
  585       tr->rtype = CK_FAILURE;   /* normal exit status */
  586     }
  587   }
  588 }
  589 
  590 static char *
  591 signal_msg (int signal)
  592 {
  593   char *msg = (char *) emalloc (MSG_LEN);       /* free'd by caller */
  594 
  595   if (alarm_received) {
  596     snprintf (msg, MSG_LEN, "Test timeout expired");
  597   } else {
  598     snprintf (msg, MSG_LEN, "Received signal %d (%s)",
  599         signal, strsignal (signal));
  600   }
  601   return msg;
  602 }
  603 
  604 static char *
  605 signal_error_msg (int signal_received, int signal_expected)
  606 {
  607   char *sig_r_str;
  608   char *sig_e_str;
  609   char *msg = (char *) emalloc (MSG_LEN);       /* free'd by caller */
  610 
  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);
  617   } else {
  618     snprintf (msg, MSG_LEN, "Received signal %d (%s), expected %d (%s)",
  619         signal_received, sig_r_str, signal_expected, sig_e_str);
  620   }
  621   free (sig_r_str);
  622   free (sig_e_str);
  623   return msg;
  624 }
  625 
  626 static char *
  627 exit_msg (int exitval)
  628 {
  629   char *msg = (char *) emalloc (MSG_LEN);       /* free'd by caller */
  630 
  631   snprintf (msg, MSG_LEN, "Early exit with return value %d", exitval);
  632   return msg;
  633 }
  634 
  635 static int
  636 waserror (int status, int signal_expected)
  637 {
  638   int was_sig = WIFSIGNALED (status);
  639   int was_exit = WIFEXITED (status);
  640   int exit_status = WEXITSTATUS (status);
  641   int signal_received = WTERMSIG (status);
  642 
  643   return ((was_sig && (signal_received != signal_expected)) ||
  644       (was_exit && exit_status != 0));
  645 }
  646 #endif /* HAVE_FORK */
  647 
  648 enum fork_status
  649 srunner_fork_status (SRunner * sr)
  650 {
  651   if (sr->fstat == CK_FORK_GETENV) {
  652     char *env = getenv ("CK_FORK");
  653 
  654     if (env == NULL)
  655 #if defined(HAVE_FORK) && HAVE_FORK==1
  656       return CK_FORK;
  657 #else
  658       return CK_NOFORK;
  659 #endif
  660     if (strcmp (env, "no") == 0)
  661       return CK_NOFORK;
  662     else {
  663 #if defined(HAVE_FORK) && HAVE_FORK==1
  664       return CK_FORK;
  665 #else /* HAVE_FORK */
  666       eprintf ("This version does not support fork", __FILE__, __LINE__);
  667       /* Ignoring, as Check is not compiled with fork support. */
  668       return CK_NOFORK;
  669 #endif /* HAVE_FORK */
  670     }
  671   } else
  672     return sr->fstat;
  673 }
  674 
  675 void
  676 srunner_set_fork_status (SRunner * sr, enum fork_status fstat)
  677 {
  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. */
  683     fstat = CK_NOFORK;
  684   }
  685 #endif /* ! HAVE_FORK */
  686   sr->fstat = fstat;
  687 }
  688 
  689 void
  690 srunner_run_all (SRunner * sr, enum print_output print_mode)
  691 {
  692   srunner_run (sr, NULL,        /* All test suites.  */
  693       NULL,                     /* All test cases.   */
  694       print_mode);
  695 }
  696 
  697 void
  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)
  701 {
  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 */
  708 
  709   /*  Get the selected test suite and test case from the
  710      environment.  */
  711   if (!tcname)
  712     tcname = getenv ("CK_RUN_CASE");
  713   if (!sname)
  714     sname = getenv ("CK_RUN_SUITE");
  715   if (!include_tags)
  716     include_tags = getenv ("CK_INCLUDE_TAGS");
  717   if (!exclude_tags)
  718     exclude_tags = getenv ("CK_EXCLUDE_TAGS");
  719 
  720   if (sr == NULL)
  721     return;
  722   if (print_mode >= CK_LAST) {
  723     eprintf ("Bad print_mode argument to srunner_run_all: %d",
  724         __FILE__, __LINE__, print_mode);
  725   }
  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);
  730 
  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);
  734 
  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,
  741       print_mode);
  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 */
  748 }
  749 
  750 void
  751 srunner_run (SRunner * sr, const char *sname, const char *tcname,
  752     enum print_output print_mode)
  753 {
  754   srunner_run_tagged (sr, sname, tcname, NULL, NULL, print_mode);
  755 }
  756 
  757 pid_t
  758 check_fork (void)
  759 {
  760 #if defined(HAVE_FORK) && HAVE_FORK==1
  761   pid_t pid = fork ();
  762 
  763   /* Set the process to a process group to be able to kill it easily. */
  764   if (pid >= 0) {
  765     setpgid (pid, group_pid);
  766   }
  767   return pid;
  768 #else /* HAVE_FORK */
  769   eprintf ("This version does not support fork", __FILE__, __LINE__);
  770   return 0;
  771 #endif /* HAVE_FORK */
  772 }
  773 
  774 void
  775 check_waitpid_and_exit (pid_t pid CK_ATTRIBUTE_UNUSED)
  776 {
  777 #if defined(HAVE_FORK) && HAVE_FORK==1
  778   pid_t pid_w;
  779   int status;
  780 
  781   if (pid > 0) {
  782     do {
  783       pid_w = waitpid (pid, &status, 0);
  784     }
  785     while (pid_w == -1);
  786     if (waserror (status, 0)) {
  787       exit (EXIT_FAILURE);
  788     }
  789   }
  790   exit (EXIT_SUCCESS);
  791 #else /* HAVE_FORK */
  792   eprintf ("This version does not support fork", __FILE__, __LINE__);
  793   /* Ignoring, as Check is not compiled with fork support. */
  794   exit (EXIT_FAILURE);
  795 #endif /* HAVE_FORK */
  796 }