libiberty:
[official-gcc.git] / libiberty / testsuite / test-pexecute.c
blobc67bcefb8f680ec889b5627f902a219fbb0bee23
1 /* Pexecute test program,
2 Copyright (C) 2005 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor <ian@airs.com>.
5 This file is part of GNU libiberty.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "ansidecl.h"
26 #include "libiberty.h"
27 #include <stdio.h>
28 #include <signal.h>
29 #include <errno.h>
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33 #include <sys/types.h>
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #ifdef HAVE_SYS_WAIT_H
41 #include <sys/wait.h>
42 #endif
43 #ifdef HAVE_SYS_TIME_H
44 #include <sys/time.h>
45 #endif
46 #ifdef HAVE_SYS_RESOURCE_H
47 #include <sys/resource.h>
48 #endif
50 #ifndef WIFSIGNALED
51 #define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
52 #endif
53 #ifndef WTERMSIG
54 #define WTERMSIG(S) ((S) & 0x7f)
55 #endif
56 #ifndef WIFEXITED
57 #define WIFEXITED(S) (((S) & 0xff) == 0)
58 #endif
59 #ifndef WEXITSTATUS
60 #define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
61 #endif
62 #ifndef WSTOPSIG
63 #define WSTOPSIG WEXITSTATUS
64 #endif
65 #ifndef WCOREDUMP
66 #define WCOREDUMP(S) ((S) & WCOREFLG)
67 #endif
68 #ifndef WCOREFLG
69 #define WCOREFLG 0200
70 #endif
72 #ifndef EXIT_SUCCESS
73 #define EXIT_SUCCESS 0
74 #endif
76 #ifndef EXIT_FAILURE
77 #define EXIT_FAILURE 1
78 #endif
80 /* When this program is run with no arguments, it runs some tests of
81 the libiberty pexecute functions. As a test program, it simply
82 invokes itself with various arguments.
84 argv[1]:
85 *empty string* Run tests, exit with success status
86 exit Exit success
87 error Exit error
88 abort Abort
89 echo Echo remaining arguments, exit success
90 echoerr Echo next arg to stdout, next to stderr, repeat
91 copy Copy stdin to stdout
92 write Write stdin to file named in next argument
95 static void fatal_error (int, const char *, int) ATTRIBUTE_NORETURN;
96 static void error (int, const char *);
97 static void check_line (int, FILE *, const char *);
98 static void do_cmd (int, char **) ATTRIBUTE_NORETURN;
100 /* The number of errors we have seen. */
102 static int error_count;
104 /* Print a fatal error and exit. LINE is the line number where we
105 detected the error, ERRMSG is the error message to print, and ERR
106 is 0 or an errno value to print. */
108 static void
109 fatal_error (int line, const char *errmsg, int err)
111 fprintf (stderr, "test-pexecute:%d: %s", line, errmsg);
112 if (errno != 0)
113 fprintf (stderr, ": %s", xstrerror (err));
114 fprintf (stderr, "\n");
115 exit (EXIT_FAILURE);
118 #define FATAL_ERROR(ERRMSG, ERR) fatal_error (__LINE__, ERRMSG, ERR)
120 /* Print an error message and bump the error count. LINE is the line
121 number where we detected the error, ERRMSG is the error to
122 print. */
124 static void
125 error (int line, const char *errmsg)
127 fprintf (stderr, "test-pexecute:%d: %s\n", line, errmsg);
128 ++error_count;
131 #define ERROR(ERRMSG) error (__LINE__, ERRMSG)
133 /* Check a line in a file. */
135 static void
136 check_line (int line, FILE *e, const char *str)
138 const char *p;
139 int c;
140 char buf[1000];
142 p = str;
143 while (1)
145 c = getc (e);
147 if (*p == '\0')
149 if (c != '\n')
151 snprintf (buf, sizeof buf, "got '%c' when expecting newline", c);
152 fatal_error (line, buf, 0);
154 c = getc (e);
155 if (c != EOF)
157 snprintf (buf, sizeof buf, "got '%c' when expecting EOF", c);
158 fatal_error (line, buf, 0);
160 return;
163 if (c != *p)
165 snprintf (buf, sizeof buf, "expected '%c', got '%c'", *p, c);
166 fatal_error (line, buf, 0);
169 ++p;
173 #define CHECK_LINE(E, STR) check_line (__LINE__, E, STR)
175 /* Main function for the pexecute tester. Run the tests. */
178 main (int argc, char **argv)
180 int trace;
181 struct pex_obj *test_pex_tmp;
182 int test_pex_status;
183 FILE *test_pex_file;
184 struct pex_obj *pex1;
185 char *subargv[10];
186 int status;
187 FILE *e;
188 int statuses[10];
190 trace = 0;
191 if (argc > 1 && strcmp (argv[1], "-t") == 0)
193 trace = 1;
194 --argc;
195 ++argv;
198 if (argc > 1)
199 do_cmd (argc, argv);
201 #define TEST_PEX_INIT(FLAGS, TEMPBASE) \
202 (((test_pex_tmp = pex_init (FLAGS, "test-pexecute", TEMPBASE)) \
203 != NULL) \
204 ? test_pex_tmp \
205 : (FATAL_ERROR ("pex_init failed", 0), NULL))
207 #define TEST_PEX_RUN(PEXOBJ, FLAGS, EXECUTABLE, ARGV, OUTNAME, ERRNAME) \
208 do \
210 int err; \
211 if (trace) \
212 fprintf (stderr, "Line %d: running %s %s\n", \
213 __LINE__, EXECUTABLE, ARGV[0]); \
214 const char *pex_run_err = pex_run (PEXOBJ, FLAGS, EXECUTABLE, \
215 ARGV, OUTNAME, ERRNAME, &err); \
216 if (pex_run_err != NULL) \
217 FATAL_ERROR (pex_run_err, err); \
219 while (0)
221 #define TEST_PEX_GET_STATUS_1(PEXOBJ) \
222 (pex_get_status (PEXOBJ, 1, &test_pex_status) \
223 ? test_pex_status \
224 : (FATAL_ERROR ("pex_get_status failed", errno), 1))
226 #define TEST_PEX_GET_STATUS(PEXOBJ, COUNT, VECTOR) \
227 do \
229 if (!pex_get_status (PEXOBJ, COUNT, VECTOR)) \
230 FATAL_ERROR ("pex_get_status failed", errno); \
232 while (0)
234 #define TEST_PEX_READ_OUTPUT(PEXOBJ) \
235 ((test_pex_file = pex_read_output (PEXOBJ, 0)) != NULL \
236 ? test_pex_file \
237 : (FATAL_ERROR ("pex_read_output failed", errno), NULL))
239 remove ("temp.x");
240 remove ("temp.y");
242 memset (subargv, 0, sizeof subargv);
244 subargv[0] = "./test-pexecute";
246 pex1 = TEST_PEX_INIT (PEX_USE_PIPES, NULL);
247 subargv[1] = "exit";
248 subargv[2] = NULL;
249 TEST_PEX_RUN (pex1, PEX_LAST, "./test-pexecute", subargv, NULL, NULL);
250 status = TEST_PEX_GET_STATUS_1 (pex1);
251 if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS)
252 ERROR ("exit failed");
253 pex_free (pex1);
255 pex1 = TEST_PEX_INIT (PEX_USE_PIPES, NULL);
256 subargv[1] = "error";
257 subargv[2] = NULL;
258 TEST_PEX_RUN (pex1, PEX_LAST, "./test-pexecute", subargv, NULL, NULL);
259 status = TEST_PEX_GET_STATUS_1 (pex1);
260 if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_FAILURE)
261 ERROR ("error test failed");
262 pex_free (pex1);
264 /* We redirect stderr to a file to avoid an error message which is
265 printed on mingw32 when the child calls abort. */
266 pex1 = TEST_PEX_INIT (PEX_USE_PIPES, NULL);
267 subargv[1] = "abort";
268 subargv[2] = NULL;
269 TEST_PEX_RUN (pex1, PEX_LAST, "./test-pexecute", subargv, NULL, "temp.z");
270 status = TEST_PEX_GET_STATUS_1 (pex1);
271 if (!WIFSIGNALED (status) || WTERMSIG (status) != SIGABRT)
272 ERROR ("abort failed");
273 pex_free (pex1);
274 remove ("temp.z");
276 pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp");
277 subargv[1] = "echo";
278 subargv[2] = "foo";
279 subargv[3] = NULL;
280 TEST_PEX_RUN (pex1, 0, "./test-pexecute", subargv, NULL, NULL);
281 e = TEST_PEX_READ_OUTPUT (pex1);
282 CHECK_LINE (e, "foo");
283 if (TEST_PEX_GET_STATUS_1 (pex1) != 0)
284 ERROR ("echo exit status failed");
285 pex_free (pex1);
287 pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp");
288 subargv[1] = "echo";
289 subargv[2] = "bar";
290 subargv[3] = NULL;
291 TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", NULL);
292 subargv[1] = "copy";
293 subargv[2] = NULL;
294 TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL);
295 e = TEST_PEX_READ_OUTPUT (pex1);
296 CHECK_LINE (e, "bar");
297 TEST_PEX_GET_STATUS (pex1, 2, statuses);
298 if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS
299 || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS)
300 ERROR ("copy exit status failed");
301 pex_free (pex1);
302 if (fopen ("temp.x", "r") != NULL || fopen ("temp.y", "r") != NULL)
303 ERROR ("temporary files exist");
305 pex1 = TEST_PEX_INIT (0, "temp");
306 subargv[1] = "echo";
307 subargv[2] = "bar";
308 subargv[3] = NULL;
309 TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", NULL);
310 subargv[1] = "copy";
311 subargv[2] = NULL;
312 TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL);
313 e = TEST_PEX_READ_OUTPUT (pex1);
314 CHECK_LINE (e, "bar");
315 TEST_PEX_GET_STATUS (pex1, 2, statuses);
316 if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS
317 || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS)
318 ERROR ("copy exit status failed");
319 pex_free (pex1);
320 if (fopen ("temp.x", "r") != NULL || fopen ("temp.y", "r") != NULL)
321 ERROR ("temporary files exist");
323 pex1 = TEST_PEX_INIT (PEX_SAVE_TEMPS, "temp");
324 subargv[1] = "echo";
325 subargv[2] = "quux";
326 subargv[3] = NULL;
327 TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", NULL);
328 subargv[1] = "copy";
329 subargv[2] = NULL;
330 TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL);
331 e = TEST_PEX_READ_OUTPUT (pex1);
332 CHECK_LINE (e, "quux");
333 TEST_PEX_GET_STATUS (pex1, 2, statuses);
334 if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS
335 || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS)
336 ERROR ("copy temp exit status failed");
337 e = fopen ("temp.x", "r");
338 if (e == NULL)
339 FATAL_ERROR ("fopen temp.x failed in copy temp", errno);
340 CHECK_LINE (e, "quux");
341 fclose (e);
342 e = fopen ("temp.y", "r");
343 if (e == NULL)
344 FATAL_ERROR ("fopen temp.y failed in copy temp", errno);
345 CHECK_LINE (e, "quux");
346 fclose (e);
347 pex_free (pex1);
348 remove ("temp.x");
349 remove ("temp.y");
351 pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp");
352 subargv[1] = "echoerr";
353 subargv[2] = "one";
354 subargv[3] = "two";
355 subargv[4] = NULL;
356 TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", "temp2.x");
357 subargv[1] = "write";
358 subargv[2] = "temp2.y";
359 subargv[3] = NULL;
360 TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL);
361 TEST_PEX_GET_STATUS (pex1, 2, statuses);
362 if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS
363 || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS)
364 ERROR ("echoerr exit status failed");
365 pex_free (pex1);
366 if (fopen ("temp.x", "r") != NULL || fopen ("temp.y", "r") != NULL)
367 ERROR ("temporary files exist");
368 e = fopen ("temp2.x", "r");
369 if (e == NULL)
370 FATAL_ERROR ("fopen temp2.x failed in echoerr", errno);
371 CHECK_LINE (e, "two");
372 fclose (e);
373 e = fopen ("temp2.y", "r");
374 if (e == NULL)
375 FATAL_ERROR ("fopen temp2.y failed in echoerr", errno);
376 CHECK_LINE (e, "one");
377 fclose (e);
378 remove ("temp2.x");
379 remove ("temp2.y");
381 /* Test the old pexecute interface. */
383 int pid1, pid2;
384 char *errmsg_fmt;
385 char *errmsg_arg;
386 char errbuf1[1000];
387 char errbuf2[1000];
389 subargv[1] = "echo";
390 subargv[2] = "oldpexecute";
391 subargv[3] = NULL;
392 pid1 = pexecute ("./test-pexecute", subargv, "test-pexecute", "temp",
393 &errmsg_fmt, &errmsg_arg, PEXECUTE_FIRST);
394 if (pid1 < 0)
396 snprintf (errbuf1, sizeof errbuf1, errmsg_fmt, errmsg_arg);
397 snprintf (errbuf2, sizeof errbuf2, "pexecute 1 failed: %s", errbuf1);
398 FATAL_ERROR (errbuf2, 0);
401 subargv[1] = "write";
402 subargv[2] = "temp.y";
403 subargv[3] = NULL;
404 pid2 = pexecute ("./test-pexecute", subargv, "test-pexecute", "temp",
405 &errmsg_fmt, &errmsg_arg, PEXECUTE_LAST);
406 if (pid2 < 0)
408 snprintf (errbuf1, sizeof errbuf1, errmsg_fmt, errmsg_arg);
409 snprintf (errbuf2, sizeof errbuf2, "pexecute 2 failed: %s", errbuf1);
410 FATAL_ERROR (errbuf2, 0);
413 if (pwait (pid1, &status, 0) < 0)
414 FATAL_ERROR ("write pwait 1 failed", errno);
415 if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS)
416 ERROR ("write exit status 1 failed");
418 if (pwait (pid2, &status, 0) < 0)
419 FATAL_ERROR ("write pwait 1 failed", errno);
420 if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS)
421 ERROR ("write exit status 2 failed");
423 e = fopen ("temp.y", "r");
424 if (e == NULL)
425 FATAL_ERROR ("fopen temp.y failed in copy temp", errno);
426 CHECK_LINE (e, "oldpexecute");
427 fclose (e);
429 remove ("temp.y");
432 if (trace)
433 fprintf (stderr, "Exiting with status %d\n", error_count);
435 return error_count;
438 /* Execute one of the special testing commands. */
440 static void
441 do_cmd (int argc, char **argv)
443 const char *s;
445 /* Try to prevent generating a core dump. */
446 #ifdef RLIMIT_CORE
448 struct rlimit r;
450 r.rlim_cur = 0;
451 r.rlim_max = 0;
452 setrlimit (RLIMIT_CORE, &r);
454 #endif
456 s = argv[1];
457 if (strcmp (s, "exit") == 0)
458 exit (EXIT_SUCCESS);
459 else if (strcmp (s, "echo") == 0)
461 int i;
463 for (i = 2; i < argc; ++i)
465 if (i > 2)
466 putchar (' ');
467 fputs (argv[i], stdout);
469 putchar ('\n');
470 exit (EXIT_SUCCESS);
472 else if (strcmp (s, "echoerr") == 0)
474 int i;
476 for (i = 2; i < argc; ++i)
478 if (i > 3)
479 putc (' ', (i & 1) == 0 ? stdout : stderr);
480 fputs (argv[i], (i & 1) == 0 ? stdout : stderr);
482 putc ('\n', stdout);
483 putc ('\n', stderr);
484 exit (EXIT_SUCCESS);
486 else if (strcmp (s, "error") == 0)
487 exit (EXIT_FAILURE);
488 else if (strcmp (s, "abort") == 0)
489 abort ();
490 else if (strcmp (s, "copy") == 0)
492 int c;
494 while ((c = getchar ()) != EOF)
495 putchar (c);
496 exit (EXIT_SUCCESS);
498 else if (strcmp (s, "write") == 0)
500 FILE *e;
501 int c;
503 e = fopen (argv[2], "w");
504 if (e == NULL)
505 FATAL_ERROR ("fopen for write failed", errno);
506 while ((c = getchar ()) != EOF)
507 putc (c, e);
508 if (fclose (e) != 0)
509 FATAL_ERROR ("fclose for write failed", errno);
510 exit (EXIT_SUCCESS);
512 else
514 char buf[1000];
516 snprintf (buf, sizeof buf, "unrecognized command %s", argv[1]);
517 FATAL_ERROR (buf, 0);
520 exit (EXIT_FAILURE);