]> git.ipfire.org Git - thirdparty/glibc.git/blob - test-skeleton.c
Document do_test in test-skeleton.c
[thirdparty/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
41 The TEST_FUNCTION expression should have a type of 'int' and should
42 return 0 to indicate a passing test, 1 to indicate a failing test,
43 or 77 to indicate an unsupported test. Other result values could be
44 used to indicate a failing test, but the result of the expression
45 is passed to exit and exit only returns the lower 8 bits of its input.
46 A non-zero return with some values could cause a test to incorrectly
47 be considered passing when it really failed. For this reason the
48 expression should always return 0, 1, or 77.
49
50 The test function may print out diagnostic or warning messages as well
51 as messages about failures. These messages should be printed to stdout
52 and not stderr so that the output is properly ordered with respect to
53 the rest of the glibc testsuite run output. */
54
55 #ifndef TEST_FUNCTION
56 # define TEST_FUNCTION do_test (argc, argv)
57 #endif
58
59 #ifndef TEST_DATA_LIMIT
60 # define TEST_DATA_LIMIT (64 << 20) /* Data limit (bytes) to run with. */
61 #endif
62
63 #ifndef TIMEOUT
64 /* Default timeout is twenty seconds. Tests should normally complete faster
65 than this, but if they don't, that's abnormal (a bug) anyways. */
66 # define TIMEOUT 20
67 #endif
68
69 #define OPT_DIRECT 1000
70 #define OPT_TESTDIR 1001
71
72 static struct option options[] =
73 {
74 #ifdef CMDLINE_OPTIONS
75 CMDLINE_OPTIONS
76 #endif
77 { "direct", no_argument, NULL, OPT_DIRECT },
78 { "test-dir", required_argument, NULL, OPT_TESTDIR },
79 { NULL, 0, NULL, 0 }
80 };
81
82 /* PID of the test itself. */
83 static pid_t pid;
84
85 /* Directory to place temporary files in. */
86 static const char *test_dir;
87
88 #define _FAIL(...) \
89 printf ("error: %s:%d: ", __FILE__, __LINE__); \
90 printf (__VA_ARGS__); \
91 printf ("\n"); \
92
93 #define FAIL_RET(...) \
94 ({ \
95 _FAIL (__VA_ARGS__); \
96 return 1; \
97 })
98
99 #define FAIL_EXIT(value, ...) \
100 ({ \
101 _FAIL (__VA_ARGS__); \
102 exit (value); \
103 })
104
105 #define FAIL_EXIT1(...) FAIL_EXIT(1, __VA_ARGS__)
106
107 static void
108 oom_error (const char *fn, size_t size)
109 {
110 printf ("%s: unable to allocate %zu bytes: %m\n", fn, size);
111 exit (1);
112 }
113
114 /* Allocate N bytes of memory dynamically, with error checking. */
115 __attribute__ ((unused))
116 static void *
117 xmalloc (size_t n)
118 {
119 void *p;
120
121 p = malloc (n);
122 if (p == NULL)
123 oom_error ("malloc", n);
124 return p;
125 }
126
127 /* Allocate memory for N elements of S bytes, with error checking. */
128 __attribute__ ((unused))
129 static void *
130 xcalloc (size_t n, size_t s)
131 {
132 void *p;
133
134 p = calloc (n, s);
135 if (p == NULL)
136 oom_error ("calloc", n * s);
137 return p;
138 }
139
140 /* Change the size of an allocated block of memory P to N bytes,
141 with error checking. */
142 __attribute__ ((unused))
143 static void *
144 xrealloc (void *p, size_t n)
145 {
146 void *result = realloc (p, n);
147 if (result == NULL && (n > 0 || p == NULL))
148 oom_error ("realloc", n);
149 return result;
150 }
151
152 /* Call asprintf with error checking. */
153 __attribute__ ((always_inline, format (printf, 1, 2)))
154 static __inline__ char *
155 xasprintf (const char *format, ...)
156 {
157 char *result;
158 if (asprintf (&result, format, __builtin_va_arg_pack ()) < 0)
159 {
160 printf ("error: asprintf: %m\n");
161 exit (1);
162 }
163 return result;
164 }
165
166 /* Write a message to standard output. Can be used in signal
167 handlers. */
168 static void
169 __attribute__ ((unused))
170 write_message (const char *message)
171 {
172 ssize_t unused __attribute__ ((unused));
173 unused = write (STDOUT_FILENO, message, strlen (message));
174 }
175
176 /* List of temporary files. */
177 struct temp_name_list
178 {
179 struct qelem q;
180 char *name;
181 } *temp_name_list;
182
183 /* Add temporary files in list. */
184 static void
185 __attribute__ ((unused))
186 add_temp_file (const char *name)
187 {
188 struct temp_name_list *newp
189 = (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
190 char *newname = strdup (name);
191 if (newname != NULL)
192 {
193 newp->name = newname;
194 if (temp_name_list == NULL)
195 temp_name_list = (struct temp_name_list *) &newp->q;
196 else
197 insque (newp, temp_name_list);
198 }
199 else
200 free (newp);
201 }
202
203 /* Delete all temporary files. */
204 static void
205 delete_temp_files (void)
206 {
207 while (temp_name_list != NULL)
208 {
209 remove (temp_name_list->name);
210 free (temp_name_list->name);
211
212 struct temp_name_list *next
213 = (struct temp_name_list *) temp_name_list->q.q_forw;
214 free (temp_name_list);
215 temp_name_list = next;
216 }
217 }
218
219 /* Create a temporary file. Return the opened file descriptor on
220 success, or -1 on failure. Write the file name to *FILENAME if
221 FILENAME is not NULL. In this case, the caller is expected to free
222 *FILENAME. */
223 static int
224 __attribute__ ((unused))
225 create_temp_file (const char *base, char **filename)
226 {
227 char *fname;
228 int fd;
229
230 fname = (char *) xmalloc (strlen (test_dir) + 1 + strlen (base)
231 + sizeof ("XXXXXX"));
232 strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
233
234 fd = mkstemp (fname);
235 if (fd == -1)
236 {
237 printf ("cannot open temporary file '%s': %m\n", fname);
238 free (fname);
239 return -1;
240 }
241
242 add_temp_file (fname);
243 if (filename != NULL)
244 *filename = fname;
245 else
246 free (fname);
247
248 return fd;
249 }
250
251 /* Timeout handler. We kill the child and exit with an error. */
252 static void
253 __attribute__ ((noreturn))
254 signal_handler (int sig __attribute__ ((unused)))
255 {
256 int killed;
257 int status;
258
259 assert (pid > 1);
260 /* Kill the whole process group. */
261 kill (-pid, SIGKILL);
262 /* In case setpgid failed in the child, kill it individually too. */
263 kill (pid, SIGKILL);
264
265 /* Wait for it to terminate. */
266 int i;
267 for (i = 0; i < 5; ++i)
268 {
269 killed = waitpid (pid, &status, WNOHANG|WUNTRACED);
270 if (killed != 0)
271 break;
272
273 /* Delay, give the system time to process the kill. If the
274 nanosleep() call return prematurely, all the better. We
275 won't restart it since this probably means the child process
276 finally died. */
277 struct timespec ts;
278 ts.tv_sec = 0;
279 ts.tv_nsec = 100000000;
280 nanosleep (&ts, NULL);
281 }
282 if (killed != 0 && killed != pid)
283 {
284 printf ("Failed to kill test process: %m\n");
285 exit (1);
286 }
287
288 #ifdef CLEANUP_HANDLER
289 CLEANUP_HANDLER;
290 #endif
291
292 if (sig == SIGINT)
293 {
294 signal (sig, SIG_DFL);
295 raise (sig);
296 }
297
298 /* If we expected this signal: good! */
299 #ifdef EXPECTED_SIGNAL
300 if (EXPECTED_SIGNAL == SIGALRM)
301 exit (0);
302 #endif
303
304 if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
305 puts ("Timed out: killed the child process");
306 else if (WIFSTOPPED (status))
307 printf ("Timed out: the child process was %s\n",
308 strsignal (WSTOPSIG (status)));
309 else if (WIFSIGNALED (status))
310 printf ("Timed out: the child process got signal %s\n",
311 strsignal (WTERMSIG (status)));
312 else
313 printf ("Timed out: killed the child process but it exited %d\n",
314 WEXITSTATUS (status));
315
316 /* Exit with an error. */
317 exit (1);
318 }
319
320 /* Avoid all the buffer overflow messages on stderr. */
321 static void
322 __attribute__ ((unused))
323 ignore_stderr (void)
324 {
325 int fd = open (_PATH_DEVNULL, O_WRONLY);
326 if (fd == -1)
327 close (STDERR_FILENO);
328 else
329 {
330 dup2 (fd, STDERR_FILENO);
331 close (fd);
332 }
333 setenv ("LIBC_FATAL_STDERR_", "1", 1);
334 }
335
336 /* Set fortification error handler. Used when tests want to verify that bad
337 code is caught by the library. */
338 static void
339 __attribute__ ((unused))
340 set_fortify_handler (void (*handler) (int sig))
341 {
342 struct sigaction sa;
343
344 sa.sa_handler = handler;
345 sa.sa_flags = 0;
346 sigemptyset (&sa.sa_mask);
347
348 sigaction (SIGABRT, &sa, NULL);
349 ignore_stderr ();
350 }
351
352 /* Show people how to run the program. */
353 static void
354 usage (void)
355 {
356 size_t i;
357
358 printf ("Usage: %s [options]\n"
359 "\n"
360 "Environment Variables:\n"
361 " TIMEOUTFACTOR An integer used to scale the timeout\n"
362 " TMPDIR Where to place temporary files\n"
363 "\n",
364 program_invocation_short_name);
365 printf ("Options:\n");
366 for (i = 0; options[i].name; ++i)
367 {
368 int indent;
369
370 indent = printf (" --%s", options[i].name);
371 if (options[i].has_arg == required_argument)
372 indent += printf (" <arg>");
373 printf ("%*s", 25 - indent, "");
374 switch (options[i].val)
375 {
376 case OPT_DIRECT:
377 printf ("Run the test directly (instead of forking & monitoring)");
378 break;
379 case OPT_TESTDIR:
380 printf ("Override the TMPDIR env var");
381 break;
382 }
383 printf ("\n");
384 }
385 }
386
387 /* We provide the entry point here. */
388 int
389 main (int argc, char *argv[])
390 {
391 int direct = 0; /* Directly call the test function? */
392 int status;
393 int opt;
394 unsigned int timeoutfactor = 1;
395 pid_t termpid;
396
397 #ifndef TEST_NO_MALLOPT
398 /* Make uses of freed and uninitialized memory known. */
399 mallopt (M_PERTURB, 42);
400 #endif
401
402 #ifdef STDOUT_UNBUFFERED
403 setbuf (stdout, NULL);
404 #endif
405
406 while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1)
407 switch (opt)
408 {
409 case '?':
410 usage ();
411 exit (1);
412 case OPT_DIRECT:
413 direct = 1;
414 break;
415 case OPT_TESTDIR:
416 test_dir = optarg;
417 break;
418 #ifdef CMDLINE_PROCESS
419 CMDLINE_PROCESS
420 #endif
421 }
422
423 /* If set, read the test TIMEOUTFACTOR value from the environment.
424 This value is used to scale the default test timeout values. */
425 char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
426 if (envstr_timeoutfactor != NULL)
427 {
428 char *envstr_conv = envstr_timeoutfactor;
429 unsigned long int env_fact;
430
431 env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
432 if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
433 timeoutfactor = MAX (env_fact, 1);
434 }
435
436 /* Set TMPDIR to specified test directory. */
437 if (test_dir != NULL)
438 {
439 setenv ("TMPDIR", test_dir, 1);
440
441 if (chdir (test_dir) < 0)
442 {
443 printf ("chdir: %m\n");
444 exit (1);
445 }
446 }
447 else
448 {
449 test_dir = getenv ("TMPDIR");
450 if (test_dir == NULL || test_dir[0] == '\0')
451 test_dir = "/tmp";
452 }
453
454 /* Make sure we see all message, even those on stdout. */
455 setvbuf (stdout, NULL, _IONBF, 0);
456
457 /* Make sure temporary files are deleted. */
458 atexit (delete_temp_files);
459
460 /* Correct for the possible parameters. */
461 argv[optind - 1] = argv[0];
462 argv += optind - 1;
463 argc -= optind - 1;
464
465 /* Call the initializing function, if one is available. */
466 #ifdef PREPARE
467 PREPARE (argc, argv);
468 #endif
469
470 const char *envstr_direct = getenv ("TEST_DIRECT");
471 if (envstr_direct != NULL)
472 {
473 FILE *f = fopen (envstr_direct, "w");
474 if (f == NULL)
475 {
476 printf ("cannot open TEST_DIRECT output file '%s': %m\n",
477 envstr_direct);
478 exit (1);
479 }
480
481 fprintf (f, "timeout=%u\ntimeoutfactor=%u\n", TIMEOUT, timeoutfactor);
482 #ifdef EXPECTED_STATUS
483 fprintf (f, "exit=%u\n", EXPECTED_STATUS);
484 #endif
485 #ifdef EXPECTED_SIGNAL
486 switch (EXPECTED_SIGNAL)
487 {
488 default: abort ();
489 # define init_sig(signo, name, text) \
490 case signo: fprintf (f, "signal=%s\n", name); break;
491 # include <siglist.h>
492 # undef init_sig
493 }
494 #endif
495
496 if (temp_name_list != NULL)
497 {
498 struct temp_name_list *n;
499 fprintf (f, "temp_files=(\n");
500 for (n = temp_name_list;
501 n != NULL;
502 n = (struct temp_name_list *) n->q.q_forw)
503 fprintf (f, " '%s'\n", n->name);
504 fprintf (f, ")\n");
505 }
506
507 fclose (f);
508 direct = 1;
509 }
510
511 /* If we are not expected to fork run the function immediately. */
512 if (direct)
513 return TEST_FUNCTION;
514
515 /* Set up the test environment:
516 - prevent core dumps
517 - set up the timer
518 - fork and execute the function. */
519
520 pid = fork ();
521 if (pid == 0)
522 {
523 /* This is the child. */
524 #ifdef RLIMIT_CORE
525 /* Try to avoid dumping core. */
526 struct rlimit core_limit;
527 core_limit.rlim_cur = 0;
528 core_limit.rlim_max = 0;
529 setrlimit (RLIMIT_CORE, &core_limit);
530 #endif
531
532 /* We put the test process in its own pgrp so that if it bogusly
533 generates any job control signals, they won't hit the whole build. */
534 if (setpgid (0, 0) != 0)
535 printf ("Failed to set the process group ID: %m\n");
536
537 /* Execute the test function and exit with the return value. */
538 exit (TEST_FUNCTION);
539 }
540 else if (pid < 0)
541 {
542 printf ("Cannot fork test program: %m\n");
543 exit (1);
544 }
545
546 /* Set timeout. */
547 signal (SIGALRM, signal_handler);
548 alarm (TIMEOUT * timeoutfactor);
549
550 /* Make sure we clean up if the wrapper gets interrupted. */
551 signal (SIGINT, signal_handler);
552
553 /* Wait for the regular termination. */
554 termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
555 if (termpid == -1)
556 {
557 printf ("Waiting for test program failed: %m\n");
558 exit (1);
559 }
560 if (termpid != pid)
561 {
562 printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
563 (long int) pid, (long int) termpid);
564 exit (1);
565 }
566
567 /* Process terminated normaly without timeout etc. */
568 if (WIFEXITED (status))
569 {
570 #ifndef EXPECTED_STATUS
571 # ifndef EXPECTED_SIGNAL
572 /* Simply exit with the return value of the test. */
573 return WEXITSTATUS (status);
574 # else
575 printf ("Expected signal '%s' from child, got none\n",
576 strsignal (EXPECTED_SIGNAL));
577 exit (1);
578 # endif
579 #else
580 if (WEXITSTATUS (status) != EXPECTED_STATUS)
581 {
582 printf ("Expected status %d, got %d\n",
583 EXPECTED_STATUS, WEXITSTATUS (status));
584 exit (1);
585 }
586
587 return 0;
588 #endif
589 }
590 /* Process was killed by timer or other signal. */
591 else
592 {
593 #ifndef EXPECTED_SIGNAL
594 printf ("Didn't expect signal from child: got `%s'\n",
595 strsignal (WTERMSIG (status)));
596 exit (1);
597 #else
598 if (WTERMSIG (status) != EXPECTED_SIGNAL)
599 {
600 printf ("Incorrect signal from child: got `%s', need `%s'\n",
601 strsignal (WTERMSIG (status)),
602 strsignal (EXPECTED_SIGNAL));
603 exit (1);
604 }
605
606 return 0;
607 #endif
608 }
609 }
610
611 /* The following functionality is only available if <pthread.h> was
612 included before this file. */
613 #ifdef _PTHREAD_H
614
615 /* Call pthread_sigmask with error checking. */
616 static void
617 xpthread_sigmask (int how, const sigset_t *set, sigset_t *oldset)
618 {
619 if (pthread_sigmask (how, set, oldset) != 0)
620 {
621 write_message ("error: pthread_setmask failed\n");
622 _exit (1);
623 }
624 }
625
626 /* Call pthread_mutex_lock with error checking. */
627 __attribute__ ((unused))
628 static void
629 xpthread_mutex_lock (pthread_mutex_t *mutex)
630 {
631 int ret = pthread_mutex_lock (mutex);
632 if (ret != 0)
633 {
634 errno = ret;
635 printf ("error: pthread_mutex_lock: %m\n");
636 exit (1);
637 }
638 }
639
640 /* Call pthread_spin_lock with error checking. */
641 __attribute__ ((unused))
642 static void
643 xpthread_spin_lock (pthread_spinlock_t *lock)
644 {
645 int ret = pthread_spin_lock (lock);
646 if (ret != 0)
647 {
648 errno = ret;
649 printf ("error: pthread_spin_lock: %m\n");
650 exit (1);
651 }
652 }
653
654 /* Call pthread_cond_wait with error checking. */
655 __attribute__ ((unused))
656 static void
657 xpthread_cond_wait (pthread_cond_t * cond,
658 pthread_mutex_t * mutex)
659 {
660 int ret = pthread_cond_wait (cond, mutex);
661 if (ret != 0)
662 {
663 errno = ret;
664 printf ("error: pthread_cond_wait: %m\n");
665 exit (1);
666 }
667 }
668
669 /* Call pthread_barrier_wait with error checking. */
670 __attribute__ ((unused))
671 static int
672 xpthread_barrier_wait (pthread_barrier_t *barrier)
673 {
674 int ret = pthread_barrier_wait (barrier);
675 if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD)
676 {
677 errno = ret;
678 printf ("error: pthread_barrier_wait: %m\n");
679 exit (1);
680 }
681 return ret;
682 }
683
684 /* Call pthread_create with error checking. */
685 static pthread_t
686 xpthread_create (pthread_attr_t *attr,
687 void *(*thread_func) (void *), void *closure)
688 {
689 pthread_t thr;
690 int ret = pthread_create (&thr, attr, thread_func, closure);
691 if (ret != 0)
692 {
693 errno = ret;
694 printf ("error: pthread_create: %m\n");
695 exit (1);
696 }
697 return thr;
698 }
699
700 /* Call pthread_detach with error checking. */
701 static void
702 xpthread_detach (pthread_t thr)
703 {
704 int ret = pthread_detach (thr);
705 if (ret != 0)
706 {
707 errno = ret;
708 printf ("error: pthread_detach: %m\n");
709 exit (1);
710 }
711 }
712
713 /* Call pthread_join with error checking. */
714 __attribute__ ((unused))
715 static void *
716 xpthread_join (pthread_t thr)
717 {
718 void *result;
719 int ret = pthread_join (thr, &result);
720 if (ret != 0)
721 {
722 errno = ret;
723 printf ("error: pthread_join: %m\n");
724 exit (1);
725 }
726 return result;
727 }
728
729 /* Used to implement the delayed_exit function defined below. */
730 static void *
731 delayed_exit_thread (void *seconds_as_ptr)
732 {
733 int seconds = (uintptr_t) seconds_as_ptr;
734 struct timespec delay = { seconds, 0 };
735 struct timespec remaining = { 0 };
736 if (nanosleep (&delay, &remaining) != 0)
737 {
738 printf ("error: nanosleep: %m\n");
739 _exit (1);
740 }
741 /* Exit the process sucessfully. */
742 exit (0);
743 return NULL;
744 }
745
746 /* Exit (with status 0) after SECONDS have elapsed, from a helper
747 thread. The process is terminated with the exit function, so
748 atexit handlers are executed. */
749 __attribute__ ((unused))
750 static void
751 delayed_exit (int seconds)
752 {
753 /* Create the new thread with all signals blocked. */
754 sigset_t all_blocked;
755 sigfillset (&all_blocked);
756 sigset_t old_set;
757 xpthread_sigmask (SIG_SETMASK, &all_blocked, &old_set);
758 /* Create a detached thread. */
759 pthread_t thr = xpthread_create
760 (NULL, delayed_exit_thread, (void *) (uintptr_t) seconds);
761 xpthread_detach (thr);
762 /* Restore the original signal mask. */
763 xpthread_sigmask (SIG_SETMASK, &old_set, NULL);
764 }
765
766 #endif /* _PTHREAD_H */