Add some more cases to the app-id unit tests
[glib.git] / gio / tests / gsubprocess.c
blobe1270b1bd76c8fe9e8edc725b3797cd65ee4b7dd
1 #include <gio/gio.h>
2 #include <string.h>
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
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
19 static GPtrArray *
20 get_test_subprocess_args (const char *mode,
21 ...) G_GNUC_NULL_TERMINATED;
23 static GPtrArray *
24 get_test_subprocess_args (const char *mode,
25 ...)
27 GPtrArray *ret;
28 char *path;
29 const char *binname;
30 va_list args;
31 gpointer arg;
33 ret = g_ptr_array_new_with_free_func (g_free);
35 #ifdef G_OS_WIN32
36 binname = "gsubprocess-testprog.exe";
37 #else
38 binname = "gsubprocess-testprog";
39 #endif
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));
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);
50 g_ptr_array_add (ret, NULL);
51 return ret;
54 static void
55 test_noop (void)
57 GError *local_error = NULL;
58 GError **error = &local_error;
59 GPtrArray *args;
60 GSubprocess *proc;
61 const gchar *id;
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);
70 g_subprocess_wait_check (proc, NULL, error);
71 g_assert_no_error (local_error);
72 g_assert (g_subprocess_get_successful (proc));
74 g_object_unref (proc);
77 static void
78 check_ready (GObject *source,
79 GAsyncResult *res,
80 gpointer user_data)
82 gboolean ret;
83 GError *error = NULL;
85 ret = g_subprocess_wait_check_finish (G_SUBPROCESS (source),
86 res,
87 &error);
88 g_assert (ret);
89 g_assert_no_error (error);
91 g_object_unref (source);
94 static void
95 test_noop_all_to_null (void)
97 GError *local_error = NULL;
98 GError **error = &local_error;
99 GPtrArray *args;
100 GSubprocess *proc;
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);
109 g_subprocess_wait_check_async (proc, NULL, check_ready, NULL);
112 static void
113 test_noop_no_wait (void)
115 GError *local_error = NULL;
116 GError **error = &local_error;
117 GPtrArray *args;
118 GSubprocess *proc;
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);
125 g_object_unref (proc);
128 static void
129 test_noop_stdin_inherit (void)
131 GError *local_error = NULL;
132 GError **error = &local_error;
133 GPtrArray *args;
134 GSubprocess *proc;
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);
141 g_subprocess_wait_check (proc, NULL, error);
142 g_assert_no_error (local_error);
144 g_object_unref (proc);
147 #ifdef G_OS_UNIX
148 static void
149 test_search_path (void)
151 GError *local_error = NULL;
152 GError **error = &local_error;
153 GSubprocess *proc;
155 proc = g_subprocess_new (G_SUBPROCESS_FLAGS_NONE, error, "true", NULL);
156 g_assert_no_error (local_error);
158 g_subprocess_wait_check (proc, NULL, error);
159 g_assert_no_error (local_error);
161 g_object_unref (proc);
163 #endif
165 static void
166 test_exit1 (void)
168 GError *local_error = NULL;
169 GError **error = &local_error;
170 GPtrArray *args;
171 GSubprocess *proc;
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);
178 g_subprocess_wait_check (proc, NULL, error);
179 g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
180 g_clear_error (error);
182 g_object_unref (proc);
185 static gchar *
186 splice_to_string (GInputStream *stream,
187 GError **error)
189 GMemoryOutputStream *buffer = NULL;
190 char *ret = NULL;
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;
196 if (!g_output_stream_write ((GOutputStream*)buffer, "\0", 1, NULL, error))
197 goto out;
199 if (!g_output_stream_close ((GOutputStream*)buffer, NULL, error))
200 goto out;
202 ret = g_memory_output_stream_steal_data (buffer);
203 out:
204 g_clear_object (&buffer);
205 return ret;
208 static void
209 test_echo1 (void)
211 GError *local_error = NULL;
212 GError **error = &local_error;
213 GSubprocess *proc;
214 GPtrArray *args;
215 GInputStream *stdout;
216 gchar *result;
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);
223 stdout = g_subprocess_get_stdout_pipe (proc);
225 result = splice_to_string (stdout, error);
226 g_assert_no_error (local_error);
228 g_assert_cmpstr (result, ==, "hello" LINEEND "world!" LINEEND);
230 g_free (result);
231 g_object_unref (proc);
234 #ifdef G_OS_UNIX
235 static void
236 test_echo_merged (void)
238 GError *local_error = NULL;
239 GError **error = &local_error;
240 GSubprocess *proc;
241 GPtrArray *args;
242 GInputStream *stdout;
243 gchar *result;
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);
252 stdout = g_subprocess_get_stdout_pipe (proc);
253 result = splice_to_string (stdout, error);
254 g_assert_no_error (local_error);
256 g_assert_cmpstr (result, ==, "merge\nmerge\nthis\nthis\n");
258 g_free (result);
259 g_object_unref (proc);
261 #endif
263 typedef struct {
264 guint events_pending;
265 GMainLoop *loop;
266 } TestCatData;
268 static void
269 test_cat_on_input_splice_complete (GObject *object,
270 GAsyncResult *result,
271 gpointer user_data)
273 TestCatData *data = user_data;
274 GError *error = NULL;
276 (void)g_output_stream_splice_finish ((GOutputStream*)object, result, &error);
277 g_assert_no_error (error);
279 data->events_pending--;
280 if (data->events_pending == 0)
281 g_main_loop_quit (data->loop);
284 static void
285 test_cat_utf8 (void)
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;
299 memset (&data, 0, sizeof (data));
300 data.loop = g_main_loop_new (NULL, TRUE);
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);
309 stdin_stream = g_subprocess_get_stdin_pipe (proc);
310 stdout_stream = g_subprocess_get_stdout_pipe (proc);
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);
316 output_buf_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
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++;
327 g_main_loop_run (data.loop);
329 g_subprocess_wait_check (proc, NULL, error);
330 g_assert_no_error (local_error);
332 output_buf = g_memory_output_stream_steal_as_bytes ((GMemoryOutputStream*)output_buf_stream);
334 g_assert_cmpmem (g_bytes_get_data (output_buf, NULL),
335 g_bytes_get_size (output_buf),
336 "hello, world!", 13);
338 g_bytes_unref (output_buf);
339 g_main_loop_unref (data.loop);
340 g_object_unref (input_buf_stream);
341 g_object_unref (output_buf_stream);
342 g_object_unref (proc);
345 static gpointer
346 cancel_soon (gpointer user_data)
348 GCancellable *cancellable = user_data;
350 g_usleep (G_TIME_SPAN_SECOND);
351 g_cancellable_cancel (cancellable);
352 g_object_unref (cancellable);
354 return NULL;
357 static void
358 test_cat_eof (void)
360 GCancellable *cancellable;
361 GError *error = NULL;
362 GSubprocess *cat;
363 gboolean result;
364 gchar buffer;
365 gssize s;
367 #ifdef G_OS_WIN32
368 g_test_skip ("This test has not been ported to Win32");
369 return;
370 #endif
372 /* Spawn 'cat' */
373 cat = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, "cat", NULL);
374 g_assert_no_error (error);
375 g_assert (cat);
377 /* Make sure that reading stdout blocks (until we cancel) */
378 cancellable = g_cancellable_new ();
379 g_thread_unref (g_thread_new ("cancel thread", cancel_soon, g_object_ref (cancellable)));
380 s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, cancellable, &error);
381 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
382 g_assert_cmpint (s, ==, -1);
383 g_object_unref (cancellable);
384 g_clear_error (&error);
386 /* Close the stream (EOF on cat's stdin) */
387 result = g_output_stream_close (g_subprocess_get_stdin_pipe (cat), NULL, &error);
388 g_assert_no_error (error);
389 g_assert (result);
391 /* Now check that reading cat's stdout gets us an EOF (since it quit) */
392 s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, NULL, &error);
393 g_assert_no_error (error);
394 g_assert (!s);
396 /* Check that the process has exited as a result of the EOF */
397 result = g_subprocess_wait (cat, NULL, &error);
398 g_assert_no_error (error);
399 g_assert (g_subprocess_get_if_exited (cat));
400 g_assert_cmpint (g_subprocess_get_exit_status (cat), ==, 0);
401 g_assert (result);
403 g_object_unref (cat);
406 typedef struct {
407 guint events_pending;
408 gboolean caught_error;
409 GError *error;
410 GMainLoop *loop;
412 gint counter;
413 GOutputStream *first_stdin;
414 } TestMultiSpliceData;
416 static void
417 on_one_multi_splice_done (GObject *obj,
418 GAsyncResult *res,
419 gpointer user_data)
421 TestMultiSpliceData *data = user_data;
423 if (!data->caught_error)
425 if (g_output_stream_splice_finish ((GOutputStream*)obj, res, &data->error) < 0)
426 data->caught_error = TRUE;
429 data->events_pending--;
430 if (data->events_pending == 0)
431 g_main_loop_quit (data->loop);
434 static gboolean
435 on_idle_multisplice (gpointer user_data)
437 TestMultiSpliceData *data = user_data;
439 /* We write 2^1 + 2^2 ... + 2^10 or 2047 copies of "Hello World!\n"
440 * ultimately
442 if (data->counter >= 2047 || data->caught_error)
444 if (!g_output_stream_close (data->first_stdin, NULL, &data->error))
445 data->caught_error = TRUE;
446 data->events_pending--;
447 if (data->events_pending == 0)
449 g_main_loop_quit (data->loop);
451 return FALSE;
453 else
455 int i;
456 for (i = 0; i < data->counter; i++)
458 gsize bytes_written;
459 if (!g_output_stream_write_all (data->first_stdin, "hello world!\n",
460 strlen ("hello world!\n"), &bytes_written,
461 NULL, &data->error))
463 data->caught_error = TRUE;
464 return FALSE;
467 data->counter *= 2;
468 return TRUE;
472 static void
473 on_subprocess_exited (GObject *object,
474 GAsyncResult *result,
475 gpointer user_data)
477 GSubprocess *subprocess = G_SUBPROCESS (object);
478 TestMultiSpliceData *data = user_data;
479 GError *error = NULL;
481 if (!g_subprocess_wait_finish (subprocess, result, &error))
483 if (!data->caught_error)
485 data->caught_error = TRUE;
486 g_propagate_error (&data->error, error);
489 g_spawn_check_exit_status (g_subprocess_get_exit_status (subprocess), &error);
490 g_assert_no_error (error);
491 data->events_pending--;
492 if (data->events_pending == 0)
493 g_main_loop_quit (data->loop);
496 static void
497 test_multi_1 (void)
499 GError *local_error = NULL;
500 GError **error = &local_error;
501 GPtrArray *args;
502 GSubprocessLauncher *launcher;
503 GSubprocess *first;
504 GSubprocess *second;
505 GSubprocess *third;
506 GOutputStream *first_stdin;
507 GInputStream *first_stdout;
508 GOutputStream *second_stdin;
509 GInputStream *second_stdout;
510 GOutputStream *third_stdin;
511 GInputStream *third_stdout;
512 GOutputStream *membuf;
513 TestMultiSpliceData data;
514 int splice_flags = G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET;
516 args = get_test_subprocess_args ("cat", NULL);
517 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE);
518 first = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
519 g_assert_no_error (local_error);
520 second = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
521 g_assert_no_error (local_error);
522 third = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
523 g_assert_no_error (local_error);
525 g_ptr_array_free (args, TRUE);
527 membuf = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
529 first_stdin = g_subprocess_get_stdin_pipe (first);
530 first_stdout = g_subprocess_get_stdout_pipe (first);
531 second_stdin = g_subprocess_get_stdin_pipe (second);
532 second_stdout = g_subprocess_get_stdout_pipe (second);
533 third_stdin = g_subprocess_get_stdin_pipe (third);
534 third_stdout = g_subprocess_get_stdout_pipe (third);
536 memset (&data, 0, sizeof (data));
537 data.loop = g_main_loop_new (NULL, TRUE);
538 data.counter = 1;
539 data.first_stdin = first_stdin;
541 data.events_pending++;
542 g_output_stream_splice_async (second_stdin, first_stdout, splice_flags, G_PRIORITY_DEFAULT,
543 NULL, on_one_multi_splice_done, &data);
544 data.events_pending++;
545 g_output_stream_splice_async (third_stdin, second_stdout, splice_flags, G_PRIORITY_DEFAULT,
546 NULL, on_one_multi_splice_done, &data);
547 data.events_pending++;
548 g_output_stream_splice_async (membuf, third_stdout, splice_flags, G_PRIORITY_DEFAULT,
549 NULL, on_one_multi_splice_done, &data);
551 data.events_pending++;
552 g_timeout_add (250, on_idle_multisplice, &data);
554 data.events_pending++;
555 g_subprocess_wait_async (first, NULL, on_subprocess_exited, &data);
556 data.events_pending++;
557 g_subprocess_wait_async (second, NULL, on_subprocess_exited, &data);
558 data.events_pending++;
559 g_subprocess_wait_async (third, NULL, on_subprocess_exited, &data);
561 g_main_loop_run (data.loop);
563 g_assert (!data.caught_error);
564 g_assert_no_error (data.error);
566 g_assert_cmpint (g_memory_output_stream_get_data_size ((GMemoryOutputStream*)membuf), ==, 26611);
568 g_main_loop_unref (data.loop);
569 g_object_unref (membuf);
570 g_object_unref (launcher);
571 g_object_unref (first);
572 g_object_unref (second);
573 g_object_unref (third);
576 typedef struct {
577 gboolean is_utf8;
578 gboolean running;
579 GError *error;
580 } TestAsyncCommunicateData;
582 static void
583 on_communicate_complete (GObject *proc,
584 GAsyncResult *result,
585 gpointer user_data)
587 TestAsyncCommunicateData *data = user_data;
588 GBytes *stdout = NULL;
589 char *stdout_str = NULL;
590 const guint8 *stdout_data;
591 gsize stdout_len;
593 data->running = FALSE;
594 if (data->is_utf8)
595 (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
596 &stdout_str, NULL, &data->error);
597 else
598 (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
599 &stdout, NULL, &data->error);
600 if (data->error)
601 return;
603 if (!data->is_utf8)
605 g_assert (stdout != NULL);
606 stdout_data = g_bytes_get_data (stdout, &stdout_len);
608 else
610 g_assert (stdout_str != NULL);
611 stdout_data = (guint8*)stdout_str;
612 stdout_len = strlen (stdout_str);
615 g_assert_cmpmem (stdout_data, stdout_len, "hello world", 11);
616 if (stdout)
617 g_bytes_unref (stdout);
618 g_free (stdout_str);
621 static void
622 test_communicate_async (void)
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;
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);
639 hellostring = "hello world";
640 input = g_bytes_new_static (hellostring, strlen (hellostring));
642 g_subprocess_communicate_async (proc, input,
643 cancellable,
644 on_communicate_complete,
645 &data);
647 data.running = TRUE;
648 while (data.running)
649 g_main_context_iteration (NULL, TRUE);
651 g_assert_no_error (data.error);
653 g_bytes_unref (input);
654 g_object_unref (proc);
657 static void
658 test_communicate (void)
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;
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);
679 hellostring = "hello world";
680 input = g_bytes_new_static (hellostring, strlen (hellostring));
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);
686 g_assert_cmpmem (stdout_data, stdout_len, "hello world", 11);
687 g_bytes_unref (stdout);
689 g_bytes_unref (input);
690 g_bytes_unref (stdout);
691 g_object_unref (proc);
694 static void
695 test_communicate_utf8_async (void)
697 GError *error = NULL;
698 GPtrArray *args;
699 TestAsyncCommunicateData data = { 0, };
700 GSubprocess *proc;
701 GCancellable *cancellable = NULL;
703 args = get_test_subprocess_args ("cat", NULL);
704 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
705 G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
706 &error);
707 g_assert_no_error (error);
708 g_ptr_array_free (args, TRUE);
710 data.is_utf8 = TRUE;
711 g_subprocess_communicate_utf8_async (proc, "hello world",
712 cancellable,
713 on_communicate_complete,
714 &data);
716 data.running = TRUE;
717 while (data.running)
718 g_main_context_iteration (NULL, TRUE);
720 g_assert_no_error (data.error);
722 g_object_unref (proc);
725 static void
726 test_communicate_utf8 (void)
728 GError *error = NULL;
729 GPtrArray *args;
730 GSubprocess *proc;
731 GCancellable *cancellable = NULL;
732 const gchar *stdin_buf;
733 gchar *stdout_buf;
735 args = get_test_subprocess_args ("cat", NULL);
736 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
737 G_SUBPROCESS_FLAGS_STDIN_PIPE
738 | G_SUBPROCESS_FLAGS_STDOUT_PIPE
739 | G_SUBPROCESS_FLAGS_STDERR_MERGE,
740 &error);
741 g_assert_no_error (error);
742 g_ptr_array_free (args, TRUE);
744 stdin_buf = "hello world";
746 g_subprocess_communicate_utf8 (proc, stdin_buf, cancellable, &stdout_buf, NULL, &error);
747 g_assert_no_error (error);
749 g_assert (strcmp (stdout_buf, "hello world") == 0);
750 g_free (stdout_buf);
752 g_object_unref (proc);
755 static void
756 test_communicate_nothing (void)
758 GError *error = NULL;
759 GPtrArray *args;
760 GSubprocess *proc;
761 GCancellable *cancellable = NULL;
762 gchar *stdout_buf;
764 args = get_test_subprocess_args ("cat", NULL);
765 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
766 G_SUBPROCESS_FLAGS_STDIN_PIPE
767 | G_SUBPROCESS_FLAGS_STDOUT_PIPE
768 | G_SUBPROCESS_FLAGS_STDERR_MERGE,
769 &error);
770 g_assert_no_error (error);
771 g_ptr_array_free (args, TRUE);
773 g_subprocess_communicate_utf8 (proc, "", cancellable, &stdout_buf, NULL, &error);
774 g_assert_no_error (error);
776 g_assert_cmpstr (stdout_buf, ==, "");
778 g_free (stdout_buf);
780 g_object_unref (proc);
783 static void
784 test_communicate_utf8_invalid (void)
786 GError *error = NULL;
787 GPtrArray *args;
788 TestAsyncCommunicateData data = { 0, };
789 GSubprocess *proc;
790 GCancellable *cancellable = NULL;
792 args = get_test_subprocess_args ("cat", NULL);
793 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
794 G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
795 &error);
796 g_assert_no_error (error);
797 g_ptr_array_free (args, TRUE);
799 data.is_utf8 = TRUE;
800 g_subprocess_communicate_utf8_async (proc, "\xFF\xFF",
801 cancellable,
802 on_communicate_complete,
803 &data);
805 data.running = TRUE;
806 while (data.running)
807 g_main_context_iteration (NULL, TRUE);
809 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_FAILED);
810 g_error_free (data.error);
812 g_object_unref (proc);
815 static gboolean
816 send_terminate (gpointer user_data)
818 GSubprocess *proc = user_data;
820 g_subprocess_force_exit (proc);
822 return FALSE;
825 static void
826 on_request_quit_exited (GObject *object,
827 GAsyncResult *result,
828 gpointer user_data)
830 GSubprocess *subprocess = G_SUBPROCESS (object);
831 GError *error = NULL;
833 g_subprocess_wait_finish (subprocess, result, &error);
834 g_assert_no_error (error);
835 #ifdef G_OS_UNIX
836 g_assert (g_subprocess_get_if_signaled (subprocess));
837 g_assert (g_subprocess_get_term_sig (subprocess) == 9);
838 #endif
839 g_spawn_check_exit_status (g_subprocess_get_status (subprocess), &error);
840 g_assert (error != NULL);
841 g_clear_error (&error);
843 g_main_loop_quit ((GMainLoop*)user_data);
846 static void
847 test_terminate (void)
849 GError *local_error = NULL;
850 GError **error = &local_error;
851 GSubprocess *proc;
852 GPtrArray *args;
853 GMainLoop *loop;
855 args = get_test_subprocess_args ("sleep-forever", NULL);
856 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
857 g_ptr_array_free (args, TRUE);
858 g_assert_no_error (local_error);
860 loop = g_main_loop_new (NULL, TRUE);
862 g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
864 g_timeout_add_seconds (3, send_terminate, proc);
866 g_main_loop_run (loop);
868 g_main_loop_unref (loop);
869 g_object_unref (proc);
872 #ifdef G_OS_UNIX
873 static gboolean
874 send_signal (gpointer user_data)
876 GSubprocess *proc = user_data;
878 g_subprocess_send_signal (proc, SIGKILL);
880 return FALSE;
883 static void
884 test_signal (void)
886 GError *local_error = NULL;
887 GError **error = &local_error;
888 GSubprocess *proc;
889 GPtrArray *args;
890 GMainLoop *loop;
892 args = get_test_subprocess_args ("sleep-forever", NULL);
893 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
894 g_ptr_array_free (args, TRUE);
895 g_assert_no_error (local_error);
897 loop = g_main_loop_new (NULL, TRUE);
899 g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
901 g_timeout_add_seconds (3, send_signal, proc);
903 g_main_loop_run (loop);
905 g_main_loop_unref (loop);
906 g_object_unref (proc);
908 #endif
910 static void
911 test_env (void)
913 GError *local_error = NULL;
914 GError **error = &local_error;
915 GSubprocessLauncher *launcher;
916 GSubprocess *proc;
917 GPtrArray *args;
918 GInputStream *stdout;
919 gchar *result;
920 gchar *envp[] = { "ONE=1", "TWO=1", "THREE=3", "FOUR=1", NULL };
921 gchar **split;
923 args = get_test_subprocess_args ("env", NULL);
924 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
925 g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
926 g_subprocess_launcher_set_environ (launcher, envp);
927 g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
928 g_subprocess_launcher_setenv (launcher, "THREE", "1", FALSE);
929 g_subprocess_launcher_unsetenv (launcher, "FOUR");
931 g_assert_null (g_subprocess_launcher_getenv (launcher, "FOUR"));
933 proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
934 g_ptr_array_free (args, TRUE);
935 g_assert_no_error (local_error);
937 stdout = g_subprocess_get_stdout_pipe (proc);
939 result = splice_to_string (stdout, error);
940 split = g_strsplit (result, "\n", -1);
941 g_assert_cmpstr (g_environ_getenv (split, "ONE"), ==, "1");
942 g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
943 g_assert_cmpstr (g_environ_getenv (split, "THREE"), ==, "3");
944 g_assert_null (g_environ_getenv (split, "FOUR"));
946 g_strfreev (split);
947 g_free (result);
948 g_object_unref (proc);
951 static void
952 test_cwd (void)
954 GError *local_error = NULL;
955 GError **error = &local_error;
956 GSubprocessLauncher *launcher;
957 GSubprocess *proc;
958 GPtrArray *args;
959 GInputStream *stdout;
960 gchar *result;
961 const char *basename;
963 args = get_test_subprocess_args ("cwd", NULL);
964 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
965 g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
966 g_subprocess_launcher_set_cwd (launcher, "/tmp");
968 proc = g_subprocess_launcher_spawnv (launcher, (const char * const *)args->pdata, error);
969 g_ptr_array_free (args, TRUE);
970 g_assert_no_error (local_error);
972 stdout = g_subprocess_get_stdout_pipe (proc);
974 result = splice_to_string (stdout, error);
976 basename = g_strrstr (result, "/");
977 g_assert (basename != NULL);
978 g_assert_cmpstr (basename, ==, "/tmp" LINEEND);
980 g_free (result);
981 g_object_unref (proc);
983 #ifdef G_OS_UNIX
984 static void
985 test_stdout_file (void)
987 GError *local_error = NULL;
988 GError **error = &local_error;
989 GSubprocessLauncher *launcher;
990 GSubprocess *proc;
991 GPtrArray *args;
992 GFile *tmpfile;
993 GFileIOStream *iostream;
994 GOutputStream *stdin;
995 const char *test_data = "this is some test data\n";
996 char *tmp_contents;
997 char *tmp_file_path;
999 tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1000 g_assert_no_error (local_error);
1001 g_clear_object (&iostream);
1003 tmp_file_path = g_file_get_path (tmpfile);
1005 args = get_test_subprocess_args ("cat", NULL);
1006 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1007 g_subprocess_launcher_set_stdout_file_path (launcher, tmp_file_path);
1008 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1009 g_ptr_array_free (args, TRUE);
1010 g_assert_no_error (local_error);
1012 stdin = g_subprocess_get_stdin_pipe (proc);
1014 g_output_stream_write_all (stdin, test_data, strlen (test_data), NULL, NULL, error);
1015 g_assert_no_error (local_error);
1017 g_output_stream_close (stdin, NULL, error);
1018 g_assert_no_error (local_error);
1020 g_subprocess_wait_check (proc, NULL, error);
1022 g_object_unref (launcher);
1023 g_object_unref (proc);
1025 g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1026 g_assert_no_error (local_error);
1028 g_assert_cmpstr (test_data, ==, tmp_contents);
1029 g_free (tmp_contents);
1031 (void) g_file_delete (tmpfile, NULL, NULL);
1032 g_object_unref (tmpfile);
1033 g_free (tmp_file_path);
1036 static void
1037 test_stdout_fd (void)
1039 GError *local_error = NULL;
1040 GError **error = &local_error;
1041 GSubprocessLauncher *launcher;
1042 GSubprocess *proc;
1043 GPtrArray *args;
1044 GFile *tmpfile;
1045 GFileIOStream *iostream;
1046 GFileDescriptorBased *descriptor_stream;
1047 GOutputStream *stdin;
1048 const char *test_data = "this is some test data\n";
1049 char *tmp_contents;
1051 tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1052 g_assert_no_error (local_error);
1054 args = get_test_subprocess_args ("cat", NULL);
1055 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1056 descriptor_stream = G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream)));
1057 g_subprocess_launcher_take_stdout_fd (launcher, dup (g_file_descriptor_based_get_fd (descriptor_stream)));
1058 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1059 g_ptr_array_free (args, TRUE);
1060 g_assert_no_error (local_error);
1062 g_clear_object (&iostream);
1064 stdin = g_subprocess_get_stdin_pipe (proc);
1066 g_output_stream_write_all (stdin, test_data, strlen (test_data), NULL, NULL, error);
1067 g_assert_no_error (local_error);
1069 g_output_stream_close (stdin, NULL, error);
1070 g_assert_no_error (local_error);
1072 g_subprocess_wait_check (proc, NULL, error);
1074 g_object_unref (launcher);
1075 g_object_unref (proc);
1077 g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1078 g_assert_no_error (local_error);
1080 g_assert_cmpstr (test_data, ==, tmp_contents);
1081 g_free (tmp_contents);
1083 (void) g_file_delete (tmpfile, NULL, NULL);
1084 g_object_unref (tmpfile);
1087 static void
1088 child_setup (gpointer user_data)
1090 dup2 (GPOINTER_TO_INT (user_data), 1);
1093 static void
1094 test_child_setup (void)
1096 GError *local_error = NULL;
1097 GError **error = &local_error;
1098 GSubprocessLauncher *launcher;
1099 GSubprocess *proc;
1100 GPtrArray *args;
1101 GFile *tmpfile;
1102 GFileIOStream *iostream;
1103 GOutputStream *stdin;
1104 const char *test_data = "this is some test data\n";
1105 char *tmp_contents;
1106 int fd;
1108 tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1109 g_assert_no_error (local_error);
1111 fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream))));
1113 args = get_test_subprocess_args ("cat", NULL);
1114 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1115 g_subprocess_launcher_set_child_setup (launcher, child_setup, GINT_TO_POINTER (fd), NULL);
1116 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1117 g_ptr_array_free (args, TRUE);
1118 g_assert_no_error (local_error);
1120 g_clear_object (&iostream);
1122 stdin = g_subprocess_get_stdin_pipe (proc);
1124 g_output_stream_write_all (stdin, test_data, strlen (test_data), NULL, NULL, error);
1125 g_assert_no_error (local_error);
1127 g_output_stream_close (stdin, NULL, error);
1128 g_assert_no_error (local_error);
1130 g_subprocess_wait_check (proc, NULL, error);
1132 g_object_unref (launcher);
1133 g_object_unref (proc);
1135 g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1136 g_assert_no_error (local_error);
1138 g_assert_cmpstr (test_data, ==, tmp_contents);
1139 g_free (tmp_contents);
1141 (void) g_file_delete (tmpfile, NULL, NULL);
1142 g_object_unref (tmpfile);
1145 static void
1146 test_pass_fd (void)
1148 GError *local_error = NULL;
1149 GError **error = &local_error;
1150 GInputStream *child_input;
1151 GDataInputStream *child_datainput;
1152 GSubprocessLauncher *launcher;
1153 GSubprocess *proc;
1154 GPtrArray *args;
1155 int basic_pipefds[2];
1156 int needdup_pipefds[2];
1157 char *buf;
1158 gsize len;
1159 char *basic_fd_str;
1160 char *needdup_fd_str;
1162 g_unix_open_pipe (basic_pipefds, FD_CLOEXEC, error);
1163 g_assert_no_error (local_error);
1164 g_unix_open_pipe (needdup_pipefds, FD_CLOEXEC, error);
1165 g_assert_no_error (local_error);
1167 basic_fd_str = g_strdup_printf ("%d", basic_pipefds[1]);
1168 needdup_fd_str = g_strdup_printf ("%d", needdup_pipefds[1] + 1);
1170 args = get_test_subprocess_args ("write-to-fds", basic_fd_str, needdup_fd_str, NULL);
1171 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1172 g_subprocess_launcher_take_fd (launcher, basic_pipefds[1], basic_pipefds[1]);
1173 g_subprocess_launcher_take_fd (launcher, needdup_pipefds[1], needdup_pipefds[1] + 1);
1174 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1175 g_ptr_array_free (args, TRUE);
1176 g_assert_no_error (local_error);
1178 g_free (basic_fd_str);
1179 g_free (needdup_fd_str);
1181 child_input = g_unix_input_stream_new (basic_pipefds[0], TRUE);
1182 child_datainput = g_data_input_stream_new (child_input);
1183 buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1184 g_assert_no_error (local_error);
1185 g_assert_cmpstr (buf, ==, "hello world");
1186 g_object_unref (child_datainput);
1187 g_object_unref (child_input);
1188 g_free (buf);
1190 child_input = g_unix_input_stream_new (needdup_pipefds[0], TRUE);
1191 child_datainput = g_data_input_stream_new (child_input);
1192 buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1193 g_assert_no_error (local_error);
1194 g_assert_cmpstr (buf, ==, "hello world");
1195 g_free (buf);
1196 g_object_unref (child_datainput);
1197 g_object_unref (child_input);
1199 g_object_unref (launcher);
1200 g_object_unref (proc);
1203 #endif
1205 static void
1206 test_launcher_environment (void)
1208 GSubprocessLauncher *launcher;
1209 GError *error = NULL;
1210 GSubprocess *proc;
1211 GPtrArray *args;
1212 gchar *out;
1214 g_setenv ("A", "B", TRUE);
1215 g_setenv ("C", "D", TRUE);
1217 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1219 /* unset a variable */
1220 g_subprocess_launcher_unsetenv (launcher, "A");
1222 /* and set a diffferent one */
1223 g_subprocess_launcher_setenv (launcher, "E", "F", TRUE);
1225 args = get_test_subprocess_args ("printenv", "A", "C", "E", NULL);
1226 proc = g_subprocess_launcher_spawnv (launcher, (const gchar **) args->pdata, &error);
1227 g_assert_no_error (error);
1228 g_assert (proc);
1230 g_subprocess_communicate_utf8 (proc, NULL, NULL, &out, NULL, &error);
1231 g_assert_no_error (error);
1233 g_assert_cmpstr (out, ==, "C=D\nE=F\n");
1234 g_free (out);
1236 g_object_unref (proc);
1240 main (int argc, char **argv)
1242 g_test_init (&argc, &argv, NULL);
1244 g_test_add_func ("/gsubprocess/noop", test_noop);
1245 g_test_add_func ("/gsubprocess/noop-all-to-null", test_noop_all_to_null);
1246 g_test_add_func ("/gsubprocess/noop-no-wait", test_noop_no_wait);
1247 g_test_add_func ("/gsubprocess/noop-stdin-inherit", test_noop_stdin_inherit);
1248 #ifdef G_OS_UNIX
1249 g_test_add_func ("/gsubprocess/search-path", test_search_path);
1250 g_test_add_func ("/gsubprocess/signal", test_signal);
1251 #endif
1252 g_test_add_func ("/gsubprocess/exit1", test_exit1);
1253 g_test_add_func ("/gsubprocess/echo1", test_echo1);
1254 #ifdef G_OS_UNIX
1255 g_test_add_func ("/gsubprocess/echo-merged", test_echo_merged);
1256 #endif
1257 g_test_add_func ("/gsubprocess/cat-utf8", test_cat_utf8);
1258 g_test_add_func ("/gsubprocess/cat-eof", test_cat_eof);
1259 g_test_add_func ("/gsubprocess/multi1", test_multi_1);
1260 g_test_add_func ("/gsubprocess/communicate", test_communicate);
1261 g_test_add_func ("/gsubprocess/communicate-async", test_communicate_async);
1262 g_test_add_func ("/gsubprocess/communicate-utf8", test_communicate_utf8);
1263 g_test_add_func ("/gsubprocess/communicate-utf8-async", test_communicate_utf8_async);
1264 g_test_add_func ("/gsubprocess/communicate-utf8-invalid", test_communicate_utf8_invalid);
1265 g_test_add_func ("/gsubprocess/communicate-nothing", test_communicate_nothing);
1266 g_test_add_func ("/gsubprocess/terminate", test_terminate);
1267 g_test_add_func ("/gsubprocess/env", test_env);
1268 g_test_add_func ("/gsubprocess/cwd", test_cwd);
1269 #ifdef G_OS_UNIX
1270 g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file);
1271 g_test_add_func ("/gsubprocess/stdout-fd", test_stdout_fd);
1272 g_test_add_func ("/gsubprocess/child-setup", test_child_setup);
1273 g_test_add_func ("/gsubprocess/pass-fd", test_pass_fd);
1274 #endif
1275 g_test_add_func ("/gsubprocess/launcher-environment", test_launcher_environment);
1277 return g_test_run ();