Back to home page

Enduro/X

 
 

    


0001 #ifndef _GNU_SOURCE
0002 #define _GNU_SOURCE
0003 #endif
0004 
0005 #include "cgreen/runner.h"
0006 #include "cgreen/internal/runner_platform.h"
0007 #include <stdio.h>
0008 #include <unistd.h>
0009 #include <sys/wait.h>
0010 #include <signal.h>
0011 #include <stdlib.h>
0012 #include <string.h>
0013 
0014 #ifdef __cplusplus
0015 namespace cgreen {
0016 #endif
0017 
0018 typedef void (*sighandler_t)(int);
0019 
0020 static int in_child_process(void);
0021 static int wait_for_child_process(void);
0022 static void stop(void);
0023 static void ignore_ctrl_c(void);
0024 static void allow_ctrl_c(void);
0025 
0026 
0027 void run_test_in_its_own_process(TestSuite *suite, CgreenTest *test, TestReporter *reporter) {
0028     (*reporter->start_test)(reporter, test->name);
0029     if (in_child_process()) {
0030         run_the_test_code(suite, test, reporter);
0031         send_reporter_completion_notification(reporter);
0032         stop();
0033     } else {
0034         const int status = wait_for_child_process();
0035         if (WIFSIGNALED(status)) {
0036             /* a C++ exception generates SIGABRT. Only print our special message for different signals. */
0037             const int sig = WTERMSIG(status);
0038             if (sig != SIGABRT) {
0039                 char buf[128];
0040                 snprintf(buf, sizeof(buf), "Test terminated with signal: %s", (const char *)strsignal(sig));
0041                 (*reporter->finish_test)(reporter, test->filename, test->line, buf);
0042                 return;
0043             }
0044         }
0045         (*reporter->finish_test)(reporter, test->filename, test->line, NULL);
0046     }
0047 }
0048 
0049 static int in_child_process(void) {
0050     fflush(NULL);               /* Flush all buffers before forking */
0051     pid_t child = fork();
0052     if (child < 0) {
0053         die("Could not fork process\n");
0054     }
0055     return ! child;
0056 }
0057 
0058 static int wait_for_child_process(void) {
0059     int status = 0;
0060     ignore_ctrl_c();
0061     wait(&status);
0062     allow_ctrl_c();
0063     return status;
0064 }
0065 
0066 void die_in(unsigned int seconds) {
0067     sighandler_t signal_result = signal(SIGALRM, (sighandler_t)&stop);
0068     if (SIG_ERR == signal_result) {
0069         fprintf(stderr, "could not set alarm signal hander\n");
0070         return;
0071     }
0072 
0073     alarm(seconds);
0074 }
0075 
0076 void run_specified_test_if_child(TestSuite *suite, TestReporter *reporter){
0077     /*not needed for systems that support fork()*/
0078     (void)suite;
0079     (void)reporter;
0080 }
0081 
0082 static void stop(void) {
0083     _exit(EXIT_SUCCESS);
0084 }
0085 
0086 static void ignore_ctrl_c(void) {
0087     signal(SIGINT, SIG_IGN);
0088 }
0089 
0090 static void allow_ctrl_c(void) {
0091     signal(SIGINT, SIG_DFL);
0092 }
0093 
0094 #ifdef __cplusplus
0095 } /* namespace cgreen */
0096 #endif
0097 
0098 /* vim: set ts=4 sw=4 et cindent: */