forked from espressif/esp-idf
ci: add log_performance
and check_performance
as fixtures in pytest
This commit is contained in:
118
conftest.py
118
conftest.py
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -219,27 +220,6 @@ def session_tempdir() -> str:
|
|||||||
return _tmpdir
|
return _tmpdir
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
|
||||||
def log_minimum_free_heap_size(dut: IdfDut, config: str) -> Callable[..., None]:
|
|
||||||
def real_func() -> None:
|
|
||||||
res = dut.expect(r'Minimum free heap size: (\d+) bytes')
|
|
||||||
logging.info(
|
|
||||||
'\n------ heap size info ------\n'
|
|
||||||
'[app_name] {}\n'
|
|
||||||
'[config_name] {}\n'
|
|
||||||
'[target] {}\n'
|
|
||||||
'[minimum_free_heap_size] {} Bytes\n'
|
|
||||||
'------ heap size end ------'.format(
|
|
||||||
os.path.basename(dut.app.app_path),
|
|
||||||
config,
|
|
||||||
dut.target,
|
|
||||||
res.group(1).decode('utf8'),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return real_func
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def case_tester(dut: IdfDut, **kwargs): # type: ignore
|
def case_tester(dut: IdfDut, **kwargs): # type: ignore
|
||||||
yield CaseTester(dut, **kwargs)
|
yield CaseTester(dut, **kwargs)
|
||||||
@@ -313,6 +293,102 @@ def junit_properties(test_case_name: str, record_xml_attribute: Callable[[str, o
|
|||||||
record_xml_attribute('name', test_case_name)
|
record_xml_attribute('name', test_case_name)
|
||||||
|
|
||||||
|
|
||||||
|
######################
|
||||||
|
# Log Util Functions #
|
||||||
|
######################
|
||||||
|
@pytest.fixture
|
||||||
|
def log_performance(record_property: Callable[[str, object], None]) -> Callable[[str, str], None]:
|
||||||
|
"""
|
||||||
|
log performance item with pre-defined format to the console
|
||||||
|
and record it under the ``properties`` tag in the junit report if available.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def real_func(item: str, value: str) -> None:
|
||||||
|
"""
|
||||||
|
:param item: performance item name
|
||||||
|
:param value: performance value
|
||||||
|
"""
|
||||||
|
logging.info('[Performance][%s]: %s', item, value)
|
||||||
|
record_property(item, value)
|
||||||
|
|
||||||
|
return real_func
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def check_performance(idf_path: str) -> Callable[[str, float, str], None]:
|
||||||
|
"""
|
||||||
|
check if the given performance item meets the passing standard or not
|
||||||
|
"""
|
||||||
|
|
||||||
|
def real_func(item: str, value: float, target: str) -> None:
|
||||||
|
"""
|
||||||
|
:param item: performance item name
|
||||||
|
:param value: performance item value
|
||||||
|
:param target: target chip
|
||||||
|
:raise: AssertionError: if check fails
|
||||||
|
"""
|
||||||
|
def _find_perf_item(operator: str, path: str) -> float:
|
||||||
|
with open(path, 'r') as f:
|
||||||
|
data = f.read()
|
||||||
|
match = re.search(r'#define\s+IDF_PERFORMANCE_{}_{}\s+([\d.]+)'.format(operator, item.upper()), data)
|
||||||
|
return float(match.group(1)) # type: ignore
|
||||||
|
|
||||||
|
def _check_perf(operator: str, standard_value: float) -> None:
|
||||||
|
if operator == 'MAX':
|
||||||
|
ret = value <= standard_value
|
||||||
|
else:
|
||||||
|
ret = value >= standard_value
|
||||||
|
if not ret:
|
||||||
|
raise AssertionError(
|
||||||
|
"[Performance] {} value is {}, doesn't meet pass standard {}".format(item, value, standard_value)
|
||||||
|
)
|
||||||
|
|
||||||
|
path_prefix = os.path.join(idf_path, 'components', 'idf_test', 'include')
|
||||||
|
performance_files = (
|
||||||
|
os.path.join(path_prefix, target, 'idf_performance_target.h'),
|
||||||
|
os.path.join(path_prefix, 'idf_performance.h'),
|
||||||
|
)
|
||||||
|
|
||||||
|
found_item = False
|
||||||
|
for op in ['MIN', 'MAX']:
|
||||||
|
for performance_file in performance_files:
|
||||||
|
try:
|
||||||
|
standard = _find_perf_item(op, performance_file)
|
||||||
|
except (IOError, AttributeError):
|
||||||
|
# performance file doesn't exist or match is not found in it
|
||||||
|
continue
|
||||||
|
|
||||||
|
_check_perf(op, standard)
|
||||||
|
found_item = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not found_item:
|
||||||
|
raise AssertionError('Failed to get performance standard for {}'.format(item))
|
||||||
|
|
||||||
|
return real_func
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def log_minimum_free_heap_size(dut: IdfDut, config: str) -> Callable[..., None]:
|
||||||
|
def real_func() -> None:
|
||||||
|
res = dut.expect(r'Minimum free heap size: (\d+) bytes')
|
||||||
|
logging.info(
|
||||||
|
'\n------ heap size info ------\n'
|
||||||
|
'[app_name] {}\n'
|
||||||
|
'[config_name] {}\n'
|
||||||
|
'[target] {}\n'
|
||||||
|
'[minimum_free_heap_size] {} Bytes\n'
|
||||||
|
'------ heap size end ------'.format(
|
||||||
|
os.path.basename(dut.app.app_path),
|
||||||
|
config,
|
||||||
|
dut.target,
|
||||||
|
res.group(1).decode('utf8'),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return real_func
|
||||||
|
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Hook functions #
|
# Hook functions #
|
||||||
##################
|
##################
|
||||||
|
Reference in New Issue
Block a user