• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <gio/gio.h>
2 #include <string.h>
3 
4 #ifdef G_OS_UNIX
5 #include <sys/wait.h>
6 #include <glib-unix.h>
7 #include <gio/gunixinputstream.h>
8 #include <gio/gfiledescriptorbased.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 #endif
12 
13 /* We write 2^1 + 2^2 ... + 2^10 or 2047 copies of "Hello World!\n"
14  * ultimately
15  */
16 #define TOTAL_HELLOS 2047
17 #define HELLO_WORLD "hello world!\n"
18 
19 #ifdef G_OS_WIN32
20 #define LINEEND "\r\n"
21 #define EXEEXT ".exe"
22 #define SPLICELEN (TOTAL_HELLOS * (strlen (HELLO_WORLD) + 1)) /* because \r */
23 #else
24 #define LINEEND "\n"
25 #define EXEEXT
26 #define SPLICELEN (TOTAL_HELLOS * strlen (HELLO_WORLD))
27 #endif
28 
29 static GPtrArray *
30 get_test_subprocess_args (const char *mode,
31                           ...) G_GNUC_NULL_TERMINATED;
32 
33 static GPtrArray *
get_test_subprocess_args(const char * mode,...)34 get_test_subprocess_args (const char *mode,
35                           ...)
36 {
37   GPtrArray *ret;
38   char *path;
39   const char *binname;
40   va_list args;
41   gpointer arg;
42 
43   ret = g_ptr_array_new_with_free_func (g_free);
44 
45 #ifdef G_OS_WIN32
46   binname = "gsubprocess-testprog.exe";
47 #else
48   binname = "gsubprocess-testprog";
49 #endif
50 
51   path = g_test_build_filename (G_TEST_BUILT, binname, NULL);
52   g_ptr_array_add (ret, path);
53   g_ptr_array_add (ret, g_strdup (mode));
54 
55   va_start (args, mode);
56   while ((arg = va_arg (args, gpointer)) != NULL)
57     g_ptr_array_add (ret, g_strdup (arg));
58   va_end (args);
59 
60   g_ptr_array_add (ret, NULL);
61   return ret;
62 }
63 
64 static void
test_noop(void)65 test_noop (void)
66 {
67   GError *local_error = NULL;
68   GError **error = &local_error;
69   GPtrArray *args;
70   GSubprocess *proc;
71 
72   args = get_test_subprocess_args ("noop", NULL);
73   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
74   g_ptr_array_free (args, TRUE);
75   g_assert_no_error (local_error);
76 
77   g_subprocess_wait_check (proc, NULL, error);
78   g_assert_no_error (local_error);
79   g_assert_true (g_subprocess_get_successful (proc));
80 
81   g_object_unref (proc);
82 }
83 
84 static void
check_ready(GObject * source,GAsyncResult * res,gpointer user_data)85 check_ready (GObject      *source,
86              GAsyncResult *res,
87              gpointer      user_data)
88 {
89   gboolean ret;
90   GError *error = NULL;
91 
92   ret = g_subprocess_wait_check_finish (G_SUBPROCESS (source),
93                                         res,
94                                         &error);
95   g_assert_true (ret);
96   g_assert_no_error (error);
97 
98   g_object_unref (source);
99 }
100 
101 static void
test_noop_all_to_null(void)102 test_noop_all_to_null (void)
103 {
104   GError *local_error = NULL;
105   GError **error = &local_error;
106   GPtrArray *args;
107   GSubprocess *proc;
108 
109   args = get_test_subprocess_args ("noop", NULL);
110   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
111                             G_SUBPROCESS_FLAGS_STDOUT_SILENCE | G_SUBPROCESS_FLAGS_STDERR_SILENCE,
112                             error);
113   g_ptr_array_free (args, TRUE);
114   g_assert_no_error (local_error);
115 
116   g_subprocess_wait_check_async (proc, NULL, check_ready, NULL);
117 }
118 
119 static void
test_noop_no_wait(void)120 test_noop_no_wait (void)
121 {
122   GError *local_error = NULL;
123   GError **error = &local_error;
124   GPtrArray *args;
125   GSubprocess *proc;
126 
127   args = get_test_subprocess_args ("noop", NULL);
128   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
129   g_ptr_array_free (args, TRUE);
130   g_assert_no_error (local_error);
131 
132   g_object_unref (proc);
133 }
134 
135 static void
test_noop_stdin_inherit(void)136 test_noop_stdin_inherit (void)
137 {
138   GError *local_error = NULL;
139   GError **error = &local_error;
140   GPtrArray *args;
141   GSubprocess *proc;
142 
143   args = get_test_subprocess_args ("noop", NULL);
144   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDIN_INHERIT, error);
145   g_ptr_array_free (args, TRUE);
146   g_assert_no_error (local_error);
147 
148   g_subprocess_wait_check (proc, NULL, error);
149   g_assert_no_error (local_error);
150 
151   g_object_unref (proc);
152 }
153 
154 #ifdef G_OS_UNIX
155 static void
test_search_path(void)156 test_search_path (void)
157 {
158   GError *local_error = NULL;
159   GError **error = &local_error;
160   GSubprocess *proc;
161 
162   proc = g_subprocess_new (G_SUBPROCESS_FLAGS_NONE, error, "true", NULL);
163   g_assert_no_error (local_error);
164 
165   g_subprocess_wait_check (proc, NULL, error);
166   g_assert_no_error (local_error);
167 
168   g_object_unref (proc);
169 }
170 #endif
171 
172 static void
test_exit1(void)173 test_exit1 (void)
174 {
175   GError *local_error = NULL;
176   GError **error = &local_error;
177   GPtrArray *args;
178   GSubprocess *proc;
179 
180   args = get_test_subprocess_args ("exit1", NULL);
181   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
182   g_ptr_array_free (args, TRUE);
183   g_assert_no_error (local_error);
184 
185   g_subprocess_wait_check (proc, NULL, error);
186   g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
187   g_clear_error (error);
188 
189   g_object_unref (proc);
190 }
191 
192 typedef struct {
193   GMainLoop    *loop;
194   GCancellable *cancellable;
195   gboolean      cb_called;
196 } TestExit1CancelData;
197 
198 static gboolean
test_exit1_cancel_idle_quit_cb(gpointer user_data)199 test_exit1_cancel_idle_quit_cb (gpointer user_data)
200 {
201   GMainLoop *loop = user_data;
202   g_main_loop_quit (loop);
203   return G_SOURCE_REMOVE;
204 }
205 
206 static void
test_exit1_cancel_wait_check_cb(GObject * source,GAsyncResult * result,gpointer user_data)207 test_exit1_cancel_wait_check_cb (GObject      *source,
208                                  GAsyncResult *result,
209                                  gpointer      user_data)
210 {
211   GSubprocess *subprocess = G_SUBPROCESS (source);
212   TestExit1CancelData *data = user_data;
213   gboolean ret;
214   GError *error = NULL;
215 
216   g_assert_false (data->cb_called);
217   data->cb_called = TRUE;
218 
219   ret = g_subprocess_wait_check_finish (subprocess, result, &error);
220   g_assert_false (ret);
221   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
222   g_clear_error (&error);
223 
224   g_idle_add (test_exit1_cancel_idle_quit_cb, data->loop);
225 }
226 
227 static void
test_exit1_cancel(void)228 test_exit1_cancel (void)
229 {
230   GError *local_error = NULL;
231   GError **error = &local_error;
232   GPtrArray *args;
233   GSubprocess *proc;
234   TestExit1CancelData data = { 0 };
235 
236   g_test_bug ("786456");
237 
238   args = get_test_subprocess_args ("exit1", NULL);
239   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
240   g_ptr_array_free (args, TRUE);
241   g_assert_no_error (local_error);
242 
243   data.loop = g_main_loop_new (NULL, FALSE);
244   data.cancellable = g_cancellable_new ();
245   g_subprocess_wait_check_async (proc, data.cancellable, test_exit1_cancel_wait_check_cb, &data);
246 
247   g_subprocess_wait_check (proc, NULL, error);
248   g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
249   g_clear_error (error);
250 
251   g_cancellable_cancel (data.cancellable);
252   g_main_loop_run (data.loop);
253 
254   g_object_unref (proc);
255   g_main_loop_unref (data.loop);
256   g_clear_object (&data.cancellable);
257 }
258 
259 static void
test_exit1_cancel_in_cb_wait_check_cb(GObject * source,GAsyncResult * result,gpointer user_data)260 test_exit1_cancel_in_cb_wait_check_cb (GObject      *source,
261                                        GAsyncResult *result,
262                                        gpointer      user_data)
263 {
264   GSubprocess *subprocess = G_SUBPROCESS (source);
265   TestExit1CancelData *data = user_data;
266   gboolean ret;
267   GError *error = NULL;
268 
269   g_assert_false (data->cb_called);
270   data->cb_called = TRUE;
271 
272   ret = g_subprocess_wait_check_finish (subprocess, result, &error);
273   g_assert_false (ret);
274   g_assert_error (error, G_SPAWN_EXIT_ERROR, 1);
275   g_clear_error (&error);
276 
277   g_cancellable_cancel (data->cancellable);
278 
279   g_idle_add (test_exit1_cancel_idle_quit_cb, data->loop);
280 }
281 
282 static void
test_exit1_cancel_in_cb(void)283 test_exit1_cancel_in_cb (void)
284 {
285   GError *local_error = NULL;
286   GError **error = &local_error;
287   GPtrArray *args;
288   GSubprocess *proc;
289   TestExit1CancelData data = { 0 };
290 
291   g_test_bug ("786456");
292 
293   args = get_test_subprocess_args ("exit1", NULL);
294   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
295   g_ptr_array_free (args, TRUE);
296   g_assert_no_error (local_error);
297 
298   data.loop = g_main_loop_new (NULL, FALSE);
299   data.cancellable = g_cancellable_new ();
300   g_subprocess_wait_check_async (proc, data.cancellable, test_exit1_cancel_in_cb_wait_check_cb, &data);
301 
302   g_subprocess_wait_check (proc, NULL, error);
303   g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
304   g_clear_error (error);
305 
306   g_main_loop_run (data.loop);
307 
308   g_object_unref (proc);
309   g_main_loop_unref (data.loop);
310   g_clear_object (&data.cancellable);
311 }
312 
313 static gchar *
splice_to_string(GInputStream * stream,GError ** error)314 splice_to_string (GInputStream   *stream,
315                   GError        **error)
316 {
317   GMemoryOutputStream *buffer = NULL;
318   char *ret = NULL;
319 
320   buffer = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
321   if (g_output_stream_splice ((GOutputStream*)buffer, stream, 0, NULL, error) < 0)
322     goto out;
323 
324   if (!g_output_stream_write ((GOutputStream*)buffer, "\0", 1, NULL, error))
325     goto out;
326 
327   if (!g_output_stream_close ((GOutputStream*)buffer, NULL, error))
328     goto out;
329 
330   ret = g_memory_output_stream_steal_data (buffer);
331  out:
332   g_clear_object (&buffer);
333   return ret;
334 }
335 
336 static void
test_echo1(void)337 test_echo1 (void)
338 {
339   GError *local_error = NULL;
340   GError **error = &local_error;
341   GSubprocess *proc;
342   GPtrArray *args;
343   GInputStream *stdout_stream;
344   gchar *result;
345 
346   args = get_test_subprocess_args ("echo", "hello", "world!", NULL);
347   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDOUT_PIPE, error);
348   g_ptr_array_free (args, TRUE);
349   g_assert_no_error (local_error);
350 
351   stdout_stream = g_subprocess_get_stdout_pipe (proc);
352 
353   result = splice_to_string (stdout_stream, error);
354   g_assert_no_error (local_error);
355 
356   g_assert_cmpstr (result, ==, "hello" LINEEND "world!" LINEEND);
357 
358   g_free (result);
359   g_object_unref (proc);
360 }
361 
362 #ifdef G_OS_UNIX
363 static void
test_echo_merged(void)364 test_echo_merged (void)
365 {
366   GError *local_error = NULL;
367   GError **error = &local_error;
368   GSubprocess *proc;
369   GPtrArray *args;
370   GInputStream *stdout_stream;
371   gchar *result;
372 
373   args = get_test_subprocess_args ("echo-stdout-and-stderr", "merge", "this", NULL);
374   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
375                             G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_MERGE,
376                             error);
377   g_ptr_array_free (args, TRUE);
378   g_assert_no_error (local_error);
379 
380   stdout_stream = g_subprocess_get_stdout_pipe (proc);
381   result = splice_to_string (stdout_stream, error);
382   g_assert_no_error (local_error);
383 
384   g_assert_cmpstr (result, ==, "merge\nmerge\nthis\nthis\n");
385 
386   g_free (result);
387   g_object_unref (proc);
388 }
389 #endif
390 
391 typedef struct {
392   guint events_pending;
393   GMainLoop *loop;
394 } TestCatData;
395 
396 static void
test_cat_on_input_splice_complete(GObject * object,GAsyncResult * result,gpointer user_data)397 test_cat_on_input_splice_complete (GObject      *object,
398                                    GAsyncResult *result,
399                                    gpointer      user_data)
400 {
401   TestCatData *data = user_data;
402   GError *error = NULL;
403 
404   (void)g_output_stream_splice_finish ((GOutputStream*)object, result, &error);
405   g_assert_no_error (error);
406 
407   data->events_pending--;
408   if (data->events_pending == 0)
409     g_main_loop_quit (data->loop);
410 }
411 
412 static void
test_cat_utf8(void)413 test_cat_utf8 (void)
414 {
415   GError *local_error = NULL;
416   GError **error = &local_error;
417   GSubprocess *proc;
418   GPtrArray *args;
419   GBytes *input_buf;
420   GBytes *output_buf;
421   GInputStream *input_buf_stream = NULL;
422   GOutputStream *output_buf_stream = NULL;
423   GOutputStream *stdin_stream = NULL;
424   GInputStream *stdout_stream = NULL;
425   TestCatData data;
426 
427   memset (&data, 0, sizeof (data));
428   data.loop = g_main_loop_new (NULL, TRUE);
429 
430   args = get_test_subprocess_args ("cat", NULL);
431   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
432                             G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
433                             error);
434   g_ptr_array_free (args, TRUE);
435   g_assert_no_error (local_error);
436 
437   stdin_stream = g_subprocess_get_stdin_pipe (proc);
438   stdout_stream = g_subprocess_get_stdout_pipe (proc);
439 
440   input_buf = g_bytes_new_static ("hello, world!", strlen ("hello, world!"));
441   input_buf_stream = g_memory_input_stream_new_from_bytes (input_buf);
442   g_bytes_unref (input_buf);
443 
444   output_buf_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
445 
446   g_output_stream_splice_async (stdin_stream, input_buf_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
447                                 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
448                                 &data);
449   data.events_pending++;
450   g_output_stream_splice_async (output_buf_stream, stdout_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
451                                 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
452                                 &data);
453   data.events_pending++;
454 
455   g_main_loop_run (data.loop);
456 
457   g_subprocess_wait_check (proc, NULL, error);
458   g_assert_no_error (local_error);
459 
460   output_buf = g_memory_output_stream_steal_as_bytes ((GMemoryOutputStream*)output_buf_stream);
461 
462   g_assert_cmpmem (g_bytes_get_data (output_buf, NULL),
463                    g_bytes_get_size (output_buf),
464                    "hello, world!", 13);
465 
466   g_bytes_unref (output_buf);
467   g_main_loop_unref (data.loop);
468   g_object_unref (input_buf_stream);
469   g_object_unref (output_buf_stream);
470   g_object_unref (proc);
471 }
472 
473 static gpointer
cancel_soon(gpointer user_data)474 cancel_soon (gpointer user_data)
475 {
476   GCancellable *cancellable = user_data;
477 
478   g_usleep (G_TIME_SPAN_SECOND);
479   g_cancellable_cancel (cancellable);
480   g_object_unref (cancellable);
481 
482   return NULL;
483 }
484 
485 static void
test_cat_eof(void)486 test_cat_eof (void)
487 {
488   GCancellable *cancellable;
489   GError *error = NULL;
490   GSubprocess *cat;
491   gboolean result;
492   gchar buffer;
493   gssize s;
494 
495 #ifdef G_OS_WIN32
496   g_test_skip ("This test has not been ported to Win32");
497   return;
498 #endif
499 
500   /* Spawn 'cat' */
501   cat = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, "cat", NULL);
502   g_assert_no_error (error);
503   g_assert_nonnull (cat);
504 
505   /* Make sure that reading stdout blocks (until we cancel) */
506   cancellable = g_cancellable_new ();
507   g_thread_unref (g_thread_new ("cancel thread", cancel_soon, g_object_ref (cancellable)));
508   s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, cancellable, &error);
509   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
510   g_assert_cmpint (s, ==, -1);
511   g_object_unref (cancellable);
512   g_clear_error (&error);
513 
514   /* Close the stream (EOF on cat's stdin) */
515   result = g_output_stream_close (g_subprocess_get_stdin_pipe (cat), NULL, &error);
516   g_assert_no_error (error);
517   g_assert_true (result);
518 
519   /* Now check that reading cat's stdout gets us an EOF (since it quit) */
520   s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, NULL, &error);
521   g_assert_no_error (error);
522   g_assert_false (s);
523 
524   /* Check that the process has exited as a result of the EOF */
525   result = g_subprocess_wait (cat, NULL, &error);
526   g_assert_no_error (error);
527   g_assert_true (g_subprocess_get_if_exited (cat));
528   g_assert_cmpint (g_subprocess_get_exit_status (cat), ==, 0);
529   g_assert_true (result);
530 
531   g_object_unref (cat);
532 }
533 
534 typedef struct {
535   guint events_pending;
536   gboolean caught_error;
537   GError *error;
538   GMainLoop *loop;
539 
540   gint counter;
541   GOutputStream *first_stdin;
542 } TestMultiSpliceData;
543 
544 static void
on_one_multi_splice_done(GObject * obj,GAsyncResult * res,gpointer user_data)545 on_one_multi_splice_done (GObject       *obj,
546                           GAsyncResult  *res,
547                           gpointer       user_data)
548 {
549   TestMultiSpliceData *data = user_data;
550 
551   if (!data->caught_error)
552     {
553       if (g_output_stream_splice_finish ((GOutputStream*)obj, res, &data->error) < 0)
554         data->caught_error = TRUE;
555     }
556 
557   data->events_pending--;
558   if (data->events_pending == 0)
559     g_main_loop_quit (data->loop);
560 }
561 
562 static gboolean
on_idle_multisplice(gpointer user_data)563 on_idle_multisplice (gpointer     user_data)
564 {
565   TestMultiSpliceData *data = user_data;
566 
567   if (data->counter >= TOTAL_HELLOS || data->caught_error)
568     {
569       if (!g_output_stream_close (data->first_stdin, NULL, &data->error))
570         data->caught_error = TRUE;
571       data->events_pending--;
572       if (data->events_pending == 0)
573         {
574           g_main_loop_quit (data->loop);
575         }
576       return FALSE;
577     }
578   else
579     {
580       int i;
581       for (i = 0; i < data->counter; i++)
582         {
583           gsize bytes_written;
584           if (!g_output_stream_write_all (data->first_stdin, HELLO_WORLD,
585                                           strlen (HELLO_WORLD), &bytes_written,
586                                           NULL, &data->error))
587             {
588               data->caught_error = TRUE;
589               return FALSE;
590             }
591         }
592       data->counter *= 2;
593       return TRUE;
594     }
595 }
596 
597 static void
on_subprocess_exited(GObject * object,GAsyncResult * result,gpointer user_data)598 on_subprocess_exited (GObject         *object,
599                       GAsyncResult    *result,
600                       gpointer         user_data)
601 {
602   GSubprocess *subprocess = G_SUBPROCESS (object);
603   TestMultiSpliceData *data = user_data;
604   GError *error = NULL;
605 
606   if (!g_subprocess_wait_finish (subprocess, result, &error))
607     {
608       if (!data->caught_error)
609         {
610           data->caught_error = TRUE;
611           g_propagate_error (&data->error, error);
612         }
613     }
614   g_spawn_check_exit_status (g_subprocess_get_exit_status (subprocess), &error);
615   g_assert_no_error (error);
616   data->events_pending--;
617   if (data->events_pending == 0)
618     g_main_loop_quit (data->loop);
619 }
620 
621 static void
test_multi_1(void)622 test_multi_1 (void)
623 {
624   GError *local_error = NULL;
625   GError **error = &local_error;
626   GPtrArray *args;
627   GSubprocessLauncher *launcher;
628   GSubprocess *first;
629   GSubprocess *second;
630   GSubprocess *third;
631   GOutputStream *first_stdin;
632   GInputStream *first_stdout;
633   GOutputStream *second_stdin;
634   GInputStream *second_stdout;
635   GOutputStream *third_stdin;
636   GInputStream *third_stdout;
637   GOutputStream *membuf;
638   TestMultiSpliceData data;
639   int splice_flags = G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET;
640 
641   args = get_test_subprocess_args ("cat", NULL);
642   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE);
643   first = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
644   g_assert_no_error (local_error);
645   second = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
646   g_assert_no_error (local_error);
647   third = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
648   g_assert_no_error (local_error);
649 
650   g_ptr_array_free (args, TRUE);
651 
652   membuf = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
653 
654   first_stdin = g_subprocess_get_stdin_pipe (first);
655   first_stdout = g_subprocess_get_stdout_pipe (first);
656   second_stdin = g_subprocess_get_stdin_pipe (second);
657   second_stdout = g_subprocess_get_stdout_pipe (second);
658   third_stdin = g_subprocess_get_stdin_pipe (third);
659   third_stdout = g_subprocess_get_stdout_pipe (third);
660 
661   memset (&data, 0, sizeof (data));
662   data.loop = g_main_loop_new (NULL, TRUE);
663   data.counter = 1;
664   data.first_stdin = first_stdin;
665 
666   data.events_pending++;
667   g_output_stream_splice_async (second_stdin, first_stdout, splice_flags, G_PRIORITY_DEFAULT,
668                                 NULL, on_one_multi_splice_done, &data);
669   data.events_pending++;
670   g_output_stream_splice_async (third_stdin, second_stdout, splice_flags, G_PRIORITY_DEFAULT,
671                                 NULL, on_one_multi_splice_done, &data);
672   data.events_pending++;
673   g_output_stream_splice_async (membuf, third_stdout, splice_flags, G_PRIORITY_DEFAULT,
674                                 NULL, on_one_multi_splice_done, &data);
675 
676   data.events_pending++;
677   g_timeout_add (250, on_idle_multisplice, &data);
678 
679   data.events_pending++;
680   g_subprocess_wait_async (first, NULL, on_subprocess_exited, &data);
681   data.events_pending++;
682   g_subprocess_wait_async (second, NULL, on_subprocess_exited, &data);
683   data.events_pending++;
684   g_subprocess_wait_async (third, NULL, on_subprocess_exited, &data);
685 
686   g_main_loop_run (data.loop);
687 
688   g_assert_false (data.caught_error);
689   g_assert_no_error (data.error);
690 
691   g_assert_cmpint (g_memory_output_stream_get_data_size ((GMemoryOutputStream*)membuf), ==, SPLICELEN);
692 
693   g_main_loop_unref (data.loop);
694   g_object_unref (membuf);
695   g_object_unref (launcher);
696   g_object_unref (first);
697   g_object_unref (second);
698   g_object_unref (third);
699 }
700 
701 typedef struct {
702   GSubprocessFlags flags;
703   gboolean is_utf8;
704   gboolean running;
705   GError *error;
706 } TestAsyncCommunicateData;
707 
708 static void
on_communicate_complete(GObject * proc,GAsyncResult * result,gpointer user_data)709 on_communicate_complete (GObject               *proc,
710                          GAsyncResult          *result,
711                          gpointer               user_data)
712 {
713   TestAsyncCommunicateData *data = user_data;
714   GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
715   char *stdout_str = NULL, *stderr_str = NULL;
716   const guint8 *stdout_data;
717   gsize stdout_len;
718 
719   data->running = FALSE;
720   if (data->is_utf8)
721     (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
722                                                  &stdout_str, &stderr_str, &data->error);
723   else
724     (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
725                                             &stdout_bytes, &stderr_bytes, &data->error);
726   if (data->error)
727       return;
728 
729   if (data->flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
730     {
731       if (data->is_utf8)
732         {
733           stdout_data = (guint8*)stdout_str;
734           stdout_len = strlen (stdout_str);
735         }
736       else
737         stdout_data = g_bytes_get_data (stdout_bytes, &stdout_len);
738 
739       g_assert_cmpmem (stdout_data, stdout_len, "# hello world" LINEEND, 13 + strlen (LINEEND));
740     }
741   else
742     {
743       g_assert_null (stdout_str);
744       g_assert_null (stdout_bytes);
745     }
746 
747   if (data->flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
748     {
749       if (data->is_utf8)
750         g_assert_nonnull (stderr_str);
751       else
752         g_assert_nonnull (stderr_bytes);
753     }
754   else
755     {
756       g_assert_null (stderr_str);
757       g_assert_null (stderr_bytes);
758     }
759 
760   g_clear_pointer (&stdout_bytes, g_bytes_unref);
761   g_clear_pointer (&stderr_bytes, g_bytes_unref);
762   g_free (stdout_str);
763   g_free (stderr_str);
764 }
765 
766 /* Test g_subprocess_communicate_async() works correctly with a variety of flags,
767  * as passed in via @test_data. */
768 static void
test_communicate_async(gconstpointer test_data)769 test_communicate_async (gconstpointer test_data)
770 {
771   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
772   GError *error = NULL;
773   GPtrArray *args;
774   TestAsyncCommunicateData data = { flags, 0, };
775   GSubprocess *proc;
776   GCancellable *cancellable = NULL;
777   GBytes *input;
778   const char *hellostring;
779 
780   args = get_test_subprocess_args ("cat", NULL);
781   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
782                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
783                             &error);
784   g_assert_no_error (error);
785   g_ptr_array_free (args, TRUE);
786 
787   /* Include a leading hash and trailing newline so that if this gets onto the
788    * test’s stdout, it doesn’t mess up TAP output. */
789   hellostring = "# hello world\n";
790   input = g_bytes_new_static (hellostring, strlen (hellostring));
791 
792   g_subprocess_communicate_async (proc, input,
793                                   cancellable,
794                                   on_communicate_complete,
795                                   &data);
796 
797   data.running = TRUE;
798   while (data.running)
799     g_main_context_iteration (NULL, TRUE);
800 
801   g_assert_no_error (data.error);
802 
803   g_bytes_unref (input);
804   g_object_unref (proc);
805 }
806 
807 /* Test g_subprocess_communicate() works correctly with a variety of flags,
808  * as passed in via @test_data. */
809 static void
test_communicate(gconstpointer test_data)810 test_communicate (gconstpointer test_data)
811 {
812   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
813   GError *error = NULL;
814   GPtrArray *args;
815   GSubprocess *proc;
816   GCancellable *cancellable = NULL;
817   GBytes *input;
818   const gchar *hellostring;
819   GBytes *stdout_bytes, *stderr_bytes;
820   const gchar *stdout_data;
821   gsize stdout_len;
822 
823   args = get_test_subprocess_args ("cat", NULL);
824   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
825                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
826                             &error);
827   g_assert_no_error (error);
828   g_ptr_array_free (args, TRUE);
829 
830   /* Include a leading hash and trailing newline so that if this gets onto the
831    * test’s stdout, it doesn’t mess up TAP output. */
832   hellostring = "# hello world\n";
833   input = g_bytes_new_static (hellostring, strlen (hellostring));
834 
835   g_subprocess_communicate (proc, input, cancellable, &stdout_bytes, &stderr_bytes, &error);
836   g_assert_no_error (error);
837 
838   if (flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
839     {
840       stdout_data = g_bytes_get_data (stdout_bytes, &stdout_len);
841       g_assert_cmpmem (stdout_data, stdout_len, "# hello world" LINEEND, 13 + strlen (LINEEND));
842     }
843   else
844     g_assert_null (stdout_bytes);
845   if (flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
846     g_assert_nonnull (stderr_bytes);
847   else
848     g_assert_null (stderr_bytes);
849 
850   g_bytes_unref (input);
851   g_clear_pointer (&stdout_bytes, g_bytes_unref);
852   g_clear_pointer (&stderr_bytes, g_bytes_unref);
853   g_object_unref (proc);
854 }
855 
856 typedef struct {
857   GSubprocess  *proc;
858   GCancellable *cancellable;
859   gboolean is_utf8;
860   gboolean running;
861   GError *error;
862 } TestCancelledCommunicateData;
863 
864 static gboolean
on_test_communicate_cancelled_idle(gpointer user_data)865 on_test_communicate_cancelled_idle (gpointer user_data)
866 {
867   TestCancelledCommunicateData *data = user_data;
868   GBytes *input;
869   const gchar *hellostring;
870   GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
871   gchar *stdout_buf = NULL, *stderr_buf = NULL;
872 
873   /* Include a leading hash and trailing newline so that if this gets onto the
874    * test’s stdout, it doesn’t mess up TAP output. */
875   hellostring = "# hello world\n";
876   input = g_bytes_new_static (hellostring, strlen (hellostring));
877 
878   if (data->is_utf8)
879     g_subprocess_communicate_utf8 (data->proc, hellostring, data->cancellable,
880                                    &stdout_buf, &stderr_buf, &data->error);
881   else
882     g_subprocess_communicate (data->proc, input, data->cancellable, &stdout_bytes,
883                               &stderr_bytes, &data->error);
884 
885   data->running = FALSE;
886 
887   if (data->is_utf8)
888     {
889       g_assert_null (stdout_buf);
890       g_assert_null (stderr_buf);
891     }
892   else
893     {
894       g_assert_null (stdout_bytes);
895       g_assert_null (stderr_bytes);
896     }
897 
898   g_bytes_unref (input);
899 
900   return G_SOURCE_REMOVE;
901 }
902 
903 /* Test g_subprocess_communicate() can be cancelled correctly */
904 static void
test_communicate_cancelled(gconstpointer test_data)905 test_communicate_cancelled (gconstpointer test_data)
906 {
907   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
908   GPtrArray *args;
909   GSubprocess *proc;
910   GCancellable *cancellable = NULL;
911   GError *error = NULL;
912   TestCancelledCommunicateData data = { 0 };
913 
914   args = get_test_subprocess_args ("cat", NULL);
915   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
916                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
917                             &error);
918   g_assert_no_error (error);
919   g_ptr_array_free (args, TRUE);
920 
921   cancellable = g_cancellable_new ();
922 
923   data.proc = proc;
924   data.cancellable = cancellable;
925   data.error = error;
926 
927   g_cancellable_cancel (cancellable);
928   g_idle_add (on_test_communicate_cancelled_idle, &data);
929 
930   data.running = TRUE;
931   while (data.running)
932     g_main_context_iteration (NULL, TRUE);
933 
934   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
935   g_clear_error (&data.error);
936 
937   g_object_unref (cancellable);
938   g_object_unref (proc);
939 }
940 
941 static void
on_communicate_cancelled_complete(GObject * proc,GAsyncResult * result,gpointer user_data)942 on_communicate_cancelled_complete (GObject               *proc,
943                                    GAsyncResult          *result,
944                                    gpointer               user_data)
945 {
946   TestAsyncCommunicateData *data = user_data;
947   GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
948   char *stdout_str = NULL, *stderr_str = NULL;
949 
950   data->running = FALSE;
951   if (data->is_utf8)
952     (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
953                                                  &stdout_str, &stderr_str, &data->error);
954   else
955     (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
956                                             &stdout_bytes, &stderr_bytes, &data->error);
957 
958   if (data->is_utf8)
959     {
960       g_assert_null (stdout_str);
961       g_assert_null (stderr_str);
962     }
963   else
964     {
965       g_assert_null (stdout_bytes);
966       g_assert_null (stderr_bytes);
967     }
968 }
969 
970 /* Test g_subprocess_communicate_async() can be cancelled correctly,
971  * as passed in via @test_data. */
972 static void
test_communicate_cancelled_async(gconstpointer test_data)973 test_communicate_cancelled_async (gconstpointer test_data)
974 {
975   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
976   GError *error = NULL;
977   GPtrArray *args;
978   TestAsyncCommunicateData data = { 0 };
979   GSubprocess *proc;
980   GCancellable *cancellable = NULL;
981   GBytes *input;
982   const char *hellostring;
983 
984   args = get_test_subprocess_args ("cat", NULL);
985   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
986                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
987                             &error);
988   g_assert_no_error (error);
989   g_ptr_array_free (args, TRUE);
990 
991   /* Include a leading hash and trailing newline so that if this gets onto the
992    * test’s stdout, it doesn’t mess up TAP output. */
993   hellostring = "# hello world\n";
994   input = g_bytes_new_static (hellostring, strlen (hellostring));
995 
996   cancellable = g_cancellable_new ();
997 
998   g_subprocess_communicate_async (proc, input,
999                                   cancellable,
1000                                   on_communicate_cancelled_complete,
1001                                   &data);
1002 
1003   g_cancellable_cancel (cancellable);
1004 
1005   data.running = TRUE;
1006   while (data.running)
1007     g_main_context_iteration (NULL, TRUE);
1008 
1009   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1010   g_clear_error (&data.error);
1011 
1012   g_bytes_unref (input);
1013   g_object_unref (cancellable);
1014   g_object_unref (proc);
1015 }
1016 
1017 /* Test g_subprocess_communicate_utf8_async() works correctly with a variety of
1018  * flags, as passed in via @test_data. */
1019 static void
test_communicate_utf8_async(gconstpointer test_data)1020 test_communicate_utf8_async (gconstpointer test_data)
1021 {
1022   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1023   GError *error = NULL;
1024   GPtrArray *args;
1025   TestAsyncCommunicateData data = { flags, 0, };
1026   GSubprocess *proc;
1027   GCancellable *cancellable = NULL;
1028 
1029   args = get_test_subprocess_args ("cat", NULL);
1030   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1031                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1032                             &error);
1033   g_assert_no_error (error);
1034   g_ptr_array_free (args, TRUE);
1035 
1036   data.is_utf8 = TRUE;
1037   g_subprocess_communicate_utf8_async (proc, "# hello world\n",
1038                                        cancellable,
1039                                        on_communicate_complete,
1040                                        &data);
1041 
1042   data.running = TRUE;
1043   while (data.running)
1044     g_main_context_iteration (NULL, TRUE);
1045 
1046   g_assert_no_error (data.error);
1047 
1048   g_object_unref (proc);
1049 }
1050 
1051 /* Test g_subprocess_communicate_utf8_async() can be cancelled correctly. */
1052 static void
test_communicate_utf8_cancelled_async(gconstpointer test_data)1053 test_communicate_utf8_cancelled_async (gconstpointer test_data)
1054 {
1055   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1056   GError *error = NULL;
1057   GPtrArray *args;
1058   TestAsyncCommunicateData data = { flags, 0, };
1059   GSubprocess *proc;
1060   GCancellable *cancellable = NULL;
1061 
1062   args = get_test_subprocess_args ("cat", NULL);
1063   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1064                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1065                             &error);
1066   g_assert_no_error (error);
1067   g_ptr_array_free (args, TRUE);
1068 
1069   cancellable = g_cancellable_new ();
1070   data.is_utf8 = TRUE;
1071   g_subprocess_communicate_utf8_async (proc, "# hello world\n",
1072                                        cancellable,
1073                                        on_communicate_cancelled_complete,
1074                                        &data);
1075 
1076   g_cancellable_cancel (cancellable);
1077 
1078   data.running = TRUE;
1079   while (data.running)
1080     g_main_context_iteration (NULL, TRUE);
1081 
1082   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1083   g_clear_error (&data.error);
1084 
1085   g_object_unref (cancellable);
1086   g_object_unref (proc);
1087 }
1088 
1089 /* Test g_subprocess_communicate_utf8() works correctly with a variety of flags,
1090  * as passed in via @test_data. */
1091 static void
test_communicate_utf8(gconstpointer test_data)1092 test_communicate_utf8 (gconstpointer test_data)
1093 {
1094   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1095   GError *error = NULL;
1096   GPtrArray *args;
1097   GSubprocess *proc;
1098   GCancellable *cancellable = NULL;
1099   const gchar *stdin_buf;
1100   gchar *stdout_buf, *stderr_buf;
1101 
1102   args = get_test_subprocess_args ("cat", NULL);
1103   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1104                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1105                             &error);
1106   g_assert_no_error (error);
1107   g_ptr_array_free (args, TRUE);
1108 
1109   /* Include a leading hash and trailing newline so that if this gets onto the
1110    * test’s stdout, it doesn’t mess up TAP output. */
1111   stdin_buf = "# hello world\n";
1112 
1113   g_subprocess_communicate_utf8 (proc, stdin_buf, cancellable, &stdout_buf, &stderr_buf, &error);
1114   g_assert_no_error (error);
1115 
1116   if (flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
1117     g_assert_cmpstr (stdout_buf, ==, "# hello world" LINEEND);
1118   else
1119     g_assert_null (stdout_buf);
1120   if (flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
1121     g_assert_nonnull (stderr_buf);
1122   else     g_assert_null (stderr_buf);
1123 
1124   g_free (stdout_buf);
1125   g_free (stderr_buf);
1126   g_object_unref (proc);
1127 }
1128 
1129 /* Test g_subprocess_communicate_utf8() can be cancelled correctly */
1130 static void
test_communicate_utf8_cancelled(gconstpointer test_data)1131 test_communicate_utf8_cancelled (gconstpointer test_data)
1132 {
1133   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1134   GPtrArray *args;
1135   GSubprocess *proc;
1136   GCancellable *cancellable = NULL;
1137   GError *error = NULL;
1138   TestCancelledCommunicateData data = { 0 };
1139 
1140   args = get_test_subprocess_args ("cat", NULL);
1141   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1142                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1143                             &error);
1144   g_assert_no_error (error);
1145   g_ptr_array_free (args, TRUE);
1146 
1147   cancellable = g_cancellable_new ();
1148 
1149   data.proc = proc;
1150   data.cancellable = cancellable;
1151   data.error = error;
1152 
1153   g_cancellable_cancel (cancellable);
1154   g_idle_add (on_test_communicate_cancelled_idle, &data);
1155 
1156   data.is_utf8 = TRUE;
1157   data.running = TRUE;
1158   while (data.running)
1159     g_main_context_iteration (NULL, TRUE);
1160 
1161   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1162   g_clear_error (&data.error);
1163 
1164   g_object_unref (cancellable);
1165   g_object_unref (proc);
1166 }
1167 
1168 static void
test_communicate_nothing(void)1169 test_communicate_nothing (void)
1170 {
1171   GError *error = NULL;
1172   GPtrArray *args;
1173   GSubprocess *proc;
1174   GCancellable *cancellable = NULL;
1175   gchar *stdout_buf;
1176 
1177   args = get_test_subprocess_args ("cat", NULL);
1178   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1179                             G_SUBPROCESS_FLAGS_STDIN_PIPE
1180                             | G_SUBPROCESS_FLAGS_STDOUT_PIPE
1181                             | G_SUBPROCESS_FLAGS_STDERR_MERGE,
1182                             &error);
1183   g_assert_no_error (error);
1184   g_ptr_array_free (args, TRUE);
1185 
1186   g_subprocess_communicate_utf8 (proc, "", cancellable, &stdout_buf, NULL, &error);
1187   g_assert_no_error (error);
1188 
1189   g_assert_cmpstr (stdout_buf, ==, "");
1190 
1191   g_free (stdout_buf);
1192 
1193   g_object_unref (proc);
1194 }
1195 
1196 static void
test_communicate_utf8_async_invalid(void)1197 test_communicate_utf8_async_invalid (void)
1198 {
1199   GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE;
1200   GError *error = NULL;
1201   GPtrArray *args;
1202   TestAsyncCommunicateData data = { flags, 0, };
1203   GSubprocess *proc;
1204   GCancellable *cancellable = NULL;
1205 
1206   args = get_test_subprocess_args ("cat", NULL);
1207   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1208                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1209                             &error);
1210   g_assert_no_error (error);
1211   g_ptr_array_free (args, TRUE);
1212 
1213   data.is_utf8 = TRUE;
1214   g_subprocess_communicate_utf8_async (proc, "\xFF\xFF",
1215                                        cancellable,
1216                                        on_communicate_complete,
1217                                        &data);
1218 
1219   data.running = TRUE;
1220   while (data.running)
1221     g_main_context_iteration (NULL, TRUE);
1222 
1223   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_FAILED);
1224   g_error_free (data.error);
1225 
1226   g_object_unref (proc);
1227 }
1228 
1229 /* Test that invalid UTF-8 received using g_subprocess_communicate_utf8()
1230  * results in an error. */
1231 static void
test_communicate_utf8_invalid(void)1232 test_communicate_utf8_invalid (void)
1233 {
1234   GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE;
1235   GError *local_error = NULL;
1236   gboolean ret;
1237   GPtrArray *args;
1238   gchar *stdout_str = NULL, *stderr_str = NULL;
1239   GSubprocess *proc;
1240 
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,
1244                             &local_error);
1245   g_assert_no_error (local_error);
1246   g_ptr_array_free (args, TRUE);
1247 
1248   ret = g_subprocess_communicate_utf8 (proc, "\xFF\xFF", NULL,
1249                                        &stdout_str, &stderr_str, &local_error);
1250   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_FAILED);
1251   g_error_free (local_error);
1252   g_assert_false (ret);
1253 
1254   g_assert_null (stdout_str);
1255   g_assert_null (stderr_str);
1256 
1257   g_object_unref (proc);
1258 }
1259 
1260 static gboolean
send_terminate(gpointer user_data)1261 send_terminate (gpointer   user_data)
1262 {
1263   GSubprocess *proc = user_data;
1264 
1265   g_subprocess_force_exit (proc);
1266 
1267   return FALSE;
1268 }
1269 
1270 static void
on_request_quit_exited(GObject * object,GAsyncResult * result,gpointer user_data)1271 on_request_quit_exited (GObject        *object,
1272                         GAsyncResult   *result,
1273                         gpointer        user_data)
1274 {
1275   GSubprocess *subprocess = G_SUBPROCESS (object);
1276   GError *error = NULL;
1277 
1278   g_subprocess_wait_finish (subprocess, result, &error);
1279   g_assert_no_error (error);
1280 #ifdef G_OS_UNIX
1281   g_assert_true (g_subprocess_get_if_signaled (subprocess));
1282   g_assert_cmpint (g_subprocess_get_term_sig (subprocess), ==, 9);
1283 #endif
1284   g_spawn_check_exit_status (g_subprocess_get_status (subprocess), &error);
1285   g_assert_nonnull (error);
1286   g_clear_error (&error);
1287 
1288   g_main_loop_quit ((GMainLoop*)user_data);
1289 }
1290 
1291 static void
test_terminate(void)1292 test_terminate (void)
1293 {
1294   GError *local_error = NULL;
1295   GError **error = &local_error;
1296   GSubprocess *proc;
1297   GPtrArray *args;
1298   GMainLoop *loop;
1299   const gchar *id;
1300 
1301   args = get_test_subprocess_args ("sleep-forever", NULL);
1302   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
1303   g_ptr_array_free (args, TRUE);
1304   g_assert_no_error (local_error);
1305 
1306   id = g_subprocess_get_identifier (proc);
1307   g_assert_nonnull (id);
1308 
1309   loop = g_main_loop_new (NULL, TRUE);
1310 
1311   g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
1312 
1313   g_timeout_add_seconds (3, send_terminate, proc);
1314 
1315   g_main_loop_run (loop);
1316 
1317   g_main_loop_unref (loop);
1318   g_object_unref (proc);
1319 }
1320 
1321 #ifdef G_OS_UNIX
1322 static gboolean
send_signal(gpointer user_data)1323 send_signal (gpointer user_data)
1324 {
1325   GSubprocess *proc = user_data;
1326 
1327   g_subprocess_send_signal (proc, SIGKILL);
1328 
1329   return FALSE;
1330 }
1331 
1332 static void
test_signal(void)1333 test_signal (void)
1334 {
1335   GError *local_error = NULL;
1336   GError **error = &local_error;
1337   GSubprocess *proc;
1338   GPtrArray *args;
1339   GMainLoop *loop;
1340 
1341   args = get_test_subprocess_args ("sleep-forever", NULL);
1342   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
1343   g_ptr_array_free (args, TRUE);
1344   g_assert_no_error (local_error);
1345 
1346   loop = g_main_loop_new (NULL, TRUE);
1347 
1348   g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
1349 
1350   g_timeout_add_seconds (3, send_signal, proc);
1351 
1352   g_main_loop_run (loop);
1353 
1354   g_main_loop_unref (loop);
1355   g_object_unref (proc);
1356 }
1357 #endif
1358 
1359 static void
test_env(void)1360 test_env (void)
1361 {
1362   GError *local_error = NULL;
1363   GError **error = &local_error;
1364   GSubprocessLauncher *launcher;
1365   GSubprocess *proc;
1366   GPtrArray *args;
1367   GInputStream *stdout_stream;
1368   gchar *result;
1369   gchar *envp[] = { NULL, "ONE=1", "TWO=1", "THREE=3", "FOUR=1", NULL };
1370   gchar **split;
1371 
1372   envp[0] = g_strdup_printf ("PATH=%s", g_getenv ("PATH"));
1373   args = get_test_subprocess_args ("env", NULL);
1374   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1375   g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1376   g_subprocess_launcher_set_environ (launcher, envp);
1377   g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
1378   g_subprocess_launcher_setenv (launcher, "THREE", "1", FALSE);
1379   g_subprocess_launcher_unsetenv (launcher, "FOUR");
1380 
1381   g_assert_null (g_subprocess_launcher_getenv (launcher, "FOUR"));
1382 
1383   proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
1384   g_ptr_array_free (args, TRUE);
1385   g_assert_no_error (local_error);
1386   g_free (envp[0]);
1387 
1388   stdout_stream = g_subprocess_get_stdout_pipe (proc);
1389 
1390   result = splice_to_string (stdout_stream, error);
1391   split = g_strsplit (result, LINEEND, -1);
1392   g_assert_cmpstr (g_environ_getenv (split, "ONE"), ==, "1");
1393   g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
1394   g_assert_cmpstr (g_environ_getenv (split, "THREE"), ==, "3");
1395   g_assert_null (g_environ_getenv (split, "FOUR"));
1396 
1397   g_strfreev (split);
1398   g_free (result);
1399   g_object_unref (proc);
1400   g_object_unref (launcher);
1401 }
1402 
1403 /* Test that explicitly inheriting and modifying the parent process’
1404  * environment works. */
1405 static void
test_env_inherit(void)1406 test_env_inherit (void)
1407 {
1408   GError *local_error = NULL;
1409   GError **error = &local_error;
1410   GSubprocessLauncher *launcher;
1411   GSubprocess *proc;
1412   GPtrArray *args;
1413   GInputStream *stdout_stream;
1414   gchar *result;
1415   gchar **split;
1416 
1417   g_setenv ("TEST_ENV_INHERIT1", "1", TRUE);
1418   g_setenv ("TEST_ENV_INHERIT2", "2", TRUE);
1419 
1420   args = get_test_subprocess_args ("env", NULL);
1421   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1422   g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1423   g_subprocess_launcher_set_environ (launcher, NULL);
1424   g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
1425   g_subprocess_launcher_unsetenv (launcher, "TEST_ENV_INHERIT1");
1426 
1427   g_assert_null (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT1"));
1428   g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT2"), ==, "2");
1429   g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TWO"), ==, "2");
1430 
1431   proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
1432   g_ptr_array_free (args, TRUE);
1433   g_assert_no_error (local_error);
1434 
1435   stdout_stream = g_subprocess_get_stdout_pipe (proc);
1436 
1437   result = splice_to_string (stdout_stream, error);
1438   split = g_strsplit (result, LINEEND, -1);
1439   g_assert_null (g_environ_getenv (split, "TEST_ENV_INHERIT1"));
1440   g_assert_cmpstr (g_environ_getenv (split, "TEST_ENV_INHERIT2"), ==, "2");
1441   g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
1442 
1443   g_strfreev (split);
1444   g_free (result);
1445   g_object_unref (proc);
1446   g_object_unref (launcher);
1447 }
1448 
1449 static void
test_cwd(void)1450 test_cwd (void)
1451 {
1452   GError *local_error = NULL;
1453   GError **error = &local_error;
1454   GSubprocessLauncher *launcher;
1455   GSubprocess *proc;
1456   GPtrArray *args;
1457   GInputStream *stdout_stream;
1458   gchar *result;
1459   const char *basename;
1460   gchar *tmp_lineend;
1461   const gchar *tmp_lineend_basename;
1462 
1463   args = get_test_subprocess_args ("cwd", NULL);
1464   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1465   g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1466   g_subprocess_launcher_set_cwd (launcher, g_get_tmp_dir ());
1467   tmp_lineend = g_strdup_printf ("%s%s", g_get_tmp_dir (), LINEEND);
1468   tmp_lineend_basename = g_strrstr (tmp_lineend, G_DIR_SEPARATOR_S);
1469 
1470   proc = g_subprocess_launcher_spawnv (launcher, (const char * const *)args->pdata, error);
1471   g_ptr_array_free (args, TRUE);
1472   g_assert_no_error (local_error);
1473 
1474   stdout_stream = g_subprocess_get_stdout_pipe (proc);
1475 
1476   result = splice_to_string (stdout_stream, error);
1477 
1478   basename = g_strrstr (result, G_DIR_SEPARATOR_S);
1479   g_assert_nonnull (basename);
1480   g_assert_cmpstr (basename, ==, tmp_lineend_basename);
1481   g_free (tmp_lineend);
1482 
1483   g_free (result);
1484   g_object_unref (proc);
1485   g_object_unref (launcher);
1486 }
1487 #ifdef G_OS_UNIX
1488 
1489 static void
test_subprocess_launcher_close(void)1490 test_subprocess_launcher_close (void)
1491 {
1492   GError *local_error = NULL;
1493   GError **error = &local_error;
1494   GSubprocessLauncher *launcher;
1495   GSubprocess *proc;
1496   GPtrArray *args;
1497   int fd, fd2;
1498   gboolean is_open;
1499 
1500   /* Open two arbitrary FDs. One of them, @fd, will be transferred to the
1501    * launcher, and the other’s FD integer will be used as its target FD, giving
1502    * the mapping `fd → fd2` if a child process were to be spawned.
1503    *
1504    * The launcher will then be closed, which should close @fd but *not* @fd2,
1505    * as the value of @fd2 is only valid as an FD in a child process. (A child
1506    * process is not actually spawned in this test.)
1507    */
1508   fd = dup (0);
1509   fd2 = dup (0);
1510   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1511   g_subprocess_launcher_take_fd (launcher, fd, fd2);
1512 
1513   is_open = fcntl (fd, F_GETFD) != -1;
1514   g_assert_true (is_open);
1515   is_open = fcntl (fd2, F_GETFD) != -1;
1516   g_assert_true (is_open);
1517 
1518   g_subprocess_launcher_close (launcher);
1519 
1520   is_open = fcntl (fd, F_GETFD) != -1;
1521   g_assert_false (is_open);
1522   is_open = fcntl (fd2, F_GETFD) != -1;
1523   g_assert_true (is_open);
1524 
1525   /* Now test that actually trying to spawn the child gives %G_IO_ERROR_CLOSED,
1526    * as g_subprocess_launcher_close() has been called. */
1527   args = get_test_subprocess_args ("cat", NULL);
1528   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1529   g_ptr_array_free (args, TRUE);
1530   g_assert_null (proc);
1531   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_CLOSED);
1532   g_clear_error (error);
1533 
1534   close (fd2);
1535   g_object_unref (launcher);
1536 }
1537 
1538 static void
test_stdout_file(void)1539 test_stdout_file (void)
1540 {
1541   GError *local_error = NULL;
1542   GError **error = &local_error;
1543   GSubprocessLauncher *launcher;
1544   GSubprocess *proc;
1545   GPtrArray *args;
1546   GFile *tmpfile;
1547   GFileIOStream *iostream;
1548   GOutputStream *stdin_stream;
1549   const char *test_data = "this is some test data\n";
1550   char *tmp_contents;
1551   char *tmp_file_path;
1552 
1553   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1554   g_assert_no_error (local_error);
1555   g_clear_object (&iostream);
1556 
1557   tmp_file_path = g_file_get_path (tmpfile);
1558 
1559   args = get_test_subprocess_args ("cat", NULL);
1560   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1561   g_subprocess_launcher_set_stdout_file_path (launcher, tmp_file_path);
1562   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1563   g_ptr_array_free (args, TRUE);
1564   g_assert_no_error (local_error);
1565 
1566   stdin_stream = g_subprocess_get_stdin_pipe (proc);
1567 
1568   g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1569   g_assert_no_error (local_error);
1570 
1571   g_output_stream_close (stdin_stream, NULL, error);
1572   g_assert_no_error (local_error);
1573 
1574   g_subprocess_wait_check (proc, NULL, error);
1575 
1576   g_object_unref (launcher);
1577   g_object_unref (proc);
1578 
1579   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1580   g_assert_no_error (local_error);
1581 
1582   g_assert_cmpstr (test_data, ==, tmp_contents);
1583   g_free (tmp_contents);
1584 
1585   (void) g_file_delete (tmpfile, NULL, NULL);
1586   g_object_unref (tmpfile);
1587   g_free (tmp_file_path);
1588 }
1589 
1590 static void
test_stdout_fd(void)1591 test_stdout_fd (void)
1592 {
1593   GError *local_error = NULL;
1594   GError **error = &local_error;
1595   GSubprocessLauncher *launcher;
1596   GSubprocess *proc;
1597   GPtrArray *args;
1598   GFile *tmpfile;
1599   GFileIOStream *iostream;
1600   GFileDescriptorBased *descriptor_stream;
1601   GOutputStream *stdin_stream;
1602   const char *test_data = "this is some test data\n";
1603   char *tmp_contents;
1604 
1605   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1606   g_assert_no_error (local_error);
1607 
1608   args = get_test_subprocess_args ("cat", NULL);
1609   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1610   descriptor_stream = G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream)));
1611   g_subprocess_launcher_take_stdout_fd (launcher, dup (g_file_descriptor_based_get_fd (descriptor_stream)));
1612   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1613   g_ptr_array_free (args, TRUE);
1614   g_assert_no_error (local_error);
1615 
1616   g_clear_object (&iostream);
1617 
1618   stdin_stream = g_subprocess_get_stdin_pipe (proc);
1619 
1620   g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1621   g_assert_no_error (local_error);
1622 
1623   g_output_stream_close (stdin_stream, NULL, error);
1624   g_assert_no_error (local_error);
1625 
1626   g_subprocess_wait_check (proc, NULL, error);
1627 
1628   g_object_unref (launcher);
1629   g_object_unref (proc);
1630 
1631   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1632   g_assert_no_error (local_error);
1633 
1634   g_assert_cmpstr (test_data, ==, tmp_contents);
1635   g_free (tmp_contents);
1636 
1637   (void) g_file_delete (tmpfile, NULL, NULL);
1638   g_object_unref (tmpfile);
1639 }
1640 
1641 static void
child_setup(gpointer user_data)1642 child_setup (gpointer user_data)
1643 {
1644   dup2 (GPOINTER_TO_INT (user_data), 1);
1645 }
1646 
1647 static void
test_child_setup(void)1648 test_child_setup (void)
1649 {
1650   GError *local_error = NULL;
1651   GError **error = &local_error;
1652   GSubprocessLauncher *launcher;
1653   GSubprocess *proc;
1654   GPtrArray *args;
1655   GFile *tmpfile;
1656   GFileIOStream *iostream;
1657   GOutputStream *stdin_stream;
1658   const char *test_data = "this is some test data\n";
1659   char *tmp_contents;
1660   int fd;
1661 
1662   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1663   g_assert_no_error (local_error);
1664 
1665   fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream))));
1666 
1667   args = get_test_subprocess_args ("cat", NULL);
1668   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1669   g_subprocess_launcher_set_child_setup (launcher, child_setup, GINT_TO_POINTER (fd), NULL);
1670   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1671   g_ptr_array_free (args, TRUE);
1672   g_assert_no_error (local_error);
1673 
1674   g_clear_object (&iostream);
1675 
1676   stdin_stream = g_subprocess_get_stdin_pipe (proc);
1677 
1678   g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1679   g_assert_no_error (local_error);
1680 
1681   g_output_stream_close (stdin_stream, NULL, error);
1682   g_assert_no_error (local_error);
1683 
1684   g_subprocess_wait_check (proc, NULL, error);
1685 
1686   g_object_unref (launcher);
1687   g_object_unref (proc);
1688 
1689   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1690   g_assert_no_error (local_error);
1691 
1692   g_assert_cmpstr (test_data, ==, tmp_contents);
1693   g_free (tmp_contents);
1694 
1695   (void) g_file_delete (tmpfile, NULL, NULL);
1696   g_object_unref (tmpfile);
1697 }
1698 
1699 static void
test_pass_fd(void)1700 test_pass_fd (void)
1701 {
1702   GError *local_error = NULL;
1703   GError **error = &local_error;
1704   GInputStream *child_input;
1705   GDataInputStream *child_datainput;
1706   GSubprocessLauncher *launcher;
1707   GSubprocess *proc;
1708   GPtrArray *args;
1709   int basic_pipefds[2];
1710   int needdup_pipefds[2];
1711   char *buf;
1712   gsize len;
1713   char *basic_fd_str;
1714   char *needdup_fd_str;
1715 
1716   g_unix_open_pipe (basic_pipefds, FD_CLOEXEC, error);
1717   g_assert_no_error (local_error);
1718   g_unix_open_pipe (needdup_pipefds, FD_CLOEXEC, error);
1719   g_assert_no_error (local_error);
1720 
1721   basic_fd_str = g_strdup_printf ("%d", basic_pipefds[1]);
1722   needdup_fd_str = g_strdup_printf ("%d", needdup_pipefds[1] + 1);
1723 
1724   args = get_test_subprocess_args ("write-to-fds", basic_fd_str, needdup_fd_str, NULL);
1725   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1726   g_subprocess_launcher_take_fd (launcher, basic_pipefds[1], basic_pipefds[1]);
1727   g_subprocess_launcher_take_fd (launcher, needdup_pipefds[1], needdup_pipefds[1] + 1);
1728   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1729   g_ptr_array_free (args, TRUE);
1730   g_assert_no_error (local_error);
1731 
1732   g_free (basic_fd_str);
1733   g_free (needdup_fd_str);
1734 
1735   child_input = g_unix_input_stream_new (basic_pipefds[0], TRUE);
1736   child_datainput = g_data_input_stream_new (child_input);
1737   buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1738   g_assert_no_error (local_error);
1739   g_assert_cmpstr (buf, ==, "hello world");
1740   g_object_unref (child_datainput);
1741   g_object_unref (child_input);
1742   g_free (buf);
1743 
1744   child_input = g_unix_input_stream_new (needdup_pipefds[0], TRUE);
1745   child_datainput = g_data_input_stream_new (child_input);
1746   buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1747   g_assert_no_error (local_error);
1748   g_assert_cmpstr (buf, ==, "hello world");
1749   g_free (buf);
1750   g_object_unref (child_datainput);
1751   g_object_unref (child_input);
1752 
1753   g_object_unref (launcher);
1754   g_object_unref (proc);
1755 }
1756 
1757 #endif
1758 
1759 static void
test_launcher_environment(void)1760 test_launcher_environment (void)
1761 {
1762   GSubprocessLauncher *launcher;
1763   GError *error = NULL;
1764   GSubprocess *proc;
1765   GPtrArray *args;
1766   gchar *out;
1767 
1768   g_setenv ("A", "B", TRUE);
1769   g_setenv ("C", "D", TRUE);
1770 
1771   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1772 
1773   /* unset a variable */
1774   g_subprocess_launcher_unsetenv (launcher, "A");
1775 
1776   /* and set a different one */
1777   g_subprocess_launcher_setenv (launcher, "E", "F", TRUE);
1778 
1779   args = get_test_subprocess_args ("printenv", "A", "C", "E", NULL);
1780   proc = g_subprocess_launcher_spawnv (launcher, (const gchar **) args->pdata, &error);
1781   g_assert_no_error (error);
1782   g_assert_nonnull (proc);
1783 
1784   g_subprocess_communicate_utf8 (proc, NULL, NULL, &out, NULL, &error);
1785   g_assert_no_error (error);
1786 
1787   g_assert_cmpstr (out, ==, "C=D" LINEEND "E=F" LINEEND);
1788   g_free (out);
1789 
1790   g_object_unref (proc);
1791   g_object_unref (launcher);
1792   g_ptr_array_unref (args);
1793 }
1794 
1795 int
main(int argc,char ** argv)1796 main (int argc, char **argv)
1797 {
1798   const struct
1799     {
1800       const gchar *subtest;
1801       GSubprocessFlags flags;
1802     }
1803   flags_vectors[] =
1804     {
1805       { "", G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_MERGE },
1806       { "/no-pipes", G_SUBPROCESS_FLAGS_NONE },
1807       { "/separate-stderr", G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE },
1808       { "/stdout-only", G_SUBPROCESS_FLAGS_STDOUT_PIPE },
1809       { "/stderr-only", G_SUBPROCESS_FLAGS_STDERR_PIPE },
1810       { "/stdout-silence", G_SUBPROCESS_FLAGS_STDOUT_SILENCE },
1811     };
1812   gsize i;
1813 
1814   g_test_init (&argc, &argv, NULL);
1815   g_test_bug_base ("https://bugzilla.gnome.org/");
1816 
1817   g_test_add_func ("/gsubprocess/noop", test_noop);
1818   g_test_add_func ("/gsubprocess/noop-all-to-null", test_noop_all_to_null);
1819   g_test_add_func ("/gsubprocess/noop-no-wait", test_noop_no_wait);
1820   g_test_add_func ("/gsubprocess/noop-stdin-inherit", test_noop_stdin_inherit);
1821 #ifdef G_OS_UNIX
1822   g_test_add_func ("/gsubprocess/search-path", test_search_path);
1823   g_test_add_func ("/gsubprocess/signal", test_signal);
1824 #endif
1825   g_test_add_func ("/gsubprocess/exit1", test_exit1);
1826   g_test_add_func ("/gsubprocess/exit1/cancel", test_exit1_cancel);
1827   g_test_add_func ("/gsubprocess/exit1/cancel_in_cb", test_exit1_cancel_in_cb);
1828   g_test_add_func ("/gsubprocess/echo1", test_echo1);
1829 #ifdef G_OS_UNIX
1830   g_test_add_func ("/gsubprocess/echo-merged", test_echo_merged);
1831 #endif
1832   g_test_add_func ("/gsubprocess/cat-utf8", test_cat_utf8);
1833   g_test_add_func ("/gsubprocess/cat-eof", test_cat_eof);
1834   g_test_add_func ("/gsubprocess/multi1", test_multi_1);
1835 
1836   /* Add various tests for g_subprocess_communicate() with different flags. */
1837   for (i = 0; i < G_N_ELEMENTS (flags_vectors); i++)
1838     {
1839       gchar *test_path = NULL;
1840 
1841       test_path = g_strdup_printf ("/gsubprocess/communicate%s", flags_vectors[i].subtest);
1842       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1843                             test_communicate);
1844       g_free (test_path);
1845 
1846       test_path = g_strdup_printf ("/gsubprocess/communicate/cancelled%s", flags_vectors[i].subtest);
1847       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1848                             test_communicate_cancelled);
1849       g_free (test_path);
1850 
1851       test_path = g_strdup_printf ("/gsubprocess/communicate/async%s", flags_vectors[i].subtest);
1852       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1853                             test_communicate_async);
1854       g_free (test_path);
1855 
1856       test_path = g_strdup_printf ("/gsubprocess/communicate/async/cancelled%s", flags_vectors[i].subtest);
1857       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1858                             test_communicate_cancelled_async);
1859       g_free (test_path);
1860 
1861       test_path = g_strdup_printf ("/gsubprocess/communicate/utf8%s", flags_vectors[i].subtest);
1862       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1863                             test_communicate_utf8);
1864       g_free (test_path);
1865 
1866       test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/cancelled%s", flags_vectors[i].subtest);
1867       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1868                             test_communicate_utf8_cancelled);
1869       g_free (test_path);
1870 
1871       test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/async%s", flags_vectors[i].subtest);
1872       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1873                             test_communicate_utf8_async);
1874       g_free (test_path);
1875 
1876       test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/async/cancelled%s", flags_vectors[i].subtest);
1877       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1878                             test_communicate_utf8_cancelled_async);
1879       g_free (test_path);
1880     }
1881 
1882   g_test_add_func ("/gsubprocess/communicate/utf8/async/invalid", test_communicate_utf8_async_invalid);
1883   g_test_add_func ("/gsubprocess/communicate/utf8/invalid", test_communicate_utf8_invalid);
1884   g_test_add_func ("/gsubprocess/communicate/nothing", test_communicate_nothing);
1885   g_test_add_func ("/gsubprocess/terminate", test_terminate);
1886   g_test_add_func ("/gsubprocess/env", test_env);
1887   g_test_add_func ("/gsubprocess/env/inherit", test_env_inherit);
1888   g_test_add_func ("/gsubprocess/cwd", test_cwd);
1889 #ifdef G_OS_UNIX
1890   g_test_add_func ("/gsubprocess/launcher-close", test_subprocess_launcher_close);
1891   g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file);
1892   g_test_add_func ("/gsubprocess/stdout-fd", test_stdout_fd);
1893   g_test_add_func ("/gsubprocess/child-setup", test_child_setup);
1894   g_test_add_func ("/gsubprocess/pass-fd", test_pass_fd);
1895 #endif
1896   g_test_add_func ("/gsubprocess/launcher-environment", test_launcher_environment);
1897 
1898   return g_test_run ();
1899 }
1900