Ensure `wint_t' is defined before use in include/stdio.h
[platform/upstream/glibc.git] / test-skeleton.c
1 /* Skeleton for test programs.
2    Copyright (C) 1998-2015 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 two seconds.  */
50 # define TIMEOUT 2
51 #endif
52
53 #define OPT_DIRECT 1000
54 #define OPT_TESTDIR 1001
55
56 static struct option options[] =
57 {
58 #ifdef CMDLINE_OPTIONS
59   CMDLINE_OPTIONS
60 #endif
61   { "direct", no_argument, NULL, OPT_DIRECT },
62   { "test-dir", required_argument, NULL, OPT_TESTDIR },
63   { NULL, 0, NULL, 0 }
64 };
65
66 /* PID of the test itself.  */
67 static pid_t pid;
68
69 /* Directory to place temporary files in.  */
70 static const char *test_dir;
71
72 /* List of temporary files.  */
73 struct temp_name_list
74 {
75   struct qelem q;
76   char *name;
77 } *temp_name_list;
78
79 /* Add temporary files in list.  */
80 static void
81 __attribute__ ((unused))
82 add_temp_file (const char *name)
83 {
84   struct temp_name_list *newp
85     = (struct temp_name_list *) calloc (sizeof (*newp), 1);
86   char *newname = strdup (name);
87   if (newp != NULL && newname != NULL)
88     {
89       newp->name = newname;
90       if (temp_name_list == NULL)
91         temp_name_list = (struct temp_name_list *) &newp->q;
92       else
93         insque (newp, temp_name_list);
94     }
95   else
96     free (newp);
97 }
98
99 /* Delete all temporary files.  */
100 static void
101 delete_temp_files (void)
102 {
103   while (temp_name_list != NULL)
104     {
105       remove (temp_name_list->name);
106       free (temp_name_list->name);
107
108       struct temp_name_list *next
109         = (struct temp_name_list *) temp_name_list->q.q_forw;
110       free (temp_name_list);
111       temp_name_list = next;
112     }
113 }
114
115 /* Create a temporary file.  Return the opened file descriptor on
116    success, or -1 on failure.  Write the file name to *FILENAME if
117    FILENAME is not NULL.  In this case, the caller is expected to free
118    *FILENAME.  */
119 static int
120 __attribute__ ((unused))
121 create_temp_file (const char *base, char **filename)
122 {
123   char *fname;
124   int fd;
125
126   fname = (char *) malloc (strlen (test_dir) + 1 + strlen (base)
127                            + sizeof ("XXXXXX"));
128   if (fname == NULL)
129     {
130       puts ("out of memory");
131       return -1;
132     }
133   strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
134
135   fd = mkstemp (fname);
136   if (fd == -1)
137     {
138       printf ("cannot open temporary file '%s': %m\n", fname);
139       free (fname);
140       return -1;
141     }
142
143   add_temp_file (fname);
144   if (filename != NULL)
145     *filename = fname;
146   else
147     free (fname);
148
149   return fd;
150 }
151
152 /* Timeout handler.  We kill the child and exit with an error.  */
153 static void
154 __attribute__ ((noreturn))
155 signal_handler (int sig __attribute__ ((unused)))
156 {
157   int killed;
158   int status;
159
160   assert (pid > 1);
161   /* Kill the whole process group.  */
162   kill (-pid, SIGKILL);
163   /* In case setpgid failed in the child, kill it individually too.  */
164   kill (pid, SIGKILL);
165
166   /* Wait for it to terminate.  */
167   int i;
168   for (i = 0; i < 5; ++i)
169     {
170       killed = waitpid (pid, &status, WNOHANG|WUNTRACED);
171       if (killed != 0)
172         break;
173
174       /* Delay, give the system time to process the kill.  If the
175          nanosleep() call return prematurely, all the better.  We
176          won't restart it since this probably means the child process
177          finally died.  */
178       struct timespec ts;
179       ts.tv_sec = 0;
180       ts.tv_nsec = 100000000;
181       nanosleep (&ts, NULL);
182     }
183   if (killed != 0 && killed != pid)
184     {
185       printf ("Failed to kill test process: %m\n");
186       exit (1);
187     }
188
189 #ifdef CLEANUP_HANDLER
190   CLEANUP_HANDLER;
191 #endif
192
193   if (sig == SIGINT)
194     {
195       signal (sig, SIG_DFL);
196       raise (sig);
197     }
198
199   /* If we expected this signal: good!  */
200 #ifdef EXPECTED_SIGNAL
201   if (EXPECTED_SIGNAL == SIGALRM)
202     exit (0);
203 #endif
204
205   if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
206     puts ("Timed out: killed the child process");
207   else if (WIFSTOPPED (status))
208     printf ("Timed out: the child process was %s\n",
209             strsignal (WSTOPSIG (status)));
210   else if (WIFSIGNALED (status))
211     printf ("Timed out: the child process got signal %s\n",
212             strsignal (WTERMSIG (status)));
213   else
214     printf ("Timed out: killed the child process but it exited %d\n",
215             WEXITSTATUS (status));
216
217   /* Exit with an error.  */
218   exit (1);
219 }
220
221 /* Set fortification error handler.  Used when tests want to verify that bad
222    code is caught by the library.  */
223 static void
224 __attribute__ ((unused))
225 set_fortify_handler (void (*handler) (int sig))
226 {
227   struct sigaction sa;
228
229   sa.sa_handler = handler;
230   sa.sa_flags = 0;
231   sigemptyset (&sa.sa_mask);
232
233   sigaction (SIGABRT, &sa, NULL);
234
235   /* Avoid all the buffer overflow messages on stderr.  */
236   int fd = open (_PATH_DEVNULL, O_WRONLY);
237   if (fd == -1)
238     close (STDERR_FILENO);
239   else
240     {
241       dup2 (fd, STDERR_FILENO);
242       close (fd);
243     }
244   setenv ("LIBC_FATAL_STDERR_", "1", 1);
245 }
246
247 /* We provide the entry point here.  */
248 int
249 main (int argc, char *argv[])
250 {
251   int direct = 0;       /* Directly call the test function?  */
252   int status;
253   int opt;
254   unsigned int timeoutfactor = 1;
255   pid_t termpid;
256
257   /* Make uses of freed and uninitialized memory known.  */
258   mallopt (M_PERTURB, 42);
259
260 #ifdef STDOUT_UNBUFFERED
261   setbuf (stdout, NULL);
262 #endif
263
264   while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1)
265     switch (opt)
266       {
267       case '?':
268         exit (1);
269       case OPT_DIRECT:
270         direct = 1;
271         break;
272       case OPT_TESTDIR:
273         test_dir = optarg;
274         break;
275 #ifdef CMDLINE_PROCESS
276         CMDLINE_PROCESS
277 #endif
278       }
279
280   /* If set, read the test TIMEOUTFACTOR value from the environment.
281      This value is used to scale the default test timeout values. */
282   char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
283   if (envstr_timeoutfactor != NULL)
284     {
285       char *envstr_conv = envstr_timeoutfactor;
286       unsigned long int env_fact;
287
288       env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
289       if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
290         timeoutfactor = MAX (env_fact, 1);
291     }
292
293   /* Set TMPDIR to specified test directory.  */
294   if (test_dir != NULL)
295     {
296       setenv ("TMPDIR", test_dir, 1);
297
298       if (chdir (test_dir) < 0)
299         {
300           printf ("chdir: %m\n");
301           exit (1);
302         }
303     }
304   else
305     {
306       test_dir = getenv ("TMPDIR");
307       if (test_dir == NULL || test_dir[0] == '\0')
308         test_dir = "/tmp";
309     }
310
311   /* Make sure we see all message, even those on stdout.  */
312   setvbuf (stdout, NULL, _IONBF, 0);
313
314   /* Make sure temporary files are deleted.  */
315   atexit (delete_temp_files);
316
317   /* Correct for the possible parameters.  */
318   argv[optind - 1] = argv[0];
319   argv += optind - 1;
320   argc -= optind - 1;
321
322   /* Call the initializing function, if one is available.  */
323 #ifdef PREPARE
324   PREPARE (argc, argv);
325 #endif
326
327   const char *envstr_direct = getenv ("TEST_DIRECT");
328   if (envstr_direct != NULL)
329     {
330       FILE *f = fopen (envstr_direct, "w");
331       if (f == NULL)
332         {
333           printf ("cannot open TEST_DIRECT output file '%s': %m\n",
334                   envstr_direct);
335           exit (1);
336         }
337
338       fprintf (f, "timeout=%u\ntimeoutfactor=%u\n", TIMEOUT, timeoutfactor);
339 #ifdef EXPECTED_STATUS
340       fprintf (f, "exit=%u\n", EXPECTED_STATUS);
341 #endif
342 #ifdef EXPECTED_SIGNAL
343       switch (EXPECTED_SIGNAL)
344         {
345         default: abort ();
346 # define init_sig(signo, name, text) \
347         case signo: fprintf (f, "signal=%s\n", name); break;
348 # include <siglist.h>
349 # undef init_sig
350         }
351 #endif
352
353       if (temp_name_list != NULL)
354         {
355           struct temp_name_list *n;
356           fprintf (f, "temp_files=(\n");
357           for (n = temp_name_list;
358                n != NULL;
359                n = (struct temp_name_list *) n->q.q_forw)
360             fprintf (f, "  '%s'\n", n->name);
361           fprintf (f, ")\n");
362         }
363
364       fclose (f);
365       direct = 1;
366     }
367
368   /* If we are not expected to fork run the function immediately.  */
369   if (direct)
370     return TEST_FUNCTION;
371
372   /* Set up the test environment:
373      - prevent core dumps
374      - set up the timer
375      - fork and execute the function.  */
376
377   pid = fork ();
378   if (pid == 0)
379     {
380       /* This is the child.  */
381 #ifdef RLIMIT_CORE
382       /* Try to avoid dumping core.  */
383       struct rlimit core_limit;
384       core_limit.rlim_cur = 0;
385       core_limit.rlim_max = 0;
386       setrlimit (RLIMIT_CORE, &core_limit);
387 #endif
388
389 #ifdef RLIMIT_DATA
390       /* Try to avoid eating all memory if a test leaks.  */
391       struct rlimit data_limit;
392       if (getrlimit (RLIMIT_DATA, &data_limit) == 0)
393         {
394           if (TEST_DATA_LIMIT == RLIM_INFINITY)
395             data_limit.rlim_cur = data_limit.rlim_max;
396           else if (data_limit.rlim_cur > (rlim_t) TEST_DATA_LIMIT)
397             data_limit.rlim_cur = MIN ((rlim_t) TEST_DATA_LIMIT,
398                                        data_limit.rlim_max);
399           if (setrlimit (RLIMIT_DATA, &data_limit) < 0)
400             printf ("setrlimit: RLIMIT_DATA: %m\n");
401         }
402       else
403         printf ("getrlimit: RLIMIT_DATA: %m\n");
404 #endif
405
406       /* We put the test process in its own pgrp so that if it bogusly
407          generates any job control signals, they won't hit the whole build.  */
408       if (setpgid (0, 0) != 0)
409         printf ("Failed to set the process group ID: %m\n");
410
411       /* Execute the test function and exit with the return value.   */
412       exit (TEST_FUNCTION);
413     }
414   else if (pid < 0)
415     {
416       printf ("Cannot fork test program: %m\n");
417       exit (1);
418     }
419
420   /* Set timeout.  */
421   signal (SIGALRM, signal_handler);
422   alarm (TIMEOUT * timeoutfactor);
423
424   /* Make sure we clean up if the wrapper gets interrupted.  */
425   signal (SIGINT, signal_handler);
426
427   /* Wait for the regular termination.  */
428   termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
429   if (termpid == -1)
430     {
431       printf ("Waiting for test program failed: %m\n");
432       exit (1);
433     }
434   if (termpid != pid)
435     {
436       printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
437               (long int) pid, (long int) termpid);
438       exit (1);
439     }
440
441   /* Process terminated normaly without timeout etc.  */
442   if (WIFEXITED (status))
443     {
444 #ifndef EXPECTED_STATUS
445 # ifndef EXPECTED_SIGNAL
446       /* Simply exit with the return value of the test.  */
447       return WEXITSTATUS (status);
448 # else
449       printf ("Expected signal '%s' from child, got none\n",
450               strsignal (EXPECTED_SIGNAL));
451       exit (1);
452 # endif
453 #else
454       if (WEXITSTATUS (status) != EXPECTED_STATUS)
455         {
456           printf ("Expected status %d, got %d\n",
457                   EXPECTED_STATUS, WEXITSTATUS (status));
458           exit (1);
459         }
460
461       return 0;
462 #endif
463     }
464   /* Process was killed by timer or other signal.  */
465   else
466     {
467 #ifndef EXPECTED_SIGNAL
468       printf ("Didn't expect signal from child: got `%s'\n",
469               strsignal (WTERMSIG (status)));
470       exit (1);
471 #else
472       if (WTERMSIG (status) != EXPECTED_SIGNAL)
473         {
474           printf ("Incorrect signal from child: got `%s', need `%s'\n",
475                   strsignal (WTERMSIG (status)),
476                   strsignal (EXPECTED_SIGNAL));
477           exit (1);
478         }
479
480       return 0;
481 #endif
482     }
483 }