packaging: add --disable-experimental-malloc
[platform/upstream/glibc.git] / support / support_test_main.c
1 /* Main worker function for the test driver.
2    Copyright (C) 1998-2023 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
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.
9
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.
14
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/>.  */
18
19 #include <support/test-driver.h>
20 #include <support/check.h>
21 #include <support/temp_file-internal.h>
22 #include <support/support.h>
23
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>
39
40 #include <xstdio.h>
41
42 static const struct option default_options[] =
43 {
44   TEST_DEFAULT_OPTIONS
45   { NULL, 0, NULL, 0 }
46 };
47
48 /* Show people how to run the program.  */
49 static void
50 usage (const struct option *options)
51 {
52   size_t i;
53
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)
64     {
65       int indent;
66
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)
72         {
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;
82         }
83       printf ("\n");
84     }
85 }
86
87 /* The PID of the test process.  */
88 static pid_t test_pid;
89
90 /* The cleanup handler passed to test_main.  */
91 static void (*cleanup_function) (void);
92
93 static void
94 print_timestamp (const char *what, struct timespec tv)
95 {
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);
106 }
107
108 /* Timeout handler.  We kill the child and exit with an error.  */
109 static void
110 __attribute__ ((noreturn))
111 signal_handler (int sig)
112 {
113   int killed;
114   int status;
115
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;
122
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);
128
129   /* Wait for it to terminate.  */
130   int i;
131   for (i = 0; i < 5; ++i)
132     {
133       killed = waitpid (test_pid, &status, WNOHANG|WUNTRACED);
134       if (killed != 0)
135         break;
136
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);
145     }
146   if (killed != 0 && killed != test_pid)
147     {
148       printf ("Failed to kill test process: %m\n");
149       exit (1);
150     }
151
152   if (cleanup_function != NULL)
153     cleanup_function ();
154
155   if (sig == SIGINT)
156     {
157       signal (sig, SIG_DFL);
158       raise (sig);
159     }
160
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));
172
173   print_timestamp ("Termination time", now);
174   if (st_available)
175     print_timestamp ("Last write to standard output", st.st_mtim);
176
177   /* Exit with an error.  */
178   exit (1);
179 }
180
181 /* This must be volatile as it will be modified by the debugger.  */
182 static volatile int wait_for_debugger = 0;
183
184 /* Run test_function or test_function_argv.  */
185 static int
186 run_test_function (int argc, char **argv, const struct test_config *config)
187 {
188   const char *wfd = getenv("WAIT_FOR_DEBUGGER");
189   if (wfd != NULL)
190     wait_for_debugger = atoi (wfd);
191   if (wait_for_debugger)
192     {
193       pid_t mypid;
194       FILE *gdb_script;
195       char *gdb_script_name;
196       int inside_container = 0;
197
198       mypid = getpid();
199       if (mypid < 3)
200         {
201           const char *outside_pid = getenv("PID_OUTSIDE_CONTAINER");
202           if (outside_pid)
203             {
204               mypid = atoi (outside_pid);
205               inside_container = 1;
206             }
207         }
208
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");
212
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);
225     }
226
227   /* Wait for the debugger to set wait_for_debugger to zero.  */
228   while (wait_for_debugger)
229     usleep (1000);
230
231   if (config->run_command_mode)
232     {
233       /* In run-command-mode, the child process executes the command line
234          arguments as a new program.  */
235       char **argv_ = xmalloc (sizeof (char *) * argc);
236       memcpy (argv_, &argv[1], sizeof (char *) * (argc - 1));
237       argv_[argc - 1] = NULL;
238       execv (argv_[0], argv_);
239       printf ("error: should not return here\n");
240       exit (1);
241     }
242
243   if (config->test_function != NULL)
244     return config->test_function ();
245   else if (config->test_function_argv != NULL)
246     return config->test_function_argv (argc, argv);
247   else
248     {
249       printf ("error: no test function defined\n");
250       exit (1);
251     }
252 }
253
254 static bool test_main_called;
255
256 const char *test_dir = NULL;
257 unsigned int test_verbose = 0;
258
259 /* If test failure reporting has been linked in, it may contribute
260    additional test failures.  */
261 static int
262 adjust_exit_status (int status)
263 {
264   if (support_report_failure != NULL)
265     return support_report_failure (status);
266   return status;
267 }
268
269 int
270 support_test_main (int argc, char **argv, const struct test_config *config)
271 {
272   if (test_main_called)
273     {
274       printf ("error: test_main called for a second time\n");
275       exit (1);
276     }
277   test_main_called = true;
278   const struct option *options;
279   if (config->options != NULL)
280     options = config->options;
281   else
282     options = default_options;
283
284   cleanup_function = config->cleanup_function;
285
286   int direct = 0;       /* Directly call the test function?  */
287   int status;
288   int opt;
289   unsigned int timeoutfactor = TIMEOUTFACTOR;
290   pid_t termpid;
291
292   /* If we're debugging the test, we need to disable timeouts and use
293      the initial pid (esp if we're running inside a container).  */
294   if (getenv("WAIT_FOR_DEBUGGER") != NULL)
295     direct = 1;
296
297   if (!config->no_mallopt)
298     {
299       /* Make uses of freed and uninitialized memory known.  Do not
300          pull in a definition for mallopt if it has not been defined
301          already.  */
302       extern __typeof__ (mallopt) mallopt __attribute__ ((weak));
303       if (mallopt != NULL)
304         mallopt (M_PERTURB, 42);
305     }
306
307   while ((opt = getopt_long (argc, argv, config->optstring, options, NULL))
308          != -1)
309     switch (opt)
310       {
311       case '?':
312         usage (options);
313         exit (1);
314       case 'v':
315         ++test_verbose;
316         break;
317       case OPT_DIRECT:
318         direct = 1;
319         break;
320       case OPT_TESTDIR:
321         test_dir = optarg;
322         break;
323       default:
324         if (config->cmdline_function != NULL)
325           config->cmdline_function (opt);
326       }
327
328   /* If set, read the test TIMEOUTFACTOR value from the environment.
329      This value is used to scale the default test timeout values. */
330   char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
331   if (envstr_timeoutfactor != NULL)
332     {
333       char *envstr_conv = envstr_timeoutfactor;
334       unsigned long int env_fact;
335
336       env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
337       if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
338         timeoutfactor = MAX (env_fact, 1);
339     }
340
341   /* Set TMPDIR to specified test directory.  */
342   if (test_dir != NULL)
343     {
344       setenv ("TMPDIR", test_dir, 1);
345
346       if (chdir (test_dir) < 0)
347         {
348           printf ("chdir: %m\n");
349           exit (1);
350         }
351     }
352   else
353     {
354       test_dir = getenv ("TMPDIR");
355       if (test_dir == NULL || test_dir[0] == '\0')
356         test_dir = "/tmp";
357     }
358   if (support_set_test_dir != NULL)
359     support_set_test_dir (test_dir);
360
361   int timeout = config->timeout;
362   if (timeout == 0)
363     timeout =  DEFAULT_TIMEOUT;
364
365   /* Make sure we see all message, even those on stdout.  */
366   if (!config->no_setvbuf)
367     setvbuf (stdout, NULL, _IONBF, 0);
368
369   /* Make sure temporary files are deleted.  */
370   if (support_delete_temp_files != NULL)
371       atexit (support_delete_temp_files);
372
373   /* Correct for the possible parameters.  */
374   argv[optind - 1] = argv[0];
375   argv += optind - 1;
376   argc -= optind - 1;
377
378   /* Call the initializing function, if one is available.  */
379   if (config->prepare_function != NULL)
380     config->prepare_function (argc, argv);
381
382   const char *envstr_direct = getenv ("TEST_DIRECT");
383   if (envstr_direct != NULL)
384     {
385       FILE *f = fopen (envstr_direct, "w");
386       if (f == NULL)
387         {
388           printf ("cannot open TEST_DIRECT output file '%s': %m\n",
389                   envstr_direct);
390           exit (1);
391         }
392
393       fprintf (f, "timeout=%u\ntimeoutfactor=%u\n",
394                config->timeout, timeoutfactor);
395       if (config->expected_status != 0)
396         fprintf (f, "exit=%u\n", config->expected_status);
397       if (config->expected_signal != 0)
398         fprintf (f, "signal=%s\n", strsignal (config->expected_signal));
399
400       if (support_print_temp_files != NULL)
401         support_print_temp_files (f);
402
403       fclose (f);
404       direct = 1;
405     }
406
407   bool disable_coredumps;
408   {
409     const char *coredumps = getenv ("TEST_COREDUMPS");
410     disable_coredumps = coredumps == NULL || coredumps[0] == '\0';
411   }
412
413   /* If we are not expected to fork run the function immediately.  */
414   if (direct)
415     return adjust_exit_status (run_test_function (argc, argv, config));
416
417   /* Set up the test environment:
418      - prevent core dumps
419      - set up the timer
420      - fork and execute the function.  */
421
422   test_pid = fork ();
423   if (test_pid == 0)
424     {
425       /* This is the child.  */
426       if (disable_coredumps)
427         {
428           /* Try to avoid dumping core.  This is necessary because we
429              run the test from the source tree, and the coredumps
430              would end up there (and not in the build tree).  */
431           struct rlimit core_limit;
432           core_limit.rlim_cur = 0;
433           core_limit.rlim_max = 0;
434           setrlimit (RLIMIT_CORE, &core_limit);
435         }
436
437       /* We put the test process in its own pgrp so that if it bogusly
438          generates any job control signals, they won't hit the whole build.  */
439       if (setpgid (0, 0) != 0)
440         printf ("Failed to set the process group ID: %m\n");
441
442       /* Execute the test function and exit with the return value.   */
443       exit (run_test_function (argc, argv, config));
444     }
445   else if (test_pid < 0)
446     {
447       printf ("Cannot fork test program: %m\n");
448       exit (1);
449     }
450
451   /* Set timeout.  */
452   signal (SIGALRM, signal_handler);
453   alarm (timeout * timeoutfactor);
454
455   /* Make sure we clean up if the wrapper gets interrupted.  */
456   signal (SIGINT, signal_handler);
457
458   /* Wait for the regular termination.  */
459   termpid = TEMP_FAILURE_RETRY (waitpid (test_pid, &status, 0));
460   if (termpid == -1)
461     {
462       printf ("Waiting for test program failed: %m\n");
463       exit (1);
464     }
465   if (termpid != test_pid)
466     {
467       printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
468               (long int) test_pid, (long int) termpid);
469       exit (1);
470     }
471
472   /* Process terminated normaly without timeout etc.  */
473   if (WIFEXITED (status))
474     {
475       if (config->expected_status == 0)
476         {
477           if (config->expected_signal == 0)
478             /* Exit with the return value of the test.  */
479             return adjust_exit_status (WEXITSTATUS (status));
480           else
481             {
482               printf ("Expected signal '%s' from child, got none\n",
483                       strsignal (config->expected_signal));
484               exit (1);
485             }
486         }
487       else
488         {
489           /* Non-zero exit status is expected */
490           if (WEXITSTATUS (status) != config->expected_status)
491             {
492               printf ("Expected status %d, got %d\n",
493                       config->expected_status, WEXITSTATUS (status));
494               exit (1);
495             }
496         }
497       return adjust_exit_status (0);
498     }
499   /* Process was killed by timer or other signal.  */
500   else
501     {
502       if (config->expected_signal == 0)
503         {
504           printf ("Didn't expect signal from child: got `%s'\n",
505                   strsignal (WTERMSIG (status)));
506           exit (1);
507         }
508       else if (WTERMSIG (status) != config->expected_signal)
509         {
510           printf ("Incorrect signal from child: got `%s', need `%s'\n",
511                   strsignal (WTERMSIG (status)),
512                   strsignal (config->expected_signal));
513           exit (1);
514         }
515
516       return adjust_exit_status (0);
517     }
518 }