Add narrowing square root functions
[glibc.git] / support / support_test_main.c
blob07e3cdd173cecfc0bf0293010acd2900ddb578be
1 /* Main worker function for the test driver.
2 Copyright (C) 1998-2021 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>
22 #include <support/support.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <getopt.h>
27 #include <malloc.h>
28 #include <signal.h>
29 #include <stdbool.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/param.h>
33 #include <sys/resource.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37 #include <time.h>
38 #include <unistd.h>
40 #include <xstdio.h>
42 static const struct option default_options[] =
44 TEST_DEFAULT_OPTIONS
45 { NULL, 0, NULL, 0 }
48 /* Show people how to run the program. */
49 static void
50 usage (const struct option *options)
52 size_t i;
54 printf ("Usage: %s [options]\n"
55 "\n"
56 "Environment Variables:\n"
57 " TIMEOUTFACTOR An integer used to scale the timeout\n"
58 " TMPDIR Where to place temporary files\n"
59 " TEST_COREDUMPS Do not disable coredumps if set\n"
60 "\n",
61 program_invocation_short_name);
62 printf ("Options:\n");
63 for (i = 0; options[i].name; ++i)
65 int indent;
67 indent = printf (" --%s", options[i].name);
68 if (options[i].has_arg == required_argument)
69 indent += printf (" <arg>");
70 printf ("%*s", 25 - indent, "");
71 switch (options[i].val)
73 case 'v':
74 printf ("Increase the output verbosity");
75 break;
76 case OPT_DIRECT:
77 printf ("Run the test directly (instead of forking & monitoring)");
78 break;
79 case OPT_TESTDIR:
80 printf ("Override the TMPDIR env var");
81 break;
83 printf ("\n");
87 /* The PID of the test process. */
88 static pid_t test_pid;
90 /* The cleanup handler passed to test_main. */
91 static void (*cleanup_function) (void);
93 static void
94 print_timestamp (const char *what, struct timespec tv)
96 struct tm tm;
97 /* Casts of tv.tv_nsec below are necessary because the type of
98 tv_nsec is not literally long int on all supported platforms. */
99 if (gmtime_r (&tv.tv_sec, &tm) == NULL)
100 printf ("%s: %lld.%09ld\n",
101 what, (long long int) tv.tv_sec, (long int) tv.tv_nsec);
102 else
103 printf ("%s: %04d-%02d-%02dT%02d:%02d:%02d.%09ld\n",
104 what, 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
105 tm.tm_hour, tm.tm_min, tm.tm_sec, (long int) tv.tv_nsec);
108 /* Timeout handler. We kill the child and exit with an error. */
109 static void
110 __attribute__ ((noreturn))
111 signal_handler (int sig)
113 int killed;
114 int status;
116 /* Do this first to avoid further interference from the
117 subprocess. */
118 struct timespec now;
119 clock_gettime (CLOCK_REALTIME, &now);
120 struct stat64 st;
121 bool st_available = fstat64 (STDOUT_FILENO, &st) == 0 && st.st_mtime != 0;
123 assert (test_pid > 1);
124 /* Kill the whole process group. */
125 kill (-test_pid, SIGKILL);
126 /* In case setpgid failed in the child, kill it individually too. */
127 kill (test_pid, SIGKILL);
129 /* Wait for it to terminate. */
130 int i;
131 for (i = 0; i < 5; ++i)
133 killed = waitpid (test_pid, &status, WNOHANG|WUNTRACED);
134 if (killed != 0)
135 break;
137 /* Delay, give the system time to process the kill. If the
138 nanosleep() call return prematurely, all the better. We
139 won't restart it since this probably means the child process
140 finally died. */
141 struct timespec ts;
142 ts.tv_sec = 0;
143 ts.tv_nsec = 100000000;
144 nanosleep (&ts, NULL);
146 if (killed != 0 && killed != test_pid)
148 printf ("Failed to kill test process: %m\n");
149 exit (1);
152 if (cleanup_function != NULL)
153 cleanup_function ();
155 if (sig == SIGINT)
157 signal (sig, SIG_DFL);
158 raise (sig);
161 if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
162 puts ("Timed out: killed the child process");
163 else if (WIFSTOPPED (status))
164 printf ("Timed out: the child process was %s\n",
165 strsignal (WSTOPSIG (status)));
166 else if (WIFSIGNALED (status))
167 printf ("Timed out: the child process got signal %s\n",
168 strsignal (WTERMSIG (status)));
169 else
170 printf ("Timed out: killed the child process but it exited %d\n",
171 WEXITSTATUS (status));
173 print_timestamp ("Termination time", now);
174 if (st_available)
175 print_timestamp ("Last write to standard output", st.st_mtim);
177 /* Exit with an error. */
178 exit (1);
181 /* This must be volatile as it will be modified by the debugger. */
182 static volatile int wait_for_debugger = 0;
184 /* Run test_function or test_function_argv. */
185 static int
186 run_test_function (int argc, char **argv, const struct test_config *config)
188 const char *wfd = getenv("WAIT_FOR_DEBUGGER");
189 if (wfd != NULL)
190 wait_for_debugger = atoi (wfd);
191 if (wait_for_debugger)
193 pid_t mypid;
194 FILE *gdb_script;
195 char *gdb_script_name;
196 int inside_container = 0;
198 mypid = getpid();
199 if (mypid < 3)
201 const char *outside_pid = getenv("PID_OUTSIDE_CONTAINER");
202 if (outside_pid)
204 mypid = atoi (outside_pid);
205 inside_container = 1;
209 gdb_script_name = (char *) xmalloc (strlen (argv[0]) + strlen (".gdb") + 1);
210 sprintf (gdb_script_name, "%s.gdb", argv[0]);
211 gdb_script = xfopen (gdb_script_name, "w");
213 fprintf (stderr, "Waiting for debugger, test process is pid %d\n", mypid);
214 fprintf (stderr, "gdb -x %s\n", gdb_script_name);
215 if (inside_container)
216 fprintf (gdb_script, "set sysroot %s/testroot.root\n", support_objdir_root);
217 fprintf (gdb_script, "file\n");
218 fprintf (gdb_script, "file %s\n", argv[0]);
219 fprintf (gdb_script, "symbol-file %s\n", argv[0]);
220 fprintf (gdb_script, "exec-file %s\n", argv[0]);
221 fprintf (gdb_script, "attach %ld\n", (long int) mypid);
222 fprintf (gdb_script, "set wait_for_debugger = 0\n");
223 fclose (gdb_script);
224 free (gdb_script_name);
227 /* Wait for the debugger to set wait_for_debugger to zero. */
228 while (wait_for_debugger)
229 usleep (1000);
231 if (config->test_function != NULL)
232 return config->test_function ();
233 else if (config->test_function_argv != NULL)
234 return config->test_function_argv (argc, argv);
235 else
237 printf ("error: no test function defined\n");
238 exit (1);
242 static bool test_main_called;
244 const char *test_dir = NULL;
245 unsigned int test_verbose = 0;
247 /* If test failure reporting has been linked in, it may contribute
248 additional test failures. */
249 static int
250 adjust_exit_status (int status)
252 if (support_report_failure != NULL)
253 return support_report_failure (status);
254 return status;
258 support_test_main (int argc, char **argv, const struct test_config *config)
260 if (test_main_called)
262 printf ("error: test_main called for a second time\n");
263 exit (1);
265 test_main_called = true;
266 const struct option *options;
267 if (config->options != NULL)
268 options = config->options;
269 else
270 options = default_options;
272 cleanup_function = config->cleanup_function;
274 int direct = 0; /* Directly call the test function? */
275 int status;
276 int opt;
277 unsigned int timeoutfactor = 1;
278 pid_t termpid;
280 /* If we're debugging the test, we need to disable timeouts and use
281 the initial pid (esp if we're running inside a container). */
282 if (getenv("WAIT_FOR_DEBUGGER") != NULL)
283 direct = 1;
285 if (!config->no_mallopt)
287 /* Make uses of freed and uninitialized memory known. Do not
288 pull in a definition for mallopt if it has not been defined
289 already. */
290 extern __typeof__ (mallopt) mallopt __attribute__ ((weak));
291 if (mallopt != NULL)
292 mallopt (M_PERTURB, 42);
295 while ((opt = getopt_long (argc, argv, config->optstring, options, NULL))
296 != -1)
297 switch (opt)
299 case '?':
300 usage (options);
301 exit (1);
302 case 'v':
303 ++test_verbose;
304 break;
305 case OPT_DIRECT:
306 direct = 1;
307 break;
308 case OPT_TESTDIR:
309 test_dir = optarg;
310 break;
311 default:
312 if (config->cmdline_function != NULL)
313 config->cmdline_function (opt);
316 /* If set, read the test TIMEOUTFACTOR value from the environment.
317 This value is used to scale the default test timeout values. */
318 char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
319 if (envstr_timeoutfactor != NULL)
321 char *envstr_conv = envstr_timeoutfactor;
322 unsigned long int env_fact;
324 env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
325 if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
326 timeoutfactor = MAX (env_fact, 1);
329 /* Set TMPDIR to specified test directory. */
330 if (test_dir != NULL)
332 setenv ("TMPDIR", test_dir, 1);
334 if (chdir (test_dir) < 0)
336 printf ("chdir: %m\n");
337 exit (1);
340 else
342 test_dir = getenv ("TMPDIR");
343 if (test_dir == NULL || test_dir[0] == '\0')
344 test_dir = "/tmp";
346 if (support_set_test_dir != NULL)
347 support_set_test_dir (test_dir);
349 int timeout = config->timeout;
350 if (timeout == 0)
351 timeout = DEFAULT_TIMEOUT;
353 /* Make sure we see all message, even those on stdout. */
354 if (!config->no_setvbuf)
355 setvbuf (stdout, NULL, _IONBF, 0);
357 /* Make sure temporary files are deleted. */
358 if (support_delete_temp_files != NULL)
359 atexit (support_delete_temp_files);
361 /* Correct for the possible parameters. */
362 argv[optind - 1] = argv[0];
363 argv += optind - 1;
364 argc -= optind - 1;
366 /* Call the initializing function, if one is available. */
367 if (config->prepare_function != NULL)
368 config->prepare_function (argc, argv);
370 const char *envstr_direct = getenv ("TEST_DIRECT");
371 if (envstr_direct != NULL)
373 FILE *f = fopen (envstr_direct, "w");
374 if (f == NULL)
376 printf ("cannot open TEST_DIRECT output file '%s': %m\n",
377 envstr_direct);
378 exit (1);
381 fprintf (f, "timeout=%u\ntimeoutfactor=%u\n",
382 config->timeout, timeoutfactor);
383 if (config->expected_status != 0)
384 fprintf (f, "exit=%u\n", config->expected_status);
385 if (config->expected_signal != 0)
386 fprintf (f, "signal=%s\n", strsignal (config->expected_signal));
388 if (support_print_temp_files != NULL)
389 support_print_temp_files (f);
391 fclose (f);
392 direct = 1;
395 bool disable_coredumps;
397 const char *coredumps = getenv ("TEST_COREDUMPS");
398 disable_coredumps = coredumps == NULL || coredumps[0] == '\0';
401 /* If we are not expected to fork run the function immediately. */
402 if (direct)
403 return adjust_exit_status (run_test_function (argc, argv, config));
405 /* Set up the test environment:
406 - prevent core dumps
407 - set up the timer
408 - fork and execute the function. */
410 test_pid = fork ();
411 if (test_pid == 0)
413 /* This is the child. */
414 if (disable_coredumps)
416 /* Try to avoid dumping core. This is necessary because we
417 run the test from the source tree, and the coredumps
418 would end up there (and not in the build tree). */
419 struct rlimit core_limit;
420 core_limit.rlim_cur = 0;
421 core_limit.rlim_max = 0;
422 setrlimit (RLIMIT_CORE, &core_limit);
425 /* We put the test process in its own pgrp so that if it bogusly
426 generates any job control signals, they won't hit the whole build. */
427 if (setpgid (0, 0) != 0)
428 printf ("Failed to set the process group ID: %m\n");
430 /* Execute the test function and exit with the return value. */
431 exit (run_test_function (argc, argv, config));
433 else if (test_pid < 0)
435 printf ("Cannot fork test program: %m\n");
436 exit (1);
439 /* Set timeout. */
440 signal (SIGALRM, signal_handler);
441 alarm (timeout * timeoutfactor);
443 /* Make sure we clean up if the wrapper gets interrupted. */
444 signal (SIGINT, signal_handler);
446 /* Wait for the regular termination. */
447 termpid = TEMP_FAILURE_RETRY (waitpid (test_pid, &status, 0));
448 if (termpid == -1)
450 printf ("Waiting for test program failed: %m\n");
451 exit (1);
453 if (termpid != test_pid)
455 printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
456 (long int) test_pid, (long int) termpid);
457 exit (1);
460 /* Process terminated normaly without timeout etc. */
461 if (WIFEXITED (status))
463 if (config->expected_status == 0)
465 if (config->expected_signal == 0)
466 /* Exit with the return value of the test. */
467 return adjust_exit_status (WEXITSTATUS (status));
468 else
470 printf ("Expected signal '%s' from child, got none\n",
471 strsignal (config->expected_signal));
472 exit (1);
475 else
477 /* Non-zero exit status is expected */
478 if (WEXITSTATUS (status) != config->expected_status)
480 printf ("Expected status %d, got %d\n",
481 config->expected_status, WEXITSTATUS (status));
482 exit (1);
485 return adjust_exit_status (0);
487 /* Process was killed by timer or other signal. */
488 else
490 if (config->expected_signal == 0)
492 printf ("Didn't expect signal from child: got `%s'\n",
493 strsignal (WTERMSIG (status)));
494 exit (1);
496 else if (WTERMSIG (status) != config->expected_signal)
498 printf ("Incorrect signal from child: got `%s', need `%s'\n",
499 strsignal (WTERMSIG (status)),
500 strsignal (config->expected_signal));
501 exit (1);
504 return adjust_exit_status (0);