Added back testing with socat as a fallback option

This commit is contained in:
Evgeny Grin (Karlson2k)
2023-06-20 23:22:54 +03:00
parent 40b675518b
commit c0f7cbb280
5 changed files with 273 additions and 53 deletions
+22 -5
View File
@@ -1789,6 +1789,7 @@ AS_VAR_IF([use_heavy_tests], ["yes"],
]
)
AM_CONDITIONAL([HEAVY_TESTS],[test "x$use_heavy_tests" = "xyes"])
AM_CONDITIONAL([VHEAVY_TESTS],[test "x$use_vheavy_tests" = "xyes"])
AM_CONDITIONAL([TESTS_STRESS_OS],[false])
AC_ARG_ENABLE([[poll]],
@@ -4844,6 +4845,7 @@ int main(void)
# fuzzing tests
run_zzuf_tests="no"
zzuf_socat_mandatory="no"
AS_VAR_IF([use_heavy_tests],["yes"],
[
AS_VAR_IF([enable_curl],["yes"],
@@ -4855,19 +4857,32 @@ AS_VAR_IF([use_heavy_tests],["yes"],
run_zzuf_tests_MSG="no, zzuf tool not found"
],
[
AC_PATH_PROG([SOCAT],[socat],[no])
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"
zzuf_socat_mandatory="yes"
AS_VAR_IF([SOCAT],["no"],
[run_zzuf_tests_MSG="no, socat not found, but required for fuzzing tests on this platform without asserts enabled"],
[
run_zzuf_tests="yes"
run_zzuf_tests_MSG="yes, with zzuf and socat tools"
]
)
],
[test -n "${enabled_sanitizers}"],
[
run_zzuf_tests="no"
run_zzuf_tests_MSG="no, fuzzing tests cannot be used with sanitizers"
zzuf_socat_mandatory="yes"
AS_VAR_IF([SOCAT],["no"],
[run_zzuf_tests_MSG="no, socat not found, but required for fuzzing tests when sanitizers enabled"],
[
run_zzuf_tests="yes"
run_zzuf_tests_MSG="yes, with zzuf and socat tools"
]
)
],
[
run_zzuf_tests="yes"
run_zzuf_tests_MSG="yes"
run_zzuf_tests_MSG="yes, with zzuf tool"
]
)
]
@@ -4885,6 +4900,7 @@ AS_VAR_IF([use_heavy_tests],["yes"],
]
)
AM_CONDITIONAL([RUN_ZZUF_TESTS],[test "x$run_zzuf_tests" = "xyes"])
AM_CONDITIONAL([FORCE_USE_ZZUF_SOCAT],[test "x$zzuf_socat_mandatory" = "xyes"])
# Final flags that may interfere with autoconf detections
AS_CASE([${enable_build_type}],[debug|debugger],
@@ -4959,6 +4975,7 @@ AC_CONFIG_COMMANDS([po-directories],
AC_DEFINE_DIR([MHD_PLUGIN_INSTALL_PREFIX], [libdir/libmicrohttpd], [tls plugins])
AC_SUBST([ZZUF])
AC_SUBST([SOCAT])
# should experimental code be compiled (code that may not yet compile)?
AC_MSG_CHECKING(whether to compile experimental code)
+26 -3
View File
@@ -10,6 +10,15 @@ ZZUF_SEED = 0
# Additional flags for zzuf
ZZUF_FLAGS =
# Additional flags for socat (if socat is used)
SOCAT_FLAGS =
if FORCE_USE_ZZUF_SOCAT
TEST_RUNNER_SCRIPT = zzuf_socat_test_runner.sh
else
TEST_RUNNER_SCRIPT = zzuf_test_runner.sh
endif
AM_CPPFLAGS = \
-I$(top_srcdir)/src/include \
-I$(top_srcdir)/src/microhttpd \
@@ -23,7 +32,9 @@ AM_LDFLAGS = $(LDFLAGS_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 ;
ZZUF_FLAGS="$(ZZUF_FLAGS)" ; export ZZUF_FLAGS ; \
SOCAT="$(SOCAT)" ; export SOCAT ; \
SOCAT_FLAGS="$(SOCAT_FLAGS)" ; export SOCAT_FLAGS ;
if USE_COVERAGE
AM_CFLAGS += -fprofile-arcs -ftest-coverage
@@ -70,9 +81,21 @@ check_PROGRAMS = \
TESTS = $(check_PROGRAMS)
dist_check_SCRIPTS = zzuf_test_runner.sh
dist_check_SCRIPTS = zzuf_test_runner.sh zzuf_socat_test_runner.sh
LOG_COMPILER = @SHELL@ $(srcdir)/zzuf_test_runner.sh
LOG_COMPILER = @SHELL@ "$(srcdir)/$(TEST_RUNNER_SCRIPT)"
if VHEAVY_TESTS
check_SCRIPTS = warn_vheavy_use
.PHONY: warn_vheavy_use
endif
warn_vheavy_use:
@echo "NOTICE" ; \
echo "NOTICE: Full heavy tests are enabled. Each test may take up to several minutes to complete." ; \
echo "NOTICE"
tests_common_sources = mhd_debug_funcs.h mhd_debug_funcs.c
+65 -42
View File
@@ -96,8 +96,14 @@ static int use_post_form;
static int use_long_header;
static int use_long_uri;
static int use_close;
static int run_with_socat;
#define TEST_BASE_URI "http:/" "/127.0.0.1/test_uri"
#define TEST_BASE_URI_SOCAT "http:/" "/127.0.0.121/test_uri"
#define SOCAT_PORT 10121
#define TEST_BASE_PORT 4010
#define EMPTY_PAGE "Empty page."
#define EMPTY_PAGE_ALT "Alternative empty page."
@@ -959,19 +965,24 @@ setupCURL (struct CBC *cbc, uint16_t port
CURLcode e;
char *buf;
const char *uri_to_use;
const char *base_uri;
#ifndef TEST_USE_STATIC_POST_DATA
*mime = NULL;
#endif /* ! TEST_USE_STATIC_POST_DATA */
base_uri = run_with_socat ? TEST_BASE_URI_SOCAT : TEST_BASE_URI;
if (! use_long_uri)
{
uri_to_use = TEST_BASE_URI;
uri_to_use = base_uri;
buf = NULL;
}
else
{
size_t pos;
size_t base_uri_len;
base_uri_len = strlen (base_uri);
buf = malloc (TEST_STRING_VLONG_LEN + 1);
if (NULL == buf)
{
@@ -979,8 +990,8 @@ setupCURL (struct CBC *cbc, uint16_t port
"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);
memcpy (buf, base_uri, base_uri_len);
for (pos = base_uri_len;
pos < TEST_STRING_VLONG_LEN;
++pos)
{
@@ -993,6 +1004,8 @@ setupCURL (struct CBC *cbc, uint16_t port
buf[TEST_STRING_VLONG_LEN] = 0;
uri_to_use = buf;
}
if (run_with_socat)
port = SOCAT_PORT;
c = curl_easy_init ();
if (NULL == c)
@@ -1189,8 +1202,10 @@ start_daemon_for_test (unsigned int daemon_flags, uint16_t *pport,
"at line %d.\n", (int) __LINE__);
return NULL;
}
/* Do not use accept4() as only accept() is intercepted by zzuf */
MHD_avoid_accept4_ (d);
if (! run_with_socat)
MHD_avoid_accept4_ (d);
if (0 == *pport)
{
@@ -1516,44 +1531,49 @@ run_all_checks (void)
unsigned int testRes;
unsigned int ret = 0;
if (MHD_are_sanitizers_enabled_ ())
if (! run_with_socat)
{
fprintf (stderr, "The test does not work with sanitizers. "
"At line %d.\n", (int) __LINE__);
return 77;
if (MHD_are_sanitizers_enabled_ ())
{
fprintf (stderr, "Direct run with zzuf 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. "
"Direct run 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 = TEST_BASE_PORT; /* 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 (! 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;
}
port = TEST_BASE_PORT; /* Use predefined port, may break parallel testing of another MHD build */
if (! dry_run && (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS)))
{
@@ -1600,6 +1620,7 @@ int
main (int argc, char *const *argv)
{
unsigned int res;
int use_magic_exit_codes;
oneone = ! has_in_name (argv[0], "10");
use_get = has_in_name (argv[0], "_get");
@@ -1613,6 +1634,7 @@ main (int argc, char *const *argv)
use_long_uri = has_in_name (argv[0], "_long_uri");
use_close = has_in_name (argv[0], "_close");
run_with_socat = has_param (argc, argv, "--with-socat");
dry_run = has_param (argc, argv, "--dry-run") ||
has_param (argc, argv, "-n");
@@ -1623,17 +1645,18 @@ main (int argc, char *const *argv)
"for the test type.\n", argv[0] ? argv[0] : "(NULL)");
return 99;
}
use_magic_exit_codes = run_with_socat || dry_run;
/* 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;
return use_magic_exit_codes ? 99 : 0;
res = run_all_checks ();
test_global_deinit ();
if (99 == res)
return dry_run ? 99 : 0;
return use_magic_exit_codes ? 99 : 0;
if (77 == res)
return dry_run ? 77 : 0;
return use_magic_exit_codes ? 77 : 0;
return (0 == res) ? 0 : 1; /* 0 == pass */
}
+118
View File
@@ -0,0 +1,118 @@
#!/bin/sh
if set -m ; then : ; else
echo "The shell $SHELL does not support background jobs, the test cannot run." 1>&2
exit 77
fi
socat_listen_ip='127.0.0.121'
socat_listen_port='10121'
mhd_listen_port='4010'
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
if test "x${SOCAT}" = "xno" ; then
echo "socat command missing" 1>&2
exit 77
fi
if command -v "${SOCAT}" > /dev/null 2>&1 ; then : ; else
echo "socat command missing" 1>&2
exit 77
fi
socat_test_params="-ls -lu \
-T0.1 -4 \
TCP-LISTEN:${socat_listen_port},bind=${socat_listen_ip},reuseaddr,linger=2,linger2=1,accept-timeout=0.1 \
TCP:127.0.0.1:${mhd_listen_port},reuseaddr"
echo "## Trying to run socat to test ports availability..."
if "${SOCAT}" ${socat_test_params} ; then
echo "Success."
else
echo "socat test run failed" 1>&2
exit 77
fi
# fuzz the input only for IP ${socat_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=${socat_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 zzuf data in logs
#zzuf_all_params="${zzuf_all_params} -dd"
socat_options="-ls -lu \
-T3 -4"
socat_addr1="TCP-LISTEN:${socat_listen_port},bind=${socat_listen_ip},reuseaddr,nodelay,linger=2,linger2=1,accept-timeout=${max_runtime_sec},fork"
socat_addr2="TCP:127.0.0.1:${mhd_listen_port},reuseaddr,connect-timeout=3,nodelay,linger=2,linger2=1"
if test -n "${SOCAT_FLAGS}" ; then
socat_options="${socat_options} ${SOCAT_FLAGS}"
fi
# Uncomment the next line to see more socat data in logs
#socat_options="${socat_options} -dd -D"
# Uncomment the next line to see all traffic in logs
#socat_options="${socat_options} -v"
stop_zzuf_socat ()
{
trap - EXIT
if test -n "$zzuf_pid" ; then
echo "The test has been interrupted." 1>&2
test "x$zzuf_pid" = "xstarting" && zzuf_pid=$!
# Finish zzuf + socat
kill -TERM ${zzuf_pid} -${zzuf_pid}
# Finish the test
kill -INT %2 2> /dev/null || kill -INT %1 2> /dev/null
exit 99
fi
}
echo "## Starting zzuf with socat to reflect fuzzed traffic..."
trap 'stop_zzuf_socat' EXIT
zzuf_pid="starting"
"${ZZUF}" ${zzuf_all_params} "${SOCAT}" ${socat_options} ${socat_addr1} ${socat_addr2} &
if test $? -eq 0 ; then
zzuf_pid=$!
echo "zzuf with socat has been started."
else
zzuf_pid=''
echo "Failed to start zzuf with socat" 1>&2
exit 99
fi
echo "## Starting real test of $@ with traffic fuzzed by zzuf with socat..."
"$@" --with-socat
test_result=$?
trap - EXIT
echo "$@ has exited with the return code $test_result"
if kill -s 0 -- $$ 2> /dev/null ; then
if kill -s 0 -- ${zzuf_pid} -${zzuf_pid} ; then : ; else
echo "No running zzuf with socat is detected after the test." 1>&2
echo "Looks like zzuf ended prematurely, at least part of the testing has not been performed." 1>&2
test_result=99
fi
fi
kill -TERM ${zzuf_pid} -${zzuf_pid}
zzuf_pid=''
exit $test_result
+42 -3
View File
@@ -13,6 +13,40 @@ if command -v "${ZZUF}" > /dev/null 2>&1 ; then : ; else
exit 77
fi
run_with_socat ()
{
echo "Trying to run the test with socat..."
script_dir=""
if command -v dirname > /dev/null 2>&1 ; then
test_dir=`dirname /`
if test "x${test_dir}" = "x/" ; then
if dirname "$1" > /dev/null 2>&1 ; then
script_dir=`dirname "$1"`
if test -n "${script_dir}" ; then
# Assume script is not in the root dir
script_dir="${script_dir}/"
else
script_dir="./"
fi
fi
fi
fi
if test -z "${script_dir}" ; then
if echo "$1" | sed 's|[^/]*$||' > /dev/null 2>&1 ; then
script_dir=`echo "$1" | sed 's|[^/]*$||'`
if test -z "${script_dir}" ; then
script_dir="./"
fi
fi
fi
if test -z "${script_dir}" ; then
echo "Cannot determine script location, will try current directory." 1>&2
script_dir="./"
fi
$SHELL "${script_dir}zzuf_socat_test_runner.sh" "$@"
exit $?
}
# 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 $@..."
@@ -20,7 +54,11 @@ 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
echo "Dry-run failed with exit code $res_code." 1>&2
if test $res_code -ne 99; then
run_with_socat "$@"
fi
echo "$@ will not be run with zzuf." 1>&2
exit $res_code
fi
@@ -46,8 +84,9 @@ 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
echo "$@ cannot be run with zzuf directly." 1>&2
run_with_socat "$@"
exit $res_code
fi
echo "## Real test of $@ with zzuf..."