1 /* Main worker function for the test driver.
2 Copyright (C) 1998-2018 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 <http://www.gnu.org/licenses/>. */
19 #include <support/test-driver.h>
20 #include <support/check.h>
21 #include <support/temp_file-internal.h>
31 #include <sys/param.h>
32 #include <sys/resource.h>
33 #include <sys/types.h>
38 static const struct option default_options
[] =
44 /* Show people how to run the program. */
46 usage (const struct option
*options
)
50 printf ("Usage: %s [options]\n"
52 "Environment Variables:\n"
53 " TIMEOUTFACTOR An integer used to scale the timeout\n"
54 " TMPDIR Where to place temporary files\n"
55 " TEST_COREDUMPS Do not disable coredumps if set\n"
57 program_invocation_short_name
);
58 printf ("Options:\n");
59 for (i
= 0; options
[i
].name
; ++i
)
63 indent
= printf (" --%s", options
[i
].name
);
64 if (options
[i
].has_arg
== required_argument
)
65 indent
+= printf (" <arg>");
66 printf ("%*s", 25 - indent
, "");
67 switch (options
[i
].val
)
70 printf ("Increase the output verbosity");
73 printf ("Run the test directly (instead of forking & monitoring)");
76 printf ("Override the TMPDIR env var");
83 /* The PID of the test process. */
84 static pid_t test_pid
;
86 /* The cleanup handler passed to test_main. */
87 static void (*cleanup_function
) (void);
89 /* Timeout handler. We kill the child and exit with an error. */
91 __attribute__ ((noreturn
))
92 signal_handler (int sig
)
97 assert (test_pid
> 1);
98 /* Kill the whole process group. */
99 kill (-test_pid
, SIGKILL
);
100 /* In case setpgid failed in the child, kill it individually too. */
101 kill (test_pid
, SIGKILL
);
103 /* Wait for it to terminate. */
105 for (i
= 0; i
< 5; ++i
)
107 killed
= waitpid (test_pid
, &status
, WNOHANG
|WUNTRACED
);
111 /* Delay, give the system time to process the kill. If the
112 nanosleep() call return prematurely, all the better. We
113 won't restart it since this probably means the child process
117 ts
.tv_nsec
= 100000000;
118 nanosleep (&ts
, NULL
);
120 if (killed
!= 0 && killed
!= test_pid
)
122 printf ("Failed to kill test process: %m\n");
126 if (cleanup_function
!= NULL
)
131 signal (sig
, SIG_DFL
);
135 if (killed
== 0 || (WIFSIGNALED (status
) && WTERMSIG (status
) == SIGKILL
))
136 puts ("Timed out: killed the child process");
137 else if (WIFSTOPPED (status
))
138 printf ("Timed out: the child process was %s\n",
139 strsignal (WSTOPSIG (status
)));
140 else if (WIFSIGNALED (status
))
141 printf ("Timed out: the child process got signal %s\n",
142 strsignal (WTERMSIG (status
)));
144 printf ("Timed out: killed the child process but it exited %d\n",
145 WEXITSTATUS (status
));
147 /* Exit with an error. */
151 /* Run test_function or test_function_argv. */
153 run_test_function (int argc
, char **argv
, const struct test_config
*config
)
155 if (config
->test_function
!= NULL
)
156 return config
->test_function ();
157 else if (config
->test_function_argv
!= NULL
)
158 return config
->test_function_argv (argc
, argv
);
161 printf ("error: no test function defined\n");
166 static bool test_main_called
;
168 const char *test_dir
= NULL
;
169 unsigned int test_verbose
= 0;
171 /* If test failure reporting has been linked in, it may contribute
172 additional test failures. */
174 adjust_exit_status (int status
)
176 if (support_report_failure
!= NULL
)
177 return support_report_failure (status
);
182 support_test_main (int argc
, char **argv
, const struct test_config
*config
)
184 if (test_main_called
)
186 printf ("error: test_main called for a second time\n");
189 test_main_called
= true;
190 const struct option
*options
;
191 if (config
->options
!= NULL
)
192 options
= config
->options
;
194 options
= default_options
;
196 cleanup_function
= config
->cleanup_function
;
198 int direct
= 0; /* Directly call the test function? */
201 unsigned int timeoutfactor
= 1;
204 if (!config
->no_mallopt
)
206 /* Make uses of freed and uninitialized memory known. Do not
207 pull in a definition for mallopt if it has not been defined
209 extern __typeof__ (mallopt
) mallopt
__attribute__ ((weak
));
211 mallopt (M_PERTURB
, 42);
214 while ((opt
= getopt_long (argc
, argv
, config
->optstring
, options
, NULL
))
231 if (config
->cmdline_function
!= NULL
)
232 config
->cmdline_function (opt
);
235 /* If set, read the test TIMEOUTFACTOR value from the environment.
236 This value is used to scale the default test timeout values. */
237 char *envstr_timeoutfactor
= getenv ("TIMEOUTFACTOR");
238 if (envstr_timeoutfactor
!= NULL
)
240 char *envstr_conv
= envstr_timeoutfactor
;
241 unsigned long int env_fact
;
243 env_fact
= strtoul (envstr_timeoutfactor
, &envstr_conv
, 0);
244 if (*envstr_conv
== '\0' && envstr_conv
!= envstr_timeoutfactor
)
245 timeoutfactor
= MAX (env_fact
, 1);
248 /* Set TMPDIR to specified test directory. */
249 if (test_dir
!= NULL
)
251 setenv ("TMPDIR", test_dir
, 1);
253 if (chdir (test_dir
) < 0)
255 printf ("chdir: %m\n");
261 test_dir
= getenv ("TMPDIR");
262 if (test_dir
== NULL
|| test_dir
[0] == '\0')
265 if (support_set_test_dir
!= NULL
)
266 support_set_test_dir (test_dir
);
268 int timeout
= config
->timeout
;
270 timeout
= DEFAULT_TIMEOUT
;
272 /* Make sure we see all message, even those on stdout. */
273 if (!config
->no_setvbuf
)
274 setvbuf (stdout
, NULL
, _IONBF
, 0);
276 /* Make sure temporary files are deleted. */
277 if (support_delete_temp_files
!= NULL
)
278 atexit (support_delete_temp_files
);
280 /* Correct for the possible parameters. */
281 argv
[optind
- 1] = argv
[0];
285 /* Call the initializing function, if one is available. */
286 if (config
->prepare_function
!= NULL
)
287 config
->prepare_function (argc
, argv
);
289 const char *envstr_direct
= getenv ("TEST_DIRECT");
290 if (envstr_direct
!= NULL
)
292 FILE *f
= fopen (envstr_direct
, "w");
295 printf ("cannot open TEST_DIRECT output file '%s': %m\n",
300 fprintf (f
, "timeout=%u\ntimeoutfactor=%u\n",
301 config
->timeout
, timeoutfactor
);
302 if (config
->expected_status
!= 0)
303 fprintf (f
, "exit=%u\n", config
->expected_status
);
304 if (config
->expected_signal
!= 0)
305 fprintf (f
, "signal=%s\n", strsignal (config
->expected_signal
));
307 if (support_print_temp_files
!= NULL
)
308 support_print_temp_files (f
);
314 bool disable_coredumps
;
316 const char *coredumps
= getenv ("TEST_COREDUMPS");
317 disable_coredumps
= coredumps
== NULL
|| coredumps
[0] == '\0';
320 /* If we are not expected to fork run the function immediately. */
322 return adjust_exit_status (run_test_function (argc
, argv
, config
));
324 /* Set up the test environment:
327 - fork and execute the function. */
332 /* This is the child. */
333 if (disable_coredumps
)
335 /* Try to avoid dumping core. This is necessary because we
336 run the test from the source tree, and the coredumps
337 would end up there (and not in the build tree). */
338 struct rlimit core_limit
;
339 core_limit
.rlim_cur
= 0;
340 core_limit
.rlim_max
= 0;
341 setrlimit (RLIMIT_CORE
, &core_limit
);
344 /* We put the test process in its own pgrp so that if it bogusly
345 generates any job control signals, they won't hit the whole build. */
346 if (setpgid (0, 0) != 0)
347 printf ("Failed to set the process group ID: %m\n");
349 /* Execute the test function and exit with the return value. */
350 exit (run_test_function (argc
, argv
, config
));
352 else if (test_pid
< 0)
354 printf ("Cannot fork test program: %m\n");
359 signal (SIGALRM
, signal_handler
);
360 alarm (timeout
* timeoutfactor
);
362 /* Make sure we clean up if the wrapper gets interrupted. */
363 signal (SIGINT
, signal_handler
);
365 /* Wait for the regular termination. */
366 termpid
= TEMP_FAILURE_RETRY (waitpid (test_pid
, &status
, 0));
369 printf ("Waiting for test program failed: %m\n");
372 if (termpid
!= test_pid
)
374 printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
375 (long int) test_pid
, (long int) termpid
);
379 /* Process terminated normaly without timeout etc. */
380 if (WIFEXITED (status
))
382 if (config
->expected_status
== 0)
384 if (config
->expected_signal
== 0)
385 /* Exit with the return value of the test. */
386 return adjust_exit_status (WEXITSTATUS (status
));
389 printf ("Expected signal '%s' from child, got none\n",
390 strsignal (config
->expected_signal
));
396 /* Non-zero exit status is expected */
397 if (WEXITSTATUS (status
) != config
->expected_status
)
399 printf ("Expected status %d, got %d\n",
400 config
->expected_status
, WEXITSTATUS (status
));
404 return adjust_exit_status (0);
406 /* Process was killed by timer or other signal. */
409 if (config
->expected_signal
== 0)
411 printf ("Didn't expect signal from child: got `%s'\n",
412 strsignal (WTERMSIG (status
)));
415 else if (WTERMSIG (status
) != config
->expected_signal
)
417 printf ("Incorrect signal from child: got `%s', need `%s'\n",
418 strsignal (WTERMSIG (status
)),
419 strsignal (config
->expected_signal
));
423 return adjust_exit_status (0);