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 /* We write 2^1 + 2^2 ... + 2^10 or 2047 copies of "Hello World!\n"
12 * ultimately
13 */
14 #define TOTAL_HELLOS 2047
15 #define HELLO_WORLD "hello world!\n"
16
17 #ifdef G_OS_WIN32
18 #define LINEEND "\r\n"
19 #define EXEEXT ".exe"
20 #define SPLICELEN (TOTAL_HELLOS * (strlen (HELLO_WORLD) + 1)) /* because \r */
21 #else
22 #define LINEEND "\n"
23 #define EXEEXT
24 #define SPLICELEN (TOTAL_HELLOS * strlen (HELLO_WORLD))
25 #endif
26
27 static GPtrArray *
28 get_test_subprocess_args (const char *mode,
29 ...) G_GNUC_NULL_TERMINATED;
30
31 static GPtrArray *
get_test_subprocess_args(const char * mode,...)32 get_test_subprocess_args (const char *mode,
33 ...)
34 {
35 GPtrArray *ret;
36 char *path;
37 const char *binname;
38 va_list args;
39 gpointer arg;
40
41 ret = g_ptr_array_new_with_free_func (g_free);
42
43 #ifdef G_OS_WIN32
44 binname = "gsubprocess-testprog.exe";
45 #else
46 binname = "gsubprocess-testprog";
47 #endif
48
49 path = g_test_build_filename (G_TEST_BUILT, binname, NULL);
50 g_ptr_array_add (ret, path);
51 g_ptr_array_add (ret, g_strdup (mode));
52
53 va_start (args, mode);
54 while ((arg = va_arg (args, gpointer)) != NULL)
55 g_ptr_array_add (ret, g_strdup (arg));
56 va_end (args);
57
58 g_ptr_array_add (ret, NULL);
59 return ret;
60 }
61
62 static void
test_noop(void)63 test_noop (void)
64 {
65 GError *local_error = NULL;
66 GError **error = &local_error;
67 GPtrArray *args;
68 GSubprocess *proc;
69
70 args = get_test_subprocess_args ("noop", NULL);
71 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
72 g_ptr_array_free (args, TRUE);
73 g_assert_no_error (local_error);
74
75 g_subprocess_wait_check (proc, NULL, error);
76 g_assert_no_error (local_error);
77 g_assert_true (g_subprocess_get_successful (proc));
78
79 g_object_unref (proc);
80 }
81
82 static void
check_ready(GObject * source,GAsyncResult * res,gpointer user_data)83 check_ready (GObject *source,
84 GAsyncResult *res,
85 gpointer user_data)
86 {
87 gboolean ret;
88 GError *error = NULL;
89
90 ret = g_subprocess_wait_check_finish (G_SUBPROCESS (source),
91 res,
92 &error);
93 g_assert_true (ret);
94 g_assert_no_error (error);
95
96 g_object_unref (source);
97 }
98
99 static void
test_noop_all_to_null(void)100 test_noop_all_to_null (void)
101 {
102 GError *local_error = NULL;
103 GError **error = &local_error;
104 GPtrArray *args;
105 GSubprocess *proc;
106
107 args = get_test_subprocess_args ("noop", NULL);
108 proc = g_subprocess_newv ((const gchar * const *) args->pdata,
109 G_SUBPROCESS_FLAGS_STDOUT_SILENCE | G_SUBPROCESS_FLAGS_STDERR_SILENCE,
110 error);
111 g_ptr_array_free (args, TRUE);
112 g_assert_no_error (local_error);
113
114 g_subprocess_wait_check_async (proc, NULL, check_ready, NULL);
115 }
116
117 static void
test_noop_no_wait(void)118 test_noop_no_wait (void)
119 {
120 GError *local_error = NULL;
121 GError **error = &local_error;
122 GPtrArray *args;
123 GSubprocess *proc;
124
125 args = get_test_subprocess_args ("noop", NULL);
126 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
127 g_ptr_array_free (args, TRUE);
128 g_assert_no_error (local_error);
129
130 g_object_unref (proc);
131 }
132
133 static void
test_noop_stdin_inherit(void)134 test_noop_stdin_inherit (void)
135 {
136 GError *local_error = NULL;
137 GError **error = &local_error;
138 GPtrArray *args;
139 GSubprocess *proc;
140
141 args = get_test_subprocess_args ("noop", NULL);
142 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDIN_INHERIT, error);
143 g_ptr_array_free (args, TRUE);
144 g_assert_no_error (local_error);
145
146 g_subprocess_wait_check (proc, NULL, error);
147 g_assert_no_error (local_error);
148
149 g_object_unref (proc);
150 }
151
152 #ifdef G_OS_UNIX
153 static void
test_search_path(void)154 test_search_path (void)
155 {
156 GError *local_error = NULL;
157 GError **error = &local_error;
158 GSubprocess *proc;
159
160 proc = g_subprocess_new (G_SUBPROCESS_FLAGS_NONE, error, "true", NULL);
161 g_assert_no_error (local_error);
162
163 g_subprocess_wait_check (proc, NULL, error);
164 g_assert_no_error (local_error);
165
166 g_object_unref (proc);
167 }
168 #endif
169
170 static void
test_exit1(void)171 test_exit1 (void)
172 {
173 GError *local_error = NULL;
174 GError **error = &local_error;
175 GPtrArray *args;
176 GSubprocess *proc;
177
178 args = get_test_subprocess_args ("exit1", NULL);
179 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
180 g_ptr_array_free (args, TRUE);
181 g_assert_no_error (local_error);
182
183 g_subprocess_wait_check (proc, NULL, error);
184 g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
185 g_clear_error (error);
186
187 g_object_unref (proc);
188 }
189
190 typedef struct {
191 GMainLoop *loop;
192 GCancellable *cancellable;
193 gboolean cb_called;
194 } TestExit1CancelData;
195
196 static gboolean
test_exit1_cancel_idle_quit_cb(gpointer user_data)197 test_exit1_cancel_idle_quit_cb (gpointer user_data)
198 {
199 GMainLoop *loop = user_data;
200 g_main_loop_quit (loop);
201 return G_SOURCE_REMOVE;
202 }
203
204 static void
test_exit1_cancel_wait_check_cb(GObject * source,GAsyncResult * result,gpointer user_data)205 test_exit1_cancel_wait_check_cb (GObject *source,
206 GAsyncResult *result,
207 gpointer user_data)
208 {
209 GSubprocess *subprocess = G_SUBPROCESS (source);
210 TestExit1CancelData *data = user_data;
211 gboolean ret;
212 GError *error = NULL;
213
214 g_assert_false (data->cb_called);
215 data->cb_called = TRUE;
216
217 ret = g_subprocess_wait_check_finish (subprocess, result, &error);
218 g_assert_false (ret);
219 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
220 g_clear_error (&error);
221
222 g_idle_add (test_exit1_cancel_idle_quit_cb, data->loop);
223 }
224
225 static void
test_exit1_cancel(void)226 test_exit1_cancel (void)
227 {
228 GError *local_error = NULL;
229 GError **error = &local_error;
230 GPtrArray *args;
231 GSubprocess *proc;
232 TestExit1CancelData data = { 0 };
233
234 g_test_bug ("786456");
235
236 args = get_test_subprocess_args ("exit1", NULL);
237 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
238 g_ptr_array_free (args, TRUE);
239 g_assert_no_error (local_error);
240
241 data.loop = g_main_loop_new (NULL, FALSE);
242 data.cancellable = g_cancellable_new ();
243 g_subprocess_wait_check_async (proc, data.cancellable, test_exit1_cancel_wait_check_cb, &data);
244
245 g_subprocess_wait_check (proc, NULL, error);
246 g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
247 g_clear_error (error);
248
249 g_cancellable_cancel (data.cancellable);
250 g_main_loop_run (data.loop);
251
252 g_object_unref (proc);
253 g_main_loop_unref (data.loop);
254 g_clear_object (&data.cancellable);
255 }
256
257 static void
test_exit1_cancel_in_cb_wait_check_cb(GObject * source,GAsyncResult * result,gpointer user_data)258 test_exit1_cancel_in_cb_wait_check_cb (GObject *source,
259 GAsyncResult *result,
260 gpointer user_data)
261 {
262 GSubprocess *subprocess = G_SUBPROCESS (source);
263 TestExit1CancelData *data = user_data;
264 gboolean ret;
265 GError *error = NULL;
266
267 g_assert_false (data->cb_called);
268 data->cb_called = TRUE;
269
270 ret = g_subprocess_wait_check_finish (subprocess, result, &error);
271 g_assert_false (ret);
272 g_assert_error (error, G_SPAWN_EXIT_ERROR, 1);
273 g_clear_error (&error);
274
275 g_cancellable_cancel (data->cancellable);
276
277 g_idle_add (test_exit1_cancel_idle_quit_cb, data->loop);
278 }
279
280 static void
test_exit1_cancel_in_cb(void)281 test_exit1_cancel_in_cb (void)
282 {
283 GError *local_error = NULL;
284 GError **error = &local_error;
285 GPtrArray *args;
286 GSubprocess *proc;
287 TestExit1CancelData data = { 0 };
288
289 g_test_bug ("786456");
290
291 args = get_test_subprocess_args ("exit1", NULL);
292 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
293 g_ptr_array_free (args, TRUE);
294 g_assert_no_error (local_error);
295
296 data.loop = g_main_loop_new (NULL, FALSE);
297 data.cancellable = g_cancellable_new ();
298 g_subprocess_wait_check_async (proc, data.cancellable, test_exit1_cancel_in_cb_wait_check_cb, &data);
299
300 g_subprocess_wait_check (proc, NULL, error);
301 g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
302 g_clear_error (error);
303
304 g_main_loop_run (data.loop);
305
306 g_object_unref (proc);
307 g_main_loop_unref (data.loop);
308 g_clear_object (&data.cancellable);
309 }
310
311 static gchar *
splice_to_string(GInputStream * stream,GError ** error)312 splice_to_string (GInputStream *stream,
313 GError **error)
314 {
315 GMemoryOutputStream *buffer = NULL;
316 char *ret = NULL;
317
318 buffer = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
319 if (g_output_stream_splice ((GOutputStream*)buffer, stream, 0, NULL, error) < 0)
320 goto out;
321
322 if (!g_output_stream_write ((GOutputStream*)buffer, "\0", 1, NULL, error))
323 goto out;
324
325 if (!g_output_stream_close ((GOutputStream*)buffer, NULL, error))
326 goto out;
327
328 ret = g_memory_output_stream_steal_data (buffer);
329 out:
330 g_clear_object (&buffer);
331 return ret;
332 }
333
334 static void
test_echo1(void)335 test_echo1 (void)
336 {
337 GError *local_error = NULL;
338 GError **error = &local_error;
339 GSubprocess *proc;
340 GPtrArray *args;
341 GInputStream *stdout_stream;
342 gchar *result;
343
344 args = get_test_subprocess_args ("echo", "hello", "world!", NULL);
345 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDOUT_PIPE, error);
346 g_ptr_array_free (args, TRUE);
347 g_assert_no_error (local_error);
348
349 stdout_stream = g_subprocess_get_stdout_pipe (proc);
350
351 result = splice_to_string (stdout_stream, error);
352 g_assert_no_error (local_error);
353
354 g_assert_cmpstr (result, ==, "hello" LINEEND "world!" LINEEND);
355
356 g_free (result);
357 g_object_unref (proc);
358 }
359
360 #ifdef G_OS_UNIX
361 static void
test_echo_merged(void)362 test_echo_merged (void)
363 {
364 GError *local_error = NULL;
365 GError **error = &local_error;
366 GSubprocess *proc;
367 GPtrArray *args;
368 GInputStream *stdout_stream;
369 gchar *result;
370
371 args = get_test_subprocess_args ("echo-stdout-and-stderr", "merge", "this", NULL);
372 proc = g_subprocess_newv ((const gchar * const *) args->pdata,
373 G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_MERGE,
374 error);
375 g_ptr_array_free (args, TRUE);
376 g_assert_no_error (local_error);
377
378 stdout_stream = g_subprocess_get_stdout_pipe (proc);
379 result = splice_to_string (stdout_stream, error);
380 g_assert_no_error (local_error);
381
382 g_assert_cmpstr (result, ==, "merge\nmerge\nthis\nthis\n");
383
384 g_free (result);
385 g_object_unref (proc);
386 }
387 #endif
388
389 typedef struct {
390 guint events_pending;
391 GMainLoop *loop;
392 } TestCatData;
393
394 static void
test_cat_on_input_splice_complete(GObject * object,GAsyncResult * result,gpointer user_data)395 test_cat_on_input_splice_complete (GObject *object,
396 GAsyncResult *result,
397 gpointer user_data)
398 {
399 TestCatData *data = user_data;
400 GError *error = NULL;
401
402 (void)g_output_stream_splice_finish ((GOutputStream*)object, result, &error);
403 g_assert_no_error (error);
404
405 data->events_pending--;
406 if (data->events_pending == 0)
407 g_main_loop_quit (data->loop);
408 }
409
410 static void
test_cat_utf8(void)411 test_cat_utf8 (void)
412 {
413 GError *local_error = NULL;
414 GError **error = &local_error;
415 GSubprocess *proc;
416 GPtrArray *args;
417 GBytes *input_buf;
418 GBytes *output_buf;
419 GInputStream *input_buf_stream = NULL;
420 GOutputStream *output_buf_stream = NULL;
421 GOutputStream *stdin_stream = NULL;
422 GInputStream *stdout_stream = NULL;
423 TestCatData data;
424
425 memset (&data, 0, sizeof (data));
426 data.loop = g_main_loop_new (NULL, TRUE);
427
428 args = get_test_subprocess_args ("cat", NULL);
429 proc = g_subprocess_newv ((const gchar * const *) args->pdata,
430 G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
431 error);
432 g_ptr_array_free (args, TRUE);
433 g_assert_no_error (local_error);
434
435 stdin_stream = g_subprocess_get_stdin_pipe (proc);
436 stdout_stream = g_subprocess_get_stdout_pipe (proc);
437
438 input_buf = g_bytes_new_static ("hello, world!", strlen ("hello, world!"));
439 input_buf_stream = g_memory_input_stream_new_from_bytes (input_buf);
440 g_bytes_unref (input_buf);
441
442 output_buf_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
443
444 g_output_stream_splice_async (stdin_stream, input_buf_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
445 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
446 &data);
447 data.events_pending++;
448 g_output_stream_splice_async (output_buf_stream, stdout_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
449 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
450 &data);
451 data.events_pending++;
452
453 g_main_loop_run (data.loop);
454
455 g_subprocess_wait_check (proc, NULL, error);
456 g_assert_no_error (local_error);
457
458 output_buf = g_memory_output_stream_steal_as_bytes ((GMemoryOutputStream*)output_buf_stream);
459
460 g_assert_cmpmem (g_bytes_get_data (output_buf, NULL),
461 g_bytes_get_size (output_buf),
462 "hello, world!", 13);
463
464 g_bytes_unref (output_buf);
465 g_main_loop_unref (data.loop);
466 g_object_unref (input_buf_stream);
467 g_object_unref (output_buf_stream);
468 g_object_unref (proc);
469 }
470
471 static gpointer
cancel_soon(gpointer user_data)472 cancel_soon (gpointer user_data)
473 {
474 GCancellable *cancellable = user_data;
475
476 g_usleep (G_TIME_SPAN_SECOND);
477 g_cancellable_cancel (cancellable);
478 g_object_unref (cancellable);
479
480 return NULL;
481 }
482
483 static void
test_cat_eof(void)484 test_cat_eof (void)
485 {
486 GCancellable *cancellable;
487 GError *error = NULL;
488 GSubprocess *cat;
489 gboolean result;
490 gchar buffer;
491 gssize s;
492
493 #ifdef G_OS_WIN32
494 g_test_skip ("This test has not been ported to Win32");
495 return;
496 #endif
497
498 /* Spawn 'cat' */
499 cat = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, "cat", NULL);
500 g_assert_no_error (error);
501 g_assert_nonnull (cat);
502
503 /* Make sure that reading stdout blocks (until we cancel) */
504 cancellable = g_cancellable_new ();
505 g_thread_unref (g_thread_new ("cancel thread", cancel_soon, g_object_ref (cancellable)));
506 s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, cancellable, &error);
507 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
508 g_assert_cmpint (s, ==, -1);
509 g_object_unref (cancellable);
510 g_clear_error (&error);
511
512 /* Close the stream (EOF on cat's stdin) */
513 result = g_output_stream_close (g_subprocess_get_stdin_pipe (cat), NULL, &error);
514 g_assert_no_error (error);
515 g_assert_true (result);
516
517 /* Now check that reading cat's stdout gets us an EOF (since it quit) */
518 s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, NULL, &error);
519 g_assert_no_error (error);
520 g_assert_false (s);
521
522 /* Check that the process has exited as a result of the EOF */
523 result = g_subprocess_wait (cat, NULL, &error);
524 g_assert_no_error (error);
525 g_assert_true (g_subprocess_get_if_exited (cat));
526 g_assert_cmpint (g_subprocess_get_exit_status (cat), ==, 0);
527 g_assert_true (result);
528
529 g_object_unref (cat);
530 }
531
532 typedef struct {
533 guint events_pending;
534 gboolean caught_error;
535 GError *error;
536 GMainLoop *loop;
537
538 gint counter;
539 GOutputStream *first_stdin;
540 } TestMultiSpliceData;
541
542 static void
on_one_multi_splice_done(GObject * obj,GAsyncResult * res,gpointer user_data)543 on_one_multi_splice_done (GObject *obj,
544 GAsyncResult *res,
545 gpointer user_data)
546 {
547 TestMultiSpliceData *data = user_data;
548
549 if (!data->caught_error)
550 {
551 if (g_output_stream_splice_finish ((GOutputStream*)obj, res, &data->error) < 0)
552 data->caught_error = TRUE;
553 }
554
555 data->events_pending--;
556 if (data->events_pending == 0)
557 g_main_loop_quit (data->loop);
558 }
559
560 static gboolean
on_idle_multisplice(gpointer user_data)561 on_idle_multisplice (gpointer user_data)
562 {
563 TestMultiSpliceData *data = user_data;
564
565 if (data->counter >= TOTAL_HELLOS || data->caught_error)
566 {
567 if (!g_output_stream_close (data->first_stdin, NULL, &data->error))
568 data->caught_error = TRUE;
569 data->events_pending--;
570 if (data->events_pending == 0)
571 {
572 g_main_loop_quit (data->loop);
573 }
574 return FALSE;
575 }
576 else
577 {
578 int i;
579 for (i = 0; i < data->counter; i++)
580 {
581 gsize bytes_written;
582 if (!g_output_stream_write_all (data->first_stdin, HELLO_WORLD,
583 strlen (HELLO_WORLD), &bytes_written,
584 NULL, &data->error))
585 {
586 data->caught_error = TRUE;
587 return FALSE;
588 }
589 }
590 data->counter *= 2;
591 return TRUE;
592 }
593 }
594
595 static void
on_subprocess_exited(GObject * object,GAsyncResult * result,gpointer user_data)596 on_subprocess_exited (GObject *object,
597 GAsyncResult *result,
598 gpointer user_data)
599 {
600 GSubprocess *subprocess = G_SUBPROCESS (object);
601 TestMultiSpliceData *data = user_data;
602 GError *error = NULL;
603
604 if (!g_subprocess_wait_finish (subprocess, result, &error))
605 {
606 if (!data->caught_error)
607 {
608 data->caught_error = TRUE;
609 g_propagate_error (&data->error, error);
610 }
611 }
612 g_spawn_check_exit_status (g_subprocess_get_exit_status (subprocess), &error);
613 g_assert_no_error (error);
614 data->events_pending--;
615 if (data->events_pending == 0)
616 g_main_loop_quit (data->loop);
617 }
618
619 static void
test_multi_1(void)620 test_multi_1 (void)
621 {
622 GError *local_error = NULL;
623 GError **error = &local_error;
624 GPtrArray *args;
625 GSubprocessLauncher *launcher;
626 GSubprocess *first;
627 GSubprocess *second;
628 GSubprocess *third;
629 GOutputStream *first_stdin;
630 GInputStream *first_stdout;
631 GOutputStream *second_stdin;
632 GInputStream *second_stdout;
633 GOutputStream *third_stdin;
634 GInputStream *third_stdout;
635 GOutputStream *membuf;
636 TestMultiSpliceData data;
637 int splice_flags = G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET;
638
639 args = get_test_subprocess_args ("cat", NULL);
640 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE);
641 first = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
642 g_assert_no_error (local_error);
643 second = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
644 g_assert_no_error (local_error);
645 third = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
646 g_assert_no_error (local_error);
647
648 g_ptr_array_free (args, TRUE);
649
650 membuf = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
651
652 first_stdin = g_subprocess_get_stdin_pipe (first);
653 first_stdout = g_subprocess_get_stdout_pipe (first);
654 second_stdin = g_subprocess_get_stdin_pipe (second);
655 second_stdout = g_subprocess_get_stdout_pipe (second);
656 third_stdin = g_subprocess_get_stdin_pipe (third);
657 third_stdout = g_subprocess_get_stdout_pipe (third);
658
659 memset (&data, 0, sizeof (data));
660 data.loop = g_main_loop_new (NULL, TRUE);
661 data.counter = 1;
662 data.first_stdin = first_stdin;
663
664 data.events_pending++;
665 g_output_stream_splice_async (second_stdin, first_stdout, splice_flags, G_PRIORITY_DEFAULT,
666 NULL, on_one_multi_splice_done, &data);
667 data.events_pending++;
668 g_output_stream_splice_async (third_stdin, second_stdout, splice_flags, G_PRIORITY_DEFAULT,
669 NULL, on_one_multi_splice_done, &data);
670 data.events_pending++;
671 g_output_stream_splice_async (membuf, third_stdout, splice_flags, G_PRIORITY_DEFAULT,
672 NULL, on_one_multi_splice_done, &data);
673
674 data.events_pending++;
675 g_timeout_add (250, on_idle_multisplice, &data);
676
677 data.events_pending++;
678 g_subprocess_wait_async (first, NULL, on_subprocess_exited, &data);
679 data.events_pending++;
680 g_subprocess_wait_async (second, NULL, on_subprocess_exited, &data);
681 data.events_pending++;
682 g_subprocess_wait_async (third, NULL, on_subprocess_exited, &data);
683
684 g_main_loop_run (data.loop);
685
686 g_assert_false (data.caught_error);
687 g_assert_no_error (data.error);
688
689 g_assert_cmpint (g_memory_output_stream_get_data_size ((GMemoryOutputStream*)membuf), ==, SPLICELEN);
690
691 g_main_loop_unref (data.loop);
692 g_object_unref (membuf);
693 g_object_unref (launcher);
694 g_object_unref (first);
695 g_object_unref (second);
696 g_object_unref (third);
697 }
698
699 typedef struct {
700 GSubprocessFlags flags;
701 gboolean is_utf8;
702 gboolean running;
703 GError *error;
704 } TestAsyncCommunicateData;
705
706 static void
on_communicate_complete(GObject * proc,GAsyncResult * result,gpointer user_data)707 on_communicate_complete (GObject *proc,
708 GAsyncResult *result,
709 gpointer user_data)
710 {
711 TestAsyncCommunicateData *data = user_data;
712 GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
713 char *stdout_str = NULL, *stderr_str = NULL;
714 const guint8 *stdout_data;
715 gsize stdout_len;
716
717 data->running = FALSE;
718 if (data->is_utf8)
719 (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
720 &stdout_str, &stderr_str, &data->error);
721 else
722 (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
723 &stdout_bytes, &stderr_bytes, &data->error);
724 if (data->error)
725 return;
726
727 if (data->flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
728 {
729 if (data->is_utf8)
730 {
731 stdout_data = (guint8*)stdout_str;
732 stdout_len = strlen (stdout_str);
733 }
734 else
735 stdout_data = g_bytes_get_data (stdout_bytes, &stdout_len);
736
737 g_assert_cmpmem (stdout_data, stdout_len, "# hello world" LINEEND, 13 + strlen (LINEEND));
738 }
739 else
740 {
741 g_assert_null (stdout_str);
742 g_assert_null (stdout_bytes);
743 }
744
745 if (data->flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
746 {
747 if (data->is_utf8)
748 g_assert_nonnull (stderr_str);
749 else
750 g_assert_nonnull (stderr_bytes);
751 }
752 else
753 {
754 g_assert_null (stderr_str);
755 g_assert_null (stderr_bytes);
756 }
757
758 g_clear_pointer (&stdout_bytes, g_bytes_unref);
759 g_clear_pointer (&stderr_bytes, g_bytes_unref);
760 g_free (stdout_str);
761 g_free (stderr_str);
762 }
763
764 /* Test g_subprocess_communicate_async() works correctly with a variety of flags,
765 * as passed in via @test_data. */
766 static void
test_communicate_async(gconstpointer test_data)767 test_communicate_async (gconstpointer test_data)
768 {
769 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
770 GError *error = NULL;
771 GPtrArray *args;
772 TestAsyncCommunicateData data = { flags, 0, };
773 GSubprocess *proc;
774 GCancellable *cancellable = NULL;
775 GBytes *input;
776 const char *hellostring;
777
778 args = get_test_subprocess_args ("cat", NULL);
779 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
780 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
781 &error);
782 g_assert_no_error (error);
783 g_ptr_array_free (args, TRUE);
784
785 /* Include a leading hash and trailing newline so that if this gets onto the
786 * test’s stdout, it doesn’t mess up TAP output. */
787 hellostring = "# hello world\n";
788 input = g_bytes_new_static (hellostring, strlen (hellostring));
789
790 g_subprocess_communicate_async (proc, input,
791 cancellable,
792 on_communicate_complete,
793 &data);
794
795 data.running = TRUE;
796 while (data.running)
797 g_main_context_iteration (NULL, TRUE);
798
799 g_assert_no_error (data.error);
800
801 g_bytes_unref (input);
802 g_object_unref (proc);
803 }
804
805 /* Test g_subprocess_communicate() works correctly with a variety of flags,
806 * as passed in via @test_data. */
807 static void
test_communicate(gconstpointer test_data)808 test_communicate (gconstpointer test_data)
809 {
810 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
811 GError *error = NULL;
812 GPtrArray *args;
813 GSubprocess *proc;
814 GCancellable *cancellable = NULL;
815 GBytes *input;
816 const gchar *hellostring;
817 GBytes *stdout_bytes, *stderr_bytes;
818 const gchar *stdout_data;
819 gsize stdout_len;
820
821 args = get_test_subprocess_args ("cat", NULL);
822 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
823 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
824 &error);
825 g_assert_no_error (error);
826 g_ptr_array_free (args, TRUE);
827
828 /* Include a leading hash and trailing newline so that if this gets onto the
829 * test’s stdout, it doesn’t mess up TAP output. */
830 hellostring = "# hello world\n";
831 input = g_bytes_new_static (hellostring, strlen (hellostring));
832
833 g_subprocess_communicate (proc, input, cancellable, &stdout_bytes, &stderr_bytes, &error);
834 g_assert_no_error (error);
835
836 if (flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
837 {
838 stdout_data = g_bytes_get_data (stdout_bytes, &stdout_len);
839 g_assert_cmpmem (stdout_data, stdout_len, "# hello world" LINEEND, 13 + strlen (LINEEND));
840 }
841 else
842 g_assert_null (stdout_bytes);
843 if (flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
844 g_assert_nonnull (stderr_bytes);
845 else
846 g_assert_null (stderr_bytes);
847
848 g_bytes_unref (input);
849 g_clear_pointer (&stdout_bytes, g_bytes_unref);
850 g_clear_pointer (&stderr_bytes, g_bytes_unref);
851 g_object_unref (proc);
852 }
853
854 typedef struct {
855 GSubprocess *proc;
856 GCancellable *cancellable;
857 gboolean is_utf8;
858 gboolean running;
859 GError *error;
860 } TestCancelledCommunicateData;
861
862 static gboolean
on_test_communicate_cancelled_idle(gpointer user_data)863 on_test_communicate_cancelled_idle (gpointer user_data)
864 {
865 TestCancelledCommunicateData *data = user_data;
866 GBytes *input;
867 const gchar *hellostring;
868 GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
869 gchar *stdout_buf = NULL, *stderr_buf = NULL;
870
871 /* Include a leading hash and trailing newline so that if this gets onto the
872 * test’s stdout, it doesn’t mess up TAP output. */
873 hellostring = "# hello world\n";
874 input = g_bytes_new_static (hellostring, strlen (hellostring));
875
876 if (data->is_utf8)
877 g_subprocess_communicate_utf8 (data->proc, hellostring, data->cancellable,
878 &stdout_buf, &stderr_buf, &data->error);
879 else
880 g_subprocess_communicate (data->proc, input, data->cancellable, &stdout_bytes,
881 &stderr_bytes, &data->error);
882
883 data->running = FALSE;
884
885 if (data->is_utf8)
886 {
887 g_assert_null (stdout_buf);
888 g_assert_null (stderr_buf);
889 }
890 else
891 {
892 g_assert_null (stdout_bytes);
893 g_assert_null (stderr_bytes);
894 }
895
896 g_bytes_unref (input);
897
898 return G_SOURCE_REMOVE;
899 }
900
901 /* Test g_subprocess_communicate() can be cancelled correctly */
902 static void
test_communicate_cancelled(gconstpointer test_data)903 test_communicate_cancelled (gconstpointer test_data)
904 {
905 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
906 GPtrArray *args;
907 GSubprocess *proc;
908 GCancellable *cancellable = NULL;
909 GError *error = NULL;
910 TestCancelledCommunicateData data = { 0 };
911
912 args = get_test_subprocess_args ("cat", NULL);
913 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
914 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
915 &error);
916 g_assert_no_error (error);
917 g_ptr_array_free (args, TRUE);
918
919 cancellable = g_cancellable_new ();
920
921 data.proc = proc;
922 data.cancellable = cancellable;
923 data.error = error;
924
925 g_cancellable_cancel (cancellable);
926 g_idle_add (on_test_communicate_cancelled_idle, &data);
927
928 data.running = TRUE;
929 while (data.running)
930 g_main_context_iteration (NULL, TRUE);
931
932 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
933 g_clear_error (&data.error);
934
935 g_object_unref (cancellable);
936 g_object_unref (proc);
937 }
938
939 static void
on_communicate_cancelled_complete(GObject * proc,GAsyncResult * result,gpointer user_data)940 on_communicate_cancelled_complete (GObject *proc,
941 GAsyncResult *result,
942 gpointer user_data)
943 {
944 TestAsyncCommunicateData *data = user_data;
945 GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
946 char *stdout_str = NULL, *stderr_str = NULL;
947
948 data->running = FALSE;
949 if (data->is_utf8)
950 (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
951 &stdout_str, &stderr_str, &data->error);
952 else
953 (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
954 &stdout_bytes, &stderr_bytes, &data->error);
955
956 if (data->is_utf8)
957 {
958 g_assert_null (stdout_str);
959 g_assert_null (stderr_str);
960 }
961 else
962 {
963 g_assert_null (stdout_bytes);
964 g_assert_null (stderr_bytes);
965 }
966 }
967
968 /* Test g_subprocess_communicate_async() can be cancelled correctly,
969 * as passed in via @test_data. */
970 static void
test_communicate_cancelled_async(gconstpointer test_data)971 test_communicate_cancelled_async (gconstpointer test_data)
972 {
973 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
974 GError *error = NULL;
975 GPtrArray *args;
976 TestAsyncCommunicateData data = { 0 };
977 GSubprocess *proc;
978 GCancellable *cancellable = NULL;
979 GBytes *input;
980 const char *hellostring;
981
982 args = get_test_subprocess_args ("cat", NULL);
983 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
984 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
985 &error);
986 g_assert_no_error (error);
987 g_ptr_array_free (args, TRUE);
988
989 /* Include a leading hash and trailing newline so that if this gets onto the
990 * test’s stdout, it doesn’t mess up TAP output. */
991 hellostring = "# hello world\n";
992 input = g_bytes_new_static (hellostring, strlen (hellostring));
993
994 cancellable = g_cancellable_new ();
995
996 g_subprocess_communicate_async (proc, input,
997 cancellable,
998 on_communicate_cancelled_complete,
999 &data);
1000
1001 g_cancellable_cancel (cancellable);
1002
1003 data.running = TRUE;
1004 while (data.running)
1005 g_main_context_iteration (NULL, TRUE);
1006
1007 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1008 g_clear_error (&data.error);
1009
1010 g_bytes_unref (input);
1011 g_object_unref (cancellable);
1012 g_object_unref (proc);
1013 }
1014
1015 /* Test g_subprocess_communicate_utf8_async() works correctly with a variety of
1016 * flags, as passed in via @test_data. */
1017 static void
test_communicate_utf8_async(gconstpointer test_data)1018 test_communicate_utf8_async (gconstpointer test_data)
1019 {
1020 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1021 GError *error = NULL;
1022 GPtrArray *args;
1023 TestAsyncCommunicateData data = { flags, 0, };
1024 GSubprocess *proc;
1025 GCancellable *cancellable = NULL;
1026
1027 args = get_test_subprocess_args ("cat", NULL);
1028 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1029 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1030 &error);
1031 g_assert_no_error (error);
1032 g_ptr_array_free (args, TRUE);
1033
1034 data.is_utf8 = TRUE;
1035 g_subprocess_communicate_utf8_async (proc, "# hello world\n",
1036 cancellable,
1037 on_communicate_complete,
1038 &data);
1039
1040 data.running = TRUE;
1041 while (data.running)
1042 g_main_context_iteration (NULL, TRUE);
1043
1044 g_assert_no_error (data.error);
1045
1046 g_object_unref (proc);
1047 }
1048
1049 /* Test g_subprocess_communicate_utf8_async() can be cancelled correclty. */
1050 static void
test_communicate_utf8_cancelled_async(gconstpointer test_data)1051 test_communicate_utf8_cancelled_async (gconstpointer test_data)
1052 {
1053 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1054 GError *error = NULL;
1055 GPtrArray *args;
1056 TestAsyncCommunicateData data = { flags, 0, };
1057 GSubprocess *proc;
1058 GCancellable *cancellable = NULL;
1059
1060 args = get_test_subprocess_args ("cat", NULL);
1061 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1062 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1063 &error);
1064 g_assert_no_error (error);
1065 g_ptr_array_free (args, TRUE);
1066
1067 cancellable = g_cancellable_new ();
1068 data.is_utf8 = TRUE;
1069 g_subprocess_communicate_utf8_async (proc, "# hello world\n",
1070 cancellable,
1071 on_communicate_cancelled_complete,
1072 &data);
1073
1074 g_cancellable_cancel (cancellable);
1075
1076 data.running = TRUE;
1077 while (data.running)
1078 g_main_context_iteration (NULL, TRUE);
1079
1080 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1081 g_clear_error (&data.error);
1082
1083 g_object_unref (cancellable);
1084 g_object_unref (proc);
1085 }
1086
1087 /* Test g_subprocess_communicate_utf8() works correctly with a variety of flags,
1088 * as passed in via @test_data. */
1089 static void
test_communicate_utf8(gconstpointer test_data)1090 test_communicate_utf8 (gconstpointer test_data)
1091 {
1092 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1093 GError *error = NULL;
1094 GPtrArray *args;
1095 GSubprocess *proc;
1096 GCancellable *cancellable = NULL;
1097 const gchar *stdin_buf;
1098 gchar *stdout_buf, *stderr_buf;
1099
1100 args = get_test_subprocess_args ("cat", NULL);
1101 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1102 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1103 &error);
1104 g_assert_no_error (error);
1105 g_ptr_array_free (args, TRUE);
1106
1107 /* Include a leading hash and trailing newline so that if this gets onto the
1108 * test’s stdout, it doesn’t mess up TAP output. */
1109 stdin_buf = "# hello world\n";
1110
1111 g_subprocess_communicate_utf8 (proc, stdin_buf, cancellable, &stdout_buf, &stderr_buf, &error);
1112 g_assert_no_error (error);
1113
1114 if (flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
1115 g_assert_cmpstr (stdout_buf, ==, "# hello world" LINEEND);
1116 else
1117 g_assert_null (stdout_buf);
1118 if (flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
1119 g_assert_nonnull (stderr_buf);
1120 else g_assert_null (stderr_buf);
1121
1122 g_free (stdout_buf);
1123 g_free (stderr_buf);
1124 g_object_unref (proc);
1125 }
1126
1127 /* Test g_subprocess_communicate_utf8() can be cancelled correctly */
1128 static void
test_communicate_utf8_cancelled(gconstpointer test_data)1129 test_communicate_utf8_cancelled (gconstpointer test_data)
1130 {
1131 GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1132 GPtrArray *args;
1133 GSubprocess *proc;
1134 GCancellable *cancellable = NULL;
1135 GError *error = NULL;
1136 TestCancelledCommunicateData data = { 0 };
1137
1138 args = get_test_subprocess_args ("cat", NULL);
1139 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1140 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1141 &error);
1142 g_assert_no_error (error);
1143 g_ptr_array_free (args, TRUE);
1144
1145 cancellable = g_cancellable_new ();
1146
1147 data.proc = proc;
1148 data.cancellable = cancellable;
1149 data.error = error;
1150
1151 g_cancellable_cancel (cancellable);
1152 g_idle_add (on_test_communicate_cancelled_idle, &data);
1153
1154 data.is_utf8 = TRUE;
1155 data.running = TRUE;
1156 while (data.running)
1157 g_main_context_iteration (NULL, TRUE);
1158
1159 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1160 g_clear_error (&data.error);
1161
1162 g_object_unref (cancellable);
1163 g_object_unref (proc);
1164 }
1165
1166 static void
test_communicate_nothing(void)1167 test_communicate_nothing (void)
1168 {
1169 GError *error = NULL;
1170 GPtrArray *args;
1171 GSubprocess *proc;
1172 GCancellable *cancellable = NULL;
1173 gchar *stdout_buf;
1174
1175 args = get_test_subprocess_args ("cat", NULL);
1176 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1177 G_SUBPROCESS_FLAGS_STDIN_PIPE
1178 | G_SUBPROCESS_FLAGS_STDOUT_PIPE
1179 | G_SUBPROCESS_FLAGS_STDERR_MERGE,
1180 &error);
1181 g_assert_no_error (error);
1182 g_ptr_array_free (args, TRUE);
1183
1184 g_subprocess_communicate_utf8 (proc, "", cancellable, &stdout_buf, NULL, &error);
1185 g_assert_no_error (error);
1186
1187 g_assert_cmpstr (stdout_buf, ==, "");
1188
1189 g_free (stdout_buf);
1190
1191 g_object_unref (proc);
1192 }
1193
1194 static void
test_communicate_utf8_async_invalid(void)1195 test_communicate_utf8_async_invalid (void)
1196 {
1197 GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE;
1198 GError *error = NULL;
1199 GPtrArray *args;
1200 TestAsyncCommunicateData data = { flags, 0, };
1201 GSubprocess *proc;
1202 GCancellable *cancellable = NULL;
1203
1204 args = get_test_subprocess_args ("cat", NULL);
1205 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1206 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1207 &error);
1208 g_assert_no_error (error);
1209 g_ptr_array_free (args, TRUE);
1210
1211 data.is_utf8 = TRUE;
1212 g_subprocess_communicate_utf8_async (proc, "\xFF\xFF",
1213 cancellable,
1214 on_communicate_complete,
1215 &data);
1216
1217 data.running = TRUE;
1218 while (data.running)
1219 g_main_context_iteration (NULL, TRUE);
1220
1221 g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_FAILED);
1222 g_error_free (data.error);
1223
1224 g_object_unref (proc);
1225 }
1226
1227 /* Test that invalid UTF-8 received using g_subprocess_communicate_utf8()
1228 * results in an error. */
1229 static void
test_communicate_utf8_invalid(void)1230 test_communicate_utf8_invalid (void)
1231 {
1232 GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE;
1233 GError *local_error = NULL;
1234 gboolean ret;
1235 GPtrArray *args;
1236 gchar *stdout_str = NULL, *stderr_str = NULL;
1237 GSubprocess *proc;
1238
1239 args = get_test_subprocess_args ("cat", NULL);
1240 proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1241 G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1242 &local_error);
1243 g_assert_no_error (local_error);
1244 g_ptr_array_free (args, TRUE);
1245
1246 ret = g_subprocess_communicate_utf8 (proc, "\xFF\xFF", NULL,
1247 &stdout_str, &stderr_str, &local_error);
1248 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_FAILED);
1249 g_error_free (local_error);
1250 g_assert_false (ret);
1251
1252 g_assert_null (stdout_str);
1253 g_assert_null (stderr_str);
1254
1255 g_object_unref (proc);
1256 }
1257
1258 static gboolean
send_terminate(gpointer user_data)1259 send_terminate (gpointer user_data)
1260 {
1261 GSubprocess *proc = user_data;
1262
1263 g_subprocess_force_exit (proc);
1264
1265 return FALSE;
1266 }
1267
1268 static void
on_request_quit_exited(GObject * object,GAsyncResult * result,gpointer user_data)1269 on_request_quit_exited (GObject *object,
1270 GAsyncResult *result,
1271 gpointer user_data)
1272 {
1273 GSubprocess *subprocess = G_SUBPROCESS (object);
1274 GError *error = NULL;
1275
1276 g_subprocess_wait_finish (subprocess, result, &error);
1277 g_assert_no_error (error);
1278 #ifdef G_OS_UNIX
1279 g_assert_true (g_subprocess_get_if_signaled (subprocess));
1280 g_assert_cmpint (g_subprocess_get_term_sig (subprocess), ==, 9);
1281 #endif
1282 g_spawn_check_exit_status (g_subprocess_get_status (subprocess), &error);
1283 g_assert_nonnull (error);
1284 g_clear_error (&error);
1285
1286 g_main_loop_quit ((GMainLoop*)user_data);
1287 }
1288
1289 static void
test_terminate(void)1290 test_terminate (void)
1291 {
1292 GError *local_error = NULL;
1293 GError **error = &local_error;
1294 GSubprocess *proc;
1295 GPtrArray *args;
1296 GMainLoop *loop;
1297 const gchar *id;
1298
1299 args = get_test_subprocess_args ("sleep-forever", NULL);
1300 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
1301 g_ptr_array_free (args, TRUE);
1302 g_assert_no_error (local_error);
1303
1304 id = g_subprocess_get_identifier (proc);
1305 g_assert_nonnull (id);
1306
1307 loop = g_main_loop_new (NULL, TRUE);
1308
1309 g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
1310
1311 g_timeout_add_seconds (3, send_terminate, proc);
1312
1313 g_main_loop_run (loop);
1314
1315 g_main_loop_unref (loop);
1316 g_object_unref (proc);
1317 }
1318
1319 #ifdef G_OS_UNIX
1320 static gboolean
send_signal(gpointer user_data)1321 send_signal (gpointer user_data)
1322 {
1323 GSubprocess *proc = user_data;
1324
1325 g_subprocess_send_signal (proc, SIGKILL);
1326
1327 return FALSE;
1328 }
1329
1330 static void
test_signal(void)1331 test_signal (void)
1332 {
1333 GError *local_error = NULL;
1334 GError **error = &local_error;
1335 GSubprocess *proc;
1336 GPtrArray *args;
1337 GMainLoop *loop;
1338
1339 args = get_test_subprocess_args ("sleep-forever", NULL);
1340 proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
1341 g_ptr_array_free (args, TRUE);
1342 g_assert_no_error (local_error);
1343
1344 loop = g_main_loop_new (NULL, TRUE);
1345
1346 g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
1347
1348 g_timeout_add_seconds (3, send_signal, proc);
1349
1350 g_main_loop_run (loop);
1351
1352 g_main_loop_unref (loop);
1353 g_object_unref (proc);
1354 }
1355 #endif
1356
1357 static void
test_env(void)1358 test_env (void)
1359 {
1360 GError *local_error = NULL;
1361 GError **error = &local_error;
1362 GSubprocessLauncher *launcher;
1363 GSubprocess *proc;
1364 GPtrArray *args;
1365 GInputStream *stdout_stream;
1366 gchar *result;
1367 gchar *envp[] = { NULL, "ONE=1", "TWO=1", "THREE=3", "FOUR=1", NULL };
1368 gchar **split;
1369
1370 envp[0] = g_strdup_printf ("PATH=%s", g_getenv ("PATH"));
1371 args = get_test_subprocess_args ("env", NULL);
1372 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1373 g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1374 g_subprocess_launcher_set_environ (launcher, envp);
1375 g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
1376 g_subprocess_launcher_setenv (launcher, "THREE", "1", FALSE);
1377 g_subprocess_launcher_unsetenv (launcher, "FOUR");
1378
1379 g_assert_null (g_subprocess_launcher_getenv (launcher, "FOUR"));
1380
1381 proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
1382 g_ptr_array_free (args, TRUE);
1383 g_assert_no_error (local_error);
1384 g_free (envp[0]);
1385
1386 stdout_stream = g_subprocess_get_stdout_pipe (proc);
1387
1388 result = splice_to_string (stdout_stream, error);
1389 split = g_strsplit (result, LINEEND, -1);
1390 g_assert_cmpstr (g_environ_getenv (split, "ONE"), ==, "1");
1391 g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
1392 g_assert_cmpstr (g_environ_getenv (split, "THREE"), ==, "3");
1393 g_assert_null (g_environ_getenv (split, "FOUR"));
1394
1395 g_strfreev (split);
1396 g_free (result);
1397 g_object_unref (proc);
1398 g_object_unref (launcher);
1399 }
1400
1401 /* Test that explicitly inheriting and modifying the parent process’
1402 * environment works. */
1403 static void
test_env_inherit(void)1404 test_env_inherit (void)
1405 {
1406 GError *local_error = NULL;
1407 GError **error = &local_error;
1408 GSubprocessLauncher *launcher;
1409 GSubprocess *proc;
1410 GPtrArray *args;
1411 GInputStream *stdout_stream;
1412 gchar *result;
1413 gchar **split;
1414
1415 g_setenv ("TEST_ENV_INHERIT1", "1", TRUE);
1416 g_setenv ("TEST_ENV_INHERIT2", "2", TRUE);
1417
1418 args = get_test_subprocess_args ("env", NULL);
1419 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1420 g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1421 g_subprocess_launcher_set_environ (launcher, NULL);
1422 g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
1423 g_subprocess_launcher_unsetenv (launcher, "TEST_ENV_INHERIT1");
1424
1425 g_assert_null (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT1"));
1426 g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT2"), ==, "2");
1427 g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TWO"), ==, "2");
1428
1429 proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
1430 g_ptr_array_free (args, TRUE);
1431 g_assert_no_error (local_error);
1432
1433 stdout_stream = g_subprocess_get_stdout_pipe (proc);
1434
1435 result = splice_to_string (stdout_stream, error);
1436 split = g_strsplit (result, LINEEND, -1);
1437 g_assert_null (g_environ_getenv (split, "TEST_ENV_INHERIT1"));
1438 g_assert_cmpstr (g_environ_getenv (split, "TEST_ENV_INHERIT2"), ==, "2");
1439 g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
1440
1441 g_strfreev (split);
1442 g_free (result);
1443 g_object_unref (proc);
1444 g_object_unref (launcher);
1445 }
1446
1447 static void
test_cwd(void)1448 test_cwd (void)
1449 {
1450 GError *local_error = NULL;
1451 GError **error = &local_error;
1452 GSubprocessLauncher *launcher;
1453 GSubprocess *proc;
1454 GPtrArray *args;
1455 GInputStream *stdout_stream;
1456 gchar *result;
1457 const char *basename;
1458 gchar *tmp_lineend;
1459 const gchar *tmp_lineend_basename;
1460
1461 args = get_test_subprocess_args ("cwd", NULL);
1462 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1463 g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1464 g_subprocess_launcher_set_cwd (launcher, g_get_tmp_dir ());
1465 tmp_lineend = g_strdup_printf ("%s%s", g_get_tmp_dir (), LINEEND);
1466 tmp_lineend_basename = g_strrstr (tmp_lineend, G_DIR_SEPARATOR_S);
1467
1468 proc = g_subprocess_launcher_spawnv (launcher, (const char * const *)args->pdata, error);
1469 g_ptr_array_free (args, TRUE);
1470 g_assert_no_error (local_error);
1471
1472 stdout_stream = g_subprocess_get_stdout_pipe (proc);
1473
1474 result = splice_to_string (stdout_stream, error);
1475
1476 basename = g_strrstr (result, G_DIR_SEPARATOR_S);
1477 g_assert_nonnull (basename);
1478 g_assert_cmpstr (basename, ==, tmp_lineend_basename);
1479 g_free (tmp_lineend);
1480
1481 g_free (result);
1482 g_object_unref (proc);
1483 g_object_unref (launcher);
1484 }
1485 #ifdef G_OS_UNIX
1486 static void
test_stdout_file(void)1487 test_stdout_file (void)
1488 {
1489 GError *local_error = NULL;
1490 GError **error = &local_error;
1491 GSubprocessLauncher *launcher;
1492 GSubprocess *proc;
1493 GPtrArray *args;
1494 GFile *tmpfile;
1495 GFileIOStream *iostream;
1496 GOutputStream *stdin_stream;
1497 const char *test_data = "this is some test data\n";
1498 char *tmp_contents;
1499 char *tmp_file_path;
1500
1501 tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1502 g_assert_no_error (local_error);
1503 g_clear_object (&iostream);
1504
1505 tmp_file_path = g_file_get_path (tmpfile);
1506
1507 args = get_test_subprocess_args ("cat", NULL);
1508 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1509 g_subprocess_launcher_set_stdout_file_path (launcher, tmp_file_path);
1510 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1511 g_ptr_array_free (args, TRUE);
1512 g_assert_no_error (local_error);
1513
1514 stdin_stream = g_subprocess_get_stdin_pipe (proc);
1515
1516 g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1517 g_assert_no_error (local_error);
1518
1519 g_output_stream_close (stdin_stream, NULL, error);
1520 g_assert_no_error (local_error);
1521
1522 g_subprocess_wait_check (proc, NULL, error);
1523
1524 g_object_unref (launcher);
1525 g_object_unref (proc);
1526
1527 g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1528 g_assert_no_error (local_error);
1529
1530 g_assert_cmpstr (test_data, ==, tmp_contents);
1531 g_free (tmp_contents);
1532
1533 (void) g_file_delete (tmpfile, NULL, NULL);
1534 g_object_unref (tmpfile);
1535 g_free (tmp_file_path);
1536 }
1537
1538 static void
test_stdout_fd(void)1539 test_stdout_fd (void)
1540 {
1541 GError *local_error = NULL;
1542 GError **error = &local_error;
1543 GSubprocessLauncher *launcher;
1544 GSubprocess *proc;
1545 GPtrArray *args;
1546 GFile *tmpfile;
1547 GFileIOStream *iostream;
1548 GFileDescriptorBased *descriptor_stream;
1549 GOutputStream *stdin_stream;
1550 const char *test_data = "this is some test data\n";
1551 char *tmp_contents;
1552
1553 tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1554 g_assert_no_error (local_error);
1555
1556 args = get_test_subprocess_args ("cat", NULL);
1557 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1558 descriptor_stream = G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream)));
1559 g_subprocess_launcher_take_stdout_fd (launcher, dup (g_file_descriptor_based_get_fd (descriptor_stream)));
1560 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1561 g_ptr_array_free (args, TRUE);
1562 g_assert_no_error (local_error);
1563
1564 g_clear_object (&iostream);
1565
1566 stdin_stream = g_subprocess_get_stdin_pipe (proc);
1567
1568 g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1569 g_assert_no_error (local_error);
1570
1571 g_output_stream_close (stdin_stream, NULL, error);
1572 g_assert_no_error (local_error);
1573
1574 g_subprocess_wait_check (proc, NULL, error);
1575
1576 g_object_unref (launcher);
1577 g_object_unref (proc);
1578
1579 g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1580 g_assert_no_error (local_error);
1581
1582 g_assert_cmpstr (test_data, ==, tmp_contents);
1583 g_free (tmp_contents);
1584
1585 (void) g_file_delete (tmpfile, NULL, NULL);
1586 g_object_unref (tmpfile);
1587 }
1588
1589 static void
child_setup(gpointer user_data)1590 child_setup (gpointer user_data)
1591 {
1592 dup2 (GPOINTER_TO_INT (user_data), 1);
1593 }
1594
1595 static void
test_child_setup(void)1596 test_child_setup (void)
1597 {
1598 GError *local_error = NULL;
1599 GError **error = &local_error;
1600 GSubprocessLauncher *launcher;
1601 GSubprocess *proc;
1602 GPtrArray *args;
1603 GFile *tmpfile;
1604 GFileIOStream *iostream;
1605 GOutputStream *stdin_stream;
1606 const char *test_data = "this is some test data\n";
1607 char *tmp_contents;
1608 int fd;
1609
1610 tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1611 g_assert_no_error (local_error);
1612
1613 fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream))));
1614
1615 args = get_test_subprocess_args ("cat", NULL);
1616 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1617 g_subprocess_launcher_set_child_setup (launcher, child_setup, GINT_TO_POINTER (fd), NULL);
1618 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1619 g_ptr_array_free (args, TRUE);
1620 g_assert_no_error (local_error);
1621
1622 g_clear_object (&iostream);
1623
1624 stdin_stream = g_subprocess_get_stdin_pipe (proc);
1625
1626 g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1627 g_assert_no_error (local_error);
1628
1629 g_output_stream_close (stdin_stream, NULL, error);
1630 g_assert_no_error (local_error);
1631
1632 g_subprocess_wait_check (proc, NULL, error);
1633
1634 g_object_unref (launcher);
1635 g_object_unref (proc);
1636
1637 g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1638 g_assert_no_error (local_error);
1639
1640 g_assert_cmpstr (test_data, ==, tmp_contents);
1641 g_free (tmp_contents);
1642
1643 (void) g_file_delete (tmpfile, NULL, NULL);
1644 g_object_unref (tmpfile);
1645 }
1646
1647 static void
test_pass_fd(void)1648 test_pass_fd (void)
1649 {
1650 GError *local_error = NULL;
1651 GError **error = &local_error;
1652 GInputStream *child_input;
1653 GDataInputStream *child_datainput;
1654 GSubprocessLauncher *launcher;
1655 GSubprocess *proc;
1656 GPtrArray *args;
1657 int basic_pipefds[2];
1658 int needdup_pipefds[2];
1659 char *buf;
1660 gsize len;
1661 char *basic_fd_str;
1662 char *needdup_fd_str;
1663
1664 g_unix_open_pipe (basic_pipefds, FD_CLOEXEC, error);
1665 g_assert_no_error (local_error);
1666 g_unix_open_pipe (needdup_pipefds, FD_CLOEXEC, error);
1667 g_assert_no_error (local_error);
1668
1669 basic_fd_str = g_strdup_printf ("%d", basic_pipefds[1]);
1670 needdup_fd_str = g_strdup_printf ("%d", needdup_pipefds[1] + 1);
1671
1672 args = get_test_subprocess_args ("write-to-fds", basic_fd_str, needdup_fd_str, NULL);
1673 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1674 g_subprocess_launcher_take_fd (launcher, basic_pipefds[1], basic_pipefds[1]);
1675 g_subprocess_launcher_take_fd (launcher, needdup_pipefds[1], needdup_pipefds[1] + 1);
1676 proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1677 g_ptr_array_free (args, TRUE);
1678 g_assert_no_error (local_error);
1679
1680 g_free (basic_fd_str);
1681 g_free (needdup_fd_str);
1682
1683 child_input = g_unix_input_stream_new (basic_pipefds[0], TRUE);
1684 child_datainput = g_data_input_stream_new (child_input);
1685 buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1686 g_assert_no_error (local_error);
1687 g_assert_cmpstr (buf, ==, "hello world");
1688 g_object_unref (child_datainput);
1689 g_object_unref (child_input);
1690 g_free (buf);
1691
1692 child_input = g_unix_input_stream_new (needdup_pipefds[0], TRUE);
1693 child_datainput = g_data_input_stream_new (child_input);
1694 buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1695 g_assert_no_error (local_error);
1696 g_assert_cmpstr (buf, ==, "hello world");
1697 g_free (buf);
1698 g_object_unref (child_datainput);
1699 g_object_unref (child_input);
1700
1701 g_object_unref (launcher);
1702 g_object_unref (proc);
1703 }
1704
1705 #endif
1706
1707 static void
test_launcher_environment(void)1708 test_launcher_environment (void)
1709 {
1710 GSubprocessLauncher *launcher;
1711 GError *error = NULL;
1712 GSubprocess *proc;
1713 GPtrArray *args;
1714 gchar *out;
1715
1716 g_setenv ("A", "B", TRUE);
1717 g_setenv ("C", "D", TRUE);
1718
1719 launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1720
1721 /* unset a variable */
1722 g_subprocess_launcher_unsetenv (launcher, "A");
1723
1724 /* and set a diffferent one */
1725 g_subprocess_launcher_setenv (launcher, "E", "F", TRUE);
1726
1727 args = get_test_subprocess_args ("printenv", "A", "C", "E", NULL);
1728 proc = g_subprocess_launcher_spawnv (launcher, (const gchar **) args->pdata, &error);
1729 g_assert_no_error (error);
1730 g_assert_nonnull (proc);
1731
1732 g_subprocess_communicate_utf8 (proc, NULL, NULL, &out, NULL, &error);
1733 g_assert_no_error (error);
1734
1735 g_assert_cmpstr (out, ==, "C=D" LINEEND "E=F" LINEEND);
1736 g_free (out);
1737
1738 g_object_unref (proc);
1739 g_object_unref (launcher);
1740 g_ptr_array_unref (args);
1741 }
1742
1743 int
main(int argc,char ** argv)1744 main (int argc, char **argv)
1745 {
1746 const struct
1747 {
1748 const gchar *subtest;
1749 GSubprocessFlags flags;
1750 }
1751 flags_vectors[] =
1752 {
1753 { "", G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_MERGE },
1754 { "/no-pipes", G_SUBPROCESS_FLAGS_NONE },
1755 { "/separate-stderr", G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE },
1756 { "/stdout-only", G_SUBPROCESS_FLAGS_STDOUT_PIPE },
1757 { "/stderr-only", G_SUBPROCESS_FLAGS_STDERR_PIPE },
1758 { "/stdout-silence", G_SUBPROCESS_FLAGS_STDOUT_SILENCE },
1759 };
1760 gsize i;
1761
1762 g_test_init (&argc, &argv, NULL);
1763 g_test_bug_base ("https://bugzilla.gnome.org/");
1764
1765 g_test_add_func ("/gsubprocess/noop", test_noop);
1766 g_test_add_func ("/gsubprocess/noop-all-to-null", test_noop_all_to_null);
1767 g_test_add_func ("/gsubprocess/noop-no-wait", test_noop_no_wait);
1768 g_test_add_func ("/gsubprocess/noop-stdin-inherit", test_noop_stdin_inherit);
1769 #ifdef G_OS_UNIX
1770 g_test_add_func ("/gsubprocess/search-path", test_search_path);
1771 g_test_add_func ("/gsubprocess/signal", test_signal);
1772 #endif
1773 g_test_add_func ("/gsubprocess/exit1", test_exit1);
1774 g_test_add_func ("/gsubprocess/exit1/cancel", test_exit1_cancel);
1775 g_test_add_func ("/gsubprocess/exit1/cancel_in_cb", test_exit1_cancel_in_cb);
1776 g_test_add_func ("/gsubprocess/echo1", test_echo1);
1777 #ifdef G_OS_UNIX
1778 g_test_add_func ("/gsubprocess/echo-merged", test_echo_merged);
1779 #endif
1780 g_test_add_func ("/gsubprocess/cat-utf8", test_cat_utf8);
1781 g_test_add_func ("/gsubprocess/cat-eof", test_cat_eof);
1782 g_test_add_func ("/gsubprocess/multi1", test_multi_1);
1783
1784 /* Add various tests for g_subprocess_communicate() with different flags. */
1785 for (i = 0; i < G_N_ELEMENTS (flags_vectors); i++)
1786 {
1787 gchar *test_path = NULL;
1788
1789 test_path = g_strdup_printf ("/gsubprocess/communicate%s", flags_vectors[i].subtest);
1790 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1791 test_communicate);
1792 g_free (test_path);
1793
1794 test_path = g_strdup_printf ("/gsubprocess/communicate/cancelled%s", flags_vectors[i].subtest);
1795 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1796 test_communicate_cancelled);
1797 g_free (test_path);
1798
1799 test_path = g_strdup_printf ("/gsubprocess/communicate/async%s", flags_vectors[i].subtest);
1800 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1801 test_communicate_async);
1802 g_free (test_path);
1803
1804 test_path = g_strdup_printf ("/gsubprocess/communicate/async/cancelled%s", flags_vectors[i].subtest);
1805 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1806 test_communicate_cancelled_async);
1807 g_free (test_path);
1808
1809 test_path = g_strdup_printf ("/gsubprocess/communicate/utf8%s", flags_vectors[i].subtest);
1810 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1811 test_communicate_utf8);
1812 g_free (test_path);
1813
1814 test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/cancelled%s", flags_vectors[i].subtest);
1815 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1816 test_communicate_utf8_cancelled);
1817 g_free (test_path);
1818
1819 test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/async%s", flags_vectors[i].subtest);
1820 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1821 test_communicate_utf8_async);
1822 g_free (test_path);
1823
1824 test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/async/cancelled%s", flags_vectors[i].subtest);
1825 g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
1826 test_communicate_utf8_cancelled_async);
1827 g_free (test_path);
1828 }
1829
1830 g_test_add_func ("/gsubprocess/communicate/utf8/async/invalid", test_communicate_utf8_async_invalid);
1831 g_test_add_func ("/gsubprocess/communicate/utf8/invalid", test_communicate_utf8_invalid);
1832 g_test_add_func ("/gsubprocess/communicate/nothing", test_communicate_nothing);
1833 g_test_add_func ("/gsubprocess/terminate", test_terminate);
1834 g_test_add_func ("/gsubprocess/env", test_env);
1835 g_test_add_func ("/gsubprocess/env/inherit", test_env_inherit);
1836 g_test_add_func ("/gsubprocess/cwd", test_cwd);
1837 #ifdef G_OS_UNIX
1838 g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file);
1839 g_test_add_func ("/gsubprocess/stdout-fd", test_stdout_fd);
1840 g_test_add_func ("/gsubprocess/child-setup", test_child_setup);
1841 g_test_add_func ("/gsubprocess/pass-fd", test_pass_fd);
1842 #endif
1843 g_test_add_func ("/gsubprocess/launcher-environment", test_launcher_environment);
1844
1845 return g_test_run ();
1846 }
1847