[powerpc] Rename fesetenv_mode to fesetenv_control
[glibc.git] / support / support_test_main.c
blob05ad92e6880a99bfc811349517412fdacac5783c
1 /* Main worker function for the test driver.
2 Copyright (C) 1998-2019 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C 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.
10 The GNU C 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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <support/test-driver.h>
20 #include <support/check.h>
21 #include <support/temp_file-internal.h>
23 #include <assert.h>
24 #include <errno.h>
25 #include <getopt.h>
26 #include <malloc.h>
27 #include <signal.h>
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/param.h>
32 #include <sys/resource.h>
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <time.h>
37 #include <unistd.h>
39 static const struct option default_options[] =
41 TEST_DEFAULT_OPTIONS
42 { NULL, 0, NULL, 0 }
45 /* Show people how to run the program. */
46 static void
47 usage (const struct option *options)
49 size_t i;
51 printf ("Usage: %s [options]\n"
52 "\n"
53 "Environment Variables:\n"
54 " TIMEOUTFACTOR An integer used to scale the timeout\n"
55 " TMPDIR Where to place temporary files\n"
56 " TEST_COREDUMPS Do not disable coredumps if set\n"
57 "\n",
58 program_invocation_short_name);
59 printf ("Options:\n");
60 for (i = 0; options[i].name; ++i)
62 int indent;
64 indent = printf (" --%s", options[i].name);
65 if (options[i].has_arg == required_argument)
66 indent += printf (" <arg>");
67 printf ("%*s", 25 - indent, "");
68 switch (options[i].val)
70 case 'v':
71 printf ("Increase the output verbosity");
72 break;
73 case OPT_DIRECT:
74 printf ("Run the test directly (instead of forking & monitoring)");
75 break;
76 case OPT_TESTDIR:
77 printf ("Override the TMPDIR env var");
78 break;
80 printf ("\n");
84 /* The PID of the test process. */
85 static pid_t test_pid;
87 /* The cleanup handler passed to test_main. */
88 static void (*cleanup_function) (void);
90 static void
91 print_timestamp (const char *what, struct timeval tv)
93 struct tm tm;
94 if (gmtime_r (&tv.tv_sec, &tm) == NULL)
95 printf ("%s: %lld.%06d\n",
96 what, (long long int) tv.tv_sec, (int) tv.tv_usec);
97 else
98 printf ("%s: %04d-%02d-%02dT%02d:%02d:%02d.%06d\n",
99 what, 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
100 tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tv.tv_usec);
103 /* Timeout handler. We kill the child and exit with an error. */
104 static void
105 __attribute__ ((noreturn))
106 signal_handler (int sig)
108 int killed;
109 int status;
111 /* Do this first to avoid further interference from the
112 subprocess. */
113 struct timeval now;
114 bool now_available = gettimeofday (&now, NULL) == 0;
115 struct stat64 st;
116 bool st_available = fstat64 (STDOUT_FILENO, &st) == 0 && st.st_mtime != 0;
118 assert (test_pid > 1);
119 /* Kill the whole process group. */
120 kill (-test_pid, SIGKILL);
121 /* In case setpgid failed in the child, kill it individually too. */
122 kill (test_pid, SIGKILL);
124 /* Wait for it to terminate. */
125 int i;
126 for (i = 0; i < 5; ++i)
128 killed = waitpid (test_pid, &status, WNOHANG|WUNTRACED);
129 if (killed != 0)
130 break;
132 /* Delay, give the system time to process the kill. If the
133 nanosleep() call return prematurely, all the better. We
134 won't restart it since this probably means the child process
135 finally died. */
136 struct timespec ts;
137 ts.tv_sec = 0;
138 ts.tv_nsec = 100000000;
139 nanosleep (&ts, NULL);
141 if (killed != 0 && killed != test_pid)
143 printf ("Failed to kill test process: %m\n");
144 exit (1);
147 if (cleanup_function != NULL)
148 cleanup_function ();
150 if (sig == SIGINT)
152 signal (sig, SIG_DFL);
153 raise (sig);
156 if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
157 puts ("Timed out: killed the child process");
158 else if (WIFSTOPPED (status))
159 printf ("Timed out: the child process was %s\n",
160 strsignal (WSTOPSIG (status)));
161 else if (WIFSIGNALED (status))
162 printf ("Timed out: the child process got signal %s\n",
163 strsignal (WTERMSIG (status)));
164 else
165 printf ("Timed out: killed the child process but it exited %d\n",
166 WEXITSTATUS (status));
168 if (now_available)
169 print_timestamp ("Termination time", now);
170 if (st_available)
171 print_timestamp ("Last write to standard output",
172 (struct timeval) { st.st_mtim.tv_sec,
173 st.st_mtim.tv_nsec / 1000 });
175 /* Exit with an error. */
176 exit (1);
179 /* Run test_function or test_function_argv. */
180 static int
181 run_test_function (int argc, char **argv, const struct test_config *config)
183 if (config->test_function != NULL)
184 return config->test_function ();
185 else if (config->test_function_argv != NULL)
186 return config->test_function_argv (argc, argv);
187 else
189 printf ("error: no test function defined\n");
190 exit (1);
194 static bool test_main_called;
196 const char *test_dir = NULL;
197 unsigned int test_verbose = 0;
199 /* If test failure reporting has been linked in, it may contribute
200 additional test failures. */
201 static int
202 adjust_exit_status (int status)
204 if (support_report_failure != NULL)
205 return support_report_failure (status);
206 return status;
210 support_test_main (int argc, char **argv, const struct test_config *config)
212 if (test_main_called)
214 printf ("error: test_main called for a second time\n");
215 exit (1);
217 test_main_called = true;
218 const struct option *options;
219 if (config->options != NULL)
220 options = config->options;
221 else
222 options = default_options;
224 cleanup_function = config->cleanup_function;
226 int direct = 0; /* Directly call the test function? */
227 int status;
228 int opt;
229 unsigned int timeoutfactor = 1;
230 pid_t termpid;
232 if (!config->no_mallopt)
234 /* Make uses of freed and uninitialized memory known. Do not
235 pull in a definition for mallopt if it has not been defined
236 already. */
237 extern __typeof__ (mallopt) mallopt __attribute__ ((weak));
238 if (mallopt != NULL)
239 mallopt (M_PERTURB, 42);
242 while ((opt = getopt_long (argc, argv, config->optstring, options, NULL))
243 != -1)
244 switch (opt)
246 case '?':
247 usage (options);
248 exit (1);
249 case 'v':
250 ++test_verbose;
251 break;
252 case OPT_DIRECT:
253 direct = 1;
254 break;
255 case OPT_TESTDIR:
256 test_dir = optarg;
257 break;
258 default:
259 if (config->cmdline_function != NULL)
260 config->cmdline_function (opt);
263 /* If set, read the test TIMEOUTFACTOR value from the environment.
264 This value is used to scale the default test timeout values. */
265 char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
266 if (envstr_timeoutfactor != NULL)
268 char *envstr_conv = envstr_timeoutfactor;
269 unsigned long int env_fact;
271 env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
272 if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
273 timeoutfactor = MAX (env_fact, 1);
276 /* Set TMPDIR to specified test directory. */
277 if (test_dir != NULL)
279 setenv ("TMPDIR", test_dir, 1);
281 if (chdir (test_dir) < 0)
283 printf ("chdir: %m\n");
284 exit (1);
287 else
289 test_dir = getenv ("TMPDIR");
290 if (test_dir == NULL || test_dir[0] == '\0')
291 test_dir = "/tmp";
293 if (support_set_test_dir != NULL)
294 support_set_test_dir (test_dir);
296 int timeout = config->timeout;
297 if (timeout == 0)
298 timeout = DEFAULT_TIMEOUT;
300 /* Make sure we see all message, even those on stdout. */
301 if (!config->no_setvbuf)
302 setvbuf (stdout, NULL, _IONBF, 0);
304 /* Make sure temporary files are deleted. */
305 if (support_delete_temp_files != NULL)
306 atexit (support_delete_temp_files);
308 /* Correct for the possible parameters. */
309 argv[optind - 1] = argv[0];
310 argv += optind - 1;
311 argc -= optind - 1;
313 /* Call the initializing function, if one is available. */
314 if (config->prepare_function != NULL)
315 config->prepare_function (argc, argv);
317 const char *envstr_direct = getenv ("TEST_DIRECT");
318 if (envstr_direct != NULL)
320 FILE *f = fopen (envstr_direct, "w");
321 if (f == NULL)
323 printf ("cannot open TEST_DIRECT output file '%s': %m\n",
324 envstr_direct);
325 exit (1);
328 fprintf (f, "timeout=%u\ntimeoutfactor=%u\n",
329 config->timeout, timeoutfactor);
330 if (config->expected_status != 0)
331 fprintf (f, "exit=%u\n", config->expected_status);
332 if (config->expected_signal != 0)
333 fprintf (f, "signal=%s\n", strsignal (config->expected_signal));
335 if (support_print_temp_files != NULL)
336 support_print_temp_files (f);
338 fclose (f);
339 direct = 1;
342 bool disable_coredumps;
344 const char *coredumps = getenv ("TEST_COREDUMPS");
345 disable_coredumps = coredumps == NULL || coredumps[0] == '\0';
348 /* If we are not expected to fork run the function immediately. */
349 if (direct)
350 return adjust_exit_status (run_test_function (argc, argv, config));
352 /* Set up the test environment:
353 - prevent core dumps
354 - set up the timer
355 - fork and execute the function. */
357 test_pid = fork ();
358 if (test_pid == 0)
360 /* This is the child. */
361 if (disable_coredumps)
363 /* Try to avoid dumping core. This is necessary because we
364 run the test from the source tree, and the coredumps
365 would end up there (and not in the build tree). */
366 struct rlimit core_limit;
367 core_limit.rlim_cur = 0;
368 core_limit.rlim_max = 0;
369 setrlimit (RLIMIT_CORE, &core_limit);
372 /* We put the test process in its own pgrp so that if it bogusly
373 generates any job control signals, they won't hit the whole build. */
374 if (setpgid (0, 0) != 0)
375 printf ("Failed to set the process group ID: %m\n");
377 /* Execute the test function and exit with the return value. */
378 exit (run_test_function (argc, argv, config));
380 else if (test_pid < 0)
382 printf ("Cannot fork test program: %m\n");
383 exit (1);
386 /* Set timeout. */
387 signal (SIGALRM, signal_handler);
388 alarm (timeout * timeoutfactor);
390 /* Make sure we clean up if the wrapper gets interrupted. */
391 signal (SIGINT, signal_handler);
393 /* Wait for the regular termination. */
394 termpid = TEMP_FAILURE_RETRY (waitpid (test_pid, &status, 0));
395 if (termpid == -1)
397 printf ("Waiting for test program failed: %m\n");
398 exit (1);
400 if (termpid != test_pid)
402 printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
403 (long int) test_pid, (long int) termpid);
404 exit (1);
407 /* Process terminated normaly without timeout etc. */
408 if (WIFEXITED (status))
410 if (config->expected_status == 0)
412 if (config->expected_signal == 0)
413 /* Exit with the return value of the test. */
414 return adjust_exit_status (WEXITSTATUS (status));
415 else
417 printf ("Expected signal '%s' from child, got none\n",
418 strsignal (config->expected_signal));
419 exit (1);
422 else
424 /* Non-zero exit status is expected */
425 if (WEXITSTATUS (status) != config->expected_status)
427 printf ("Expected status %d, got %d\n",
428 config->expected_status, WEXITSTATUS (status));
429 exit (1);
432 return adjust_exit_status (0);
434 /* Process was killed by timer or other signal. */
435 else
437 if (config->expected_signal == 0)
439 printf ("Didn't expect signal from child: got `%s'\n",
440 strsignal (WTERMSIG (status)));
441 exit (1);
443 else if (WTERMSIG (status) != config->expected_signal)
445 printf ("Incorrect signal from child: got `%s', need `%s'\n",
446 strsignal (WTERMSIG (status)),
447 strsignal (config->expected_signal));
448 exit (1);
451 return adjust_exit_status (0);