diff --git a/glib/gtestutils.c b/glib/gtestutils.c index 83b0ee5de..e9ca56dbd 100644 --- a/glib/gtestutils.c +++ b/glib/gtestutils.c @@ -4177,7 +4177,7 @@ g_test_trap_subprocess_with_envp (const char *test_path, flags = G_SPAWN_DO_NOT_REAP_CHILD; if (test_log_fd != -1) flags |= G_SPAWN_LEAVE_DESCRIPTORS_OPEN; - if (test_flags & G_TEST_TRAP_INHERIT_STDIN) + if (test_flags & G_TEST_SUBPROCESS_INHERIT_STDIN) flags |= G_SPAWN_CHILD_INHERITS_STDIN; if (!g_spawn_async_with_pipes (test_initial_cwd, diff --git a/glib/tests/testing.c b/glib/tests/testing.c index 0b6633700..fd541b010 100644 --- a/glib/tests/testing.c +++ b/glib/tests/testing.c @@ -35,6 +35,13 @@ #include #include +#ifdef G_OS_UNIX +#define _POSIX_C_SOURCE 200809L /* for F_DUPFD_CLOEXEC */ +#include +#include +#include +#endif + #define TAP_VERSION G_STRINGIFY (14) #define TAP_SUBTEST_PREFIX " " @@ -423,6 +430,56 @@ test_subprocess_envp (void) g_strfreev (envp); } +static void +test_subprocess_stdin (void) +{ +#ifdef G_OS_UNIX + int old_stdin_fd = -1; + int pipe_fd[2] = { -1, -1 }; + const char *test_string = "*hello there*"; + GError *local_error = NULL; + + if (g_test_subprocess ()) + { + char buf[100]; + ssize_t n_read; + + g_assert_no_errno (n_read = read (STDIN_FILENO, buf, sizeof (buf))); + g_assert_cmpint (n_read, >, 0); + + g_print ("Read: %.*s\n", (int) n_read, buf); + + return; + } + + /* Temporarily override this process’ stdin with a pipe. */ + old_stdin_fd = fcntl (STDIN_FILENO, F_DUPFD_CLOEXEC, 0); + g_assert_cmpint (old_stdin_fd, >=, 0); + + g_unix_open_pipe (pipe_fd, O_CLOEXEC, &local_error); + g_assert_no_error (local_error); + + g_assert_no_errno (dup2 (pipe_fd[0], STDIN_FILENO)); + + /* Write something into it for the subprocess to read. */ + g_assert_no_errno (write (pipe_fd[1], test_string, strlen (test_string) + 1)); + + /* Run the subprocess. */ + g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDIN); + g_test_trap_assert_passed (); + g_test_trap_assert_stdout (test_string); + + /* Restore the old stdin */ + g_assert_no_errno (dup2 (old_stdin_fd, STDIN_FILENO)); + + g_assert_no_errno (close (old_stdin_fd)); + g_assert_no_errno (close (pipe_fd[0])); + g_assert_no_errno (close (pipe_fd[1])); +#else + g_test_skip ("Testing stdin for subprocesses can only be done on Unix at the moment"); +#endif +} + /* run a test with fixture setup and teardown */ typedef struct { guint seed; @@ -2916,6 +2973,7 @@ main (int argc, g_test_add_func ("/trap_subprocess/no-such-test", test_subprocess_no_such_test); g_test_add_func ("/trap_subprocess/timeout", test_subprocess_timeout); g_test_add_func ("/trap_subprocess/envp", test_subprocess_envp); + g_test_add_func ("/trap_subprocess/stdin", test_subprocess_stdin); g_test_add_func ("/trap_subprocess/patterns", test_subprocess_patterns);