Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / tools / testing / selftests / powerpc / harness.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2013, Michael Ellerman, IBM Corp.
4  */
5
6 #include <errno.h>
7 #include <signal.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/wait.h>
13 #include <unistd.h>
14 #include <elf.h>
15 #include <fcntl.h>
16 #include <link.h>
17 #include <sys/stat.h>
18
19 #include "subunit.h"
20 #include "utils.h"
21
22 #define KILL_TIMEOUT    5
23
24 /* Setting timeout to -1 disables the alarm */
25 static uint64_t timeout = 120;
26
27 int run_test(int (test_function)(void), char *name)
28 {
29         bool terminated;
30         int rc, status;
31         pid_t pid;
32
33         /* Make sure output is flushed before forking */
34         fflush(stdout);
35
36         pid = fork();
37         if (pid == 0) {
38                 setpgid(0, 0);
39                 exit(test_function());
40         } else if (pid == -1) {
41                 perror("fork");
42                 return 1;
43         }
44
45         setpgid(pid, pid);
46
47         if (timeout != -1)
48                 /* Wake us up in timeout seconds */
49                 alarm(timeout);
50         terminated = false;
51
52 wait:
53         rc = waitpid(pid, &status, 0);
54         if (rc == -1) {
55                 if (errno != EINTR) {
56                         printf("unknown error from waitpid\n");
57                         return 1;
58                 }
59
60                 if (terminated) {
61                         printf("!! force killing %s\n", name);
62                         kill(-pid, SIGKILL);
63                         return 1;
64                 } else {
65                         printf("!! killing %s\n", name);
66                         kill(-pid, SIGTERM);
67                         terminated = true;
68                         alarm(KILL_TIMEOUT);
69                         goto wait;
70                 }
71         }
72
73         /* Kill anything else in the process group that is still running */
74         kill(-pid, SIGTERM);
75
76         if (WIFEXITED(status))
77                 status = WEXITSTATUS(status);
78         else {
79                 if (WIFSIGNALED(status))
80                         printf("!! child died by signal %d\n", WTERMSIG(status));
81                 else
82                         printf("!! child died by unknown cause\n");
83
84                 status = 1; /* Signal or other */
85         }
86
87         return status;
88 }
89
90 static void sig_handler(int signum)
91 {
92         /* Just wake us up from waitpid */
93 }
94
95 static struct sigaction sig_action = {
96         .sa_handler = sig_handler,
97 };
98
99 void test_harness_set_timeout(uint64_t time)
100 {
101         timeout = time;
102 }
103
104 int test_harness(int (test_function)(void), char *name)
105 {
106         int rc;
107
108         test_start(name);
109         test_set_git_version(GIT_VERSION);
110
111         if (sigaction(SIGINT, &sig_action, NULL)) {
112                 perror("sigaction (sigint)");
113                 test_error(name);
114                 return 1;
115         }
116
117         if (sigaction(SIGALRM, &sig_action, NULL)) {
118                 perror("sigaction (sigalrm)");
119                 test_error(name);
120                 return 1;
121         }
122
123         rc = run_test(test_function, name);
124
125         if (rc == MAGIC_SKIP_RETURN_VALUE) {
126                 test_skip(name);
127                 /* so that skipped test is not marked as failed */
128                 rc = 0;
129         } else
130                 test_finish(name, rc);
131
132         return rc;
133 }