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