forked from espressif/esp-idf
Merge branch 'feature/rewrite_build_sys_tests_v4' into 'master'
Tools: Rewrite build system unit tests to python - idf.py sdkconfig, bootloader, components Closes IDF-7164 See merge request espressif/esp-idf!22325
This commit is contained in:
@@ -50,7 +50,7 @@ idf.py fails if IDF_TARGET settings don't match in sdkconfig, CMakeCache.txt, an
|
|||||||
Setting EXTRA_COMPONENT_DIRS works | test_components.py::test_component_extra_dirs |
|
Setting EXTRA_COMPONENT_DIRS works | test_components.py::test_component_extra_dirs |
|
||||||
Non-existent paths in EXTRA_COMPONENT_DIRS are not allowed | test_components.py::test_component_nonexistent_extra_dirs_not_allowed |
|
Non-existent paths in EXTRA_COMPONENT_DIRS are not allowed | test_components.py::test_component_nonexistent_extra_dirs_not_allowed |
|
||||||
Component names may contain spaces | test_components.py::test_component_names_contain_spaces |
|
Component names may contain spaces | test_components.py::test_component_names_contain_spaces |
|
||||||
sdkconfig should have contents of all files: sdkconfig, sdkconfig.defaults, sdkconfig.defaults.IDF_TARGET | |
|
sdkconfig should have contents of all files: sdkconfig, sdkconfig.defaults, sdkconfig.defaults.IDF_TARGET | test_sdkconfig.py::test_sdkconfig_contains_all_files |
|
||||||
Test if it can build the example to run on host | |
|
Test if it can build the example to run on host | |
|
||||||
Test build ESP-IDF as a library to a custom CMake projects for all targets | test_cmake.py::test_build_custom_cmake_project |
|
Test build ESP-IDF as a library to a custom CMake projects for all targets | test_cmake.py::test_build_custom_cmake_project |
|
||||||
Building a project with CMake library imported and PSRAM workaround, all files compile with workaround | test_cmake.py::test_build_cmake_library_psram_workaround |
|
Building a project with CMake library imported and PSRAM workaround, all files compile with workaround | test_cmake.py::test_build_cmake_library_psram_workaround |
|
||||||
@@ -63,22 +63,22 @@ Handling deprecated Kconfig options | test_kconfig.py::test_kconfig_deprecated_o
|
|||||||
Handling deprecated Kconfig options in sdkconfig.defaults | test_kconfig.py::test_kconfig_deprecated_options |
|
Handling deprecated Kconfig options in sdkconfig.defaults | test_kconfig.py::test_kconfig_deprecated_options |
|
||||||
Can have multiple deprecated Kconfig options map to a single new option | test_kconfig.py::test_kconfig_multiple_and_target_specific_options |
|
Can have multiple deprecated Kconfig options map to a single new option | test_kconfig.py::test_kconfig_multiple_and_target_specific_options |
|
||||||
Can have target specific deprecated Kconfig options | test_kconfig.py::test_kconfig_multiple_and_target_specific_options |
|
Can have target specific deprecated Kconfig options | test_kconfig.py::test_kconfig_multiple_and_target_specific_options |
|
||||||
Confserver can be invoked by idf.py | |
|
Confserver can be invoked by idf.py | test_common.py::test_invoke_confserver |
|
||||||
Check ccache is used to build | |
|
Check ccache is used to build | test_common.py::test_ccache_used_to_build |
|
||||||
Custom bootloader overrides original | |
|
Custom bootloader overrides original | test_bootloader.py::test_bootloader_custom_overrides_original |
|
||||||
Empty directory not treated as a component | |
|
Empty directory not treated as a component | test_components.py::test_component_can_not_be_empty_dir |
|
||||||
If a component directory is added to COMPONENT_DIRS, its subdirectories are not added | |
|
If a component directory is added to COMPONENT_DIRS, its subdirectories are not added | test_components.py::test_component_subdirs_not_added_to_component_dirs |
|
||||||
If a component directory is added to COMPONENT_DIRS, its sibling directories are not added | |
|
If a component directory is added to COMPONENT_DIRS, its sibling directories are not added | test_components.py::test_component_sibling_dirs_not_added_to_component_dirs |
|
||||||
toolchain prefix is set in project description file | |
|
toolchain prefix is set in project description file | test_common.py::test_toolchain_prefix_in_description_file |
|
||||||
Can set options to subcommands: print_filter for monitor | |
|
Can set options to subcommands: print_filter for monitor | test_common.py::test_subcommands_with_options |
|
||||||
Fail on build time works | |
|
Fail on build time works | test_build.py::test_build_fail_on_build_time |
|
||||||
Component properties are set | |
|
Component properties are set | test_components.py::test_component_properties_are_set |
|
||||||
should be able to specify multiple sdkconfig default files | |
|
should be able to specify multiple sdkconfig default files | test_sdkconfig.py::test_sdkconfig_multiple_default_files |
|
||||||
Supports git worktree | |
|
Supports git worktree | |
|
||||||
idf.py fallback to build system target | |
|
idf.py fallback to build system target | |
|
||||||
Build fails if partitions don't fit in flash | |
|
Build fails if partitions don't fit in flash | |
|
||||||
Warning is given if smallest partition is nearly full | |
|
Warning is given if smallest partition is nearly full | |
|
||||||
Flash size is correctly set in the bootloader image header | |
|
Flash size is correctly set in the bootloader image header | test_bootloader.py::test_bootloader_correctly_set_image_header |
|
||||||
DFU build works | |
|
DFU build works | |
|
||||||
UF2 build works | |
|
UF2 build works | |
|
||||||
Loadable ELF build works | |
|
Loadable ELF build works | |
|
||||||
|
@@ -139,6 +139,6 @@ def fixture_default_idf_env() -> EnvDict:
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def idf_py(default_idf_env: EnvDict) -> IdfPyFunc:
|
def idf_py(default_idf_env: EnvDict) -> IdfPyFunc:
|
||||||
def result(*args: str, check: bool = True) -> subprocess.CompletedProcess:
|
def result(*args: str, check: bool = True, input_str: typing.Optional[str] = None) -> subprocess.CompletedProcess:
|
||||||
return run_idf_py(*args, env=default_idf_env, workdir=os.getcwd(), check=check) # type: ignore
|
return run_idf_py(*args, env=default_idf_env, workdir=os.getcwd(), check=check, input_str=input_str) # type: ignore
|
||||||
return result
|
return result
|
||||||
|
53
tools/test_build_system/test_bootloader.py
Normal file
53
tools/test_build_system/test_bootloader.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
import logging
|
||||||
|
import shutil
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
from test_build_system_helpers import EnvDict, IdfPyFunc, file_contains
|
||||||
|
|
||||||
|
|
||||||
|
def get_two_header_bytes(file_path: Union[str, Path]) -> str:
|
||||||
|
'''
|
||||||
|
get the bytes 3-4 of the given file
|
||||||
|
https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/firmware-image-format.html
|
||||||
|
'''
|
||||||
|
data = b''
|
||||||
|
with open(file_path, 'rb') as f:
|
||||||
|
data = f.read(4)
|
||||||
|
extracted_bytes = data[2:4]
|
||||||
|
return extracted_bytes.hex()
|
||||||
|
|
||||||
|
|
||||||
|
def test_bootloader_custom_overrides_original(test_app_copy: Path, idf_py: IdfPyFunc, default_idf_env: EnvDict) -> None:
|
||||||
|
logging.info('Custom bootloader overrides original')
|
||||||
|
idf_path = Path(default_idf_env.get('IDF_PATH'))
|
||||||
|
shutil.copytree(idf_path / 'components' / 'bootloader', test_app_copy / 'components' / 'bootloader')
|
||||||
|
# Because of relative include of Kconfig, also esp_bootloader_format needs to be copied.
|
||||||
|
shutil.copytree(idf_path / 'components' / 'esp_bootloader_format', test_app_copy / 'components' / 'esp_bootloader_format')
|
||||||
|
idf_py('bootloader')
|
||||||
|
assert file_contains(test_app_copy / 'build' / 'bootloader' / 'compile_commands.json',
|
||||||
|
str(test_app_copy / 'components' / 'bootloader' / 'subproject' / 'main' / 'bootloader_start.c'))
|
||||||
|
|
||||||
|
|
||||||
|
def test_bootloader_correctly_set_image_header(test_app_copy: Path, idf_py: IdfPyFunc) -> None:
|
||||||
|
logging.info('Flash size is correctly set in the bootloader image header')
|
||||||
|
# Build with the default 2MB setting
|
||||||
|
idf_py('bootloader')
|
||||||
|
assert get_two_header_bytes(test_app_copy / 'build' / 'bootloader' / 'bootloader.bin') == '0210'
|
||||||
|
|
||||||
|
# Change to 4MB
|
||||||
|
(test_app_copy / 'sdkconfig').write_text('CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y')
|
||||||
|
idf_py('reconfigure', 'bootloader')
|
||||||
|
assert get_two_header_bytes(test_app_copy / 'build' / 'bootloader' / 'bootloader.bin') == '0220'
|
||||||
|
|
||||||
|
# Change to QIO, bootloader should still be DIO (will change to QIO in 2nd stage bootloader)
|
||||||
|
(test_app_copy / 'sdkconfig').write_text('CONFIG_FLASHMODE_QIO=y')
|
||||||
|
idf_py('reconfigure', 'bootloader')
|
||||||
|
assert get_two_header_bytes(test_app_copy / 'build' / 'bootloader' / 'bootloader.bin') == '0210'
|
||||||
|
|
||||||
|
# Change to 80 MHz
|
||||||
|
(test_app_copy / 'sdkconfig').write_text('CONFIG_ESPTOOLPY_FLASHFREQ_80M=y')
|
||||||
|
idf_py('reconfigure', 'bootloader')
|
||||||
|
assert get_two_header_bytes(test_app_copy / 'build' / 'bootloader' / 'bootloader.bin') == '021f'
|
@@ -128,3 +128,15 @@ def test_build_with_sdkconfig_build_abspath(idf_py: IdfPyFunc, test_app_copy: Pa
|
|||||||
build_path = test_app_copy / 'build_tmp'
|
build_path = test_app_copy / 'build_tmp'
|
||||||
sdkconfig_path = build_path / 'sdkconfig'
|
sdkconfig_path = build_path / 'sdkconfig'
|
||||||
idf_py('-D', f'SDKCONFIG={sdkconfig_path}', '-B', str(build_path), 'build')
|
idf_py('-D', f'SDKCONFIG={sdkconfig_path}', '-B', str(build_path), 'build')
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_fail_on_build_time(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
|
||||||
|
logging.info('Fail on build time works')
|
||||||
|
append_to_file(test_app_copy / 'CMakeLists.txt', '\n'.join(['',
|
||||||
|
'if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/hello.txt")',
|
||||||
|
'fail_at_build_time(test_file "hello.txt does not exists")',
|
||||||
|
'endif()']))
|
||||||
|
ret = idf_py('build', check=False)
|
||||||
|
assert ret.returncode != 0, 'Build should fail if requirements are not satisfied'
|
||||||
|
(test_app_copy / 'hello.txt').touch()
|
||||||
|
idf_py('build')
|
||||||
|
@@ -61,7 +61,8 @@ def run_idf_py(*args: str,
|
|||||||
idf_path: typing.Optional[typing.Union[str,Path]] = None,
|
idf_path: typing.Optional[typing.Union[str,Path]] = None,
|
||||||
workdir: typing.Optional[str] = None,
|
workdir: typing.Optional[str] = None,
|
||||||
check: bool = True,
|
check: bool = True,
|
||||||
python: typing.Optional[str] = None) -> subprocess.CompletedProcess:
|
python: typing.Optional[str] = None,
|
||||||
|
input_str: typing.Optional[str] = None) -> subprocess.CompletedProcess:
|
||||||
"""
|
"""
|
||||||
Run idf.py command with given arguments, raise an exception on failure
|
Run idf.py command with given arguments, raise an exception on failure
|
||||||
:param args: arguments to pass to idf.py
|
:param args: arguments to pass to idf.py
|
||||||
@@ -70,19 +71,19 @@ def run_idf_py(*args: str,
|
|||||||
:param workdir: directory where to run the build; if not set, the current directory is used
|
:param workdir: directory where to run the build; if not set, the current directory is used
|
||||||
:param check: check process exits with a zero exit code, if false all retvals are accepted without failing the test
|
:param check: check process exits with a zero exit code, if false all retvals are accepted without failing the test
|
||||||
:param python: absolute path to python interpreter
|
:param python: absolute path to python interpreter
|
||||||
|
:param input_str: input to idf.py
|
||||||
"""
|
"""
|
||||||
env_dict = dict(**os.environ)
|
if not env:
|
||||||
if env is not None:
|
env = dict(**os.environ)
|
||||||
env_dict.update(env)
|
|
||||||
if not workdir:
|
if not workdir:
|
||||||
workdir = os.getcwd()
|
workdir = os.getcwd()
|
||||||
# order: function argument -> value in env dictionary -> system environment
|
# order: function argument -> value in env dictionary -> system environment
|
||||||
if idf_path is None:
|
if idf_path is None:
|
||||||
idf_path = env_dict.get('IDF_PATH')
|
idf_path = env.get('IDF_PATH')
|
||||||
if not idf_path:
|
if not idf_path:
|
||||||
raise ValueError('IDF_PATH must be set in the env array if idf_path argument is not set')
|
raise ValueError('IDF_PATH must be set in the env array if idf_path argument is not set')
|
||||||
if python is None:
|
if python is None:
|
||||||
python = find_python(env_dict['PATH'])
|
python = find_python(env['PATH'])
|
||||||
|
|
||||||
cmd = [
|
cmd = [
|
||||||
python,
|
python,
|
||||||
@@ -91,9 +92,9 @@ def run_idf_py(*args: str,
|
|||||||
cmd += args # type: ignore
|
cmd += args # type: ignore
|
||||||
logging.debug('running {} in {}'.format(' '.join(cmd), workdir))
|
logging.debug('running {} in {}'.format(' '.join(cmd), workdir))
|
||||||
return subprocess.run(
|
return subprocess.run(
|
||||||
cmd, env=env_dict, cwd=workdir,
|
cmd, env=env, cwd=workdir,
|
||||||
check=check, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
check=check, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||||
text=True, encoding='utf-8', errors='backslashreplace')
|
text=True, encoding='utf-8', errors='backslashreplace', input=input_str)
|
||||||
|
|
||||||
|
|
||||||
def run_cmake(*cmake_args: str, env: typing.Optional[EnvDict] = None,
|
def run_cmake(*cmake_args: str, env: typing.Optional[EnvDict] = None,
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@@ -12,8 +13,7 @@ from pathlib import Path
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.monkeypatch import MonkeyPatch
|
from test_build_system_helpers import EnvDict, IdfPyFunc, find_python, get_snapshot, replace_in_file, run_idf_py
|
||||||
from test_build_system_helpers import IdfPyFunc, find_python, get_snapshot, replace_in_file, run_idf_py
|
|
||||||
|
|
||||||
|
|
||||||
def get_subdirs_absolute_paths(path: Path) -> List[str]:
|
def get_subdirs_absolute_paths(path: Path) -> List[str]:
|
||||||
@@ -78,14 +78,13 @@ def test_idf_copy(idf_copy: Path, idf_py: IdfPyFunc) -> None:
|
|||||||
|
|
||||||
def test_idf_build_with_env_var_sdkconfig_defaults(
|
def test_idf_build_with_env_var_sdkconfig_defaults(
|
||||||
test_app_copy: Path,
|
test_app_copy: Path,
|
||||||
idf_py: IdfPyFunc,
|
default_idf_env: EnvDict
|
||||||
monkeypatch: MonkeyPatch,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
with open(test_app_copy / 'sdkconfig.test', 'w') as fw:
|
with open(test_app_copy / 'sdkconfig.test', 'w') as fw:
|
||||||
fw.write('CONFIG_BT_ENABLED=y')
|
fw.write('CONFIG_BT_ENABLED=y')
|
||||||
|
|
||||||
monkeypatch.setenv('SDKCONFIG_DEFAULTS', 'sdkconfig.test')
|
default_idf_env['SDKCONFIG_DEFAULTS'] = 'sdkconfig.test'
|
||||||
idf_py('build')
|
run_idf_py('build', env=default_idf_env)
|
||||||
|
|
||||||
with open(test_app_copy / 'sdkconfig') as fr:
|
with open(test_app_copy / 'sdkconfig') as fr:
|
||||||
assert 'CONFIG_BT_ENABLED=y' in fr.read()
|
assert 'CONFIG_BT_ENABLED=y' in fr.read()
|
||||||
@@ -93,12 +92,11 @@ def test_idf_build_with_env_var_sdkconfig_defaults(
|
|||||||
|
|
||||||
@pytest.mark.usefixtures('test_app_copy')
|
@pytest.mark.usefixtures('test_app_copy')
|
||||||
@pytest.mark.test_app_copy('examples/system/efuse')
|
@pytest.mark.test_app_copy('examples/system/efuse')
|
||||||
def test_efuse_symmary_cmake_functions(
|
def test_efuse_summary_cmake_functions(
|
||||||
idf_py: IdfPyFunc,
|
default_idf_env: EnvDict
|
||||||
monkeypatch: MonkeyPatch
|
|
||||||
) -> None:
|
) -> None:
|
||||||
monkeypatch.setenv('IDF_CI_BUILD', '1')
|
default_idf_env['IDF_CI_BUILD'] = '1'
|
||||||
output = idf_py('efuse-summary')
|
output = run_idf_py('efuse-summary', env=default_idf_env)
|
||||||
assert 'FROM_CMAKE: MAC: 00:00:00:00:00:00' in output.stdout
|
assert 'FROM_CMAKE: MAC: 00:00:00:00:00:00' in output.stdout
|
||||||
assert 'FROM_CMAKE: WR_DIS: 0' in output.stdout
|
assert 'FROM_CMAKE: WR_DIS: 0' in output.stdout
|
||||||
|
|
||||||
@@ -158,3 +156,50 @@ def test_python_interpreter_win(test_app_copy: Path) -> None:
|
|||||||
# python is loaded from env:$PATH, but since false interpreter is provided there, python needs to be specified as argument
|
# python is loaded from env:$PATH, but since false interpreter is provided there, python needs to be specified as argument
|
||||||
# if idf.py is reconfigured during it's execution, it would load a false interpreter
|
# if idf.py is reconfigured during it's execution, it would load a false interpreter
|
||||||
run_idf_py('reconfigure', env=env_dict, python=python)
|
run_idf_py('reconfigure', env=env_dict, python=python)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('test_app_copy')
|
||||||
|
def test_invoke_confserver(idf_py: IdfPyFunc) -> None:
|
||||||
|
logging.info('Confserver can be invoked by idf.py')
|
||||||
|
idf_py('confserver', input_str='{"version": 1}')
|
||||||
|
|
||||||
|
|
||||||
|
def test_ccache_used_to_build(test_app_copy: Path) -> None:
|
||||||
|
logging.info('Check ccache is used to build')
|
||||||
|
(test_app_copy / 'ccache').touch(mode=0o755)
|
||||||
|
env_dict = dict(**os.environ)
|
||||||
|
env_dict['PATH'] = str(test_app_copy) + os.pathsep + env_dict['PATH']
|
||||||
|
# Disable using ccache automatically
|
||||||
|
if 'IDF_CCACHE_ENABLE' in env_dict:
|
||||||
|
env_dict.pop('IDF_CCACHE_ENABLE')
|
||||||
|
|
||||||
|
ret = run_idf_py('--ccache', 'reconfigure', env=env_dict)
|
||||||
|
assert 'ccache will be used' in ret.stdout
|
||||||
|
run_idf_py('fullclean', env=env_dict)
|
||||||
|
ret = run_idf_py('reconfigure', env=env_dict)
|
||||||
|
assert 'ccache will be used' not in ret.stdout
|
||||||
|
ret = run_idf_py('--no-ccache', 'reconfigure', env=env_dict)
|
||||||
|
assert 'ccache will be used' not in ret.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_toolchain_prefix_in_description_file(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
|
||||||
|
logging.info('Toolchain prefix is set in project description file')
|
||||||
|
idf_py('reconfigure')
|
||||||
|
data = json.load(open(test_app_copy / 'build' / 'project_description.json', 'r'))
|
||||||
|
assert 'monitor_toolprefix' in data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('test_app_copy')
|
||||||
|
def test_subcommands_with_options(idf_py: IdfPyFunc, default_idf_env: EnvDict) -> None:
|
||||||
|
logging.info('Can set options to subcommands: print_filter for monitor')
|
||||||
|
idf_path = Path(default_idf_env.get('IDF_PATH'))
|
||||||
|
# try - finally block is here used to backup and restore idf_monitor.py
|
||||||
|
# since we need to handle only one file, this souluton is much faster than using idf_copy fixture
|
||||||
|
monitor_backup = (idf_path / 'tools' / 'idf_monitor.py').read_text()
|
||||||
|
try:
|
||||||
|
(idf_path / 'tools' / 'idf_monitor.py').write_text('import sys;print(sys.argv[1:])')
|
||||||
|
idf_py('build')
|
||||||
|
ret = idf_py('monitor', '--print-filter=*:I', '-p', 'tty.fake')
|
||||||
|
assert "'--print_filter', '*:I'" in ret.stdout
|
||||||
|
finally:
|
||||||
|
(idf_path / 'tools' / 'idf_monitor.py').write_text(monitor_backup)
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from test_build_system_helpers import IdfPyFunc, replace_in_file
|
from test_build_system_helpers import IdfPyFunc, append_to_file, replace_in_file
|
||||||
|
|
||||||
|
|
||||||
def test_component_extra_dirs(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
|
def test_component_extra_dirs(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
|
||||||
@@ -30,3 +31,55 @@ def test_component_names_contain_spaces(idf_py: IdfPyFunc, test_app_copy: Path)
|
|||||||
(test_app_copy / 'extra component').mkdir()
|
(test_app_copy / 'extra component').mkdir()
|
||||||
(test_app_copy / 'extra component' / 'CMakeLists.txt').write_text('idf_component_register')
|
(test_app_copy / 'extra component' / 'CMakeLists.txt').write_text('idf_component_register')
|
||||||
idf_py('-DEXTRA_COMPONENT_DIRS="extra component;main"')
|
idf_py('-DEXTRA_COMPONENT_DIRS="extra component;main"')
|
||||||
|
|
||||||
|
|
||||||
|
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.mkdir(parents=True)
|
||||||
|
idf_py('reconfigure')
|
||||||
|
data = json.load(open(test_app_copy / 'build' / 'project_description.json', 'r'))
|
||||||
|
assert str(empty_component_dir) not in data.get('build_component_paths')
|
||||||
|
|
||||||
|
|
||||||
|
def test_component_subdirs_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 subdirectories are not added')
|
||||||
|
(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'))
|
||||||
|
assert str(test_app_copy / 'main' / 'test') not in data.get('build_component_paths')
|
||||||
|
assert str(test_app_copy / 'main') 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 / 'mycomponent').mkdir(parents=True)
|
||||||
|
(mycomponents_subdir / 'mycomponent' / 'CMakeLists.txt').write_text('idf_component_register()')
|
||||||
|
|
||||||
|
# first test by adding single component directory to EXTRA_COMPONENT_DIRS
|
||||||
|
(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'))
|
||||||
|
assert str(mycomponents_subdir / 'esp32') not in data.get('build_component_paths')
|
||||||
|
assert str(mycomponents_subdir / 'mycomponent') in data.get('build_component_paths')
|
||||||
|
shutil.rmtree(mycomponents_subdir / 'esp32')
|
||||||
|
|
||||||
|
# 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'))
|
||||||
|
assert str(test_app_copy / 'esp32') not in data.get('build_component_paths')
|
||||||
|
assert str(mycomponents_subdir / 'mycomponent') 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})']))
|
||||||
|
ret = idf_py('reconfigure')
|
||||||
|
assert 'SRCS:{}'.format(test_app_copy / 'main' / 'build_test_app.c') in ret.stdout, 'Component properties should be set'
|
||||||
|
26
tools/test_build_system/test_sdkconfig.py
Normal file
26
tools/test_build_system/test_sdkconfig.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from test_build_system_helpers import IdfPyFunc, file_contains
|
||||||
|
|
||||||
|
|
||||||
|
def test_sdkconfig_contains_all_files(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
|
||||||
|
logging.info('sdkconfig should have contents of all files: sdkconfig, sdkconfig.defaults, sdkconfig.defaults.IDF_TARGET')
|
||||||
|
(test_app_copy / 'sdkconfig').write_text('CONFIG_PARTITION_TABLE_TWO_OTA=y')
|
||||||
|
(test_app_copy / 'sdkconfig.defaults').write_text('CONFIG_PARTITION_TABLE_OFFSET=0x10000')
|
||||||
|
(test_app_copy / 'sdkconfig.defaults.esp32').write_text('CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y')
|
||||||
|
idf_py('reconfigure')
|
||||||
|
assert all([file_contains((test_app_copy / 'sdkconfig'), x) for x in ['CONFIG_PARTITION_TABLE_TWO_OTA=y',
|
||||||
|
'CONFIG_PARTITION_TABLE_OFFSET=0x10000',
|
||||||
|
'CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y']])
|
||||||
|
|
||||||
|
|
||||||
|
def test_sdkconfig_multiple_default_files(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
|
||||||
|
logging.info('should be able to specify multiple sdkconfig default files')
|
||||||
|
(test_app_copy / 'sdkconfig.defaults1').write_text('CONFIG_PARTITION_TABLE_OFFSET=0x10000')
|
||||||
|
(test_app_copy / 'sdkconfig.defaults2').write_text('CONFIG_PARTITION_TABLE_TWO_OTA=y')
|
||||||
|
idf_py('-DSDKCONFIG_DEFAULTS=sdkconfig.defaults1;sdkconfig.defaults2', 'reconfigure')
|
||||||
|
assert all([file_contains((test_app_copy / 'sdkconfig'), x) for x in ['CONFIG_PARTITION_TABLE_TWO_OTA=y',
|
||||||
|
'CONFIG_PARTITION_TABLE_OFFSET=0x10000']])
|
Reference in New Issue
Block a user