nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 | #ifdef G_OS_WIN32 |
||
30 | #define LINEEND "\r\n" |
||
31 | #else |
||
32 | #define LINEEND "\n" |
||
33 | #endif |
||
34 | |||
35 | /* MinGW builds are likely done using a BASH-style shell, so run the |
||
36 | * normal script there, as on non-Windows builds, as it is more likely |
||
37 | * that one will run 'make check' in such shells to test the code |
||
38 | */ |
||
39 | #if defined (G_OS_WIN32) && defined (_MSC_VER) |
||
40 | #define SCRIPT_EXT ".bat" |
||
41 | #else |
||
42 | #define SCRIPT_EXT |
||
43 | #endif |
||
44 | |||
45 | static char *echo_prog_path; |
||
46 | static char *echo_script_path; |
||
47 | |||
48 | typedef struct { |
||
49 | GMainLoop *loop; |
||
50 | gboolean child_exited; |
||
51 | gboolean stdout_done; |
||
52 | GString *stdout_buf; |
||
53 | } SpawnAsyncMultithreadedData; |
||
54 | |||
55 | static gboolean |
||
56 | on_child_exited (GPid pid, |
||
57 | gint status, |
||
58 | gpointer datap) |
||
59 | { |
||
60 | SpawnAsyncMultithreadedData *data = datap; |
||
61 | |||
62 | data->child_exited = TRUE; |
||
63 | if (data->child_exited && data->stdout_done) |
||
64 | g_main_loop_quit (data->loop); |
||
65 | |||
66 | return G_SOURCE_REMOVE; |
||
67 | } |
||
68 | |||
69 | static gboolean |
||
70 | on_child_stdout (GIOChannel *channel, |
||
71 | GIOCondition condition, |
||
72 | gpointer datap) |
||
73 | { |
||
74 | char buf[1024]; |
||
75 | GError *error = NULL; |
||
76 | gsize bytes_read; |
||
77 | SpawnAsyncMultithreadedData *data = datap; |
||
78 | |||
79 | if (condition & G_IO_IN) |
||
80 | { |
||
81 | GIOStatus status; |
||
82 | status = g_io_channel_read_chars (channel, buf, sizeof (buf), &bytes_read, &error); |
||
83 | g_assert_no_error (error); |
||
84 | g_string_append_len (data->stdout_buf, buf, (gssize) bytes_read); |
||
85 | if (status == G_IO_STATUS_EOF) |
||
86 | data->stdout_done = TRUE; |
||
87 | } |
||
88 | if (condition & G_IO_HUP) |
||
89 | data->stdout_done = TRUE; |
||
90 | if (condition & G_IO_ERR) |
||
91 | g_error ("Error reading from child stdin"); |
||
92 | |||
93 | if (data->child_exited && data->stdout_done) |
||
94 | g_main_loop_quit (data->loop); |
||
95 | |||
96 | return !data->stdout_done; |
||
97 | } |
||
98 | |||
99 | static void |
||
100 | test_spawn_async (void) |
||
101 | { |
||
102 | int tnum = 1; |
||
103 | GError *error = NULL; |
||
104 | GPtrArray *argv; |
||
105 | char *arg; |
||
106 | GPid pid; |
||
107 | GMainContext *context; |
||
108 | GMainLoop *loop; |
||
109 | GIOChannel *channel; |
||
110 | GSource *source; |
||
111 | int child_stdout_fd; |
||
112 | SpawnAsyncMultithreadedData data; |
||
113 | |||
114 | context = g_main_context_new (); |
||
115 | loop = g_main_loop_new (context, TRUE); |
||
116 | |||
117 | arg = g_strdup_printf ("thread %d", tnum); |
||
118 | |||
119 | argv = g_ptr_array_new (); |
||
120 | g_ptr_array_add (argv, echo_prog_path); |
||
121 | g_ptr_array_add (argv, arg); |
||
122 | g_ptr_array_add (argv, NULL); |
||
123 | |||
124 | g_spawn_async_with_pipes (NULL, (char**)argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL, |
||
125 | &child_stdout_fd, NULL, &error); |
||
126 | g_assert_no_error (error); |
||
127 | g_ptr_array_free (argv, TRUE); |
||
128 | |||
129 | data.loop = loop; |
||
130 | data.stdout_done = FALSE; |
||
131 | data.child_exited = FALSE; |
||
132 | data.stdout_buf = g_string_new (0); |
||
133 | |||
134 | source = g_child_watch_source_new (pid); |
||
135 | g_source_set_callback (source, (GSourceFunc)on_child_exited, &data, NULL); |
||
136 | g_source_attach (source, context); |
||
137 | g_source_unref (source); |
||
138 | |||
139 | channel = g_io_channel_unix_new (child_stdout_fd); |
||
140 | source = g_io_create_watch (channel, G_IO_IN | G_IO_HUP | G_IO_ERR); |
||
141 | g_source_set_callback (source, (GSourceFunc)on_child_stdout, &data, NULL); |
||
142 | g_source_attach (source, context); |
||
143 | g_source_unref (source); |
||
144 | |||
145 | g_main_loop_run (loop); |
||
146 | |||
147 | g_assert (data.child_exited); |
||
148 | g_assert (data.stdout_done); |
||
149 | g_assert_cmpstr (data.stdout_buf->str, ==, arg); |
||
150 | g_string_free (data.stdout_buf, TRUE); |
||
151 | |||
152 | g_io_channel_unref (channel); |
||
153 | g_main_context_unref (context); |
||
154 | g_main_loop_unref (loop); |
||
155 | |||
156 | g_free (arg); |
||
157 | } |
||
158 | |||
159 | static void |
||
160 | test_spawn_sync (void) |
||
161 | { |
||
162 | int tnum = 1; |
||
163 | GError *error = NULL; |
||
164 | GPtrArray *argv; |
||
165 | char *arg; |
||
166 | char *stdout_str; |
||
167 | int estatus; |
||
168 | |||
169 | arg = g_strdup_printf ("thread %d", tnum); |
||
170 | |||
171 | argv = g_ptr_array_new (); |
||
172 | g_ptr_array_add (argv, echo_prog_path); |
||
173 | g_ptr_array_add (argv, arg); |
||
174 | g_ptr_array_add (argv, NULL); |
||
175 | |||
176 | g_spawn_sync (NULL, (char**)argv->pdata, NULL, 0, NULL, NULL, &stdout_str, NULL, &estatus, &error); |
||
177 | g_assert_no_error (error); |
||
178 | g_assert_cmpstr (arg, ==, stdout_str); |
||
179 | g_free (arg); |
||
180 | g_free (stdout_str); |
||
181 | g_ptr_array_free (argv, TRUE); |
||
182 | } |
||
183 | |||
184 | static void |
||
185 | test_spawn_script (void) |
||
186 | { |
||
187 | GError *error = NULL; |
||
188 | GPtrArray *argv; |
||
189 | char *stdout_str; |
||
190 | int estatus; |
||
191 | |||
192 | argv = g_ptr_array_new (); |
||
193 | g_ptr_array_add (argv, echo_script_path); |
||
194 | g_ptr_array_add (argv, NULL); |
||
195 | |||
196 | g_spawn_sync (NULL, (char**)argv->pdata, NULL, 0, NULL, NULL, &stdout_str, NULL, &estatus, &error); |
||
197 | g_assert_no_error (error); |
||
198 | g_assert_cmpstr ("echo" LINEEND, ==, stdout_str); |
||
199 | g_free (stdout_str); |
||
200 | g_ptr_array_free (argv, TRUE); |
||
201 | } |
||
202 | |||
203 | int |
||
204 | main (int argc, |
||
205 | char *argv[]) |
||
206 | { |
||
207 | char *dirname; |
||
208 | int ret; |
||
209 | |||
210 | g_test_init (&argc, &argv, NULL); |
||
211 | |||
212 | dirname = g_path_get_dirname (argv[0]); |
||
213 | echo_prog_path = g_build_filename (dirname, "test-spawn-echo" EXEEXT, NULL); |
||
214 | if (!g_file_test (echo_prog_path, G_FILE_TEST_EXISTS)) |
||
215 | { |
||
216 | g_free (echo_prog_path); |
||
217 | echo_prog_path = g_build_filename (dirname, "lt-test-spawn-echo" EXEEXT, NULL); |
||
218 | } |
||
219 | echo_script_path = g_build_filename (dirname, "echo-script" SCRIPT_EXT, NULL); |
||
220 | if (!g_file_test (echo_script_path, G_FILE_TEST_EXISTS)) |
||
221 | { |
||
222 | g_free (echo_script_path); |
||
223 | echo_script_path = g_test_build_filename (G_TEST_DIST, "echo-script" SCRIPT_EXT, NULL); |
||
224 | } |
||
225 | g_free (dirname); |
||
226 | |||
227 | g_assert (g_file_test (echo_prog_path, G_FILE_TEST_EXISTS)); |
||
228 | g_assert (g_file_test (echo_script_path, G_FILE_TEST_EXISTS)); |
||
229 | |||
230 | g_test_add_func ("/gthread/spawn-single-sync", test_spawn_sync); |
||
231 | g_test_add_func ("/gthread/spawn-single-async", test_spawn_async); |
||
232 | g_test_add_func ("/gthread/spawn-script", test_spawn_script); |
||
233 | |||
234 | ret = g_test_run(); |
||
235 | |||
236 | g_free (echo_script_path); |
||
237 | g_free (echo_prog_path); |
||
238 | |||
239 | return ret; |
||
240 | } |