Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions test/README.pytest
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,42 @@ also raises the error log level of the tested modules.
> pytest -vvv -k test_h2_004_01
run the specific test with mod_http2 at log level TRACE2.

There is an option to archive the results across different
modules and httpd versions. The archiving will preserve
error_log.log, access_log.log, and all config files (*.conf)
from that pytest run. The following command will store the files
inside of '/path/to/archive/${HTTPD_VERSION}/modules/core'.
> pytest -k test_core --archive=/path/to/archive/

To archive the entire /test/gen/ directory (logs, confs, certs, htdocs, etc.)
use --archive-all instead:
> pytest -k test_core --archive-all=/path/to/archive/

If you don't provide any specific module, pytest will execute all of them
and the already archived folders and files will be replaced by the new ones.
> pytest --archive=/path/to/archive

Always use --archive=<path> or --archive-all=<path>
(with =, not a space) to avoid pytest rootdir issues.

Using the --archive OR --archive-all option having installed a different httpd version
will preserve any results from previous executions so you would
end up with a different folder structure for each httpd version.
You can also archive the results of different modules and that will
work incrementally, which means it will add a new folder per module to the structure.

The following structure shows the archived results from 3 different httpd versions:
├── /path/to/archive
│ ├── 2.4.65
│ │ ├── core
│ │ ├── http1
│ │ ├── http2
│ ├── 2.4.66
│ │ └── core
│ └── 2.5.1
│ └── http2


By default, test cases will configure httpd with mpm_event. You
can change that with the invocation:
> MPM=worker pytest test/modules/http2
Expand Down
16 changes: 15 additions & 1 deletion test/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys
import os
import warnings

import pytest

Expand All @@ -15,6 +16,10 @@ def pytest_addoption(parser):
parser.addoption("--repeat", action="store", type=int, default=1,
help='Number of times to repeat each test')
parser.addoption("--all", action="store_true")
parser.addoption("--archive", action="store", default=None,
help='Archive logs and configs after each test package to the specified folder')
parser.addoption("--archive-all", action="store", default=None,
help='Archive the entire gen/ directory after each test package to the specified folder')


def pytest_generate_tests(metafunc):
Expand All @@ -39,9 +44,18 @@ def _module_scope(env):


@pytest.fixture(autouse=True, scope="package")
def _package_scope(env):
def _package_scope(env, request):
env.httpd_error_log.clear_ignored_matches()
env.httpd_error_log.clear_ignored_lognos()
yield
assert env.apache_stop() == 0
env.check_error_log()
archive_all_dir = request.config.getoption("--archive-all")
archive_dir = archive_all_dir or request.config.getoption("--archive")
if archive_dir == "":
warnings.warn("--archive/--archive-all option was empty, skipping archiving")
if archive_dir:
fspath = str(request.fspath)
parts = fspath.split('modules/')
package_name = parts[1].split('/')[0]
env.archive_logs(package_name, archive_dir, copy_all=bool(archive_all_dir))
17 changes: 17 additions & 0 deletions test/pyhttpd/env.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import glob
import importlib
import inspect
import logging
Expand Down Expand Up @@ -341,6 +342,22 @@ def check_error_log(self):
f"apache logged {len(errors)} errors and {len(warnings)} warnings: \n"\
"{0}\n{1}\n".format("\n".join(errors), "\n".join(warnings))

def archive_logs(self, package_name, archive_dir, copy_all=False):
version = self.get_httpd_version()
dest = os.path.join(archive_dir, version, package_name)
if os.path.isdir(dest):
shutil.rmtree(dest)
if copy_all:
shutil.copytree(self._gen_dir, dest)
else:
os.makedirs(dest)
for log_file in ['error_log', 'access_log']:
log_fpath = os.path.join(self._server_logs_dir, log_file)
if os.path.isfile(log_fpath) and os.path.getsize(log_fpath) > 0:
shutil.copy(log_fpath, os.path.join(dest, f"{log_file}.log"))
for conf_file in glob.glob(os.path.join(self._server_conf_dir, '*.conf')):
shutil.copy(conf_file, os.path.join(dest, os.path.basename(conf_file)))

@property
def curl(self) -> str:
return self._curl
Expand Down