Tests: print_log_on_assert() decorator introduced.

This commit is contained in:
Andrei Zeliankou 2021-07-06 12:22:10 +01:00
parent bc84992075
commit 4f94df6a71

View file

@ -74,7 +74,7 @@ def pytest_addoption(parser):
unit_instance = {}
_processes = []
_fds_check = {
_fds_info = {
'main': {'fds': 0, 'skip': False},
'router': {'name': 'unit: router', 'pid': -1, 'fds': 0, 'skip': False},
'controller': {
@ -115,6 +115,17 @@ def pytest_configure(config):
fcntl.fcntl(sys.stdout.fileno(), fcntl.F_SETFL, 0)
def print_log_on_assert(func):
def inner_function(*args, **kwargs):
try:
func(*args, **kwargs)
except AssertionError as e:
_print_log(kwargs.get('log', None))
raise e
return inner_function
def pytest_generate_tests(metafunc):
cls = metafunc.cls
if (
@ -275,9 +286,9 @@ def run(request):
]
option.skip_sanitizer = False
_fds_check['main']['skip'] = False
_fds_check['router']['skip'] = False
_fds_check['controller']['skip'] = False
_fds_info['main']['skip'] = False
_fds_info['router']['skip'] = False
_fds_info['controller']['skip'] = False
yield
@ -299,7 +310,7 @@ def run(request):
# clean temp_dir before the next test
if not option.restart:
_clear_conf(unit['temp_dir'] + '/control.unit.sock', log)
_clear_conf(unit['temp_dir'] + '/control.unit.sock', log=log)
for item in os.listdir(unit['temp_dir']):
if item not in [
@ -319,51 +330,9 @@ def run(request):
else:
shutil.rmtree(path)
# check descriptors (wait for some time before check)
# check descriptors
def waitforfds(diff):
for i in range(600):
fds_diff = diff()
if fds_diff <= option.fds_threshold:
break
time.sleep(0.1)
return fds_diff
ps = _fds_check['main']
if not ps['skip']:
fds_diff = waitforfds(
lambda: _count_fds(unit_instance['pid']) - ps['fds']
)
ps['fds'] += fds_diff
assert (
fds_diff <= option.fds_threshold
), 'descriptors leak main process'
else:
ps['fds'] = _count_fds(unit_instance['pid'])
for name in ['controller', 'router']:
ps = _fds_check[name]
ps_pid = ps['pid']
ps['pid'] = pid_by_name(ps['name'])
if not ps['skip']:
fds_diff = waitforfds(lambda: _count_fds(ps['pid']) - ps['fds'])
ps['fds'] += fds_diff
if not option.restart:
assert ps['pid'] == ps_pid, 'same pid %s' % name
assert fds_diff <= option.fds_threshold, (
'descriptors leak %s' % name
)
else:
ps['fds'] = _count_fds(ps['pid'])
_check_fds(log=log)
# print unit.log in case of error
@ -440,13 +409,13 @@ def unit_run():
_clear_conf(unit_instance['temp_dir'] + '/control.unit.sock')
_fds_check['main']['fds'] = _count_fds(unit_instance['pid'])
_fds_info['main']['fds'] = _count_fds(unit_instance['pid'])
router = _fds_check['router']
router = _fds_info['router']
router['pid'] = pid_by_name(router['name'])
router['fds'] = _count_fds(router['pid'])
controller = _fds_check['controller']
controller = _fds_info['controller']
controller['pid'] = pid_by_name(controller['name'])
controller['fds'] = _count_fds(controller['pid'])
@ -481,7 +450,8 @@ def unit_stop():
return 'Could not terminate unit'
def _check_alerts(log=None):
@print_log_on_assert
def _check_alerts(*, log=None):
if log is None:
with Log.open(encoding='utf-8') as f:
log = f.read()
@ -499,22 +469,18 @@ def _check_alerts(log=None):
for skip in option.skip_alerts:
alerts = [al for al in alerts if re.search(skip, al) is None]
if alerts:
_print_log(log)
assert not alerts, 'alert(s)'
assert not alerts, 'alert(s)'
if not option.skip_sanitizer:
sanitizer_errors = re.findall('.+Sanitizer.+', log)
if sanitizer_errors:
_print_log(log)
assert not sanitizer_errors, 'sanitizer error(s)'
assert not sanitizer_errors, 'sanitizer error(s)'
if found:
print('skipped.')
def _print_log(data=None):
def _print_log(log):
path = Log.get_path()
print('Path to unit.log:\n' + path + '\n')
@ -523,19 +489,15 @@ def _print_log(data=None):
os.set_blocking(sys.stdout.fileno(), True)
sys.stdout.flush()
if data is None:
if log is None:
with open(path, 'r', encoding='utf-8', errors='ignore') as f:
shutil.copyfileobj(f, sys.stdout)
else:
sys.stdout.write(data)
sys.stdout.write(log)
def _clear_conf(sock, log=None):
def check_success(resp):
if 'success' not in resp:
_print_log(log)
assert 'success' in resp
@print_log_on_assert
def _clear_conf(sock, *, log=None):
resp = http.put(
url='/config',
sock_type='unix',
@ -543,7 +505,7 @@ def _clear_conf(sock, log=None):
body=json.dumps({"listeners": {}, "applications": {}}),
)['body']
check_success(resp)
assert 'success' in resp, 'clear conf'
if 'openssl' not in option.available['modules']:
return
@ -561,7 +523,54 @@ def _clear_conf(sock, log=None):
url='/certificates/' + cert, sock_type='unix', addr=sock,
)['body']
check_success(resp)
assert 'success' in resp, 'remove certificate'
@print_log_on_assert
def _check_fds(*, log=None):
def waitforfds(diff):
for i in range(600):
fds_diff = diff()
if fds_diff <= option.fds_threshold:
break
time.sleep(0.1)
return fds_diff
ps = _fds_info['main']
if not ps['skip']:
fds_diff = waitforfds(
lambda: _count_fds(unit_instance['pid']) - ps['fds']
)
ps['fds'] += fds_diff
assert (
fds_diff <= option.fds_threshold
), 'descriptors leak main process'
else:
ps['fds'] = _count_fds(unit_instance['pid'])
for name in ['controller', 'router']:
ps = _fds_info[name]
ps_pid = ps['pid']
ps['pid'] = pid_by_name(ps['name'])
if not ps['skip']:
fds_diff = waitforfds(lambda: _count_fds(ps['pid']) - ps['fds'])
ps['fds'] += fds_diff
if not option.restart:
assert ps['pid'] == ps_pid, 'same pid %s' % name
assert fds_diff <= option.fds_threshold, (
'descriptors leak %s' % name
)
else:
ps['fds'] = _count_fds(ps['pid'])
def _count_fds(pid):
@ -639,9 +648,9 @@ def skip_alert():
@pytest.fixture()
def skip_fds_check():
def _skip(main=False, router=False, controller=False):
_fds_check['main']['skip'] = main
_fds_check['router']['skip'] = router
_fds_check['controller']['skip'] = controller
_fds_info['main']['skip'] = main
_fds_info['router']['skip'] = router
_fds_info['controller']['skip'] = controller
return _skip