Blame src/testcurl/test_get_response_cleanup.c

Packit 875988
/* DO NOT CHANGE THIS LINE */
Packit 875988
/*
Packit 875988
     This file is part of libmicrohttpd
Packit 875988
     Copyright (C) 2007, 2009 Christian Grothoff
Packit 875988
Packit 875988
     libmicrohttpd is free software; you can redistribute it and/or modify
Packit 875988
     it under the terms of the GNU General Public License as published
Packit 875988
     by the Free Software Foundation; either version 2, or (at your
Packit 875988
     option) any later version.
Packit 875988
Packit 875988
     libmicrohttpd is distributed in the hope that it will be useful, but
Packit 875988
     WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 875988
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 875988
     General Public License for more details.
Packit 875988
Packit 875988
     You should have received a copy of the GNU General Public License
Packit 875988
     along with libmicrohttpd; see the file COPYING.  If not, write to the
Packit 875988
     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit 875988
     Boston, MA 02110-1301, USA.
Packit 875988
*/
Packit 875988
Packit 875988
/**
Packit 875988
 * @file daemontest_get_response_cleanup.c
Packit 875988
 * @brief  Testcase for libmicrohttpd response cleanup
Packit 875988
 * @author Christian Grothoff
Packit 875988
 */
Packit 875988
Packit 875988
#include "MHD_config.h"
Packit 875988
#include "platform.h"
Packit 875988
#include <microhttpd.h>
Packit 875988
#include <stdlib.h>
Packit 875988
#include <unistd.h>
Packit 875988
#include <string.h>
Packit 875988
#include <time.h>
Packit 875988
#include <sys/types.h>
Packit 875988
#include <sys/wait.h>
Packit 875988
#include <fcntl.h>
Packit 875988
#ifndef _WIN32
Packit 875988
#include <signal.h>
Packit 875988
#endif /* _WIN32 */
Packit 875988
Packit 875988
#ifndef WINDOWS
Packit 875988
#include <sys/socket.h>
Packit 875988
#include <unistd.h>
Packit 875988
#endif
Packit 875988
Packit 875988
#ifdef _WIN32
Packit 875988
#ifndef WIN32_LEAN_AND_MEAN
Packit 875988
#define WIN32_LEAN_AND_MEAN 1
Packit 875988
#endif /* !WIN32_LEAN_AND_MEAN */
Packit 875988
#include <windows.h>
Packit 875988
#endif
Packit 875988
Packit 875988
#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
Packit 875988
#undef CPU_COUNT
Packit 875988
#endif
Packit 875988
#if !defined(CPU_COUNT)
Packit 875988
#define CPU_COUNT 2
Packit 875988
#endif
Packit 875988
Packit 875988
#define TESTSTR "/* DO NOT CHANGE THIS LINE */"
Packit 875988
Packit 875988
static int oneone;
Packit 875988
Packit 875988
static int ok;
Packit 875988
Packit 875988
Packit 875988
static pid_t
Packit 875988
fork_curl (const char *url)
Packit 875988
{
Packit 875988
  pid_t ret;
Packit 875988
Packit 875988
  ret = fork();
Packit 875988
  if (ret != 0)
Packit 875988
    return ret;
Packit 875988
  execlp ("curl", "curl", "-s", "-N", "-o", "/dev/null", "-GET", url, NULL);
Packit 875988
  fprintf (stderr,
Packit 875988
	   "Failed to exec curl: %s\n",
Packit 875988
	   strerror (errno));
Packit 875988
  _exit (-1);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static void
Packit 875988
kill_curl (pid_t pid)
Packit 875988
{
Packit 875988
  int status;
Packit 875988
Packit 875988
  //fprintf (stderr, "Killing curl\n");
Packit 875988
  kill (pid, SIGTERM);
Packit 875988
  waitpid (pid, &status, 0);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static ssize_t
Packit 875988
push_callback (void *cls, uint64_t pos, char *buf, size_t max)
Packit 875988
{
Packit 875988
  (void)cls;(void)pos;	/* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if (max == 0)
Packit 875988
    return 0;
Packit 875988
  buf[0] = 'd';
Packit 875988
  return 1;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static void
Packit 875988
push_free_callback (void *cls)
Packit 875988
{
Packit 875988
  int *ok = cls;
Packit 875988
Packit 875988
  //fprintf (stderr, "Cleanup callback called!\n");
Packit 875988
  *ok = 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
ahc_echo (void *cls,
Packit 875988
          struct MHD_Connection *connection,
Packit 875988
          const char *url,
Packit 875988
          const char *method,
Packit 875988
          const char *version,
Packit 875988
          const char *upload_data, size_t *upload_data_size,
Packit 875988
          void **unused)
Packit 875988
{
Packit 875988
  static int ptr;
Packit 875988
  const char *me = cls;
Packit 875988
  struct MHD_Response *response;
Packit 875988
  int ret;
Packit 875988
  (void)url;(void)version;                      /* Unused. Silent compiler warning. */
Packit 875988
  (void)upload_data;(void)upload_data_size;     /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  //fprintf (stderr, "In CB: %s!\n", method);
Packit 875988
  if (0 != strcmp (me, method))
Packit 875988
    return MHD_NO;              /* unexpected method */
Packit 875988
  if (&ptr != *unused)
Packit 875988
    {
Packit 875988
      *unused = &pt;;
Packit 875988
      return MHD_YES;
Packit 875988
    }
Packit 875988
  *unused = NULL;
Packit 875988
  response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
Packit 875988
						32 * 1024,
Packit 875988
						&push_callback,
Packit 875988
						&ok,
Packit 875988
						&push_free_callback);
Packit 875988
  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
Packit 875988
  MHD_destroy_response (response);
Packit 875988
  if (ret == MHD_NO)
Packit 875988
    abort ();
Packit 875988
  return ret;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testInternalGet ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  pid_t curl;
Packit 875988
  int port;
Packit 875988
  char url[127];
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
  else
Packit 875988
    {
Packit 875988
      port = 1180;
Packit 875988
      if (oneone)
Packit 875988
        port += 10;
Packit 875988
    }
Packit 875988
Packit 875988
  ok = 1;
Packit 875988
  d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 1;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  sprintf(url, "http://127.0.0.1:%d/", port);
Packit 875988
  curl = fork_curl (url);
Packit 875988
  (void)sleep (1);
Packit 875988
  kill_curl (curl);
Packit 875988
  (void)sleep (1);
Packit 875988
  /* fprintf (stderr, "Stopping daemon!\n"); */
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (ok != 0)
Packit 875988
    return 2;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testMultithreadedGet ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  pid_t curl;
Packit 875988
  int port;
Packit 875988
  char url[127];
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
  else
Packit 875988
    {
Packit 875988
      port = 1181;
Packit 875988
      if (oneone)
Packit 875988
        port += 10;
Packit 875988
    }
Packit 875988
Packit 875988
  ok = 1;
Packit 875988
  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_echo, "GET",
Packit 875988
			MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 2,
Packit 875988
			MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 16;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  sprintf(url, "http://127.0.0.1:%d/", port);
Packit 875988
  //fprintf (stderr, "Forking cURL!\n");
Packit 875988
  curl = fork_curl (url);
Packit 875988
  (void)sleep (1);
Packit 875988
  kill_curl (curl);
Packit 875988
  (void)sleep (1);
Packit 875988
  curl = fork_curl (url);
Packit 875988
  (void)sleep (1);
Packit 875988
  if (ok != 0)
Packit 875988
    {
Packit 875988
      kill_curl (curl);
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 64;
Packit 875988
    }
Packit 875988
  kill_curl (curl);
Packit 875988
  (void)sleep (1);
Packit 875988
  //fprintf (stderr, "Stopping daemon!\n");
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (ok != 0)
Packit 875988
    return 32;
Packit 875988
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testMultithreadedPoolGet ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  pid_t curl;
Packit 875988
  int port;
Packit 875988
  char url[127];
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
  else
Packit 875988
    {
Packit 875988
      port = 1182;
Packit 875988
      if (oneone)
Packit 875988
        port += 10;
Packit 875988
    }
Packit 875988
Packit 875988
  ok = 1;
Packit 875988
  d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_echo, "GET",
Packit 875988
                        MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 64;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  sprintf(url, "http://127.0.0.1:%d/", port);
Packit 875988
  curl = fork_curl (url);
Packit 875988
  (void)sleep (1);
Packit 875988
  kill_curl (curl);
Packit 875988
  (void)sleep (1);
Packit 875988
  //fprintf (stderr, "Stopping daemon!\n");
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (ok != 0)
Packit 875988
    return 128;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testExternalGet ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  fd_set rs;
Packit 875988
  fd_set ws;
Packit 875988
  fd_set es;
Packit 875988
  MHD_socket max;
Packit 875988
  time_t start;
Packit 875988
  struct timeval tv;
Packit 875988
  pid_t curl;
Packit 875988
  int port;
Packit 875988
  char url[127];
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
  else
Packit 875988
    {
Packit 875988
      port = 1183;
Packit 875988
      if (oneone)
Packit 875988
        port += 10;
Packit 875988
    }
Packit 875988
Packit 875988
  ok = 1;
Packit 875988
  d = MHD_start_daemon (MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 256;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  sprintf(url, "http://127.0.0.1:%d/", port);
Packit 875988
  curl = fork_curl (url);
Packit 875988
Packit 875988
  start = time (NULL);
Packit 875988
  while ((time (NULL) - start < 2))
Packit 875988
    {
Packit 875988
      max = 0;
Packit 875988
      FD_ZERO (&rs);
Packit 875988
      FD_ZERO (&ws);
Packit 875988
      FD_ZERO (&es);
Packit 875988
      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
Packit 875988
        {
Packit 875988
          MHD_stop_daemon (d);
Packit 875988
          return 4096;
Packit 875988
        }
Packit 875988
      tv.tv_sec = 0;
Packit 875988
      tv.tv_usec = 1000;
Packit 875988
      if (-1 == select (max + 1, &rs, &ws, &es, &tv))
Packit 875988
        {
Packit 875988
          if (EINTR != errno)
Packit 875988
            abort ();
Packit 875988
        }
Packit 875988
      MHD_run (d);
Packit 875988
    }
Packit 875988
  kill_curl (curl);
Packit 875988
  start = time (NULL);
Packit 875988
  while ((time (NULL) - start < 2))
Packit 875988
    {
Packit 875988
      max = 0;
Packit 875988
      FD_ZERO (&rs);
Packit 875988
      FD_ZERO (&ws);
Packit 875988
      FD_ZERO (&es);
Packit 875988
      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
Packit 875988
        {
Packit 875988
          MHD_stop_daemon (d);
Packit 875988
          return 4096;
Packit 875988
        }
Packit 875988
      tv.tv_sec = 0;
Packit 875988
      tv.tv_usec = 1000;
Packit 875988
      if (-1 == select (max + 1, &rs, &ws, &es, &tv))
Packit 875988
        {
Packit 875988
          if (EINTR != errno)
Packit 875988
            abort ();
Packit 875988
        }
Packit 875988
      MHD_run (d);
Packit 875988
    }
Packit 875988
  /* fprintf (stderr, "Stopping daemon!\n"); */
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (ok != 0)
Packit 875988
    return 1024;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
int
Packit 875988
main (int argc, char *const *argv)
Packit 875988
{
Packit 875988
  unsigned int errorCount = 0;
Packit 875988
  (void)argc;   /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
#ifndef _WIN32
Packit 875988
  /* Solaris has no way to disable SIGPIPE on socket disconnect. */
Packit 875988
  if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTOSUPPRESS_SIGPIPE))
Packit 875988
    {
Packit 875988
      struct sigaction act;
Packit 875988
Packit 875988
      act.sa_handler = SIG_IGN;
Packit 875988
      sigaction(SIGPIPE, &act, NULL);
Packit 875988
    }
Packit 875988
#endif /* _WIN32 */
Packit 875988
Packit 875988
  oneone = (NULL != strrchr (argv[0], (int) '/')) ?
Packit 875988
    (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
Packit 875988
  errorCount += testInternalGet ();
Packit 875988
  errorCount += testMultithreadedGet ();
Packit 875988
  errorCount += testMultithreadedPoolGet ();
Packit 875988
  errorCount += testExternalGet ();
Packit 875988
  if (errorCount != 0)
Packit 875988
    fprintf (stderr, "Error (code: %u)\n", errorCount);
Packit 875988
  return errorCount != 0;       /* 0 == pass */
Packit 875988
}