diff --git a/tools/test_build_system/test_components.py b/tools/test_build_system/test_components.py index 1cbff9706f..5f13f2a80a 100644 --- a/tools/test_build_system/test_components.py +++ b/tools/test_build_system/test_components.py @@ -1,16 +1,16 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import json import logging import os import shutil +from collections.abc import Generator from pathlib import Path -from typing import Generator import pytest -from test_build_system_helpers import append_to_file from test_build_system_helpers import EnvDict from test_build_system_helpers import IdfPyFunc +from test_build_system_helpers import append_to_file from test_build_system_helpers import replace_in_file @@ -42,8 +42,11 @@ def create_idf_components(request: pytest.FixtureRequest) -> Generator: def test_component_extra_dirs(idf_py: IdfPyFunc, test_app_copy: Path) -> None: logging.info('Setting EXTRA_COMPONENT_DIRS works') shutil.move(test_app_copy / 'main', test_app_copy / 'different_main' / 'main') - replace_in_file((test_app_copy / 'CMakeLists.txt'), '# placeholder_before_include_project_cmake', - 'set(EXTRA_COMPONENT_DIRS {})'.format(Path('different_main', 'main').as_posix())) + replace_in_file( + (test_app_copy / 'CMakeLists.txt'), + '# placeholder_before_include_project_cmake', + 'set(EXTRA_COMPONENT_DIRS {})'.format(Path('different_main', 'main').as_posix()), + ) ret = idf_py('reconfigure') assert str((test_app_copy / 'different_main' / 'main').as_posix()) in ret.stdout assert str((test_app_copy / 'main').as_posix()) not in ret.stdout @@ -64,10 +67,10 @@ def test_component_names_contain_spaces(idf_py: IdfPyFunc, test_app_copy: Path) def test_component_can_not_be_empty_dir(idf_py: IdfPyFunc, test_app_copy: Path) -> None: logging.info('Empty directory not treated as a component') - empty_component_dir = (test_app_copy / 'components' / 'esp32') + empty_component_dir = test_app_copy / 'components' / 'esp32' empty_component_dir.mkdir(parents=True) idf_py('reconfigure') - data = json.load(open(test_app_copy / 'build' / 'project_description.json', 'r')) + data = json.load(open(test_app_copy / 'build' / 'project_description.json')) assert str(empty_component_dir) not in data.get('build_component_paths') @@ -76,14 +79,14 @@ def test_component_subdirs_not_added_to_component_dirs(idf_py: IdfPyFunc, test_a (test_app_copy / 'main' / 'test').mkdir(parents=True) (test_app_copy / 'main' / 'test' / 'CMakeLists.txt').write_text('idf_component_register()') idf_py('reconfigure') - data = json.load(open(test_app_copy / 'build' / 'project_description.json', 'r')) + data = json.load(open(test_app_copy / 'build' / 'project_description.json')) assert str((test_app_copy / 'main' / 'test').as_posix()) not in data.get('build_component_paths') assert str((test_app_copy / 'main').as_posix()) in data.get('build_component_paths') def test_component_sibling_dirs_not_added_to_component_dirs(idf_py: IdfPyFunc, test_app_copy: Path) -> None: logging.info('If a component directory is added to COMPONENT_DIRS, its sibling directories are not added') - mycomponents_subdir = (test_app_copy / 'mycomponents') + mycomponents_subdir = test_app_copy / 'mycomponents' (mycomponents_subdir / 'mycomponent').mkdir(parents=True) (mycomponents_subdir / 'mycomponent' / 'CMakeLists.txt').write_text('idf_component_register()') @@ -91,7 +94,7 @@ def test_component_sibling_dirs_not_added_to_component_dirs(idf_py: IdfPyFunc, t (mycomponents_subdir / 'esp32').mkdir(parents=True) (mycomponents_subdir / 'esp32' / 'CMakeLists.txt').write_text('idf_component_register()') idf_py('-DEXTRA_COMPONENT_DIRS={}'.format(str(mycomponents_subdir / 'mycomponent')), 'reconfigure') - data = json.load(open(test_app_copy / 'build' / 'project_description.json', 'r')) + data = json.load(open(test_app_copy / 'build' / 'project_description.json')) assert str((mycomponents_subdir / 'esp32').as_posix()) not in data.get('build_component_paths') assert str((mycomponents_subdir / 'mycomponent').as_posix()) in data.get('build_component_paths') shutil.rmtree(mycomponents_subdir / 'esp32') @@ -99,74 +102,95 @@ def test_component_sibling_dirs_not_added_to_component_dirs(idf_py: IdfPyFunc, t # now the same thing, but add a components directory (test_app_copy / 'esp32').mkdir() (test_app_copy / 'esp32' / 'CMakeLists.txt').write_text('idf_component_register()') - idf_py('-DEXTRA_COMPONENT_DIRS={}'.format(str(mycomponents_subdir)), 'reconfigure') - data = json.load(open(test_app_copy / 'build' / 'project_description.json', 'r')) + idf_py(f'-DEXTRA_COMPONENT_DIRS={str(mycomponents_subdir)}', 'reconfigure') + data = json.load(open(test_app_copy / 'build' / 'project_description.json')) assert str((test_app_copy / 'esp32').as_posix()) not in data.get('build_component_paths') assert str((mycomponents_subdir / 'mycomponent').as_posix()) in data.get('build_component_paths') def test_component_properties_are_set(idf_py: IdfPyFunc, test_app_copy: Path) -> None: logging.info('Component properties are set') - append_to_file(test_app_copy / 'CMakeLists.txt', '\n'.join(['', - 'idf_component_get_property(srcs main SRCS)', - 'message(STATUS SRCS:${srcs})'])) + append_to_file( + test_app_copy / 'CMakeLists.txt', + '\n'.join(['', 'idf_component_get_property(srcs main SRCS)', 'message(STATUS SRCS:${srcs})']), + ) ret = idf_py('reconfigure') - assert 'SRCS:{}'.format((test_app_copy / 'main' / 'build_test_app.c').as_posix()) in ret.stdout, 'Component properties should be set' + assert 'SRCS:{}'.format((test_app_copy / 'main' / 'build_test_app.c').as_posix()) in ret.stdout, ( + 'Component properties should be set' + ) def test_get_property_for_unknown_component(idf_py: IdfPyFunc, test_app_copy: Path) -> None: logging.info('Getting property of unknown component fails gracefully') - append_to_file(test_app_copy / 'CMakeLists.txt', '\n'.join(['', - 'idf_component_get_property(VAR UNKNOWN PROP)'])) + append_to_file(test_app_copy / 'CMakeLists.txt', '\n'.join(['', 'idf_component_get_property(VAR UNKNOWN PROP)'])) ret = idf_py('reconfigure', check=False) - assert "Failed to resolve component 'UNKNOWN'" in ret.stderr, ('idf_component_get_property ' - 'for unknown component should fail gracefully') + assert "Failed to resolve component 'UNKNOWN'" in ret.stderr, ( + 'idf_component_get_property for unknown component should fail gracefully' + ) def test_set_property_for_unknown_component(idf_py: IdfPyFunc, test_app_copy: Path) -> None: logging.info('Setting property of unknown component fails gracefully') - append_to_file(test_app_copy / 'CMakeLists.txt', '\n'.join(['', - 'idf_component_set_property(UNKNOWN PROP VAL)'])) + append_to_file(test_app_copy / 'CMakeLists.txt', '\n'.join(['', 'idf_component_set_property(UNKNOWN PROP VAL)'])) ret = idf_py('reconfigure', check=False) - assert "Failed to resolve component 'UNKNOWN'" in ret.stderr, ('idf_component_set_property ' - 'for unknown component should fail gracefully') + assert "Failed to resolve component 'UNKNOWN'" in ret.stderr, ( + 'idf_component_set_property for unknown component should fail gracefully' + ) def test_component_overridden_dir(idf_py: IdfPyFunc, test_app_copy: Path, default_idf_env: EnvDict) -> None: logging.info('Getting component overridden dir') (test_app_copy / 'components' / 'hal').mkdir(parents=True) - (test_app_copy / 'components' / 'hal' / 'CMakeLists.txt').write_text('\n'.join([ - 'idf_component_get_property(overridden_dir ${COMPONENT_NAME} COMPONENT_OVERRIDEN_DIR)', - 'message(STATUS overridden_dir:${overridden_dir})', 'idf_component_register()'])) + (test_app_copy / 'components' / 'hal' / 'CMakeLists.txt').write_text( + '\n'.join( + [ + 'idf_component_get_property(overridden_dir ${COMPONENT_NAME} COMPONENT_OVERRIDEN_DIR)', + 'message(STATUS overridden_dir:${overridden_dir})', + 'idf_component_register()', + ] + ) + ) ret = idf_py('reconfigure') idf_path = Path(default_idf_env.get('IDF_PATH')) # no registration, overrides registration as well - assert 'overridden_dir:{}'.format((idf_path / 'components' / 'hal').as_posix()) in ret.stdout, 'Failed to get overridden dir' - append_to_file((test_app_copy / 'components' / 'hal' / 'CMakeLists.txt'), '\n'.join([ - '', - 'idf_component_register(KCONFIG ${overridden_dir}/Kconfig)', - 'idf_component_get_property(kconfig ${COMPONENT_NAME} KCONFIG)', - 'message(STATUS kconfig:${overridden_dir}/Kconfig)'])) + assert 'overridden_dir:{}'.format((idf_path / 'components' / 'hal').as_posix()) in ret.stdout, ( + 'Failed to get overridden dir' + ) + append_to_file( + (test_app_copy / 'components' / 'hal' / 'CMakeLists.txt'), + '\n'.join( + [ + '', + 'idf_component_register(KCONFIG ${overridden_dir}/Kconfig)', + 'idf_component_get_property(kconfig ${COMPONENT_NAME} KCONFIG)', + 'message(STATUS kconfig:${overridden_dir}/Kconfig)', + ] + ), + ) ret = idf_py('reconfigure', check=False) - assert 'kconfig:{}'.format((idf_path / 'components' / 'hal').as_posix()) in ret.stdout, 'Failed to verify original `main` directory' + assert 'kconfig:{}'.format((idf_path / 'components' / 'hal').as_posix()) in ret.stdout, ( + 'Failed to verify original `main` directory' + ) def test_project_components_overrides_extra_components(idf_py: IdfPyFunc, test_app_copy: Path) -> None: logging.info('Project components override components defined in EXTRA_COMPONENT_DIRS') (test_app_copy / 'extra_dir' / 'my_component').mkdir(parents=True) (test_app_copy / 'extra_dir' / 'my_component' / 'CMakeLists.txt').write_text('idf_component_register()') - replace_in_file(test_app_copy / 'CMakeLists.txt', - '# placeholder_before_include_project_cmake', - 'set(EXTRA_COMPONENT_DIRS extra_dir)') + replace_in_file( + test_app_copy / 'CMakeLists.txt', + '# placeholder_before_include_project_cmake', + 'set(EXTRA_COMPONENT_DIRS extra_dir)', + ) idf_py('reconfigure') - with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + with open(test_app_copy / 'build' / 'project_description.json') as f: data = json.load(f) assert str((test_app_copy / 'extra_dir' / 'my_component').as_posix()) in data.get('build_component_paths') (test_app_copy / 'components' / 'my_component').mkdir(parents=True) (test_app_copy / 'components' / 'my_component' / 'CMakeLists.txt').write_text('idf_component_register()') idf_py('reconfigure') - with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + with open(test_app_copy / 'build' / 'project_description.json') as f: data = json.load(f) assert str((test_app_copy / 'components' / 'my_component').as_posix()) in data.get('build_component_paths') assert str((test_app_copy / 'extra_dir' / 'my_component').as_posix()) not in data.get('build_component_paths') @@ -179,22 +203,24 @@ def test_extra_components_overrides_managed_components(idf_py: IdfPyFunc, test_a example/cmp: "*" """) idf_py('reconfigure') - with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + with open(test_app_copy / 'build' / 'project_description.json') as f: data = json.load(f) - assert str((test_app_copy / 'managed_components' / 'example__cmp').as_posix()) in data.get( - 'build_component_paths') + assert str((test_app_copy / 'managed_components' / 'example__cmp').as_posix()) in data.get('build_component_paths') (test_app_copy / 'extra_dir' / 'cmp').mkdir(parents=True) (test_app_copy / 'extra_dir' / 'cmp' / 'CMakeLists.txt').write_text('idf_component_register()') - replace_in_file(test_app_copy / 'CMakeLists.txt', - '# placeholder_before_include_project_cmake', - 'set(EXTRA_COMPONENT_DIRS extra_dir)') + replace_in_file( + test_app_copy / 'CMakeLists.txt', + '# placeholder_before_include_project_cmake', + 'set(EXTRA_COMPONENT_DIRS extra_dir)', + ) idf_py('reconfigure') - with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + with open(test_app_copy / 'build' / 'project_description.json') as f: data = json.load(f) assert str((test_app_copy / 'extra_dir' / 'cmp').as_posix()) in data.get('build_component_paths') assert str((test_app_copy / 'managed_components' / 'example__cmp').as_posix()) not in data.get( - 'build_component_paths') + 'build_component_paths' + ) @pytest.mark.with_idf_components(['cmp']) @@ -203,32 +229,31 @@ def test_managed_components_overrides_idf_components(idf_py: IdfPyFunc, test_app # created idf component 'cmp' in marker idf_path = Path(os.environ['IDF_PATH']) idf_py('reconfigure') - with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + with open(test_app_copy / 'build' / 'project_description.json') as f: data = json.load(f) - assert str((idf_path / 'components' / 'cmp').as_posix()) in data.get( - 'build_component_paths') + assert str((idf_path / 'components' / 'cmp').as_posix()) in data.get('build_component_paths') (test_app_copy / 'main' / 'idf_component.yml').write_text(""" dependencies: example/cmp: "*" """) idf_py('reconfigure') - with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + with open(test_app_copy / 'build' / 'project_description.json') as f: data = json.load(f) - assert str((test_app_copy / 'managed_components' / 'example__cmp').as_posix()) in data.get( - 'build_component_paths') - assert str((idf_path / 'components' / 'cmp').as_posix()) not in data.get( - 'build_component_paths') + assert str((test_app_copy / 'managed_components' / 'example__cmp').as_posix()) in data.get('build_component_paths') + assert str((idf_path / 'components' / 'cmp').as_posix()) not in data.get('build_component_paths') def test_manifest_local_source_overrides_extra_components(idf_py: IdfPyFunc, test_app_copy: Path) -> None: (test_app_copy / '..' / 'extra_dir' / 'cmp').mkdir(parents=True) (test_app_copy / '..' / 'extra_dir' / 'cmp' / 'CMakeLists.txt').write_text('idf_component_register()') - replace_in_file(test_app_copy / 'CMakeLists.txt', - '# placeholder_before_include_project_cmake', - 'set(EXTRA_COMPONENT_DIRS ../extra_dir)') + replace_in_file( + test_app_copy / 'CMakeLists.txt', + '# placeholder_before_include_project_cmake', + 'set(EXTRA_COMPONENT_DIRS ../extra_dir)', + ) idf_py('reconfigure') - with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + with open(test_app_copy / 'build' / 'project_description.json') as f: data = json.load(f) assert str((test_app_copy / '..' / 'extra_dir' / 'cmp').resolve().as_posix()) in data.get('build_component_paths') @@ -241,10 +266,12 @@ dependencies: path: '../../cmp' """) idf_py('reconfigure') - with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + with open(test_app_copy / 'build' / 'project_description.json') as f: data = json.load(f) assert str((test_app_copy / '..' / 'cmp').resolve().as_posix()) in data.get('build_component_paths') - assert str((test_app_copy / '..' / 'extra_dir' / 'cmp').resolve().as_posix()) not in data.get('build_component_paths') + assert str((test_app_copy / '..' / 'extra_dir' / 'cmp').resolve().as_posix()) not in data.get( + 'build_component_paths' + ) def test_exclude_components_not_passed(idf_py: IdfPyFunc, test_app_copy: Path) -> None: @@ -258,8 +285,11 @@ def test_exclude_components_not_passed(idf_py: IdfPyFunc, test_app_copy: Path) - def test_version_in_component_cmakelist(idf_py: IdfPyFunc, test_app_copy: Path) -> None: logging.info('Use IDF version variables in component CMakeLists.txt file') - replace_in_file((test_app_copy / 'main' / 'CMakeLists.txt'), '# placeholder_before_idf_component_register', - '\n'.join(['if (NOT IDF_VERSION_MAJOR)', ' message(FATAL_ERROR "IDF version not set")', 'endif()'])) + replace_in_file( + (test_app_copy / 'main' / 'CMakeLists.txt'), + '# placeholder_before_idf_component_register', + '\n'.join(['if (NOT IDF_VERSION_MAJOR)', ' message(FATAL_ERROR "IDF version not set")', 'endif()']), + ) idf_py('reconfigure') @@ -271,4 +301,4 @@ def test_unknown_component_error(idf_py: IdfPyFunc, test_app_copy: Path) -> None replace='REQUIRES unknown', ) ret = idf_py('reconfigure', check=False) - assert 'Failed to resolve component \'unknown\' required by component \'main\'' in ret.stderr + assert "Failed to resolve component 'unknown' required by component 'main'" in ret.stderr