aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/test_os_start_process.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/test_os_start_process.c')
-rw-r--r--src/lib/util/test_os_start_process.c290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/lib/util/test_os_start_process.c b/src/lib/util/test_os_start_process.c
new file mode 100644
index 000000000..cdb1acf03
--- /dev/null
+++ b/src/lib/util/test_os_start_process.c
@@ -0,0 +1,290 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file util/test_os_start_process.c
22 * @brief testcase for os start process code
23 *
24 * This testcase simply calls the os start process code
25 * giving a file descriptor to write stdout to. If the
26 * correct data "HELLO" is read then all is well.
27 */
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "disk.h"
32
33
34static const char *test_phrase = "HELLO WORLD";
35
36static int ok;
37
38static struct GNUNET_OS_Process *proc;
39
40/**
41 * Pipe to write to started processes stdin (on write end)
42 */
43static struct GNUNET_DISK_PipeHandle *hello_pipe_stdin;
44
45/**
46 * Pipe to read from started processes stdout (on read end)
47 */
48static struct GNUNET_DISK_PipeHandle *hello_pipe_stdout;
49
50static struct GNUNET_SCHEDULER_Task *die_task;
51
52struct read_context
53{
54 char buf[16];
55 int buf_offset;
56 const struct GNUNET_DISK_FileHandle *stdout_read_handle;
57};
58
59
60static struct read_context rc;
61
62
63static void
64end_task (void *cls)
65{
66 if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG))
67 {
68 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
69 }
70 GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc));
71 GNUNET_OS_process_destroy (proc);
72 proc = NULL;
73 GNUNET_DISK_pipe_close (hello_pipe_stdout);
74 GNUNET_DISK_pipe_close (hello_pipe_stdin);
75}
76
77
78static void
79read_call (void *cls)
80{
81 int bytes;
82
83 bytes = GNUNET_DISK_file_read (rc.stdout_read_handle,
84 &rc.buf[rc.buf_offset],
85 sizeof(rc.buf) - rc.buf_offset);
86 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
87 "bytes is %d\n",
88 bytes);
89
90 if (bytes < 1)
91 {
92 GNUNET_break (0);
93 ok = 1;
94 GNUNET_SCHEDULER_cancel (die_task);
95 (void) GNUNET_SCHEDULER_add_now (&end_task, NULL);
96 return;
97 }
98
99 ok = strncmp (rc.buf, test_phrase, strlen (test_phrase));
100 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
101 "read %s\n",
102 &rc.buf[rc.buf_offset]);
103 rc.buf_offset += bytes;
104
105 if (0 == ok)
106 {
107 GNUNET_SCHEDULER_cancel (die_task);
108 (void) GNUNET_SCHEDULER_add_now (&end_task, NULL);
109 return;
110 }
111
112 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
113 rc.stdout_read_handle,
114 &read_call,
115 NULL);
116}
117
118
119static void
120run_task (void *cls)
121{
122 const struct GNUNET_DISK_FileHandle *stdout_read_handle;
123 const struct GNUNET_DISK_FileHandle *wh;
124
125 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
126 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
127 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
128 {
129 GNUNET_break (0);
130 ok = 1;
131 return;
132 }
133
134 proc =
135 GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR,
136 hello_pipe_stdin, hello_pipe_stdout, NULL,
137 "cat",
138 "cat", "-", NULL);
139 /* Close the write end of the read pipe */
140 GNUNET_DISK_pipe_close_end (hello_pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
141 /* Close the read end of the write pipe */
142 GNUNET_DISK_pipe_close_end (hello_pipe_stdin, GNUNET_DISK_PIPE_END_READ);
143
144 wh = GNUNET_DISK_pipe_handle (hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE);
145
146 /* Write the test_phrase to the cat process */
147 if (GNUNET_DISK_file_write (wh, test_phrase, strlen (test_phrase) + 1) !=
148 strlen (test_phrase) + 1)
149 {
150 GNUNET_break (0);
151 ok = 1;
152 return;
153 }
154
155 /* Close the write end to end the cycle! */
156 GNUNET_DISK_pipe_close_end (hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE);
157
158 stdout_read_handle =
159 GNUNET_DISK_pipe_handle (hello_pipe_stdout, GNUNET_DISK_PIPE_END_READ);
160
161 die_task =
162 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
163 (GNUNET_TIME_UNIT_MINUTES, 1),
164 &end_task,
165 NULL);
166
167 memset (&rc, 0, sizeof(rc));
168 rc.stdout_read_handle = stdout_read_handle;
169 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
170 stdout_read_handle,
171 &read_call,
172 NULL);
173}
174
175
176/**
177 * Main method, starts scheduler with task1,
178 * checks that "ok" is correct at the end.
179 */
180static int
181check_run ()
182{
183 ok = 1;
184 GNUNET_SCHEDULER_run (&run_task, &ok);
185 return ok;
186}
187
188
189/**
190 * Test killing via pipe.
191 */
192static int
193check_kill ()
194{
195 char *fn;
196
197 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
198 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
199 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
200 {
201 return 1;
202 }
203 fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
204 proc =
205 GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR
206 | GNUNET_OS_USE_PIPE_CONTROL,
207 hello_pipe_stdin,
208 hello_pipe_stdout,
209 NULL,
210 fn,
211 "gnunet-service-resolver", "-",
212 NULL);
213 if (NULL == proc)
214 {
215 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
216 "Failed to launch gnunet-service-resolver. Is your system setup correct?\n");
217 return 77;
218 }
219 sleep (1); /* give process time to start, so we actually use the pipe-kill mechanism! */
220 GNUNET_free (fn);
221 if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG))
222 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
223 GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc));
224 GNUNET_OS_process_destroy (proc);
225 proc = NULL;
226 GNUNET_DISK_pipe_close (hello_pipe_stdout);
227 GNUNET_DISK_pipe_close (hello_pipe_stdin);
228 return 0;
229}
230
231
232/**
233 * Test killing via pipe.
234 */
235static int
236check_instant_kill ()
237{
238 char *fn;
239
240 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
241 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
242 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
243 {
244 return 1;
245 }
246 fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
247 proc =
248 GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR
249 | GNUNET_OS_USE_PIPE_CONTROL,
250 hello_pipe_stdin, hello_pipe_stdout, NULL,
251 fn,
252 "gnunet-service-resolver", "-", NULL);
253 if (NULL == proc)
254 {
255 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
256 "Failed to launch gnunet-service-resolver. Is your system setup correct?\n");
257 return 77;
258 }
259 if (0 != GNUNET_OS_process_kill (proc,
260 GNUNET_TERM_SIG))
261 {
262 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
263 }
264 GNUNET_free (fn);
265 GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc));
266 GNUNET_OS_process_destroy (proc);
267 proc = NULL;
268 GNUNET_DISK_pipe_close (hello_pipe_stdout);
269 GNUNET_DISK_pipe_close (hello_pipe_stdin);
270 return 0;
271}
272
273
274int
275main (int argc, char *argv[])
276{
277 int ret;
278
279 GNUNET_log_setup ("test-os-start-process",
280 "WARNING",
281 NULL);
282 ret = 0;
283 ret |= check_run ();
284 ret |= check_kill ();
285 ret |= check_instant_kill ();
286 return ret;
287}
288
289
290/* end of test_os_start_process.c */