check: duplicate code branches
[platform/upstream/gstreamer.git] / libs / gst / check / libcheck / check_run.c
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 }