Add pytest fixture for checking test artifacts

Prior to introducing the pytest runner, clean.sh files were used as a
list of files that the test is expected to leave around as artifacts and
check that no extra files were created.

With the pytest runner, those scripts are no longer used, but the
ability to detect extraneous files is still useful. Add a new
"extra_artifacts" mark which can be used for the same purpose.

(cherry picked from commit 3a9f4edddc)
This commit is contained in:
Michał Kępień 2024-08-19 18:49:08 +02:00 committed by Nicki Křížek
parent ee91ba9dd3
commit 95d3bbd5dc
2 changed files with 66 additions and 1 deletions

View file

@ -10,6 +10,7 @@
# information regarding copyright ownership.
from functools import partial
import filecmp
import os
from pathlib import Path
import re
@ -297,7 +298,28 @@ def logger(request, system_test_name):
@pytest.fixture(scope="module")
def system_test_dir(request, system_test_name):
def expected_artifacts(request):
common_artifacts = [
"ns*/named.run",
"ns*/named.run.prev",
"ns*/named.conf",
"ns*/named.memstats",
"pytest.log.txt",
]
try:
test_specific_artifacts = request.node.get_closest_marker("extra_artifacts")
except AttributeError:
return None
if test_specific_artifacts:
return common_artifacts + test_specific_artifacts.args[0]
return common_artifacts
@pytest.fixture(scope="module")
def system_test_dir(request, system_test_name, expected_artifacts):
"""
Temporary directory for executing the test.
@ -345,6 +367,45 @@ def system_test_dir(request, system_test_name):
except FileNotFoundError:
pass
def check_artifacts(source_dir, run_dir):
def check_artifacts_recursive(dcmp):
def artifact_expected(path, expected):
for glob in expected:
if path.match(glob):
return True
return False
# test must not remove any Git-tracked file, ignore libtool and gcov artifacts
for name in dcmp.left_only:
assert name.startswith("lt-") or name.endswith(".gcda")
for name in dcmp.diff_files:
# There should be no diff_files. However, due to how the
# obsolete dnsrps tests are launched, this workaround is
# required to ignore the dnsrps-dnsrps.gcda file which may
# get detected here as git-tracked in some circumstances
assert name.endswith(
".gcda"
), "test must not modify any Git-tracked file"
dir_path = Path(dcmp.left).relative_to(source_dir)
for name in dcmp.right_only:
file = dir_path / Path(name)
if not artifact_expected(file, expected_artifacts):
unexpected_files.append(str(file))
for subdir in dcmp.subdirs.values():
check_artifacts_recursive(subdir)
if expected_artifacts is None: # skip the check if artifact list is unavailable
return
unexpected_files = []
dcmp = filecmp.dircmp(source_dir, run_dir)
check_artifacts_recursive(dcmp)
assert (
not unexpected_files
), f"Unexpected files found in test directory: {unexpected_files}"
# Create a temporary directory with a copy of the original system test dir contents
system_test_root = Path(os.environ["builddir"])
testdir = Path(
@ -374,6 +435,9 @@ def system_test_dir(request, system_test_name):
result = get_test_result()
if result == "passed":
check_artifacts(system_test_root / system_test_name, testdir)
# Clean temporary dir unless it should be kept
keep = False
if request.config.getoption("--noclean"):

View file

@ -21,3 +21,4 @@ junit_log_passing_tests = 0
markers =
requires_zones_loaded: ensures the test does not start until the specified named instances load all configured zones
algorithm_set: use to select desired algorithms from isctest/vars/algorithms.py
extra_artifacts: list of files (globs) that are expected to appear in the test directory after the test is run