gsubprocess: Fix error detection logic in tests
[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 static GPtrArray *
12 get_test_subprocess_args (const char *mode,
13                           ...) G_GNUC_NULL_TERMINATED;
14
15 static GPtrArray *
16 get_test_subprocess_args (const char *mode,
17                           ...)
18 {
19   GPtrArray *ret;
20   char *path;
21   const char *binname;
22   va_list args;
23   gpointer arg;
24
25   ret = g_ptr_array_new_with_free_func (g_free);
26
27 #ifdef G_OS_WIN32
28   binname = "gsubprocess-testprog.exe";
29 #else
30   binname = "gsubprocess-testprog";
31 #endif
32
33   path = g_test_build_filename (G_TEST_BUILT, binname, NULL);
34   g_ptr_array_add (ret, path);
35   g_ptr_array_add (ret, g_strdup (mode));
36
37   va_start (args, mode);
38   while ((arg = va_arg (args, gpointer)) != NULL)
39     g_ptr_array_add (ret, g_strdup (arg));
40   va_end (args);
41
42   g_ptr_array_add (ret, NULL);
43   return ret;
44 }
45
46 static void
47 test_noop (void)
48 {
49   GError *local_error = NULL;
50   GError **error = &local_error;
51   GPtrArray *args;
52   GSubprocess *proc;
53
54   args = get_test_subprocess_args ("noop", NULL);
55   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
56   g_ptr_array_free (args, TRUE);
57   g_assert_no_error (local_error);
58
59   g_subprocess_wait_check (proc, NULL, error);
60   g_assert_no_error (local_error);
61
62   g_object_unref (proc);
63 }
64
65 static void
66 test_noop_all_to_null (void)
67 {
68   GError *local_error = NULL;
69   GError **error = &local_error;
70   GPtrArray *args;
71   GSubprocess *proc;
72
73   args = get_test_subprocess_args ("noop", NULL);
74   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
75                             G_SUBPROCESS_FLAGS_STDOUT_SILENCE | G_SUBPROCESS_FLAGS_STDERR_SILENCE,
76                             error);
77   g_ptr_array_free (args, TRUE);
78   g_assert_no_error (local_error);
79
80   g_subprocess_wait_check (proc, NULL, error);
81   g_assert_no_error (local_error);
82
83   g_object_unref (proc);
84 }
85
86 static void
87 test_noop_no_wait (void)
88 {
89   GError *local_error = NULL;
90   GError **error = &local_error;
91   GPtrArray *args;
92   GSubprocess *proc;
93
94   args = get_test_subprocess_args ("noop", NULL);
95   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
96   g_ptr_array_free (args, TRUE);
97   g_assert_no_error (local_error);
98
99   g_object_unref (proc);
100 }
101
102 static void
103 test_noop_stdin_inherit (void)
104 {
105   GError *local_error = NULL;
106   GError **error = &local_error;
107   GPtrArray *args;
108   GSubprocess *proc;
109
110   args = get_test_subprocess_args ("noop", NULL);
111   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDIN_INHERIT, error);
112   g_ptr_array_free (args, TRUE);
113   g_assert_no_error (local_error);
114
115   g_subprocess_wait_check (proc, NULL, error);
116   g_assert_no_error (local_error);
117
118   g_object_unref (proc);
119 }
120
121 #ifdef G_OS_UNIX
122 static void
123 test_search_path (void)
124 {
125   GError *local_error = NULL;
126   GError **error = &local_error;
127   GSubprocess *proc;
128
129   proc = g_subprocess_new (G_SUBPROCESS_FLAGS_NONE, error, "true", NULL);
130   g_assert_no_error (local_error);
131
132   g_subprocess_wait_check (proc, NULL, error);
133   g_assert_no_error (local_error);
134
135   g_object_unref (proc);
136 }
137 #endif
138
139 static void
140 test_exit1 (void)
141 {
142   GError *local_error = NULL;
143   GError **error = &local_error;
144   GPtrArray *args;
145   GSubprocess *proc;
146
147   args = get_test_subprocess_args ("exit1", NULL);
148   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
149   g_ptr_array_free (args, TRUE);
150   g_assert_no_error (local_error);
151
152   g_subprocess_wait_check (proc, NULL, error);
153   g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
154   g_clear_error (error);
155
156   g_object_unref (proc);
157 }
158
159 static gchar *
160 splice_to_string (GInputStream   *stream,
161                   GError        **error)
162 {
163   GMemoryOutputStream *buffer = NULL;
164   char *ret = NULL;
165
166   buffer = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
167   if (g_output_stream_splice ((GOutputStream*)buffer, stream, 0, NULL, error) < 0)
168     goto out;
169
170   if (!g_output_stream_write ((GOutputStream*)buffer, "\0", 1, NULL, error))
171     goto out;
172
173   if (!g_output_stream_close ((GOutputStream*)buffer, NULL, error))
174     goto out;
175
176   ret = g_memory_output_stream_steal_data (buffer);
177  out:
178   g_clear_object (&buffer);
179   return ret;
180 }
181
182 static void
183 test_echo1 (void)
184 {
185   GError *local_error = NULL;
186   GError **error = &local_error;
187   GSubprocess *proc;
188   GPtrArray *args;
189   GInputStream *stdout;
190   gchar *result;
191
192   args = get_test_subprocess_args ("echo", "hello", "world!", NULL);
193   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDOUT_PIPE, error);
194   g_ptr_array_free (args, TRUE);
195   g_assert_no_error (local_error);
196
197   stdout = g_subprocess_get_stdout_pipe (proc);
198
199   result = splice_to_string (stdout, error);
200   g_assert_no_error (local_error);
201
202   g_assert_cmpstr (result, ==, "hello\nworld!\n");
203
204   g_free (result);
205   g_object_unref (proc);
206 }
207
208 #ifdef G_OS_UNIX
209 static void
210 test_echo_merged (void)
211 {
212   GError *local_error = NULL;
213   GError **error = &local_error;
214   GSubprocess *proc;
215   GPtrArray *args;
216   GInputStream *stdout;
217   gchar *result;
218
219   args = get_test_subprocess_args ("echo-stdout-and-stderr", "merge", "this", NULL);
220   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
221                             G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_MERGE,
222                             error);
223   g_ptr_array_free (args, TRUE);
224   g_assert_no_error (local_error);
225
226   stdout = g_subprocess_get_stdout_pipe (proc);
227   result = splice_to_string (stdout, error);
228   g_assert_no_error (local_error);
229
230   g_assert_cmpstr (result, ==, "merge\nmerge\nthis\nthis\n");
231
232   g_free (result);
233   g_object_unref (proc);
234 }
235 #endif
236
237 typedef struct {
238   guint events_pending;
239   GMainLoop *loop;
240 } TestCatData;
241
242 static void
243 test_cat_on_input_splice_complete (GObject      *object,
244                                    GAsyncResult *result,
245                                    gpointer      user_data)
246 {
247   TestCatData *data = user_data;
248   GError *error = NULL;
249
250   (void)g_output_stream_splice_finish ((GOutputStream*)object, result, &error);
251   g_assert_no_error (error);
252
253   data->events_pending--;
254   if (data->events_pending == 0)
255     g_main_loop_quit (data->loop);
256 }
257
258 static void
259 test_cat_utf8 (void)
260 {
261   GError *local_error = NULL;
262   GError **error = &local_error;
263   GSubprocess *proc;
264   GPtrArray *args;
265   GBytes *input_buf;
266   GBytes *output_buf;
267   GInputStream *input_buf_stream = NULL;
268   GOutputStream *output_buf_stream = NULL;
269   GOutputStream *stdin_stream = NULL;
270   GInputStream *stdout_stream = NULL;
271   TestCatData data;
272
273   memset (&data, 0, sizeof (data));
274   data.loop = g_main_loop_new (NULL, TRUE);
275
276   args = get_test_subprocess_args ("cat", NULL);
277   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
278                             G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
279                             error);
280   g_ptr_array_free (args, TRUE);
281   g_assert_no_error (local_error);
282
283   stdin_stream = g_subprocess_get_stdin_pipe (proc);
284   stdout_stream = g_subprocess_get_stdout_pipe (proc);
285
286   input_buf = g_bytes_new_static ("hello, world!", strlen ("hello, world!"));
287   input_buf_stream = g_memory_input_stream_new_from_bytes (input_buf);
288   g_bytes_unref (input_buf);
289
290   output_buf_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
291
292   g_output_stream_splice_async (stdin_stream, input_buf_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
293                                 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
294                                 &data);
295   data.events_pending++;
296   g_output_stream_splice_async (output_buf_stream, stdout_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
297                                 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
298                                 &data);
299   data.events_pending++;
300
301   g_main_loop_run (data.loop);
302
303   g_subprocess_wait_check (proc, NULL, error);
304   g_assert_no_error (local_error);
305
306   output_buf = g_memory_output_stream_steal_as_bytes ((GMemoryOutputStream*)output_buf_stream);
307
308   g_assert_cmpint (g_bytes_get_size (output_buf), ==, 13);
309   g_assert_cmpint (memcmp (g_bytes_get_data (output_buf, NULL), "hello, world!", 13), ==, 0);
310
311   g_bytes_unref (output_buf);
312   g_main_loop_unref (data.loop);
313   g_object_unref (input_buf_stream);
314   g_object_unref (output_buf_stream);
315   g_object_unref (proc);
316 }
317
318 static gpointer
319 cancel_soon (gpointer user_data)
320 {
321   GCancellable *cancellable = user_data;
322
323   g_usleep (G_TIME_SPAN_SECOND);
324   g_cancellable_cancel (cancellable);
325   g_object_unref (cancellable);
326
327   return NULL;
328 }
329
330 static void
331 test_cat_eof (void)
332 {
333   GCancellable *cancellable;
334   GError *error = NULL;
335   GSubprocess *cat;
336   gboolean result;
337   gchar buffer;
338   gssize s;
339
340   /* Spawn 'cat' */
341   cat = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, "cat", NULL);
342   g_assert_no_error (error);
343   g_assert (cat);
344
345   /* Make sure that reading stdout blocks (until we cancel) */
346   cancellable = g_cancellable_new ();
347   g_thread_unref (g_thread_new ("cancel thread", cancel_soon, g_object_ref (cancellable)));
348   s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, cancellable, &error);
349   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
350   g_assert_cmpint (s, ==, -1);
351   g_object_unref (cancellable);
352   g_clear_error (&error);
353
354   /* Close the stream (EOF on cat's stdin) */
355   result = g_output_stream_close (g_subprocess_get_stdin_pipe (cat), NULL, &error);
356   g_assert_no_error (error);
357   g_assert (result);
358
359   /* Now check that reading cat's stdout gets us an EOF (since it quit) */
360   s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, NULL, &error);
361   g_assert_no_error (error);
362   g_assert (!s);
363
364   /* Check that the process has exited as a result of the EOF */
365   result = g_subprocess_wait (cat, NULL, &error);
366   g_assert_no_error (error);
367   g_assert (g_subprocess_get_if_exited (cat));
368   g_assert_cmpint (g_subprocess_get_exit_status (cat), ==, 0);
369   g_assert (result);
370
371   g_object_unref (cat);
372 }
373
374 typedef struct {
375   guint events_pending;
376   gboolean caught_error;
377   GError *error;
378   GMainLoop *loop;
379
380   gint counter;
381   GOutputStream *first_stdin;
382 } TestMultiSpliceData;
383
384 static void
385 on_one_multi_splice_done (GObject       *obj,
386                           GAsyncResult  *res,
387                           gpointer       user_data)
388 {
389   TestMultiSpliceData *data = user_data;
390
391   if (!data->caught_error)
392     {
393       if (g_output_stream_splice_finish ((GOutputStream*)obj, res, &data->error) < 0)
394         data->caught_error = TRUE;
395     }
396
397   data->events_pending--;
398   if (data->events_pending == 0)
399     g_main_loop_quit (data->loop);
400 }
401
402 static gboolean
403 on_idle_multisplice (gpointer     user_data)
404 {
405   TestMultiSpliceData *data = user_data;
406
407   /* We write 2^1 + 2^2 ... + 2^10 or 2047 copies of "Hello World!\n"
408    * ultimately
409    */
410   if (data->counter >= 2047 || data->caught_error)
411     {
412       if (!g_output_stream_close (data->first_stdin, NULL, &data->error))
413         data->caught_error = TRUE;
414       data->events_pending--;
415       if (data->events_pending == 0)
416         {
417           g_main_loop_quit (data->loop);
418         }
419       return FALSE;
420     }
421   else
422     {
423       int i;
424       for (i = 0; i < data->counter; i++)
425         {
426           gsize bytes_written;
427           if (!g_output_stream_write_all (data->first_stdin, "hello world!\n",
428                                           strlen ("hello world!\n"), &bytes_written,
429                                           NULL, &data->error))
430             {
431               data->caught_error = TRUE;
432               return FALSE;
433             }
434         }
435       data->counter *= 2;
436       return TRUE;
437     }
438 }
439
440 static void
441 on_subprocess_exited (GObject         *object,
442                       GAsyncResult    *result,
443                       gpointer         user_data)
444 {
445   GSubprocess *subprocess = G_SUBPROCESS (object);
446   TestMultiSpliceData *data = user_data;
447   GError *error = NULL;
448
449   if (!g_subprocess_wait_finish (subprocess, result, &error))
450     {
451       if (!data->caught_error)
452         {
453           data->caught_error = TRUE;
454           g_propagate_error (&data->error, error);
455         }
456     }
457   g_spawn_check_exit_status (g_subprocess_get_exit_status (subprocess), &error);
458   g_assert_no_error (error);
459   data->events_pending--;
460   if (data->events_pending == 0)
461     g_main_loop_quit (data->loop);
462 }
463
464 static void
465 test_multi_1 (void)
466 {
467   GError *local_error = NULL;
468   GError **error = &local_error;
469   GPtrArray *args;
470   GSubprocessLauncher *launcher;
471   GSubprocess *first;
472   GSubprocess *second;
473   GSubprocess *third;
474   GOutputStream *first_stdin;
475   GInputStream *first_stdout;
476   GOutputStream *second_stdin;
477   GInputStream *second_stdout;
478   GOutputStream *third_stdin;
479   GInputStream *third_stdout;
480   GOutputStream *membuf;
481   TestMultiSpliceData data;
482   int splice_flags = G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET;
483
484   args = get_test_subprocess_args ("cat", NULL);
485   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE);
486   first = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
487   g_assert_no_error (local_error);
488   second = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
489   g_assert_no_error (local_error);
490   third = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
491   g_assert_no_error (local_error);
492
493   g_ptr_array_free (args, TRUE);
494
495   membuf = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
496
497   first_stdin = g_subprocess_get_stdin_pipe (first);
498   first_stdout = g_subprocess_get_stdout_pipe (first);
499   second_stdin = g_subprocess_get_stdin_pipe (second);
500   second_stdout = g_subprocess_get_stdout_pipe (second);
501   third_stdin = g_subprocess_get_stdin_pipe (third);
502   third_stdout = g_subprocess_get_stdout_pipe (third);
503
504   memset (&data, 0, sizeof (data));
505   data.loop = g_main_loop_new (NULL, TRUE);
506   data.counter = 1;
507   data.first_stdin = first_stdin;
508
509   data.events_pending++;
510   g_output_stream_splice_async (second_stdin, first_stdout, splice_flags, G_PRIORITY_DEFAULT,
511                                 NULL, on_one_multi_splice_done, &data);
512   data.events_pending++;
513   g_output_stream_splice_async (third_stdin, second_stdout, splice_flags, G_PRIORITY_DEFAULT,
514                                 NULL, on_one_multi_splice_done, &data);
515   data.events_pending++;
516   g_output_stream_splice_async (membuf, third_stdout, splice_flags, G_PRIORITY_DEFAULT,
517                                 NULL, on_one_multi_splice_done, &data);
518
519   data.events_pending++;
520   g_timeout_add (250, on_idle_multisplice, &data);
521
522   data.events_pending++;
523   g_subprocess_wait_async (first, NULL, on_subprocess_exited, &data);
524   data.events_pending++;
525   g_subprocess_wait_async (second, NULL, on_subprocess_exited, &data);
526   data.events_pending++;
527   g_subprocess_wait_async (third, NULL, on_subprocess_exited, &data);
528
529   g_main_loop_run (data.loop);
530
531   g_assert (!data.caught_error);
532   g_assert_no_error (data.error);
533
534   g_assert_cmpint (g_memory_output_stream_get_data_size ((GMemoryOutputStream*)membuf), ==, 26611);
535
536   g_main_loop_unref (data.loop);
537   g_object_unref (membuf);
538   g_object_unref (launcher);
539   g_object_unref (first);
540   g_object_unref (second);
541   g_object_unref (third);
542 }
543
544 typedef struct {
545   gboolean is_utf8;
546   gboolean running;
547   GError *error;
548 } TestAsyncCommunicateData;
549
550 static void
551 on_communicate_complete (GObject               *proc,
552                          GAsyncResult          *result,
553                          gpointer               user_data)
554 {
555   TestAsyncCommunicateData *data = user_data;
556   GBytes *stdout = NULL;
557   char *stdout_str = NULL;
558   const guint8 *stdout_data;
559   gsize stdout_len;
560
561   data->running = FALSE;
562   if (data->is_utf8)
563     (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
564                                                  &stdout_str, NULL, &data->error);
565   else
566     (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
567                                             &stdout, NULL, &data->error);
568   if (data->error)
569       return;
570
571   if (!data->is_utf8)
572     {
573       stdout_data = g_bytes_get_data (stdout, &stdout_len);
574     }
575   else
576     {
577       stdout_data = (guint8*)stdout_str;
578       stdout_len = strlen (stdout_str);
579     }
580
581   g_assert_cmpint (stdout_len, ==, 11);
582   g_assert (memcmp (stdout_data, "hello world", 11) == 0);
583   if (stdout)
584     g_bytes_unref (stdout);
585   g_free (stdout_str);
586 }
587
588 static void
589 test_communicate (void)
590 {
591   GError *error = NULL;
592   GPtrArray *args;
593   TestAsyncCommunicateData data = { 0, };
594   GSubprocess *proc;
595   GCancellable *cancellable = NULL;
596   GBytes *input;
597   const char *hellostring;
598
599   args = get_test_subprocess_args ("cat", NULL);
600   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
601                             G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
602                             &error);
603   g_assert_no_error (error);
604   g_ptr_array_free (args, TRUE);
605
606   hellostring = "hello world";
607   input = g_bytes_new_static (hellostring, strlen (hellostring));
608
609   g_subprocess_communicate_async (proc, input,
610                                   cancellable,
611                                   on_communicate_complete, 
612                                   &data);
613   
614   data.running = TRUE;
615   while (data.running)
616     g_main_context_iteration (NULL, TRUE);
617
618   g_assert_no_error (data.error);
619
620   g_object_unref (proc);
621 }
622
623 static void
624 test_communicate_utf8 (void)
625 {
626   GError *error = NULL;
627   GPtrArray *args;
628   TestAsyncCommunicateData data = { 0, };
629   GSubprocess *proc;
630   GCancellable *cancellable = NULL;
631
632   args = get_test_subprocess_args ("cat", NULL);
633   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
634                             G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
635                             &error);
636   g_assert_no_error (error);
637   g_ptr_array_free (args, TRUE);
638
639   data.is_utf8 = TRUE;
640   g_subprocess_communicate_utf8_async (proc, "hello world",
641                                        cancellable,
642                                        on_communicate_complete, 
643                                        &data);
644   
645   data.running = TRUE;
646   while (data.running)
647     g_main_context_iteration (NULL, TRUE);
648
649   g_assert_no_error (data.error);
650
651   g_object_unref (proc);
652 }
653
654 static void
655 test_communicate_utf8_invalid (void)
656 {
657   GError *error = NULL;
658   GPtrArray *args;
659   TestAsyncCommunicateData data = { 0, };
660   GSubprocess *proc;
661   GCancellable *cancellable = NULL;
662
663   args = get_test_subprocess_args ("cat", NULL);
664   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
665                             G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
666                             &error);
667   g_assert_no_error (error);
668   g_ptr_array_free (args, TRUE);
669
670   data.is_utf8 = TRUE;
671   g_subprocess_communicate_utf8_async (proc, "\xFF\xFF",
672                                        cancellable,
673                                        on_communicate_complete, 
674                                        &data);
675   
676   data.running = TRUE;
677   while (data.running)
678     g_main_context_iteration (NULL, TRUE);
679
680   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_FAILED);
681   g_error_free (data.error);
682
683   g_object_unref (proc);
684 }
685
686 static gboolean
687 send_terminate (gpointer   user_data)
688 {
689   GSubprocess *proc = user_data;
690
691   g_subprocess_force_exit (proc);
692
693   return FALSE;
694 }
695
696 static void
697 on_request_quit_exited (GObject        *object,
698                         GAsyncResult   *result,
699                         gpointer        user_data)
700 {
701   GSubprocess *subprocess = G_SUBPROCESS (object);
702   GError *error = NULL;
703
704   g_subprocess_wait_finish (subprocess, result, &error);
705   g_assert_no_error (error);
706 #ifdef G_OS_UNIX
707   g_assert (g_subprocess_get_if_signaled (subprocess));
708   g_assert (g_subprocess_get_term_sig (subprocess) == 9);
709 #endif
710   g_spawn_check_exit_status (g_subprocess_get_status (subprocess), &error);
711   g_assert (error != NULL);
712   g_clear_error (&error);
713
714   g_main_loop_quit ((GMainLoop*)user_data);
715 }
716
717 static void
718 test_terminate (void)
719 {
720   GError *local_error = NULL;
721   GError **error = &local_error;
722   GSubprocess *proc;
723   GPtrArray *args;
724   GMainLoop *loop;
725
726   args = get_test_subprocess_args ("sleep-forever", NULL);
727   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
728   g_ptr_array_free (args, TRUE);
729   g_assert_no_error (local_error);
730
731   loop = g_main_loop_new (NULL, TRUE);
732
733   g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
734
735   g_timeout_add_seconds (3, send_terminate, proc);
736
737   g_main_loop_run (loop);
738
739   g_main_loop_unref (loop);
740   g_object_unref (proc);
741 }
742
743 #ifdef G_OS_UNIX
744 static void
745 test_stdout_file (void)
746 {
747   GError *local_error = NULL;
748   GError **error = &local_error;
749   GSubprocessLauncher *launcher;
750   GSubprocess *proc;
751   GPtrArray *args;
752   GFile *tmpfile;
753   GFileIOStream *iostream;
754   GOutputStream *stdin;
755   const char *test_data = "this is some test data\n";
756   char *tmp_contents;
757   char *tmp_file_path;
758
759   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
760   g_assert_no_error (local_error);
761   g_clear_object (&iostream);
762
763   tmp_file_path = g_file_get_path (tmpfile);
764
765   args = get_test_subprocess_args ("cat", NULL);
766   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
767   g_subprocess_launcher_set_stdout_file_path (launcher, tmp_file_path);
768   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
769   g_ptr_array_free (args, TRUE);
770   g_assert_no_error (local_error);
771
772   stdin = g_subprocess_get_stdin_pipe (proc);
773
774   g_output_stream_write_all (stdin, test_data, strlen (test_data), NULL, NULL, error);
775   g_assert_no_error (local_error);
776
777   g_output_stream_close (stdin, NULL, error);
778   g_assert_no_error (local_error);
779
780   g_subprocess_wait_check (proc, NULL, error);
781
782   g_object_unref (launcher);
783   g_object_unref (proc);
784
785   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
786   g_assert_no_error (local_error);
787
788   g_assert_cmpstr (test_data, ==, tmp_contents);
789   g_free (tmp_contents);
790
791   (void) g_file_delete (tmpfile, NULL, NULL);
792   g_free (tmp_file_path);
793 }
794
795 static void
796 test_stdout_fd (void)
797 {
798   GError *local_error = NULL;
799   GError **error = &local_error;
800   GSubprocessLauncher *launcher;
801   GSubprocess *proc;
802   GPtrArray *args;
803   GFile *tmpfile;
804   GFileIOStream *iostream;
805   GFileDescriptorBased *descriptor_stream;
806   GOutputStream *stdin;
807   const char *test_data = "this is some test data\n";
808   char *tmp_contents;
809
810   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
811   g_assert_no_error (local_error);
812
813   args = get_test_subprocess_args ("cat", NULL);
814   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
815   descriptor_stream = G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream)));
816   g_subprocess_launcher_take_stdout_fd (launcher, dup (g_file_descriptor_based_get_fd (descriptor_stream)));
817   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
818   g_ptr_array_free (args, TRUE);
819   g_assert_no_error (local_error);
820
821   g_clear_object (&iostream);
822
823   stdin = g_subprocess_get_stdin_pipe (proc);
824
825   g_output_stream_write_all (stdin, test_data, strlen (test_data), NULL, NULL, error);
826   g_assert_no_error (local_error);
827
828   g_output_stream_close (stdin, NULL, error);
829   g_assert_no_error (local_error);
830
831   g_subprocess_wait_check (proc, NULL, error);
832
833   g_object_unref (launcher);
834   g_object_unref (proc);
835
836   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
837   g_assert_no_error (local_error);
838
839   g_assert_cmpstr (test_data, ==, tmp_contents);
840   g_free (tmp_contents);
841
842   (void) g_file_delete (tmpfile, NULL, NULL);
843 }
844
845 static void
846 child_setup (gpointer user_data)
847 {
848   dup2 (GPOINTER_TO_INT (user_data), 1);
849 }
850
851 static void
852 test_child_setup (void)
853 {
854   GError *local_error = NULL;
855   GError **error = &local_error;
856   GSubprocessLauncher *launcher;
857   GSubprocess *proc;
858   GPtrArray *args;
859   GFile *tmpfile;
860   GFileIOStream *iostream;
861   GOutputStream *stdin;
862   const char *test_data = "this is some test data\n";
863   char *tmp_contents;
864   int fd;
865
866   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
867   g_assert_no_error (local_error);
868
869   fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream))));
870
871   args = get_test_subprocess_args ("cat", NULL);
872   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
873   g_subprocess_launcher_set_child_setup (launcher, child_setup, GINT_TO_POINTER (fd), NULL);
874   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
875   g_ptr_array_free (args, TRUE);
876   g_assert_no_error (local_error);
877
878   g_clear_object (&iostream);
879
880   stdin = g_subprocess_get_stdin_pipe (proc);
881
882   g_output_stream_write_all (stdin, test_data, strlen (test_data), NULL, NULL, error);
883   g_assert_no_error (local_error);
884
885   g_output_stream_close (stdin, NULL, error);
886   g_assert_no_error (local_error);
887
888   g_subprocess_wait_check (proc, NULL, error);
889
890   g_object_unref (launcher);
891   g_object_unref (proc);
892
893   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
894   g_assert_no_error (local_error);
895
896   g_assert_cmpstr (test_data, ==, tmp_contents);
897   g_free (tmp_contents);
898
899   (void) g_file_delete (tmpfile, NULL, NULL);
900 }
901
902 static void
903 test_pass_fd (void)
904 {
905   GError *local_error = NULL;
906   GError **error = &local_error;
907   GInputStream *child_input;
908   GDataInputStream *child_datainput;
909   GSubprocessLauncher *launcher;
910   GSubprocess *proc;
911   GPtrArray *args;
912   int basic_pipefds[2];
913   int needdup_pipefds[2];
914   char *buf;
915   gsize len;
916   char *basic_fd_str;
917   char *needdup_fd_str;
918
919   g_unix_open_pipe (basic_pipefds, FD_CLOEXEC, error);
920   g_assert_no_error (local_error);
921   g_unix_open_pipe (needdup_pipefds, FD_CLOEXEC, error);
922   g_assert_no_error (local_error);
923
924   basic_fd_str = g_strdup_printf ("%d", basic_pipefds[1]);
925   needdup_fd_str = g_strdup_printf ("%d", needdup_pipefds[1] + 1);
926
927   args = get_test_subprocess_args ("write-to-fds", basic_fd_str, needdup_fd_str, NULL);
928   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
929   g_subprocess_launcher_take_fd (launcher, basic_pipefds[1], basic_pipefds[1]);
930   g_subprocess_launcher_take_fd (launcher, needdup_pipefds[1], needdup_pipefds[1] + 1);
931   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
932   g_ptr_array_free (args, TRUE);
933   g_assert_no_error (local_error);
934
935   g_free (basic_fd_str);
936   g_free (needdup_fd_str);
937
938   child_input = g_unix_input_stream_new (basic_pipefds[0], TRUE);
939   child_datainput = g_data_input_stream_new (child_input);
940   buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
941   g_assert_no_error (local_error);
942   g_assert_cmpstr (buf, ==, "hello world");
943   g_object_unref (child_datainput);
944   g_object_unref (child_input);
945   g_free (buf);
946
947   child_input = g_unix_input_stream_new (needdup_pipefds[0], TRUE);
948   child_datainput = g_data_input_stream_new (child_input);
949   buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
950   g_assert_no_error (local_error);
951   g_assert_cmpstr (buf, ==, "hello world");
952   g_free (buf);
953   g_object_unref (child_datainput);
954   g_object_unref (child_input);
955
956   g_object_unref (launcher);
957   g_object_unref (proc);
958 }
959
960 #endif
961
962 int
963 main (int argc, char **argv)
964 {
965   g_test_init (&argc, &argv, NULL);
966
967   g_test_add_func ("/gsubprocess/noop", test_noop);
968   g_test_add_func ("/gsubprocess/noop-all-to-null", test_noop_all_to_null);
969   g_test_add_func ("/gsubprocess/noop-no-wait", test_noop_no_wait);
970   g_test_add_func ("/gsubprocess/noop-stdin-inherit", test_noop_stdin_inherit);
971 #ifdef G_OS_UNIX
972   g_test_add_func ("/gsubprocess/search-path", test_search_path);
973 #endif
974   g_test_add_func ("/gsubprocess/exit1", test_exit1);
975   g_test_add_func ("/gsubprocess/echo1", test_echo1);
976 #ifdef G_OS_UNIX
977   g_test_add_func ("/gsubprocess/echo-merged", test_echo_merged);
978 #endif
979   g_test_add_func ("/gsubprocess/cat-utf8", test_cat_utf8);
980   g_test_add_func ("/gsubprocess/cat-eof", test_cat_eof);
981   g_test_add_func ("/gsubprocess/multi1", test_multi_1);
982   g_test_add_func ("/gsubprocess/communicate", test_communicate);
983   g_test_add_func ("/gsubprocess/communicate-utf8", test_communicate_utf8);
984   g_test_add_func ("/gsubprocess/communicate-utf8-invalid", test_communicate_utf8_invalid);
985   g_test_add_func ("/gsubprocess/terminate", test_terminate);
986 #ifdef G_OS_UNIX
987   g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file);
988   g_test_add_func ("/gsubprocess/stdout-fd", test_stdout_fd);
989   g_test_add_func ("/gsubprocess/child-setup", test_child_setup);
990   g_test_add_func ("/gsubprocess/pass-fd", test_pass_fd);
991 #endif
992
993   return g_test_run ();
994 }