Revert "tests/spawn-*.c: fix on Windows"
[platform/upstream/glib.git] / glib / tests / spawn-singlethread.c
1 /* 
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
4  * This work is provided "as is"; redistribution and modification
5  * in whole or in part, in any medium, physical or electronic is
6  * permitted without restriction.
7  *
8  * This work is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * In no event shall the authors or contributors be liable for any
13  * direct, indirect, incidental, special, exemplary, or consequential
14  * damages (including, but not limited to, procurement of substitute
15  * goods or services; loss of use, data, or profits; or business
16  * interruption) however caused and on any theory of liability, whether
17  * in contract, strict liability, or tort (including negligence or
18  * otherwise) arising in any way out of the use of this software, even
19  * if advised of the possibility of such damage.
20  *
21  * Author: Colin Walters <walters@verbum.org> 
22  */
23
24 #include "config.h"
25
26 #include <glib.h>
27 #include <string.h>
28
29 static char *echo_prog_path;
30 static char *echo_script_path;
31
32 typedef struct {
33   GMainLoop *loop;
34   gboolean child_exited;
35   gboolean stdout_done;
36   GString *stdout_buf;
37 } SpawnAsyncMultithreadedData;
38
39 static gboolean
40 on_child_exited (GPid     pid,
41                  gint     status,
42                  gpointer datap)
43 {
44   SpawnAsyncMultithreadedData *data = datap;
45
46   data->child_exited = TRUE;
47   if (data->child_exited && data->stdout_done)
48     g_main_loop_quit (data->loop);
49   
50   return G_SOURCE_REMOVE;
51 }
52
53 static gboolean
54 on_child_stdout (GIOChannel   *channel,
55                  GIOCondition  condition,
56                  gpointer      datap)
57 {
58   char buf[1024];
59   GError *error = NULL;
60   gsize bytes_read;
61   SpawnAsyncMultithreadedData *data = datap;
62
63   if (condition & G_IO_IN)
64     {
65       GIOStatus status;
66       status = g_io_channel_read_chars (channel, buf, sizeof (buf), &bytes_read, &error);
67       g_assert_no_error (error);
68       g_string_append_len (data->stdout_buf, buf, (gssize) bytes_read);
69       if (status == G_IO_STATUS_EOF)
70         data->stdout_done = TRUE;
71     }
72   if (condition & G_IO_HUP)
73     data->stdout_done = TRUE;
74   if (condition & G_IO_ERR)
75     g_error ("Error reading from child stdin");
76
77   if (data->child_exited && data->stdout_done)
78     g_main_loop_quit (data->loop);
79
80   return !data->stdout_done;
81 }
82
83 static void
84 test_spawn_async (void)
85 {
86   int tnum = 1;
87   GError *error = NULL;
88   GPtrArray *argv;
89   char *arg;
90   GPid pid;
91   GMainContext *context;
92   GMainLoop *loop;
93   GIOChannel *channel;
94   GSource *source;
95   int child_stdout_fd;
96   SpawnAsyncMultithreadedData data;
97
98   context = g_main_context_new ();
99   loop = g_main_loop_new (context, TRUE);
100
101   arg = g_strdup_printf ("thread %d", tnum);
102
103   argv = g_ptr_array_new ();
104   g_ptr_array_add (argv, echo_prog_path);
105   g_ptr_array_add (argv, arg);
106   g_ptr_array_add (argv, NULL);
107
108   g_spawn_async_with_pipes (NULL, (char**)argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL,
109                             &child_stdout_fd, NULL, &error);
110   g_assert_no_error (error);
111   g_ptr_array_free (argv, TRUE);
112
113   data.loop = loop;
114   data.stdout_done = FALSE;
115   data.child_exited = FALSE;
116   data.stdout_buf = g_string_new (0);
117
118   source = g_child_watch_source_new (pid);
119   g_source_set_callback (source, (GSourceFunc)on_child_exited, &data, NULL);
120   g_source_attach (source, context);
121   g_source_unref (source);
122
123   channel = g_io_channel_unix_new (child_stdout_fd);
124   source = g_io_create_watch (channel, G_IO_IN | G_IO_HUP | G_IO_ERR);
125   g_source_set_callback (source, (GSourceFunc)on_child_stdout, &data, NULL);
126   g_source_attach (source, context);
127   g_source_unref (source);
128
129   g_main_loop_run (loop);
130
131   g_assert (data.child_exited);
132   g_assert (data.stdout_done);
133   g_assert_cmpstr (data.stdout_buf->str, ==, arg);
134   g_string_free (data.stdout_buf, TRUE);
135
136   g_io_channel_unref (channel);
137   g_main_context_unref (context);
138   g_main_loop_unref (loop);
139
140   g_free (arg);
141 }
142
143 static void
144 test_spawn_sync (void)
145 {
146   int tnum = 1;
147   GError *error = NULL;
148   GPtrArray *argv;
149   char *arg;
150   char *stdout_str;
151   int estatus;
152
153   arg = g_strdup_printf ("thread %d", tnum);
154
155   argv = g_ptr_array_new ();
156   g_ptr_array_add (argv, echo_prog_path);
157   g_ptr_array_add (argv, arg);
158   g_ptr_array_add (argv, NULL);
159
160   g_spawn_sync (NULL, (char**)argv->pdata, NULL, 0, NULL, NULL, &stdout_str, NULL, &estatus, &error);
161   g_assert_no_error (error);
162   g_assert_cmpstr (arg, ==, stdout_str);
163   g_free (arg);
164   g_free (stdout_str);
165   g_ptr_array_free (argv, TRUE);
166 }
167
168 static void
169 test_spawn_script (void)
170 {
171   GError *error = NULL;
172   GPtrArray *argv;
173   char *stdout_str;
174   int estatus;
175
176   argv = g_ptr_array_new ();
177   g_ptr_array_add (argv, echo_script_path);
178   g_ptr_array_add (argv, NULL);
179
180   g_spawn_sync (NULL, (char**)argv->pdata, NULL, 0, NULL, NULL, &stdout_str, NULL, &estatus, &error);
181   g_assert_no_error (error);
182   g_assert_cmpstr ("echo\n", ==, stdout_str);
183   g_free (stdout_str);
184   g_ptr_array_free (argv, TRUE);
185 }
186
187 int
188 main (int   argc,
189       char *argv[])
190 {
191   char *dirname;
192   int ret;
193
194   g_test_init (&argc, &argv, NULL);
195
196   dirname = g_path_get_dirname (argv[0]);
197   echo_prog_path = g_build_filename (dirname, "test-spawn-echo", NULL);
198   if (!g_file_test (echo_prog_path, G_FILE_TEST_EXISTS))
199     {
200       g_free (echo_prog_path);
201       echo_prog_path = g_build_filename (dirname, "lt-test-spawn-echo", NULL);
202     }
203 #ifndef SRCDIR
204 #define SRCDIR dirname
205 #endif
206   echo_script_path = g_build_filename (SRCDIR, "echo-script", NULL);
207   if (!g_file_test (echo_script_path, G_FILE_TEST_EXISTS))
208     {
209       gchar *tmp;
210       /* strip .libs */
211       tmp = g_path_get_dirname (dirname);
212       g_free (echo_script_path);
213       echo_script_path = g_build_filename (tmp, "echo-script", NULL);
214       g_free (tmp);
215     }
216   g_free (dirname);
217
218   g_assert (g_file_test (echo_prog_path, G_FILE_TEST_EXISTS));
219   g_assert (g_file_test (echo_script_path, G_FILE_TEST_EXISTS));
220
221   g_test_add_func ("/gthread/spawn-single-sync", test_spawn_sync);
222   g_test_add_func ("/gthread/spawn-single-async", test_spawn_async);
223   g_test_add_func ("/gthread/spawn-script", test_spawn_script);
224
225   ret = g_test_run();
226
227   g_free (echo_script_path);
228   g_free (echo_prog_path);
229
230   return ret;
231 }