malloc: Run tests without calling mallopt [BZ #19469]
[platform/upstream/glibc.git] / test-skeleton.c
1 /* Skeleton for test programs.
2    Copyright (C) 1998-2016 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <assert.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <getopt.h>
24 #include <malloc.h>
25 #include <paths.h>
26 #include <search.h>
27 #include <signal.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/resource.h>
33 #include <sys/wait.h>
34 #include <sys/param.h>
35 #include <time.h>
36
37 /* The test function is normally called `do_test' and it is called
38    with argc and argv as the arguments.  We nevertheless provide the
39    possibility to overwrite this name.  */
40 #ifndef TEST_FUNCTION
41 # define TEST_FUNCTION do_test (argc, argv)
42 #endif
43
44 #ifndef TEST_DATA_LIMIT
45 # define TEST_DATA_LIMIT (64 << 20) /* Data limit (bytes) to run with.  */
46 #endif
47
48 #ifndef TIMEOUT
49   /* Default timeout is twenty seconds.  Tests should normally complete faster
50      than this, but if they don't, that's abnormal (a bug) anyways.  */
51 # define TIMEOUT 20
52 #endif
53
54 #define OPT_DIRECT 1000
55 #define OPT_TESTDIR 1001
56
57 static struct option options[] =
58 {
59 #ifdef CMDLINE_OPTIONS
60   CMDLINE_OPTIONS
61 #endif
62   { "direct", no_argument, NULL, OPT_DIRECT },
63   { "test-dir", required_argument, NULL, OPT_TESTDIR },
64   { NULL, 0, NULL, 0 }
65 };
66
67 /* PID of the test itself.  */
68 static pid_t pid;
69
70 /* Directory to place temporary files in.  */
71 static const char *test_dir;
72
73 static void
74 oom_error (const char *fn, size_t size)
75 {
76   printf ("%s: unable to allocate %zu bytes: %m\n", fn, size);
77   exit (1);
78 }
79
80 /* Allocate N bytes of memory dynamically, with error checking.  */
81 __attribute__ ((unused))
82 static void *
83 xmalloc (size_t n)
84 {
85   void *p;
86
87   p = malloc (n);
88   if (p == NULL)
89     oom_error ("malloc", n);
90   return p;
91 }
92
93 /* Allocate memory for N elements of S bytes, with error checking.  */
94 __attribute__ ((unused))
95 static void *
96 xcalloc (size_t n, size_t s)
97 {
98   void *p;
99
100   p = calloc (n, s);
101   if (p == NULL)
102     oom_error ("calloc", n * s);
103   return p;
104 }
105
106 /* Change the size of an allocated block of memory P to N bytes,
107    with error checking.  */
108 __attribute__ ((unused))
109 static void *
110 xrealloc (void *p, size_t n)
111 {
112   void *result = realloc (p, n);
113   if (result == NULL && (n > 0 || p == NULL))
114     oom_error ("realloc", n);
115   return result;
116 }
117
118 /* Write a message to standard output.  Can be used in signal
119    handlers.  */
120 static void
121 __attribute__ ((unused))
122 write_message (const char *message)
123 {
124   ssize_t unused __attribute__ ((unused));
125   unused = write (STDOUT_FILENO, message, strlen (message));
126 }
127
128 /* List of temporary files.  */
129 struct temp_name_list
130 {
131   struct qelem q;
132   char *name;
133 } *temp_name_list;
134
135 /* Add temporary files in list.  */
136 static void
137 __attribute__ ((unused))
138 add_temp_file (const char *name)
139 {
140   struct temp_name_list *newp
141     = (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
142   char *newname = strdup (name);
143   if (newname != NULL)
144     {
145       newp->name = newname;
146       if (temp_name_list == NULL)
147         temp_name_list = (struct temp_name_list *) &newp->q;
148       else
149         insque (newp, temp_name_list);
150     }
151   else
152     free (newp);
153 }
154
155 /* Delete all temporary files.  */
156 static void
157 delete_temp_files (void)
158 {
159   while (temp_name_list != NULL)
160     {
161       remove (temp_name_list->name);
162       free (temp_name_list->name);
163
164       struct temp_name_list *next
165         = (struct temp_name_list *) temp_name_list->q.q_forw;
166       free (temp_name_list);
167       temp_name_list = next;
168     }
169 }
170
171 /* Create a temporary file.  Return the opened file descriptor on
172    success, or -1 on failure.  Write the file name to *FILENAME if
173    FILENAME is not NULL.  In this case, the caller is expected to free
174    *FILENAME.  */
175 static int
176 __attribute__ ((unused))
177 create_temp_file (const char *base, char **filename)
178 {
179   char *fname;
180   int fd;
181
182   fname = (char *) xmalloc (strlen (test_dir) + 1 + strlen (base)
183                             + sizeof ("XXXXXX"));
184   strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
185
186   fd = mkstemp (fname);
187   if (fd == -1)
188     {
189       printf ("cannot open temporary file '%s': %m\n", fname);
190       free (fname);
191       return -1;
192     }
193
194   add_temp_file (fname);
195   if (filename != NULL)
196     *filename = fname;
197   else
198     free (fname);
199
200   return fd;
201 }
202
203 /* Timeout handler.  We kill the child and exit with an error.  */
204 static void
205 __attribute__ ((noreturn))
206 signal_handler (int sig __attribute__ ((unused)))
207 {
208   int killed;
209   int status;
210
211   assert (pid > 1);
212   /* Kill the whole process group.  */
213   kill (-pid, SIGKILL);
214   /* In case setpgid failed in the child, kill it individually too.  */
215   kill (pid, SIGKILL);
216
217   /* Wait for it to terminate.  */
218   int i;
219   for (i = 0; i < 5; ++i)
220     {
221       killed = waitpid (pid, &status, WNOHANG|WUNTRACED);
222       if (killed != 0)
223         break;
224
225       /* Delay, give the system time to process the kill.  If the
226          nanosleep() call return prematurely, all the better.  We
227          won't restart it since this probably means the child process
228          finally died.  */
229       struct timespec ts;
230       ts.tv_sec = 0;
231       ts.tv_nsec = 100000000;
232       nanosleep (&ts, NULL);
233     }
234   if (killed != 0 && killed != pid)
235     {
236       printf ("Failed to kill test process: %m\n");
237       exit (1);
238     }
239
240 #ifdef CLEANUP_HANDLER
241   CLEANUP_HANDLER;
242 #endif
243
244   if (sig == SIGINT)
245     {
246       signal (sig, SIG_DFL);
247       raise (sig);
248     }
249
250   /* If we expected this signal: good!  */
251 #ifdef EXPECTED_SIGNAL
252   if (EXPECTED_SIGNAL == SIGALRM)
253     exit (0);
254 #endif
255
256   if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
257     puts ("Timed out: killed the child process");
258   else if (WIFSTOPPED (status))
259     printf ("Timed out: the child process was %s\n",
260             strsignal (WSTOPSIG (status)));
261   else if (WIFSIGNALED (status))
262     printf ("Timed out: the child process got signal %s\n",
263             strsignal (WTERMSIG (status)));
264   else
265     printf ("Timed out: killed the child process but it exited %d\n",
266             WEXITSTATUS (status));
267
268   /* Exit with an error.  */
269   exit (1);
270 }
271
272 /* Avoid all the buffer overflow messages on stderr.  */
273 static void
274 __attribute__ ((unused))
275 ignore_stderr (void)
276 {
277   int fd = open (_PATH_DEVNULL, O_WRONLY);
278   if (fd == -1)
279     close (STDERR_FILENO);
280   else
281     {
282       dup2 (fd, STDERR_FILENO);
283       close (fd);
284     }
285   setenv ("LIBC_FATAL_STDERR_", "1", 1);
286 }
287
288 /* Set fortification error handler.  Used when tests want to verify that bad
289    code is caught by the library.  */
290 static void
291 __attribute__ ((unused))
292 set_fortify_handler (void (*handler) (int sig))
293 {
294   struct sigaction sa;
295
296   sa.sa_handler = handler;
297   sa.sa_flags = 0;
298   sigemptyset (&sa.sa_mask);
299
300   sigaction (SIGABRT, &sa, NULL);
301   ignore_stderr ();
302 }
303
304 /* Show people how to run the program.  */
305 static void
306 usage (void)
307 {
308   size_t i;
309
310   printf ("Usage: %s [options]\n"
311           "\n"
312           "Environment Variables:\n"
313           "  TIMEOUTFACTOR          An integer used to scale the timeout\n"
314           "  TMPDIR                 Where to place temporary files\n"
315           "\n",
316           program_invocation_short_name);
317   printf ("Options:\n");
318   for (i = 0; options[i].name; ++i)
319     {
320       int indent;
321
322       indent = printf ("  --%s", options[i].name);
323       if (options[i].has_arg == required_argument)
324         indent += printf (" <arg>");
325       printf ("%*s", 25 - indent, "");
326       switch (options[i].val)
327         {
328         case OPT_DIRECT:
329           printf ("Run the test directly (instead of forking & monitoring)");
330           break;
331         case OPT_TESTDIR:
332           printf ("Override the TMPDIR env var");
333           break;
334         }
335       printf ("\n");
336     }
337 }
338
339 /* We provide the entry point here.  */
340 int
341 main (int argc, char *argv[])
342 {
343   int direct = 0;       /* Directly call the test function?  */
344   int status;
345   int opt;
346   unsigned int timeoutfactor = 1;
347   pid_t termpid;
348
349 #ifndef TEST_NO_MALLOPT
350   /* Make uses of freed and uninitialized memory known.  */
351   mallopt (M_PERTURB, 42);
352 #endif
353
354 #ifdef STDOUT_UNBUFFERED
355   setbuf (stdout, NULL);
356 #endif
357
358   while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1)
359     switch (opt)
360       {
361       case '?':
362         usage ();
363         exit (1);
364       case OPT_DIRECT:
365         direct = 1;
366         break;
367       case OPT_TESTDIR:
368         test_dir = optarg;
369         break;
370 #ifdef CMDLINE_PROCESS
371         CMDLINE_PROCESS
372 #endif
373       }
374
375   /* If set, read the test TIMEOUTFACTOR value from the environment.
376      This value is used to scale the default test timeout values. */
377   char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
378   if (envstr_timeoutfactor != NULL)
379     {
380       char *envstr_conv = envstr_timeoutfactor;
381       unsigned long int env_fact;
382
383       env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
384       if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
385         timeoutfactor = MAX (env_fact, 1);
386     }
387
388   /* Set TMPDIR to specified test directory.  */
389   if (test_dir != NULL)
390     {
391       setenv ("TMPDIR", test_dir, 1);
392
393       if (chdir (test_dir) < 0)
394         {
395           printf ("chdir: %m\n");
396           exit (1);
397         }
398     }
399   else
400     {
401       test_dir = getenv ("TMPDIR");
402       if (test_dir == NULL || test_dir[0] == '\0')
403         test_dir = "/tmp";
404     }
405
406   /* Make sure we see all message, even those on stdout.  */
407   setvbuf (stdout, NULL, _IONBF, 0);
408
409   /* Make sure temporary files are deleted.  */
410   atexit (delete_temp_files);
411
412   /* Correct for the possible parameters.  */
413   argv[optind - 1] = argv[0];
414   argv += optind - 1;
415   argc -= optind - 1;
416
417   /* Call the initializing function, if one is available.  */
418 #ifdef PREPARE
419   PREPARE (argc, argv);
420 #endif
421
422   const char *envstr_direct = getenv ("TEST_DIRECT");
423   if (envstr_direct != NULL)
424     {
425       FILE *f = fopen (envstr_direct, "w");
426       if (f == NULL)
427         {
428           printf ("cannot open TEST_DIRECT output file '%s': %m\n",
429                   envstr_direct);
430           exit (1);
431         }
432
433       fprintf (f, "timeout=%u\ntimeoutfactor=%u\n", TIMEOUT, timeoutfactor);
434 #ifdef EXPECTED_STATUS
435       fprintf (f, "exit=%u\n", EXPECTED_STATUS);
436 #endif
437 #ifdef EXPECTED_SIGNAL
438       switch (EXPECTED_SIGNAL)
439         {
440         default: abort ();
441 # define init_sig(signo, name, text) \
442         case signo: fprintf (f, "signal=%s\n", name); break;
443 # include <siglist.h>
444 # undef init_sig
445         }
446 #endif
447
448       if (temp_name_list != NULL)
449         {
450           struct temp_name_list *n;
451           fprintf (f, "temp_files=(\n");
452           for (n = temp_name_list;
453                n != NULL;
454                n = (struct temp_name_list *) n->q.q_forw)
455             fprintf (f, "  '%s'\n", n->name);
456           fprintf (f, ")\n");
457         }
458
459       fclose (f);
460       direct = 1;
461     }
462
463   /* If we are not expected to fork run the function immediately.  */
464   if (direct)
465     return TEST_FUNCTION;
466
467   /* Set up the test environment:
468      - prevent core dumps
469      - set up the timer
470      - fork and execute the function.  */
471
472   pid = fork ();
473   if (pid == 0)
474     {
475       /* This is the child.  */
476 #ifdef RLIMIT_CORE
477       /* Try to avoid dumping core.  */
478       struct rlimit core_limit;
479       core_limit.rlim_cur = 0;
480       core_limit.rlim_max = 0;
481       setrlimit (RLIMIT_CORE, &core_limit);
482 #endif
483
484       /* We put the test process in its own pgrp so that if it bogusly
485          generates any job control signals, they won't hit the whole build.  */
486       if (setpgid (0, 0) != 0)
487         printf ("Failed to set the process group ID: %m\n");
488
489       /* Execute the test function and exit with the return value.   */
490       exit (TEST_FUNCTION);
491     }
492   else if (pid < 0)
493     {
494       printf ("Cannot fork test program: %m\n");
495       exit (1);
496     }
497
498   /* Set timeout.  */
499   signal (SIGALRM, signal_handler);
500   alarm (TIMEOUT * timeoutfactor);
501
502   /* Make sure we clean up if the wrapper gets interrupted.  */
503   signal (SIGINT, signal_handler);
504
505   /* Wait for the regular termination.  */
506   termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
507   if (termpid == -1)
508     {
509       printf ("Waiting for test program failed: %m\n");
510       exit (1);
511     }
512   if (termpid != pid)
513     {
514       printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
515               (long int) pid, (long int) termpid);
516       exit (1);
517     }
518
519   /* Process terminated normaly without timeout etc.  */
520   if (WIFEXITED (status))
521     {
522 #ifndef EXPECTED_STATUS
523 # ifndef EXPECTED_SIGNAL
524       /* Simply exit with the return value of the test.  */
525       return WEXITSTATUS (status);
526 # else
527       printf ("Expected signal '%s' from child, got none\n",
528               strsignal (EXPECTED_SIGNAL));
529       exit (1);
530 # endif
531 #else
532       if (WEXITSTATUS (status) != EXPECTED_STATUS)
533         {
534           printf ("Expected status %d, got %d\n",
535                   EXPECTED_STATUS, WEXITSTATUS (status));
536           exit (1);
537         }
538
539       return 0;
540 #endif
541     }
542   /* Process was killed by timer or other signal.  */
543   else
544     {
545 #ifndef EXPECTED_SIGNAL
546       printf ("Didn't expect signal from child: got `%s'\n",
547               strsignal (WTERMSIG (status)));
548       exit (1);
549 #else
550       if (WTERMSIG (status) != EXPECTED_SIGNAL)
551         {
552           printf ("Incorrect signal from child: got `%s', need `%s'\n",
553                   strsignal (WTERMSIG (status)),
554                   strsignal (EXPECTED_SIGNAL));
555           exit (1);
556         }
557
558       return 0;
559 #endif
560     }
561 }