test-skeleton.c: Add write_message function
[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 /* 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   /* Make uses of freed and uninitialized memory known.  */
350   mallopt (M_PERTURB, 42);
351
352 #ifdef STDOUT_UNBUFFERED
353   setbuf (stdout, NULL);
354 #endif
355
356   while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1)
357     switch (opt)
358       {
359       case '?':
360         usage ();
361         exit (1);
362       case OPT_DIRECT:
363         direct = 1;
364         break;
365       case OPT_TESTDIR:
366         test_dir = optarg;
367         break;
368 #ifdef CMDLINE_PROCESS
369         CMDLINE_PROCESS
370 #endif
371       }
372
373   /* If set, read the test TIMEOUTFACTOR value from the environment.
374      This value is used to scale the default test timeout values. */
375   char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
376   if (envstr_timeoutfactor != NULL)
377     {
378       char *envstr_conv = envstr_timeoutfactor;
379       unsigned long int env_fact;
380
381       env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
382       if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
383         timeoutfactor = MAX (env_fact, 1);
384     }
385
386   /* Set TMPDIR to specified test directory.  */
387   if (test_dir != NULL)
388     {
389       setenv ("TMPDIR", test_dir, 1);
390
391       if (chdir (test_dir) < 0)
392         {
393           printf ("chdir: %m\n");
394           exit (1);
395         }
396     }
397   else
398     {
399       test_dir = getenv ("TMPDIR");
400       if (test_dir == NULL || test_dir[0] == '\0')
401         test_dir = "/tmp";
402     }
403
404   /* Make sure we see all message, even those on stdout.  */
405   setvbuf (stdout, NULL, _IONBF, 0);
406
407   /* Make sure temporary files are deleted.  */
408   atexit (delete_temp_files);
409
410   /* Correct for the possible parameters.  */
411   argv[optind - 1] = argv[0];
412   argv += optind - 1;
413   argc -= optind - 1;
414
415   /* Call the initializing function, if one is available.  */
416 #ifdef PREPARE
417   PREPARE (argc, argv);
418 #endif
419
420   const char *envstr_direct = getenv ("TEST_DIRECT");
421   if (envstr_direct != NULL)
422     {
423       FILE *f = fopen (envstr_direct, "w");
424       if (f == NULL)
425         {
426           printf ("cannot open TEST_DIRECT output file '%s': %m\n",
427                   envstr_direct);
428           exit (1);
429         }
430
431       fprintf (f, "timeout=%u\ntimeoutfactor=%u\n", TIMEOUT, timeoutfactor);
432 #ifdef EXPECTED_STATUS
433       fprintf (f, "exit=%u\n", EXPECTED_STATUS);
434 #endif
435 #ifdef EXPECTED_SIGNAL
436       switch (EXPECTED_SIGNAL)
437         {
438         default: abort ();
439 # define init_sig(signo, name, text) \
440         case signo: fprintf (f, "signal=%s\n", name); break;
441 # include <siglist.h>
442 # undef init_sig
443         }
444 #endif
445
446       if (temp_name_list != NULL)
447         {
448           struct temp_name_list *n;
449           fprintf (f, "temp_files=(\n");
450           for (n = temp_name_list;
451                n != NULL;
452                n = (struct temp_name_list *) n->q.q_forw)
453             fprintf (f, "  '%s'\n", n->name);
454           fprintf (f, ")\n");
455         }
456
457       fclose (f);
458       direct = 1;
459     }
460
461   /* If we are not expected to fork run the function immediately.  */
462   if (direct)
463     return TEST_FUNCTION;
464
465   /* Set up the test environment:
466      - prevent core dumps
467      - set up the timer
468      - fork and execute the function.  */
469
470   pid = fork ();
471   if (pid == 0)
472     {
473       /* This is the child.  */
474 #ifdef RLIMIT_CORE
475       /* Try to avoid dumping core.  */
476       struct rlimit core_limit;
477       core_limit.rlim_cur = 0;
478       core_limit.rlim_max = 0;
479       setrlimit (RLIMIT_CORE, &core_limit);
480 #endif
481
482       /* We put the test process in its own pgrp so that if it bogusly
483          generates any job control signals, they won't hit the whole build.  */
484       if (setpgid (0, 0) != 0)
485         printf ("Failed to set the process group ID: %m\n");
486
487       /* Execute the test function and exit with the return value.   */
488       exit (TEST_FUNCTION);
489     }
490   else if (pid < 0)
491     {
492       printf ("Cannot fork test program: %m\n");
493       exit (1);
494     }
495
496   /* Set timeout.  */
497   signal (SIGALRM, signal_handler);
498   alarm (TIMEOUT * timeoutfactor);
499
500   /* Make sure we clean up if the wrapper gets interrupted.  */
501   signal (SIGINT, signal_handler);
502
503   /* Wait for the regular termination.  */
504   termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
505   if (termpid == -1)
506     {
507       printf ("Waiting for test program failed: %m\n");
508       exit (1);
509     }
510   if (termpid != pid)
511     {
512       printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
513               (long int) pid, (long int) termpid);
514       exit (1);
515     }
516
517   /* Process terminated normaly without timeout etc.  */
518   if (WIFEXITED (status))
519     {
520 #ifndef EXPECTED_STATUS
521 # ifndef EXPECTED_SIGNAL
522       /* Simply exit with the return value of the test.  */
523       return WEXITSTATUS (status);
524 # else
525       printf ("Expected signal '%s' from child, got none\n",
526               strsignal (EXPECTED_SIGNAL));
527       exit (1);
528 # endif
529 #else
530       if (WEXITSTATUS (status) != EXPECTED_STATUS)
531         {
532           printf ("Expected status %d, got %d\n",
533                   EXPECTED_STATUS, WEXITSTATUS (status));
534           exit (1);
535         }
536
537       return 0;
538 #endif
539     }
540   /* Process was killed by timer or other signal.  */
541   else
542     {
543 #ifndef EXPECTED_SIGNAL
544       printf ("Didn't expect signal from child: got `%s'\n",
545               strsignal (WTERMSIG (status)));
546       exit (1);
547 #else
548       if (WTERMSIG (status) != EXPECTED_SIGNAL)
549         {
550           printf ("Incorrect signal from child: got `%s', need `%s'\n",
551                   strsignal (WTERMSIG (status)),
552                   strsignal (EXPECTED_SIGNAL));
553           exit (1);
554         }
555
556       return 0;
557 #endif
558     }
559 }