[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 11/29: testzzuf: re-worked zzuf testing
From: |
gnunet |
Subject: |
[libmicrohttpd] 11/29: testzzuf: re-worked zzuf testing |
Date: |
Tue, 20 Jun 2023 22:24:24 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit 40b675518b14fef4d327323f63c9c70f1b2bc44e
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Fri Oct 28 11:59:21 2022 +0300
testzzuf: re-worked zzuf testing
* merged test_get, test_get_chunked, test_put
* fixed use of header instead of footer in chunked data callback
* added checks for results of all used MHD functions
* added reading of all data in the input buffer provided by MHD for
callback
* re-used libcurl handles to re-use connections in all modes
* added testing of 'poll' and 'epoll' for all tests
* removed the need for socat
* removed forking with potential forked process zombies
* fixed processing only of the first request (as soon as socat
connection become broken, all following requests went to nowhere)
* implemented correct response for unsupported methods
* used proper timeout for 'external select()' (taken into account
libcurl timeout too)
* added check for extra reply data
* added debug print of libcurl sent and received data
* merged all tests into single source file
* fixed a lot of compiler warnings
* added check for incorrect replies produced by MHD
---
configure.ac | 86 +-
src/testzzuf/Makefile.am | 121 ++-
src/testzzuf/mhd_debug_funcs.c | 45 +
src/testzzuf/mhd_debug_funcs.h | 10 +
src/testzzuf/socat.c | 117 ---
src/testzzuf/test_get.c | 1726 +++++++++++++++++++++++++++++++++-----
src/testzzuf/test_get_chunked.c | 364 --------
src/testzzuf/test_long_header.c | 265 ------
src/testzzuf/test_post.c | 416 ---------
src/testzzuf/test_post_form.c | 432 ----------
src/testzzuf/test_put.c | 380 ---------
src/testzzuf/test_put_chunked.c | 395 ---------
src/testzzuf/test_put_large.c | 403 ---------
src/testzzuf/zzuf_test_runner.sh | 55 ++
14 files changed, 1746 insertions(+), 3069 deletions(-)
diff --git a/configure.ac b/configure.ac
index c329812c..5b3c578c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3052,47 +3052,6 @@ AS_IF([[test "x$enable_postprocessor" != "xno"]],
AM_CONDITIONAL([HAVE_POSTPROCESSOR], [test "x$enable_postprocessor" != "xno"])
AC_MSG_RESULT([[$enable_postprocessor]])
-
-# optional: have zzuf, socat?
-run_zzuf_tests="no"
-AS_VAR_IF([use_heavy_tests],["yes"],
- [
- AS_VAR_IF([enable_curl],["yes"],
- [
- AC_CHECK_PROG([have_zzuf],[zzuf],[yes],[no])
- AS_VAR_IF([have_zzuf],["yes"],
- [
- AC_CHECK_PROG([have_socat],[socat],[yes],[no])
- AS_VAR_IF([have_socat],["yes"],
- [
- run_zzuf_tests="yes"
- run_zzuf_tests_MSG="yes"
- ],
- [
- run_zzuf_tests="no"
- run_zzuf_tests_MSG="no, socat tool not found"
- ]
- )
- ],
- [
- run_zzuf_tests="no"
- run_zzuf_tests_MSG="no, zzuf tool not found"
- ]
- )
- ],
- [
- run_zzuf_tests="no"
- run_zzuf_tests_MSG="no, tests with libcurl are not enabled"
- ]
- )
- ],
- [
- run_zzuf_tests="no"
- run_zzuf_tests_MSG="no, heavy tests are not enabled"
- ]
-)
-AM_CONDITIONAL([RUN_ZZUF_TESTS],[test "x$run_zzuf_tests" = "xyes"])
-
have_gnutls=no
have_gnutls_sni=no
have_gcrypt=no
@@ -4883,6 +4842,50 @@ int main(void)
]
)
+# fuzzing tests
+run_zzuf_tests="no"
+AS_VAR_IF([use_heavy_tests],["yes"],
+ [
+ AS_VAR_IF([enable_curl],["yes"],
+ [
+ AC_PATH_PROG([ZZUF],[zzuf],[no])
+ AS_VAR_IF([ZZUF],["no"],
+ [
+ run_zzuf_tests="no"
+ run_zzuf_tests_MSG="no, zzuf tool not found"
+ ],
+ [
+ AS_IF([test "x${ac_cv_func_accept4}" = "xyes" && test
"x${enable_asserts}" = "xno"],
+ [
+ run_zzuf_tests="no"
+ run_zzuf_tests_MSG="no, fuzzing tests require asserts enabled
on this platform"
+ ],
+ [test -n "${enabled_sanitizers}"],
+ [
+ run_zzuf_tests="no"
+ run_zzuf_tests_MSG="no, fuzzing tests cannot be used with
sanitizers"
+ ],
+ [
+ run_zzuf_tests="yes"
+ run_zzuf_tests_MSG="yes"
+ ]
+ )
+ ]
+ )
+ ],
+ [
+ run_zzuf_tests="no"
+ run_zzuf_tests_MSG="no, tests with libcurl are not enabled"
+ ]
+ )
+ ],
+ [
+ run_zzuf_tests="no"
+ run_zzuf_tests_MSG="no, heavy tests are not enabled"
+ ]
+)
+AM_CONDITIONAL([RUN_ZZUF_TESTS],[test "x$run_zzuf_tests" = "xyes"])
+
# Final flags that may interfere with autoconf detections
AS_CASE([${enable_build_type}],[debug|debugger],
[ # Debug build or build for walking with debugger
@@ -4955,6 +4958,7 @@ AC_CONFIG_COMMANDS([po-directories],
# not contain the actual installation.
AC_DEFINE_DIR([MHD_PLUGIN_INSTALL_PREFIX], [libdir/libmicrohttpd], [tls
plugins])
+AC_SUBST([ZZUF])
# should experimental code be compiled (code that may not yet compile)?
AC_MSG_CHECKING(whether to compile experimental code)
diff --git a/src/testzzuf/Makefile.am b/src/testzzuf/Makefile.am
index 5c5c00ea..23b96d66 100644
--- a/src/testzzuf/Makefile.am
+++ b/src/testzzuf/Makefile.am
@@ -1,17 +1,29 @@
# This Makefile.am is in the public domain
+
SUBDIRS = .
+# ZZUF_SEED can be redefined to use other initial seeds
+# for extended testing. E.g.,
+# make ZZUF_SEED=1234 check
+ZZUF_SEED = 0
+
+# Additional flags for zzuf
+ZZUF_FLAGS =
+
AM_CPPFLAGS = \
-I$(top_srcdir)/src/include \
-I$(top_srcdir)/src/microhttpd \
-DMHD_CPU_COUNT=$(CPU_COUNT) \
$(CPPFLAGS_ac) $(LIBCURL_CPPFLAGS)
-AM_CFLAGS = $(CFLAGS_ac) @LIBGCRYPT_CFLAGS@
+AM_CFLAGS = $(CFLAGS_ac)
AM_LDFLAGS = $(LDFLAGS_ac)
-AM_TESTS_ENVIRONMENT = $(TESTS_ENVIRONMENT_ac)
+AM_TESTS_ENVIRONMENT = $(TESTS_ENVIRONMENT_ac) \
+ ZZUF="$(ZZUF)" ; export ZZUF ; \
+ ZZUF_SEED="$(ZZUF_SEED)" ; export ZZUF_SEED ; \
+ ZZUF_FLAGS="$(ZZUF_FLAGS)" ; export ZZUF_FLAGS ;
if USE_COVERAGE
AM_CFLAGS += -fprofile-arcs -ftest-coverage
@@ -25,11 +37,6 @@ $(top_builddir)/src/microhttpd/libmicrohttpd.la:
$(top_builddir)/src/microhttpd/
@echo ' cd $(top_builddir)/src/microhttpd && $(MAKE) $(AM_MAKEFLAGS)
libmicrohttpd.la'; \
$(am__cd) $(top_builddir)/src/microhttpd && $(MAKE) $(AM_MAKEFLAGS)
libmicrohttpd.la
-EXTRA_DIST = README socat.c
-
-THREAD_ONLY_TESTS = \
- test_long_header
-
check_PROGRAMS = \
test_get \
test_get_chunked \
@@ -38,64 +45,86 @@ check_PROGRAMS = \
test_put \
test_put_chunked \
test_put_large \
- test_get11 \
- test_post11 \
- test_post_form11 \
- test_put11 \
- test_put_large11
+ test_get_long_uri \
+ test_get_long_header \
+ test_get_close \
+ test_get_chunked_close \
+ test_post_close \
+ test_post_form_close \
+ test_put_close \
+ test_put_chunked_close \
+ test_put_large_close \
+ test_get_long_uri_close \
+ test_get_long_header_close \
+ test_get10 \
+ test_get_chunked10 \
+ test_post10 \
+ test_post_form10 \
+ test_put10 \
+ test_put_large10 \
+ test_get_long_uri10 \
+ test_get_long_header10
.NOTPARALLEL:
-if USE_POSIX_THREADS
-check_PROGRAMS += \
- $(THREAD_ONLY_TESTS)
-endif
-if USE_W32_THREADS
-check_PROGRAMS += \
- $(THREAD_ONLY_TESTS)
-endif
+TESTS = $(check_PROGRAMS)
+dist_check_SCRIPTS = zzuf_test_runner.sh
-TESTS = $(check_PROGRAMS)
+LOG_COMPILER = @SHELL@ $(srcdir)/zzuf_test_runner.sh
+
+tests_common_sources = mhd_debug_funcs.h mhd_debug_funcs.c
test_get_SOURCES = \
- test_get.c
+ test_get.c $(tests_common_sources)
+
+test_get_chunked_SOURCES = $(test_get_SOURCES)
+
+test_post_SOURCES = $(test_get_SOURCES)
+
+test_post_form_SOURCES = $(test_get_SOURCES)
+
+test_put_SOURCES = $(test_get_SOURCES)
+
+test_put_chunked_SOURCES = $(test_get_SOURCES)
+
+test_put_large_SOURCES = $(test_get_SOURCES)
+
+test_get_long_uri_SOURCES = $(test_get_SOURCES)
+
+test_get_long_header_SOURCES = $(test_get_SOURCES)
+
+test_get_close_SOURCES = $(test_get_SOURCES)
+
+test_get_chunked_close_SOURCES = $(test_get_chunked_SOURCES)
+
+test_post_close_SOURCES = $(test_post_SOURCES)
-test_get_chunked_SOURCES = \
- test_get_chunked.c
+test_post_form_close_SOURCES = $(test_post_form_SOURCES)
-test_post_SOURCES = \
- test_post.c
+test_put_close_SOURCES = $(test_put_SOURCES)
-test_post_form_SOURCES = \
- test_post_form.c
+test_put_chunked_close_SOURCES = $(test_put_chunked_SOURCES)
-test_put_SOURCES = \
- test_put.c
+test_put_large_close_SOURCES = $(test_put_large_SOURCES)
-test_put_chunked_SOURCES = \
- test_put_chunked.c
+test_get_long_uri_close_SOURCES = $(test_get_long_uri_SOURCES)
-test_put_large_SOURCES = \
- test_put_large.c
+test_get_long_header_close_SOURCES = $(test_get_long_header_SOURCES)
+test_get10_SOURCES = $(test_get_SOURCES)
+test_get_chunked10_SOURCES = $(test_get_chunked_SOURCES)
-test_get11_SOURCES = \
- test_get.c
+test_post10_SOURCES = $(test_post_SOURCES)
-test_post11_SOURCES = \
- test_post.c
+test_post_form10_SOURCES = $(test_post_form_SOURCES)
-test_post_form11_SOURCES = \
- test_post_form.c
+test_put10_SOURCES = $(test_put_SOURCES)
-test_put11_SOURCES = \
- test_put.c
+test_put_large10_SOURCES = $(test_put_large_SOURCES)
-test_put_large11_SOURCES = \
- test_put_large.c
+test_get_long_uri10_SOURCES = $(test_get_long_uri_SOURCES)
-test_long_header_SOURCES = \
- test_long_header.c
+test_get_long_header10_SOURCES = $(test_get_long_header_SOURCES)
diff --git a/src/testzzuf/mhd_debug_funcs.c b/src/testzzuf/mhd_debug_funcs.c
index 9bfd3001..5db50b41 100644
--- a/src/testzzuf/mhd_debug_funcs.c
+++ b/src/testzzuf/mhd_debug_funcs.c
@@ -61,3 +61,48 @@ MHD_avoid_accept4_ (struct MHD_Daemon *daemon)
#endif /* ! _DEBUG */
#endif /* USE_ACCEPT4 */
}
+
+#ifdef MHD_ASAN_ACTIVE
+#define MHD_ASAN_ENABLED_ 1
+#else /* ! MHD_ASAN_ACTIVE */
+#ifdef __SANITIZE_ADDRESS__
+#define MHD_ASAN_ENABLED_ 1
+#else /* ! __SANITIZE_ADDRESS__ */
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+#define MHD_ASAN_ENABLED_ 1
+#endif /* __has_feature(address_sanitizer) */
+#endif /* __has_feature */
+#endif /* ! __SANITIZE_ADDRESS__ */
+#endif /* ! MHD_ASAN_ACTIVE */
+/**
+ * Checks whether any know sanitizer is enabled for this build.
+ * zzuf does not work together with sanitizers as both are intercepting
+ * standard library calls.
+ * @return non-zero if any sanitizer is enabled,
+ * zero otherwise
+ */
+int
+MHD_are_sanitizers_enabled_ (void)
+{
+ int ret = 0;
+#ifdef MHD_ASAN_ENABLED_
+ ++ret;
+#endif /* ! MHD_ASAN_ENABLED_ */
+#if defined(__has_feature)
+#if __has_feature(thread_sanitizer)
+ ++ret;
+#endif
+#if __has_feature(memory_sanitizer)
+ ++ret;
+#endif
+#if __has_feature(dataflow_sanitizer)
+ ++ret;
+#endif
+#else /* ! defined(__has_feature) */
+#ifdef __SANITIZE_THREAD__
+ ++ret;
+#endif
+#endif /* ! defined(__has_feature) */
+ return ret;
+}
diff --git a/src/testzzuf/mhd_debug_funcs.h b/src/testzzuf/mhd_debug_funcs.h
index 02423edb..04de0970 100644
--- a/src/testzzuf/mhd_debug_funcs.h
+++ b/src/testzzuf/mhd_debug_funcs.h
@@ -44,4 +44,14 @@ MHD_is_avoid_accept4_possible_ (void);
void
MHD_avoid_accept4_ (struct MHD_Daemon *daemon);
+/**
+ * Checks whether any know sanitizer is enabled for this build.
+ * zzuf does not work together with sanitizers as both are intercepting
+ * standard library calls.
+ * @return non-zero if any sanitizer is enabled,
+ * zero otherwise
+ */
+int
+MHD_are_sanitizers_enabled_ (void);
+
#endif /* MHD_DEBUG_FUNCS_H */
diff --git a/src/testzzuf/socat.c b/src/testzzuf/socat.c
deleted file mode 100644
index 0ee14749..00000000
--- a/src/testzzuf/socat.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- This file is part of libmicrohttpd
- Copyright (C) 2008,2016 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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file socat.c
- * @brief Code to fork-exec zzuf and start the socat process
- * @author Christian Grothoff
- */
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#ifdef _WIN32
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN 1
-#endif /* !WIN32_LEAN_AND_MEAN */
-#include <windows.h>
-#endif
-
-
-/**
- * A larger loop count will run more random tests --
- * which would be good, except that it may take too
- * long for most user's patience. So this small
- * value is the default.
- */
-#ifndef _MHD_VHEAVY_TESTS
-#define LOOP_COUNT 10
-#else /* ! _MHD_VHEAVY_TESTS */
-#define LOOP_COUNT 200
-#endif /* ! _MHD_VHEAVY_TESTS */
-
-#define CURL_TIMEOUT 50L
-
-static pid_t zzuf_pid;
-
-static void
-zzuf_socat_start ()
-{
- int status;
- char *const args[] = {
- "zzuf",
- "--ratio=0.0:0.75",
- "-n",
- "-A",
- "socat",
- "-lf",
- "/dev/null",
- "TCP4-LISTEN:11081,reuseaddr,fork",
- "TCP4:127.0.0.1:11080",
- NULL,
- };
- zzuf_pid = fork ();
- if (zzuf_pid == -1)
- {
- fprintf (stderr, "fork failed: %s\n", strerror (errno));
- exit (1);
- }
- if (zzuf_pid != 0)
- {
- (void) sleep (1); /* allow zzuf and socat to start */
- status = 0;
- if (0 < waitpid (zzuf_pid, &status, WNOHANG))
- {
- if (WIFEXITED (status))
- fprintf (stderr,
- "zzuf died with status code %d!\n",
- WEXITSTATUS (status));
- if (WIFSIGNALED (status))
- fprintf (stderr,
- "zzuf died from signal %d!\n", WTERMSIG (status));
- exit (1);
- }
- return;
- }
- setpgid (0, 0);
- execvp ("zzuf", args);
- fprintf (stderr, "execution of `zzuf' failed: %s\n", strerror (errno));
- exit (1);
-}
-
-
-static void
-zzuf_socat_stop ()
-{
- int status;
- if (zzuf_pid != 0)
- {
- if (0 != killpg (zzuf_pid, SIGINT))
- fprintf (stderr, "Failed to killpg: %s\n", strerror (errno));
- kill (zzuf_pid, SIGINT);
- waitpid (zzuf_pid, &status, 0);
- (void) sleep (1); /* allow socat to also die in peace */
- }
-}
-
-
-/* end of socat.c */
diff --git a/src/testzzuf/test_get.c b/src/testzzuf/test_get.c
index e2b86ffe..904808bc 100644
--- a/src/testzzuf/test_get.c
+++ b/src/testzzuf/test_get.c
@@ -1,6 +1,7 @@
/*
This file is part of libmicrohttpd
Copyright (C) 2007, 2008 Christian Grothoff
+ Copyright (C) 2016-2022 Evgeny Grin (Karlson2k)
libmicrohttpd is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -19,12 +20,12 @@
*/
/**
- * @file test_get.c
- * @brief Testcase for libmicrohttpd GET operations
+ * @file testzzuf/test_get.c
+ * @brief Several testcases for libmicrohttpd with input fuzzing
* @author Christian Grothoff
+ * @author Karlson2k (Evgeny Grin)
*/
-#include "MHD_config.h"
#include "platform.h"
#include <curl/curl.h>
#include <microhttpd.h>
@@ -36,298 +37,1603 @@
#include <unistd.h>
#endif
-#include "socat.c"
+#include "mhd_debug_funcs.h"
+#include "test_helpers.h"
+#ifndef MHD_STATICSTR_LEN_
+/**
+ * Determine length of static string / macro strings at compile time.
+ */
+#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1)
+#endif /* ! MHD_STATICSTR_LEN_ */
+
+#ifndef CURL_VERSION_BITS
+#define CURL_VERSION_BITS(x,y,z) ((x) << 16 | (y) << 8 | (z))
+#endif /* ! CURL_VERSION_BITS */
+#ifndef CURL_AT_LEAST_VERSION
+#define CURL_AT_LEAST_VERSION(x,y,z) \
+ (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS (x, y, z))
+#endif /* ! CURL_AT_LEAST_VERSION */
+
+/**
+ * A larger loop count will run more random tests --
+ * which would be good, except that it may take too
+ * long for most user's patience. So this small
+ * value is the default.
+ * Can be redefined by CPPFLAGS=-DLOOP_COUNT=123
+ */
+#ifndef LOOP_COUNT
+#ifndef _MHD_VHEAVY_TESTS
+#define LOOP_COUNT 10
+#else /* ! _MHD_HEAVY_TESTS */
+#define LOOP_COUNT 200
+#endif /* ! _MHD_HEAVY_TESTS */
+#endif /* LOOP_COUNT */
+
+#ifdef _DEBUG
+/* Uncomment the next line (or use CPPFLAGS) to see all request and response
bodies in log */
+/* #define TEST_PRINT_BODY */
+/* Uncomment the next line (or use CPPFLAGS) to see all request bodies as they
are sent by libcurl */
+/* #define TEST_PRINT_BODY_RQ 1 */
+/* Uncomment the next line (or use CPPFLAGS) to see all request bodies as they
are received by libcurl */
+/* #define TEST_PRINT_BODY_RP 1 */
+#endif /* _DEBUG */
+
+#define MHD_TIMEOUT 2
+
+#define CURL_TIMEOUT 5
+
+/* Global test parameters */
static int oneone;
+static int dry_run;
+static int use_get;
+static int use_get_chunked;
+static int use_put;
+static int use_put_large;
+static int use_put_chunked;
+static int use_post;
+static int use_post_form;
+static int use_long_header;
+static int use_long_uri;
+static int use_close;
-struct CBC
+#define TEST_BASE_URI "http:/" "/127.0.0.1/test_uri"
+
+#define EMPTY_PAGE "Empty page."
+#define EMPTY_PAGE_ALT "Alternative empty page."
+#define METHOD_NOT_SUPPORTED "HTTP method is not supported."
+#define POST_DATA_BROKEN "The POST request is ill-formed."
+
+#define POST_KEY1 "test"
+#define POST_VALUE1 "test_post"
+#define POST_KEY2 "library"
+#define POST_VALUE2 "GNU libmicrohttpd"
+#define POST_URLENC_DATA \
+ POST_KEY1 "=" POST_VALUE1 "&" POST_KEY2 "=" "GNU%20libmicrohttpd"
+
+#define PUT_NORMAL_SIZE 11
+/* Does not need to be very large as MHD buffer will be made smaller anyway */
+#define PUT_LARGE_SIZE (4 * 1024)
+/* The length of "very long" URI and header strings. MHD uses smaller buffer.
*/
+#define TEST_STRING_VLONG_LEN 8 * 1024
+
+
+#if ! CURL_AT_LEAST_VERSION (7,56,0)
+#define TEST_USE_STATIC_POST_DATA 1
+static struct curl_httppost *post_first;
+static struct curl_httppost *post_last;
+#endif /* ! CURL_AT_LEAST_VERSION(7,56,0) */
+
+static struct curl_slist *libcurl_long_header;
+
+/**
+ * Initialise long header for libcurl
+ *
+ * @return non-zero if succeed,
+ * zero if failed
+ */
+static int
+long_header_init (void)
{
char *buf;
- size_t pos;
- size_t size;
+
+ buf = malloc (TEST_STRING_VLONG_LEN + 1);
+ if (NULL == buf)
+ {
+ fprintf (stderr, "malloc() failed "
+ "at line %d.\n", (int) __LINE__);
+ return 0;
+ }
+ buf[TEST_STRING_VLONG_LEN] = 0;
+ buf[0] = 'A';
+ memset (buf + 1, 'a', TEST_STRING_VLONG_LEN / 2 - 2);
+ buf[TEST_STRING_VLONG_LEN / 2 - 1] = ':';
+ buf[TEST_STRING_VLONG_LEN / 2] = ' ';
+ memset (buf + TEST_STRING_VLONG_LEN / 2 + 1, 'c',
+ TEST_STRING_VLONG_LEN / 2 - 1);
+ libcurl_long_header = curl_slist_append (NULL, buf);
+ free (buf);
+ if (NULL != libcurl_long_header)
+ return ! 0; /* Success exit point */
+
+ fprintf (stderr, "curl_slist_append() failed "
+ "at line %d.\n", (int) __LINE__);
+ return 0; /* Failure exit point */
+}
+
+
+/**
+ * Globally initialise test environment
+ * @return non-zero if succeed,
+ * zero if failed
+ */
+static int
+test_global_init (void)
+{
+ libcurl_long_header = NULL;
+ if (CURLE_OK != curl_global_init (CURL_GLOBAL_WIN32))
+ {
+ fprintf (stderr, "curl_global_init() failed "
+ "at line %d.\n", (int) __LINE__);
+ return 0;
+ }
+
+ if (long_header_init ())
+ {
+#ifndef TEST_USE_STATIC_POST_DATA
+ return 1; /* Success exit point */
+#else /* ! TEST_USE_STATIC_POST_DATA */
+ post_first = NULL;
+ post_last = NULL;
+ if ((CURL_FORMADD_OK !=
+ curl_formadd (&post_first, &post_last,
+ CURLFORM_PTRNAME, POST_KEY1,
+ CURLFORM_NAMELENGTH,
+ (long) MHD_STATICSTR_LEN_ (POST_KEY1),
+ CURLFORM_PTRCONTENTS, POST_VALUE1,
+#if CURL_AT_LEAST_VERSION (7,46,0)
+ CURLFORM_CONTENTLEN,
+ (curl_off_t) MHD_STATICSTR_LEN_ (POST_VALUE1),
+#else /* ! CURL_AT_LEAST_VERSION(7,46,0) */
+ CURLFORM_CONTENTSLENGTH,
+ (long) MHD_STATICSTR_LEN_ (POST_VALUE1),
+#endif /* ! CURL_AT_LEAST_VERSION(7,46,0) */
+ CURLFORM_END)) ||
+ (CURL_FORMADD_OK !=
+ curl_formadd (&post_first, &post_last,
+ CURLFORM_PTRNAME, POST_KEY2,
+ CURLFORM_NAMELENGTH,
+ (long) MHD_STATICSTR_LEN_ (POST_KEY2),
+ CURLFORM_PTRCONTENTS, POST_VALUE2,
+#if CURL_AT_LEAST_VERSION (7,46,0)
+ CURLFORM_CONTENTLEN,
+ (curl_off_t) MHD_STATICSTR_LEN_ (POST_VALUE2),
+#else /* ! CURL_AT_LEAST_VERSION(7,46,0) */
+ CURLFORM_CONTENTSLENGTH,
+ (long) MHD_STATICSTR_LEN_ (POST_VALUE2),
+#endif /* ! CURL_AT_LEAST_VERSION(7,46,0) */
+ CURLFORM_END)))
+ fprintf (stderr, "curl_formadd() failed "
+ "at line %d.\n", (int) __LINE__);
+ else
+ return 1; /* Success exit point */
+
+ if (NULL != post_first)
+ curl_formfree (post_first);
+ curl_slist_free_all (libcurl_long_header);
+#endif /* ! CURL_AT_LEAST_VERSION(7,56,0) */
+ }
+ curl_global_cleanup ();
+ return 0; /* Failure exit point */
+}
+
+
+/**
+ * Globally de-initialise test environment
+ */
+static void
+test_global_deinit (void)
+{
+#ifdef TEST_USE_STATIC_POST_DATA
+ curl_formfree (post_first);
+#endif /* TEST_USE_STATIC_POST_DATA */
+ curl_global_cleanup ();
+ if (NULL != libcurl_long_header)
+ curl_slist_free_all (libcurl_long_header);
+}
+
+
+/**
+ * libcurl callback parameters for uploads, downloads and debug callbacks
+ */
+struct CBC
+{
+ /* Upload members */
+ size_t up_pos;
+ size_t up_size;
+ /* Download members */
+ char *dn_buf;
+ size_t dn_pos;
+ size_t dn_buf_size;
+ /* Debug callback members */
+ unsigned int excess_found;
};
+static void
+initCBC (struct CBC *libcurlcbc, char *dn_buf, size_t dn_buf_size)
+{
+ libcurlcbc->up_pos = 0;
+ if (use_put_large)
+ libcurlcbc->up_size = PUT_LARGE_SIZE;
+ else if (use_put)
+ libcurlcbc->up_size = PUT_NORMAL_SIZE;
+ else
+ libcurlcbc->up_size = 0;
+ libcurlcbc->dn_buf = dn_buf;
+ libcurlcbc->dn_pos = 0;
+ libcurlcbc->dn_buf_size = dn_buf_size;
+ libcurlcbc->excess_found = 0;
+}
+
+
+static void
+resetCBC (struct CBC *libcurlcbc)
+{
+ libcurlcbc->up_pos = 0;
+ libcurlcbc->dn_pos = 0;
+}
+
+
+static size_t
+putBuffer (void *stream, size_t item_size, size_t nitems, void *ctx)
+{
+ size_t to_fill;
+ size_t i;
+ struct CBC *cbc = ctx;
+
+ to_fill = cbc->up_size - cbc->up_pos;
+ /* Skip overflow check as the return value is valid anyway */
+ if (use_put_chunked)
+ {
+ /* Send data as several chunks */
+ if (to_fill > cbc->up_size / 3)
+ to_fill = cbc->up_size / 3;
+ }
+ if (to_fill > item_size * nitems)
+ to_fill = item_size * nitems;
+
+ /* Avoid libcurl magic numbers */
+#ifdef CURL_READFUNC_PAUSE
+ if (CURL_READFUNC_ABORT == to_fill)
+ to_fill -= 2;
+#endif /* CURL_READFUNC_PAUSE */
+#ifdef CURL_READFUNC_ABORT
+ if (CURL_READFUNC_ABORT == to_fill)
+ --to_fill;
+#endif /* CURL_READFUNC_ABORT */
+ for (i = 0; i < to_fill; ++i)
+ ((char *) stream)[i] = 'a' + (char) ((cbc->up_pos + i)
+ % (unsigned char) ('z' - 'a' + 1));
+
+ cbc->up_pos += to_fill;
+ return to_fill;
+}
+
+
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)
+ if (cbc->dn_pos + size * nmemb > cbc->dn_buf_size)
return 0; /* overflow */
- memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
- cbc->pos += size * nmemb;
+ memcpy (&cbc->dn_buf[cbc->dn_pos], ptr, size * nmemb);
+ cbc->dn_pos += size * nmemb;
return size * nmemb;
}
+#define TEST_MAGIC_MARKER0 0xFEE1C0DE
+#define TEST_MAGIC_MARKER1 (TEST_MAGIC_MARKER0 + 1)
+#define TEST_MAGIC_MARKER2 (TEST_MAGIC_MARKER0 + 2)
+
+struct content_cb_param_strct
+{
+ unsigned int magic0; /**< Must have TEST_MAGIC_MARKER0 value */
+ struct MHD_Response *response; /**< The pointer to the response structure */
+};
+
+/**
+ * MHD content reader callback that returns
+ * data in chunks.
+ */
+static ssize_t
+content_cb (void *cls, uint64_t pos, char *buf, size_t max)
+{
+ struct content_cb_param_strct *param = (struct content_cb_param_strct *) cls;
+ size_t fill_size;
+
+ if ((unsigned int) TEST_MAGIC_MARKER0 != param->magic0)
+ {
+ fprintf (stderr, "Wrong cls pointer "
+ "at line %d.\n", (int) __LINE__);
+ fflush (stderr);
+ abort ();
+ }
+
+ if (pos >= 128 * 10)
+ {
+ if (MHD_YES !=
+ MHD_add_response_footer (param->response, "Footer", "working"))
+ {
+ fprintf (stderr, "MHD_add_response_footer() failed "
+ "at line %d.\n", (int) __LINE__);
+ fflush (stderr);
+ abort ();
+ }
+ return MHD_CONTENT_READER_END_OF_STREAM;
+ }
+
+ if (128 > max)
+ fill_size = 128;
+ else
+ fill_size = max;
+ memset (buf, 'A' + (char) (unsigned int) (pos / 128), fill_size);
+
+ return (ssize_t) fill_size;
+}
+
+
+/**
+ * Deallocate memory for callback cls.
+ */
+static void
+crcf (void *ptr)
+{
+ free (ptr);
+}
+
+
+struct req_process_strct
+{
+ unsigned int magic2; /**< Must have TEST_MAGIC_MARKER2 value */
+ int is_static; /**< Non-zero if statically allocated, zero if
malloc()'ed */
+ struct MHD_PostProcessor *postprocsr;
+ unsigned int post_data_sum;
+};
+
static enum MHD_Result
-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 **req_cls)
+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)
+{
+ struct req_process_strct *param = (struct req_process_strct *) cls;
+ size_t i;
+
+ (void) filename; (void) content_type; (void) transfer_encoding;
+ (void) off; /* Unused. Mute compiler warnings. */
+
+ if (TEST_MAGIC_MARKER2 != param->magic2)
+ {
+ fprintf (stderr, "The 'param->magic2' has wrong value "
+ "at line %d.\n", (int) __LINE__);
+ abort ();
+ }
+
+ if (MHD_POSTDATA_KIND != kind)
+ {
+ fprintf (stderr, "The 'kind' parameter has wrong value "
+ "at line %d.\n", (int) __LINE__);
+ abort ();
+ }
+
+ if (NULL != key)
+ param->post_data_sum += (unsigned int) strlen (key);
+
+ for (i = 0; size > i; ++i)
+ param->post_data_sum += (unsigned int) (unsigned char) value[i];
+
+ return MHD_YES;
+}
+
+
+static void
+free_req_pr_data (struct req_process_strct *pr_data)
+{
+ if (NULL == pr_data)
+ return;
+ if (TEST_MAGIC_MARKER2 != pr_data->magic2)
+ {
+ fprintf (stderr, "The 'pr_data->magic2' has wrong value "
+ "at line %d.\n", (int) __LINE__);
+ abort ();
+ }
+ if (pr_data->is_static)
+ {
+ if (NULL != pr_data->postprocsr)
+ {
+ fprintf (stderr, "The 'pr_data->postprocsr' has wrong value "
+ "at line %d.\n", (int) __LINE__);
+ abort ();
+ }
+ return;
+ }
+ if (NULL != pr_data->postprocsr)
+ MHD_destroy_post_processor (pr_data->postprocsr);
+ pr_data->postprocsr = NULL;
+ free (pr_data);
+}
+
+
+struct ahc_param_strct
+{
+ unsigned int magic1; /**< Must have TEST_MAGIC_MARKER1 value */
+ unsigned int err_flag; /**< Non-zero if any error is encountered */
+ unsigned int num_replies; /**< The number of replies sent for the current
request */
+};
+
+static enum MHD_Result
+send_error_response (struct MHD_Connection *connection,
+ struct ahc_param_strct *param,
+ unsigned int status_code,
+ const char *static_text,
+ const size_t static_text_len)
{
- static int ptr;
- const char *me = cls;
+ struct MHD_Response *response;
+ response =
+ MHD_create_response_from_buffer_static (static_text_len,
+ static_text);
+ if (NULL != response)
+ {
+ if (MHD_YES == MHD_add_response_header (response,
+ MHD_HTTP_HEADER_CONNECTION,
+ "close"))
+ {
+ if (MHD_YES == MHD_queue_response (connection, status_code, response))
+ {
+ MHD_destroy_response (response);
+ return MHD_YES; /* Success exit point */
+ }
+ else
+ fprintf (stderr, "MHD_queue_response() failed "
+ "at line %d.\n", (int) __LINE__);
+ }
+ else
+ fprintf (stderr, "MHD_add_response_header() failed "
+ "at line %d.\n", (int) __LINE__);
+ MHD_destroy_response (response);
+ }
+ else
+ fprintf (stderr, "MHD_create_response_from_callback() failed "
+ "at line %d.\n", (int) __LINE__);
+
+ param->err_flag = 1;
+ return MHD_NO; /* Failure exit point */
+}
+
+
+static enum MHD_Result
+ahc_check (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 **req_cls)
+{
+ static struct req_process_strct static_req_pr_data = {
+ TEST_MAGIC_MARKER2, ! 0, NULL, 0
+ };
+ struct req_process_strct *req_pr_data;
+ struct ahc_param_strct *param = (struct ahc_param_strct *) cls;
struct MHD_Response *response;
enum MHD_Result ret;
- (void) version; (void) upload_data; (void) upload_data_size; /*
Unused. Silent compiler warning. */
+ unsigned char data_sum;
+ int is_post_req;
+ if (NULL == cls)
+ {
+ fprintf (stderr, "The 'cls' parameter is NULL "
+ "at line %d.\n", (int) __LINE__);
+ fflush (stderr);
+ abort ();
+ }
+ if ((unsigned int) TEST_MAGIC_MARKER1 != param->magic1)
+ {
+ fprintf (stderr, "The 'param->magic1' has wrong value "
+ "at line %d.\n", (int) __LINE__);
+ fflush (stderr);
+ abort ();
+ }
+ if (NULL == connection)
+ {
+ fprintf (stderr, "The 'connection' parameter is NULL "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ return MHD_NO; /* Should not reply */
+ }
+ if (1)
+ { /* Simple check for 'connection' parameter validity */
+ const union MHD_ConnectionInfo *conn_info;
+ conn_info =
+ MHD_get_connection_info (connection,
+ MHD_CONNECTION_INFO_CONNECTION_TIMEOUT);
+ if (NULL == conn_info)
+ {
+ fprintf (stderr, "The 'MHD_get_connection_info' has returned NULL "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ }
+ else if (MHD_TIMEOUT != conn_info->connection_timeout)
+ {
+ fprintf (stderr, "The 'MHD_get_connection_info' has returned "
+ "unexpected timeout value "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ }
+ }
if (NULL == url)
- fprintf (stderr, "The \"url\" parameter is NULL.\n");
+ {
+ fprintf (stderr, "The 'url' parameter is NULL "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ }
if (NULL == method)
- fprintf (stderr, "The \"method\" parameter is NULL.\n");
+ {
+ fprintf (stderr, "The 'method' parameter is NULL "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ return MHD_NO; /* Should not reply */
+ }
if (NULL == version)
- fprintf (stderr, "The \"version\" parameter is NULL.\n");
+ {
+ fprintf (stderr, "The 'version' parameter is NULL "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ return MHD_NO; /* Should not reply */
+ }
if (NULL == upload_data_size)
- fprintf (stderr, "The \"upload_data_size\" parameter is NULL.\n");
+ {
+ fprintf (stderr, "The 'upload_data_size' parameter is NULL "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ return MHD_NO; /* Should not reply */
+ }
if ((0 != *upload_data_size) && (NULL == upload_data))
- fprintf (stderr, "Upload data is NULL with non-zero size.\n");
- if (0 != strcmp (me, method))
- return MHD_NO; /* unexpected method */
- if (&ptr != *req_cls)
{
- *req_cls = &ptr;
+ fprintf (stderr, "The 'upload_data' parameter is NULL "
+ "while '*upload_data_size' is not zero "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ return MHD_NO; /* Should not reply */
+ }
+ if ((NULL != upload_data) && (0 == *upload_data_size))
+ {
+ fprintf (stderr, "The 'upload_data' parameter is NOT NULL "
+ "while '*upload_data_size' is zero "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ return MHD_NO; /* Should not reply */
+ }
+
+ if (0 != param->num_replies)
+ {
+ /* Phantom "second" request due to the fuzzing of the input. Refuse. */
+ return MHD_NO;
+ }
+
+ is_post_req = (0 == strcmp (method, MHD_HTTP_METHOD_POST));
+ if ((0 != strcmp (method, MHD_HTTP_METHOD_GET))
+ && (0 != strcmp (method, MHD_HTTP_METHOD_HEAD))
+ && (0 != strcmp (method, MHD_HTTP_METHOD_PUT))
+ && (! is_post_req))
+ {
+ /* Unsupported method for this callback */
+ return send_error_response (connection, param, MHD_HTTP_NOT_IMPLEMENTED,
+ METHOD_NOT_SUPPORTED,
+ MHD_STATICSTR_LEN_ (METHOD_NOT_SUPPORTED));
+ }
+
+ if (NULL == *req_cls)
+ {
+ if (! is_post_req)
+ { /* Use static memory */
+ *req_cls = &static_req_pr_data;
+ }
+ else
+ { /* POST request, use PostProcessor */
+ req_pr_data =
+ (struct req_process_strct *) malloc (sizeof (struct
req_process_strct));
+ if (NULL == req_pr_data)
+ {
+ fprintf (stderr, "malloc() failed "
+ "at line %d.\n", (int) __LINE__);
+ return MHD_NO;
+ }
+ req_pr_data->magic2 = TEST_MAGIC_MARKER2;
+ req_pr_data->is_static = 0;
+ req_pr_data->post_data_sum = 0;
+ req_pr_data->postprocsr = MHD_create_post_processor (connection, 1024,
+ &post_iterator,
+ req_pr_data);
+ if (NULL == req_pr_data->postprocsr)
+ {
+ free (req_pr_data);
+ if (NULL == upload_data)
+ return send_error_response (connection, param, MHD_HTTP_BAD_REQUEST,
+ POST_DATA_BROKEN,
+ MHD_STATICSTR_LEN_ (POST_DATA_BROKEN));
+ else
+ return MHD_NO; /* Cannot handle request, broken POST */
+ }
+ *req_cls = req_pr_data;
+ }
+ if (NULL == upload_data)
+ return MHD_YES;
+ }
+ req_pr_data = (struct req_process_strct *) *req_cls;
+
+ data_sum = 0;
+ if (NULL != upload_data)
+ {
+ if (is_post_req)
+ {
+ if (MHD_YES != MHD_post_process (req_pr_data->postprocsr,
+ upload_data, *upload_data_size))
+ {
+ free_req_pr_data (req_pr_data);
+ *req_cls = NULL;
+ /* Processing upload body (context), error reply cannot be queued here
*/
+ return MHD_NO;
+ }
+ *upload_data_size = 0; /* All data have been processed */
+ }
+ else
+ {
+ /* Check that all 'upload_data' is addressable */
+ size_t pos;
+ for (pos = 0; pos < *upload_data_size; ++pos)
+ data_sum += (unsigned char) upload_data[pos];
+ if (0 != *upload_data_size)
+ {
+ if (3 >= *upload_data_size)
+ *upload_data_size = 0; /* Consume all
incoming data */
+ else
+ *upload_data_size = data_sum % *upload_data_size; /* Pseudo-random
*/
+ }
+ }
return MHD_YES;
}
+ if (is_post_req)
+ {
+ if (MHD_YES != MHD_destroy_post_processor (req_pr_data->postprocsr))
+ {
+ free (req_pr_data);
+ *req_cls = NULL;
+ return send_error_response (connection, param, MHD_HTTP_BAD_REQUEST,
+ POST_DATA_BROKEN,
+ MHD_STATICSTR_LEN_ (POST_DATA_BROKEN));
+ }
+ req_pr_data->postprocsr = NULL;
+ }
+ data_sum += (unsigned char) req_pr_data->post_data_sum;
+ free_req_pr_data (req_pr_data);
*req_cls = 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)
+
+ ret = MHD_YES;
+ if (use_get_chunked)
+ {
+ struct content_cb_param_strct *cnt_cb_param;
+ cnt_cb_param = malloc (sizeof (struct content_cb_param_strct));
+ if (NULL == cnt_cb_param)
+ {
+ fprintf (stderr, "malloc() failed "
+ "at line %d.\n", (int) __LINE__);
+ /* External error, do not rise the error flag */
+ return MHD_NO;
+ }
+ cnt_cb_param->magic0 = (unsigned int) TEST_MAGIC_MARKER0;
+ response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
+ 1024,
+ &content_cb, cnt_cb_param,
+ &crcf);
+ if (NULL == response)
+ {
+ fprintf (stderr, "MHD_create_response_from_callback() failed "
+ "at line %d.\n", (int) __LINE__);
+ free (cnt_cb_param);
+ param->err_flag = 1;
+ ret = MHD_NO;
+ }
+ else
+ cnt_cb_param->response = response;
+ }
+ else if (use_get || use_put || use_post)
+ {
+ /* Randomly choose the response page for the POST requests */
+ if (0 == data_sum % 2)
+ response =
+ MHD_create_response_from_buffer_static (MHD_STATICSTR_LEN_
(EMPTY_PAGE),
+ EMPTY_PAGE);
+ else
+ response =
+ MHD_create_response_from_buffer_static (MHD_STATICSTR_LEN_ ( \
+ EMPTY_PAGE_ALT),
+ EMPTY_PAGE_ALT);
+
+ if (NULL == response)
+ {
+ fprintf (stderr, "MHD_create_response_from_buffer_static() failed "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ ret = MHD_NO;
+ }
+ }
+ else
+ {
+ fprintf (stderr, "Response is not implemented for this test. "
+ "Internal logic is broken. "
+ "At line %d.\n", (int) __LINE__);
abort ();
+ }
+
+ if (NULL != response)
+ {
+ if ((MHD_YES == ret) &&
+ (use_close || (! oneone && (0 != strcmp (version,
+ MHD_HTTP_VERSION_1_0)))))
+ {
+ ret = MHD_add_response_header (response,
+ MHD_HTTP_HEADER_CONNECTION,
+ "close");
+ if (MHD_YES != ret)
+ {
+ fprintf (stderr, "MHD_add_response_header() failed "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ }
+ }
+ if (MHD_YES == ret)
+ {
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ if (MHD_YES != ret)
+ {
+ fprintf (stderr, "MHD_queue_response() failed "
+ "at line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ }
+ }
+ else
+ param->num_replies++;
+
+ MHD_destroy_response (response);
+ }
+ else
+ {
+ fprintf (stderr, "MHD_create_response_from_buffer_static() failed "
+ "at line %d.\n", (int) __LINE__);
+ ret = MHD_NO;
+ }
return ret;
}
-static unsigned int
-testInternalGet ()
+static void
+req_completed_cleanup (void *cls,
+ struct MHD_Connection *connection,
+ void **req_cls,
+ enum MHD_RequestTerminationCode toe)
+{
+ struct ahc_param_strct *param = (struct ahc_param_strct *) cls;
+ struct req_process_strct *req_pr_data = (struct req_process_strct *)
*req_cls;
+ (void) connection; /* Unused. Mute compiler warning. */
+
+ if (NULL == param)
+ {
+ fprintf (stderr, "The 'cls' parameter is NULL at line %d.\n",
+ (int) __LINE__);
+ fflush (stderr);
+ abort ();
+ }
+ if ((unsigned int) TEST_MAGIC_MARKER1 != param->magic1)
+ {
+ fprintf (stderr, "The 'param->magic1' has wrong value at line %d.\n",
+ (int) __LINE__);
+ fflush (stderr);
+ abort ();
+ }
+ if (NULL == req_pr_data)
+ return; /* The data have been freed */
+ if ((unsigned int) TEST_MAGIC_MARKER2 != req_pr_data->magic2)
+ {
+ fprintf (stderr, "The 'req_pr_data->magic2' has wrong value at line %d.\n",
+ (int) __LINE__);
+ fflush (stderr);
+ abort ();
+ }
+ if (MHD_REQUEST_TERMINATED_COMPLETED_OK == toe)
+ {
+ fprintf (stderr, "The request completed successful, but request cls has"
+ "not been cleared. "
+ "At line %d.\n", (int) __LINE__);
+ param->err_flag = 1;
+ }
+ if (req_pr_data->is_static)
+ return;
+ if (NULL != req_pr_data->postprocsr)
+ MHD_destroy_post_processor (req_pr_data->postprocsr);
+ req_pr_data->postprocsr = NULL;
+ free (req_pr_data);
+ *req_cls = NULL;
+}
+
+
+/* Un-comment the next line (or use CPPFLAGS) to avoid
+ logging of the traffic with debug builds */
+/* #define TEST_NO_PRINT_TRAFFIC 1 */
+
+#ifdef _DEBUG
+#ifdef TEST_PRINT_BODY
+#ifndef TEST_PRINT_BODY_RQ
+#define TEST_PRINT_BODY_RQ 1
+#endif /* TEST_PRINT_BODY_RQ */
+#ifndef TEST_PRINT_BODY_RP
+#define TEST_PRINT_BODY_RP 1
+#endif /* TEST_PRINT_BODY_RP */
+#endif /* TEST_PRINT_BODY */
+#endif /* _DEBUG */
+
+static int
+libcurl_debug_cb (CURL *handle,
+ curl_infotype type,
+ char *data,
+ size_t size,
+ void *ctx)
+{
+ static const char excess_mark[] = "Excess found";
+ static const size_t excess_mark_len = MHD_STATICSTR_LEN_ (excess_mark);
+ struct CBC *cbc = ctx;
+ (void) handle;
+
+#if defined(_DEBUG) && ! defined(TEST_NO_PRINT_TRAFFIC)
+ switch (type)
+ {
+ case CURLINFO_TEXT:
+ fprintf (stderr, "* %.*s", (int) size, data);
+ break;
+ case CURLINFO_HEADER_IN:
+ fprintf (stderr, "< %.*s", (int) size, data);
+ break;
+ case CURLINFO_HEADER_OUT:
+ fprintf (stderr, "> %.*s", (int) size, data);
+ break;
+ case CURLINFO_DATA_IN:
+#ifdef TEST_PRINT_BODY_RP
+ fprintf (stderr, "<| %.*s\n", (int) size, data);
+#endif /* TEST_PRINT_BODY_RP */
+ break;
+ case CURLINFO_DATA_OUT:
+#ifdef TEST_PRINT_BODY_RQ
+ fprintf (stderr, ">| %.*s\n", (int) size, data);
+#endif /* TEST_PRINT_BODY_RQ */
+ break;
+ case CURLINFO_SSL_DATA_IN:
+ case CURLINFO_SSL_DATA_OUT:
+ case CURLINFO_END:
+ default:
+ break;
+ }
+#endif /* _DEBUG && ! TEST_NO_PRINT_TRAFFIC */
+ if (use_close || ! oneone)
+ {
+ /* Check for extra data only if every connection is terminated by MHD
+ after one request, otherwise MHD may react on garbage after request
+ data. */
+ if (CURLINFO_TEXT == type)
+ {
+ if ((size >= excess_mark_len) &&
+ (0 == memcmp (data, excess_mark, excess_mark_len)))
+ {
+ fprintf (stderr, "Extra data has been detected in MHD reply "
+ "at line %d.\n", (int) __LINE__);
+ cbc->excess_found++;
+ }
+ }
+ }
+ return 0;
+}
+
+
+static CURL *
+setupCURL (struct CBC *cbc, uint16_t port
+#ifndef TEST_USE_STATIC_POST_DATA
+ , curl_mime **mime
+#endif /* ! TEST_USE_STATIC_POST_DATA */
+ )
{
- 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_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG
*/,
- 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://127.0.0.1:11081/hello_world");
- curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
- curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
- curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
- 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);
+ CURLcode e;
+ char *buf;
+ const char *uri_to_use;
+
+#ifndef TEST_USE_STATIC_POST_DATA
+ *mime = NULL;
+#endif /* ! TEST_USE_STATIC_POST_DATA */
+
+ if (! use_long_uri)
+ {
+ uri_to_use = TEST_BASE_URI;
+ buf = NULL;
+ }
+ else
+ {
+ size_t pos;
+ buf = malloc (TEST_STRING_VLONG_LEN + 1);
+ if (NULL == buf)
+ {
+ fprintf (stderr, "malloc() failed "
+ "at line %d.\n", (int) __LINE__);
+ return NULL;
+ }
+ memcpy (buf, TEST_BASE_URI, MHD_STATICSTR_LEN_ (TEST_BASE_URI));
+ for (pos = MHD_STATICSTR_LEN_ (TEST_BASE_URI);
+ pos < TEST_STRING_VLONG_LEN;
+ ++pos)
+ {
+ if (0 == pos % 9)
+ buf[pos] = '/';
+ else
+ buf[pos] = 'a' + (char) (unsigned char) (pos % ((unsigned char)
+ ('z' - 'a' + 1)));
+ }
+ buf[TEST_STRING_VLONG_LEN] = 0;
+ uri_to_use = buf;
+ }
+
+ c = curl_easy_init ();
+ if (NULL == c)
+ {
+ fprintf (stderr, "curl_easy_init() failed "
+ "at line %d.\n", (int) __LINE__);
+ return NULL;
+ }
+
+ if ((CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_URL,
+ uri_to_use))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_WRITEFUNCTION,
+ ©Buffer))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_WRITEDATA, cbc))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT,
+ ((long) CURL_TIMEOUT)))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_HTTP_VERSION,
+ oneone ?
+ CURL_HTTP_VERSION_1_1 :
+ CURL_HTTP_VERSION_1_0))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_TIMEOUT,
+ ((long) CURL_TIMEOUT)))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_FAILONERROR, 0L))) &&
+#ifdef _DEBUG
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_VERBOSE, 1L))) &&
+#endif /* _DEBUG */
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_DEBUGFUNCTION,
+ &libcurl_debug_cb))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_DEBUGDATA,
+ cbc))) &&
+#if CURL_AT_LEAST_VERSION (7, 19, 4)
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_PROTOCOLS,
+ CURLPROTO_HTTP))) &&
+#endif /* CURL_AT_LEAST_VERSION (7, 19, 4) */
+#if CURL_AT_LEAST_VERSION (7, 45, 0)
+ (CURLE_OK == (e = curl_easy_setopt (c,
+ CURLOPT_DEFAULT_PROTOCOL, "http")))
&&
+#endif /* CURL_AT_LEAST_VERSION (7, 45, 0) */
+#if CURL_AT_LEAST_VERSION (7, 24, 0)
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_INTERFACE,
+ "host!127.0.0.101"))) &&
+#else /* ! CURL_AT_LEAST_VERSION (7, 24, 0) */
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_INTERFACE,
+ "127.0.0.101"))) &&
+#endif /* ! CURL_AT_LEAST_VERSION (7, 24, 0) */
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_PORT, ((long) port)))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_HTTPHEADER,
+ use_long_header ?
+ libcurl_long_header : NULL)))
+ )
+ {
+ if (NULL != buf)
+ {
+ free (buf);
+ buf = NULL;
+ }
+ if (use_put)
+ {
+ if ((CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_READFUNCTION,
+ &putBuffer))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_READDATA, cbc))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_UPLOAD, (long) 1))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE,
+ use_put_chunked ?
+ ((curl_off_t) -1) :
+ ((curl_off_t) cbc->up_size)))))
+ {
+ return c; /* Success exit point for 'use_put' */
+ }
+ else
+ fprintf (stderr, "PUT-related curl_easy_setopt() failed at line %d, "
+ "error: %s\n", (int) __LINE__,
+ curl_easy_strerror (e));
+ }
+ else if (use_post)
+ {
+ if (! use_post_form)
+ {
+ if ((CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_POST, (long) 1))) &&
+ (CURLE_OK == (e = curl_easy_setopt (c, CURLOPT_POSTFIELDS,
+ POST_URLENC_DATA))) &&
+ (CURLE_OK ==
+ (e = curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE,
+ MHD_STATICSTR_LEN_ (POST_URLENC_DATA)))))
+ {
+ return c; /* Success exit point for 'use_post' */
+ }
+ else
+ fprintf (stderr,
+ "POST-related curl_easy_setopt() failed at line %d, "
+ "error: %s\n", (int) __LINE__,
+ curl_easy_strerror (e));
+ }
+ else
+ {
+#ifndef TEST_USE_STATIC_POST_DATA
+ *mime = curl_mime_init (c);
+ if (NULL != *mime)
+ {
+ curl_mimepart *part;
+ if ((NULL != (part = curl_mime_addpart (*mime))) &&
+ (CURLE_OK == curl_mime_name (part, POST_KEY1)) &&
+ (CURLE_OK == curl_mime_data (part, POST_VALUE1,
+ MHD_STATICSTR_LEN_ (POST_VALUE1)))
&&
+ (NULL != (part = curl_mime_addpart (*mime))) &&
+ (CURLE_OK == curl_mime_name (part, POST_KEY2)) &&
+ (CURLE_OK == curl_mime_data (part, POST_VALUE2,
+ MHD_STATICSTR_LEN_ (POST_VALUE2))))
+ {
+ if (CURLE_OK ==
+ (e = curl_easy_setopt (c, CURLOPT_MIMEPOST, *mime)))
+ return c; /* Success exit point for 'use_post' */
+ else
+ fprintf (stderr, "curl_easy_setopt(c, CURLOPT_MIMEPOST, mime) "
+ "failed at line %d, error: %s\n",
+ (int) __LINE__, curl_easy_strerror (e));
+ }
+ else
+ fprintf (stderr, "curl_mime_addpart(), curl_mime_name() or "
+ "curl_mime_data() failed.\n");
+ }
+ else
+ fprintf (stderr, "curl_mime_init() failed.\n");
+
+#else /* TEST_USE_STATIC_POST_DATA */
+ if (CURLE_OK == (e = curl_easy_setopt (c,
+ CURLOPT_HTTPPOST, post_first)))
+ {
+ return c; /* Success exit point for 'use_post' */
+ }
+ else
+ fprintf (stderr, "POST form-related curl_easy_setopt() failed, "
+ "error: %s\n", curl_easy_strerror (e));
+#endif /* TEST_USE_STATIC_POST_DATA */
+ }
+ }
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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
+ return c; /* Success exit point */
}
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
- return 0;
+ else
+ fprintf (stderr, "curl_easy_setopt() failed at line %d, "
+ "error: %s\n", (int) __LINE__,
+ curl_easy_strerror (e));
+
+ curl_easy_cleanup (c);
+#ifndef TEST_USE_STATIC_POST_DATA
+ if (NULL != *mime)
+ curl_mime_free (*mime);
+#endif /* ! TEST_USE_STATIC_POST_DATA */
+
+ if (NULL != buf)
+ free (buf);
+
+ return NULL; /* Failure exit point */
+}
+
+
+static struct MHD_Daemon *
+start_daemon_for_test (unsigned int daemon_flags, uint16_t *pport,
+ struct ahc_param_strct *callback_param)
+{
+ struct MHD_Daemon *d;
+ struct MHD_OptionItem ops[] = {
+ { MHD_OPTION_END, 0, NULL },
+ { MHD_OPTION_END, 0, NULL }
+ };
+ callback_param->magic1 = (unsigned int) TEST_MAGIC_MARKER1;
+ callback_param->err_flag = 0;
+ callback_param->num_replies = 0;
+
+ if (use_put_large)
+ {
+ ops[0].option = MHD_OPTION_CONNECTION_MEMORY_LIMIT;
+ ops[0].value = (intptr_t) (PUT_LARGE_SIZE / 4);
+ }
+ else if (use_long_header || use_long_uri)
+ {
+ ops[0].option = MHD_OPTION_CONNECTION_MEMORY_LIMIT;
+ ops[0].value = (intptr_t) (TEST_STRING_VLONG_LEN / 2);
+ }
+ d = MHD_start_daemon (daemon_flags /* | MHD_USE_ERROR_LOG */,
+ *pport, NULL, NULL,
+ &ahc_check, callback_param,
+ MHD_OPTION_CONNECTION_TIMEOUT,
+ (unsigned int) MHD_TIMEOUT,
+ MHD_OPTION_NOTIFY_COMPLETED,
+ &req_completed_cleanup, callback_param,
+ MHD_OPTION_ARRAY, ops,
+ MHD_OPTION_END);
+ if (NULL == d)
+ {
+ fprintf (stderr, "MHD_start_daemon() failed "
+ "at line %d.\n", (int) __LINE__);
+ return NULL;
+ }
+ /* Do not use accept4() as only accept() is intercepted by zzuf */
+ MHD_avoid_accept4_ (d);
+
+ if (0 == *pport)
+ {
+ const union MHD_DaemonInfo *dinfo;
+
+ dinfo = MHD_get_daemon_info (d,
+ MHD_DAEMON_INFO_BIND_PORT);
+ if ( (NULL == dinfo) ||
+ (0 == dinfo->port) )
+ {
+ fprintf (stderr, "MHD_get_daemon_info() failed "
+ "at line %d.\n", (int) __LINE__);
+ MHD_stop_daemon (d);
+ return NULL;
+ }
+ *pport = dinfo->port;
+ }
+ return d;
+}
+
+
+static void
+print_test_starting (unsigned int daemon_flags)
+{
+ fflush (stderr);
+ if (0 != (MHD_USE_INTERNAL_POLLING_THREAD & daemon_flags))
+ {
+ if (0 != (MHD_USE_THREAD_PER_CONNECTION & daemon_flags))
+ {
+ if (0 != (MHD_USE_POLL & daemon_flags))
+ printf ("\nStarting test with internal polling by poll() and "
+ "thread-per-connection.\n");
+ else
+ printf ("\nStarting test with internal polling by select() and "
+ "thread-per-connection.\n");
+ }
+ else
+ {
+ if (0 != (MHD_USE_POLL & daemon_flags))
+ printf ("\nStarting test with internal polling by poll().\n");
+ else if (0 != (MHD_USE_EPOLL & daemon_flags))
+ printf ("\nStarting test with internal polling by 'epoll'.\n");
+ else
+ printf ("\nStarting test with internal polling by select().\n");
+ }
+ }
+ else
+ {
+ if (0 != (MHD_USE_EPOLL & daemon_flags))
+ printf ("\nStarting test with external polling and internal 'epoll'.\n");
+ else
+ printf ("\nStarting test with external polling.\n");
+ }
+ fflush (stdout);
}
static unsigned int
-testMultithreadedGet ()
+testInternalPolling (uint16_t *pport, unsigned int daemon_flags)
{
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_INTERNAL_POLLING_THREAD /* |
MHD_USE_ERROR_LOG */,
- 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ struct ahc_param_strct callback_param;
+ unsigned int ret;
+#ifndef TEST_USE_STATIC_POST_DATA
+ curl_mime *mime;
+#endif /* ! TEST_USE_STATIC_POST_DATA */
+
+ if (0 == (MHD_USE_INTERNAL_POLLING_THREAD & daemon_flags))
+ {
+ fprintf (stderr, "Wrong internal flags, the test is broken. "
+ "At line %d.\n", (int) __LINE__);
+ abort (); /* Wrong flags, error in code */
+ }
+
+ print_test_starting (daemon_flags);
+ initCBC (&cbc, buf, sizeof(buf));
+ d = start_daemon_for_test (daemon_flags, pport, &callback_param);
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://127.0.0.1:11081/hello_world");
- curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
- curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
- curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
- 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, 1L);
- curl_easy_perform (c);
+ return 1;
+
+ ret = 0;
+ c = setupCURL (&cbc, *pport
+#ifndef TEST_USE_STATIC_POST_DATA
+ , &mime
+#endif /* ! TEST_USE_STATIC_POST_DATA */
+ );
+ if (NULL != c)
+ {
+ int i;
+
+ for (i = dry_run ? LOOP_COUNT : 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ callback_param.num_replies = 0;
+ resetCBC (&cbc);
+ /* Run libcurl without checking the result */
+ curl_easy_perform (c);
+ fflush (stderr);
+ }
curl_easy_cleanup (c);
+#ifndef TEST_USE_STATIC_POST_DATA
+ if (NULL != mime)
+ curl_mime_free (mime);
+#endif /* ! TEST_USE_STATIC_POST_DATA */
+ }
+ else
+ ret = 99; /* Not an MHD error */
+
+ if ((0 == ret) && callback_param.err_flag)
+ {
+ fprintf (stderr, "One or more errors have been detected by "
+ "access handler callback function. "
+ "At line %d.\n", (int) __LINE__);
+ ret = 1;
+ }
+ else if ((0 == ret) && cbc.excess_found)
+ {
+ fprintf (stderr, "The extra reply data have been detected one "
+ "or more times. "
+ "At line %d.\n", (int) __LINE__);
+ ret = 1;
}
+
fprintf (stderr, "\n");
- zzuf_socat_stop ();
MHD_stop_daemon (d);
- return 0;
+ fflush (stderr);
+ return ret;
}
static unsigned int
-testExternalGet ()
+testExternalPolling (uint16_t *pport, unsigned int daemon_flags)
{
struct MHD_Daemon *d;
- CURL *c;
+ CURLM *multi;
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_ERROR_LOG */,
- 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ struct ahc_param_strct callback_param;
+ unsigned int ret;
+#ifndef TEST_USE_STATIC_POST_DATA
+ curl_mime *mime;
+#endif /* ! TEST_USE_STATIC_POST_DATA */
+
+ if (0 != (MHD_USE_INTERNAL_POLLING_THREAD & daemon_flags))
+ {
+ fprintf (stderr, "Wrong internal flags, the test is broken. "
+ "At line %d.\n", (int) __LINE__);
+ abort (); /* Wrong flags, error in code */
+ }
+
+ print_test_starting (daemon_flags);
+ initCBC (&cbc, buf, sizeof(buf));
+ d = start_daemon_for_test (daemon_flags, pport, &callback_param);
if (d == NULL)
- return 256;
+ return 1;
+
+ ret = 0;
multi = curl_multi_init ();
if (multi == NULL)
{
- MHD_stop_daemon (d);
- return 512;
+ fprintf (stderr, "curl_multi_init() failed "
+ "at line %d.\n", (int) __LINE__);
+ ret = 99; /* Not an MHD error */
}
- zzuf_socat_start ();
- for (i = 0; i < LOOP_COUNT; i++)
+ else
{
- fprintf (stderr, ".");
- c = curl_easy_init ();
- curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11081/hello_world");
- curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
- curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
- curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
- if (oneone)
- curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ CURL *c;
+ c = setupCURL (&cbc, *pport
+#ifndef TEST_USE_STATIC_POST_DATA
+ , &mime
+#endif /* ! TEST_USE_STATIC_POST_DATA */
+ );
+
+ if (NULL == c)
+ ret = 99; /* Not an MHD error */
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, 1L);
- 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)
+ int i;
+
+ for (i = dry_run ? LOOP_COUNT : 0;
+ (i < LOOP_COUNT) && (0 == ret); i++)
{
- curl_multi_info_read (multi, &running);
- curl_multi_remove_handle (multi, c);
- curl_easy_cleanup (c);
- c = NULL;
+ CURLMcode mret;
+
+ /* The same 'multi' handle will be used in transfers so
+ connection will be reused.
+ The same 'easy' handle is added (and removed later) to (re-)start
+ the same transfer. */
+ mret = curl_multi_add_handle (multi, c);
+ if (CURLM_OK != mret)
+ {
+ fprintf (stderr, "curl_multi_add_handle() failed at %d, "
+ "error: %s\n", (int) __LINE__,
+ curl_multi_strerror (mret));
+ ret = 99; /* Not an MHD error */
+ }
+ else
+ {
+ time_t start;
+
+ fprintf (stderr, ".");
+ callback_param.num_replies = 0;
+ resetCBC (&cbc);
+ start = time (NULL);
+ do
+ {
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int maxfd_curl;
+ MHD_socket maxfd_mhd;
+ int maxfd;
+ int running;
+ struct timeval tv;
+
+ maxfd_curl = 0;
+ maxfd_mhd = MHD_INVALID_SOCKET;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ if (0 == running)
+ {
+ int msgs_left;
+ do
+ {
+ (void) curl_multi_info_read (multi, &msgs_left);
+ } while (0 != msgs_left);
+ break; /* The transfer has been finished */
+ }
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxfd_curl);
+ if (CURLM_OK != mret)
+ {
+ fprintf (stderr, "curl_multi_fdset() failed at line %d, "
+ "error: %s\n", (int) __LINE__,
+ curl_multi_strerror (mret));
+ ret = 99; /* Not an MHD error */
+ break;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxfd_mhd))
+ {
+ fprintf (stderr, "MHD_get_fdset() failed "
+ "at line %d.\n", (int) __LINE__);
+ ret = 1;
+ break;
+ }
+#ifndef MHD_WINSOCK_SOCKETS
+ if ((int) maxfd_mhd > maxfd_curl)
+ maxfd = (int) maxfd_mhd;
+ else
+#endif /* ! MHD_WINSOCK_SOCKETS */
+ maxfd = maxfd_curl;
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+ if (0 == MHD_get_timeout64s (d))
+ tv.tv_usec = 0;
+ else
+ {
+ long curl_to = -1;
+ curl_multi_timeout (multi, &curl_to);
+ if (0 == curl_to)
+ tv.tv_usec = 0;
+ }
+ if (-1 == select (maxfd + 1, &rs, &ws, &es, &tv))
+ {
+#ifdef MHD_POSIX_SOCKETS
+ if (EINTR != errno)
+ fprintf (stderr, "Unexpected select() error "
+ "at line %d.\n", (int) __LINE__);
+#else /* ! MHD_POSIX_SOCKETS */
+ if ((WSAEINVAL != WSAGetLastError ()) ||
+ (0 != rs.fd_count) || (0 != ws.fd_count) ||
+ (0 != es.fd_count))
+ fprintf (stderr, "Unexpected select() error "
+ "at line %d.\n", (int) __LINE__);
+ Sleep ((unsigned long) tv.tv_usec / 1000);
+#endif /* ! MHD_POSIX_SOCKETS */
+ }
+ MHD_run (d);
+ } while (time (NULL) - start <= MHD_TIMEOUT);
+ /* Remove 'easy' handle from 'multi' handle to
+ * restart the transfer or to finish. */
+ curl_multi_remove_handle (multi, c);
+ }
}
- MHD_run (d);
- }
- if (c != NULL)
- {
- curl_multi_remove_handle (multi, c);
curl_easy_cleanup (c);
}
+ curl_multi_cleanup (multi);
+#ifndef TEST_USE_STATIC_POST_DATA
+ if (NULL != mime)
+ curl_mime_free (mime);
+#endif /* ! TEST_USE_STATIC_POST_DATA */
}
+
+ if ((0 == ret) && callback_param.err_flag)
+ {
+ fprintf (stderr, "One or more errors have been detected by "
+ "access handler callback function. "
+ "At line %d.\n", (int) __LINE__);
+ ret = 1;
+ }
+ else if ((0 == ret) && cbc.excess_found)
+ {
+ fprintf (stderr, "The extra reply data have been detected one "
+ "or more times. "
+ "At line %d.\n", (int) __LINE__);
+ ret = 1;
+ }
+
fprintf (stderr, "\n");
- curl_multi_cleanup (multi);
- zzuf_socat_stop ();
MHD_stop_daemon (d);
return 0;
}
+static unsigned int
+run_all_checks (void)
+{
+ uint16_t port;
+ unsigned int testRes;
+ unsigned int ret = 0;
+
+ if (MHD_are_sanitizers_enabled_ ())
+ {
+ fprintf (stderr, "The test does not work with sanitizers. "
+ "At line %d.\n", (int) __LINE__);
+ return 77;
+ }
+ if (! MHD_is_avoid_accept4_possible_ ())
+ {
+ fprintf (stderr,
+ "Non-debug build of MHD on this platform use accept4() function. "
+ "Test with zzuf is not possible. "
+ "At line %d.\n", (int) __LINE__);
+ return 77;
+ }
+ if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
+ port = 0; /* Use system automatic assignment */
+ else
+ {
+ port = 4010; /* Use predefined port, may break parallel testing of
another MHD build */
+ if (oneone)
+ port += 100;
+ if (use_long_uri)
+ port += 30;
+ else if (use_long_header)
+ port += 35;
+ else if (use_get_chunked)
+ port += 0;
+ else if (use_get)
+ port += 5;
+ else if (use_post_form)
+ port += 10;
+ else if (use_post)
+ port += 15;
+ else if (use_put_large)
+ port += 20;
+ else if (use_put_chunked)
+ port += 25;
+ }
+
+ if (! dry_run && (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS)))
+ {
+ testRes = testInternalPolling (&port, MHD_USE_SELECT_INTERNALLY);
+ if ((77 == testRes) || (99 == testRes))
+ return testRes;
+ ret += testRes;
+ testRes = testInternalPolling (&port, MHD_USE_SELECT_INTERNALLY
+ | MHD_USE_THREAD_PER_CONNECTION);
+ if ((77 == testRes) || (99 == testRes))
+ return testRes;
+ ret += testRes;
+
+ if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_POLL))
+ {
+ testRes = testInternalPolling (&port, MHD_USE_POLL_INTERNALLY);
+ if ((77 == testRes) || (99 == testRes))
+ return testRes;
+ ret += testRes;
+ testRes = testInternalPolling (&port, MHD_USE_POLL_INTERNALLY
+ | MHD_USE_THREAD_PER_CONNECTION);
+ if ((77 == testRes) || (99 == testRes))
+ return testRes;
+ ret += testRes;
+ }
+
+ if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_EPOLL))
+ {
+ testRes = testInternalPolling (&port, MHD_USE_EPOLL_INTERNALLY);
+ if ((77 == testRes) || (99 == testRes))
+ return testRes;
+ }
+ }
+ testRes = testExternalPolling (&port, MHD_NO_FLAG);
+ if ((77 == testRes) || (99 == testRes))
+ return testRes;
+ ret += testRes;
+
+ return ret;
+}
+
+
int
main (int argc, char *const *argv)
{
- unsigned int errorCount = 0;
- (void) argc; /* Unused. Silent compiler warning. */
+ unsigned int res;
+
+ oneone = ! has_in_name (argv[0], "10");
+ use_get = has_in_name (argv[0], "_get");
+ use_get_chunked = has_in_name (argv[0], "_get_chunked");
+ use_put = has_in_name (argv[0], "_put");
+ use_put_large = has_in_name (argv[0], "_put_large");
+ use_put_chunked = has_in_name (argv[0], "_put_chunked");
+ use_post = has_in_name (argv[0], "_post");
+ use_post_form = has_in_name (argv[0], "_post_form");
+ use_long_header = has_in_name (argv[0], "_long_header");
+ use_long_uri = has_in_name (argv[0], "_long_uri");
+ use_close = has_in_name (argv[0], "_close");
- oneone = (NULL != strrchr (argv[0], (int) '/')) ?
- (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
- if (0 != curl_global_init (CURL_GLOBAL_WIN32))
- return 2;
- if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS))
+ dry_run = has_param (argc, argv, "--dry-run") ||
+ has_param (argc, argv, "-n");
+
+ if (1 !=
+ ((use_get ? 1 : 0) + (use_put ? 1 : 0) + (use_post ? 1 : 0)))
{
- errorCount += testInternalGet ();
- errorCount += testMultithreadedGet ();
+ fprintf (stderr, "Wrong test name '%s': no or multiple indications "
+ "for the test type.\n", argv[0] ? argv[0] : "(NULL)");
+ return 99;
}
- errorCount += testExternalGet ();
- if (errorCount != 0)
- fprintf (stderr, "Error (code: %u)\n", errorCount);
- curl_global_cleanup ();
- return (0 == errorCount) ? 0 : 1; /* 0 == pass */
+
+ /* zzuf cannot bypass exit values.
+ Unless 'dry run' is used, do not return errors for external error
+ conditions (like out-of-memory) as they will be reported as test
failures. */
+ if (! test_global_init ())
+ return dry_run ? 99 : 0;
+ res = run_all_checks ();
+ test_global_deinit ();
+ if (99 == res)
+ return dry_run ? 99 : 0;
+ if (77 == res)
+ return dry_run ? 77 : 0;
+ return (0 == res) ? 0 : 1; /* 0 == pass */
}
diff --git a/src/testzzuf/test_get_chunked.c b/src/testzzuf/test_get_chunked.c
deleted file mode 100644
index 8013494f..00000000
--- a/src/testzzuf/test_get_chunked.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- This file is part of libmicrohttpd
- Copyright (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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, 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 <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#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 enum MHD_Result
-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 **req_cls)
-{
- static int aptr;
- const char *me = cls;
- struct MHD_Response *response;
- struct MHD_Response **responseptr;
- enum MHD_Result ret;
-
- (void) url;
- (void) version; /* Unused. Silent compiler warning. */
- (void) upload_data;
- (void) upload_data_size; /* Unused. Silent compiler warning. */
-
- if (NULL == url)
- fprintf (stderr, "The \"url\" parameter is NULL.\n");
- if (NULL == method)
- fprintf (stderr, "The \"method\" parameter is NULL.\n");
- if (NULL == version)
- fprintf (stderr, "The \"version\" parameter is NULL.\n");
- if (NULL == upload_data_size)
- fprintf (stderr, "The \"upload_data_size\" parameter is NULL.\n");
- if ((0 != *upload_data_size) && (NULL == upload_data))
- fprintf (stderr, "Upload data is NULL with non-zero size.\n");
- if (0 != strcmp (me, method))
- return MHD_NO; /* unexpected method */
- if (&aptr != *req_cls)
- {
- /* do never respond on first call */
- *req_cls = &aptr;
- return MHD_YES;
- }
- responseptr = malloc (sizeof (struct MHD_Response *));
- if (NULL == responseptr)
- return MHD_NO;
- response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
- 1024,
- &crc, responseptr, &crcf);
- if (NULL == response)
- {
- free (responseptr);
- return MHD_NO;
- }
- *responseptr = response;
- ret = MHD_queue_response (connection,
- MHD_HTTP_OK,
- response);
- MHD_destroy_response (response);
- return ret;
-}
-
-
-static unsigned 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_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG
*/,
- 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://127.0.0.1:11081/hello_world");
- curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
- curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
- curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_INTERNAL_POLLING_THREAD /* |
MHD_USE_ERROR_LOG */,
- 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://127.0.0.1:11081/hello_world");
- curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
- curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
- curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_ERROR_LOG */,
- 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://127.0.0.1:11081/hello_world");
- curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
- curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
- curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
- 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, 1L);
- 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;
- (void) argc; (void) argv; /* Unused. Silent compiler warning. */
-
- if (0 != curl_global_init (CURL_GLOBAL_WIN32))
- return 2;
- if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS))
- {
- errorCount += testInternalGet ();
- errorCount += testMultithreadedGet ();
- }
- errorCount += testExternalGet ();
- if (errorCount != 0)
- fprintf (stderr, "Error (code: %u)\n", errorCount);
- curl_global_cleanup ();
- return (0 == errorCount) ? 0 : 1; /* 0 == pass */
-}
diff --git a/src/testzzuf/test_long_header.c b/src/testzzuf/test_long_header.c
deleted file mode 100644
index c0259398..00000000
--- a/src/testzzuf/test_long_header.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- This file is part of libmicrohttpd
- Copyright (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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file test_long_header.c
- * @brief Testcase for libmicrohttpd handling of very long headers
- * @author Christian Grothoff
- */
-
-#include "MHD_config.h"
-#include "platform.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#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 enum MHD_Result
-apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
-{
- (void) cls; (void) addr; (void) addrlen; /* Unused. Silent compiler
warning. */
- 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)
-{
- (void) ptr; (void) ctx; /* Unused. Silent compiler warning. */
- return size * nmemb;
-}
-
-
-static enum MHD_Result
-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 **req_cls)
-{
- const char *me = cls;
- struct MHD_Response *response;
- enum MHD_Result ret;
- (void) version; (void) upload_data; /* Unused. Silent compiler warning.
*/
- (void) upload_data_size; (void) req_cls; /* Unused. Silent compiler warning.
*/
-
- if (NULL == url)
- fprintf (stderr, "The \"url\" parameter is NULL.\n");
- if (NULL == method)
- fprintf (stderr, "The \"method\" parameter is NULL.\n");
- if (NULL == version)
- fprintf (stderr, "The \"version\" parameter is NULL.\n");
- if (NULL == upload_data_size)
- fprintf (stderr, "The \"upload_data_size\" parameter is NULL.\n");
- if ((0 != *upload_data_size) && (NULL == upload_data))
- fprintf (stderr, "Upload data is NULL with non-zero size.\n");
- 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 unsigned 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_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG
*/,
- 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);
- if (NULL == url)
- {
- zzuf_socat_stop ();
- return 1;
- }
- memset (url, 'a', VERY_LONG);
- url[VERY_LONG - 1] = '\0';
- memcpy (url, "http://127.0.0.1:11081/",
- strlen ("http://127.0.0.1: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, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- free (url);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
-
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG
*/,
- 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);
- if (NULL == url)
- {
- zzuf_socat_stop ();
- curl_easy_cleanup (c);
- return 16;
- }
- 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://127.0.0.1:11081/hello_world");
- curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
- curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
- curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_slist_free_all (header);
- header = NULL;
- curl_easy_cleanup (c);
- free (url);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
-
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-int
-main (int argc, char *const *argv)
-{
- unsigned int errorCount = 0;
- const char *sl;
- (void) argc; /* Unused. Silent compiler warning. */
-
- sl = strrchr (argv[0], (int) '/');
- oneone = (NULL != sl) ? (NULL != strstr (sl, "11")) : 0;
- 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 (0 == errorCount) ? 0 : 1; /* 0 == pass */
-}
diff --git a/src/testzzuf/test_post.c b/src/testzzuf/test_post.c
deleted file mode 100644
index 895c5fce..00000000
--- a/src/testzzuf/test_post.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- This file is part of libmicrohttpd
- Copyright (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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file test_post.c
- * @brief Testcase for libmicrohttpd POST operations using URL-encoding
- * @author Christian Grothoff
- */
-
-#include "MHD_config.h"
-#include "platform.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#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 void
-completed_cb (void *cls,
- struct MHD_Connection *connection,
- void **req_cls,
- enum MHD_RequestTerminationCode toe)
-{
- struct MHD_PostProcessor *pp = *req_cls;
- (void) cls; (void) connection; (void) toe; /* Unused. Silent compiler
warning. */
-
- if (NULL != pp)
- MHD_destroy_post_processor (pp);
- *req_cls = NULL;
-}
-
-
-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 enum MHD_Result
-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;
- (void) kind; (void) filename; (void) content_type; /* Unused. Silent
compiler warning. */
- (void) transfer_encoding; (void) off; /* Unused. Silent compiler
warning. */
-
- 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 enum MHD_Result
-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 **req_cls)
-{
- static int eok;
- struct MHD_Response *response;
- struct MHD_PostProcessor *pp;
- enum MHD_Result ret;
- (void) cls; (void) version; /* Unused. Silent compiler warning. */
-
- if (NULL == url)
- fprintf (stderr, "The \"url\" parameter is NULL.\n");
- if (NULL == method)
- fprintf (stderr, "The \"method\" parameter is NULL.\n");
- if (NULL == version)
- fprintf (stderr, "The \"version\" parameter is NULL.\n");
- if (NULL == upload_data_size)
- fprintf (stderr, "The \"upload_data_size\" parameter is NULL.\n");
- if ((0 != *upload_data_size) && (NULL == upload_data))
- fprintf (stderr, "Upload data is NULL with non-zero size.\n");
- if (0 != strcmp ("POST", method))
- {
- return MHD_NO; /* unexpected method */
- }
- pp = *req_cls;
- if (pp == NULL)
- {
- eok = 0;
- pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok);
- *req_cls = 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);
- *req_cls = NULL;
- return ret;
- }
- *upload_data_size = 0;
- return MHD_YES;
-}
-
-
-static unsigned 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_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG
*/,
- 11080, NULL, NULL, &ahc_echo, NULL,
- MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, 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://127.0.0.1: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, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
-
- return 0;
-}
-
-
-static unsigned 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_INTERNAL_POLLING_THREAD /* |
MHD_USE_ERROR_LOG */,
- 11080, NULL, NULL, &ahc_echo, NULL,
- MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, 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://127.0.0.1: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, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
-
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_ERROR_LOG */,
- 1082, NULL, NULL, &ahc_echo, NULL,
- MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, 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://127.0.0.1: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, 1L);
- 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, 1L);
-
-
- 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;
- (void) argc; /* Unused. Silent compiler warning. */
-
- oneone = (NULL != strrchr (argv[0], (int) '/')) ?
- (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
- if (0 != curl_global_init (CURL_GLOBAL_WIN32))
- return 2;
- if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS))
- {
- errorCount += testInternalPost ();
- errorCount += testMultithreadedPost ();
- }
- errorCount += testExternalPost ();
- if (errorCount != 0)
- fprintf (stderr, "Error (code: %u)\n", errorCount);
- curl_global_cleanup ();
- return (0 == errorCount) ? 0 : 1; /* 0 == pass */
-}
diff --git a/src/testzzuf/test_post_form.c b/src/testzzuf/test_post_form.c
deleted file mode 100644
index b16b0cdd..00000000
--- a/src/testzzuf/test_post_form.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- This file is part of libmicrohttpd
- Copyright (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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file test_post_form.c
- * @brief Testcase for libmicrohttpd POST operations using multipart/postform
data
- * @author Christian Grothoff
- */
-
-#include "MHD_config.h"
-#include "platform.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#endif
-
-
-#include "socat.c"
-
-static int oneone;
-
-struct CBC
-{
- char *buf;
- size_t pos;
- size_t size;
-};
-
-
-static void
-completed_cb (void *cls,
- struct MHD_Connection *connection,
- void **req_cls,
- enum MHD_RequestTerminationCode toe)
-{
- struct MHD_PostProcessor *pp = *req_cls;
- (void) cls; (void) connection; (void) toe; /* Unused. Silent
compiler warning. */
-
- if (NULL != pp)
- MHD_destroy_post_processor (pp);
- *req_cls = NULL;
-}
-
-
-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 enum MHD_Result
-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;
- (void) kind; (void) filename; (void) content_type; /* Unused. Silent
compiler warning. */
- (void) transfer_encoding; (void) off; /* Unused. Silent compiler
warning. */
-
- 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 enum MHD_Result
-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 **req_cls)
-{
- static int eok;
- struct MHD_Response *response;
- struct MHD_PostProcessor *pp;
- enum MHD_Result ret;
- (void) cls; (void) version; /* Unused. Silent compiler warning. */
-
- if (NULL == url)
- fprintf (stderr, "The \"url\" parameter is NULL.\n");
- if (NULL == method)
- fprintf (stderr, "The \"method\" parameter is NULL.\n");
- if (NULL == version)
- fprintf (stderr, "The \"version\" parameter is NULL.\n");
- if (NULL == upload_data_size)
- fprintf (stderr, "The \"upload_data_size\" parameter is NULL.\n");
- if ((0 != *upload_data_size) && (NULL == upload_data))
- fprintf (stderr, "Upload data is NULL with non-zero size.\n");
- if (0 != strcmp ("POST", method))
- {
- return MHD_NO; /* unexpected method */
- }
- pp = *req_cls;
- if (pp == NULL)
- {
- eok = 0;
- pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok);
- if (pp == NULL)
- return MHD_NO;
- *req_cls = 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);
- *req_cls = 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 unsigned 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_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG
*/,
- 11080, NULL, NULL, &ahc_echo, NULL,
- MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, 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://127.0.0.1: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, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- curl_formfree (pd);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_INTERNAL_POLLING_THREAD /* |
MHD_USE_ERROR_LOG */,
- 11080, NULL, NULL, &ahc_echo, NULL,
- MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, 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://127.0.0.1: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, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- curl_formfree (pd);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_ERROR_LOG */,
- 1082, NULL, NULL, &ahc_echo, NULL,
- MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, 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://127.0.0.1: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, 1L);
- 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, 1L);
-
- 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 ();
- curl_multi_cleanup (multi);
-
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-int
-main (int argc, char *const *argv)
-{
- unsigned int errorCount = 0;
- (void) argc; /* Unused. Silent compiler warning. */
-
- oneone = (NULL != strrchr (argv[0], (int) '/')) ?
- (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
- if (0 != curl_global_init (CURL_GLOBAL_WIN32))
- return 2;
- if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS))
- {
- errorCount += testInternalPost ();
- errorCount += testMultithreadedPost ();
- }
- errorCount += testExternalPost ();
- if (errorCount != 0)
- fprintf (stderr, "Error (code: %u)\n", errorCount);
- curl_global_cleanup ();
- return (0 == errorCount) ? 0 : 1; /* 0 == pass */
-}
diff --git a/src/testzzuf/test_put.c b/src/testzzuf/test_put.c
deleted file mode 100644
index 9e3749d1..00000000
--- a/src/testzzuf/test_put.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- This file is part of libmicrohttpd
- Copyright (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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file test_put.c
- * @brief Testcase for libmicrohttpd PUT operations
- * @author Christian Grothoff
- */
-
-#include "MHD_config.h"
-#include "platform.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#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 enum MHD_Result
-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 **req_cls)
-{
- int *done = cls;
- struct MHD_Response *response;
- enum MHD_Result ret;
- (void) version; (void) req_cls; /* Unused. Silent compiler warning. */
-
- if (NULL == url)
- fprintf (stderr, "The \"url\" parameter is NULL.\n");
- if (NULL == method)
- fprintf (stderr, "The \"method\" parameter is NULL.\n");
- if (NULL == version)
- fprintf (stderr, "The \"version\" parameter is NULL.\n");
- if (NULL == upload_data_size)
- fprintf (stderr, "The \"upload_data_size\" parameter is NULL.\n");
- if ((0 != *upload_data_size) && (NULL == upload_data))
- fprintf (stderr, "Upload data is NULL with non-zero size.\n");
- 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 unsigned 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_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG
*/,
- 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://127.0.0.1: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, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_INTERNAL_POLLING_THREAD /* |
MHD_USE_ERROR_LOG */,
- 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://127.0.0.1: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, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_ERROR_LOG */,
- 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://127.0.0.1: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, 1L);
- 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, 1L);
-
-
- 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;
- (void) argc; /* Unused. Silent compiler warning. */
-
- oneone = (NULL != strrchr (argv[0], (int) '/')) ?
- (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
- if (0 != curl_global_init (CURL_GLOBAL_WIN32))
- return 2;
- if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS))
- {
- errorCount += testInternalPut ();
- errorCount += testMultithreadedPut ();
- }
- errorCount += testExternalPut ();
- if (errorCount != 0)
- fprintf (stderr, "Error (code: %u)\n", errorCount);
- curl_global_cleanup ();
- return (0 == errorCount) ? 0 : 1; /* 0 == pass */
-}
diff --git a/src/testzzuf/test_put_chunked.c b/src/testzzuf/test_put_chunked.c
deleted file mode 100644
index 3dd67e43..00000000
--- a/src/testzzuf/test_put_chunked.c
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- This file is part of libmicrohttpd
- Copyright (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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, 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 <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#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 enum MHD_Result
-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 **req_cls)
-{
- int *done = cls;
- struct MHD_Response *response;
- enum MHD_Result ret;
- int have;
- (void) version; (void) req_cls; /* Unused. Silent compiler warning. */
-
- if (NULL == url)
- fprintf (stderr, "The \"url\" parameter is NULL.\n");
- if (NULL == method)
- fprintf (stderr, "The \"method\" parameter is NULL.\n");
- if (NULL == version)
- fprintf (stderr, "The \"version\" parameter is NULL.\n");
- if (NULL == upload_data_size)
- fprintf (stderr, "The \"upload_data_size\" parameter is NULL.\n");
- if ((0 != *upload_data_size) && (NULL == upload_data))
- fprintf (stderr, "Upload data is NULL with non-zero size.\n");
- 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 == have)
- {
- (void) 0; /* Do nothing - no data yet */
- }
- else 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 unsigned 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_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
- 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, ".");
- done_flag = 0;
- c = curl_easy_init ();
- curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1: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, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
- 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://127.0.0.1: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, 1L);
- 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, 1L);
- 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 unsigned 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_ERROR_LOG,
- 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, ".");
- done_flag = 0;
- c = curl_easy_init ();
- curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1: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, 1L);
- 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, 1L);
-
-
- 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;
- (void) argc; (void) argv; /* Unused. Silent compiler warning. */
-
- if (0 != curl_global_init (CURL_GLOBAL_WIN32))
- return 2;
- if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS))
- {
- errorCount += testInternalPut ();
- errorCount += testMultithreadedPut ();
- }
- errorCount += testExternalPut ();
- if (errorCount != 0)
- fprintf (stderr, "Error (code: %u)\n", errorCount);
- curl_global_cleanup ();
- return (0 == errorCount) ? 0 : 1; /* 0 == pass */
-}
diff --git a/src/testzzuf/test_put_large.c b/src/testzzuf/test_put_large.c
deleted file mode 100644
index 900284ef..00000000
--- a/src/testzzuf/test_put_large.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- This file is part of libmicrohttpd
- Copyright (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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file test_put_large.c
- * @brief Testcase for libmicrohttpd PUT operations
- * @author Christian Grothoff
- */
-
-#include "MHD_config.h"
-#include "platform.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#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 enum MHD_Result
-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 **req_cls)
-{
- int *done = cls;
- struct MHD_Response *response;
- enum MHD_Result ret;
- (void) version; (void) req_cls; /* Unused. Silent compiler warning. */
-
- if (NULL == url)
- fprintf (stderr, "The \"url\" parameter is NULL.\n");
- if (NULL == method)
- fprintf (stderr, "The \"method\" parameter is NULL.\n");
- if (NULL == version)
- fprintf (stderr, "The \"version\" parameter is NULL.\n");
- if (NULL == upload_data_size)
- fprintf (stderr, "The \"upload_data_size\" parameter is NULL.\n");
- if ((0 != *upload_data_size) && (NULL == upload_data))
- fprintf (stderr, "Upload data is NULL with non-zero size.\n");
- 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 unsigned 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_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG
*/,
- 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://127.0.0.1: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, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_INTERNAL_POLLING_THREAD /* |
MHD_USE_ERROR_LOG */,
- 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://127.0.0.1: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, 1L);
- 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, 1L);
- curl_easy_perform (c);
- curl_easy_cleanup (c);
- }
- fprintf (stderr, "\n");
- zzuf_socat_stop ();
- MHD_stop_daemon (d);
- return 0;
-}
-
-
-static unsigned 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_ERROR_LOG */,
- 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://127.0.0.1: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, 1L);
- 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, 1L);
-
-
- 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;
- (void) argc; /* Unused. Silent compiler warning. */
-
- oneone = (NULL != strrchr (argv[0], (int) '/')) ?
- (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
- if (0 != curl_global_init (CURL_GLOBAL_WIN32))
- return 2;
- put_buffer = malloc (PUT_SIZE);
- if (0 == put_buffer)
- return 77;
- memset (put_buffer, 1, PUT_SIZE);
- if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS))
- {
- errorCount += testInternalPut ();
- errorCount += testMultithreadedPut ();
- }
- errorCount += testExternalPut ();
- free (put_buffer);
- if (errorCount != 0)
- fprintf (stderr, "Error (code: %u)\n", errorCount);
- curl_global_cleanup ();
- return (0 == errorCount) ? 0 : 1; /* 0 == pass */
-}
diff --git a/src/testzzuf/zzuf_test_runner.sh b/src/testzzuf/zzuf_test_runner.sh
new file mode 100755
index 00000000..aa1dfdde
--- /dev/null
+++ b/src/testzzuf/zzuf_test_runner.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+mhd_listen_ip='127.0.0.1'
+max_runtime_sec='300'
+
+if test "x${ZZUF}" = "xno" ; then
+ echo "zzuf command missing" 1>&2
+ exit 77
+fi
+
+if command -v "${ZZUF}" > /dev/null 2>&1 ; then : ; else
+ echo "zzuf command missing" 1>&2
+ exit 77
+fi
+
+# zzuf cannot pass-through the return value of checked program
+# so try the direct dry-run first to get possibe 77 or 99 codes
+echo "## Dry-run of the $@..."
+if "$@" --dry-run ; then
+ echo "# Dry-run succeded."
+else
+ res_code=$?
+ echo "Dry-run failed with exit code $res_code. $@ will not be run with
zzuf." 1>&2
+ exit $res_code
+fi
+
+# fuzz the input only for IP ${mhd_listen_ip}. libcurl uses another IP
+# in this test therefore libcurl input is not fuzzed.
+zzuf_all_params="--ratio=0.001:0.4 --autoinc --verbose --signal \
+ --max-usertime=${max_runtime_sec} --check-exit --network \
+ --allow=${mhd_listen_ip} --exclude=."
+
+if test -n "${ZZUF_SEED}" ; then
+ zzuf_all_params="${zzuf_all_params} --seed=${ZZUF_SEED}"
+fi
+
+if test -n "${ZZUF_FLAGS}" ; then
+ zzuf_all_params="${zzuf_all_params} ${ZZUF_FLAGS}"
+fi
+
+# Uncomment the next line to see more data in logs
+#zzuf_all_params="${zzuf_all_params} -dd"
+
+echo "## Dry-run of the $@ with zzuf..."
+if "$ZZUF" ${zzuf_all_params} "$@" --dry-run ; then
+ echo "# Dry-run with zzuf succeded."
+else
+ res_code=$?
+ echo "$@ cannot be run with zzuf. The test is skipped." 1>&2
+ exit 77
+fi
+
+echo "## Real test of $@ with zzuf..."
+"$ZZUF" ${zzuf_all_params} "$@"
+exit $?
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libmicrohttpd] 02/29: Re-implemented parsing of the request line from scratch., (continued)
- [libmicrohttpd] 02/29: Re-implemented parsing of the request line from scratch., gnunet, 2023/06/20
- [libmicrohttpd] 08/29: tests: minor improvemnts, gnunet, 2023/06/20
- [libmicrohttpd] 07/29: Removed request line and headers processing old functions and variables, gnunet, 2023/06/20
- [libmicrohttpd] 09/29: daemon: added debug member to avoid accept4() usage, gnunet, 2023/06/20
- [libmicrohttpd] 01/29: Refactoring: check whether memory block is resizable, gnunet, 2023/06/20
- [libmicrohttpd] 06/29: Re-implemented parsing of the request headers and footers from scratch., gnunet, 2023/06/20
- [libmicrohttpd] 12/29: Added back testing with socat as a fallback option, gnunet, 2023/06/20
- [libmicrohttpd] 05/29: Request body processing: removed impossible code paths, gnunet, 2023/06/20
- [libmicrohttpd] 16/29: Added tests with single and double folded header, gnunet, 2023/06/20
- [libmicrohttpd] 21/29: process_request_body(): minor readability improvementы, gnunet, 2023/06/20
- [libmicrohttpd] 11/29: testzzuf: re-worked zzuf testing,
gnunet <=
- [libmicrohttpd] 10/29: testzzuf: added special debug functions, gnunet, 2023/06/20
- [libmicrohttpd] 22/29: Minor refactoring for partially processed request body, gnunet, 2023/06/20
- [libmicrohttpd] 14/29: Added test with folded header placed last, gnunet, 2023/06/20
- [libmicrohttpd] 15/29: Added test with large folded header, gnunet, 2023/06/20
- [libmicrohttpd] 20/29: Added checks for correct values specified for connection memory limits, gnunet, 2023/06/20
- [libmicrohttpd] 19/29: connection: fixed pipelined requests processing, gnunet, 2023/06/20
- [libmicrohttpd] 13/29: Added new tests with header fold, gnunet, 2023/06/20
- [libmicrohttpd] 18/29: Added proper connection's buffers pre-initialisaion, gnunet, 2023/06/20
- [libmicrohttpd] 17/29: connection.c: corrected error responses, gnunet, 2023/06/20
- [libmicrohttpd] 24/29: process new connection: fixed missing mutex unlock in error handling path, gnunet, 2023/06/20