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