diff options
author | Bruno Haible <bruno@clisp.org> | 2020-11-29 21:27:57 +0100 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2020-11-29 21:34:04 +0100 |
commit | d43e61a65dcba77cbfddb96b19847daced7ef426 (patch) | |
tree | 23d4e805b5184f399d29dabdcd2defbfc9ee20cd /tests/test-execute-child.c | |
parent | a5a7a76caa23695c8b8229e48366cba980291cb4 (diff) | |
download | gnulib-d43e61a65dcba77cbfddb96b19847daced7ef426.tar.gz |
execute: Add tests.
* tests/test-execute.sh: New file.
* tests/test-execute-main.c: New file.
* tests/test-execute-child.c: New file.
* modules/execute-tests: New file.
Diffstat (limited to 'tests/test-execute-child.c')
-rw-r--r-- | tests/test-execute-child.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/tests/test-execute-child.c b/tests/test-execute-child.c new file mode 100644 index 0000000000..2994476bb7 --- /dev/null +++ b/tests/test-execute-child.c @@ -0,0 +1,176 @@ +/* Child program invoked by test-execute-main. + Copyright (C) 2009-2020 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include <fcntl.h> +#include <signal.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +/* Get _get_osfhandle. */ +# include <io.h> +#endif + +/* In this file, we use only system functions, no overrides from gnulib. */ +#undef atoi +#undef fcntl +#undef fflush +#undef fgetc +#undef fprintf +#undef fputs +#undef fstat +#undef raise +#undef sprintf +#undef stat +#undef strcmp +#undef strlen + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static void __cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ +} +#endif + +/* Return non-zero if FD is open. */ +static int +is_open (int fd) +{ +#if defined _WIN32 && ! defined __CYGWIN__ + /* On native Windows, the initial state of unassigned standard file + descriptors is that they are open but point to an + INVALID_HANDLE_VALUE, and there is no fcntl. */ + return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; +#else +# ifndef F_GETFL +# error Please port fcntl to your platform +# endif + return 0 <= fcntl (fd, F_GETFL); +#endif +} + +int +main (int argc, char *argv[]) +{ + if (argc == 1) + /* Check an invocation without arguments. Check the exit code. */ + return 40; + + int test = atoi (argv[1]); + switch (test) + { + case 2: + /* Check argument passing. */ + return !(argc == 12 + && strcmp (argv[2], "abc def") == 0 + && strcmp (argv[3], "abc\"def\"ghi") == 0 + && strcmp (argv[4], "xyz\"") == 0 + && strcmp (argv[5], "abc\\def\\ghi") == 0 + && strcmp (argv[6], "xyz\\") == 0 + && strcmp (argv[7], "???") == 0 + && strcmp (argv[8], "***") == 0 + && strcmp (argv[9], "") == 0 + && strcmp (argv[10], "foo") == 0 + && strcmp (argv[11], "") == 0); + #if !(defined _WIN32 && !defined __CYGWIN__) + case 3: + /* Check SIGPIPE handling with ignore_sigpipe = false. */ + case 4: + /* Check SIGPIPE handling with ignore_sigpipe = true. */ + raise (SIGPIPE); + return 71; + #endif + case 5: + /* Check other signal. */ + raise (SIGINT); + return 71; + case 6: + /* Check stdin is inherited. */ + return !(fgetc (stdin) == 'F' && fgetc (stdin) == 'o'); + case 7: + /* Check null_stdin = true. */ + return !(fgetc (stdin) == EOF); + case 8: + /* Check stdout is inherited, part 1 (regular file). */ + return !(fputs ("bar", stdout) != EOF && fflush (stdout) == 0); + case 9: + /* Check stdout is inherited, part 2 (device). */ + case 10: + /* Check null_stdout = true. */ + { + struct stat st; + return !(fstat (STDOUT_FILENO, &st) >= 0 && !S_ISREG (st.st_mode)); + } + case 11: + /* Check stderr is inherited, part 1 (regular file). */ + return !(fputs ("bar", stderr) != EOF && fflush (stderr) == 0); + case 12: + /* Check stderr is inherited, part 2 (device). */ + case 13: + /* Check null_stderr = true. */ + { + struct stat st; + return !(fstat (STDERR_FILENO, &st) >= 0 && !S_ISREG (st.st_mode)); + } + case 14: + case 15: + /* Check file descriptors >= 3 can be inherited. */ + case 16: + /* Check file descriptors >= 3 with O_CLOEXEC bit are not inherited. */ + #if HAVE_MSVC_INVALID_PARAMETER_HANDLER + /* Avoid exceptions from within _get_osfhandle. */ + _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler); + #endif + { + char buf[300]; + buf[0] = '\0'; + char *p = buf; + int fd; + for (fd = 0; fd < 20; fd++) + #ifdef __NetBSD__ + if (fd != 3) + #endif + if (is_open (fd)) + { + sprintf (p, "%d ", fd); + p += strlen (p); + } + const char *expected = (test < 16 ? "0 1 2 10 " : "0 1 2 "); + if (strcmp (buf, expected) == 0) + return 0; + else + { + fprintf (stderr, "Test case %d: %s\n", test, buf); fflush (stderr); + return 1; + } + } + default: + abort (); + } +} |