7 #include <gio/gunixinputstream.h>
8 #include <gio/gunixoutputstream.h>
9 #include <gio/gfiledescriptorbased.h>
15 #include <sys/ptrace.h>
18 /* We write 2^1 + 2^2 ... + 2^10 or 2047 copies of "Hello World!\n"
21 #define TOTAL_HELLOS 2047
22 #define HELLO_WORLD "hello world!\n"
25 #define LINEEND "\r\n"
27 #define SPLICELEN (TOTAL_HELLOS * (strlen (HELLO_WORLD) + 1)) /* because \r */
31 #define SPLICELEN (TOTAL_HELLOS * strlen (HELLO_WORLD))
37 #define TESTPROG "gsubprocess-testprog.exe"
39 #define TESTPROG "gsubprocess-testprog"
43 get_test_subprocess_args (const char *mode,
44 ...) G_GNUC_NULL_TERMINATED;
47 get_test_subprocess_args (const char *mode,
55 ret = g_ptr_array_new_with_free_func (g_free);
57 path = g_test_build_filename (G_TEST_BUILT, TESTPROG, NULL);
58 g_ptr_array_add (ret, path);
59 g_ptr_array_add (ret, g_strdup (mode));
61 va_start (args, mode);
62 while ((arg = va_arg (args, gpointer)) != NULL)
63 g_ptr_array_add (ret, g_strdup (arg));
66 g_ptr_array_add (ret, NULL);
73 GError *local_error = NULL;
74 GError **error = &local_error;
78 args = get_test_subprocess_args ("noop", NULL);
79 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
80 g_ptr_array_free (args, TRUE);
81 g_assert_no_error (local_error);
83 g_subprocess_wait_check (proc, NULL, error);
84 g_assert_no_error (local_error);
85 g_assert_true (g_subprocess_get_successful (proc));
87 g_object_unref (proc);
91 check_ready (GObject *source,
98 ret = g_subprocess_wait_check_finish (G_SUBPROCESS (source),
102 g_assert_no_error (error);
104 g_object_unref (source);
108 test_noop_all_to_null (void)
110 GError *local_error = NULL;
111 GError **error = &local_error;
115 args = get_test_subprocess_args ("noop", NULL);
116 proc = g_subprocess_newv ((const gchar * const *) args->pdata,
117 G_SUBPROCESS_FLAGS_STDOUT_SILENCE | G_SUBPROCESS_FLAGS_STDERR_SILENCE,
119 g_ptr_array_free (args, TRUE);
120 g_assert_no_error (local_error);
122 g_subprocess_wait_check_async (proc, NULL, check_ready, NULL);
126 test_noop_no_wait (void)
128 GError *local_error = NULL;
129 GError **error = &local_error;
133 args = get_test_subprocess_args ("noop", NULL);
134 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
135 g_ptr_array_free (args, TRUE);
136 g_assert_no_error (local_error);
138 g_object_unref (proc);
142 test_noop_stdin_inherit (void)
144 GError *local_error = NULL;
145 GError **error = &local_error;
149 args = get_test_subprocess_args ("noop", NULL);
150 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDIN_INHERIT, error);
151 g_ptr_array_free (args, TRUE);
152 g_assert_no_error (local_error);
154 g_subprocess_wait_check (proc, NULL, error);
155 g_assert_no_error (local_error);
157 g_object_unref (proc);
162 test_search_path (void)
164 GError *local_error = NULL;
165 GError **error = &local_error;
168 proc = g_subprocess_new (G_SUBPROCESS_FLAGS_NONE, error, "true", NULL);
169 g_assert_no_error (local_error);
171 g_subprocess_wait_check (proc, NULL, error);
172 g_assert_no_error (local_error);
174 g_object_unref (proc);
178 test_search_path_from_envp (void)
180 GError *local_error = NULL;
181 GError **error = &local_error;
182 GSubprocessLauncher *launcher;
186 path = g_test_get_dir (G_TEST_BUILT);
188 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP);
189 g_subprocess_launcher_setenv (launcher, "PATH", path, TRUE);
191 proc = g_subprocess_launcher_spawn (launcher, error, TESTPROG, "exit1", NULL);
192 g_assert_no_error (local_error);
193 g_object_unref (launcher);
195 g_subprocess_wait_check (proc, NULL, error);
196 g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
197 g_clear_error (error);
199 g_object_unref (proc);
206 GError *local_error = NULL;
207 GError **error = &local_error;
211 args = get_test_subprocess_args ("exit1", NULL);
212 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
213 g_ptr_array_free (args, TRUE);
214 g_assert_no_error (local_error);
216 g_subprocess_wait_check (proc, NULL, error);
217 g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
218 g_clear_error (error);
220 g_object_unref (proc);
225 GCancellable *cancellable;
227 } TestExit1CancelData;
230 test_exit1_cancel_idle_quit_cb (gpointer user_data)
232 GMainLoop *loop = user_data;
233 g_main_loop_quit (loop);
234 return G_SOURCE_REMOVE;
238 test_exit1_cancel_wait_check_cb (GObject *source,
239 GAsyncResult *result,
242 GSubprocess *subprocess = G_SUBPROCESS (source);
243 TestExit1CancelData *data = user_data;
245 GError *error = NULL;
247 g_assert_false (data->cb_called);
248 data->cb_called = TRUE;
250 ret = g_subprocess_wait_check_finish (subprocess, result, &error);
251 g_assert_false (ret);
252 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
253 g_clear_error (&error);
255 g_idle_add (test_exit1_cancel_idle_quit_cb, data->loop);
259 test_exit1_cancel (void)
261 GError *local_error = NULL;
262 GError **error = &local_error;
265 TestExit1CancelData data = { 0 };
267 g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=786456");
269 args = get_test_subprocess_args ("exit1", NULL);
270 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
271 g_ptr_array_free (args, TRUE);
272 g_assert_no_error (local_error);
274 data.loop = g_main_loop_new (NULL, FALSE);
275 data.cancellable = g_cancellable_new ();
276 g_subprocess_wait_check_async (proc, data.cancellable, test_exit1_cancel_wait_check_cb, &data);
278 g_subprocess_wait_check (proc, NULL, error);
279 g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
280 g_clear_error (error);
282 g_cancellable_cancel (data.cancellable);
283 g_main_loop_run (data.loop);
285 g_object_unref (proc);
286 g_main_loop_unref (data.loop);
287 g_clear_object (&data.cancellable);
291 test_exit1_cancel_in_cb_wait_check_cb (GObject *source,
292 GAsyncResult *result,
295 GSubprocess *subprocess = G_SUBPROCESS (source);
296 TestExit1CancelData *data = user_data;
298 GError *error = NULL;
300 g_assert_false (data->cb_called);
301 data->cb_called = TRUE;
303 ret = g_subprocess_wait_check_finish (subprocess, result, &error);
304 g_assert_false (ret);
305 g_assert_error (error, G_SPAWN_EXIT_ERROR, 1);
306 g_clear_error (&error);
308 g_cancellable_cancel (data->cancellable);
310 g_idle_add (test_exit1_cancel_idle_quit_cb, data->loop);
314 test_exit1_cancel_in_cb (void)
316 GError *local_error = NULL;
317 GError **error = &local_error;
320 TestExit1CancelData data = { 0 };
322 g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=786456");
324 args = get_test_subprocess_args ("exit1", NULL);
325 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
326 g_ptr_array_free (args, TRUE);
327 g_assert_no_error (local_error);
329 data.loop = g_main_loop_new (NULL, FALSE);
330 data.cancellable = g_cancellable_new ();
331 g_subprocess_wait_check_async (proc, data.cancellable, test_exit1_cancel_in_cb_wait_check_cb, &data);
333 g_subprocess_wait_check (proc, NULL, error);
334 g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
335 g_clear_error (error);
337 g_main_loop_run (data.loop);
339 g_object_unref (proc);
340 g_main_loop_unref (data.loop);
341 g_clear_object (&data.cancellable);
345 splice_to_string (GInputStream *stream,
348 GMemoryOutputStream *buffer = NULL;
351 buffer = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
352 if (g_output_stream_splice ((GOutputStream*)buffer, stream, 0, NULL, error) < 0)
355 if (!g_output_stream_write ((GOutputStream*)buffer, "\0", 1, NULL, error))
358 if (!g_output_stream_close ((GOutputStream*)buffer, NULL, error))
361 ret = g_memory_output_stream_steal_data (buffer);
363 g_clear_object (&buffer);
370 GError *local_error = NULL;
371 GError **error = &local_error;
374 GInputStream *stdout_stream;
377 args = get_test_subprocess_args ("echo", "hello", "world!", NULL);
378 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDOUT_PIPE, error);
379 g_ptr_array_free (args, TRUE);
380 g_assert_no_error (local_error);
382 stdout_stream = g_subprocess_get_stdout_pipe (proc);
384 result = splice_to_string (stdout_stream, error);
385 g_assert_no_error (local_error);
387 g_assert_cmpstr (result, ==, "hello" LINEEND "world!" LINEEND);
390 g_object_unref (proc);
395 test_echo_merged (void)
397 GError *local_error = NULL;
398 GError **error = &local_error;
401 GInputStream *stdout_stream;
404 args = get_test_subprocess_args ("echo-stdout-and-stderr", "merge", "this", NULL);
405 proc = g_subprocess_newv ((const gchar * const *) args->pdata,
406 G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_MERGE,
408 g_ptr_array_free (args, TRUE);
409 g_assert_no_error (local_error);
411 stdout_stream = g_subprocess_get_stdout_pipe (proc);
412 result = splice_to_string (stdout_stream, error);
413 g_assert_no_error (local_error);
415 g_assert_cmpstr (result, ==, "merge\nmerge\nthis\nthis\n");
418 g_object_unref (proc);
423 guint events_pending;
428 test_cat_on_input_splice_complete (GObject *object,
429 GAsyncResult *result,
432 TestCatData *data = user_data;
433 GError *error = NULL;
435 (void)g_output_stream_splice_finish ((GOutputStream*)object, result, &error);
436 g_assert_no_error (error);
438 data->events_pending--;
439 if (data->events_pending == 0)
440 g_main_loop_quit (data->loop);
446 GError *local_error = NULL;
447 GError **error = &local_error;
452 GInputStream *input_buf_stream = NULL;
453 GOutputStream *output_buf_stream = NULL;
454 GOutputStream *stdin_stream = NULL;
455 GInputStream *stdout_stream = NULL;
458 memset (&data, 0, sizeof (data));
459 data.loop = g_main_loop_new (NULL, TRUE);
461 args = get_test_subprocess_args ("cat", NULL);
462 proc = g_subprocess_newv ((const gchar * const *) args->pdata,
463 G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
465 g_ptr_array_free (args, TRUE);
466 g_assert_no_error (local_error);
468 stdin_stream = g_subprocess_get_stdin_pipe (proc);
469 stdout_stream = g_subprocess_get_stdout_pipe (proc);
471 input_buf = g_bytes_new_static ("hello, world!", strlen ("hello, world!"));
472 input_buf_stream = g_memory_input_stream_new_from_bytes (input_buf);
473 g_bytes_unref (input_buf);
475 output_buf_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
477 g_output_stream_splice_async (stdin_stream, input_buf_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
478 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
480 data.events_pending++;
481 g_output_stream_splice_async (output_buf_stream, stdout_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
482 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
484 data.events_pending++;
486 g_main_loop_run (data.loop);
488 g_subprocess_wait_check (proc, NULL, error);
489 g_assert_no_error (local_error);
491 output_buf = g_memory_output_stream_steal_as_bytes ((GMemoryOutputStream*)output_buf_stream);
493 g_assert_cmpmem (g_bytes_get_data (output_buf, NULL),
494 g_bytes_get_size (output_buf),
495 "hello, world!", 13);
497 g_bytes_unref (output_buf);
498 g_main_loop_unref (data.loop);
499 g_object_unref (input_buf_stream);
500 g_object_unref (output_buf_stream);
501 g_object_unref (proc);
505 cancel_soon (gpointer user_data)
507 GCancellable *cancellable = user_data;
509 g_usleep (G_TIME_SPAN_SECOND);
510 g_cancellable_cancel (cancellable);
511 g_object_unref (cancellable);
519 GCancellable *cancellable;
520 GError *error = NULL;
527 g_test_skip ("This test has not been ported to Win32");
532 cat = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, "cat", NULL);
533 g_assert_no_error (error);
534 g_assert_nonnull (cat);
536 /* Make sure that reading stdout blocks (until we cancel) */
537 cancellable = g_cancellable_new ();
538 g_thread_unref (g_thread_new ("cancel thread", cancel_soon, g_object_ref (cancellable)));
539 s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, cancellable, &error);
540 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
541 g_assert_cmpint (s, ==, -1);
542 g_object_unref (cancellable);
543 g_clear_error (&error);
545 /* Close the stream (EOF on cat's stdin) */
546 result = g_output_stream_close (g_subprocess_get_stdin_pipe (cat), NULL, &error);
547 g_assert_no_error (error);
548 g_assert_true (result);
550 /* Now check that reading cat's stdout gets us an EOF (since it quit) */
551 s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, NULL, &error);
552 g_assert_no_error (error);
555 /* Check that the process has exited as a result of the EOF */
556 result = g_subprocess_wait (cat, NULL, &error);
557 g_assert_no_error (error);
558 g_assert_true (g_subprocess_get_if_exited (cat));
559 g_assert_cmpint (g_subprocess_get_exit_status (cat), ==, 0);
560 g_assert_true (result);
562 g_object_unref (cat);
566 guint events_pending;
567 gboolean caught_error;
572 GOutputStream *first_stdin;
573 } TestMultiSpliceData;
576 on_one_multi_splice_done (GObject *obj,
580 TestMultiSpliceData *data = user_data;
582 if (!data->caught_error)
584 if (g_output_stream_splice_finish ((GOutputStream*)obj, res, &data->error) < 0)
585 data->caught_error = TRUE;
588 data->events_pending--;
589 if (data->events_pending == 0)
590 g_main_loop_quit (data->loop);
594 on_idle_multisplice (gpointer user_data)
596 TestMultiSpliceData *data = user_data;
598 if (data->counter >= TOTAL_HELLOS || data->caught_error)
600 if (!g_output_stream_close (data->first_stdin, NULL, &data->error))
601 data->caught_error = TRUE;
602 data->events_pending--;
603 if (data->events_pending == 0)
605 g_main_loop_quit (data->loop);
612 for (i = 0; i < data->counter; i++)
615 if (!g_output_stream_write_all (data->first_stdin, HELLO_WORLD,
616 strlen (HELLO_WORLD), &bytes_written,
619 data->caught_error = TRUE;
629 on_subprocess_exited (GObject *object,
630 GAsyncResult *result,
633 GSubprocess *subprocess = G_SUBPROCESS (object);
634 TestMultiSpliceData *data = user_data;
635 GError *error = NULL;
637 if (!g_subprocess_wait_finish (subprocess, result, &error))
639 if (!data->caught_error)
641 data->caught_error = TRUE;
642 g_propagate_error (&data->error, error);
645 g_spawn_check_wait_status (g_subprocess_get_status (subprocess), &error);
646 g_assert_no_error (error);
647 data->events_pending--;
648 if (data->events_pending == 0)
649 g_main_loop_quit (data->loop);
655 GError *local_error = NULL;
656 GError **error = &local_error;
658 GSubprocessLauncher *launcher;
662 GOutputStream *first_stdin;
663 GInputStream *first_stdout;
664 GOutputStream *second_stdin;
665 GInputStream *second_stdout;
666 GOutputStream *third_stdin;
667 GInputStream *third_stdout;
668 GOutputStream *membuf;
669 TestMultiSpliceData data;
670 int splice_flags = G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET;
672 args = get_test_subprocess_args ("cat", NULL);
673 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE);
674 first = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
675 g_assert_no_error (local_error);
676 second = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
677 g_assert_no_error (local_error);
678 third = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
679 g_assert_no_error (local_error);
681 g_ptr_array_free (args, TRUE);
683 membuf = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
685 first_stdin = g_subprocess_get_stdin_pipe (first);
686 first_stdout = g_subprocess_get_stdout_pipe (first);
687 second_stdin = g_subprocess_get_stdin_pipe (second);
688 second_stdout = g_subprocess_get_stdout_pipe (second);
689 third_stdin = g_subprocess_get_stdin_pipe (third);
690 third_stdout = g_subprocess_get_stdout_pipe (third);
692 memset (&data, 0, sizeof (data));
693 data.loop = g_main_loop_new (NULL, TRUE);
695 data.first_stdin = first_stdin;
697 data.events_pending++;
698 g_output_stream_splice_async (second_stdin, first_stdout, splice_flags, G_PRIORITY_DEFAULT,
699 NULL, on_one_multi_splice_done, &data);
700 data.events_pending++;
701 g_output_stream_splice_async (third_stdin, second_stdout, splice_flags, G_PRIORITY_DEFAULT,
702 NULL, on_one_multi_splice_done, &data);
703 data.events_pending++;
704 g_output_stream_splice_async (membuf, third_stdout, splice_flags, G_PRIORITY_DEFAULT,
705 NULL, on_one_multi_splice_done, &data);
707 data.events_pending++;
708 g_timeout_add (250, on_idle_multisplice, &data);
710 data.events_pending++;
711 g_subprocess_wait_async (first, NULL, on_subprocess_exited, &data);
712 data.events_pending++;
713 g_subprocess_wait_async (second, NULL, on_subprocess_exited, &data);
714 data.events_pending++;
715 g_subprocess_wait_async (third, NULL, on_subprocess_exited, &data);
717 g_main_loop_run (data.loop);
719 g_assert_false (data.caught_error);
720 g_assert_no_error (data.error);
722 g_assert_cmpint (g_memory_output_stream_get_data_size ((GMemoryOutputStream*)membuf), ==, SPLICELEN);
724 g_main_loop_unref (data.loop);
725 g_object_unref (membuf);
726 g_object_unref (launcher);
727 g_object_unref (first);
728 g_object_unref (second);
729 g_object_unref (third);
733 GSubprocessFlags flags;
737 } TestAsyncCommunicateData;
740 on_communicate_complete (GObject *proc,
741 GAsyncResult *result,
744 TestAsyncCommunicateData *data = user_data;
745 GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
746 char *stdout_str = NULL, *stderr_str = NULL;
747 const guint8 *stdout_data;
750 data->running = FALSE;
752 (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
753 &stdout_str, &stderr_str, &data->error);
755 (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
756 &stdout_bytes, &stderr_bytes, &data->error);
760 if (data->flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
764 g_assert_nonnull (stdout_str);
765 stdout_data = (guint8*)stdout_str;
766 stdout_len = strlen (stdout_str);
770 g_assert_nonnull (stdout_bytes);
771 stdout_data = g_bytes_get_data (stdout_bytes, &stdout_len);
774 g_assert_cmpmem (stdout_data, stdout_len, "# hello world" LINEEND, 13 + strlen (LINEEND));
778 g_assert_null (stdout_str);
779 g_assert_null (stdout_bytes);
782 if (data->flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
785 g_assert_nonnull (stderr_str);
787 g_assert_nonnull (stderr_bytes);
791 g_assert_null (stderr_str);
792 g_assert_null (stderr_bytes);
795 g_clear_pointer (&stdout_bytes, g_bytes_unref);
796 g_clear_pointer (&stderr_bytes, g_bytes_unref);
801 /* Test g_subprocess_communicate_async() works correctly with a variety of flags,
802 * as passed in via @test_data. */
804 test_communicate_async (gconstpointer test_data)
806 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
807 GError *error = NULL;
809 TestAsyncCommunicateData data = { flags, 0, 0, NULL };
811 GCancellable *cancellable = NULL;
813 const char *hellostring;
815 args = get_test_subprocess_args ("cat", NULL);
816 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
817 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
819 g_assert_no_error (error);
820 g_ptr_array_free (args, TRUE);
822 /* Include a leading hash and trailing newline so that if this gets onto the
823 * test’s stdout, it doesn’t mess up TAP output. */
824 hellostring = "# hello world\n";
825 input = g_bytes_new_static (hellostring, strlen (hellostring));
827 g_subprocess_communicate_async (proc, input,
829 on_communicate_complete,
834 g_main_context_iteration (NULL, TRUE);
836 g_assert_no_error (data.error);
838 g_bytes_unref (input);
839 g_object_unref (proc);
842 /* Test g_subprocess_communicate() works correctly with a variety of flags,
843 * as passed in via @test_data. */
845 test_communicate (gconstpointer test_data)
847 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
848 GError *error = NULL;
851 GCancellable *cancellable = NULL;
853 const gchar *hellostring;
854 GBytes *stdout_bytes, *stderr_bytes;
855 const gchar *stdout_data;
858 args = get_test_subprocess_args ("cat", NULL);
859 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
860 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
862 g_assert_no_error (error);
863 g_ptr_array_free (args, TRUE);
865 /* Include a leading hash and trailing newline so that if this gets onto the
866 * test’s stdout, it doesn’t mess up TAP output. */
867 hellostring = "# hello world\n";
868 input = g_bytes_new_static (hellostring, strlen (hellostring));
870 g_subprocess_communicate (proc, input, cancellable, &stdout_bytes, &stderr_bytes, &error);
871 g_assert_no_error (error);
873 if (flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
875 stdout_data = g_bytes_get_data (stdout_bytes, &stdout_len);
876 g_assert_cmpmem (stdout_data, stdout_len, "# hello world" LINEEND, 13 + strlen (LINEEND));
879 g_assert_null (stdout_bytes);
880 if (flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
881 g_assert_nonnull (stderr_bytes);
883 g_assert_null (stderr_bytes);
885 g_bytes_unref (input);
886 g_clear_pointer (&stdout_bytes, g_bytes_unref);
887 g_clear_pointer (&stderr_bytes, g_bytes_unref);
888 g_object_unref (proc);
893 GCancellable *cancellable;
897 } TestCancelledCommunicateData;
900 on_test_communicate_cancelled_idle (gpointer user_data)
902 TestCancelledCommunicateData *data = user_data;
904 const gchar *hellostring;
905 GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
906 gchar *stdout_buf = NULL, *stderr_buf = NULL;
908 /* Include a leading hash and trailing newline so that if this gets onto the
909 * test’s stdout, it doesn’t mess up TAP output. */
910 hellostring = "# hello world\n";
911 input = g_bytes_new_static (hellostring, strlen (hellostring));
914 g_subprocess_communicate_utf8 (data->proc, hellostring, data->cancellable,
915 &stdout_buf, &stderr_buf, &data->error);
917 g_subprocess_communicate (data->proc, input, data->cancellable, &stdout_bytes,
918 &stderr_bytes, &data->error);
920 data->running = FALSE;
924 g_assert_null (stdout_buf);
925 g_assert_null (stderr_buf);
929 g_assert_null (stdout_bytes);
930 g_assert_null (stderr_bytes);
933 g_bytes_unref (input);
935 return G_SOURCE_REMOVE;
938 /* Test g_subprocess_communicate() can be cancelled correctly */
940 test_communicate_cancelled (gconstpointer test_data)
942 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
945 GCancellable *cancellable = NULL;
946 GError *error = NULL;
947 TestCancelledCommunicateData data = { 0 };
949 args = get_test_subprocess_args ("cat", NULL);
950 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
951 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
953 g_assert_no_error (error);
954 g_ptr_array_free (args, TRUE);
956 cancellable = g_cancellable_new ();
959 data.cancellable = cancellable;
962 g_cancellable_cancel (cancellable);
963 g_idle_add (on_test_communicate_cancelled_idle, &data);
967 g_main_context_iteration (NULL, TRUE);
969 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
970 g_clear_error (&data.error);
972 g_object_unref (cancellable);
973 g_object_unref (proc);
977 on_communicate_cancelled_complete (GObject *proc,
978 GAsyncResult *result,
981 TestAsyncCommunicateData *data = user_data;
982 GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
983 char *stdout_str = NULL, *stderr_str = NULL;
985 data->running = FALSE;
987 (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
988 &stdout_str, &stderr_str, &data->error);
990 (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
991 &stdout_bytes, &stderr_bytes, &data->error);
995 g_assert_null (stdout_str);
996 g_assert_null (stderr_str);
1000 g_assert_null (stdout_bytes);
1001 g_assert_null (stderr_bytes);
1005 /* Test g_subprocess_communicate_async() can be cancelled correctly,
1006 * as passed in via @test_data. */
1008 test_communicate_cancelled_async (gconstpointer test_data)
1010 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1011 GError *error = NULL;
1013 TestAsyncCommunicateData data = { 0 };
1015 GCancellable *cancellable = NULL;
1017 const char *hellostring;
1019 args = get_test_subprocess_args ("cat", NULL);
1020 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1021 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1023 g_assert_no_error (error);
1024 g_ptr_array_free (args, TRUE);
1026 /* Include a leading hash and trailing newline so that if this gets onto the
1027 * test’s stdout, it doesn’t mess up TAP output. */
1028 hellostring = "# hello world\n";
1029 input = g_bytes_new_static (hellostring, strlen (hellostring));
1031 cancellable = g_cancellable_new ();
1033 g_subprocess_communicate_async (proc, input,
1035 on_communicate_cancelled_complete,
1038 g_cancellable_cancel (cancellable);
1040 data.running = TRUE;
1041 while (data.running)
1042 g_main_context_iteration (NULL, TRUE);
1044 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1045 g_clear_error (&data.error);
1047 g_bytes_unref (input);
1048 g_object_unref (cancellable);
1049 g_object_unref (proc);
1052 /* Test g_subprocess_communicate_utf8_async() works correctly with a variety of
1053 * flags, as passed in via @test_data. */
1055 test_communicate_utf8_async (gconstpointer test_data)
1057 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1058 GError *error = NULL;
1060 TestAsyncCommunicateData data = { flags, 0, 0, NULL };
1062 GCancellable *cancellable = NULL;
1064 args = get_test_subprocess_args ("cat", NULL);
1065 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1066 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1068 g_assert_no_error (error);
1069 g_ptr_array_free (args, TRUE);
1071 data.is_utf8 = TRUE;
1072 g_subprocess_communicate_utf8_async (proc, "# hello world\n",
1074 on_communicate_complete,
1077 data.running = TRUE;
1078 while (data.running)
1079 g_main_context_iteration (NULL, TRUE);
1081 g_assert_no_error (data.error);
1083 g_object_unref (proc);
1086 /* Test g_subprocess_communicate_utf8_async() can be cancelled correctly. */
1088 test_communicate_utf8_cancelled_async (gconstpointer test_data)
1090 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1091 GError *error = NULL;
1093 TestAsyncCommunicateData data = { flags, 0, 0, NULL };
1095 GCancellable *cancellable = NULL;
1097 args = get_test_subprocess_args ("cat", NULL);
1098 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1099 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1101 g_assert_no_error (error);
1102 g_ptr_array_free (args, TRUE);
1104 cancellable = g_cancellable_new ();
1105 data.is_utf8 = TRUE;
1106 g_subprocess_communicate_utf8_async (proc, "# hello world\n",
1108 on_communicate_cancelled_complete,
1111 g_cancellable_cancel (cancellable);
1113 data.running = TRUE;
1114 while (data.running)
1115 g_main_context_iteration (NULL, TRUE);
1117 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1118 g_clear_error (&data.error);
1120 g_object_unref (cancellable);
1121 g_object_unref (proc);
1124 /* Test g_subprocess_communicate_utf8() works correctly with a variety of flags,
1125 * as passed in via @test_data. */
1127 test_communicate_utf8 (gconstpointer test_data)
1129 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1130 GError *error = NULL;
1133 GCancellable *cancellable = NULL;
1134 const gchar *stdin_buf;
1135 gchar *stdout_buf, *stderr_buf;
1137 args = get_test_subprocess_args ("cat", NULL);
1138 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1139 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1141 g_assert_no_error (error);
1142 g_ptr_array_free (args, TRUE);
1144 /* Include a leading hash and trailing newline so that if this gets onto the
1145 * test’s stdout, it doesn’t mess up TAP output. */
1146 stdin_buf = "# hello world\n";
1148 g_subprocess_communicate_utf8 (proc, stdin_buf, cancellable, &stdout_buf, &stderr_buf, &error);
1149 g_assert_no_error (error);
1151 if (flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
1152 g_assert_cmpstr (stdout_buf, ==, "# hello world" LINEEND);
1154 g_assert_null (stdout_buf);
1155 if (flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
1156 g_assert_nonnull (stderr_buf);
1157 else g_assert_null (stderr_buf);
1159 g_free (stdout_buf);
1160 g_free (stderr_buf);
1161 g_object_unref (proc);
1164 /* Test g_subprocess_communicate_utf8() can be cancelled correctly */
1166 test_communicate_utf8_cancelled (gconstpointer test_data)
1168 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1171 GCancellable *cancellable = NULL;
1172 GError *error = NULL;
1173 TestCancelledCommunicateData data = { 0 };
1175 args = get_test_subprocess_args ("cat", NULL);
1176 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1177 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1179 g_assert_no_error (error);
1180 g_ptr_array_free (args, TRUE);
1182 cancellable = g_cancellable_new ();
1185 data.cancellable = cancellable;
1188 g_cancellable_cancel (cancellable);
1189 g_idle_add (on_test_communicate_cancelled_idle, &data);
1191 data.is_utf8 = TRUE;
1192 data.running = TRUE;
1193 while (data.running)
1194 g_main_context_iteration (NULL, TRUE);
1196 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1197 g_clear_error (&data.error);
1199 g_object_unref (cancellable);
1200 g_object_unref (proc);
1204 test_communicate_nothing (void)
1206 GError *error = NULL;
1209 GCancellable *cancellable = NULL;
1212 args = get_test_subprocess_args ("cat", NULL);
1213 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1214 G_SUBPROCESS_FLAGS_STDIN_PIPE
1215 | G_SUBPROCESS_FLAGS_STDOUT_PIPE
1216 | G_SUBPROCESS_FLAGS_STDERR_MERGE,
1218 g_assert_no_error (error);
1219 g_ptr_array_free (args, TRUE);
1221 g_subprocess_communicate_utf8 (proc, "", cancellable, &stdout_buf, NULL, &error);
1222 g_assert_no_error (error);
1224 g_assert_cmpstr (stdout_buf, ==, "");
1226 g_free (stdout_buf);
1228 g_object_unref (proc);
1232 test_communicate_utf8_async_invalid (void)
1234 GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE;
1235 GError *error = NULL;
1237 TestAsyncCommunicateData data = { flags, 0, 0, NULL };
1239 GCancellable *cancellable = NULL;
1241 args = get_test_subprocess_args ("cat", NULL);
1242 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1243 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1245 g_assert_no_error (error);
1246 g_ptr_array_free (args, TRUE);
1248 data.is_utf8 = TRUE;
1249 g_subprocess_communicate_utf8_async (proc, "\xFF\xFF",
1251 on_communicate_complete,
1254 data.running = TRUE;
1255 while (data.running)
1256 g_main_context_iteration (NULL, TRUE);
1258 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_FAILED);
1259 g_error_free (data.error);
1261 g_object_unref (proc);
1264 /* Test that invalid UTF-8 received using g_subprocess_communicate_utf8()
1265 * results in an error. */
1267 test_communicate_utf8_invalid (void)
1269 GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE;
1270 GError *local_error = NULL;
1273 gchar *stdout_str = NULL, *stderr_str = NULL;
1276 args = get_test_subprocess_args ("cat", NULL);
1277 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1278 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1280 g_assert_no_error (local_error);
1281 g_ptr_array_free (args, TRUE);
1283 ret = g_subprocess_communicate_utf8 (proc, "\xFF\xFF", NULL,
1284 &stdout_str, &stderr_str, &local_error);
1285 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_FAILED);
1286 g_error_free (local_error);
1287 g_assert_false (ret);
1289 g_assert_null (stdout_str);
1290 g_assert_null (stderr_str);
1292 g_object_unref (proc);
1296 send_terminate (gpointer user_data)
1298 GSubprocess *proc = user_data;
1300 g_subprocess_force_exit (proc);
1304 on_request_quit_exited (GObject *object,
1305 GAsyncResult *result,
1308 GSubprocess *subprocess = G_SUBPROCESS (object);
1309 GError *error = NULL;
1311 g_subprocess_wait_finish (subprocess, result, &error);
1312 g_assert_no_error (error);
1314 g_assert_true (g_subprocess_get_if_signaled (subprocess));
1315 g_assert_cmpint (g_subprocess_get_term_sig (subprocess), ==, 9);
1317 g_spawn_check_wait_status (g_subprocess_get_status (subprocess), &error);
1318 g_assert_nonnull (error);
1319 g_clear_error (&error);
1321 g_main_loop_quit ((GMainLoop*)user_data);
1325 test_terminate (void)
1327 GError *local_error = NULL;
1328 GError **error = &local_error;
1334 args = get_test_subprocess_args ("sleep-forever", NULL);
1335 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
1336 g_ptr_array_free (args, TRUE);
1337 g_assert_no_error (local_error);
1339 id = g_subprocess_get_identifier (proc);
1340 g_assert_nonnull (id);
1342 loop = g_main_loop_new (NULL, TRUE);
1344 g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
1346 g_timeout_add_seconds_once (3, send_terminate, proc);
1348 g_main_loop_run (loop);
1350 g_main_loop_unref (loop);
1351 g_object_unref (proc);
1356 send_signal (gpointer user_data)
1358 GSubprocess *proc = user_data;
1360 g_subprocess_send_signal (proc, SIGKILL);
1366 GError *local_error = NULL;
1367 GError **error = &local_error;
1372 args = get_test_subprocess_args ("sleep-forever", NULL);
1373 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
1374 g_ptr_array_free (args, TRUE);
1375 g_assert_no_error (local_error);
1377 loop = g_main_loop_new (NULL, TRUE);
1379 g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
1381 g_timeout_add_seconds_once (3, send_signal, proc);
1383 g_main_loop_run (loop);
1385 g_main_loop_unref (loop);
1386 g_object_unref (proc);
1393 GError *local_error = NULL;
1394 GError **error = &local_error;
1395 GSubprocessLauncher *launcher;
1398 GInputStream *stdout_stream;
1400 gchar *envp[] = { NULL, "ONE=1", "TWO=1", "THREE=3", "FOUR=1", NULL };
1403 envp[0] = g_strdup_printf ("PATH=%s", g_getenv ("PATH"));
1404 args = get_test_subprocess_args ("env", NULL);
1405 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1406 g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1407 g_subprocess_launcher_set_environ (launcher, envp);
1408 g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
1409 g_subprocess_launcher_setenv (launcher, "THREE", "1", FALSE);
1410 g_subprocess_launcher_unsetenv (launcher, "FOUR");
1412 g_assert_null (g_subprocess_launcher_getenv (launcher, "FOUR"));
1414 proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
1415 g_ptr_array_free (args, TRUE);
1416 g_assert_no_error (local_error);
1419 stdout_stream = g_subprocess_get_stdout_pipe (proc);
1421 result = splice_to_string (stdout_stream, error);
1422 split = g_strsplit (result, LINEEND, -1);
1423 g_assert_cmpstr (g_environ_getenv (split, "ONE"), ==, "1");
1424 g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
1425 g_assert_cmpstr (g_environ_getenv (split, "THREE"), ==, "3");
1426 g_assert_null (g_environ_getenv (split, "FOUR"));
1430 g_object_unref (proc);
1431 g_object_unref (launcher);
1434 /* Test that explicitly inheriting and modifying the parent process’
1435 * environment works. */
1437 test_env_inherit (void)
1439 GError *local_error = NULL;
1440 GError **error = &local_error;
1441 GSubprocessLauncher *launcher;
1444 GInputStream *stdout_stream;
1448 g_setenv ("TEST_ENV_INHERIT1", "1", TRUE);
1449 g_setenv ("TEST_ENV_INHERIT2", "2", TRUE);
1451 args = get_test_subprocess_args ("env", NULL);
1452 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1453 g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1454 g_subprocess_launcher_set_environ (launcher, NULL);
1455 g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
1456 g_subprocess_launcher_unsetenv (launcher, "TEST_ENV_INHERIT1");
1458 g_assert_null (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT1"));
1459 g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT2"), ==, "2");
1460 g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TWO"), ==, "2");
1462 proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
1463 g_ptr_array_free (args, TRUE);
1464 g_assert_no_error (local_error);
1466 stdout_stream = g_subprocess_get_stdout_pipe (proc);
1468 result = splice_to_string (stdout_stream, error);
1469 split = g_strsplit (result, LINEEND, -1);
1470 g_assert_null (g_environ_getenv (split, "TEST_ENV_INHERIT1"));
1471 g_assert_cmpstr (g_environ_getenv (split, "TEST_ENV_INHERIT2"), ==, "2");
1472 g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
1476 g_object_unref (proc);
1477 g_object_unref (launcher);
1483 GError *local_error = NULL;
1484 GSubprocessLauncher *launcher;
1487 GInputStream *stdout_stream;
1490 const gchar *tmpdir = g_get_tmp_dir ();
1491 gchar *tmpdir_basename = NULL, *result_basename = NULL;
1493 args = get_test_subprocess_args ("cwd", NULL);
1494 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1495 g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1496 g_subprocess_launcher_set_cwd (launcher, tmpdir);
1498 proc = g_subprocess_launcher_spawnv (launcher, (const char * const *)args->pdata, &local_error);
1499 g_ptr_array_free (args, TRUE);
1500 g_assert_no_error (local_error);
1502 stdout_stream = g_subprocess_get_stdout_pipe (proc);
1504 result = splice_to_string (stdout_stream, &local_error);
1505 g_assert_no_error (local_error);
1506 result_len = strlen (result);
1508 /* The result should end with a line ending */
1509 g_assert_cmpstr (result + result_len - strlen (LINEEND), ==, LINEEND);
1511 /* Not sure if the testprog guarantees to return an absolute path for the cwd,
1512 * so only compare the basenames. */
1513 tmpdir_basename = g_path_get_basename (tmpdir);
1514 result_basename = g_path_get_basename (g_strstrip (result));
1515 g_assert_cmpstr (tmpdir_basename, ==, result_basename);
1516 g_free (tmpdir_basename);
1517 g_free (result_basename);
1520 g_object_unref (proc);
1521 g_object_unref (launcher);
1526 test_subprocess_launcher_close (void)
1528 GError *local_error = NULL;
1529 GError **error = &local_error;
1530 GSubprocessLauncher *launcher;
1536 /* Open two arbitrary FDs. One of them, @fd, will be transferred to the
1537 * launcher, and the other’s FD integer will be used as its target FD, giving
1538 * the mapping `fd → fd2` if a child process were to be spawned.
1540 * The launcher will then be closed, which should close @fd but *not* @fd2,
1541 * as the value of @fd2 is only valid as an FD in a child process. (A child
1542 * process is not actually spawned in this test.)
1546 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1547 g_subprocess_launcher_take_fd (launcher, fd, fd2);
1549 is_open = fcntl (fd, F_GETFD) != -1;
1550 g_assert_true (is_open);
1551 is_open = fcntl (fd2, F_GETFD) != -1;
1552 g_assert_true (is_open);
1554 g_subprocess_launcher_close (launcher);
1556 is_open = fcntl (fd, F_GETFD) != -1;
1557 g_assert_false (is_open);
1558 is_open = fcntl (fd2, F_GETFD) != -1;
1559 g_assert_true (is_open);
1561 /* Now test that actually trying to spawn the child gives %G_IO_ERROR_CLOSED,
1562 * as g_subprocess_launcher_close() has been called. */
1563 args = get_test_subprocess_args ("cat", NULL);
1564 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1565 g_ptr_array_free (args, TRUE);
1566 g_assert_null (proc);
1567 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_CLOSED);
1568 g_clear_error (error);
1571 g_object_unref (launcher);
1575 test_stdout_file (void)
1577 GError *local_error = NULL;
1578 GError **error = &local_error;
1579 GSubprocessLauncher *launcher;
1583 GFileIOStream *iostream;
1584 GOutputStream *stdin_stream;
1585 const char *test_data = "this is some test data\n";
1587 char *tmp_file_path;
1589 tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1590 g_assert_no_error (local_error);
1591 g_clear_object (&iostream);
1593 tmp_file_path = g_file_get_path (tmpfile);
1595 args = get_test_subprocess_args ("cat", NULL);
1596 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1597 g_subprocess_launcher_set_stdout_file_path (launcher, tmp_file_path);
1598 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1599 g_ptr_array_free (args, TRUE);
1600 g_assert_no_error (local_error);
1602 stdin_stream = g_subprocess_get_stdin_pipe (proc);
1604 g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1605 g_assert_no_error (local_error);
1607 g_output_stream_close (stdin_stream, NULL, error);
1608 g_assert_no_error (local_error);
1610 g_subprocess_wait_check (proc, NULL, error);
1612 g_object_unref (launcher);
1613 g_object_unref (proc);
1615 g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1616 g_assert_no_error (local_error);
1618 g_assert_cmpstr (test_data, ==, tmp_contents);
1619 g_free (tmp_contents);
1621 (void) g_file_delete (tmpfile, NULL, NULL);
1622 g_object_unref (tmpfile);
1623 g_free (tmp_file_path);
1627 test_stdout_fd (void)
1629 GError *local_error = NULL;
1630 GError **error = &local_error;
1631 GSubprocessLauncher *launcher;
1635 GFileIOStream *iostream;
1636 GFileDescriptorBased *descriptor_stream;
1637 GOutputStream *stdin_stream;
1638 const char *test_data = "this is some test data\n";
1641 tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1642 g_assert_no_error (local_error);
1644 args = get_test_subprocess_args ("cat", NULL);
1645 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1646 descriptor_stream = G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream)));
1647 g_subprocess_launcher_take_stdout_fd (launcher, dup (g_file_descriptor_based_get_fd (descriptor_stream)));
1648 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1649 g_ptr_array_free (args, TRUE);
1650 g_assert_no_error (local_error);
1652 g_clear_object (&iostream);
1654 stdin_stream = g_subprocess_get_stdin_pipe (proc);
1656 g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1657 g_assert_no_error (local_error);
1659 g_output_stream_close (stdin_stream, NULL, error);
1660 g_assert_no_error (local_error);
1662 g_subprocess_wait_check (proc, NULL, error);
1664 g_object_unref (launcher);
1665 g_object_unref (proc);
1667 g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1668 g_assert_no_error (local_error);
1670 g_assert_cmpstr (test_data, ==, tmp_contents);
1671 g_free (tmp_contents);
1673 (void) g_file_delete (tmpfile, NULL, NULL);
1674 g_object_unref (tmpfile);
1678 child_setup (gpointer user_data)
1680 dup2 (GPOINTER_TO_INT (user_data), 1);
1684 test_child_setup (void)
1686 GError *local_error = NULL;
1687 GError **error = &local_error;
1688 GSubprocessLauncher *launcher;
1692 GFileIOStream *iostream;
1693 GOutputStream *stdin_stream;
1694 const char *test_data = "this is some test data\n";
1698 tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1699 g_assert_no_error (local_error);
1701 fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream))));
1703 args = get_test_subprocess_args ("cat", NULL);
1704 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1705 g_subprocess_launcher_set_child_setup (launcher, child_setup, GINT_TO_POINTER (fd), NULL);
1706 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1707 g_ptr_array_free (args, TRUE);
1708 g_assert_no_error (local_error);
1710 g_clear_object (&iostream);
1712 stdin_stream = g_subprocess_get_stdin_pipe (proc);
1714 g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1715 g_assert_no_error (local_error);
1717 g_output_stream_close (stdin_stream, NULL, error);
1718 g_assert_no_error (local_error);
1720 g_subprocess_wait_check (proc, NULL, error);
1722 g_object_unref (launcher);
1723 g_object_unref (proc);
1725 g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1726 g_assert_no_error (local_error);
1728 g_assert_cmpstr (test_data, ==, tmp_contents);
1729 g_free (tmp_contents);
1731 (void) g_file_delete (tmpfile, NULL, NULL);
1732 g_object_unref (tmpfile);
1736 do_test_pass_fd (GSubprocessFlags flags,
1737 GSpawnChildSetupFunc child_setup)
1739 GError *local_error = NULL;
1740 GError **error = &local_error;
1741 GInputStream *child_input;
1742 GDataInputStream *child_datainput;
1743 GSubprocessLauncher *launcher;
1746 int basic_pipefds[2];
1747 int needdup_pipefds[2];
1751 char *needdup_fd_str;
1753 g_unix_open_pipe (basic_pipefds, O_CLOEXEC, error);
1754 g_assert_no_error (local_error);
1755 g_unix_open_pipe (needdup_pipefds, O_CLOEXEC, error);
1756 g_assert_no_error (local_error);
1758 basic_fd_str = g_strdup_printf ("%d", basic_pipefds[1]);
1759 needdup_fd_str = g_strdup_printf ("%d", needdup_pipefds[1] + 1);
1761 args = get_test_subprocess_args ("write-to-fds", basic_fd_str, needdup_fd_str, NULL);
1762 launcher = g_subprocess_launcher_new (flags);
1763 g_subprocess_launcher_take_fd (launcher, basic_pipefds[1], basic_pipefds[1]);
1764 g_subprocess_launcher_take_fd (launcher, needdup_pipefds[1], needdup_pipefds[1] + 1);
1765 if (child_setup != NULL)
1766 g_subprocess_launcher_set_child_setup (launcher, child_setup, NULL, NULL);
1767 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1768 g_ptr_array_free (args, TRUE);
1769 g_assert_no_error (local_error);
1771 g_free (basic_fd_str);
1772 g_free (needdup_fd_str);
1774 child_input = g_unix_input_stream_new (basic_pipefds[0], TRUE);
1775 child_datainput = g_data_input_stream_new (child_input);
1776 buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1777 g_assert_no_error (local_error);
1778 g_assert_cmpstr (buf, ==, "hello world");
1779 g_object_unref (child_datainput);
1780 g_object_unref (child_input);
1783 child_input = g_unix_input_stream_new (needdup_pipefds[0], TRUE);
1784 child_datainput = g_data_input_stream_new (child_input);
1785 buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1786 g_assert_no_error (local_error);
1787 g_assert_cmpstr (buf, ==, "hello world");
1789 g_object_unref (child_datainput);
1790 g_object_unref (child_input);
1792 g_object_unref (launcher);
1793 g_object_unref (proc);
1799 do_test_pass_fd (G_SUBPROCESS_FLAGS_NONE, NULL);
1803 empty_child_setup (gpointer user_data)
1808 test_pass_fd_empty_child_setup (void)
1810 /* Using a child setup function forces gspawn to use fork/exec
1811 * rather than posix_spawn.
1813 do_test_pass_fd (G_SUBPROCESS_FLAGS_NONE, empty_child_setup);
1817 test_pass_fd_inherit_fds (void)
1819 /* Try to test the optimized posix_spawn codepath instead of
1820 * fork/exec. Currently this requires using INHERIT_FDS since gspawn's
1821 * posix_spawn codepath does not currently handle closing
1822 * non-inherited fds. Note that using INHERIT_FDS means our testing of
1823 * g_subprocess_launcher_take_fd() is less-comprehensive than when
1824 * using G_SUBPROCESS_FLAGS_NONE.
1826 do_test_pass_fd (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL);
1830 do_test_fd_conflation (GSubprocessFlags flags,
1831 GSpawnChildSetupFunc child_setup,
1832 gboolean test_child_err_report_fd)
1834 char success_message[] = "Yay success!";
1835 GError *error = NULL;
1836 GOutputStream *output_stream;
1837 GSubprocessLauncher *launcher;
1840 int unused_pipefds[2];
1842 int fd_to_pass_to_child;
1843 gsize bytes_written;
1847 /* This test must run in a new process because it is extremely sensitive to
1848 * order of opened fds.
1850 if (!g_test_subprocess ())
1852 g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR);
1853 g_test_trap_assert_passed ();
1857 g_unix_open_pipe (unused_pipefds, O_CLOEXEC, &error);
1858 g_assert_no_error (error);
1860 g_unix_open_pipe (pipefds, O_CLOEXEC, &error);
1861 g_assert_no_error (error);
1863 /* The fds should be sequential since we are in a new process. */
1864 g_assert_cmpint (unused_pipefds[0] /* 3 */, ==, unused_pipefds[1] - 1);
1865 g_assert_cmpint (unused_pipefds[1] /* 4 */, ==, pipefds[0] - 1);
1866 g_assert_cmpint (pipefds[0] /* 5 */, ==, pipefds[1] /* 6 */ - 1);
1868 /* Because GSubprocess allows arbitrary remapping of fds, it has to be careful
1869 * to avoid fd conflation issues, e.g. it should properly handle 5 -> 4 and
1870 * 4 -> 5 at the same time. GIO previously attempted to handle this by naively
1871 * dup'ing the source fds, but this was not good enough because it was
1872 * possible that the dup'ed result could still conflict with one of the target
1875 * source_fd 5 -> target_fd 9, source_fd 3 -> target_fd 7
1877 * dup(5) -> dup returns 8
1878 * dup(3) -> dup returns 9
1880 * After dup'ing, we wind up with: 8 -> 9, 9 -> 7. That means that after we
1881 * dup2(8, 9), we have clobbered fd 9 before we dup2(9, 7). The end result is
1882 * we have remapped 5 -> 9 as expected, but then remapped 5 -> 7 instead of
1883 * 3 -> 7 as the application intended.
1885 * This issue has been fixed in the simplest way possible, by passing a
1886 * minimum fd value when using F_DUPFD_CLOEXEC that is higher than any of the
1887 * target fds, to guarantee all source fds are different than all target fds,
1888 * eliminating any possibility of conflation.
1890 * Anyway, that is why we have the unused_pipefds here. We need to open fds in
1891 * a certain order in order to trick older GSubprocess into conflating the
1892 * fds. The primary goal of this test is to ensure this particular conflation
1893 * issue is not reintroduced. See glib#2503.
1895 * This test also has an alternate mode of operation where it instead tests
1896 * for conflation with gspawn's child_err_report_fd, glib#2506.
1898 * Be aware this test is necessarily extremely fragile. To reproduce these
1899 * bugs, it relies on internals of gspawn and gmain that will likely change
1900 * in the future, eventually causing this test to no longer test the bugs
1901 * it was originally designed to test. That is OK! If the test fails, at
1902 * least you know *something* is wrong.
1904 if (test_child_err_report_fd)
1905 fd_to_pass_to_child = pipefds[1] + 2 /* 8 */;
1907 fd_to_pass_to_child = pipefds[1] + 3 /* 9 */;
1909 launcher = g_subprocess_launcher_new (flags);
1910 g_subprocess_launcher_take_fd (launcher, pipefds[0] /* 5 */, fd_to_pass_to_child);
1911 g_subprocess_launcher_take_fd (launcher, unused_pipefds[0] /* 3 */, pipefds[1] + 1 /* 7 */);
1912 if (child_setup != NULL)
1913 g_subprocess_launcher_set_child_setup (launcher, child_setup, NULL, NULL);
1914 fd_str = g_strdup_printf ("%d", fd_to_pass_to_child);
1915 args = get_test_subprocess_args ("read-from-fd", fd_str, NULL);
1916 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, &error);
1917 g_assert_no_error (error);
1918 g_assert_nonnull (proc);
1919 g_ptr_array_free (args, TRUE);
1920 g_object_unref (launcher);
1923 /* Close the read ends of the pipes. */
1924 close (unused_pipefds[0]);
1927 /* Also close the write end of the unused pipe. */
1928 close (unused_pipefds[1]);
1930 /* If doing our normal test:
1932 * So now pipefds[0] should be inherited into the subprocess as
1933 * pipefds[1] + 2, and unused_pipefds[0] should be inherited as
1934 * pipefds[1] + 1. We will write to pipefds[1] and the subprocess will verify
1935 * that it reads the expected data. But older broken GIO will accidentally
1936 * clobber pipefds[1] + 2 with pipefds[1] + 1! This will cause the subprocess
1937 * to hang trying to read from the wrong pipe.
1939 * If testing conflation with child_err_report_fd:
1941 * We are actually already done. The real test succeeded if we made it this
1942 * far without hanging while spawning the child. But let's continue with our
1943 * write and read anyway, to ensure things are good.
1945 output_stream = g_unix_output_stream_new (pipefds[1], TRUE);
1946 success = g_output_stream_write_all (output_stream,
1947 success_message, sizeof (success_message),
1951 g_assert_no_error (error);
1952 g_assert_cmpint (bytes_written, ==, sizeof (success_message));
1953 g_assert_true (success);
1954 g_object_unref (output_stream);
1956 success = g_subprocess_wait_check (proc, NULL, &error);
1957 g_assert_no_error (error);
1958 g_object_unref (proc);
1962 test_fd_conflation (void)
1964 do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, NULL, FALSE);
1968 test_fd_conflation_empty_child_setup (void)
1970 /* Using a child setup function forces gspawn to use fork/exec
1971 * rather than posix_spawn.
1973 do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup, FALSE);
1977 test_fd_conflation_inherit_fds (void)
1979 /* Try to test the optimized posix_spawn codepath instead of
1980 * fork/exec. Currently this requires using INHERIT_FDS since gspawn's
1981 * posix_spawn codepath does not currently handle closing
1982 * non-inherited fds.
1984 do_test_fd_conflation (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL, FALSE);
1988 test_fd_conflation_child_err_report_fd (void)
1990 /* Using a child setup function forces gspawn to use fork/exec
1991 * rather than posix_spawn.
1993 do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup, TRUE);
1998 /* Handle ptrace events on @main_child, and assert that when it exits, it does
1999 * so with status %EXIT_SUCCESS, rather than signalling. Other than that, this
2000 * just calls %PTRACE_CONT for all trace events. */
2002 trace_children (pid_t main_child)
2006 g_assert_no_errno (waitpid (main_child, &wstatus, 0));
2007 g_assert_no_errno (ptrace (PTRACE_SETOPTIONS, main_child, NULL,
2008 (PTRACE_O_TRACEFORK |
2009 #ifdef HAVE_PTRACE_O_EXITKILL
2012 PTRACE_O_TRACEVFORK |
2013 PTRACE_O_TRACECLONE |
2014 PTRACE_O_TRACEEXEC)));
2015 g_assert_no_errno (ptrace (PTRACE_CONT, main_child, NULL, 0));
2024 pid = waitpid (-1, &wstatus, 0);
2025 if (pid == -1 && errno == ECHILD)
2028 g_assert_cmpint (errno, ==, 0);
2029 g_assert_cmpint (pid, >=, 0);
2031 if (WIFSTOPPED (wstatus))
2032 stop_signum = WSTOPSIG (wstatus);
2036 switch (stop_signum)
2039 ptrace_event = (wstatus >> 16) & 0xffff;
2040 switch (ptrace_event)
2043 g_assert_no_errno (ptrace (PTRACE_CONT, pid, NULL, stop_signum));
2046 g_assert_no_errno (ptrace (PTRACE_CONT, pid, NULL, 0));
2051 g_assert_no_errno (ptrace (PTRACE_CONT, pid, NULL, 0));
2054 if (!WIFEXITED (wstatus) && !WIFSIGNALED (wstatus))
2055 g_assert_no_errno (ptrace (PTRACE_CONT, pid, NULL, stop_signum));
2059 if (pid == main_child)
2061 g_assert_false (WIFSIGNALED (wstatus));
2062 if (WIFEXITED (wstatus))
2064 g_assert_cmpint (WEXITSTATUS (wstatus), ==, EXIT_SUCCESS);
2071 #endif /* __linux__ */
2074 test_exit_status_trapped (void)
2077 GPtrArray *args = NULL;
2081 g_test_summary ("Test that exit status is reported correctly for ptrace()d child processes");
2082 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3433");
2085 /* Call fork() directly here, rather than using #GSubprocess, so that we can
2086 * safely call waitpid() on it ourselves without interfering with the internals
2088 * See https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3433#note_1749055 */
2089 args = get_test_subprocess_args ("sleep-and-kill", NULL);
2090 test_child = fork ();
2091 if (test_child == 0)
2093 /* Between fork() and exec() we can only call async-signal-safe functions. */
2094 if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) < 0)
2097 g_assert_no_errno (execvp (args->pdata[0], (char * const *) args->pdata));
2100 trace_children (test_child);
2102 g_clear_pointer (&args, g_ptr_array_unref);
2104 g_test_skip ("ptrace() support for this test is only tested on Linux");
2108 #endif /* G_OS_UNIX */
2111 test_launcher_environment (void)
2113 GSubprocessLauncher *launcher;
2114 GError *error = NULL;
2119 g_setenv ("A", "B", TRUE);
2120 g_setenv ("C", "D", TRUE);
2122 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
2124 /* unset a variable */
2125 g_subprocess_launcher_unsetenv (launcher, "A");
2127 /* and set a different one */
2128 g_subprocess_launcher_setenv (launcher, "E", "F", TRUE);
2130 args = get_test_subprocess_args ("printenv", "A", "C", "E", NULL);
2131 proc = g_subprocess_launcher_spawnv (launcher, (const gchar **) args->pdata, &error);
2132 g_assert_no_error (error);
2133 g_assert_nonnull (proc);
2135 g_subprocess_communicate_utf8 (proc, NULL, NULL, &out, NULL, &error);
2136 g_assert_no_error (error);
2138 g_assert_cmpstr (out, ==, "C=D" LINEEND "E=F" LINEEND);
2141 g_object_unref (proc);
2142 g_object_unref (launcher);
2143 g_ptr_array_unref (args);
2147 main (int argc, char **argv)
2151 const gchar *subtest;
2152 GSubprocessFlags flags;
2156 { "", G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_MERGE },
2157 { "/no-pipes", G_SUBPROCESS_FLAGS_NONE },
2158 { "/separate-stderr", G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE },
2159 { "/stdout-only", G_SUBPROCESS_FLAGS_STDOUT_PIPE },
2160 { "/stderr-only", G_SUBPROCESS_FLAGS_STDERR_PIPE },
2161 { "/stdout-silence", G_SUBPROCESS_FLAGS_STDOUT_SILENCE },
2165 g_test_init (&argc, &argv, NULL);
2167 g_test_add_func ("/gsubprocess/noop", test_noop);
2168 g_test_add_func ("/gsubprocess/noop-all-to-null", test_noop_all_to_null);
2169 g_test_add_func ("/gsubprocess/noop-no-wait", test_noop_no_wait);
2170 g_test_add_func ("/gsubprocess/noop-stdin-inherit", test_noop_stdin_inherit);
2172 g_test_add_func ("/gsubprocess/search-path", test_search_path);
2173 g_test_add_func ("/gsubprocess/search-path-from-envp", test_search_path_from_envp);
2174 g_test_add_func ("/gsubprocess/signal", test_signal);
2176 g_test_add_func ("/gsubprocess/exit1", test_exit1);
2177 g_test_add_func ("/gsubprocess/exit1/cancel", test_exit1_cancel);
2178 g_test_add_func ("/gsubprocess/exit1/cancel_in_cb", test_exit1_cancel_in_cb);
2179 g_test_add_func ("/gsubprocess/echo1", test_echo1);
2181 g_test_add_func ("/gsubprocess/echo-merged", test_echo_merged);
2183 g_test_add_func ("/gsubprocess/cat-utf8", test_cat_utf8);
2184 g_test_add_func ("/gsubprocess/cat-eof", test_cat_eof);
2185 g_test_add_func ("/gsubprocess/multi1", test_multi_1);
2187 /* Add various tests for g_subprocess_communicate() with different flags. */
2188 for (i = 0; i < G_N_ELEMENTS (flags_vectors); i++)
2190 gchar *test_path = NULL;
2192 test_path = g_strdup_printf ("/gsubprocess/communicate%s", flags_vectors[i].subtest);
2193 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2197 test_path = g_strdup_printf ("/gsubprocess/communicate/cancelled%s", flags_vectors[i].subtest);
2198 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2199 test_communicate_cancelled);
2202 test_path = g_strdup_printf ("/gsubprocess/communicate/async%s", flags_vectors[i].subtest);
2203 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2204 test_communicate_async);
2207 test_path = g_strdup_printf ("/gsubprocess/communicate/async/cancelled%s", flags_vectors[i].subtest);
2208 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2209 test_communicate_cancelled_async);
2212 test_path = g_strdup_printf ("/gsubprocess/communicate/utf8%s", flags_vectors[i].subtest);
2213 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2214 test_communicate_utf8);
2217 test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/cancelled%s", flags_vectors[i].subtest);
2218 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2219 test_communicate_utf8_cancelled);
2222 test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/async%s", flags_vectors[i].subtest);
2223 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2224 test_communicate_utf8_async);
2227 test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/async/cancelled%s", flags_vectors[i].subtest);
2228 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2229 test_communicate_utf8_cancelled_async);
2233 g_test_add_func ("/gsubprocess/communicate/utf8/async/invalid", test_communicate_utf8_async_invalid);
2234 g_test_add_func ("/gsubprocess/communicate/utf8/invalid", test_communicate_utf8_invalid);
2235 g_test_add_func ("/gsubprocess/communicate/nothing", test_communicate_nothing);
2236 g_test_add_func ("/gsubprocess/terminate", test_terminate);
2237 g_test_add_func ("/gsubprocess/env", test_env);
2238 g_test_add_func ("/gsubprocess/env/inherit", test_env_inherit);
2239 g_test_add_func ("/gsubprocess/cwd", test_cwd);
2241 g_test_add_func ("/gsubprocess/launcher-close", test_subprocess_launcher_close);
2242 g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file);
2243 g_test_add_func ("/gsubprocess/stdout-fd", test_stdout_fd);
2244 g_test_add_func ("/gsubprocess/child-setup", test_child_setup);
2245 g_test_add_func ("/gsubprocess/pass-fd/basic", test_pass_fd);
2246 g_test_add_func ("/gsubprocess/pass-fd/empty-child-setup", test_pass_fd_empty_child_setup);
2247 g_test_add_func ("/gsubprocess/pass-fd/inherit-fds", test_pass_fd_inherit_fds);
2248 g_test_add_func ("/gsubprocess/fd-conflation/basic", test_fd_conflation);
2249 g_test_add_func ("/gsubprocess/fd-conflation/empty-child-setup", test_fd_conflation_empty_child_setup);
2250 g_test_add_func ("/gsubprocess/fd-conflation/inherit-fds", test_fd_conflation_inherit_fds);
2251 g_test_add_func ("/gsubprocess/fd-conflation/child-err-report-fd", test_fd_conflation_child_err_report_fd);
2252 g_test_add_func ("/gsubprocess/exit-status/trapped", test_exit_status_trapped);
2254 g_test_add_func ("/gsubprocess/launcher-environment", test_launcher_environment);
2256 return g_test_run ();