blob: c89b3c73ff29d9447f8e0bfd682aa482d1419079 [file]
This directory contains useful test code for testing various bits
of Apache functionality. This stuff is for the developers only,
so we might remove it on public releases.
Python / pytest test suites
===========================
There are two complementary Python (pytest) test suites in this directory,
run as one pytest project against an already-built httpd.
pyhttpd / modules/ httpd's own test framework. Covers HTTP/2, mod_md
(ACME), HTTP/1, proxy and core behaviour. Drives the
server with external clients (curl, nghttp, h2load);
each test package writes the configuration it needs and
restarts the server. Framework code lives in pyhttpd/;
tests live in modules/{core,http1,http2,md,proxy,...}/.
pytest_suite/ A self-contained port of the classic Perl Apache::Test
suite (core HTTP, per-module tests, security/CVE
regressions, SSL/TLS, PHP). One server with a static
configuration, driven by an in-process Python HTTP
client (httpx) and raw sockets. It ships its own conf
templates, document root and C test modules under
pytest_suite/. See pytest_suite/README.md for details,
including how to add new tests.
Both use the same framework underneath (pyhttpd/: finding and probing the
build, marker-based skipping, starting and stopping httpd, ports, test
certificates, C test modules). The framework in pytest_suite/apache_pytest/
is a thin layer over it, so that the classic test files stay identical to
their upstream copy in the httpd-tests repository.
One project, one environment: test/pyproject.toml holds the dependencies and
the pytest configuration, test/uv.lock pins the versions, and test/.venv is
the virtualenv.
Running the tests: runtests.sh
-------------------------------
runtests.sh (runtests.bat on Windows) creates or updates the venv, finds apxs
and php-fpm, and runs pytest from this directory. It can be invoked from any
directory. Without a path it runs both suites.
./runtests.sh # both suites
./runtests.sh modules # only the modules/ suites
./runtests.sh pytest_suite/tests # only the classic suite
./runtests.sh modules/http2 -k 003 -v # a subset; any pytest option passes through
./runtests.sh --apxs=/path/to/apxs # a specific httpd build
./runtests.sh tests/t/php --php-fpm=/path/to/php-fpm
Paths are relative to this directory; a path relative to pytest_suite/
(tests/t/php) is accepted as well. ./run-one-test.sh PATH[::nodeid] re-runs a
single test from a path as printed in a test run, and lists all tests when
called without arguments.
The venv is (re)built automatically when it is missing or pyproject.toml or
uv.lock has changed, with `uv sync`; uv (https://docs.astral.sh/uv/) is required. To force
a clean rebuild, `rm -rf test/.venv`. You can also run
`.venv/bin/pytest --apxs=/path/to/apxs` yourself from test/.
How the httpd build is found: from --apxs (or $APXS); else from --httpd with
--conf (or $HTTPD); else from the config.ini that httpd's configure generates
in pyhttpd/ (or $PYHTTPD_CONFIG); runtests.sh only falls back to an apxs on
$PATH without that. It is found once, before the tests are collected, and
both suites, and every skip and expected failure, use that one build; a
build named with --apxs or --httpd that is not usable stops the run. The
modules/ suites
need curl and, for HTTP/2, nghttp2 and h2load; modules/md needs an ACME test
server (pebble) and skips without it. A suite whose optional dependency is
missing skips (and fails under --strict-optional).
Ports: the modules/ suites listen on free ports picked for each test
environment. --fixed-ports uses the ports of config.ini (5001 ...) instead,
--base-port N uses N to N+4.
Error log: the modules/ suites fail a test that makes httpd log an unexpected
error or warning. The classic suite does the same; what it expects is listed
in pyhttpd/classic_errorlog.py (--classic-elog-report=FILE lists what each
test caused instead of failing).
The C modules the tests load (mod_aptest, mod_h1test, mod_h2test, the
c-modules/ of pytest_suite) are built with apxs, once: next to each .so a
.stamp records the sources, defines and the httpd it was built for, and a
module is rebuilt when one of them changes, e.g. when you point --apxs at
another build. --clean-modules removes all of them first.
From a build tree, `make check-all-pytest` builds the check/ tree and runs the
same thing; pass paths and options as PYTEST_ARGS, for example
`make check-all-pytest PYTEST_ARGS=modules/http2`.
Other contents
--------------
unit/ C-based unit tests (libcheck / httpdunit).
clients/ helper client programs used by the tests.
*.c small standalone C test programs.