OSDN Git Service

mips/dl-tls.h: Adjust TLS_TPREL_VALUE and TLS_DTPREL_VALUE
[uclinux-h8/uClibc.git] / test / test-skeleton.c
1 /* Skeleton for test programs.
2    Copyright (C) 1998,2000-2004, 2005 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, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include <errno.h>
22 #include <getopt.h>
23 #include <malloc.h>
24 #include <search.h>
25 #include <signal.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/resource.h>
31 #include <sys/wait.h>
32 #include <sys/param.h>
33 #include <time.h>
34 #include <features.h>
35
36 /* The test function is normally called `do_test' and it is called
37    with argc and argv as the arguments.  We nevertheless provide the
38    possibility to overwrite this name.  */
39 #ifndef TEST_FUNCTION
40 # define TEST_FUNCTION do_test (argc, argv)
41 #endif
42
43 #ifndef TEST_DATA_LIMIT
44 # define TEST_DATA_LIMIT (64 << 20) /* Data limit (bytes) to run with.  */
45 #endif
46
47 #define OPT_DIRECT 1000
48 #define OPT_TESTDIR 1001
49
50 static struct option options[] =
51 {
52 #ifdef CMDLINE_OPTIONS
53   CMDLINE_OPTIONS
54 #endif
55   { "direct", no_argument, NULL, OPT_DIRECT },
56   { "test-dir", required_argument, NULL, OPT_TESTDIR },
57   { NULL, 0, NULL, 0 }
58 };
59
60 /* PID of the test itself.  */
61 static pid_t pid;
62
63 /* Directory to place temporary files in.  */
64 static const char *test_dir;
65
66 /* List of temporary files.  */
67 struct temp_name_list
68 {
69   struct qelem q;
70   const char *name;
71 } *temp_name_list;
72
73 /* Add temporary files in list.  */
74 static void
75 __attribute__ ((unused))
76 add_temp_file (const char *name)
77 {
78   struct temp_name_list *newp
79     = (struct temp_name_list *) calloc (sizeof (*newp), 1);
80   if (newp != NULL)
81     {
82       newp->name = name;
83       if (temp_name_list == NULL)
84         temp_name_list = (struct temp_name_list *) &newp->q;
85       else
86         insque (newp, temp_name_list);
87     }
88 }
89
90 /* Delete all temporary files.  */
91 static void
92 delete_temp_files (void)
93 {
94   while (temp_name_list != NULL)
95     {
96       remove (temp_name_list->name);
97       temp_name_list = (struct temp_name_list *) temp_name_list->q.q_forw;
98     }
99 }
100
101 /* Create a temporary file.  */
102 static int
103 __attribute__ ((unused))
104 create_temp_file (const char *base, char **filename)
105 {
106   char *fname;
107   int fd;
108
109   fname = (char *) malloc (strlen (test_dir) + 1 + strlen (base)
110                            + sizeof ("XXXXXX"));
111   if (fname == NULL)
112     {
113       puts ("out of memory");
114       return -1;
115     }
116   strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
117
118   fd = mkstemp (fname);
119   if (fd == -1)
120     {
121       printf ("cannot open temporary file '%s': %s\n", fname, strerror(errno));
122       free (fname);
123       return -1;
124     }
125
126   add_temp_file (fname);
127   if (filename != NULL)
128     *filename = fname;
129
130   return fd;
131 }
132
133 /* Timeout handler.  We kill the child and exit with an error.  */
134 static void
135 __attribute__ ((noreturn))
136 timeout_handler (int sig __attribute__ ((unused)))
137 {
138   int killed = 0;
139   int status;
140   int i;
141
142   /* Send signal.  */
143   kill (pid, SIGKILL);
144
145   /* Wait for it to terminate.  */
146   for (i = 0; i < 5; ++i)
147     {
148       struct timespec ts;
149       killed = waitpid (pid, &status, WNOHANG|WUNTRACED);
150       if (killed != 0)
151         break;
152
153       /* Delay, give the system time to process the kill.  If the
154          nanosleep() call return prematurely, all the better.  We
155          won't restart it since this probably means the child process
156          finally died.  */
157       ts.tv_sec = 0;
158       ts.tv_nsec = 100000000;
159       nanosleep (&ts, NULL);
160     }
161   if (killed != 0 && killed != pid)
162     {
163       perror ("Failed to kill test process");
164       exit (1);
165     }
166
167 #ifdef CLEANUP_HANDLER
168   CLEANUP_HANDLER;
169 #endif
170
171   /* If we expected this signal: good!  */
172 #ifdef EXPECTED_SIGNAL
173   if (EXPECTED_SIGNAL == SIGALRM)
174     exit (0);
175 #endif
176
177   if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
178     fputs ("Timed out: killed the child process\n", stderr);
179   else if (WIFSTOPPED (status))
180     fprintf (stderr, "Timed out: the child process was %s\n",
181              strsignal (WSTOPSIG (status)));
182   else if (WIFSIGNALED (status))
183     fprintf (stderr, "Timed out: the child process got signal %s\n",
184              strsignal (WTERMSIG (status)));
185   else
186     fprintf (stderr, "Timed out: killed the child process but it exited %d\n",
187              WEXITSTATUS (status));
188
189   /* Exit with an error.  */
190   exit (1);
191 }
192
193 static void
194 __attribute__ ((noreturn))
195 handler_killpid(int sig)
196 {
197         kill(pid, SIGKILL); /* kill test */
198         signal(sig, SIG_DFL);
199         raise(sig); /* kill ourself */
200         _exit(128 + sig); /* paranoia */
201 }
202
203 /* We provide the entry point here.  */
204 int
205 main (int argc, char *argv[])
206 {
207 #ifdef __ARCH_USE_MMU__
208   int direct = 0;       /* Directly call the test function?  */
209 #else
210   int direct = 1;
211 #endif
212   int status;
213   int opt;
214   unsigned int timeoutfactor = 1;
215   pid_t termpid;
216   char *envstr_timeoutfactor;
217
218   /* Make uses of freed and uninitialized memory known.  */
219 #ifdef __MALLOC_STANDARD__
220 #ifndef M_PERTURB
221 # define M_PERTURB -6
222 #endif
223   mallopt (M_PERTURB, 42);
224 #endif
225
226 #ifdef STDOUT_UNBUFFERED
227   setbuf (stdout, NULL);
228 #endif
229
230   while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1)
231     switch (opt)
232       {
233       case '?':
234         exit (1);
235       case OPT_DIRECT:
236         direct = 1;
237         break;
238       case OPT_TESTDIR:
239         test_dir = optarg;
240         break;
241 #ifdef CMDLINE_PROCESS
242         CMDLINE_PROCESS
243 #endif
244       }
245
246   /* If set, read the test TIMEOUTFACTOR value from the environment.
247      This value is used to scale the default test timeout values. */
248   envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
249   if (envstr_timeoutfactor != NULL)
250     {
251       char *envstr_conv = envstr_timeoutfactor;
252       unsigned long int env_fact;
253
254       env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
255       if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
256         timeoutfactor = MAX (env_fact, 1);
257     }
258
259   /* Set TMPDIR to specified test directory.  */
260   if (test_dir != NULL)
261     {
262       setenv ("TMPDIR", test_dir, 1);
263
264       if (chdir (test_dir) < 0)
265         {
266           perror ("chdir");
267           exit (1);
268         }
269     }
270   else
271     {
272       test_dir = getenv ("TMPDIR");
273       if (test_dir == NULL || test_dir[0] == '\0')
274         test_dir = "/tmp";
275     }
276
277   /* Make sure we see all message, even those on stdout.  */
278   setvbuf (stdout, NULL, _IONBF, 0);
279
280   /* make sure temporary files are deleted.  */
281   atexit (delete_temp_files);
282
283   /* Correct for the possible parameters.  */
284   argv[optind - 1] = argv[0];
285   argv += optind - 1;
286   argc -= optind - 1;
287
288   /* Call the initializing function, if one is available.  */
289 #ifdef PREPARE
290   PREPARE (argc, argv);
291 #endif
292
293   /* If we are not expected to fork run the function immediately.  */
294   if (direct)
295     return TEST_FUNCTION;
296
297   /* Set up the test environment:
298      - prevent core dumps
299      - set up the timer
300      - fork and execute the function.  */
301
302 #if defined __ARCH_USE_MMU__ || ! defined __UCLIBC__
303   pid = fork ();
304   if (pid == 0)
305     {
306       /* This is the child.  */
307 #ifdef RLIMIT_DATA
308       struct rlimit data_limit;
309 #endif
310 #ifdef RLIMIT_CORE
311       /* Try to avoid dumping core.  */
312       struct rlimit core_limit;
313       core_limit.rlim_cur = 0;
314       core_limit.rlim_max = 0;
315       setrlimit (RLIMIT_CORE, &core_limit);
316 #endif
317
318 #ifdef RLIMIT_DATA
319       /* Try to avoid eating all memory if a test leaks.  */
320       if (getrlimit (RLIMIT_DATA, &data_limit) == 0)
321         {
322           if (TEST_DATA_LIMIT == RLIM_INFINITY)
323             data_limit.rlim_cur = data_limit.rlim_max;
324           else if (data_limit.rlim_cur > (rlim_t) TEST_DATA_LIMIT)
325             data_limit.rlim_cur = MIN ((rlim_t) TEST_DATA_LIMIT,
326                                        data_limit.rlim_max);
327           if (setrlimit (RLIMIT_DATA, &data_limit) < 0)
328             perror ("setrlimit: RLIMIT_DATA");
329         }
330       else
331         perror ("getrlimit: RLIMIT_DATA");
332 #endif
333
334       /* We put the test process in its own pgrp so that if it bogusly
335          generates any job control signals, they won't hit the whole build.  */
336       setpgid (0, 0);
337
338       /* Execute the test function and exit with the return value.   */
339       exit (TEST_FUNCTION);
340     }
341   else if (pid < 0)
342 #endif
343     {
344       perror ("Cannot fork test program");
345       exit (1);
346     }
347
348   signal (SIGTERM, handler_killpid);
349   signal (SIGINT, handler_killpid);
350   signal (SIGQUIT, handler_killpid);
351
352   /* Set timeout.  */
353 #ifndef TIMEOUT
354   /* Default timeout is two seconds.  */
355 # define TIMEOUT 2
356 #endif
357   signal (SIGALRM, timeout_handler);
358   alarm (TIMEOUT * timeoutfactor);
359
360   /* Wait for the regular termination.  */
361   termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
362   if (termpid == -1)
363     {
364       printf ("Waiting for test program failed: %s\n", strerror(errno));
365       exit (1);
366     }
367   if (termpid != pid)
368     {
369       printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
370               (long int) pid, (long int) termpid);
371       exit (1);
372     }
373
374 #ifndef EXPECTED_SIGNAL
375   /* We don't expect any signal.  */
376 # define EXPECTED_SIGNAL 0
377 #endif
378   if (WTERMSIG (status) != EXPECTED_SIGNAL)
379     {
380       if (EXPECTED_SIGNAL != 0)
381         {
382           if (WTERMSIG (status) == 0)
383             fprintf (stderr,
384                      "Expected signal '%s' from child, got none\n",
385                      strsignal (EXPECTED_SIGNAL));
386           else
387             fprintf (stderr,
388                      "Incorrect signal from child: got `%s', need `%s'\n",
389                      strsignal (WTERMSIG (status)),
390                      strsignal (EXPECTED_SIGNAL));
391         }
392       else
393         fprintf (stderr, "Didn't expect signal from child: got `%s'\n",
394                  strsignal (WTERMSIG (status)));
395       exit (1);
396     }
397
398   /* Simply exit with the return value of the test.  */
399 #ifndef EXPECTED_STATUS
400   return WEXITSTATUS (status);
401 #else
402   if (WEXITSTATUS (status) != EXPECTED_STATUS)
403     {
404       fprintf (stderr, "Expected status %d, got %d\n",
405                EXPECTED_STATUS, WEXITSTATUS (status));
406       exit (1);
407     }
408
409   return 0;
410 #endif
411 }