blob: 54ee551e8d5e5e1cde60470c79fc6b38172b17d6 [file]
#!/bin/bash -ex
# Not every branch has every MPM: MotorZ is on trunk only, for now. A job
# which configures a branch without it has nothing to build or test, so it
# says so and succeeds; the same workflow can then be used on both branches.
case "${CONFIG:-}" in
*--with-mpm=motorz*)
if ! test -d server/mpm/motorz; then
echo "::notice::This branch has no MotorZ MPM, nothing to do."
exit 0
fi
;;
esac
# Test for APLOGNO() macro errors (duplicates, empty args) etc. For
# trunk, run the updater script to see if it fails. If it succeeds
# and changes any files (because there was a missing argument), the
# git diff will be non-empty, so fail for that case too. For
# non-trunk use a grep and only catch the empty argument case.
if test -v TEST_LOGNO; then
if test -f docs/log-message-tags/update-log-msg-tags; then
find server modules os -name \*.c | \
xargs perl docs/log-message-tags/update-log-msg-tags
git diff --exit-code .
: PASSED
exit 0
else
set -o pipefail
if find server modules os -name \*.c | \
xargs grep -C1 --color=always 'APLOGNO()'; then
: FAILED
exit 1
else
: PASSED
exit 0
fi
fi
fi
### Installed apr/apr-util don't include the *.m4 files but the
### Debian packages helpfully install them, so use the system APR to buildconf
./buildconf --with-apr=/usr/bin/apr-1-config ${BUILDCONFIG}
PREFIX=${PREFIX:-$HOME/build/httpd-root}
# If perl-framework testing is required, the workflow checks it out
# here:
if test -d test/perl-framework; then
CONFIG="$CONFIG --enable-load-all-modules"
if grep -q ^check: Makefile.in; then
CONFIG="--with-test-suite=test/perl-framework $CONFIG"
WITH_TEST_SUITE=1
fi
# Use the CPAN environment.
eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)
fi
if test -v APR_VERSION; then
CONFIG="$CONFIG --with-apr=$HOME/root/apr-${APR_VERSION}"
else
CONFIG="$CONFIG --with-apr=/usr"
fi
if test -v APU_VERSION; then
CONFIG="$CONFIG --with-apr-util=$HOME/root/apr-util-${APU_VERSION}"
else
CONFIG="$CONFIG --with-apr-util=/usr"
fi
# Pick up the rustls install built previously.
if test -v TEST_MOD_TLS -a -v RUSTLS_VERSION; then
CONFIG="$CONFIG --with-tls --with-rustls=$HOME/root/rustls"
fi
if test -v TEST_OPENSSL3; then
CONFIG="$CONFIG --with-ssl=$HOME/root/openssl3"
export PATH=$HOME/root/openssl3/bin:$PATH
# Force everything built to hard-code an RPATH
export LDFLAGS="-Wl,-rpath,$HOME/root/openssl3/lib -Wl,-rpath,$HOME/root/openssl3/lib64"
openssl version
fi
if test -v TEST_NGHTTP2; then
# APACHE_CHECK_NGHTTP2 only yields -L, so an RPATH is needed here or
# mod_http2.so resolves to the system libnghttp2 at run-time.
CONFIG="$CONFIG --with-nghttp2=$HOME/root/nghttp2"
export LDFLAGS="${LDFLAGS:-} -Wl,-rpath,$HOME/root/nghttp2/lib"
fi
srcdir=$PWD
if test -v TEST_VPATH; then
mkdir ../vpath
cd ../vpath
fi
builddir=$PWD
$srcdir/configure --prefix=$PREFIX $CONFIG
make $MFLAGS
if test -v TEST_NGHTTP2; then
ldd modules/http2/.libs/mod_http2.so | grep --color=always nghttp2
if ! ldd modules/http2/.libs/mod_http2.so | grep -q "$HOME/root/nghttp2/lib"; then
: mod_http2 is not linked against the nghttp2 built from source
exit 1
fi
fi
if test -v TEST_OPENSSL3; then
# Clear the library/run paths so that anything else run during
# testing is not forced to use the custom OpenSSL build; e.g. perl,
# php-fpm, ...
unset LD_LIBRARY_PATH
unset LD_RUN_PATH
fi
if test -v TEST_INSTALL; then
make install
pushd $PREFIX
# Basic sanity tests of the installed server.
./bin/apachectl -V
test `./bin/apxs -q PREFIX` = $PREFIX
test `$PWD/bin/apxs -q PREFIX` = $PREFIX
./bin/apxs -g -n foobar
cd foobar; make
popd
fi
if test -v SKIP_TESTING; then
# Check that httpd was built successfully, nothing more.
./httpd -V
exit 0
fi
###############################################################
### Everything below is only run if SKIP_TESTING was not set ##
###############################################################
: Running tests...
set +e
RV=0
if test -v TEST_MALLOC; then
# Enable enhanced glibc malloc debugging, see mallopt(3)
export MALLOC_PERTURB_=65 MALLOC_CHECK_=3
export LIBC_FATAL_STDERR_=1
fi
if test -v TEST_UBSAN; then
export UBSAN_OPTIONS="log_path=$PWD/ubsan.log"
fi
if test -v TEST_ASAN; then
export ASAN_OPTIONS="log_path=$PWD/asan.log:detect_leaks=0"
fi
# Try to keep all potential coredumps from all processes
sudo sysctl -w kernel.core_uses_pid=1 2>/dev/null || true
# Systemd based systems might process core dumps via systemd-coredump.
# But we want to have local unprocessed files.
sudo sysctl -w kernel.core_pattern=core || true
ulimit -c unlimited 2>/dev/null || true
if ! test -v NO_TEST_FRAMEWORK; then
# 2.4.x has no libcheck-based unit tests.
if grep -q httpdunit Makefile.in; then
: Running libcheck-based unit tests.
if ! prove -v ./test/httpdunit; then
RV=1
fi
fi
if test -v WITH_TEST_SUITE -a $RV -eq 0; then
make check-test-framework TESTS="${TESTS}" TEST_CONFIG="${TEST_ARGS}" | tee test.log
RV=${PIPESTATUS[0]}
# re-run failing tests with -v, avoiding set -e
if [ $RV -ne 0 ]; then
# mv test/perl-framework/t/logs/error_log test/perl-framework/t/logs/error_log_save
FAILERS=""
while read FAILER; do
FAILERS="$FAILERS $FAILER"
done < <(awk '/Failed:/{print $1}' test.log)
if [ -n "$FAILERS" ]; then
make check-test-framework TESTS="-v $FAILERS" || true
fi
# set -e would have killed us after the original t/TEST
rm -f test.log
# mv test/perl-framework/t/logs/error_log_save test/perl-framework/t/logs/error_log
false
fi
else
test -v TEST_INSTALL || make install
pushd test/perl-framework
perl Makefile.PL -apxs $PREFIX/bin/apxs
make test APACHE_TEST_EXTRA_ARGS="${TEST_ARGS} ${TESTS}" | tee test.log
RV=${PIPESTATUS[0]}
# re-run failing tests with -v, avoiding set -e
if [ $RV -ne 0 ]; then
# mv t/logs/error_log t/logs/error_log_save
FAILERS=""
while read FAILER; do
FAILERS="$FAILERS $FAILER"
done < <(awk '/Failed:/{print $1}' test.log)
if [ -n "$FAILERS" ]; then
t/TEST -v $FAILERS || true
fi
# set -e would have killed us after the original t/TEST
rm -f test.log
# mv t/logs/error_log_save t/logs/error_log
false
fi
popd
fi
# Skip further testing if a core dump was created during the test
# suite run above.
if test $RV -eq 0 && test -n "`ls test/perl-framework/t/core{,.*} 2>/dev/null`"; then
RV=4
fi
fi
if test \( -v TEST_SSL -o -v TEST_OPENSSL3 \) \
-a -f test/perl-framework/t/logs/error_log; then
: -- Check OpenSSL version used by mod_ssl at compile- and run-time --
grep 'mod_ssl.*compiled against' test/perl-framework/t/logs/error_log | tail -n1 | grep --color=always 'OpenSSL/[^ ]*'
grep 'resuming normal operations' test/perl-framework/t/logs/error_log | tail -n1 | grep --color=always 'OpenSSL/[^ ]*'
fi
if test -v TEST_SSL -a $RV -eq 0; then
pushd test/perl-framework
# Test loading encrypted private keys
./t/TEST -defines "TEST_SSL_DES3_KEY TEST_SSL_PASSPHRASE_EXEC" t/ssl
RV=$?
# Test various session cache backends
for cache in shmcb redis:localhost:6379 memcache:localhost:11211; do
test $RV -eq 0 || break
SSL_SESSCACHE=$cache ./t/TEST -sslproto TLSv1.2 -defines TEST_SSL_SESSCACHE -start
./t/TEST t/ssl
RV=$?
if test $RV -eq 0; then
# TODO: only really useful in e.g. triggering
# server segfaults which are caught later, doesn't
# directly catch non-200 responses etc.
$builddir/support/ab -qd -n 4000 -c 20 -f TLS1.2 https://localhost:8532/
RV=$?
fi
./t/TEST -stop
SRV=$?
if test $RV -eq 0 -a $SRV -ne 0; then
RV=$SRV
fi
done
popd
fi
if test -v LITMUS -a $RV -eq 0; then
pushd test/perl-framework
mkdir -p t/htdocs/modules/dav
./t/TEST -start
# litmus uses $TESTS, so unset it.
unset TESTS
litmus http://localhost:8529/modules/dav/
RV=$?
./t/TEST -stop
popd
fi
if test $RV -ne 0 && test -f test/perl-framework/t/logs/error_log; then
grep -v ':\(debug\|trace[12345678]\)\]' test/perl-framework/t/logs/error_log
fi
if test -v TEST_PYTEST -a $RV -eq 0; then
# Run all available pytest-based test suites against this build, via
# the unified `make check-all-pytest` target: test/pytest_suite/ (the
# self-contained port of the classic Apache::Test suite, incl. PHP
# tests if PHP_FPM is set) and every test/modules/*/ suite (core,
# http1, http2, proxy, ssl, aaa, ...), in one pytest session. This
# replaces the old per-suite TEST_CORE / TEST_PROXY / TEST_H2 /
# TEST_MD flags, which each invoked py.test-3 directly against a
# `make install`ed tree; check-all-pytest instead builds and tests
# entirely from the in-tree check/ build, needing no install. This is
# the same on trunk and 2.4.x.
#
# Suites whose dependencies are missing skip themselves: modules/md
# without `pebble` on PATH (a job wanting md coverage must install
# pebble first, see README.ci), modules/http2 when mod_http2 wasn't
# built (e.g. the UBSan job's --disable-http2).
#
# A job can narrow this down with PYTEST_ARGS: test paths relative to
# test/ and any pytest options; see README.ci.
if test -v TEST_LDAP && ! test -v PYTEST_ARGS; then
# Only pytest_suite has LDAP coverage, and it needs the LDAP
# define to configure the mod_authnz_ldap vhosts. The other
# suites are covered by the pytest-specific jobs.
PYTEST_ARGS="--defines=LDAP pytest_suite/tests/t/modules/test_ldap.py"
fi
(cd test/clients && make)
make check-all-pytest PYTEST_ARGS="${PYTEST_ARGS:-}"
RV=$?
fi
# Catch cases where abort()s get logged to stderr by libraries but
# only cause child processes to terminate e.g. during shutdown,
# which may not otherwise trigger test failures.
# "glibc detected": printed with LIBC_FATAL_STDERR_/MALLOC_CHECK_
# glibc will abort when malloc errors are detected. This will get
# caught by the segfault grep as well.
# "pool concurrency check": printed by APR built with
# --enable-thread-debug when an APR pool concurrency check aborts
for phrase in 'Segmentation fault' 'glibc detected' 'pool concurrency check:' 'Assertion.*failed'; do
# Ignore IO/debug logs
if grep -v ':\(debug\|trace[12345678]\)\]' test/perl-framework/t/logs/error_log | grep -q "$phrase"; then
grep --color=always -C5 "$phrase" test/perl-framework/t/logs/error_log
RV=2
fi
done
if test -v TEST_UBSAN && test -n "`ls ubsan.log.* 2>/dev/null`"; then
cat ubsan.log.*
RV=3
fi
if test -v TEST_ASAN && test -n "`ls asan.log.* 2>/dev/null`"; then
cat asan.log.*
# ASan can report memory leaks, fail on errors only
if grep -q "ERROR: AddressSanitizer:" `ls asan.log.*`; then
RV=4
fi
fi
for core in `ls test/perl-framework/t/core{,.*} test/gen/apache/core{,.*} 2>/dev/null`; do
gdb -ex 'thread apply all backtrace full' -batch ./httpd "$core"
RV=5
done
exit $RV