Blame src/testzzuf/test_put_large.c

Packit 875988
/*
Packit 875988
     This file is part of libmicrohttpd
Packit 875988
     Copyright (C) 2007, 2008 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 test_put_large.c
Packit 875988
 * @brief  Testcase for libmicrohttpd PUT operations
Packit 875988
 * @author Christian Grothoff
Packit 875988
 */
Packit 875988
Packit 875988
#include "MHD_config.h"
Packit 875988
#include "platform.h"
Packit 875988
#include <curl/curl.h>
Packit 875988
#include <microhttpd.h>
Packit 875988
#include <stdlib.h>
Packit 875988
#include <string.h>
Packit 875988
#include <time.h>
Packit 875988
Packit 875988
#ifndef WINDOWS
Packit 875988
#include <unistd.h>
Packit 875988
#endif
Packit 875988
Packit 875988
#include "socat.c"
Packit 875988
Packit 875988
static int oneone;
Packit 875988
Packit 875988
/**
Packit 875988
 * Do not make this much larger since we will hit the
Packit 875988
 * MHD default buffer limit and the test code is not
Packit 875988
 * written for incremental upload processing...
Packit 875988
 */
Packit 875988
#define PUT_SIZE (256 * 1024)
Packit 875988
Packit 875988
static char *put_buffer;
Packit 875988
Packit 875988
struct CBC
Packit 875988
{
Packit 875988
  char *buf;
Packit 875988
  size_t pos;
Packit 875988
  size_t size;
Packit 875988
};
Packit 875988
Packit 875988
static size_t
Packit 875988
putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
Packit 875988
{
Packit 875988
  unsigned int *pos = ptr;
Packit 875988
  unsigned int wrt;
Packit 875988
Packit 875988
  wrt = size * nmemb;
Packit 875988
  if (wrt > PUT_SIZE - (*pos))
Packit 875988
    wrt = PUT_SIZE - (*pos);
Packit 875988
  memcpy (stream, &put_buffer[*pos], wrt);
Packit 875988
  (*pos) += wrt;
Packit 875988
  return wrt;
Packit 875988
}
Packit 875988
Packit 875988
static size_t
Packit 875988
copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
Packit 875988
{
Packit 875988
  struct CBC *cbc = ctx;
Packit 875988
Packit 875988
  if (cbc->pos + size * nmemb > cbc->size)
Packit 875988
    return 0;                   /* overflow */
Packit 875988
  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
Packit 875988
  cbc->pos += size * nmemb;
Packit 875988
  return size * nmemb;
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
  int *done = cls;
Packit 875988
  struct MHD_Response *response;
Packit 875988
  int ret;
Packit 875988
  (void)version;(void)unused;	/* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if (0 != strcmp ("PUT", method))
Packit 875988
    return MHD_NO;              /* unexpected method */
Packit 875988
  if ((*done) == 0)
Packit 875988
    {
Packit 875988
      if (*upload_data_size != PUT_SIZE)
Packit 875988
        {
Packit 875988
#if 0
Packit 875988
          fprintf (stderr,
Packit 875988
                   "Waiting for more data (%u/%u)...\n",
Packit 875988
                   *upload_data_size, PUT_SIZE);
Packit 875988
#endif
Packit 875988
          return MHD_YES;       /* not yet ready */
Packit 875988
        }
Packit 875988
      if (0 == memcmp (upload_data, put_buffer, PUT_SIZE))
Packit 875988
        {
Packit 875988
          *upload_data_size = 0;
Packit 875988
        }
Packit 875988
      else
Packit 875988
        {
Packit 875988
          return MHD_NO;
Packit 875988
        }
Packit 875988
      *done = 1;
Packit 875988
      return MHD_YES;
Packit 875988
    }
Packit 875988
  response = MHD_create_response_from_buffer (strlen (url),
Packit 875988
					      (void *) url, 
Packit 875988
					      MHD_RESPMEM_MUST_COPY);
Packit 875988
  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
Packit 875988
  MHD_destroy_response (response);
Packit 875988
  return ret;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testInternalPut ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  struct CBC cbc;
Packit 875988
  unsigned int pos = 0;
Packit 875988
  int done_flag = 0;
Packit 875988
  char buf[2048];
Packit 875988
  int i;
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  cbc.pos = 0;
Packit 875988
  d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG */ ,
Packit 875988
                        11080,
Packit 875988
                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 1;
Packit 875988
  zzuf_socat_start ();
Packit 875988
  for (i = 0; i < LOOP_COUNT; i++)
Packit 875988
    {
Packit 875988
      fprintf (stderr, ".");
Packit 875988
Packit 875988
      c = curl_easy_init ();
Packit 875988
      curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11081/hello_world");
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
      curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
Packit 875988
      curl_easy_setopt (c, CURLOPT_READDATA, &pos;;
Packit 875988
      curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
Packit 875988
      curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
Packit 875988
      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
      curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
Packit 875988
      if (oneone)
Packit 875988
        curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
      else
Packit 875988
        curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
Packit 875988
      /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
       *   setting NOSIGNAL results in really weird
Packit 875988
       *   crashes on my system! */
Packit 875988
      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
      curl_easy_perform (c);
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
    }
Packit 875988
  fprintf (stderr, "\n");
Packit 875988
  zzuf_socat_stop ();
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
static int
Packit 875988
testMultithreadedPut ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  struct CBC cbc;
Packit 875988
  unsigned int pos = 0;
Packit 875988
  int done_flag = 0;
Packit 875988
  char buf[2048];
Packit 875988
  int i;
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  cbc.pos = 0;
Packit 875988
  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG */ ,
Packit 875988
                        11080,
Packit 875988
                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 16;
Packit 875988
  zzuf_socat_start ();
Packit 875988
  for (i = 0; i < LOOP_COUNT; i++)
Packit 875988
    {
Packit 875988
      fprintf (stderr, ".");
Packit 875988
Packit 875988
      c = curl_easy_init ();
Packit 875988
      curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11081/hello_world");
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
      curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
Packit 875988
      curl_easy_setopt (c, CURLOPT_READDATA, &pos;;
Packit 875988
      curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
Packit 875988
      curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
Packit 875988
      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
      curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
Packit 875988
      if (oneone)
Packit 875988
        curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
      else
Packit 875988
        curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
Packit 875988
      /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
       *   setting NOSIGNAL results in really weird
Packit 875988
       *   crashes on my system! */
Packit 875988
      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
      curl_easy_perform (c);
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
    }
Packit 875988
  fprintf (stderr, "\n");
Packit 875988
  zzuf_socat_stop ();
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testExternalPut ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  struct CBC cbc;
Packit 875988
  CURLM *multi;
Packit 875988
  CURLMcode mret;
Packit 875988
  fd_set rs;
Packit 875988
  fd_set ws;
Packit 875988
  fd_set es;
Packit 875988
  int max;
Packit 875988
  int running;
Packit 875988
  time_t start;
Packit 875988
  struct timeval tv;
Packit 875988
  unsigned int pos = 0;
Packit 875988
  int done_flag = 0;
Packit 875988
  char buf[2048];
Packit 875988
  int i;
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  cbc.pos = 0;
Packit 875988
  multi = NULL;
Packit 875988
  d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_ERROR_LOG */,
Packit 875988
                        11080,
Packit 875988
                        NULL, NULL, &ahc_echo, &done_flag,
Packit 875988
                        MHD_OPTION_CONNECTION_MEMORY_LIMIT,
Packit 875988
                        (size_t) (PUT_SIZE * 4), MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 256;
Packit 875988
  multi = curl_multi_init ();
Packit 875988
  if (multi == NULL)
Packit 875988
    {
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 512;
Packit 875988
    }
Packit 875988
  zzuf_socat_start ();
Packit 875988
  for (i = 0; i < LOOP_COUNT; i++)
Packit 875988
    {
Packit 875988
      fprintf (stderr, ".");
Packit 875988
Packit 875988
      c = curl_easy_init ();
Packit 875988
      curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11081/hello_world");
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
      curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
Packit 875988
      curl_easy_setopt (c, CURLOPT_READDATA, &pos;;
Packit 875988
      curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
Packit 875988
      curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
Packit 875988
      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
      curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
Packit 875988
      if (oneone)
Packit 875988
        curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
      else
Packit 875988
        curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
Packit 875988
      /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
       *   setting NOSIGNAL results in really weird
Packit 875988
       *   crashes on my system! */
Packit 875988
      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
Packit 875988
Packit 875988
Packit 875988
      mret = curl_multi_add_handle (multi, c);
Packit 875988
      if (mret != CURLM_OK)
Packit 875988
        {
Packit 875988
          curl_multi_cleanup (multi);
Packit 875988
          curl_easy_cleanup (c);
Packit 875988
          zzuf_socat_stop ();
Packit 875988
          MHD_stop_daemon (d);
Packit 875988
          return 1024;
Packit 875988
        }
Packit 875988
      start = time (NULL);
Packit 875988
      while ((time (NULL) - start < 5) && (c != NULL))
Packit 875988
        {
Packit 875988
          max = 0;
Packit 875988
          FD_ZERO (&rs);
Packit 875988
          FD_ZERO (&ws);
Packit 875988
          FD_ZERO (&es);
Packit 875988
          curl_multi_perform (multi, &running);
Packit 875988
          mret = curl_multi_fdset (multi, &rs, &ws, &es, &max;;
Packit 875988
          if (mret != CURLM_OK)
Packit 875988
            {
Packit 875988
              curl_multi_remove_handle (multi, c);
Packit 875988
              curl_multi_cleanup (multi);
Packit 875988
              curl_easy_cleanup (c);
Packit 875988
              zzuf_socat_stop ();
Packit 875988
              MHD_stop_daemon (d);
Packit 875988
              return 2048;
Packit 875988
            }
Packit 875988
          if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
Packit 875988
            {
Packit 875988
              curl_multi_remove_handle (multi, c);
Packit 875988
              curl_multi_cleanup (multi);
Packit 875988
              curl_easy_cleanup (c);
Packit 875988
              zzuf_socat_stop ();
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
          select (max + 1, &rs, &ws, &es, &tv;;
Packit 875988
          curl_multi_perform (multi, &running);
Packit 875988
          if (running == 0)
Packit 875988
            {
Packit 875988
              curl_multi_info_read (multi, &running);
Packit 875988
              curl_multi_remove_handle (multi, c);
Packit 875988
              curl_easy_cleanup (c);
Packit 875988
              c = NULL;
Packit 875988
            }
Packit 875988
          MHD_run (d);
Packit 875988
        }
Packit 875988
      if (c != NULL)
Packit 875988
        {
Packit 875988
          curl_multi_remove_handle (multi, c);
Packit 875988
          curl_easy_cleanup (c);
Packit 875988
        }
Packit 875988
    }
Packit 875988
  fprintf (stderr, "\n");
Packit 875988
  zzuf_socat_stop ();
Packit 875988
  curl_multi_cleanup (multi);
Packit 875988
  MHD_stop_daemon (d);
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
  oneone = (NULL != strrchr (argv[0], (int) '/')) ?
Packit 875988
    (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
Packit 875988
  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
Packit 875988
    return 2;
Packit 875988
  put_buffer = malloc (PUT_SIZE);
Packit 875988
  memset (put_buffer, 1, PUT_SIZE);
Packit 875988
  errorCount += testInternalPut ();
Packit 875988
  errorCount += testMultithreadedPut ();
Packit 875988
  errorCount += testExternalPut ();
Packit 875988
  free (put_buffer);
Packit 875988
  if (errorCount != 0)
Packit 875988
    fprintf (stderr, "Error (code: %u)\n", errorCount);
Packit 875988
  curl_global_cleanup ();
Packit 875988
  return errorCount != 0;       /* 0 == pass */
Packit 875988
}