mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-03 12:44:33 +02:00
ci: ci_build_apps.py supports filter_expr
This commit is contained in:
@@ -23,10 +23,11 @@ def get_pytest_apps(
|
|||||||
target: str,
|
target: str,
|
||||||
config_rules_str: List[str],
|
config_rules_str: List[str],
|
||||||
marker_expr: str,
|
marker_expr: str,
|
||||||
|
filter_expr: str,
|
||||||
preserve_all: bool = False,
|
preserve_all: bool = False,
|
||||||
extra_default_build_targets: Optional[List[str]] = None,
|
extra_default_build_targets: Optional[List[str]] = None,
|
||||||
) -> List[App]:
|
) -> List[App]:
|
||||||
pytest_cases = get_pytest_cases(paths, target, marker_expr)
|
pytest_cases = get_pytest_cases(paths, target, marker_expr, filter_expr)
|
||||||
|
|
||||||
_paths: Set[str] = set()
|
_paths: Set[str] = set()
|
||||||
test_related_app_configs = defaultdict(set)
|
test_related_app_configs = defaultdict(set)
|
||||||
@@ -126,6 +127,7 @@ def main(args: argparse.Namespace) -> None:
|
|||||||
args.target,
|
args.target,
|
||||||
args.config,
|
args.config,
|
||||||
args.marker_expr,
|
args.marker_expr,
|
||||||
|
args.filter_expr,
|
||||||
args.preserve_all,
|
args.preserve_all,
|
||||||
extra_default_build_targets,
|
extra_default_build_targets,
|
||||||
)
|
)
|
||||||
@@ -181,8 +183,8 @@ if __name__ == '__main__':
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-t',
|
'-t',
|
||||||
'--target',
|
'--target',
|
||||||
required=True,
|
default='all',
|
||||||
help='Build apps for given target. could pass "all" to get apps for all targets',
|
help='Build apps for given target',
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--config',
|
'--config',
|
||||||
@@ -263,6 +265,12 @@ if __name__ == '__main__':
|
|||||||
help='only build tests matching given mark expression. For example: -m "host_test and generic". Works only'
|
help='only build tests matching given mark expression. For example: -m "host_test and generic". Works only'
|
||||||
'for pytest',
|
'for pytest',
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-k',
|
||||||
|
'--filter-expr',
|
||||||
|
help='only build tests matching given filter expression. For example: -k "test_hello_world". Works only'
|
||||||
|
'for pytest',
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--default-build-test-rules',
|
'--default-build-test-rules',
|
||||||
default=os.path.join(IDF_PATH, '.gitlab', 'ci', 'default-build-test-rules.yml'),
|
default=os.path.join(IDF_PATH, '.gitlab', 'ci', 'default-build-test-rules.yml'),
|
||||||
|
@@ -24,9 +24,7 @@ except ImportError:
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from _pytest.python import Function
|
from _pytest.python import Function
|
||||||
|
|
||||||
IDF_PATH = os.path.abspath(
|
IDF_PATH = os.path.abspath(os.getenv('IDF_PATH', os.path.join(os.path.dirname(__file__), '..', '..')))
|
||||||
os.getenv('IDF_PATH', os.path.join(os.path.dirname(__file__), '..', '..'))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_submodule_dirs(full_path: bool = False) -> List:
|
def get_submodule_dirs(full_path: bool = False) -> List:
|
||||||
@@ -66,11 +64,7 @@ def get_submodule_dirs(full_path: bool = False) -> List:
|
|||||||
|
|
||||||
def _check_git_filemode(full_path): # type: (str) -> bool
|
def _check_git_filemode(full_path): # type: (str) -> bool
|
||||||
try:
|
try:
|
||||||
stdout = (
|
stdout = subprocess.check_output(['git', 'ls-files', '--stage', full_path]).strip().decode('utf-8')
|
||||||
subprocess.check_output(['git', 'ls-files', '--stage', full_path])
|
|
||||||
.strip()
|
|
||||||
.decode('utf-8')
|
|
||||||
)
|
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -150,6 +144,7 @@ class PytestCase:
|
|||||||
path: str
|
path: str
|
||||||
name: str
|
name: str
|
||||||
apps: Set[PytestApp]
|
apps: Set[PytestApp]
|
||||||
|
|
||||||
nightly_run: bool
|
nightly_run: bool
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
def __hash__(self) -> int:
|
||||||
@@ -185,14 +180,8 @@ class PytestCollectPlugin:
|
|||||||
self.get_param(item, 'app_path', os.path.dirname(case_path)),
|
self.get_param(item, 'app_path', os.path.dirname(case_path)),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
configs = to_list(
|
configs = to_list(parse_multi_dut_args(count, self.get_param(item, 'config', 'default')))
|
||||||
parse_multi_dut_args(
|
targets = to_list(parse_multi_dut_args(count, self.get_param(item, 'target', target)))
|
||||||
count, self.get_param(item, 'config', 'default')
|
|
||||||
)
|
|
||||||
)
|
|
||||||
targets = to_list(
|
|
||||||
parse_multi_dut_args(count, self.get_param(item, 'target', target))
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
app_paths = [os.path.dirname(case_path)]
|
app_paths = [os.path.dirname(case_path)]
|
||||||
configs = ['default']
|
configs = ['default']
|
||||||
@@ -213,7 +202,10 @@ class PytestCollectPlugin:
|
|||||||
|
|
||||||
|
|
||||||
def get_pytest_cases(
|
def get_pytest_cases(
|
||||||
paths: Union[str, List[str]], target: str = 'all', marker_expr: Optional[str] = None
|
paths: Union[str, List[str]],
|
||||||
|
target: str = 'all',
|
||||||
|
marker_expr: Optional[str] = None,
|
||||||
|
filter_expr: Optional[str] = None,
|
||||||
) -> List[PytestCase]:
|
) -> List[PytestCase]:
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
@@ -250,17 +242,15 @@ def get_pytest_cases(
|
|||||||
with io.StringIO() as buf:
|
with io.StringIO() as buf:
|
||||||
with redirect_stdout(buf):
|
with redirect_stdout(buf):
|
||||||
cmd = ['--collect-only', path, '-q', '-m', _marker_expr]
|
cmd = ['--collect-only', path, '-q', '-m', _marker_expr]
|
||||||
|
if filter_expr:
|
||||||
|
cmd.extend(['-k', filter_expr])
|
||||||
res = pytest.main(cmd, plugins=[collector])
|
res = pytest.main(cmd, plugins=[collector])
|
||||||
if res.value != ExitCode.OK:
|
if res.value != ExitCode.OK:
|
||||||
if res.value == ExitCode.NO_TESTS_COLLECTED:
|
if res.value == ExitCode.NO_TESTS_COLLECTED:
|
||||||
print(
|
print(f'WARNING: no pytest app found for target {t} under path {path}')
|
||||||
f'WARNING: no pytest app found for target {t} under path {path}'
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(buf.getvalue())
|
print(buf.getvalue())
|
||||||
raise RuntimeError(
|
raise RuntimeError(f'pytest collection failed at {path} with command \"{" ".join(cmd)}\"')
|
||||||
f'pytest collection failed at {path} with command \"{" ".join(cmd)}\"'
|
|
||||||
)
|
|
||||||
|
|
||||||
cases.extend(collector.cases)
|
cases.extend(collector.cases)
|
||||||
|
|
||||||
@@ -296,9 +286,7 @@ def get_ttfw_cases(paths: Union[str, List[str]]) -> List[Any]:
|
|||||||
|
|
||||||
cases = []
|
cases = []
|
||||||
for path in to_list(paths):
|
for path in to_list(paths):
|
||||||
assign = IDFAssignTest(
|
assign = IDFAssignTest(path, os.path.join(IDF_PATH, '.gitlab', 'ci', 'target-test.yml'))
|
||||||
path, os.path.join(IDF_PATH, '.gitlab', 'ci', 'target-test.yml')
|
|
||||||
)
|
|
||||||
with contextlib.redirect_stdout(None): # swallow stdout
|
with contextlib.redirect_stdout(None): # swallow stdout
|
||||||
try:
|
try:
|
||||||
cases += assign.search_cases()
|
cases += assign.search_cases()
|
||||||
@@ -308,9 +296,7 @@ def get_ttfw_cases(paths: Union[str, List[str]]) -> List[Any]:
|
|||||||
return cases
|
return cases
|
||||||
|
|
||||||
|
|
||||||
def get_ttfw_app_paths(
|
def get_ttfw_app_paths(paths: Union[str, List[str]], target: Optional[str] = None) -> Set[str]:
|
||||||
paths: Union[str, List[str]], target: Optional[str] = None
|
|
||||||
) -> Set[str]:
|
|
||||||
"""
|
"""
|
||||||
Get the app paths from ttfw_idf under the given paths
|
Get the app paths from ttfw_idf under the given paths
|
||||||
"""
|
"""
|
||||||
|
Reference in New Issue
Block a user