-move tcp session check into extra checks condition
[oweals/gnunet.git] / src / util / test_os_start_process.c
index 8453bde05487e778628fe536648c9e7624ac6cb3..90d8ae101ef50552cd2e0c04a5cee87477f0a0e6 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
  * 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.
  * 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.
- *
- * TODO: This test case will not work on windows because
- * there is no cat (unless there is).  Perhaps we should
- * add a gnunet_cat program/test program to util so we can
- * adequately test this functionality on windows?
  */
 #include "platform.h"
  */
 #include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_getopt_lib.h"
-#include "gnunet_os_lib.h"
-#include "gnunet_program_lib.h"
-#include "gnunet_scheduler_lib.h"
+#include "gnunet_util_lib.h"
 #include "disk.h"
 
 #include "disk.h"
 
-#define VERBOSE GNUNET_NO
 
 
-static char *test_phrase = "HELLO WORLD";
+static const char *test_phrase = "HELLO WORLD";
+
 static int ok;
 
 static int ok;
 
-pid_t pid;
-/* Pipe to write to started processes stdin (on write end) */
-struct GNUNET_DISK_PipeHandle *hello_pipe_stdin;
-/* Pipe to read from started processes stdout (on read end) */
-struct GNUNET_DISK_PipeHandle *hello_pipe_stdout;
+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 GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+struct read_context
+{
+  char buf[16];
+  int buf_offset;
+  const struct GNUNET_DISK_FileHandle *stdout_read_handle;
+};
 
 
-GNUNET_SCHEDULER_TaskIdentifier die_task;
+struct read_context rc;
 
 static void
 end_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
 
 static void
 end_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-
-  if (0 != PLIBC_KILL (pid, SIGTERM))
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
-    }
-  GNUNET_OS_process_wait (pid);
-  GNUNET_DISK_pipe_close(hello_pipe_stdout);
-  GNUNET_DISK_pipe_close(hello_pipe_stdin);
+  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, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
 static void
 read_call (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct GNUNET_DISK_FileHandle *stdout_read_handle = cls;
-  char buf[16];
-  memset(&buf, 0, sizeof(buf));
   int bytes;
   int bytes;
-  bytes = GNUNET_DISK_file_read(stdout_read_handle, &buf, sizeof(buf));
 
 
-#if VERBOSE
-  fprintf(stderr, "bytes is %d\n", bytes);
-#endif
+  bytes = GNUNET_DISK_file_read (rc.stdout_read_handle, &rc.buf[rc.buf_offset], \
+      sizeof (rc.buf) - rc.buf_offset);
 
 
-  if (bytes < 1)
-    {
-      ok = 1;
-      GNUNET_SCHEDULER_cancel(tc->sched, die_task);
-      GNUNET_SCHEDULER_add_now(tc->sched, &end_task, NULL);
-      return;
-    }
-
-  ok = strncmp(&buf[0], test_phrase, strlen(test_phrase));
-#if VERBOSE
-  fprintf(stderr, "read %s\n", &buf[0]);
-#endif
-  if (ok == 0)
-    {
-      GNUNET_SCHEDULER_cancel(tc->sched, die_task);
-      GNUNET_SCHEDULER_add_now(tc->sched, &end_task, NULL);
-      return;
-    }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "bytes is %d\n", bytes);
 
 
-  GNUNET_SCHEDULER_add_read_file (tc->sched,
-                                       GNUNET_TIME_UNIT_FOREVER_REL,
-                                       stdout_read_handle, &read_call, stdout_read_handle);
+  if (bytes < 1)
+  {
+    GNUNET_break (0);
+    ok = 1;
+    GNUNET_SCHEDULER_cancel (die_task);
+    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);
+    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
 
 }
 
 
 static void
-task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+run_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   char *fn;
 {
   char *fn;
-  char *buf;
-  int fd_stdout;
-  int fd_stdin;
-
   const struct GNUNET_DISK_FileHandle *stdout_read_handle;
   const struct GNUNET_DISK_FileHandle *stdout_read_handle;
+  const struct GNUNET_DISK_FileHandle *wh;
 
 
-  buf = GNUNET_malloc(strlen(test_phrase) + 1);
-  GNUNET_asprintf(&fn, "cat");
+#if !WINDOWS
+  GNUNET_asprintf (&fn, "cat");
+#else
+  GNUNET_asprintf (&fn, "w32cat");
+#endif
 
 
-  hello_pipe_stdin = GNUNET_DISK_pipe(GNUNET_YES);
-  hello_pipe_stdout = GNUNET_DISK_pipe(GNUNET_YES);
+  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))
 
   if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
-    {
-      ok = 1;
-      return;
-    }
-
-  pid = GNUNET_OS_start_process (hello_pipe_stdin, hello_pipe_stdout, fn,
-                                 "test_gnunet_echo_hello", "-", 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, fn,
+                               "test_gnunet_echo_hello", "-", NULL);
+  GNUNET_free (fn);
 
   /* Close the write end of the read pipe */
 
   /* Close the write end of the read pipe */
-  GNUNET_DISK_pipe_close_end(hello_pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
+  GNUNET_DISK_pipe_close_end (hello_pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
   /* Close the read end of the write pipe */
   /* Close the read end of the write pipe */
-  GNUNET_DISK_pipe_close_end(hello_pipe_stdin, GNUNET_DISK_PIPE_END_READ);
-  /* Get the FD to read from */
-  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(hello_pipe_stdout, GNUNET_DISK_PIPE_END_READ), &fd_stdout, sizeof (int));
-  /* Get the FD to write to */
-  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE), &fd_stdin, sizeof (int));
+  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 */
 
   /* Write the test_phrase to the cat process */
-  if (write(fd_stdin, test_phrase, strlen(test_phrase) + 1) == GNUNET_SYSERR)
-    {
-      ok = 1;
-      return;
-    }
+  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! */
 
   /* 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);
+  GNUNET_DISK_pipe_close_end (hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE);
 
 
-  die_task = GNUNET_SCHEDULER_add_delayed(tc->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 1), &end_task, NULL);
+  stdout_read_handle =
+      GNUNET_DISK_pipe_handle (hello_pipe_stdout, GNUNET_DISK_PIPE_END_READ);
 
 
-  GNUNET_SCHEDULER_add_read_file (tc->sched,
-                                  GNUNET_TIME_UNIT_FOREVER_REL,
-                                  stdout_read_handle, &read_call, (void *)stdout_read_handle);
+  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
 /**
  * Main method, starts scheduler with task1,
  * checks that "ok" is correct at the end.
  */
 static int
-check ()
+check_run ()
 {
   ok = 1;
 {
   ok = 1;
-  GNUNET_SCHEDULER_run (&task, &ok);
+  GNUNET_SCHEDULER_run (&run_task, &ok);
   return 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, fn,
+                            "gnunet-service-resolver", "-", NULL);
+  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, fn,
+                            "gnunet-service-resolver", "-", NULL);
+  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;
 
 int
 main (int argc, char *argv[])
 {
   int ret;
 
-  GNUNET_log_setup ("test-start-process",
-#if VERBOSE
-                    "DEBUG",
-#else
+  GNUNET_log_setup ("test-os-start-process",
                     "WARNING",
                     "WARNING",
-#endif
                     NULL);
                     NULL);
-  ret = check ();
-
+  ret = 0;
+  ret |= check_run ();
+  ret |= check_kill ();
+  ret |= check_instant_kill ();
   return ret;
 }
   return ret;
 }
+
+/* end of test_os_start_process.c */