diff --git a/tools/ci/test_build_system_cmake.sh b/tools/ci/test_build_system_cmake.sh index 88cc6f0b49..4b8701f60c 100755 --- a/tools/ci/test_build_system_cmake.sh +++ b/tools/ci/test_build_system_cmake.sh @@ -894,7 +894,7 @@ endmenu\n" >> ${IDF_PATH}/Kconfig echo "CONFIG_ESP_ERR_TO_NAME_LOOKUP=n" >> sdkconfig idf.py reconfigure || failure "Couldn't configure for loadable ELF file" - test -f build/flasher_args.json && failure "flasher_args.json should not be generated in a loadable ELF build" + test ! -f build/flasher_args.json && failure "flasher_args.json should be generated in a loadable ELF build" idf.py build || failure "Couldn't build a loadable ELF file" print_status "Defaults set properly for unspecified idf_build_process args" diff --git a/tools/test_apps/.build-test-rules.yml b/tools/test_apps/.build-test-rules.yml index 7fc8297b8b..11131f809d 100644 --- a/tools/test_apps/.build-test-rules.yml +++ b/tools/test_apps/.build-test-rules.yml @@ -161,6 +161,12 @@ tools/test_apps/system/panic: temporary: true reason: test app not ported to this target yet +tools/test_apps/system/ram_loadable_app: + disable: + - if: IDF_TARGET == "esp32h2" or IDF_TARGET == "esp32h4" + temporary: true + reason: lack of runners + tools/test_apps/system/startup: enable: - if: INCLUDE_DEFAULT == 1 or IDF_TARGET in ["esp32h4", "esp32c6"] # preview targets diff --git a/tools/test_apps/system/ram_loadable_app/conftest.py b/tools/test_apps/system/ram_loadable_app/conftest.py new file mode 100644 index 0000000000..5c99c8eb50 --- /dev/null +++ b/tools/test_apps/system/ram_loadable_app/conftest.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +# pylint: disable=W0621 # redefined-outer-name + +import pytest +from _pytest.fixtures import FixtureRequest +from _pytest.monkeypatch import MonkeyPatch +from test_ram_loadable_app_util.loadable_app_serial import LoadableAppSerial + + +@pytest.fixture(scope='module') +def monkeypatch_module(request: FixtureRequest) -> MonkeyPatch: + mp = MonkeyPatch() + request.addfinalizer(mp.undo) + return mp + + +@pytest.fixture(scope='module', autouse=True) +def replace_dut_class(monkeypatch_module: MonkeyPatch) -> None: + monkeypatch_module.setattr('pytest_embedded_idf.serial.IdfSerial', LoadableAppSerial) + monkeypatch_module.setattr('pytest_embedded_idf.IdfSerial', LoadableAppSerial) diff --git a/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py b/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py new file mode 100644 index 0000000000..8068351016 --- /dev/null +++ b/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded_idf.dut import IdfDut + + +@pytest.mark.esp32 +@pytest.mark.esp32c2 +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.generic +@pytest.mark.parametrize('config', ['pure_ram',], indirect=True,) +def test_pure_ram_loadable_app(dut: IdfDut) -> None: + dut.expect('app_start: Starting scheduler', timeout=10) + dut.expect('Time since boot: 3 seconds...', timeout=10) + + +@pytest.mark.esp32c2 +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.generic +@pytest.mark.parametrize('config', ['defaults',], indirect=True,) +def test_ram_loadable_app(dut: IdfDut) -> None: + dut.expect('spi_flash: detected chip', timeout=10) + dut.expect('Time since boot: 3 seconds...', timeout=10) diff --git a/tools/test_apps/system/ram_loadable_app/sdkconfig.ci.defaults b/tools/test_apps/system/ram_loadable_app/sdkconfig.ci.defaults new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tools/test_apps/system/ram_loadable_app/sdkconfig.ci.pure_ram b/tools/test_apps/system/ram_loadable_app/sdkconfig.ci.pure_ram new file mode 100644 index 0000000000..5158a87a8d --- /dev/null +++ b/tools/test_apps/system/ram_loadable_app/sdkconfig.ci.pure_ram @@ -0,0 +1 @@ +CONFIG_APP_BUILD_TYPE_PURE_RAM_APP=y diff --git a/tools/test_apps/system/ram_loadable_app/sdkconfig.defaults b/tools/test_apps/system/ram_loadable_app/sdkconfig.defaults index 640d086d6b..6c0ad38fad 100644 --- a/tools/test_apps/system/ram_loadable_app/sdkconfig.defaults +++ b/tools/test_apps/system/ram_loadable_app/sdkconfig.defaults @@ -5,3 +5,5 @@ CONFIG_VFS_SUPPORT_IO=n # Reset is meaningless to ram_app CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y + +CONFIG_APP_BUILD_TYPE_PURE_RAM_APP=n diff --git a/tools/test_apps/system/ram_loadable_app/sdkconfig.defaults.esp32 b/tools/test_apps/system/ram_loadable_app/sdkconfig.defaults.esp32 new file mode 100644 index 0000000000..8feb070c3a --- /dev/null +++ b/tools/test_apps/system/ram_loadable_app/sdkconfig.defaults.esp32 @@ -0,0 +1,9 @@ +CONFIG_APP_BUILD_TYPE_RAM=y + +# Save size +CONFIG_VFS_SUPPORT_TERMIOS=n + +# Reset is meaningless to ram_app +CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y + +CONFIG_APP_BUILD_TYPE_PURE_RAM_APP=y diff --git a/tools/test_apps/system/ram_loadable_app/test_ram_loadable_app_util/loadable_app_serial.py b/tools/test_apps/system/ram_loadable_app/test_ram_loadable_app_util/loadable_app_serial.py new file mode 100644 index 0000000000..9cb8ca4dfb --- /dev/null +++ b/tools/test_apps/system/ram_loadable_app/test_ram_loadable_app_util/loadable_app_serial.py @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import logging +from typing import Any, Optional + +import esptool +from pytest_embedded_idf.app import IdfApp +from pytest_embedded_serial_esp.serial import EspSerial, EsptoolArgs + + +class LoadableAppSerial(EspSerial): + def __init__( + self, + app: IdfApp, + target: Optional[str] = None, + **kwargs: Any, + ) -> None: + self.app = app + self.app.bin_file = self.app._get_bin_file() + + if not hasattr(self.app, 'target'): + raise ValueError(f'Idf app not parsable. Please check if it\'s valid: {self.app.binary_path}') + + if target and self.app.target and self.app.target != target: + raise ValueError(f'Targets do not match. App target: {self.app.target}, Cmd target: {target}.') + + super().__init__( + target=target or app.target, + **kwargs, + ) + + def _start(self) -> None: + self.load_ram() + + @EspSerial.use_esptool(hard_reset_after=False, no_stub=True) + def load_ram(self) -> None: + if not self.app.bin_file: + logging.error('No image file detected. Skipping load ram...') + return + + f_bin_file = open(self.app.bin_file, 'rb') + + default_kwargs = { + 'filename': f_bin_file, + 'chip': self.esp.CHIP_NAME.lower().replace('-', ''), + } + + load_ram_args = EsptoolArgs(**default_kwargs) + + try: + self.esp.change_baud(460800) + esptool.load_ram(self.esp, load_ram_args) + finally: + f_bin_file.close()