123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- /*
- This file is part of GNUnet.
- Copyright (C) 2009 GNUnet e.V.
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @file util/test_os_start_process.c
- * @brief testcase for os start process code
- *
- * This testcase simply calls the os start process code
- * giving a file descriptor to write stdout to. If the
- * correct data "HELLO" is read then all is well.
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "disk.h"
- static const char *test_phrase = "HELLO WORLD";
- static int ok;
- static struct GNUNET_OS_Process *proc;
- /**
- * Pipe to write to started processes stdin (on write end)
- */
- static struct GNUNET_DISK_PipeHandle *hello_pipe_stdin;
- /**
- * Pipe to read from started processes stdout (on read end)
- */
- static struct GNUNET_DISK_PipeHandle *hello_pipe_stdout;
- static struct GNUNET_SCHEDULER_Task *die_task;
- struct read_context
- {
- char buf[16];
- int buf_offset;
- const struct GNUNET_DISK_FileHandle *stdout_read_handle;
- };
- static struct read_context rc;
- static void
- end_task (void *cls)
- {
- if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG))
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
- }
- GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc));
- GNUNET_OS_process_destroy (proc);
- proc = NULL;
- GNUNET_DISK_pipe_close (hello_pipe_stdout);
- GNUNET_DISK_pipe_close (hello_pipe_stdin);
- }
- static void
- read_call (void *cls)
- {
- int bytes;
- bytes = GNUNET_DISK_file_read (rc.stdout_read_handle,
- &rc.buf[rc.buf_offset],
- sizeof(rc.buf) - rc.buf_offset);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "bytes is %d\n",
- bytes);
- if (bytes < 1)
- {
- GNUNET_break (0);
- ok = 1;
- GNUNET_SCHEDULER_cancel (die_task);
- (void) GNUNET_SCHEDULER_add_now (&end_task, NULL);
- return;
- }
- ok = strncmp (rc.buf, test_phrase, strlen (test_phrase));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "read %s\n",
- &rc.buf[rc.buf_offset]);
- rc.buf_offset += bytes;
- if (0 == ok)
- {
- GNUNET_SCHEDULER_cancel (die_task);
- (void) GNUNET_SCHEDULER_add_now (&end_task, NULL);
- return;
- }
- GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
- rc.stdout_read_handle,
- &read_call,
- NULL);
- }
- static void
- run_task (void *cls)
- {
- char *fn;
- const struct GNUNET_DISK_FileHandle *stdout_read_handle;
- const struct GNUNET_DISK_FileHandle *wh;
- GNUNET_asprintf (&fn, "cat");
- hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES,
- GNUNET_NO);
- hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO,
- GNUNET_YES);
- if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
- {
- GNUNET_break (0);
- ok = 1;
- GNUNET_free (fn);
- return;
- }
- proc =
- GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR,
- hello_pipe_stdin, hello_pipe_stdout, NULL,
- fn,
- "test_gnunet_echo_hello", "-", NULL);
- GNUNET_free (fn);
- /* Close the write end of the read pipe */
- GNUNET_DISK_pipe_close_end (hello_pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
- /* Close the read end of the write pipe */
- GNUNET_DISK_pipe_close_end (hello_pipe_stdin, GNUNET_DISK_PIPE_END_READ);
- wh = GNUNET_DISK_pipe_handle (hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE);
- /* Write the test_phrase to the cat process */
- if (GNUNET_DISK_file_write (wh, test_phrase, strlen (test_phrase) + 1) !=
- strlen (test_phrase) + 1)
- {
- GNUNET_break (0);
- ok = 1;
- return;
- }
- /* Close the write end to end the cycle! */
- GNUNET_DISK_pipe_close_end (hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE);
- stdout_read_handle =
- GNUNET_DISK_pipe_handle (hello_pipe_stdout, GNUNET_DISK_PIPE_END_READ);
- die_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MINUTES, 1),
- &end_task,
- NULL);
- memset (&rc, 0, sizeof(rc));
- rc.stdout_read_handle = stdout_read_handle;
- GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
- stdout_read_handle,
- &read_call,
- NULL);
- }
- /**
- * Main method, starts scheduler with task1,
- * checks that "ok" is correct at the end.
- */
- static int
- check_run ()
- {
- ok = 1;
- GNUNET_SCHEDULER_run (&run_task, &ok);
- return ok;
- }
- /**
- * Test killing via pipe.
- */
- static int
- check_kill ()
- {
- char *fn;
- hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES,
- GNUNET_NO);
- hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO,
- GNUNET_YES);
- if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
- {
- return 1;
- }
- fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
- proc =
- GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR,
- hello_pipe_stdin,
- hello_pipe_stdout,
- NULL,
- fn,
- "gnunet-service-resolver", "-",
- NULL);
- if (NULL == proc)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to launch gnunet-service-resolver. Is your system setup correct?\n");
- return 77;
- }
- sleep (1); /* give process time to start, so we actually use the pipe-kill mechanism! */
- GNUNET_free (fn);
- if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG))
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
- GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc));
- GNUNET_OS_process_destroy (proc);
- proc = NULL;
- GNUNET_DISK_pipe_close (hello_pipe_stdout);
- GNUNET_DISK_pipe_close (hello_pipe_stdin);
- return 0;
- }
- /**
- * Test killing via pipe.
- */
- static int
- check_instant_kill ()
- {
- char *fn;
- hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES,
- GNUNET_NO);
- hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO,
- GNUNET_YES);
- if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
- {
- return 1;
- }
- fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
- proc =
- GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR,
- hello_pipe_stdin, hello_pipe_stdout, NULL,
- fn,
- "gnunet-service-resolver", "-", NULL);
- if (NULL == proc)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to launch gnunet-service-resolver. Is your system setup correct?\n");
- return 77;
- }
- if (0 != GNUNET_OS_process_kill (proc,
- GNUNET_TERM_SIG))
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
- }
- GNUNET_free (fn);
- GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc));
- GNUNET_OS_process_destroy (proc);
- proc = NULL;
- GNUNET_DISK_pipe_close (hello_pipe_stdout);
- GNUNET_DISK_pipe_close (hello_pipe_stdin);
- return 0;
- }
- int
- main (int argc, char *argv[])
- {
- int ret;
- GNUNET_log_setup ("test-os-start-process",
- "WARNING",
- NULL);
- ret = 0;
- ret |= check_run ();
- ret |= check_kill ();
- ret |= check_instant_kill ();
- return ret;
- }
- /* end of test_os_start_process.c */
|