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