From c7818b51b52649e1b35b61d8e6e6a855399eba9a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 29 Mar 2013 15:57:58 +0000 Subject: -renaming for consistency --- src/testzzuf/Makefile.am | 107 +++++----- src/testzzuf/daemontest_get.c | 314 --------------------------- src/testzzuf/daemontest_get_chunked.c | 330 ----------------------------- src/testzzuf/daemontest_large_put.c | 382 --------------------------------- src/testzzuf/daemontest_long_header.c | 232 -------------------- src/testzzuf/daemontest_post.c | 372 -------------------------------- src/testzzuf/daemontest_postform.c | 387 ---------------------------------- src/testzzuf/daemontest_put.c | 361 ------------------------------- src/testzzuf/daemontest_put_chunked.c | 371 -------------------------------- src/testzzuf/test_get.c | 314 +++++++++++++++++++++++++++ src/testzzuf/test_get_chunked.c | 330 +++++++++++++++++++++++++++++ src/testzzuf/test_long_header.c | 232 ++++++++++++++++++++ src/testzzuf/test_post.c | 372 ++++++++++++++++++++++++++++++++ src/testzzuf/test_post_form.c | 387 ++++++++++++++++++++++++++++++++++ src/testzzuf/test_put.c | 361 +++++++++++++++++++++++++++++++ src/testzzuf/test_put_chunked.c | 371 ++++++++++++++++++++++++++++++++ src/testzzuf/test_put_large.c | 382 +++++++++++++++++++++++++++++++++ 17 files changed, 2803 insertions(+), 2802 deletions(-) delete mode 100644 src/testzzuf/daemontest_get.c delete mode 100644 src/testzzuf/daemontest_get_chunked.c delete mode 100644 src/testzzuf/daemontest_large_put.c delete mode 100644 src/testzzuf/daemontest_long_header.c delete mode 100644 src/testzzuf/daemontest_post.c delete mode 100644 src/testzzuf/daemontest_postform.c delete mode 100644 src/testzzuf/daemontest_put.c delete mode 100644 src/testzzuf/daemontest_put_chunked.c create mode 100644 src/testzzuf/test_get.c create mode 100644 src/testzzuf/test_get_chunked.c create mode 100644 src/testzzuf/test_long_header.c create mode 100644 src/testzzuf/test_post.c create mode 100644 src/testzzuf/test_post_form.c create mode 100644 src/testzzuf/test_put.c create mode 100644 src/testzzuf/test_put_chunked.c create mode 100644 src/testzzuf/test_put_large.c (limited to 'src/testzzuf') diff --git a/src/testzzuf/Makefile.am b/src/testzzuf/Makefile.am index a50c9e3a..688f0cbb 100644 --- a/src/testzzuf/Makefile.am +++ b/src/testzzuf/Makefile.am @@ -13,97 +13,98 @@ INCLUDES = $(PLIBC_INCLUDE) -I$(top_srcdir)/src/include EXTRA_DIST = README socat.c check_PROGRAMS = \ - daemontest_get \ - daemontest_post \ - daemontest_postform \ - daemontest_put \ - daemontest_large_put \ - daemontest_get11 \ - daemontest_post11 \ - daemontest_postform11 \ - daemontest_put11 \ - daemontest_large_put11 \ - daemontest_long_header \ - daemontest_get_chunked \ - daemontest_put_chunked + test_get \ + test_get_chunked \ + test_post \ + test_post_form \ + test_put \ + test_put_chunked \ + test_put_large \ + test_get11 \ + test_post11 \ + test_post_form11 \ + test_put11 \ + test_put_large11 \ + test_long_header TESTS = $(check_PROGRAMS) -daemontest_get_SOURCES = \ - daemontest_get.c -daemontest_get_LDADD = \ +test_get_SOURCES = \ + test_get.c +test_get_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_get_chunked_SOURCES = \ - daemontest_get_chunked.c -daemontest_get_chunked_LDADD = \ +test_get_chunked_SOURCES = \ + test_get_chunked.c +test_get_chunked_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_post_SOURCES = \ - daemontest_post.c -daemontest_post_LDADD = \ +test_post_SOURCES = \ + test_post.c +test_post_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_postform_SOURCES = \ - daemontest_postform.c -daemontest_postform_LDADD = \ +test_post_form_SOURCES = \ + test_post_form.c +test_post_form_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_put_SOURCES = \ - daemontest_put.c -daemontest_put_LDADD = \ +test_put_SOURCES = \ + test_put.c +test_put_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_put_chunked_SOURCES = \ - daemontest_put_chunked.c -daemontest_put_chunked_LDADD = \ +test_put_chunked_SOURCES = \ + test_put_chunked.c +test_put_chunked_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_get11_SOURCES = \ - daemontest_get.c -daemontest_get11_LDADD = \ +test_put_large_SOURCES = \ + test_put_large.c +test_put_large_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_post11_SOURCES = \ - daemontest_post.c -daemontest_post11_LDADD = \ + + +test_get11_SOURCES = \ + test_get.c +test_get11_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_postform11_SOURCES = \ - daemontest_postform.c -daemontest_postform11_LDADD = \ +test_post11_SOURCES = \ + test_post.c +test_post11_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_put11_SOURCES = \ - daemontest_put.c -daemontest_put11_LDADD = \ +test_post_form11_SOURCES = \ + test_post_form.c +test_post_form11_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ - -daemontest_large_put_SOURCES = \ - daemontest_large_put.c -daemontest_large_put_LDADD = \ +test_put11_SOURCES = \ + test_put.c +test_put11_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_large_put11_SOURCES = \ - daemontest_large_put.c -daemontest_large_put11_LDADD = \ +test_put_large11_SOURCES = \ + test_put_large.c +test_put_large11_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ -daemontest_long_header_SOURCES = \ - daemontest_long_header.c -daemontest_long_header_LDADD = \ +test_long_header_SOURCES = \ + test_long_header.c +test_long_header_LDADD = \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ diff --git a/src/testzzuf/daemontest_get.c b/src/testzzuf/daemontest_get.c deleted file mode 100644 index 4aed7fb5..00000000 --- a/src/testzzuf/daemontest_get.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - This file is part of libmicrohttpd - (C) 2007, 2008 Christian Grothoff - - libmicrohttpd 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 - option) any later version. - - libmicrohttpd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file daemontest_get.c - * @brief Testcase for libmicrohttpd GET operations - * @author Christian Grothoff - */ - -#include "MHD_config.h" -#include "platform.h" -#include -#include -#include -#include -#include - -#ifndef WINDOWS -#include -#endif - -#include "socat.c" - -static int oneone; - -struct CBC -{ - char *buf; - size_t pos; - size_t size; -}; - -static size_t -copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) -{ - struct CBC *cbc = ctx; - - if (cbc->pos + size * nmemb > cbc->size) - return 0; /* overflow */ - memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); - cbc->pos += size * nmemb; - return size * nmemb; -} - -static int -ahc_echo (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, size_t *upload_data_size, - void **unused) -{ - static int ptr; - const char *me = cls; - struct MHD_Response *response; - int ret; - - if (0 != strcmp (me, method)) - return MHD_NO; /* unexpected method */ - if (&ptr != *unused) - { - *unused = &ptr; - return MHD_YES; - } - *unused = NULL; - response = MHD_create_response_from_buffer (strlen (url), - (void *) url, - MHD_RESPMEM_MUST_COPY); - ret = MHD_queue_response (connection, MHD_HTTP_OK, response); - MHD_destroy_response (response); - if (ret == MHD_NO) - abort (); - return ret; -} - - -static int -testInternalGet () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , - 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); - if (d == NULL) - return 1; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - -static int -testMultithreadedGet () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , - 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); - if (d == NULL) - return 16; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - - -static int -testExternalGet () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - CURLM *multi; - CURLMcode mret; - fd_set rs; - fd_set ws; - fd_set es; - int max; - int running; - time_t start; - struct timeval tv; - int i; - - multi = NULL; - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , - 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); - if (d == NULL) - return 256; - multi = curl_multi_init (); - if (multi == NULL) - { - MHD_stop_daemon (d); - return 512; - } - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - mret = curl_multi_add_handle (multi, c); - if (mret != CURLM_OK) - { - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 1024; - } - start = time (NULL); - while ((time (NULL) - start < 5) && (c != NULL)) - { - max = 0; - FD_ZERO (&rs); - FD_ZERO (&ws); - FD_ZERO (&es); - curl_multi_perform (multi, &running); - mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); - if (mret != CURLM_OK) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 2048; - } - if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 4096; - } - tv.tv_sec = 0; - tv.tv_usec = 1000; - select (max + 1, &rs, &ws, &es, &tv); - curl_multi_perform (multi, &running); - if (running == 0) - { - curl_multi_info_read (multi, &running); - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - c = NULL; - } - MHD_run (d); - } - if (c != NULL) - { - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - } - } - fprintf (stderr, "\n"); - curl_multi_cleanup (multi); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - - - -int -main (int argc, char *const *argv) -{ - unsigned int errorCount = 0; - - oneone = NULL != strstr (argv[0], "11"); - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return 2; - errorCount += testInternalGet (); - errorCount += testMultithreadedGet (); - errorCount += testExternalGet (); - if (errorCount != 0) - fprintf (stderr, "Error (code: %u)\n", errorCount); - curl_global_cleanup (); - return errorCount != 0; /* 0 == pass */ -} diff --git a/src/testzzuf/daemontest_get_chunked.c b/src/testzzuf/daemontest_get_chunked.c deleted file mode 100644 index 35eed49d..00000000 --- a/src/testzzuf/daemontest_get_chunked.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - This file is part of libmicrohttpd - (C) 2007, 2008 Christian Grothoff - - libmicrohttpd 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 - option) any later version. - - libmicrohttpd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file daemontest_get_chunked.c - * @brief Testcase for libmicrohttpd GET operations with chunked content encoding - * @author Christian Grothoff - */ - -#include "MHD_config.h" -#include "platform.h" -#include -#include -#include -#include -#include - -#ifndef WINDOWS -#include -#endif - -#include "socat.c" - -struct CBC -{ - char *buf; - size_t pos; - size_t size; -}; - -static size_t -copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) -{ - struct CBC *cbc = ctx; - - if (cbc->pos + size * nmemb > cbc->size) - return 0; /* overflow */ - memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); - cbc->pos += size * nmemb; - return size * nmemb; -} - -/** - * MHD content reader callback that returns - * data in chunks. - */ -static ssize_t -crc (void *cls, uint64_t pos, char *buf, size_t max) -{ - struct MHD_Response **responseptr = cls; - - if (pos == 128 * 10) - { - MHD_add_response_header (*responseptr, "Footer", "working"); - return MHD_CONTENT_READER_END_OF_STREAM; - } - if (max < 128) - abort (); /* should not happen in this testcase... */ - memset (buf, 'A' + (pos / 128), 128); - return 128; -} - -/** - * Dummy function that does nothing. - */ -static void -crcf (void *ptr) -{ - free (ptr); -} - -static int -ahc_echo (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, size_t *upload_data_size, void **ptr) -{ - static int aptr; - const char *me = cls; - struct MHD_Response *response; - struct MHD_Response **responseptr; - int ret; - - if (0 != strcmp (me, method)) - return MHD_NO; /* unexpected method */ - if (&aptr != *ptr) - { - /* do never respond on first call */ - *ptr = &aptr; - return MHD_YES; - } - responseptr = malloc (sizeof (struct MHD_Response *)); - response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, - 1024, - &crc, responseptr, &crcf); - *responseptr = response; - ret = MHD_queue_response (connection, MHD_HTTP_OK, response); - MHD_destroy_response (response); - return ret; -} - -static int -testInternalGet () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , - 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); - if (d == NULL) - return 1; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - -static int -testMultithreadedGet () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , - 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); - if (d == NULL) - return 16; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - - -static int -testExternalGet () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - CURLM *multi; - CURLMcode mret; - fd_set rs; - fd_set ws; - fd_set es; - int max; - int running; - time_t start; - struct timeval tv; - int i; - - multi = NULL; - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , - 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); - if (d == NULL) - return 256; - multi = curl_multi_init (); - if (multi == NULL) - { - MHD_stop_daemon (d); - return 512; - } - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - mret = curl_multi_add_handle (multi, c); - if (mret != CURLM_OK) - { - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 1024; - } - start = time (NULL); - while ((time (NULL) - start < 5) && (c != NULL)) - { - max = 0; - FD_ZERO (&rs); - FD_ZERO (&ws); - FD_ZERO (&es); - curl_multi_perform (multi, &running); - mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); - if (mret != CURLM_OK) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 2048; - } - if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 4096; - } - tv.tv_sec = 0; - tv.tv_usec = 1000; - select (max + 1, &rs, &ws, &es, &tv); - curl_multi_perform (multi, &running); - if (running == 0) - { - curl_multi_info_read (multi, &running); - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - c = NULL; - } - MHD_run (d); - } - if (c != NULL) - { - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - } - } - fprintf (stderr, "\n"); - curl_multi_cleanup (multi); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - - - -int -main (int argc, char *const *argv) -{ - unsigned int errorCount = 0; - - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return 2; - errorCount += testInternalGet (); - errorCount += testMultithreadedGet (); - errorCount += testExternalGet (); - if (errorCount != 0) - fprintf (stderr, "Error (code: %u)\n", errorCount); - curl_global_cleanup (); - return errorCount != 0; /* 0 == pass */ -} diff --git a/src/testzzuf/daemontest_large_put.c b/src/testzzuf/daemontest_large_put.c deleted file mode 100644 index 10fc8b06..00000000 --- a/src/testzzuf/daemontest_large_put.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - This file is part of libmicrohttpd - (C) 2007, 2008 Christian Grothoff - - libmicrohttpd 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 - option) any later version. - - libmicrohttpd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file daemontest_large_put.c - * @brief Testcase for libmicrohttpd PUT operations - * @author Christian Grothoff - */ - -#include "MHD_config.h" -#include "platform.h" -#include -#include -#include -#include -#include - -#ifndef WINDOWS -#include -#endif - -#include "socat.c" - -static int oneone; - -/** - * Do not make this much larger since we will hit the - * MHD default buffer limit and the test code is not - * written for incremental upload processing... - */ -#define PUT_SIZE (256 * 1024) - -static char *put_buffer; - -struct CBC -{ - char *buf; - size_t pos; - size_t size; -}; - -static size_t -putBuffer (void *stream, size_t size, size_t nmemb, void *ptr) -{ - unsigned int *pos = ptr; - unsigned int wrt; - - wrt = size * nmemb; - if (wrt > PUT_SIZE - (*pos)) - wrt = PUT_SIZE - (*pos); - memcpy (stream, &put_buffer[*pos], wrt); - (*pos) += wrt; - return wrt; -} - -static size_t -copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) -{ - struct CBC *cbc = ctx; - - if (cbc->pos + size * nmemb > cbc->size) - return 0; /* overflow */ - memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); - cbc->pos += size * nmemb; - return size * nmemb; -} - -static int -ahc_echo (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, size_t *upload_data_size, - void **unused) -{ - int *done = cls; - struct MHD_Response *response; - int ret; - - if (0 != strcmp ("PUT", method)) - return MHD_NO; /* unexpected method */ - if ((*done) == 0) - { - if (*upload_data_size != PUT_SIZE) - { -#if 0 - fprintf (stderr, - "Waiting for more data (%u/%u)...\n", - *upload_data_size, PUT_SIZE); -#endif - return MHD_YES; /* not yet ready */ - } - if (0 == memcmp (upload_data, put_buffer, PUT_SIZE)) - { - *upload_data_size = 0; - } - else - { - return MHD_NO; - } - *done = 1; - return MHD_YES; - } - response = MHD_create_response_from_buffer (strlen (url), - (void *) url, - MHD_RESPMEM_MUST_COPY); - ret = MHD_queue_response (connection, MHD_HTTP_OK, response); - MHD_destroy_response (response); - return ret; -} - - -static int -testInternalPut () -{ - struct MHD_Daemon *d; - CURL *c; - struct CBC cbc; - unsigned int pos = 0; - int done_flag = 0; - char buf[2048]; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , - 11080, - NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); - if (d == NULL) - return 1; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); - curl_easy_setopt (c, CURLOPT_READDATA, &pos); - curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); - curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - -static int -testMultithreadedPut () -{ - struct MHD_Daemon *d; - CURL *c; - struct CBC cbc; - unsigned int pos = 0; - int done_flag = 0; - char buf[2048]; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , - 11080, - NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); - if (d == NULL) - return 16; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); - curl_easy_setopt (c, CURLOPT_READDATA, &pos); - curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); - curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - - -static int -testExternalPut () -{ - struct MHD_Daemon *d; - CURL *c; - struct CBC cbc; - CURLM *multi; - CURLMcode mret; - fd_set rs; - fd_set ws; - fd_set es; - int max; - int running; - time_t start; - struct timeval tv; - unsigned int pos = 0; - int done_flag = 0; - char buf[2048]; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - multi = NULL; - d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */, - 11080, - NULL, NULL, &ahc_echo, &done_flag, - MHD_OPTION_CONNECTION_MEMORY_LIMIT, - (size_t) (PUT_SIZE * 4), MHD_OPTION_END); - if (d == NULL) - return 256; - multi = curl_multi_init (); - if (multi == NULL) - { - MHD_stop_daemon (d); - return 512; - } - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); - curl_easy_setopt (c, CURLOPT_READDATA, &pos); - curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); - curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - - - - mret = curl_multi_add_handle (multi, c); - if (mret != CURLM_OK) - { - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 1024; - } - start = time (NULL); - while ((time (NULL) - start < 5) && (c != NULL)) - { - max = 0; - FD_ZERO (&rs); - FD_ZERO (&ws); - FD_ZERO (&es); - curl_multi_perform (multi, &running); - mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); - if (mret != CURLM_OK) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 2048; - } - if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 4096; - } - tv.tv_sec = 0; - tv.tv_usec = 1000; - select (max + 1, &rs, &ws, &es, &tv); - curl_multi_perform (multi, &running); - if (running == 0) - { - curl_multi_info_read (multi, &running); - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - c = NULL; - } - MHD_run (d); - } - if (c != NULL) - { - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - } - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - curl_multi_cleanup (multi); - MHD_stop_daemon (d); - return 0; -} - - - -int -main (int argc, char *const *argv) -{ - unsigned int errorCount = 0; - - oneone = NULL != strstr (argv[0], "11"); - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return 2; - put_buffer = malloc (PUT_SIZE); - memset (put_buffer, 1, PUT_SIZE); - errorCount += testInternalPut (); - errorCount += testMultithreadedPut (); - errorCount += testExternalPut (); - free (put_buffer); - if (errorCount != 0) - fprintf (stderr, "Error (code: %u)\n", errorCount); - curl_global_cleanup (); - return errorCount != 0; /* 0 == pass */ -} diff --git a/src/testzzuf/daemontest_long_header.c b/src/testzzuf/daemontest_long_header.c deleted file mode 100644 index d285768f..00000000 --- a/src/testzzuf/daemontest_long_header.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - This file is part of libmicrohttpd - (C) 2007, 2008 Christian Grothoff - - libmicrohttpd 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 - option) any later version. - - libmicrohttpd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file daemontest_long_header.c - * @brief Testcase for libmicrohttpd handling of very long headers - * @author Christian Grothoff - */ - -#include "MHD_config.h" -#include "platform.h" -#include -#include -#include -#include -#include - -#ifndef WINDOWS -#include -#endif - -#include "socat.c" - -/** - * We will set the memory available per connection to - * half of this value, so the actual value does not have - * to be big at all... - */ -#define VERY_LONG (1024*10) - -static int oneone; - -static int -apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen) -{ - return MHD_YES; -} - -struct CBC -{ - char *buf; - size_t pos; - size_t size; -}; - -static size_t -copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) -{ - return size * nmemb; -} - -static int -ahc_echo (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, size_t *upload_data_size, - void **unused) -{ - const char *me = cls; - struct MHD_Response *response; - int ret; - - if (0 != strcmp (me, method)) - return MHD_NO; /* unexpected method */ - response = MHD_create_response_from_buffer (strlen (url), - (void *) url, - MHD_RESPMEM_MUST_COPY); - ret = MHD_queue_response (connection, MHD_HTTP_OK, response); - MHD_destroy_response (response); - return ret; -} - - -static int -testLongUrlGet () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - char *url; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , - 11080, - &apc_all, - NULL, - &ahc_echo, - "GET", - MHD_OPTION_CONNECTION_MEMORY_LIMIT, - (size_t) (VERY_LONG / 2), MHD_OPTION_END); - - if (d == NULL) - return 1; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - - c = curl_easy_init (); - url = malloc (VERY_LONG); - memset (url, 'a', VERY_LONG); - url[VERY_LONG - 1] = '\0'; - memcpy (url, "http://localhost:11081/", - strlen ("http://localhost:11081/")); - curl_easy_setopt (c, CURLOPT_URL, url); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - - MHD_stop_daemon (d); - free (url); - return 0; -} - - -static int -testLongHeaderGet () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - char *url; - struct curl_slist *header = NULL; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , - 11080, - &apc_all, - NULL, - &ahc_echo, - "GET", - MHD_OPTION_CONNECTION_MEMORY_LIMIT, - (size_t) (VERY_LONG / 2), MHD_OPTION_END); - if (d == NULL) - return 16; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - url = malloc (VERY_LONG); - memset (url, 'a', VERY_LONG); - url[VERY_LONG - 1] = '\0'; - url[VERY_LONG / 2] = ':'; - url[VERY_LONG / 2 + 1] = ' '; - header = curl_slist_append (header, url); - - curl_easy_setopt (c, CURLOPT_HTTPHEADER, header); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_slist_free_all (header); - header = NULL; - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - - MHD_stop_daemon (d); - free (url); - return 0; -} - -int -main (int argc, char *const *argv) -{ - unsigned int errorCount = 0; - - oneone = NULL != strstr (argv[0], "11"); - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return 2; - errorCount += testLongUrlGet (); - errorCount += testLongHeaderGet (); - if (errorCount != 0) - fprintf (stderr, "Error (code: %u)\n", errorCount); - curl_global_cleanup (); - return errorCount != 0; /* 0 == pass */ -} diff --git a/src/testzzuf/daemontest_post.c b/src/testzzuf/daemontest_post.c deleted file mode 100644 index 66077b4f..00000000 --- a/src/testzzuf/daemontest_post.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - This file is part of libmicrohttpd - (C) 2007, 2008 Christian Grothoff - - libmicrohttpd 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 - option) any later version. - - libmicrohttpd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file daemontest_post.c - * @brief Testcase for libmicrohttpd POST operations using URL-encoding - * @author Christian Grothoff - */ - -#include "MHD_config.h" -#include "platform.h" -#include -#include -#include -#include -#include - -#ifndef WINDOWS -#include -#endif - - -#include "socat.c" - -#define POST_DATA "name=daniel&project=curl" - -static int oneone; - -struct CBC -{ - char *buf; - size_t pos; - size_t size; -}; - -static size_t -copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) -{ - struct CBC *cbc = ctx; - - if (cbc->pos + size * nmemb > cbc->size) - return 0; /* overflow */ - memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); - cbc->pos += size * nmemb; - return size * nmemb; -} - -/** - * Note that this post_iterator is not perfect - * in that it fails to support incremental processing. - * (to be fixed in the future) - */ -static int -post_iterator (void *cls, - enum MHD_ValueKind kind, - const char *key, - const char *filename, - const char *content_type, - const char *transfer_encoding, - const char *value, uint64_t off, size_t size) -{ - int *eok = cls; - - if ((0 == strcmp (key, "name")) && - (size == strlen ("daniel")) && (0 == strncmp (value, "daniel", size))) - (*eok) |= 1; - if ((0 == strcmp (key, "project")) && - (size == strlen ("curl")) && (0 == strncmp (value, "curl", size))) - (*eok) |= 2; - return MHD_YES; -} - -static int -ahc_echo (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, size_t *upload_data_size, - void **unused) -{ - static int eok; - struct MHD_Response *response; - struct MHD_PostProcessor *pp; - int ret; - - if (0 != strcmp ("POST", method)) - { - return MHD_NO; /* unexpected method */ - } - pp = *unused; - if (pp == NULL) - { - eok = 0; - pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok); - *unused = pp; - } - MHD_post_process (pp, upload_data, *upload_data_size); - if ((eok == 3) && (0 == *upload_data_size)) - { - response = MHD_create_response_from_buffer (strlen (url), - (void *) url, - MHD_RESPMEM_MUST_COPY); - ret = MHD_queue_response (connection, MHD_HTTP_OK, response); - MHD_destroy_response (response); - MHD_destroy_post_processor (pp); - *unused = NULL; - return ret; - } - *upload_data_size = 0; - return MHD_YES; -} - - -static int -testInternalPost () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , - 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); - if (d == NULL) - return 1; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); - curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); - curl_easy_setopt (c, CURLOPT_POST, 1L); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - - return 0; -} - -static int -testMultithreadedPost () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , - 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); - if (d == NULL) - return 16; - - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); - curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); - curl_easy_setopt (c, CURLOPT_POST, 1L); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - - MHD_stop_daemon (d); - return 0; -} - - -static int -testExternalPost () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - CURLM *multi; - CURLMcode mret; - fd_set rs; - fd_set ws; - fd_set es; - int max; - int running; - time_t start; - struct timeval tv; - int i; - - multi = NULL; - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , - 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); - if (d == NULL) - return 256; - multi = curl_multi_init (); - if (multi == NULL) - { - MHD_stop_daemon (d); - return 512; - } - - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - - - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); - curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); - curl_easy_setopt (c, CURLOPT_POST, 1L); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - - - mret = curl_multi_add_handle (multi, c); - if (mret != CURLM_OK) - { - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 1024; - } - start = time (NULL); - while ((time (NULL) - start < 5) && (c != NULL)) - { - max = 0; - FD_ZERO (&rs); - FD_ZERO (&ws); - FD_ZERO (&es); - curl_multi_perform (multi, &running); - mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); - if (mret != CURLM_OK) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 2048; - } - if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 4096; - } - tv.tv_sec = 0; - tv.tv_usec = 1000; - select (max + 1, &rs, &ws, &es, &tv); - curl_multi_perform (multi, &running); - if (running == 0) - { - curl_multi_info_read (multi, &running); - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - c = NULL; - } - MHD_run (d); - } - if (c != NULL) - { - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - } - - } - fprintf (stderr, "\n"); - curl_multi_cleanup (multi); - zzuf_socat_stop (); - - MHD_stop_daemon (d); - return 0; -} - - - -int -main (int argc, char *const *argv) -{ - unsigned int errorCount = 0; - - oneone = NULL != strstr (argv[0], "11"); - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return 2; - errorCount += testInternalPost (); - errorCount += testMultithreadedPost (); - errorCount += testExternalPost (); - if (errorCount != 0) - fprintf (stderr, "Error (code: %u)\n", errorCount); - curl_global_cleanup (); - return errorCount != 0; /* 0 == pass */ -} diff --git a/src/testzzuf/daemontest_postform.c b/src/testzzuf/daemontest_postform.c deleted file mode 100644 index 873c7fef..00000000 --- a/src/testzzuf/daemontest_postform.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - This file is part of libmicrohttpd - (C) 2007, 2008 Christian Grothoff - - libmicrohttpd 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 - option) any later version. - - libmicrohttpd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file daemontest_post.c - * @brief Testcase for libmicrohttpd POST operations using multipart/postform data - * @author Christian Grothoff - */ - -#include "MHD_config.h" -#include "platform.h" -#include -#include -#include -#include -#include - -#ifndef WINDOWS -#include -#endif - - -#include "socat.c" - -static int oneone; - -struct CBC -{ - char *buf; - size_t pos; - size_t size; -}; - -static size_t -copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) -{ - struct CBC *cbc = ctx; - - if (cbc->pos + size * nmemb > cbc->size) - return 0; /* overflow */ - memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); - cbc->pos += size * nmemb; - return size * nmemb; -} - -/** - * Note that this post_iterator is not perfect - * in that it fails to support incremental processing. - * (to be fixed in the future) - */ -static int -post_iterator (void *cls, - enum MHD_ValueKind kind, - const char *key, - const char *filename, - const char *content_type, - const char *transfer_encoding, - const char *value, uint64_t off, size_t size) -{ - int *eok = cls; - - if (key == NULL) - return MHD_YES; -#if 0 - fprintf (stderr, "PI sees %s-%.*s\n", key, size, value); -#endif - if ((0 == strcmp (key, "name")) && - (size == strlen ("daniel")) && (0 == strncmp (value, "daniel", size))) - (*eok) |= 1; - if ((0 == strcmp (key, "project")) && - (size == strlen ("curl")) && (0 == strncmp (value, "curl", size))) - (*eok) |= 2; - return MHD_YES; -} - -static int -ahc_echo (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, size_t *upload_data_size, - void **unused) -{ - static int eok; - struct MHD_Response *response; - struct MHD_PostProcessor *pp; - int ret; - - if (0 != strcmp ("POST", method)) - { - return MHD_NO; /* unexpected method */ - } - pp = *unused; - if (pp == NULL) - { - eok = 0; - pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok); - if (pp == NULL) - return MHD_NO; - *unused = pp; - } - MHD_post_process (pp, upload_data, *upload_data_size); - if ((eok == 3) && (0 == *upload_data_size)) - { - response = MHD_create_response_from_buffer (strlen (url), - (void *) url, - MHD_RESPMEM_MUST_COPY); - ret = MHD_queue_response (connection, MHD_HTTP_OK, response); - MHD_destroy_response (response); - MHD_destroy_post_processor (pp); - *unused = NULL; - return ret; - } - *upload_data_size = 0; - return MHD_YES; -} - -static struct curl_httppost * -make_form () -{ - struct curl_httppost *post = NULL; - struct curl_httppost *last = NULL; - - curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", - CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END); - curl_formadd (&post, &last, CURLFORM_COPYNAME, "project", - CURLFORM_COPYCONTENTS, "curl", CURLFORM_END); - return post; -} - - -static int -testInternalPost () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - int i; - struct curl_httppost *pd; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , - 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); - if (d == NULL) - return 1; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - pd = make_form (); - curl_easy_setopt (c, CURLOPT_HTTPPOST, pd); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - curl_formfree (pd); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - -static int -testMultithreadedPost () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - int i; - struct curl_httppost *pd; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , - 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); - if (d == NULL) - return 16; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - pd = make_form (); - curl_easy_setopt (c, CURLOPT_HTTPPOST, pd); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - curl_formfree (pd); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - - -static int -testExternalPost () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - CURLM *multi; - CURLMcode mret; - fd_set rs; - fd_set ws; - fd_set es; - int max; - int running; - time_t start; - struct timeval tv; - struct curl_httppost *pd; - int i; - - multi = NULL; - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , - 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); - if (d == NULL) - return 256; - multi = curl_multi_init (); - if (multi == NULL) - { - MHD_stop_daemon (d); - return 512; - } - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - pd = make_form (); - curl_easy_setopt (c, CURLOPT_HTTPPOST, pd); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - - - mret = curl_multi_add_handle (multi, c); - if (mret != CURLM_OK) - { - curl_multi_cleanup (multi); - curl_formfree (pd); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 1024; - } - start = time (NULL); - while ((time (NULL) - start < 5) && (c != NULL)) - { - max = 0; - FD_ZERO (&rs); - FD_ZERO (&ws); - FD_ZERO (&es); - curl_multi_perform (multi, &running); - mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); - if (mret != CURLM_OK) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - curl_formfree (pd); - return 2048; - } - if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - curl_formfree (pd); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 4096; - } - tv.tv_sec = 0; - tv.tv_usec = 1000; - select (max + 1, &rs, &ws, &es, &tv); - curl_multi_perform (multi, &running); - if (running == 0) - { - curl_multi_info_read (multi, &running); - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - c = NULL; - } - MHD_run (d); - } - if (c != NULL) - { - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - } - curl_formfree (pd); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - - MHD_stop_daemon (d); - return 0; -} - - - -int -main (int argc, char *const *argv) -{ - unsigned int errorCount = 0; - - oneone = NULL != strstr (argv[0], "11"); - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return 2; - errorCount += testInternalPost (); - errorCount += testMultithreadedPost (); - errorCount += testExternalPost (); - if (errorCount != 0) - fprintf (stderr, "Error (code: %u)\n", errorCount); - curl_global_cleanup (); - return errorCount != 0; /* 0 == pass */ -} diff --git a/src/testzzuf/daemontest_put.c b/src/testzzuf/daemontest_put.c deleted file mode 100644 index c658c39c..00000000 --- a/src/testzzuf/daemontest_put.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - This file is part of libmicrohttpd - (C) 2007, 2008 Christian Grothoff - - libmicrohttpd 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 - option) any later version. - - libmicrohttpd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file daemontest_put.c - * @brief Testcase for libmicrohttpd PUT operations - * @author Christian Grothoff - */ - -#include "MHD_config.h" -#include "platform.h" -#include -#include -#include -#include -#include - -#ifndef WINDOWS -#include -#endif - - -#include "socat.c" - -static int oneone; - -struct CBC -{ - char *buf; - size_t pos; - size_t size; -}; - -static size_t -putBuffer (void *stream, size_t size, size_t nmemb, void *ptr) -{ - unsigned int *pos = ptr; - unsigned int wrt; - - wrt = size * nmemb; - if (wrt > 8 - (*pos)) - wrt = 8 - (*pos); - memcpy (stream, &("Hello123"[*pos]), wrt); - (*pos) += wrt; - return wrt; -} - -static size_t -copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) -{ - struct CBC *cbc = ctx; - - if (cbc->pos + size * nmemb > cbc->size) - return 0; /* overflow */ - memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); - cbc->pos += size * nmemb; - return size * nmemb; -} - -static int -ahc_echo (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, size_t *upload_data_size, - void **unused) -{ - int *done = cls; - struct MHD_Response *response; - int ret; - - if (0 != strcmp ("PUT", method)) - return MHD_NO; /* unexpected method */ - if ((*done) == 0) - { - if (*upload_data_size != 8) - return MHD_YES; /* not yet ready */ - if (0 == memcmp (upload_data, "Hello123", 8)) - { - *upload_data_size = 0; - } - else - { - printf ("Invalid upload data `%8s'!\n", upload_data); - return MHD_NO; - } - *done = 1; - return MHD_YES; - } - response = MHD_create_response_from_buffer (strlen (url), - (void *) url, - MHD_RESPMEM_MUST_COPY); - ret = MHD_queue_response (connection, MHD_HTTP_OK, response); - MHD_destroy_response (response); - return ret; -} - - -static int -testInternalPut () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - unsigned int pos = 0; - int done_flag = 0; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , - 11080, - NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); - if (d == NULL) - return 1; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); - curl_easy_setopt (c, CURLOPT_READDATA, &pos); - curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); - curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - -static int -testMultithreadedPut () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - unsigned int pos = 0; - int done_flag = 0; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , - 11080, - NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); - if (d == NULL) - return 16; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); - curl_easy_setopt (c, CURLOPT_READDATA, &pos); - curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); - curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - - -static int -testExternalPut () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - CURLM *multi; - CURLMcode mret; - fd_set rs; - fd_set ws; - fd_set es; - int max; - int running; - time_t start; - struct timeval tv; - unsigned int pos = 0; - int done_flag = 0; - int i; - - multi = NULL; - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , - 11080, - NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); - if (d == NULL) - return 256; - multi = curl_multi_init (); - if (multi == NULL) - { - MHD_stop_daemon (d); - return 512; - } - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); - curl_easy_setopt (c, CURLOPT_READDATA, &pos); - curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); - curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - if (oneone) - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - else - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - - - - mret = curl_multi_add_handle (multi, c); - if (mret != CURLM_OK) - { - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 1024; - } - start = time (NULL); - while ((time (NULL) - start < 5) && (c != NULL)) - { - max = 0; - FD_ZERO (&rs); - FD_ZERO (&ws); - FD_ZERO (&es); - curl_multi_perform (multi, &running); - mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); - if (mret != CURLM_OK) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 2048; - } - if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 4096; - } - tv.tv_sec = 0; - tv.tv_usec = 1000; - select (max + 1, &rs, &ws, &es, &tv); - curl_multi_perform (multi, &running); - if (running == 0) - { - curl_multi_info_read (multi, &running); - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - c = NULL; - } - MHD_run (d); - } - if (c != NULL) - { - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - } - } - fprintf (stderr, "\n"); - curl_multi_cleanup (multi); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - - - -int -main (int argc, char *const *argv) -{ - unsigned int errorCount = 0; - - oneone = NULL != strstr (argv[0], "11"); - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return 2; - errorCount += testInternalPut (); - errorCount += testMultithreadedPut (); - errorCount += testExternalPut (); - if (errorCount != 0) - fprintf (stderr, "Error (code: %u)\n", errorCount); - curl_global_cleanup (); - return errorCount != 0; /* 0 == pass */ -} diff --git a/src/testzzuf/daemontest_put_chunked.c b/src/testzzuf/daemontest_put_chunked.c deleted file mode 100644 index 47d0f0ba..00000000 --- a/src/testzzuf/daemontest_put_chunked.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - This file is part of libmicrohttpd - (C) 2007, 2008 Christian Grothoff - - libmicrohttpd 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 - option) any later version. - - libmicrohttpd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file daemontest_put_chunked.c - * @brief Testcase for libmicrohttpd PUT operations with chunked encoding - * for the upload data - * @author Christian Grothoff - */ - -#include "MHD_config.h" -#include "platform.h" -#include -#include -#include -#include -#include - -#ifndef WINDOWS -#include -#endif - -#include "socat.c" - -struct CBC -{ - char *buf; - size_t pos; - size_t size; -}; - -static size_t -putBuffer (void *stream, size_t size, size_t nmemb, void *ptr) -{ - unsigned int *pos = ptr; - unsigned int wrt; - - wrt = size * nmemb; - if (wrt > 8 - (*pos)) - wrt = 8 - (*pos); - if (wrt > 4) - wrt = 4; /* only send half at first => force multiple chunks! */ - memcpy (stream, &("Hello123"[*pos]), wrt); - (*pos) += wrt; - return wrt; -} - -static size_t -copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) -{ - struct CBC *cbc = ctx; - - if (cbc->pos + size * nmemb > cbc->size) - return 0; /* overflow */ - memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); - cbc->pos += size * nmemb; - return size * nmemb; -} - -static int -ahc_echo (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, size_t *upload_data_size, - void **unused) -{ - int *done = cls; - struct MHD_Response *response; - int ret; - int have; - - if (0 != strcmp ("PUT", method)) - return MHD_NO; /* unexpected method */ - if ((*done) < 8) - { - have = *upload_data_size; - if (have + *done > 8) - { - return MHD_NO; - } - if (0 == memcmp (upload_data, &"Hello123"[*done], have)) - { - *done += have; - *upload_data_size = 0; - } - else - { - return MHD_NO; - } -#if 0 - fprintf (stderr, "Not ready for response: %u/%u\n", *done, 8); -#endif - return MHD_YES; - } - response = MHD_create_response_from_buffer (strlen (url), - (void *) url, - MHD_RESPMEM_MUST_COPY); - ret = MHD_queue_response (connection, MHD_HTTP_OK, response); - MHD_destroy_response (response); - return ret; -} - - -static int -testInternalPut () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - unsigned int pos = 0; - int done_flag = 0; - int i; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, - 11080, - NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); - if (d == NULL) - return 1; - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); - curl_easy_setopt (c, CURLOPT_READDATA, &pos); - curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); - /* - // by not giving the file size, we force chunking! - curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); - */ - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - curl_easy_perform (c); - curl_easy_cleanup (c); - } - fprintf (stderr, "\n"); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - -static int -testMultithreadedPut () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - unsigned int pos = 0; - int done_flag = 0; - CURLcode errornum; - - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, - 11081, - NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); - if (d == NULL) - return 16; - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); - curl_easy_setopt (c, CURLOPT_READDATA, &pos); - curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); - /* - // by not giving the file size, we force chunking! - curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); - */ - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - if (CURLE_OK != (errornum = curl_easy_perform (c))) - { - fprintf (stderr, - "curl_easy_perform failed: `%s'\n", - curl_easy_strerror (errornum)); - curl_easy_cleanup (c); - MHD_stop_daemon (d); - return 32; - } - curl_easy_cleanup (c); - MHD_stop_daemon (d); - if (cbc.pos != strlen ("/hello_world")) - return 64; - if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) - return 128; - - return 0; -} - - -static int -testExternalPut () -{ - struct MHD_Daemon *d; - CURL *c; - char buf[2048]; - struct CBC cbc; - CURLM *multi; - CURLMcode mret; - fd_set rs; - fd_set ws; - fd_set es; - int max; - int running; - time_t start; - struct timeval tv; - unsigned int pos = 0; - int done_flag = 0; - int i; - - multi = NULL; - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_DEBUG, - 11082, - NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); - if (d == NULL) - return 256; - - multi = curl_multi_init (); - if (multi == NULL) - { - MHD_stop_daemon (d); - return 512; - } - zzuf_socat_start (); - for (i = 0; i < LOOP_COUNT; i++) - { - fprintf (stderr, "."); - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11082/hello_world"); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); - curl_easy_setopt (c, CURLOPT_READDATA, &pos); - curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); - /* - // by not giving the file size, we force chunking! - curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); - */ - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); - curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); - // NOTE: use of CONNECTTIMEOUT without also - // setting NOSIGNAL results in really weird - // crashes on my system! - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); - - - mret = curl_multi_add_handle (multi, c); - if (mret != CURLM_OK) - { - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 1024; - } - start = time (NULL); - while ((time (NULL) - start < 5) && (c != NULL)) - { - max = 0; - FD_ZERO (&rs); - FD_ZERO (&ws); - FD_ZERO (&es); - curl_multi_perform (multi, &running); - mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); - if (mret != CURLM_OK) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 2048; - } - if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 4096; - } - tv.tv_sec = 0; - tv.tv_usec = 1000; - select (max + 1, &rs, &ws, &es, &tv); - curl_multi_perform (multi, &running); - if (running == 0) - { - curl_multi_info_read (multi, &running); - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - c = NULL; - } - MHD_run (d); - } - if (c != NULL) - { - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - } - } - fprintf (stderr, "\n"); - curl_multi_cleanup (multi); - zzuf_socat_stop (); - MHD_stop_daemon (d); - return 0; -} - - - -int -main (int argc, char *const *argv) -{ - unsigned int errorCount = 0; - - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return 2; - errorCount += testInternalPut (); - errorCount += testMultithreadedPut (); - errorCount += testExternalPut (); - if (errorCount != 0) - fprintf (stderr, "Error (code: %u)\n", errorCount); - curl_global_cleanup (); - return errorCount != 0; /* 0 == pass */ -} diff --git a/src/testzzuf/test_get.c b/src/testzzuf/test_get.c new file mode 100644 index 00000000..4aed7fb5 --- /dev/null +++ b/src/testzzuf/test_get.c @@ -0,0 +1,314 @@ +/* + This file is part of libmicrohttpd + (C) 2007, 2008 Christian Grothoff + + libmicrohttpd 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 + option) any later version. + + libmicrohttpd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file daemontest_get.c + * @brief Testcase for libmicrohttpd GET operations + * @author Christian Grothoff + */ + +#include "MHD_config.h" +#include "platform.h" +#include +#include +#include +#include +#include + +#ifndef WINDOWS +#include +#endif + +#include "socat.c" + +static int oneone; + +struct CBC +{ + char *buf; + size_t pos; + size_t size; +}; + +static size_t +copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) +{ + struct CBC *cbc = ctx; + + if (cbc->pos + size * nmemb > cbc->size) + return 0; /* overflow */ + memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); + cbc->pos += size * nmemb; + return size * nmemb; +} + +static int +ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, + void **unused) +{ + static int ptr; + const char *me = cls; + struct MHD_Response *response; + int ret; + + if (0 != strcmp (me, method)) + return MHD_NO; /* unexpected method */ + if (&ptr != *unused) + { + *unused = &ptr; + return MHD_YES; + } + *unused = NULL; + response = MHD_create_response_from_buffer (strlen (url), + (void *) url, + MHD_RESPMEM_MUST_COPY); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + if (ret == MHD_NO) + abort (); + return ret; +} + + +static int +testInternalGet () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , + 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); + if (d == NULL) + return 1; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + +static int +testMultithreadedGet () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , + 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); + if (d == NULL) + return 16; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + + +static int +testExternalGet () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + CURLM *multi; + CURLMcode mret; + fd_set rs; + fd_set ws; + fd_set es; + int max; + int running; + time_t start; + struct timeval tv; + int i; + + multi = NULL; + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , + 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); + if (d == NULL) + return 256; + multi = curl_multi_init (); + if (multi == NULL) + { + MHD_stop_daemon (d); + return 512; + } + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + mret = curl_multi_add_handle (multi, c); + if (mret != CURLM_OK) + { + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 1024; + } + start = time (NULL); + while ((time (NULL) - start < 5) && (c != NULL)) + { + max = 0; + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + curl_multi_perform (multi, &running); + mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); + if (mret != CURLM_OK) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 2048; + } + if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 4096; + } + tv.tv_sec = 0; + tv.tv_usec = 1000; + select (max + 1, &rs, &ws, &es, &tv); + curl_multi_perform (multi, &running); + if (running == 0) + { + curl_multi_info_read (multi, &running); + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + c = NULL; + } + MHD_run (d); + } + if (c != NULL) + { + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + } + } + fprintf (stderr, "\n"); + curl_multi_cleanup (multi); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + + + +int +main (int argc, char *const *argv) +{ + unsigned int errorCount = 0; + + oneone = NULL != strstr (argv[0], "11"); + if (0 != curl_global_init (CURL_GLOBAL_WIN32)) + return 2; + errorCount += testInternalGet (); + errorCount += testMultithreadedGet (); + errorCount += testExternalGet (); + if (errorCount != 0) + fprintf (stderr, "Error (code: %u)\n", errorCount); + curl_global_cleanup (); + return errorCount != 0; /* 0 == pass */ +} diff --git a/src/testzzuf/test_get_chunked.c b/src/testzzuf/test_get_chunked.c new file mode 100644 index 00000000..35eed49d --- /dev/null +++ b/src/testzzuf/test_get_chunked.c @@ -0,0 +1,330 @@ +/* + This file is part of libmicrohttpd + (C) 2007, 2008 Christian Grothoff + + libmicrohttpd 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 + option) any later version. + + libmicrohttpd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file daemontest_get_chunked.c + * @brief Testcase for libmicrohttpd GET operations with chunked content encoding + * @author Christian Grothoff + */ + +#include "MHD_config.h" +#include "platform.h" +#include +#include +#include +#include +#include + +#ifndef WINDOWS +#include +#endif + +#include "socat.c" + +struct CBC +{ + char *buf; + size_t pos; + size_t size; +}; + +static size_t +copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) +{ + struct CBC *cbc = ctx; + + if (cbc->pos + size * nmemb > cbc->size) + return 0; /* overflow */ + memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); + cbc->pos += size * nmemb; + return size * nmemb; +} + +/** + * MHD content reader callback that returns + * data in chunks. + */ +static ssize_t +crc (void *cls, uint64_t pos, char *buf, size_t max) +{ + struct MHD_Response **responseptr = cls; + + if (pos == 128 * 10) + { + MHD_add_response_header (*responseptr, "Footer", "working"); + return MHD_CONTENT_READER_END_OF_STREAM; + } + if (max < 128) + abort (); /* should not happen in this testcase... */ + memset (buf, 'A' + (pos / 128), 128); + return 128; +} + +/** + * Dummy function that does nothing. + */ +static void +crcf (void *ptr) +{ + free (ptr); +} + +static int +ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, void **ptr) +{ + static int aptr; + const char *me = cls; + struct MHD_Response *response; + struct MHD_Response **responseptr; + int ret; + + if (0 != strcmp (me, method)) + return MHD_NO; /* unexpected method */ + if (&aptr != *ptr) + { + /* do never respond on first call */ + *ptr = &aptr; + return MHD_YES; + } + responseptr = malloc (sizeof (struct MHD_Response *)); + response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, + 1024, + &crc, responseptr, &crcf); + *responseptr = response; + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + return ret; +} + +static int +testInternalGet () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , + 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); + if (d == NULL) + return 1; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + +static int +testMultithreadedGet () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , + 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); + if (d == NULL) + return 16; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + + +static int +testExternalGet () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + CURLM *multi; + CURLMcode mret; + fd_set rs; + fd_set ws; + fd_set es; + int max; + int running; + time_t start; + struct timeval tv; + int i; + + multi = NULL; + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , + 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); + if (d == NULL) + return 256; + multi = curl_multi_init (); + if (multi == NULL) + { + MHD_stop_daemon (d); + return 512; + } + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + mret = curl_multi_add_handle (multi, c); + if (mret != CURLM_OK) + { + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 1024; + } + start = time (NULL); + while ((time (NULL) - start < 5) && (c != NULL)) + { + max = 0; + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + curl_multi_perform (multi, &running); + mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); + if (mret != CURLM_OK) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 2048; + } + if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 4096; + } + tv.tv_sec = 0; + tv.tv_usec = 1000; + select (max + 1, &rs, &ws, &es, &tv); + curl_multi_perform (multi, &running); + if (running == 0) + { + curl_multi_info_read (multi, &running); + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + c = NULL; + } + MHD_run (d); + } + if (c != NULL) + { + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + } + } + fprintf (stderr, "\n"); + curl_multi_cleanup (multi); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + + + +int +main (int argc, char *const *argv) +{ + unsigned int errorCount = 0; + + if (0 != curl_global_init (CURL_GLOBAL_WIN32)) + return 2; + errorCount += testInternalGet (); + errorCount += testMultithreadedGet (); + errorCount += testExternalGet (); + if (errorCount != 0) + fprintf (stderr, "Error (code: %u)\n", errorCount); + curl_global_cleanup (); + return errorCount != 0; /* 0 == pass */ +} diff --git a/src/testzzuf/test_long_header.c b/src/testzzuf/test_long_header.c new file mode 100644 index 00000000..d285768f --- /dev/null +++ b/src/testzzuf/test_long_header.c @@ -0,0 +1,232 @@ +/* + This file is part of libmicrohttpd + (C) 2007, 2008 Christian Grothoff + + libmicrohttpd 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 + option) any later version. + + libmicrohttpd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file daemontest_long_header.c + * @brief Testcase for libmicrohttpd handling of very long headers + * @author Christian Grothoff + */ + +#include "MHD_config.h" +#include "platform.h" +#include +#include +#include +#include +#include + +#ifndef WINDOWS +#include +#endif + +#include "socat.c" + +/** + * We will set the memory available per connection to + * half of this value, so the actual value does not have + * to be big at all... + */ +#define VERY_LONG (1024*10) + +static int oneone; + +static int +apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen) +{ + return MHD_YES; +} + +struct CBC +{ + char *buf; + size_t pos; + size_t size; +}; + +static size_t +copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) +{ + return size * nmemb; +} + +static int +ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, + void **unused) +{ + const char *me = cls; + struct MHD_Response *response; + int ret; + + if (0 != strcmp (me, method)) + return MHD_NO; /* unexpected method */ + response = MHD_create_response_from_buffer (strlen (url), + (void *) url, + MHD_RESPMEM_MUST_COPY); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + return ret; +} + + +static int +testLongUrlGet () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + char *url; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , + 11080, + &apc_all, + NULL, + &ahc_echo, + "GET", + MHD_OPTION_CONNECTION_MEMORY_LIMIT, + (size_t) (VERY_LONG / 2), MHD_OPTION_END); + + if (d == NULL) + return 1; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + + c = curl_easy_init (); + url = malloc (VERY_LONG); + memset (url, 'a', VERY_LONG); + url[VERY_LONG - 1] = '\0'; + memcpy (url, "http://localhost:11081/", + strlen ("http://localhost:11081/")); + curl_easy_setopt (c, CURLOPT_URL, url); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + + MHD_stop_daemon (d); + free (url); + return 0; +} + + +static int +testLongHeaderGet () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + char *url; + struct curl_slist *header = NULL; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , + 11080, + &apc_all, + NULL, + &ahc_echo, + "GET", + MHD_OPTION_CONNECTION_MEMORY_LIMIT, + (size_t) (VERY_LONG / 2), MHD_OPTION_END); + if (d == NULL) + return 16; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + url = malloc (VERY_LONG); + memset (url, 'a', VERY_LONG); + url[VERY_LONG - 1] = '\0'; + url[VERY_LONG / 2] = ':'; + url[VERY_LONG / 2 + 1] = ' '; + header = curl_slist_append (header, url); + + curl_easy_setopt (c, CURLOPT_HTTPHEADER, header); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_slist_free_all (header); + header = NULL; + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + + MHD_stop_daemon (d); + free (url); + return 0; +} + +int +main (int argc, char *const *argv) +{ + unsigned int errorCount = 0; + + oneone = NULL != strstr (argv[0], "11"); + if (0 != curl_global_init (CURL_GLOBAL_WIN32)) + return 2; + errorCount += testLongUrlGet (); + errorCount += testLongHeaderGet (); + if (errorCount != 0) + fprintf (stderr, "Error (code: %u)\n", errorCount); + curl_global_cleanup (); + return errorCount != 0; /* 0 == pass */ +} diff --git a/src/testzzuf/test_post.c b/src/testzzuf/test_post.c new file mode 100644 index 00000000..66077b4f --- /dev/null +++ b/src/testzzuf/test_post.c @@ -0,0 +1,372 @@ +/* + This file is part of libmicrohttpd + (C) 2007, 2008 Christian Grothoff + + libmicrohttpd 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 + option) any later version. + + libmicrohttpd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file daemontest_post.c + * @brief Testcase for libmicrohttpd POST operations using URL-encoding + * @author Christian Grothoff + */ + +#include "MHD_config.h" +#include "platform.h" +#include +#include +#include +#include +#include + +#ifndef WINDOWS +#include +#endif + + +#include "socat.c" + +#define POST_DATA "name=daniel&project=curl" + +static int oneone; + +struct CBC +{ + char *buf; + size_t pos; + size_t size; +}; + +static size_t +copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) +{ + struct CBC *cbc = ctx; + + if (cbc->pos + size * nmemb > cbc->size) + return 0; /* overflow */ + memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); + cbc->pos += size * nmemb; + return size * nmemb; +} + +/** + * Note that this post_iterator is not perfect + * in that it fails to support incremental processing. + * (to be fixed in the future) + */ +static int +post_iterator (void *cls, + enum MHD_ValueKind kind, + const char *key, + const char *filename, + const char *content_type, + const char *transfer_encoding, + const char *value, uint64_t off, size_t size) +{ + int *eok = cls; + + if ((0 == strcmp (key, "name")) && + (size == strlen ("daniel")) && (0 == strncmp (value, "daniel", size))) + (*eok) |= 1; + if ((0 == strcmp (key, "project")) && + (size == strlen ("curl")) && (0 == strncmp (value, "curl", size))) + (*eok) |= 2; + return MHD_YES; +} + +static int +ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, + void **unused) +{ + static int eok; + struct MHD_Response *response; + struct MHD_PostProcessor *pp; + int ret; + + if (0 != strcmp ("POST", method)) + { + return MHD_NO; /* unexpected method */ + } + pp = *unused; + if (pp == NULL) + { + eok = 0; + pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok); + *unused = pp; + } + MHD_post_process (pp, upload_data, *upload_data_size); + if ((eok == 3) && (0 == *upload_data_size)) + { + response = MHD_create_response_from_buffer (strlen (url), + (void *) url, + MHD_RESPMEM_MUST_COPY); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + MHD_destroy_post_processor (pp); + *unused = NULL; + return ret; + } + *upload_data_size = 0; + return MHD_YES; +} + + +static int +testInternalPost () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , + 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); + if (d == NULL) + return 1; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); + curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); + curl_easy_setopt (c, CURLOPT_POST, 1L); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + + return 0; +} + +static int +testMultithreadedPost () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , + 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); + if (d == NULL) + return 16; + + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); + curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); + curl_easy_setopt (c, CURLOPT_POST, 1L); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + + MHD_stop_daemon (d); + return 0; +} + + +static int +testExternalPost () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + CURLM *multi; + CURLMcode mret; + fd_set rs; + fd_set ws; + fd_set es; + int max; + int running; + time_t start; + struct timeval tv; + int i; + + multi = NULL; + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , + 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); + if (d == NULL) + return 256; + multi = curl_multi_init (); + if (multi == NULL) + { + MHD_stop_daemon (d); + return 512; + } + + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + + + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); + curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); + curl_easy_setopt (c, CURLOPT_POST, 1L); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + + + mret = curl_multi_add_handle (multi, c); + if (mret != CURLM_OK) + { + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 1024; + } + start = time (NULL); + while ((time (NULL) - start < 5) && (c != NULL)) + { + max = 0; + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + curl_multi_perform (multi, &running); + mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); + if (mret != CURLM_OK) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 2048; + } + if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 4096; + } + tv.tv_sec = 0; + tv.tv_usec = 1000; + select (max + 1, &rs, &ws, &es, &tv); + curl_multi_perform (multi, &running); + if (running == 0) + { + curl_multi_info_read (multi, &running); + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + c = NULL; + } + MHD_run (d); + } + if (c != NULL) + { + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + } + + } + fprintf (stderr, "\n"); + curl_multi_cleanup (multi); + zzuf_socat_stop (); + + MHD_stop_daemon (d); + return 0; +} + + + +int +main (int argc, char *const *argv) +{ + unsigned int errorCount = 0; + + oneone = NULL != strstr (argv[0], "11"); + if (0 != curl_global_init (CURL_GLOBAL_WIN32)) + return 2; + errorCount += testInternalPost (); + errorCount += testMultithreadedPost (); + errorCount += testExternalPost (); + if (errorCount != 0) + fprintf (stderr, "Error (code: %u)\n", errorCount); + curl_global_cleanup (); + return errorCount != 0; /* 0 == pass */ +} diff --git a/src/testzzuf/test_post_form.c b/src/testzzuf/test_post_form.c new file mode 100644 index 00000000..873c7fef --- /dev/null +++ b/src/testzzuf/test_post_form.c @@ -0,0 +1,387 @@ +/* + This file is part of libmicrohttpd + (C) 2007, 2008 Christian Grothoff + + libmicrohttpd 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 + option) any later version. + + libmicrohttpd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file daemontest_post.c + * @brief Testcase for libmicrohttpd POST operations using multipart/postform data + * @author Christian Grothoff + */ + +#include "MHD_config.h" +#include "platform.h" +#include +#include +#include +#include +#include + +#ifndef WINDOWS +#include +#endif + + +#include "socat.c" + +static int oneone; + +struct CBC +{ + char *buf; + size_t pos; + size_t size; +}; + +static size_t +copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) +{ + struct CBC *cbc = ctx; + + if (cbc->pos + size * nmemb > cbc->size) + return 0; /* overflow */ + memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); + cbc->pos += size * nmemb; + return size * nmemb; +} + +/** + * Note that this post_iterator is not perfect + * in that it fails to support incremental processing. + * (to be fixed in the future) + */ +static int +post_iterator (void *cls, + enum MHD_ValueKind kind, + const char *key, + const char *filename, + const char *content_type, + const char *transfer_encoding, + const char *value, uint64_t off, size_t size) +{ + int *eok = cls; + + if (key == NULL) + return MHD_YES; +#if 0 + fprintf (stderr, "PI sees %s-%.*s\n", key, size, value); +#endif + if ((0 == strcmp (key, "name")) && + (size == strlen ("daniel")) && (0 == strncmp (value, "daniel", size))) + (*eok) |= 1; + if ((0 == strcmp (key, "project")) && + (size == strlen ("curl")) && (0 == strncmp (value, "curl", size))) + (*eok) |= 2; + return MHD_YES; +} + +static int +ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, + void **unused) +{ + static int eok; + struct MHD_Response *response; + struct MHD_PostProcessor *pp; + int ret; + + if (0 != strcmp ("POST", method)) + { + return MHD_NO; /* unexpected method */ + } + pp = *unused; + if (pp == NULL) + { + eok = 0; + pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok); + if (pp == NULL) + return MHD_NO; + *unused = pp; + } + MHD_post_process (pp, upload_data, *upload_data_size); + if ((eok == 3) && (0 == *upload_data_size)) + { + response = MHD_create_response_from_buffer (strlen (url), + (void *) url, + MHD_RESPMEM_MUST_COPY); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + MHD_destroy_post_processor (pp); + *unused = NULL; + return ret; + } + *upload_data_size = 0; + return MHD_YES; +} + +static struct curl_httppost * +make_form () +{ + struct curl_httppost *post = NULL; + struct curl_httppost *last = NULL; + + curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END); + curl_formadd (&post, &last, CURLFORM_COPYNAME, "project", + CURLFORM_COPYCONTENTS, "curl", CURLFORM_END); + return post; +} + + +static int +testInternalPost () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + int i; + struct curl_httppost *pd; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , + 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); + if (d == NULL) + return 1; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + pd = make_form (); + curl_easy_setopt (c, CURLOPT_HTTPPOST, pd); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + curl_formfree (pd); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + +static int +testMultithreadedPost () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + int i; + struct curl_httppost *pd; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , + 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); + if (d == NULL) + return 16; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + pd = make_form (); + curl_easy_setopt (c, CURLOPT_HTTPPOST, pd); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + curl_formfree (pd); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + + +static int +testExternalPost () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + CURLM *multi; + CURLMcode mret; + fd_set rs; + fd_set ws; + fd_set es; + int max; + int running; + time_t start; + struct timeval tv; + struct curl_httppost *pd; + int i; + + multi = NULL; + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , + 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); + if (d == NULL) + return 256; + multi = curl_multi_init (); + if (multi == NULL) + { + MHD_stop_daemon (d); + return 512; + } + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + pd = make_form (); + curl_easy_setopt (c, CURLOPT_HTTPPOST, pd); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + + + mret = curl_multi_add_handle (multi, c); + if (mret != CURLM_OK) + { + curl_multi_cleanup (multi); + curl_formfree (pd); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 1024; + } + start = time (NULL); + while ((time (NULL) - start < 5) && (c != NULL)) + { + max = 0; + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + curl_multi_perform (multi, &running); + mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); + if (mret != CURLM_OK) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + curl_formfree (pd); + return 2048; + } + if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + curl_formfree (pd); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 4096; + } + tv.tv_sec = 0; + tv.tv_usec = 1000; + select (max + 1, &rs, &ws, &es, &tv); + curl_multi_perform (multi, &running); + if (running == 0) + { + curl_multi_info_read (multi, &running); + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + c = NULL; + } + MHD_run (d); + } + if (c != NULL) + { + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + } + curl_formfree (pd); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + + MHD_stop_daemon (d); + return 0; +} + + + +int +main (int argc, char *const *argv) +{ + unsigned int errorCount = 0; + + oneone = NULL != strstr (argv[0], "11"); + if (0 != curl_global_init (CURL_GLOBAL_WIN32)) + return 2; + errorCount += testInternalPost (); + errorCount += testMultithreadedPost (); + errorCount += testExternalPost (); + if (errorCount != 0) + fprintf (stderr, "Error (code: %u)\n", errorCount); + curl_global_cleanup (); + return errorCount != 0; /* 0 == pass */ +} diff --git a/src/testzzuf/test_put.c b/src/testzzuf/test_put.c new file mode 100644 index 00000000..c658c39c --- /dev/null +++ b/src/testzzuf/test_put.c @@ -0,0 +1,361 @@ +/* + This file is part of libmicrohttpd + (C) 2007, 2008 Christian Grothoff + + libmicrohttpd 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 + option) any later version. + + libmicrohttpd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file daemontest_put.c + * @brief Testcase for libmicrohttpd PUT operations + * @author Christian Grothoff + */ + +#include "MHD_config.h" +#include "platform.h" +#include +#include +#include +#include +#include + +#ifndef WINDOWS +#include +#endif + + +#include "socat.c" + +static int oneone; + +struct CBC +{ + char *buf; + size_t pos; + size_t size; +}; + +static size_t +putBuffer (void *stream, size_t size, size_t nmemb, void *ptr) +{ + unsigned int *pos = ptr; + unsigned int wrt; + + wrt = size * nmemb; + if (wrt > 8 - (*pos)) + wrt = 8 - (*pos); + memcpy (stream, &("Hello123"[*pos]), wrt); + (*pos) += wrt; + return wrt; +} + +static size_t +copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) +{ + struct CBC *cbc = ctx; + + if (cbc->pos + size * nmemb > cbc->size) + return 0; /* overflow */ + memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); + cbc->pos += size * nmemb; + return size * nmemb; +} + +static int +ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, + void **unused) +{ + int *done = cls; + struct MHD_Response *response; + int ret; + + if (0 != strcmp ("PUT", method)) + return MHD_NO; /* unexpected method */ + if ((*done) == 0) + { + if (*upload_data_size != 8) + return MHD_YES; /* not yet ready */ + if (0 == memcmp (upload_data, "Hello123", 8)) + { + *upload_data_size = 0; + } + else + { + printf ("Invalid upload data `%8s'!\n", upload_data); + return MHD_NO; + } + *done = 1; + return MHD_YES; + } + response = MHD_create_response_from_buffer (strlen (url), + (void *) url, + MHD_RESPMEM_MUST_COPY); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + return ret; +} + + +static int +testInternalPut () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + unsigned int pos = 0; + int done_flag = 0; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , + 11080, + NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); + if (d == NULL) + return 1; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); + curl_easy_setopt (c, CURLOPT_READDATA, &pos); + curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); + curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + +static int +testMultithreadedPut () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + unsigned int pos = 0; + int done_flag = 0; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , + 11080, + NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); + if (d == NULL) + return 16; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); + curl_easy_setopt (c, CURLOPT_READDATA, &pos); + curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); + curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + + +static int +testExternalPut () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + CURLM *multi; + CURLMcode mret; + fd_set rs; + fd_set ws; + fd_set es; + int max; + int running; + time_t start; + struct timeval tv; + unsigned int pos = 0; + int done_flag = 0; + int i; + + multi = NULL; + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , + 11080, + NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); + if (d == NULL) + return 256; + multi = curl_multi_init (); + if (multi == NULL) + { + MHD_stop_daemon (d); + return 512; + } + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); + curl_easy_setopt (c, CURLOPT_READDATA, &pos); + curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); + curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + + + + mret = curl_multi_add_handle (multi, c); + if (mret != CURLM_OK) + { + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 1024; + } + start = time (NULL); + while ((time (NULL) - start < 5) && (c != NULL)) + { + max = 0; + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + curl_multi_perform (multi, &running); + mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); + if (mret != CURLM_OK) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 2048; + } + if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 4096; + } + tv.tv_sec = 0; + tv.tv_usec = 1000; + select (max + 1, &rs, &ws, &es, &tv); + curl_multi_perform (multi, &running); + if (running == 0) + { + curl_multi_info_read (multi, &running); + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + c = NULL; + } + MHD_run (d); + } + if (c != NULL) + { + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + } + } + fprintf (stderr, "\n"); + curl_multi_cleanup (multi); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + + + +int +main (int argc, char *const *argv) +{ + unsigned int errorCount = 0; + + oneone = NULL != strstr (argv[0], "11"); + if (0 != curl_global_init (CURL_GLOBAL_WIN32)) + return 2; + errorCount += testInternalPut (); + errorCount += testMultithreadedPut (); + errorCount += testExternalPut (); + if (errorCount != 0) + fprintf (stderr, "Error (code: %u)\n", errorCount); + curl_global_cleanup (); + return errorCount != 0; /* 0 == pass */ +} diff --git a/src/testzzuf/test_put_chunked.c b/src/testzzuf/test_put_chunked.c new file mode 100644 index 00000000..47d0f0ba --- /dev/null +++ b/src/testzzuf/test_put_chunked.c @@ -0,0 +1,371 @@ +/* + This file is part of libmicrohttpd + (C) 2007, 2008 Christian Grothoff + + libmicrohttpd 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 + option) any later version. + + libmicrohttpd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file daemontest_put_chunked.c + * @brief Testcase for libmicrohttpd PUT operations with chunked encoding + * for the upload data + * @author Christian Grothoff + */ + +#include "MHD_config.h" +#include "platform.h" +#include +#include +#include +#include +#include + +#ifndef WINDOWS +#include +#endif + +#include "socat.c" + +struct CBC +{ + char *buf; + size_t pos; + size_t size; +}; + +static size_t +putBuffer (void *stream, size_t size, size_t nmemb, void *ptr) +{ + unsigned int *pos = ptr; + unsigned int wrt; + + wrt = size * nmemb; + if (wrt > 8 - (*pos)) + wrt = 8 - (*pos); + if (wrt > 4) + wrt = 4; /* only send half at first => force multiple chunks! */ + memcpy (stream, &("Hello123"[*pos]), wrt); + (*pos) += wrt; + return wrt; +} + +static size_t +copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) +{ + struct CBC *cbc = ctx; + + if (cbc->pos + size * nmemb > cbc->size) + return 0; /* overflow */ + memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); + cbc->pos += size * nmemb; + return size * nmemb; +} + +static int +ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, + void **unused) +{ + int *done = cls; + struct MHD_Response *response; + int ret; + int have; + + if (0 != strcmp ("PUT", method)) + return MHD_NO; /* unexpected method */ + if ((*done) < 8) + { + have = *upload_data_size; + if (have + *done > 8) + { + return MHD_NO; + } + if (0 == memcmp (upload_data, &"Hello123"[*done], have)) + { + *done += have; + *upload_data_size = 0; + } + else + { + return MHD_NO; + } +#if 0 + fprintf (stderr, "Not ready for response: %u/%u\n", *done, 8); +#endif + return MHD_YES; + } + response = MHD_create_response_from_buffer (strlen (url), + (void *) url, + MHD_RESPMEM_MUST_COPY); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + return ret; +} + + +static int +testInternalPut () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + unsigned int pos = 0; + int done_flag = 0; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, + 11080, + NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); + if (d == NULL) + return 1; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); + curl_easy_setopt (c, CURLOPT_READDATA, &pos); + curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); + /* + // by not giving the file size, we force chunking! + curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); + */ + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + +static int +testMultithreadedPut () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + unsigned int pos = 0; + int done_flag = 0; + CURLcode errornum; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, + 11081, + NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); + if (d == NULL) + return 16; + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); + curl_easy_setopt (c, CURLOPT_READDATA, &pos); + curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); + /* + // by not giving the file size, we force chunking! + curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); + */ + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + if (CURLE_OK != (errornum = curl_easy_perform (c))) + { + fprintf (stderr, + "curl_easy_perform failed: `%s'\n", + curl_easy_strerror (errornum)); + curl_easy_cleanup (c); + MHD_stop_daemon (d); + return 32; + } + curl_easy_cleanup (c); + MHD_stop_daemon (d); + if (cbc.pos != strlen ("/hello_world")) + return 64; + if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) + return 128; + + return 0; +} + + +static int +testExternalPut () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + CURLM *multi; + CURLMcode mret; + fd_set rs; + fd_set ws; + fd_set es; + int max; + int running; + time_t start; + struct timeval tv; + unsigned int pos = 0; + int done_flag = 0; + int i; + + multi = NULL; + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_DEBUG, + 11082, + NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); + if (d == NULL) + return 256; + + multi = curl_multi_init (); + if (multi == NULL) + { + MHD_stop_daemon (d); + return 512; + } + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11082/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); + curl_easy_setopt (c, CURLOPT_READDATA, &pos); + curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); + /* + // by not giving the file size, we force chunking! + curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); + */ + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + + + mret = curl_multi_add_handle (multi, c); + if (mret != CURLM_OK) + { + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 1024; + } + start = time (NULL); + while ((time (NULL) - start < 5) && (c != NULL)) + { + max = 0; + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + curl_multi_perform (multi, &running); + mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); + if (mret != CURLM_OK) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 2048; + } + if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 4096; + } + tv.tv_sec = 0; + tv.tv_usec = 1000; + select (max + 1, &rs, &ws, &es, &tv); + curl_multi_perform (multi, &running); + if (running == 0) + { + curl_multi_info_read (multi, &running); + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + c = NULL; + } + MHD_run (d); + } + if (c != NULL) + { + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + } + } + fprintf (stderr, "\n"); + curl_multi_cleanup (multi); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + + + +int +main (int argc, char *const *argv) +{ + unsigned int errorCount = 0; + + if (0 != curl_global_init (CURL_GLOBAL_WIN32)) + return 2; + errorCount += testInternalPut (); + errorCount += testMultithreadedPut (); + errorCount += testExternalPut (); + if (errorCount != 0) + fprintf (stderr, "Error (code: %u)\n", errorCount); + curl_global_cleanup (); + return errorCount != 0; /* 0 == pass */ +} diff --git a/src/testzzuf/test_put_large.c b/src/testzzuf/test_put_large.c new file mode 100644 index 00000000..10fc8b06 --- /dev/null +++ b/src/testzzuf/test_put_large.c @@ -0,0 +1,382 @@ +/* + This file is part of libmicrohttpd + (C) 2007, 2008 Christian Grothoff + + libmicrohttpd 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 + option) any later version. + + libmicrohttpd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file daemontest_large_put.c + * @brief Testcase for libmicrohttpd PUT operations + * @author Christian Grothoff + */ + +#include "MHD_config.h" +#include "platform.h" +#include +#include +#include +#include +#include + +#ifndef WINDOWS +#include +#endif + +#include "socat.c" + +static int oneone; + +/** + * Do not make this much larger since we will hit the + * MHD default buffer limit and the test code is not + * written for incremental upload processing... + */ +#define PUT_SIZE (256 * 1024) + +static char *put_buffer; + +struct CBC +{ + char *buf; + size_t pos; + size_t size; +}; + +static size_t +putBuffer (void *stream, size_t size, size_t nmemb, void *ptr) +{ + unsigned int *pos = ptr; + unsigned int wrt; + + wrt = size * nmemb; + if (wrt > PUT_SIZE - (*pos)) + wrt = PUT_SIZE - (*pos); + memcpy (stream, &put_buffer[*pos], wrt); + (*pos) += wrt; + return wrt; +} + +static size_t +copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) +{ + struct CBC *cbc = ctx; + + if (cbc->pos + size * nmemb > cbc->size) + return 0; /* overflow */ + memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); + cbc->pos += size * nmemb; + return size * nmemb; +} + +static int +ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, + void **unused) +{ + int *done = cls; + struct MHD_Response *response; + int ret; + + if (0 != strcmp ("PUT", method)) + return MHD_NO; /* unexpected method */ + if ((*done) == 0) + { + if (*upload_data_size != PUT_SIZE) + { +#if 0 + fprintf (stderr, + "Waiting for more data (%u/%u)...\n", + *upload_data_size, PUT_SIZE); +#endif + return MHD_YES; /* not yet ready */ + } + if (0 == memcmp (upload_data, put_buffer, PUT_SIZE)) + { + *upload_data_size = 0; + } + else + { + return MHD_NO; + } + *done = 1; + return MHD_YES; + } + response = MHD_create_response_from_buffer (strlen (url), + (void *) url, + MHD_RESPMEM_MUST_COPY); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + return ret; +} + + +static int +testInternalPut () +{ + struct MHD_Daemon *d; + CURL *c; + struct CBC cbc; + unsigned int pos = 0; + int done_flag = 0; + char buf[2048]; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , + 11080, + NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); + if (d == NULL) + return 1; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); + curl_easy_setopt (c, CURLOPT_READDATA, &pos); + curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); + curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + +static int +testMultithreadedPut () +{ + struct MHD_Daemon *d; + CURL *c; + struct CBC cbc; + unsigned int pos = 0; + int done_flag = 0; + char buf[2048]; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ , + 11080, + NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); + if (d == NULL) + return 16; + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); + curl_easy_setopt (c, CURLOPT_READDATA, &pos); + curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); + curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + curl_easy_perform (c); + curl_easy_cleanup (c); + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 0; +} + + +static int +testExternalPut () +{ + struct MHD_Daemon *d; + CURL *c; + struct CBC cbc; + CURLM *multi; + CURLMcode mret; + fd_set rs; + fd_set ws; + fd_set es; + int max; + int running; + time_t start; + struct timeval tv; + unsigned int pos = 0; + int done_flag = 0; + char buf[2048]; + int i; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + multi = NULL; + d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */, + 11080, + NULL, NULL, &ahc_echo, &done_flag, + MHD_OPTION_CONNECTION_MEMORY_LIMIT, + (size_t) (PUT_SIZE * 4), MHD_OPTION_END); + if (d == NULL) + return 256; + multi = curl_multi_init (); + if (multi == NULL) + { + MHD_stop_daemon (d); + return 512; + } + zzuf_socat_start (); + for (i = 0; i < LOOP_COUNT; i++) + { + fprintf (stderr, "."); + + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); + curl_easy_setopt (c, CURLOPT_READDATA, &pos); + curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); + curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); + // NOTE: use of CONNECTTIMEOUT without also + // setting NOSIGNAL results in really weird + // crashes on my system! + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + + + + mret = curl_multi_add_handle (multi, c); + if (mret != CURLM_OK) + { + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 1024; + } + start = time (NULL); + while ((time (NULL) - start < 5) && (c != NULL)) + { + max = 0; + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + curl_multi_perform (multi, &running); + mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); + if (mret != CURLM_OK) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 2048; + } + if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + zzuf_socat_stop (); + MHD_stop_daemon (d); + return 4096; + } + tv.tv_sec = 0; + tv.tv_usec = 1000; + select (max + 1, &rs, &ws, &es, &tv); + curl_multi_perform (multi, &running); + if (running == 0) + { + curl_multi_info_read (multi, &running); + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + c = NULL; + } + MHD_run (d); + } + if (c != NULL) + { + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + } + } + fprintf (stderr, "\n"); + zzuf_socat_stop (); + curl_multi_cleanup (multi); + MHD_stop_daemon (d); + return 0; +} + + + +int +main (int argc, char *const *argv) +{ + unsigned int errorCount = 0; + + oneone = NULL != strstr (argv[0], "11"); + if (0 != curl_global_init (CURL_GLOBAL_WIN32)) + return 2; + put_buffer = malloc (PUT_SIZE); + memset (put_buffer, 1, PUT_SIZE); + errorCount += testInternalPut (); + errorCount += testMultithreadedPut (); + errorCount += testExternalPut (); + free (put_buffer); + if (errorCount != 0) + fprintf (stderr, "Error (code: %u)\n", errorCount); + curl_global_cleanup (); + return errorCount != 0; /* 0 == pass */ +} -- cgit v1.2.3