2016-06-09 Paul Pluzhnikov <ppluzhnikov@gmail.com>
[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 static void *
82 __attribute__ ((used))
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 static void *
95 __attribute__ ((used))
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 static void *
109 __attribute__ ((used))
110 xrealloc (void *p, size_t n)
111 {
112   p = realloc (p, n);
113   if (p == NULL)
114     oom_error ("realloc", n);
115   return p;
116 }
117
118 /* List of temporary files.  */
119 struct temp_name_list
120 {
121   struct qelem q;
122   char *name;
123 } *temp_name_list;
124
125 /* Add temporary files in list.  */
126 static void
127 __attribute__ ((unused))
128 add_temp_file (const char *name)
129 {
130   struct temp_name_list *newp
131     = (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
132   char *newname = strdup (name);
133   if (newname != NULL)
134     {
135       newp->name = newname;
136       if (temp_name_list == NULL)
137         temp_name_list = (struct temp_name_list *) &newp->q;
138       else
139         insque (newp, temp_name_list);
140     }
141   else
142     free (newp);
143 }
144
145 /* Delete all temporary files.  */
146 static void
147 delete_temp_files (void)
148 {
149   while (temp_name_list != NULL)
150     {
151       remove (temp_name_list->name);
152       free (temp_name_list->name);
153
154       struct temp_name_list *next
155         = (struct temp_name_list *) temp_name_list->q.q_forw;
156       free (temp_name_list);
157       temp_name_list = next;
158     }
159 }
160
161 /* Create a temporary file.  Return the opened file descriptor on
162    success, or -1 on failure.  Write the file name to *FILENAME if
163    FILENAME is not NULL.  In this case, the caller is expected to free
164    *FILENAME.  */
165 static int
166 __attribute__ ((unused))
167 create_temp_file (const char *base, char **filename)
168 {
169   char *fname;
170   int fd;
171
172   fname = (char *) xmalloc (strlen (test_dir) + 1 + strlen (base)
173                             + sizeof ("XXXXXX"));
174   strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
175
176   fd = mkstemp (fname);
177   if (fd == -1)
178     {
179       printf ("cannot open temporary file '%s': %m\n", fname);
180       free (fname);
181       return -1;
182     }
183
184   add_temp_file (fname);
185   if (filename != NULL)
186     *filename = fname;
187   else
188     free (fname);
189
190   return fd;
191 }
192
193 /* Timeout handler.  We kill the child and exit with an error.  */
194 static void
195 __attribute__ ((noreturn))
196 signal_handler (int sig __attribute__ ((unused)))
197 {
198   int killed;
199   int status;
200
201   assert (pid > 1);
202   /* Kill the whole process group.  */
203   kill (-pid, SIGKILL);
204   /* In case setpgid failed in the child, kill it individually too.  */
205   kill (pid, SIGKILL);
206
207   /* Wait for it to terminate.  */
208   int i;
209   for (i = 0; i < 5; ++i)
210     {
211       killed = waitpid (pid, &status, WNOHANG|WUNTRACED);
212       if (killed != 0)
213         break;
214
215       /* Delay, give the system time to process the kill.  If the
216          nanosleep() call return prematurely, all the better.  We
217          won't restart it since this probably means the child process
218          finally died.  */
219       struct timespec ts;
220       ts.tv_sec = 0;
221       ts.tv_nsec = 100000000;
222       nanosleep (&ts, NULL);
223     }
224   if (killed != 0 && killed != pid)
225     {
226       printf ("Failed to kill test process: %m\n");
227       exit (1);
228     }
229
230 #ifdef CLEANUP_HANDLER
231   CLEANUP_HANDLER;
232 #endif
233
234   if (sig == SIGINT)
235     {
236       signal (sig, SIG_DFL);
237       raise (sig);
238     }
239
240   /* If we expected this signal: good!  */
241 #ifdef EXPECTED_SIGNAL
242   if (EXPECTED_SIGNAL == SIGALRM)
243     exit (0);
244 #endif
245
246   if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
247     puts ("Timed out: killed the child process");
248   else if (WIFSTOPPED (status))
249     printf ("Timed out: the child process was %s\n",
250             strsignal (WSTOPSIG (status)));
251   else if (WIFSIGNALED (status))
252     printf ("Timed out: the child process got signal %s\n",
253             strsignal (WTERMSIG (status)));
254   else
255     printf ("Timed out: killed the child process but it exited %d\n",
256             WEXITSTATUS (status));
257
258   /* Exit with an error.  */
259   exit (1);
260 }
261
262 /* Avoid all the buffer overflow messages on stderr.  */
263 static void
264 __attribute__ ((unused))
265 ignore_stderr (void)
266 {
267   int fd = open (_PATH_DEVNULL, O_WRONLY);
268   if (fd == -1)
269     close (STDERR_FILENO);
270   else
271     {
272       dup2 (fd, STDERR_FILENO);
273       close (fd);
274     }
275   setenv ("LIBC_FATAL_STDERR_", "1", 1);
276 }
277
278 /* Set fortification error handler.  Used when tests want to verify that bad
279    code is caught by the library.  */
280 static void
281 __attribute__ ((unused))
282 set_fortify_handler (void (*handler) (int sig))
283 {
284   struct sigaction sa;
285
286   sa.sa_handler = handler;
287   sa.sa_flags = 0;
288   sigemptyset (&sa.sa_mask);
289
290   sigaction (SIGABRT, &sa, NULL);
291   ignore_stderr ();
292 }
293
294 /* Show people how to run the program.  */
295 static void
296 usage (void)
297 {
298   size_t i;
299
300   printf ("Usage: %s [options]\n"
301           "\n"
302           "Environment Variables:\n"
303           "  TIMEOUTFACTOR          An integer used to scale the timeout\n"
304           "  TMPDIR                 Where to place temporary files\n"
305           "\n",
306           program_invocation_short_name);
307   printf ("Options:\n");
308   for (i = 0; options[i].name; ++i)
309     {
310       int indent;
311
312       indent = printf ("  --%s", options[i].name);
313       if (options[i].has_arg == required_argument)
314         indent += printf (" <arg>");
315       printf ("%*s", 25 - indent, "");
316       switch (options[i].val)
317         {
318         case OPT_DIRECT:
319           printf ("Run the test directly (instead of forking & monitoring)");
320           break;
321         case OPT_TESTDIR:
322           printf ("Override the TMPDIR env var");
323           break;
324         }
325       printf ("\n");
326     }
327 }
328
329 /* We provide the entry point here.  */
330 int
331 main (int argc, char *argv[])
332 {
333   int direct = 0;       /* Directly call the test function?  */
334   int status;
335   int opt;
336   unsigned int timeoutfactor = 1;
337   pid_t termpid;
338
339   /* Make uses of freed and uninitialized memory known.  */
340   mallopt (M_PERTURB, 42);
341
342 #ifdef STDOUT_UNBUFFERED
343   setbuf (stdout, NULL);
344 #endif
345
346   while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1)
347     switch (opt)
348       {
349       case '?':
350         usage ();
351         exit (1);
352       case OPT_DIRECT:
353         direct = 1;
354         break;
355       case OPT_TESTDIR:
356         test_dir = optarg;
357         break;
358 #ifdef CMDLINE_PROCESS
359         CMDLINE_PROCESS
360 #endif
361       }
362
363   /* If set, read the test TIMEOUTFACTOR value from the environment.
364      This value is used to scale the default test timeout values. */
365   char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
366   if (envstr_timeoutfactor != NULL)
367     {
368       char *envstr_conv = envstr_timeoutfactor;
369       unsigned long int env_fact;
370
371       env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
372       if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
373         timeoutfactor = MAX (env_fact, 1);
374     }
375
376   /* Set TMPDIR to specified test directory.  */
377   if (test_dir != NULL)
378     {
379       setenv ("TMPDIR", test_dir, 1);
380
381       if (chdir (test_dir) < 0)
382         {
383           printf ("chdir: %m\n");
384           exit (1);
385         }
386     }
387   else
388     {
389       test_dir = getenv ("TMPDIR");
390       if (test_dir == NULL || test_dir[0] == '\0')
391         test_dir = "/tmp";
392     }
393
394   /* Make sure we see all message, even those on stdout.  */
395   setvbuf (stdout, NULL, _IONBF, 0);
396
397   /* Make sure temporary files are deleted.  */
398   atexit (delete_temp_files);
399
400   /* Correct for the possible parameters.  */
401   argv[optind - 1] = argv[0];
402   argv += optind - 1;
403   argc -= optind - 1;
404
405   /* Call the initializing function, if one is available.  */
406 #ifdef PREPARE
407   PREPARE (argc, argv);
408 #endif
409
410   const char *envstr_direct = getenv ("TEST_DIRECT");
411   if (envstr_direct != NULL)
412     {
413       FILE *f = fopen (envstr_direct, "w");
414       if (f == NULL)
415         {
416           printf ("cannot open TEST_DIRECT output file '%s': %m\n",
417                   envstr_direct);
418           exit (1);
419         }
420
421       fprintf (f, "timeout=%u\ntimeoutfactor=%u\n", TIMEOUT, timeoutfactor);
422 #ifdef EXPECTED_STATUS
423       fprintf (f, "exit=%u\n", EXPECTED_STATUS);
424 #endif
425 #ifdef EXPECTED_SIGNAL
426       switch (EXPECTED_SIGNAL)
427         {
428         default: abort ();
429 # define init_sig(signo, name, text) \
430         case signo: fprintf (f, "signal=%s\n", name); break;
431 # include <siglist.h>
432 # undef init_sig
433         }
434 #endif
435
436       if (temp_name_list != NULL)
437         {
438           struct temp_name_list *n;
439           fprintf (f, "temp_files=(\n");
440           for (n = temp_name_list;
441                n != NULL;
442                n = (struct temp_name_list *) n->q.q_forw)
443             fprintf (f, "  '%s'\n", n->name);
444           fprintf (f, ")\n");
445         }
446
447       fclose (f);
448       direct = 1;
449     }
450
451   /* If we are not expected to fork run the function immediately.  */
452   if (direct)
453     return TEST_FUNCTION;
454
455   /* Set up the test environment:
456      - prevent core dumps
457      - set up the timer
458      - fork and execute the function.  */
459
460   pid = fork ();
461   if (pid == 0)
462     {
463       /* This is the child.  */
464 #ifdef RLIMIT_CORE
465       /* Try to avoid dumping core.  */
466       struct rlimit core_limit;
467       core_limit.rlim_cur = 0;
468       core_limit.rlim_max = 0;
469       setrlimit (RLIMIT_CORE, &core_limit);
470 #endif
471
472       /* We put the test process in its own pgrp so that if it bogusly
473          generates any job control signals, they won't hit the whole build.  */
474       if (setpgid (0, 0) != 0)
475         printf ("Failed to set the process group ID: %m\n");
476
477       /* Execute the test function and exit with the return value.   */
478       exit (TEST_FUNCTION);
479     }
480   else if (pid < 0)
481     {
482       printf ("Cannot fork test program: %m\n");
483       exit (1);
484     }
485
486   /* Set timeout.  */
487   signal (SIGALRM, signal_handler);
488   alarm (TIMEOUT * timeoutfactor);
489
490   /* Make sure we clean up if the wrapper gets interrupted.  */
491   signal (SIGINT, signal_handler);
492
493   /* Wait for the regular termination.  */
494   termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
495   if (termpid == -1)
496     {
497       printf ("Waiting for test program failed: %m\n");
498       exit (1);
499     }
500   if (termpid != pid)
501     {
502       printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
503               (long int) pid, (long int) termpid);
504       exit (1);
505     }
506
507   /* Process terminated normaly without timeout etc.  */
508   if (WIFEXITED (status))
509     {
510 #ifndef EXPECTED_STATUS
511 # ifndef EXPECTED_SIGNAL
512       /* Simply exit with the return value of the test.  */
513       return WEXITSTATUS (status);
514 # else
515       printf ("Expected signal '%s' from child, got none\n",
516               strsignal (EXPECTED_SIGNAL));
517       exit (1);
518 # endif
519 #else
520       if (WEXITSTATUS (status) != EXPECTED_STATUS)
521         {
522           printf ("Expected status %d, got %d\n",
523                   EXPECTED_STATUS, WEXITSTATUS (status));
524           exit (1);
525         }
526
527       return 0;
528 #endif
529     }
530   /* Process was killed by timer or other signal.  */
531   else
532     {
533 #ifndef EXPECTED_SIGNAL
534       printf ("Didn't expect signal from child: got `%s'\n",
535               strsignal (WTERMSIG (status)));
536       exit (1);
537 #else
538       if (WTERMSIG (status) != EXPECTED_SIGNAL)
539         {
540           printf ("Incorrect signal from child: got `%s', need `%s'\n",
541                   strsignal (WTERMSIG (status)),
542                   strsignal (EXPECTED_SIGNAL));
543           exit (1);
544         }
545
546       return 0;
547 #endif
548     }
549 }