gnunet-svn
[Top][All Lists]
Advanced

[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, &copyBuffer);
-    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,
+                                          &copyBuffer))) &&
+      (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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-  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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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, &copyBuffer);
-    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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]