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