[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[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 static gchar *
186 splice_to_string (GInputStream   *stream,
187                   GError        **error)
188 {
189   GMemoryOutputStream *buffer = NULL;
190   char *ret = NULL;
191
192   buffer = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
193   if (g_output_stream_splice ((GOutputStream*)buffer, stream, 0, NULL, error) < 0)
194     goto out;
195
196   if (!g_output_stream_write ((GOutputStream*)buffer, "\0", 1, NULL, error))
197     goto out;
198
199   if (!g_output_stream_close ((GOutputStream*)buffer, NULL, error))
200     goto out;
201
202   ret = g_memory_output_stream_steal_data (buffer);
203  out:
204   g_clear_object (&buffer);
205   return ret;
206 }
207
208 static void
209 test_echo1 (void)
210 {
211   GError *local_error = NULL;
212   GError **error = &local_error;
213   GSubprocess *proc;
214   GPtrArray *args;
215   GInputStream *stdout;
216   gchar *result;
217
218   args = get_test_subprocess_args ("echo", "hello", "world!", NULL);
219   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDOUT_PIPE, error);
220   g_ptr_array_free (args, TRUE);
221   g_assert_no_error (local_error);
222
223   stdout = g_subprocess_get_stdout_pipe (proc);
224
225   result = splice_to_string (stdout, error);
226   g_assert_no_error (local_error);
227
228   g_assert_cmpstr (result, ==, "hello" LINEEND "world!" LINEEND);
229
230   g_free (result);
231   g_object_unref (proc);
232 }
233
234 #ifdef G_OS_UNIX
235 static void
236 test_echo_merged (void)
237 {
238   GError *local_error = NULL;
239   GError **error = &local_error;
240   GSubprocess *proc;
241   GPtrArray *args;
242   GInputStream *stdout;
243   gchar *result;
244
245   args = get_test_subprocess_args ("echo-stdout-and-stderr", "merge", "this", NULL);
246   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
247                             G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_MERGE,
248                             error);
249   g_ptr_array_free (args, TRUE);
250   g_assert_no_error (local_error);
251
252   stdout = g_subprocess_get_stdout_pipe (proc);
253   result = splice_to_string (stdout, error);
254   g_assert_no_error (local_error);
255
256   g_assert_cmpstr (result, ==, "merge\nmerge\nthis\nthis\n");
257
258   g_free (result);
259   g_object_unref (proc);
260 }
261 #endif
262
263 typedef struct {
264   guint events_pending;
265   GMainLoop *loop;
266 } TestCatData;
267
268 static void
269 test_cat_on_input_splice_complete (GObject      *object,
270                                    GAsyncResult *result,
271                                    gpointer      user_data)
272 {
273   TestCatData *data = user_data;
274   GError *error = NULL;
275
276   (void)g_output_stream_splice_finish ((GOutputStream*)object, result, &error);
277   g_assert_no_error (error);
278
279   data->events_pending--;
280   if (data->events_pending == 0)
281     g_main_loop_quit (data->loop);
282 }
283
284 static void
285 test_cat_utf8 (void)
286 {
287   GError *local_error = NULL;
288   GError **error = &local_error;
289   GSubprocess *proc;
290   GPtrArray *args;
291   GBytes *input_buf;
292   GBytes *output_buf;
293   GInputStream *input_buf_stream = NULL;
294   GOutputStream *output_buf_stream = NULL;
295   GOutputStream *stdin_stream = NULL;
296   GInputStream *stdout_stream = NULL;
297   TestCatData data;
298
299   memset (&data, 0, sizeof (data));
300   data.loop = g_main_loop_new (NULL, TRUE);
301
302   args = get_test_subprocess_args ("cat", NULL);
303   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
304                             G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
305                             error);
306   g_ptr_array_free (args, TRUE);
307   g_assert_no_error (local_error);
308
309   stdin_stream = g_subprocess_get_stdin_pipe (proc);
310   stdout_stream = g_subprocess_get_stdout_pipe (proc);
311
312   input_buf = g_bytes_new_static ("hello, world!", strlen ("hello, world!"));
313   input_buf_stream = g_memory_input_stream_new_from_bytes (input_buf);
314   g_bytes_unref (input_buf);
315
316   output_buf_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
317
318   g_output_stream_splice_async (stdin_stream, input_buf_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
319                                 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
320                                 &data);
321   data.events_pending++;
322   g_output_stream_splice_async (output_buf_stream, stdout_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
323                                 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
324                                 &data);
325   data.events_pending++;
326
327   g_main_loop_run (data.loop);
328
329   g_subprocess_wait_check (proc, NULL, error);
330   g_assert_no_error (local_error);
331
332   output_buf = g_memory_output_stream_steal_as_bytes ((GMemoryOutputStream*)output_buf_stream);
333
334   g_assert_cmpint (g_bytes_get_size (output_buf), ==, 13);
335   g_assert_cmpint (memcmp (g_bytes_get_data (output_buf, NULL), "hello, world!", 13), ==, 0);
336
337   g_bytes_unref (output_buf);
338   g_main_loop_unref (data.loop);
339   g_object_unref (input_buf_stream);
340   g_object_unref (output_buf_stream);
341   g_object_unref (proc);
342 }
343
344 static gpointer
345 cancel_soon (gpointer user_data)
346 {
347   GCancellable *cancellable = user_data;
348
349   g_usleep (G_TIME_SPAN_SECOND);
350   g_cancellable_cancel (cancellable);
351   g_object_unref (cancellable);
352
353   return NULL;
354 }
355
356 static void
357 test_cat_eof (void)
358 {
359   GCancellable *cancellable;
360   GError *error = NULL;
361   GSubprocess *cat;
362   gboolean result;
363   gchar buffer;
364   gssize s;
365
366 #ifdef G_OS_WIN32
367   g_test_skip ("This test has not been ported to Win32");
368   return;
369 #endif
370
371   /* Spawn 'cat' */
372   cat = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, "cat", NULL);
373   g_assert_no_error (error);
374   g_assert (cat);
375
376   /* Make sure that reading stdout blocks (until we cancel) */
377   cancellable = g_cancellable_new ();
378   g_thread_unref (g_thread_new ("cancel thread", cancel_soon, g_object_ref (cancellable)));
379   s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, cancellable, &error);
380   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
381   g_assert_cmpint (s, ==, -1);
382   g_object_unref (cancellable);
383   g_clear_error (&error);
384
385   /* Close the stream (EOF on cat's stdin) */
386   result = g_output_stream_close (g_subprocess_get_stdin_pipe (cat), NULL, &error);
387   g_assert_no_error (error);
388   g_assert (result);
389
390   /* Now check that reading cat's stdout gets us an EOF (since it quit) */
391   s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, NULL, &error);
392   g_assert_no_error (error);
393   g_assert (!s);
394
395   /* Check that the process has exited as a result of the EOF */
396   result = g_subprocess_wait (cat, NULL, &error);
397   g_assert_no_error (error);
398   g_assert (g_subprocess_get_if_exited (cat));
399   g_assert_cmpint (g_subprocess_get_exit_status (cat), ==, 0);
400   g_assert (result);
401
402   g_object_unref (cat);
403 }
404
405 typedef struct {
406   guint events_pending;
407   gboolean caught_error;
408   GError *error;
409   GMainLoop *loop;
410
411   gint counter;
412   GOutputStream *first_stdin;
413 } TestMultiSpliceData;
414
415 static void
416 on_one_multi_splice_done (GObject       *obj,
417                           GAsyncResult  *res,
418                           gpointer       user_data)
419 {
420   TestMultiSpliceData *data = user_data;
421
422   if (!data->caught_error)
423     {
424       if (g_output_stream_splice_finish ((GOutputStream*)obj, res, &data->error) < 0)
425         data->caught_error = TRUE;
426     }
427
428   data->events_pending--;
429   if (data->events_pending == 0)
430     g_main_loop_quit (data->loop);
431 }
432
433 static gboolean
434 on_idle_multisplice (gpointer     user_data)
435 {
436   TestMultiSpliceData *data = user_data;
437
438   /* We write 2^1 + 2^2 ... + 2^10 or 2047 copies of "Hello World!\n"
439    * ultimately
440    */
441   if (data->counter >= 2047 || data->caught_error)
442     {
443       if (!g_output_stream_close (data->first_stdin, NULL, &data->error))
444         data->caught_error = TRUE;
445       data->events_pending--;
446       if (data->events_pending == 0)
447         {
448           g_main_loop_quit (data->loop);
449         }
450       return FALSE;
451     }
452   else
453     {
454       int i;
455       for (i = 0; i < data->counter; i++)
456         {
457           gsize bytes_written;
458           if (!g_output_stream_write_all (data->first_stdin, "hello world!\n",
459                                           strlen ("hello world!\n"), &bytes_written,
460                                           NULL, &data->error))
461             {
462               data->caught_error = TRUE;
463               return FALSE;
464             }
465         }
466       data->counter *= 2;
467       return TRUE;
468     }
469 }
470
471 static void
472 on_subprocess_exited (GObject         *object,
473                       GAsyncResult    *result,
474                       gpointer         user_data)
475 {
476   GSubprocess *subprocess = G_SUBPROCESS (object);
477   TestMultiSpliceData *data = user_data;
478   GError *error = NULL;
479
480   if (!g_subprocess_wait_finish (subprocess, result, &error))
481     {
482       if (!data->caught_error)
483         {
484           data->caught_error = TRUE;
485           g_propagate_error (&data->error, error);
486         }
487     }
488   g_spawn_check_exit_status (g_subprocess_get_exit_status (subprocess), &error);
489   g_assert_no_error (error);
490   data->events_pending--;
491   if (data->events_pending == 0)
492     g_main_loop_quit (data->loop);
493 }
494
495 static void
496 test_multi_1 (void)
497 {
498   GError *local_error = NULL;
499   GError **error = &local_error;
500   GPtrArray *args;
501   GSubprocessLauncher *launcher;
502   GSubprocess *first;
503   GSubprocess *second;
504   GSubprocess *third;
505   GOutputStream *first_stdin;
506   GInputStream *first_stdout;
507   GOutputStream *second_stdin;
508   GInputStream *second_stdout;
509   GOutputStream *third_stdin;
510   GInputStream *third_stdout;
511   GOutputStream *membuf;
512   TestMultiSpliceData data;
513   int splice_flags = G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET;
514
515   args = get_test_subprocess_args ("cat", NULL);
516   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE);
517   first = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
518   g_assert_no_error (local_error);
519   second = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
520   g_assert_no_error (local_error);
521   third = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
522   g_assert_no_error (local_error);
523
524   g_ptr_array_free (args, TRUE);
525
526   membuf = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
527
528   first_stdin = g_subprocess_get_stdin_pipe (first);
529   first_stdout = g_subprocess_get_stdout_pipe (first);
530   second_stdin = g_subprocess_get_stdin_pipe (second);
531   second_stdout = g_subprocess_get_stdout_pipe (second);
532   third_stdin = g_subprocess_get_stdin_pipe (third);
533   third_stdout = g_subprocess_get_stdout_pipe (third);
534
535   memset (&data, 0, sizeof (data));
536   data.loop = g_main_loop_new (NULL, TRUE);
537   data.counter = 1;
538   data.first_stdin = first_stdin;
539
540   data.events_pending++;
541   g_output_stream_splice_async (second_stdin, first_stdout, splice_flags, G_PRIORITY_DEFAULT,
542                                 NULL, on_one_multi_splice_done, &data);
543   data.events_pending++;
544   g_output_stream_splice_async (third_stdin, second_stdout, splice_flags, G_PRIORITY_DEFAULT,
545                                 NULL, on_one_multi_splice_done, &data);
546   data.events_pending++;
547   g_output_stream_splice_async (membuf, third_stdout, splice_flags, G_PRIORITY_DEFAULT,
548                                 NULL, on_one_multi_splice_done, &data);
549
550   data.events_pending++;
551   g_timeout_add (250, on_idle_multisplice, &data);
552
553   data.events_pending++;
554   g_subprocess_wait_async (first, NULL, on_subprocess_exited, &data);
555   data.events_pending++;
556   g_subprocess_wait_async (second, NULL, on_subprocess_exited, &data);
557   data.events_pending++;
558   g_subprocess_wait_async (third, NULL, on_subprocess_exited, &data);
559
560   g_main_loop_run (data.loop);
561
562   g_assert (!data.caught_error);
563   g_assert_no_error (data.error);
564
565   g_assert_cmpint (g_memory_output_stream_get_data_size ((GMemoryOutputStream*)membuf), ==, 26611);
566
567   g_main_loop_unref (data.loop);
568   g_object_unref (membuf);
569   g_object_unref (launcher);
570   g_object_unref (first);
571   g_object_unref (second);
572   g_object_unref (third);
573 }
574
575 typedef struct {
576   gboolean is_utf8;
577   gboolean running;
578   GError *error;
579 } TestAsyncCommunicateData;
580
581 static void
582 on_communicate_complete (GObject               *proc,
583                          GAsyncResult          *result,
584                          gpointer               user_data)
585 {
586   TestAsyncCommunicateData *data = user_data;
587   GBytes *stdout = NULL;
588   char *stdout_str = NULL;
589   const guint8 *stdout_data;
590   gsize stdout_len;
591
592   data->running = FALSE;
593   if (data->is_utf8)
594     (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
595                                                  &stdout_str, NULL, &data->error);
596   else
597     (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
598                                             &stdout, NULL, &data->error);
599   if (data->error)
600       return;
601
602   if (!data->is_utf8)
603     {
604       g_assert (stdout != NULL);
605       stdout_data = g_bytes_get_data (stdout, &stdout_len);
606     }
607   else
608     {
609       g_assert (stdout_str != NULL);
610       stdout_data = (guint8*)stdout_str;
611       stdout_len = strlen (stdout_str);
612     }
613
614   g_assert_cmpint (stdout_len, ==, 11);
615   g_assert (memcmp (stdout_data, "hello world", 11) == 0);
616   if (stdout)
617     g_bytes_unref (stdout);
618   g_free (stdout_str);
619 }
620
621 static void
622 test_communicate_async (void)
623 {
624   GError *error = NULL;
625   GPtrArray *args;
626   TestAsyncCommunicateData data = { 0, };
627   GSubprocess *proc;
628   GCancellable *cancellable = NULL;
629   GBytes *input;
630   const char *hellostring;
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   hellostring = "hello world";
640   input = g_bytes_new_static (hellostring, strlen (hellostring));
641
642   g_subprocess_communicate_async (proc, input,
643                                   cancellable,
644                                   on_communicate_complete, 
645                                   &data);
646   
647   data.running = TRUE;
648   while (data.running)
649     g_main_context_iteration (NULL, TRUE);
650
651   g_assert_no_error (data.error);
652
653   g_bytes_unref (input);
654   g_object_unref (proc);
655 }
656
657 static void
658 test_communicate (void)
659 {
660   GError *error = NULL;
661   GPtrArray *args;
662   GSubprocess *proc;
663   GCancellable *cancellable = NULL;
664   GBytes *input;
665   const gchar *hellostring;
666   GBytes *stdout;
667   const gchar *stdout_data;
668   gsize stdout_len;
669
670   args = get_test_subprocess_args ("cat", NULL);
671   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
672                             G_SUBPROCESS_FLAGS_STDIN_PIPE
673                             | G_SUBPROCESS_FLAGS_STDOUT_PIPE
674                             | G_SUBPROCESS_FLAGS_STDERR_MERGE,
675                             &error);
676   g_assert_no_error (error);
677   g_ptr_array_free (args, TRUE);
678
679   hellostring = "hello world";
680   input = g_bytes_new_static (hellostring, strlen (hellostring));
681
682   g_subprocess_communicate (proc, input, cancellable, &stdout, NULL, &error);
683   g_assert_no_error (error);
684   stdout_data = g_bytes_get_data (stdout, &stdout_len);
685
686   g_assert_cmpint (stdout_len, ==, 11);
687   g_assert (memcmp (stdout_data, "hello world", 11) == 0);
688   g_bytes_unref (stdout);
689   
690   g_bytes_unref (input);
691   g_bytes_unref (stdout);
692   g_object_unref (proc);
693 }
694
695 static void
696 test_communicate_utf8_async (void)
697 {
698   GError *error = NULL;
699   GPtrArray *args;
700   TestAsyncCommunicateData data = { 0, };
701   GSubprocess *proc;
702   GCancellable *cancellable = NULL;
703
704   args = get_test_subprocess_args ("cat", NULL);
705   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
706                             G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
707                             &error);
708   g_assert_no_error (error);
709   g_ptr_array_free (args, TRUE);
710
711   data.is_utf8 = TRUE;
712   g_subprocess_communicate_utf8_async (proc, "hello world",
713                                        cancellable,
714                                        on_communicate_complete, 
715                                        &data);
716   
717   data.running = TRUE;
718   while (data.running)
719     g_main_context_iteration (NULL, TRUE);
720
721   g_assert_no_error (data.error);
722
723   g_object_unref (proc);
724 }
725
726 static void
727 test_communicate_utf8 (void)
728 {
729   GError *error = NULL;
730   GPtrArray *args;
731   GSubprocess *proc;
732   GCancellable *cancellable = NULL;
733   const gchar *stdin_buf;
734   gchar *stdout_buf;
735
736   args = get_test_subprocess_args ("cat", NULL);
737   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
738                             G_SUBPROCESS_FLAGS_STDIN_PIPE
739                             | G_SUBPROCESS_FLAGS_STDOUT_PIPE
740                             | G_SUBPROCESS_FLAGS_STDERR_MERGE,
741                             &error);
742   g_assert_no_error (error);
743   g_ptr_array_free (args, TRUE);
744
745   stdin_buf = "hello world";
746
747   g_subprocess_communicate_utf8 (proc, stdin_buf, cancellable, &stdout_buf, NULL, &error);
748   g_assert_no_error (error);
749
750   g_assert (strcmp (stdout_buf, "hello world") == 0);
751   g_free (stdout_buf);
752   
753   g_object_unref (proc);
754 }
755
756 static void
757 test_communicate_nothing (void)
758 {
759   GError *error = NULL;
760   GPtrArray *args;
761   GSubprocess *proc;
762   GCancellable *cancellable = NULL;
763   gchar *stdout_buf;
764
765   args = get_test_subprocess_args ("cat", NULL);
766   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
767                             G_SUBPROCESS_FLAGS_STDIN_PIPE
768                             | G_SUBPROCESS_FLAGS_STDOUT_PIPE
769                             | G_SUBPROCESS_FLAGS_STDERR_MERGE,
770                             &error);
771   g_assert_no_error (error);
772   g_ptr_array_free (args, TRUE);
773
774   g_subprocess_communicate_utf8 (proc, "", cancellable, &stdout_buf, NULL, &error);
775   g_assert_no_error (error);
776
777   g_assert_cmpstr (stdout_buf, ==, "");
778
779   g_free (stdout_buf);
780
781   g_object_unref (proc);
782 }
783
784 static void
785 test_communicate_utf8_invalid (void)
786 {
787   GError *error = NULL;
788   GPtrArray *args;
789   TestAsyncCommunicateData data = { 0, };
790   GSubprocess *proc;
791   GCancellable *cancellable = NULL;
792
793   args = get_test_subprocess_args ("cat", NULL);
794   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
795                             G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
796                             &error);
797   g_assert_no_error (error);
798   g_ptr_array_free (args, TRUE);
799
800   data.is_utf8 = TRUE;
801   g_subprocess_communicate_utf8_async (proc, "\xFF\xFF",
802                                        cancellable,
803                                        on_communicate_complete, 
804                                        &data);
805   
806   data.running = TRUE;
807   while (data.running)
808     g_main_context_iteration (NULL, TRUE);
809
810   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_FAILED);
811   g_error_free (data.error);
812
813   g_object_unref (proc);
814 }
815
816 static gboolean
817 send_terminate (gpointer   user_data)
818 {
819   GSubprocess *proc = user_data;
820
821   g_subprocess_force_exit (proc);
822
823   return FALSE;
824 }
825
826 static void
827 on_request_quit_exited (GObject        *object,
828                         GAsyncResult   *result,
829                         gpointer        user_data)
830 {
831   GSubprocess *subprocess = G_SUBPROCESS (object);
832   GError *error = NULL;
833
834   g_subprocess_wait_finish (subprocess, result, &error);
835   g_assert_no_error (error);
836 #ifdef G_OS_UNIX
837   g_assert (g_subprocess_get_if_signaled (subprocess));
838   g_assert (g_subprocess_get_term_sig (subprocess) == 9);
839 #endif
840   g_spawn_check_exit_status (g_subprocess_get_status (subprocess), &error);
841   g_assert (error != NULL);
842   g_clear_error (&error);
843
844   g_main_loop_quit ((GMainLoop*)user_data);
845 }
846
847 static void
848 test_terminate (void)
849 {
850   GError *local_error = NULL;
851   GError **error = &local_error;
852   GSubprocess *proc;
853   GPtrArray *args;
854   GMainLoop *loop;
855
856   args = get_test_subprocess_args ("sleep-forever", NULL);
857   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
858   g_ptr_array_free (args, TRUE);
859   g_assert_no_error (local_error);
860
861   loop = g_main_loop_new (NULL, TRUE);
862
863   g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
864
865   g_timeout_add_seconds (3, send_terminate, proc);
866
867   g_main_loop_run (loop);
868
869   g_main_loop_unref (loop);
870   g_object_unref (proc);
871 }
872
873 #ifdef G_OS_UNIX
874 static gboolean
875 send_signal (gpointer user_data)
876 {
877   GSubprocess *proc = user_data;
878
879   g_subprocess_send_signal (proc, SIGKILL);
880
881   return FALSE;
882 }
883
884 static void
885 test_signal (void)
886 {
887   GError *local_error = NULL;
888   GError **error = &local_error;
889   GSubprocess *proc;
890   GPtrArray *args;
891   GMainLoop *loop;
892
893   args = get_test_subprocess_args ("sleep-forever", NULL);
894   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
895   g_ptr_array_free (args, TRUE);
896   g_assert_no_error (local_error);
897
898   loop = g_main_loop_new (NULL, TRUE);
899
900   g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
901
902   g_timeout_add_seconds (3, send_signal, proc);
903
904   g_main_loop_run (loop);
905
906   g_main_loop_unref (loop);
907   g_object_unref (proc);
908 }
909 #endif
910
911 static void
912 test_env (void)
913 {
914   GError *local_error = NULL;
915   GError **error = &local_error;
916   GSubprocessLauncher *launcher;
917   GSubprocess *proc;
918   GPtrArray *args;
919   GInputStream *stdout;
920   gchar *result;
921   gchar *envp[] = { "ONE=1", "TWO=1", "THREE=3", "FOUR=1", NULL };
922   gchar **split;
923
924   args = get_test_subprocess_args ("env", NULL);
925   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
926   g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
927   g_subprocess_launcher_set_environ (launcher, envp);
928   g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
929   g_subprocess_launcher_setenv (launcher, "THREE", "1", FALSE);
930   g_subprocess_launcher_unsetenv (launcher, "FOUR");
931
932   g_assert_null (g_subprocess_launcher_getenv (launcher, "FOUR"));
933    
934   proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
935   g_ptr_array_free (args, TRUE);
936   g_assert_no_error (local_error);
937
938   stdout = g_subprocess_get_stdout_pipe (proc);
939
940   result = splice_to_string (stdout, error);
941   split = g_strsplit (result, "\n", -1);
942   g_assert_cmpstr (g_environ_getenv (split, "ONE"), ==, "1");
943   g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
944   g_assert_cmpstr (g_environ_getenv (split, "THREE"), ==, "3");
945   g_assert_null (g_environ_getenv (split, "FOUR"));
946
947   g_strfreev (split);
948   g_free (result);
949   g_object_unref (proc);
950 }
951
952 static void
953 test_cwd (void)
954 {
955   GError *local_error = NULL;
956   GError **error = &local_error;
957   GSubprocessLauncher *launcher;
958   GSubprocess *proc;
959   GPtrArray *args;
960   GInputStream *stdout;
961   gchar *result;
962   const char *basename;
963
964   args = get_test_subprocess_args ("cwd", NULL);
965   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
966   g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
967   g_subprocess_launcher_set_cwd (launcher, "/tmp");
968
969   proc = g_subprocess_launcher_spawnv (launcher, (const char * const *)args->pdata, error);
970   g_ptr_array_free (args, TRUE);
971   g_assert_no_error (local_error);
972
973   stdout = g_subprocess_get_stdout_pipe (proc);
974
975   result = splice_to_string (stdout, error);
976
977   basename = g_strrstr (result, "/");
978   g_assert (basename != NULL);
979   g_assert_cmpstr (basename, ==, "/tmp" LINEEND);
980
981   g_free (result);
982   g_object_unref (proc);
983 }
984 #ifdef G_OS_UNIX
985 static void
986 test_stdout_file (void)
987 {
988   GError *local_error = NULL;
989   GError **error = &local_error;
990   GSubprocessLauncher *launcher;
991   GSubprocess *proc;
992   GPtrArray *args;
993   GFile *tmpfile;
994   GFileIOStream *iostream;
995   GOutputStream *stdin;
996   const char *test_data = "this is some test data\n";
997   char *tmp_contents;
998   char *tmp_file_path;
999
1000   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1001   g_assert_no_error (local_error);
1002   g_clear_object (&iostream);
1003
1004   tmp_file_path = g_file_get_path (tmpfile);
1005
1006   args = get_test_subprocess_args ("cat", NULL);
1007   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1008   g_subprocess_launcher_set_stdout_file_path (launcher, tmp_file_path);
1009   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1010   g_ptr_array_free (args, TRUE);
1011   g_assert_no_error (local_error);
1012
1013   stdin = g_subprocess_get_stdin_pipe (proc);
1014
1015   g_output_stream_write_all (stdin, test_data, strlen (test_data), NULL, NULL, error);
1016   g_assert_no_error (local_error);
1017
1018   g_output_stream_close (stdin, NULL, error);
1019   g_assert_no_error (local_error);
1020
1021   g_subprocess_wait_check (proc, NULL, error);
1022
1023   g_object_unref (launcher);
1024   g_object_unref (proc);
1025
1026   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1027   g_assert_no_error (local_error);
1028
1029   g_assert_cmpstr (test_data, ==, tmp_contents);
1030   g_free (tmp_contents);
1031
1032   (void) g_file_delete (tmpfile, NULL, NULL);
1033   g_object_unref (tmpfile);
1034   g_free (tmp_file_path);
1035 }
1036
1037 static void
1038 test_stdout_fd (void)
1039 {
1040   GError *local_error = NULL;
1041   GError **error = &local_error;
1042   GSubprocessLauncher *launcher;
1043   GSubprocess *proc;
1044   GPtrArray *args;
1045   GFile *tmpfile;
1046   GFileIOStream *iostream;
1047   GFileDescriptorBased *descriptor_stream;
1048   GOutputStream *stdin;
1049   const char *test_data = "this is some test data\n";
1050   char *tmp_contents;
1051
1052   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1053   g_assert_no_error (local_error);
1054
1055   args = get_test_subprocess_args ("cat", NULL);
1056   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1057   descriptor_stream = G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream)));
1058   g_subprocess_launcher_take_stdout_fd (launcher, dup (g_file_descriptor_based_get_fd (descriptor_stream)));
1059   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1060   g_ptr_array_free (args, TRUE);
1061   g_assert_no_error (local_error);
1062
1063   g_clear_object (&iostream);
1064
1065   stdin = g_subprocess_get_stdin_pipe (proc);
1066
1067   g_output_stream_write_all (stdin, test_data, strlen (test_data), NULL, NULL, error);
1068   g_assert_no_error (local_error);
1069
1070   g_output_stream_close (stdin, NULL, error);
1071   g_assert_no_error (local_error);
1072
1073   g_subprocess_wait_check (proc, NULL, error);
1074
1075   g_object_unref (launcher);
1076   g_object_unref (proc);
1077
1078   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1079   g_assert_no_error (local_error);
1080
1081   g_assert_cmpstr (test_data, ==, tmp_contents);
1082   g_free (tmp_contents);
1083
1084   (void) g_file_delete (tmpfile, NULL, NULL);
1085   g_object_unref (tmpfile);
1086 }
1087
1088 static void
1089 child_setup (gpointer user_data)
1090 {
1091   dup2 (GPOINTER_TO_INT (user_data), 1);
1092 }
1093
1094 static void
1095 test_child_setup (void)
1096 {
1097   GError *local_error = NULL;
1098   GError **error = &local_error;
1099   GSubprocessLauncher *launcher;
1100   GSubprocess *proc;
1101   GPtrArray *args;
1102   GFile *tmpfile;
1103   GFileIOStream *iostream;
1104   GOutputStream *stdin;
1105   const char *test_data = "this is some test data\n";
1106   char *tmp_contents;
1107   int fd;
1108
1109   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1110   g_assert_no_error (local_error);
1111
1112   fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream))));
1113
1114   args = get_test_subprocess_args ("cat", NULL);
1115   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1116   g_subprocess_launcher_set_child_setup (launcher, child_setup, GINT_TO_POINTER (fd), NULL);
1117   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1118   g_ptr_array_free (args, TRUE);
1119   g_assert_no_error (local_error);
1120
1121   g_clear_object (&iostream);
1122
1123   stdin = g_subprocess_get_stdin_pipe (proc);
1124
1125   g_output_stream_write_all (stdin, test_data, strlen (test_data), NULL, NULL, error);
1126   g_assert_no_error (local_error);
1127
1128   g_output_stream_close (stdin, NULL, error);
1129   g_assert_no_error (local_error);
1130
1131   g_subprocess_wait_check (proc, NULL, error);
1132
1133   g_object_unref (launcher);
1134   g_object_unref (proc);
1135
1136   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1137   g_assert_no_error (local_error);
1138
1139   g_assert_cmpstr (test_data, ==, tmp_contents);
1140   g_free (tmp_contents);
1141
1142   (void) g_file_delete (tmpfile, NULL, NULL);
1143   g_object_unref (tmpfile);
1144 }
1145
1146 static void
1147 test_pass_fd (void)
1148 {
1149   GError *local_error = NULL;
1150   GError **error = &local_error;
1151   GInputStream *child_input;
1152   GDataInputStream *child_datainput;
1153   GSubprocessLauncher *launcher;
1154   GSubprocess *proc;
1155   GPtrArray *args;
1156   int basic_pipefds[2];
1157   int needdup_pipefds[2];
1158   char *buf;
1159   gsize len;
1160   char *basic_fd_str;
1161   char *needdup_fd_str;
1162
1163   g_unix_open_pipe (basic_pipefds, FD_CLOEXEC, error);
1164   g_assert_no_error (local_error);
1165   g_unix_open_pipe (needdup_pipefds, FD_CLOEXEC, error);
1166   g_assert_no_error (local_error);
1167
1168   basic_fd_str = g_strdup_printf ("%d", basic_pipefds[1]);
1169   needdup_fd_str = g_strdup_printf ("%d", needdup_pipefds[1] + 1);
1170
1171   args = get_test_subprocess_args ("write-to-fds", basic_fd_str, needdup_fd_str, NULL);
1172   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1173   g_subprocess_launcher_take_fd (launcher, basic_pipefds[1], basic_pipefds[1]);
1174   g_subprocess_launcher_take_fd (launcher, needdup_pipefds[1], needdup_pipefds[1] + 1);
1175   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1176   g_ptr_array_free (args, TRUE);
1177   g_assert_no_error (local_error);
1178
1179   g_free (basic_fd_str);
1180   g_free (needdup_fd_str);
1181
1182   child_input = g_unix_input_stream_new (basic_pipefds[0], TRUE);
1183   child_datainput = g_data_input_stream_new (child_input);
1184   buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1185   g_assert_no_error (local_error);
1186   g_assert_cmpstr (buf, ==, "hello world");
1187   g_object_unref (child_datainput);
1188   g_object_unref (child_input);
1189   g_free (buf);
1190
1191   child_input = g_unix_input_stream_new (needdup_pipefds[0], TRUE);
1192   child_datainput = g_data_input_stream_new (child_input);
1193   buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1194   g_assert_no_error (local_error);
1195   g_assert_cmpstr (buf, ==, "hello world");
1196   g_free (buf);
1197   g_object_unref (child_datainput);
1198   g_object_unref (child_input);
1199
1200   g_object_unref (launcher);
1201   g_object_unref (proc);
1202 }
1203
1204 #endif
1205
1206 static void
1207 test_launcher_environment (void)
1208 {
1209   GSubprocessLauncher *launcher;
1210   GError *error = NULL;
1211   GSubprocess *proc;
1212   GPtrArray *args;
1213   gchar *out;
1214
1215   g_setenv ("A", "B", TRUE);
1216   g_setenv ("C", "D", TRUE);
1217
1218   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1219
1220   /* unset a variable */
1221   g_subprocess_launcher_unsetenv (launcher, "A");
1222
1223   /* and set a diffferent one */
1224   g_subprocess_launcher_setenv (launcher, "E", "F", TRUE);
1225
1226   args = get_test_subprocess_args ("printenv", "A", "C", "E", NULL);
1227   proc = g_subprocess_launcher_spawnv (launcher, (const gchar **) args->pdata, &error);
1228   g_assert_no_error (error);
1229   g_assert (proc);
1230
1231   g_subprocess_communicate_utf8 (proc, NULL, NULL, &out, NULL, &error);
1232   g_assert_no_error (error);
1233
1234   g_assert_cmpstr (out, ==, "C=D\nE=F\n");
1235   g_free (out);
1236
1237   g_object_unref (proc);
1238 }
1239
1240 int
1241 main (int argc, char **argv)
1242 {
1243   g_test_init (&argc, &argv, NULL);
1244
1245   g_test_add_func ("/gsubprocess/noop", test_noop);
1246   g_test_add_func ("/gsubprocess/noop-all-to-null", test_noop_all_to_null);
1247   g_test_add_func ("/gsubprocess/noop-no-wait", test_noop_no_wait);
1248   g_test_add_func ("/gsubprocess/noop-stdin-inherit", test_noop_stdin_inherit);
1249 #ifdef G_OS_UNIX
1250   g_test_add_func ("/gsubprocess/search-path", test_search_path);
1251   g_test_add_func ("/gsubprocess/signal", test_signal);
1252 #endif
1253   g_test_add_func ("/gsubprocess/exit1", test_exit1);
1254   g_test_add_func ("/gsubprocess/echo1", test_echo1);
1255 #ifdef G_OS_UNIX
1256   g_test_add_func ("/gsubprocess/echo-merged", test_echo_merged);
1257 #endif
1258   g_test_add_func ("/gsubprocess/cat-utf8", test_cat_utf8);
1259   g_test_add_func ("/gsubprocess/cat-eof", test_cat_eof);
1260   g_test_add_func ("/gsubprocess/multi1", test_multi_1);
1261   g_test_add_func ("/gsubprocess/communicate", test_communicate);
1262   g_test_add_func ("/gsubprocess/communicate-async", test_communicate_async);
1263   g_test_add_func ("/gsubprocess/communicate-utf8", test_communicate_utf8);
1264   g_test_add_func ("/gsubprocess/communicate-utf8-async", test_communicate_utf8_async);
1265   g_test_add_func ("/gsubprocess/communicate-utf8-invalid", test_communicate_utf8_invalid);
1266   g_test_add_func ("/gsubprocess/communicate-nothing", test_communicate_nothing);
1267   g_test_add_func ("/gsubprocess/terminate", test_terminate);
1268   g_test_add_func ("/gsubprocess/env", test_env);
1269   g_test_add_func ("/gsubprocess/cwd", test_cwd);
1270 #ifdef G_OS_UNIX
1271   g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file);
1272   g_test_add_func ("/gsubprocess/stdout-fd", test_stdout_fd);
1273   g_test_add_func ("/gsubprocess/child-setup", test_child_setup);
1274   g_test_add_func ("/gsubprocess/pass-fd", test_pass_fd);
1275 #endif
1276   g_test_add_func ("/gsubprocess/launcher-environment", test_launcher_environment);
1277
1278   return g_test_run ();
1279 }