Run each testsuite test with a timeout.
authorWayne Davison <wayned@samba.org>
Sun, 13 Dec 2009 22:14:38 +0000 (14:14 -0800)
committerWayne Davison <wayned@samba.org>
Sun, 13 Dec 2009 22:14:38 +0000 (14:14 -0800)
.gitignore
Makefile.in
runtests.sh
testrun.c [new file with mode: 0644]

index 76693bb..805af45 100644 (file)
@@ -28,6 +28,7 @@ config.status
 /tests-dont-exist
 /testtmp
 /tls
+/testrun
 /trimslash
 /t_unsafe
 /wildtest
index 826cf1f..6285666 100644 (file)
@@ -47,12 +47,12 @@ TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxa
 
 # Programs we must have to run the test cases
 CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
-       trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
+       testrun$(EXEEXT) trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
 
 CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test
 
 # Objects for CHECK_PROGS to clean
-CHECK_OBJS=tls.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
+CHECK_OBJS=tls.o testrun.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
 
 # note that the -I. is needed to handle config.h when using VPATH
 .c.o:
@@ -102,6 +102,9 @@ rounding.h: rounding.c rsync.h
 tls$(EXEEXT): $(TLS_OBJ)
        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
 
+testrun$(EXEEXT): testrun.o
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ testrun.o
+
 getgroups$(EXEEXT): getgroups.o
        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ getgroups.o $(LIBS)
 
index 41d566b..db95d8f 100755 (executable)
@@ -262,7 +262,7 @@ do
     prep_scratch
 
     set +e
-    sh $RUNSHFLAGS "$testscript" >"$scratchdir/test.log" 2>&1
+    "$TOOLDIR/"testrun $RUNSHFLAGS "$testscript" >"$scratchdir/test.log" 2>&1
     result=$?
     set -e
 
diff --git a/testrun.c b/testrun.c
new file mode 100644 (file)
index 0000000..e1f0831
--- /dev/null
+++ b/testrun.c
@@ -0,0 +1,54 @@
+/* Run a testsuite script with a timeout. */
+
+#include "rsync.h"
+
+#define MAX_TEST_SECONDS (3*60)
+
+ int main(int argc, char *argv[])
+{
+       pid_t pid;
+       int status, slept = 0;
+
+       if (argc < 2) {
+               fprintf(stderr, "Usage: testrun [SHELL_OPTIONS] TESTSUITE_SCRIPT [ARGS]\n");
+               exit(1);
+       }
+
+       if ((pid = fork()) < 0) {
+               fprintf(stderr, "TESTRUN ERROR: fork failed: %s\n", strerror(errno));
+               exit(1);
+       }
+
+       if (pid == 0) {
+               argv[0] = "sh";
+               execvp(argv[0], argv);
+               fprintf(stderr, "TESTRUN ERROR: failed to exec %s: %s\n", argv[0], strerror(errno));
+               _exit(1);
+       }
+
+       while (1) {
+               int ret = waitpid(pid, &status, WNOHANG);
+               if (ret > 0)
+                       break;
+               if (ret < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       fprintf(stderr, "TESTRUN ERROR: waitpid failed: %s\n", strerror(errno));
+                       exit(1);
+               }
+               if (slept++ > MAX_TEST_SECONDS) {
+                       fprintf(stderr, "TESTRUN TIMEOUT: test took over %d seconds.\n", MAX_TEST_SECONDS);
+                       if (kill(pid, SIGTERM) < 0)
+                               fprintf(stderr, "TESTRUN ERROR: failed to kill pid %ld: %s\n", (long)pid, strerror(errno));
+                       else
+                               fprintf(stderr, "TESTRUN INFO: killed pid %ld\n", (long)pid);
+                       exit(1);
+               }
+               sleep(1);
+       }
+
+       if (!WIFEXITED(status))
+               exit(255);
+
+       return WEXITSTATUS(status);
+}