mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 06:34:44 +00:00
tests: fix --valgrind-memleaks option
Previously, when a valgrind memleak was discovered, would cause a catastrophic pytest failure. Now correctly fails the current pytest as intended. As a result of this fix --valgrind-memleaks now works in distributed pytest mode as well. Signed-off-by: Christian Hopps <chopps@labn.net>
This commit is contained in:
parent
1f87861ecc
commit
a15e5ac082
@ -21,13 +21,6 @@ from lib.topolog import logger
|
|||||||
from lib.topotest import g_extra_config as topotest_extra_config
|
from lib.topotest import g_extra_config as topotest_extra_config
|
||||||
from lib.topotest import json_cmp_result
|
from lib.topotest import json_cmp_result
|
||||||
|
|
||||||
try:
|
|
||||||
from _pytest._code.code import ExceptionInfo
|
|
||||||
|
|
||||||
leak_check_ok = True
|
|
||||||
except ImportError:
|
|
||||||
leak_check_ok = False
|
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
"""
|
"""
|
||||||
@ -138,8 +131,7 @@ def pytest_addoption(parser):
|
|||||||
|
|
||||||
|
|
||||||
def check_for_memleaks():
|
def check_for_memleaks():
|
||||||
if not topotest_extra_config["valgrind_memleaks"]:
|
assert topotest_extra_config["valgrind_memleaks"]
|
||||||
return
|
|
||||||
|
|
||||||
leaks = []
|
leaks = []
|
||||||
tgen = get_topogen()
|
tgen = get_topogen()
|
||||||
@ -151,21 +143,25 @@ def check_for_memleaks():
|
|||||||
existing = tgen.valgrind_existing_files
|
existing = tgen.valgrind_existing_files
|
||||||
latest = glob.glob(os.path.join(logdir, "*.valgrind.*"))
|
latest = glob.glob(os.path.join(logdir, "*.valgrind.*"))
|
||||||
|
|
||||||
|
daemons = set()
|
||||||
for vfile in latest:
|
for vfile in latest:
|
||||||
if vfile in existing:
|
if vfile in existing:
|
||||||
continue
|
continue
|
||||||
with open(vfile) as vf:
|
existing.append(vfile)
|
||||||
|
with open(vfile, encoding="ascii") as vf:
|
||||||
vfcontent = vf.read()
|
vfcontent = vf.read()
|
||||||
match = re.search(r"ERROR SUMMARY: (\d+) errors", vfcontent)
|
match = re.search(r"ERROR SUMMARY: (\d+) errors", vfcontent)
|
||||||
if match and match.group(1) != "0":
|
if match and match.group(1) != "0":
|
||||||
emsg = "{} in {}".format(match.group(1), vfile)
|
emsg = "{} in {}".format(match.group(1), vfile)
|
||||||
leaks.append(emsg)
|
leaks.append(emsg)
|
||||||
|
daemons.add(re.match(r".*\.valgrind\.(.*)\.\d+", vfile).group(1))
|
||||||
|
|
||||||
|
if tgen is not None:
|
||||||
|
tgen.valgrind_existing_files = existing
|
||||||
|
|
||||||
if leaks:
|
if leaks:
|
||||||
if leak_check_ok:
|
logger.error("valgrind memleaks found:\n\t%s", "\n\t".join(leaks))
|
||||||
pytest.fail("Memleaks found:\n\t" + "\n\t".join(leaks))
|
pytest.fail("valgrind memleaks found for daemons: " + " ".join(daemons))
|
||||||
else:
|
|
||||||
logger.error("Memleaks found:\n\t" + "\n\t".join(leaks))
|
|
||||||
|
|
||||||
|
|
||||||
def pytest_runtest_logstart(nodeid, location):
|
def pytest_runtest_logstart(nodeid, location):
|
||||||
@ -178,18 +174,21 @@ def pytest_runtest_logfinish(nodeid, location):
|
|||||||
topolog.logfinish(nodeid, location)
|
topolog.logfinish(nodeid, location)
|
||||||
|
|
||||||
|
|
||||||
def pytest_runtest_call():
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
"""
|
def pytest_runtest_call(item: pytest.Item) -> None:
|
||||||
This function must be run after setup_module(), it does standarized post
|
"Hook the function that is called to execute the test."
|
||||||
setup routines. It is only being used for the 'topology-only' option.
|
|
||||||
"""
|
|
||||||
if topotest_extra_config["topology_only"]:
|
|
||||||
tgen = get_topogen()
|
|
||||||
if tgen is not None:
|
|
||||||
# Allow user to play with the setup.
|
|
||||||
tgen.cli()
|
|
||||||
|
|
||||||
pytest.exit("the topology executed successfully")
|
# For topology only run the CLI then exit
|
||||||
|
if topotest_extra_config["topology_only"]:
|
||||||
|
get_topogen().cli()
|
||||||
|
pytest.exit("exiting after --topology-only")
|
||||||
|
|
||||||
|
# Let the default pytest_runtest_call execute the test function
|
||||||
|
yield
|
||||||
|
|
||||||
|
# Check for leaks if requested
|
||||||
|
if topotest_extra_config["valgrind_memleaks"]:
|
||||||
|
check_for_memleaks()
|
||||||
|
|
||||||
|
|
||||||
def pytest_assertrepr_compare(op, left, right):
|
def pytest_assertrepr_compare(op, left, right):
|
||||||
@ -333,7 +332,10 @@ def pytest_configure(config):
|
|||||||
topotest_extra_config["pause"] = pause
|
topotest_extra_config["pause"] = pause
|
||||||
assert_feature_windows(pause, "--pause")
|
assert_feature_windows(pause, "--pause")
|
||||||
|
|
||||||
topotest_extra_config["topology_only"] = config.getoption("--topology-only")
|
topology_only = config.getoption("--topology-only")
|
||||||
|
if topology_only and is_xdist:
|
||||||
|
pytest.exit("Cannot use --topology-only with distributed test mode")
|
||||||
|
topotest_extra_config["topology_only"] = topology_only
|
||||||
|
|
||||||
# Check environment now that we have config
|
# Check environment now that we have config
|
||||||
if not diagnose_env(rundir):
|
if not diagnose_env(rundir):
|
||||||
@ -373,12 +375,6 @@ def pytest_runtest_makereport(item, call):
|
|||||||
else:
|
else:
|
||||||
pause = False
|
pause = False
|
||||||
|
|
||||||
if call.excinfo is None and call.when == "call":
|
|
||||||
try:
|
|
||||||
check_for_memleaks()
|
|
||||||
except:
|
|
||||||
call.excinfo = ExceptionInfo()
|
|
||||||
|
|
||||||
title = "unset"
|
title = "unset"
|
||||||
|
|
||||||
if call.excinfo is None:
|
if call.excinfo is None:
|
||||||
|
Loading…
Reference in New Issue
Block a user