diff --git a/components/app_update/test_apps/test_app_update/pytest_app_update_ut.py b/components/app_update/test_apps/test_app_update/pytest_app_update_ut.py index e9d9633e33..d5cead2da2 100644 --- a/components/app_update/test_apps/test_app_update/pytest_app_update_ut.py +++ b/components/app_update/test_apps/test_app_update/pytest_app_update_ut.py @@ -1,16 +1,18 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import re import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize DEFAULT_TIMEOUT = 20 TEST_SUBMENU_PATTERN_PYTEST = re.compile(rb'\s+\((\d+)\)\s+"([^"]+)"\r?\n') -@pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32c5'], reason='C5 has not supported deep sleep') # TODO: [ESP32C5] IDF-8640, IDF-10317 +@pytest.mark.temp_skip_ci( + targets=['esp32c5'], reason='C5 has not supported deep sleep' +) # TODO: [ESP32C5] IDF-8640, IDF-10317 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -19,11 +21,11 @@ TEST_SUBMENU_PATTERN_PYTEST = re.compile(rb'\s+\((\d+)\)\s+"([^"]+)"\r?\n') ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_app_update(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=90) -@pytest.mark.supported_targets # TODO: [ESP32C61] IDF-9245, IDF-10983 @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C61 has not supported deep sleep') @pytest.mark.generic @@ -34,12 +36,14 @@ def test_app_update(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_app_update_xip_psram(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=90) -@pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32c5'], reason='C5 has not supported deep sleep') # TODO: [ESP32C5] IDF-8640, IDF-10317 +@pytest.mark.temp_skip_ci( + targets=['esp32c5'], reason='C5 has not supported deep sleep' +) # TODO: [ESP32C5] IDF-8640, IDF-10317 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -48,5 +52,6 @@ def test_app_update_xip_psram(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_app_update_xip_psram_rom_impl(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=90) diff --git a/components/bootloader_support/test_apps/bootloader_support/pytest_bootloader_support.py b/components/bootloader_support/test_apps/bootloader_support/pytest_bootloader_support.py index 8082cac3f2..1a7397fd60 100644 --- a/components/bootloader_support/test_apps/bootloader_support/pytest_bootloader_support.py +++ b/components/bootloader_support/test_apps/bootloader_support/pytest_bootloader_support.py @@ -1,26 +1,26 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.supported_targets +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_bootloader_support(dut: Dut) -> None: dut.run_all_single_board_cases() @pytest.mark.host_test @pytest.mark.qemu -@pytest.mark.esp32 +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_bootloader_support_qemu_esp32(dut: Dut) -> None: dut.run_all_single_board_cases() @pytest.mark.host_test @pytest.mark.qemu -@pytest.mark.esp32c3 +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_bootloader_support_qemu_esp32c3(dut: Dut) -> None: for case in dut.test_menu: if 'qemu-ignore-c3' not in case.groups: diff --git a/components/bootloader_support/test_apps/rtc_custom_section/pytest_rtc_mem.py b/components/bootloader_support/test_apps/rtc_custom_section/pytest_rtc_mem.py index 6dbf4030a3..167f95c7b5 100644 --- a/components/bootloader_support/test_apps/rtc_custom_section/pytest_rtc_mem.py +++ b/components/bootloader_support/test_apps/rtc_custom_section/pytest_rtc_mem.py @@ -1,17 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 +@idf_parametrize( + 'target', + ['esp32', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32p4'], + indirect=['target'], +) def test_rtc_reserved_memory(dut: Dut) -> None: dut.expect_exact('SUCCESS: data were saved across reboot', timeout=10) diff --git a/components/bt/test_apps/basic_unit_test/pytest_basic_unit_test.py b/components/bt/test_apps/basic_unit_test/pytest_basic_unit_test.py index de3d235bb5..486e96c919 100644 --- a/components/bt/test_apps/basic_unit_test/pytest_basic_unit_test.py +++ b/components/bt/test_apps/basic_unit_test/pytest_basic_unit_test.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c3 +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_bt(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/bt/test_apps/memory_release/pytest_memory_release.py b/components/bt/test_apps/memory_release/pytest_memory_release.py index fbb3916991..bc3ee19bd6 100644 --- a/components/bt/test_apps/memory_release/pytest_memory_release.py +++ b/components/bt/test_apps/memory_release/pytest_memory_release.py @@ -1,14 +1,20 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.parametrize('config', [ - pytest.param('default', marks=[pytest.mark.esp32, pytest.mark.esp32c2, pytest.mark.generic]), - pytest.param('iram', marks=[pytest.mark.esp32c2, pytest.mark.generic]), - pytest.param('psram', marks=[pytest.mark.esp32, pytest.mark.psram]), -], indirect=True) +@idf_parametrize( + 'config,target,markers', + [ + ('default', 'esp32', (pytest.mark.generic,)), + ('default', 'esp32c2', (pytest.mark.generic,)), + ('iram', 'esp32c2', (pytest.mark.generic,)), + ('psram', 'esp32', (pytest.mark.psram,)), + ], + indirect=['config', 'target'], +) def test_bt_memory_release(dut: Dut) -> None: dut.expect_exact('BLE Host Task Started', timeout=6) dut.expect_exact('BLE Host Task Stopped', timeout=8) diff --git a/components/console/test_apps/console/pytest_console.py b/components/console/test_apps/console/pytest_console.py index 20901b4652..3d6243391f 100644 --- a/components/console/test_apps/console/pytest_console.py +++ b/components/console/test_apps/console/pytest_console.py @@ -1,7 +1,8 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def do_test_quit(dut: Dut) -> None: @@ -44,69 +45,61 @@ def do_test_help_quit(dut: Dut) -> None: dut.expect(r'quit\s+Quit REPL environment\s+esp>') -@pytest.mark.parametrize( - 'config', [ - pytest.param('defaults'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), - pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), - pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), - ] +@idf_parametrize('config', ['defaults'], indirect=['config']) +@idf_parametrize( + 'target,test_on,markers', + [ + ('linux', 'host', (pytest.mark.host_test,)), + ('esp32', 'target', (pytest.mark.generic,)), + ('esp32c3', 'target', (pytest.mark.generic,)), + ('esp32', 'qemu', (pytest.mark.host_test, pytest.mark.qemu)), + ], + indirect=['target'], ) def test_console(dut: Dut, test_on: str) -> None: dut.run_all_single_board_cases(group='!ignore', timeout=120) -@pytest.mark.parametrize( - 'config', [ - pytest.param('defaults'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), - pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), - pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), - ] +@idf_parametrize('config', ['defaults'], indirect=['config']) +@idf_parametrize( + 'target,test_on,markers', + [ + ('linux', 'host', (pytest.mark.host_test,)), + ('esp32', 'target', (pytest.mark.generic,)), + ('esp32c3', 'target', (pytest.mark.generic,)), + ('esp32', 'qemu', (pytest.mark.host_test, pytest.mark.qemu)), + ], + indirect=['target'], ) def test_console_repl(dut: Dut, test_on: str) -> None: do_test_quit(dut) -@pytest.mark.parametrize( - 'config', [ - pytest.param('defaults'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), - pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), - pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), - ] +@idf_parametrize('config', ['defaults'], indirect=['config']) +@idf_parametrize( + 'target,test_on,markers', + [ + ('linux', 'host', (pytest.mark.host_test,)), + ('esp32', 'target', (pytest.mark.generic,)), + ('esp32c3', 'target', (pytest.mark.generic,)), + ('esp32', 'qemu', (pytest.mark.host_test, pytest.mark.qemu)), + ], + indirect=['target'], ) def test_console_help_sorted_registration(dut: Dut, test_on: str) -> None: do_test_help_generic(dut, 'sorted') -@pytest.mark.parametrize( - 'config', [ - pytest.param('defaults'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), - pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), - pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), - ] +@idf_parametrize('config', ['defaults'], indirect=['config']) +@idf_parametrize( + 'target,test_on,markers', + [ + ('linux', 'host', (pytest.mark.host_test,)), + ('esp32', 'target', (pytest.mark.generic,)), + ('esp32c3', 'target', (pytest.mark.generic,)), + ('esp32', 'qemu', (pytest.mark.host_test, pytest.mark.qemu)), + ], + indirect=['target'], ) def test_console_help_reverse_registration(dut: Dut, test_on: str) -> None: dut.expect_exact('Press ENTER to see the list of tests') @@ -131,63 +124,45 @@ def test_console_help_reverse_registration(dut: Dut, test_on: str) -> None: dut.expect_exact('esp>') -@pytest.mark.parametrize( - 'config', [ - pytest.param('sorted'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - ] -) +@idf_parametrize('config', ['sorted'], indirect=['config']) +@idf_parametrize('target', ['linux'], indirect=['target']) +@idf_parametrize('test_on,markers', [('host', (pytest.mark.host_test,))]) def test_console_sorted_help_sorted_registration(dut: Dut, test_on: str) -> None: do_test_help_generic(dut, 'sorted') -@pytest.mark.parametrize( - 'config', [ - pytest.param('sorted', marks=[pytest.mark.linux, pytest.mark.host_test]), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - ] -) +@idf_parametrize('config', ['sorted'], indirect=['config']) +@idf_parametrize('target', ['linux'], indirect=['target']) +@idf_parametrize('test_on,markers', [('host', (pytest.mark.host_test,))]) def test_console_sorted_help_reverse_registration(dut: Dut, test_on: str) -> None: do_test_help_generic(dut, 'reverse') -@pytest.mark.parametrize( - 'config', [ - pytest.param('defaults'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), - pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), - pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), - ] +@idf_parametrize('config', ['defaults'], indirect=['config']) +@idf_parametrize( + 'target,test_on,markers', + [ + ('linux', 'host', (pytest.mark.host_test,)), + ('esp32', 'target', (pytest.mark.generic,)), + ('esp32c3', 'target', (pytest.mark.generic,)), + ('esp32', 'qemu', (pytest.mark.host_test, pytest.mark.qemu)), + ], + indirect=['target'], ) def test_console_help_quit(dut: Dut, test_on: str) -> None: do_test_help_quit(dut) -@pytest.mark.parametrize( - 'config', [ - pytest.param('defaults'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), - pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), - pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), - ] +@idf_parametrize('config', ['defaults'], indirect=['config']) +@idf_parametrize( + 'target,test_on,markers', + [ + ('linux', 'host', (pytest.mark.host_test,)), + ('esp32', 'target', (pytest.mark.generic,)), + ('esp32c3', 'target', (pytest.mark.generic,)), + ('esp32', 'qemu', (pytest.mark.host_test, pytest.mark.qemu)), + ], + indirect=['target'], ) def test_console_help_verbose_level_0(dut: Dut, test_on: str) -> None: help_verbose_info = 'Print the summary of all registered commands if no arguments are given,' @@ -200,18 +175,16 @@ def test_console_help_verbose_level_0(dut: Dut, test_on: str) -> None: dut.expect_exact('help', not_matching=help_verbose_info) -@pytest.mark.parametrize( - 'config', [ - pytest.param('defaults'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), - pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), - pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), - ] +@idf_parametrize('config', ['defaults'], indirect=['config']) +@idf_parametrize( + 'target,test_on,markers', + [ + ('linux', 'host', (pytest.mark.host_test,)), + ('esp32', 'target', (pytest.mark.generic,)), + ('esp32c3', 'target', (pytest.mark.generic,)), + ('esp32', 'qemu', (pytest.mark.host_test, pytest.mark.qemu)), + ], + indirect=['target'], ) def test_console_help_verbose_level_1(dut: Dut, test_on: str) -> None: help_verbose_info = 'Print the summary of all registered commands if no arguments are given,' @@ -223,18 +196,16 @@ def test_console_help_verbose_level_1(dut: Dut, test_on: str) -> None: dut.expect_exact(help_verbose_info) -@pytest.mark.parametrize( - 'config', [ - pytest.param('defaults'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), - pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), - pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), - ] +@idf_parametrize('config', ['defaults'], indirect=['config']) +@idf_parametrize( + 'target,test_on,markers', + [ + ('linux', 'host', (pytest.mark.host_test,)), + ('esp32', 'target', (pytest.mark.generic,)), + ('esp32c3', 'target', (pytest.mark.generic,)), + ('esp32', 'qemu', (pytest.mark.host_test, pytest.mark.qemu)), + ], + indirect=['target'], ) def test_console_help_verbose_subcommand(dut: Dut, test_on: str) -> None: help_verbose_info = 'Print the summary of all registered commands if no arguments are given,' @@ -244,24 +215,23 @@ def test_console_help_verbose_subcommand(dut: Dut, test_on: str) -> None: # verify help --verbose=0 subcommand dut.write('help --verbose=0') dut.write('help --verbose=0') - dut.expect_exact('help --verbose=0',not_matching=help_verbose_info) + dut.expect_exact('help --verbose=0', not_matching=help_verbose_info) # verify help --verbose=1 subcommand dut.write('help --verbose=1') dut.expect_exact(help_verbose_info) -@pytest.mark.parametrize( - 'config', [ - pytest.param('defaults'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.esp32c3, pytest.mark.generic]), - pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), - ] +@idf_parametrize('config', ['defaults'], indirect=['config']) +@idf_parametrize( + 'target,test_on,markers', + [ + ('linux', 'host', (pytest.mark.host_test,)), + ('esp32', 'target', (pytest.mark.generic,)), + ('esp32c3', 'target', (pytest.mark.generic,)), + ('esp32', 'qemu', (pytest.mark.host_test, pytest.mark.qemu)), + ], + indirect=['target'], ) def test_console_help_deregister(dut: Dut, test_on: str) -> None: dut.expect_exact('Press ENTER to see the list of tests') @@ -275,17 +245,16 @@ def test_console_help_deregister(dut: Dut, test_on: str) -> None: dut.expect_exact(cmd_z_description, not_matching=cmd_a_description) -@pytest.mark.parametrize( - 'config', [ - pytest.param('defaults'), - ] -) -@pytest.mark.parametrize( - 'test_on', [ - pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.esp32c3, pytest.mark.generic]), - pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), - ] +@idf_parametrize('config', ['defaults'], indirect=['config']) +@idf_parametrize( + 'target,test_on,markers', + [ + ('linux', 'host', (pytest.mark.host_test,)), + ('esp32', 'target', (pytest.mark.generic,)), + ('esp32c3', 'target', (pytest.mark.generic,)), + ('esp32', 'qemu', (pytest.mark.host_test, pytest.mark.qemu)), + ], + indirect=['target'], ) def test_console_help_re_register(dut: Dut, test_on: str) -> None: dut.expect_exact('Press ENTER to see the list of tests') diff --git a/components/cxx/test_apps/exception/pytest_cxx_exception.py b/components/cxx/test_apps/exception/pytest_cxx_exception.py index f270c017f5..28b67253a6 100644 --- a/components/cxx/test_apps/exception/pytest_cxx_exception.py +++ b/components/cxx/test_apps/exception/pytest_cxx_exception.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_cxx_exception(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/cxx/test_apps/exception_no_except/pytest_cxx_exception_no_except.py b/components/cxx/test_apps/exception_no_except/pytest_cxx_exception_no_except.py index ee825df7a1..697831b313 100644 --- a/components/cxx/test_apps/exception_no_except/pytest_cxx_exception_no_except.py +++ b/components/cxx/test_apps/exception_no_except/pytest_cxx_exception_no_except.py @@ -1,13 +1,12 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_cxx_noexcept_out_of_range(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('1') @@ -15,9 +14,8 @@ def test_cxx_noexcept_out_of_range(dut: Dut) -> None: dut.expect_exact('Rebooting...') -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_cxx_noexcept_bad_alloc(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('2') diff --git a/components/cxx/test_apps/general/pytest_cxx_general.py b/components/cxx/test_apps/general/pytest_cxx_general.py index 0ba975526b..dfecf85d70 100644 --- a/components/cxx/test_apps/general/pytest_cxx_general.py +++ b/components/cxx/test_apps/general/pytest_cxx_general.py @@ -1,36 +1,31 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -configurations = [ - 'noexcept', - 'exceptions_rtti' -] +configurations = ['noexcept', 'exceptions_rtti'] -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic @pytest.mark.parametrize('config', configurations, indirect=True) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_cxx_static_init_non_pod(dut: Dut) -> None: dut.run_all_single_board_cases(name=['can use static initializers for non-POD types']) -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic @pytest.mark.parametrize('config', configurations, indirect=True) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_cxx_misc(dut: Dut) -> None: dut.run_all_single_board_cases(group='misc') -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic @pytest.mark.parametrize('config', configurations, indirect=True) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_cxx_stack_smash(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') - dut.write('\"stack smashing protection CXX\"') + dut.write('"stack smashing protection CXX"') dut.expect_exact('Stack smashing protect failure!') dut.expect_exact('Rebooting...') diff --git a/components/cxx/test_apps/rtti/pytest_cxx_rtti.py b/components/cxx/test_apps/rtti/pytest_cxx_rtti.py index a5217c66d7..4fa9681663 100644 --- a/components/cxx/test_apps/rtti/pytest_cxx_rtti.py +++ b/components/cxx/test_apps/rtti/pytest_cxx_rtti.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_cxx_rtti(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/driver/test_apps/dac_test_apps/legacy_dac_driver/pytest_legacy_dac.py b/components/driver/test_apps/dac_test_apps/legacy_dac_driver/pytest_legacy_dac.py index 89e8486cd4..38274ca7ac 100644 --- a/components/driver/test_apps/dac_test_apps/legacy_dac_driver/pytest_legacy_dac.py +++ b/components/driver/test_apps/dac_test_apps/legacy_dac_driver/pytest_legacy_dac.py @@ -1,12 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -15,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target']) def test_legacy_dac(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac/pytest_legacy_i2s_adc_dac.py b/components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac/pytest_legacy_i2s_adc_dac.py index 59b4de2b1e..3c4095b524 100644 --- a/components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac/pytest_legacy_i2s_adc_dac.py +++ b/components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac/pytest_legacy_i2s_adc_dac.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,6 +13,7 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_i2s_adc_dac(dut: Dut) -> None: # ADC_DMA_read test takes more than 30 sec dut.run_all_single_board_cases(timeout=60) diff --git a/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/pytest_legacy_i2s.py b/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/pytest_legacy_i2s.py index bb70f8ee6a..96e9e0ec69 100644 --- a/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/pytest_legacy_i2s.py +++ b/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/pytest_legacy_i2s.py @@ -1,18 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -21,5 +13,10 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32c3', 'esp32c5', 'esp32s3', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c61'], + indirect=['target'], +) def test_legacy_i2s(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/driver/test_apps/legacy_adc_driver/pytest_legacy_adc.py b/components/driver/test_apps/legacy_adc_driver/pytest_legacy_adc.py index 064d9449ab..454a551a88 100644 --- a/components/driver/test_apps/legacy_adc_driver/pytest_legacy_adc.py +++ b/components/driver/test_apps/legacy_adc_driver/pytest_legacy_adc.py @@ -1,17 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32c5 -@pytest.mark.esp32p4 @pytest.mark.adc @pytest.mark.parametrize( 'config', @@ -20,11 +13,15 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32c5', 'esp32p4'], + indirect=['target'], +) def test_legacy_adc(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c2 @pytest.mark.adc @pytest.mark.xtal_26mhz @pytest.mark.parametrize( @@ -34,5 +31,6 @@ def test_legacy_adc(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_legacy_adc_esp32c2_xtal_26mhz(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/driver/test_apps/legacy_i2c_driver/pytest_i2c_legacy.py b/components/driver/test_apps/legacy_i2c_driver/pytest_i2c_legacy.py index 4ec552ee8f..ae1d94ae85 100644 --- a/components/driver/test_apps/legacy_i2c_driver/pytest_i2c_legacy.py +++ b/components/driver/test_apps/legacy_i2c_driver/pytest_i2c_legacy.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,43 +14,46 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_i2c_legacy(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic_multi_device @pytest.mark.parametrize( 'count, config', [ - (2, 'defaults',), + ( + 2, + 'defaults', + ), ], - indirect=True + indirect=True, ) -def test_i2c_multi_dev_legacy(case_tester) -> None: # type: ignore +@idf_parametrize( + 'target', + ['esp32', 'esp32c3', 'esp32c6', 'esp32c5', 'esp32h2', 'esp32p4', 'esp32s2', 'esp32s3'], + indirect=['target'], +) +def test_i2c_multi_dev_legacy(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True, timeout=120) -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.generic_multi_device @pytest.mark.parametrize( 'count, config', [ - (2, 'sleep_retention',), + ( + 2, + 'sleep_retention', + ), ], - indirect=True + indirect=True, ) -def test_i2c_sleep_retention_legacy(case_tester) -> None: # type: ignore +@idf_parametrize('target', ['esp32c6', 'esp32h2'], indirect=['target']) +def test_i2c_sleep_retention_legacy(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True, timeout=250) diff --git a/components/driver/test_apps/legacy_mcpwm_driver/pytest_legacy_mcpwm.py b/components/driver/test_apps/legacy_mcpwm_driver/pytest_legacy_mcpwm.py index a8a9e25bd1..6a81ba98f1 100644 --- a/components/driver/test_apps/legacy_mcpwm_driver/pytest_legacy_mcpwm.py +++ b/components/driver/test_apps/legacy_mcpwm_driver/pytest_legacy_mcpwm.py @@ -1,15 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -18,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) def test_legacy_mcpwm(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/driver/test_apps/legacy_pcnt_driver/pytest_legacy_pcnt.py b/components/driver/test_apps/legacy_pcnt_driver/pytest_legacy_pcnt.py index 46eddeb18e..29246133c1 100644 --- a/components/driver/test_apps/legacy_pcnt_driver/pytest_legacy_pcnt.py +++ b/components/driver/test_apps/legacy_pcnt_driver/pytest_legacy_pcnt.py @@ -1,16 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -19,5 +13,8 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target'] +) def test_legacy_pcnt(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=240) diff --git a/components/driver/test_apps/legacy_rmt_driver/pytest_legacy_rmt_driver.py b/components/driver/test_apps/legacy_rmt_driver/pytest_legacy_rmt_driver.py index 654b4a06b1..d3cf3cf104 100644 --- a/components/driver/test_apps/legacy_rmt_driver/pytest_legacy_rmt_driver.py +++ b/components/driver/test_apps/legacy_rmt_driver/pytest_legacy_rmt_driver.py @@ -1,20 +1,22 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'release', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], + indirect=['target'], +) def test_legacy_rmt(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) diff --git a/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py b/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py index ae8d5d0fe5..d8622ec317 100644 --- a/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py +++ b/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py @@ -1,20 +1,22 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'release', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5'], + indirect=['target'], +) def test_legacy_temp_sensor_driver(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) diff --git a/components/driver/test_apps/legacy_sigma_delta_driver/pytest_legacy_sigma_delta.py b/components/driver/test_apps/legacy_sigma_delta_driver/pytest_legacy_sigma_delta.py index 30b41ab229..12673594d9 100644 --- a/components/driver/test_apps/legacy_sigma_delta_driver/pytest_legacy_sigma_delta.py +++ b/components/driver/test_apps/legacy_sigma_delta_driver/pytest_legacy_sigma_delta.py @@ -1,23 +1,22 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', [ 'release', ], - indirect=True) + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32p4'], + indirect=['target'], +) def test_legacy_sigma_delta(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='sigma_delta') diff --git a/components/driver/test_apps/legacy_timer_driver/pytest_legacy_timer_driver.py b/components/driver/test_apps/legacy_timer_driver/pytest_legacy_timer_driver.py index 726f05adc7..09733d82a1 100644 --- a/components/driver/test_apps/legacy_timer_driver/pytest_legacy_timer_driver.py +++ b/components/driver/test_apps/legacy_timer_driver/pytest_legacy_timer_driver.py @@ -1,13 +1,18 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'release', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_legacy_timer_driver(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) diff --git a/components/driver/test_apps/touch_sensor_v1/pytest_touch_sensor_v1.py b/components/driver/test_apps/touch_sensor_v1/pytest_touch_sensor_v1.py index 368fa6cca2..97745c7103 100644 --- a/components/driver/test_apps/touch_sensor_v1/pytest_touch_sensor_v1.py +++ b/components/driver/test_apps/touch_sensor_v1/pytest_touch_sensor_v1.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -13,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_touch_sensor_v1(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=60) diff --git a/components/driver/test_apps/touch_sensor_v2/pytest_touch_sensor_v2.py b/components/driver/test_apps/touch_sensor_v2/pytest_touch_sensor_v2.py index 3f03441018..368ddda0dd 100644 --- a/components/driver/test_apps/touch_sensor_v2/pytest_touch_sensor_v2.py +++ b/components/driver/test_apps/touch_sensor_v2/pytest_touch_sensor_v2.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_touch_sensor_v2(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) diff --git a/components/driver/test_apps/twai/pytest_twai.py b/components/driver/test_apps/twai/pytest_twai.py index b35b97a674..688ba267e7 100644 --- a/components/driver/test_apps/twai/pytest_twai.py +++ b/components/driver/test_apps/twai/pytest_twai.py @@ -8,15 +8,9 @@ import pytest from can import Bus from can import Message from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -25,6 +19,9 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32p4'], indirect=['target'] +) def test_twai_self(dut: Dut) -> None: dut.run_all_single_board_cases(group='twai-loop-back') @@ -36,18 +33,11 @@ def fixture_create_socket_can() -> Bus: stop_command = 'sudo ip link set can0 down' subprocess.run(start_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) bus = Bus(interface='socketcan', channel='can0', bitrate=250000) - yield bus # test invoked here + yield bus # test invoked here bus.shutdown() subprocess.run(stop_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.twai_std @pytest.mark.parametrize( 'config', @@ -56,6 +46,9 @@ def fixture_create_socket_can() -> Bus: ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32p4'], indirect=['target'] +) def test_twai_listen_only(dut: Dut, socket_can: Bus) -> None: dut.expect_exact('Press ENTER to see the list of tests') @@ -74,13 +67,6 @@ def test_twai_listen_only(dut: Dut, socket_can: Bus) -> None: dut.expect_unity_test_output() -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.twai_std @pytest.mark.parametrize( 'config', @@ -89,6 +75,9 @@ def test_twai_listen_only(dut: Dut, socket_can: Bus) -> None: ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32p4'], indirect=['target'] +) def test_twai_remote_request(dut: Dut, socket_can: Bus) -> None: dut.expect_exact('Press ENTER to see the list of tests') diff --git a/components/efuse/test_apps/pytest_efuse.py b/components/efuse/test_apps/pytest_efuse.py index f746d5cd98..4ca945ab5b 100644 --- a/components/efuse/test_apps/pytest_efuse.py +++ b/components/efuse/test_apps/pytest_efuse.py @@ -1,24 +1,27 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32s2', 'esp32s3'], reason='eFuse for S2 and S3 is similar to the C3 chip, so testing on C3 is enough') +@pytest.mark.temp_skip_ci( + targets=['esp32s2', 'esp32s3'], reason='eFuse for S2 and S3 is similar to the C3 chip, so testing on C3 is enough' +) @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_efuse(dut: Dut) -> None: dut.run_all_single_board_cases() @pytest.mark.qemu -@pytest.mark.esp32 @pytest.mark.host_test +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_efuse_qemu(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_efuse_linux(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=60) diff --git a/components/esp-tls/test_apps/pytest_esp-tls.py b/components/esp-tls/test_apps/pytest_esp-tls.py index 37acd0be3e..6f666a12ff 100644 --- a/components/esp-tls/test_apps/pytest_esp-tls.py +++ b/components/esp-tls/test_apps/pytest_esp-tls.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_tls(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_adc/test_apps/adc/pytest_adc.py b/components/esp_adc/test_apps/adc/pytest_adc.py index 3339a576f0..77d91d9fbc 100644 --- a/components/esp_adc/test_apps/adc/pytest_adc.py +++ b/components/esp_adc/test_apps/adc/pytest_adc.py @@ -1,29 +1,22 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32c5 -@pytest.mark.esp32p4 @pytest.mark.adc -@pytest.mark.parametrize('config', [ - 'iram_safe', - 'release', - 'pm_enable' -], indirect=True) +@pytest.mark.parametrize('config', ['iram_safe', 'release', 'pm_enable'], indirect=True) +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32c5', 'esp32p4'], + indirect=['target'], +) def test_adc(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120, reset=True) # No PM test, as C2 doesn't support ADC continuous mode -@pytest.mark.esp32c2 @pytest.mark.adc @pytest.mark.xtal_26mhz @pytest.mark.parametrize( @@ -34,5 +27,6 @@ def test_adc(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_adc_esp32c2_xtal_26mhz(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120, reset=True) diff --git a/components/esp_app_format/test_apps/pytest_esp_app_format.py b/components/esp_app_format/test_apps/pytest_esp_app_format.py index 1c0a3e90d3..a090183195 100644 --- a/components/esp_app_format/test_apps/pytest_esp_app_format.py +++ b/components/esp_app_format/test_apps/pytest_esp_app_format.py @@ -1,18 +1,17 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32c3'], indirect=['target']) def test_esp_app_format(dut: Dut) -> None: dut.expect_unity_test_output() -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_esp_app_format_linux(dut: Dut) -> None: dut.expect_unity_test_output() diff --git a/components/esp_bootloader_format/test_apps/pytest_esp_bootloader_format.py b/components/esp_bootloader_format/test_apps/pytest_esp_bootloader_format.py index fa4d7a7f3a..5fb4011f07 100644 --- a/components/esp_bootloader_format/test_apps/pytest_esp_bootloader_format.py +++ b/components/esp_bootloader_format/test_apps/pytest_esp_bootloader_format.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_bootloader_format(dut: Dut) -> None: dut.expect_unity_test_output() diff --git a/components/esp_common/test_apps/esp_common/pytest_esp_common.py b/components/esp_common/test_apps/esp_common/pytest_esp_common.py index aa47cf812f..4254a14372 100644 --- a/components/esp_common/test_apps/esp_common/pytest_esp_common.py +++ b/components/esp_common/test_apps/esp_common/pytest_esp_common.py @@ -1,30 +1,24 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 from typing import Any import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.supported_targets @pytest.mark.parametrize( 'config', - [ - 'default' - ], + ['default'], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_common(dut: Dut) -> None: dut.run_all_single_board_cases() # psram noinit attr tests with psram enabled -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -33,35 +27,24 @@ def test_esp_common(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32p4', 'esp32c5'], indirect=['target']) def test_esp_attr_psram_noinit(dut: Dut) -> None: dut.run_all_single_board_cases() # psram noinit memory tests with psram enabled -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.generic -@pytest.mark.supported_targets @pytest.mark.parametrize( 'config', - [ - 'psram_noinit' - ], + ['psram_noinit'], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_attr_psram_noinit_multiple_stages(case_tester: Any) -> None: case_tester.run_all_multi_stage_cases() # psram attr tests with psram enabled -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -70,47 +53,42 @@ def test_esp_attr_psram_noinit_multiple_stages(case_tester: Any) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32p4', 'esp32c5'], indirect=['target']) def test_esp_attr_psram(dut: Dut) -> None: dut.run_all_single_board_cases() # psram attr tests with xip_psram -@pytest.mark.esp32s2 @pytest.mark.generic @pytest.mark.parametrize( 'config', - [ - 'xip_psram_esp32s2' - ], + ['xip_psram_esp32s2'], indirect=True, ) +@idf_parametrize('target', ['esp32s2'], indirect=['target']) def test_esp_attr_xip_psram_esp32s2(dut: Dut) -> None: dut.run_all_single_board_cases() # psram attr tests with xip_psram -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize( 'config', - [ - 'xip_psram_esp32s3' - ], + ['xip_psram_esp32s3'], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_esp_attr_xip_psram_esp32s3(dut: Dut) -> None: dut.run_all_single_board_cases() # psram attr tests with xip_psram -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', - [ - 'xip_psram_esp32p4' - ], + ['xip_psram_esp32p4'], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_esp_attr_xip_psram_esp32p4(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_ana_cmpr/test_apps/analog_comparator/pytest_ana_cmpr.py b/components/esp_driver_ana_cmpr/test_apps/analog_comparator/pytest_ana_cmpr.py index 020ff3713e..67bdbe74b2 100644 --- a/components/esp_driver_ana_cmpr/test_apps/analog_comparator/pytest_ana_cmpr.py +++ b/components/esp_driver_ana_cmpr/test_apps/analog_comparator/pytest_ana_cmpr.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -15,5 +14,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32h2', 'esp32p4'], indirect=['target']) def test_ana_cmpr(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_cam/test_apps/csi/pytest_csi.py b/components/esp_driver_cam/test_apps/csi/pytest_csi.py index 07510eac36..77e871877c 100644 --- a/components/esp_driver_cam/test_apps/csi/pytest_csi.py +++ b/components/esp_driver_cam/test_apps/csi/pytest_csi.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_csi(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_cam/test_apps/isp_dvp/pytest_isp_dvp.py b/components/esp_driver_cam/test_apps/isp_dvp/pytest_isp_dvp.py index a9922987c5..f7600b579d 100644 --- a/components/esp_driver_cam/test_apps/isp_dvp/pytest_isp_dvp.py +++ b/components/esp_driver_cam/test_apps/isp_dvp/pytest_isp_dvp.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_isp_dvp(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_dac/test_apps/dac/pytest_dac.py b/components/esp_driver_dac/test_apps/dac/pytest_dac.py index 3caf0085f0..a4e2fa0570 100644 --- a/components/esp_driver_dac/test_apps/dac/pytest_dac.py +++ b/components/esp_driver_dac/test_apps/dac/pytest_dac.py @@ -1,12 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -16,5 +14,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target']) def test_dac(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_gpio/test_apps/gpio/pytest_gpio.py b/components/esp_driver_gpio/test_apps/gpio/pytest_gpio.py index bb0a48d5c4..f9177b3f3c 100644 --- a/components/esp_driver_gpio/test_apps/gpio/pytest_gpio.py +++ b/components/esp_driver_gpio/test_apps/gpio/pytest_gpio.py @@ -1,7 +1,8 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize CONFIGS = [ 'iram_safe', @@ -9,21 +10,17 @@ CONFIGS = [ ] -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_gpio(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='gpio') -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.generic @pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5'], indirect=['target'] +) def test_rtc_io(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='rtcio') diff --git a/components/esp_driver_gpio/test_apps/gpio_extensions/pytest_gpio_extensions.py b/components/esp_driver_gpio/test_apps/gpio_extensions/pytest_gpio_extensions.py index df1ec8260a..fdf4edc6d4 100644 --- a/components/esp_driver_gpio/test_apps/gpio_extensions/pytest_gpio_extensions.py +++ b/components/esp_driver_gpio/test_apps/gpio_extensions/pytest_gpio_extensions.py @@ -1,7 +1,8 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize CONFIGS = [ 'iram_safe', @@ -9,42 +10,30 @@ CONFIGS = [ ] -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize( + 'target', + ['esp32c2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32p4'], + indirect=['target'], +) def test_gpio_filter(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='gpio_filter') -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize( + 'target', + ['esp32c2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32p4'], + indirect=['target'], +) def test_dedic_gpio(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='dedic_gpio') -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], indirect=['target']) def test_gpio_etm(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='gpio_etm') diff --git a/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py b/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py index 178619615c..d081097f68 100644 --- a/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py +++ b/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -15,11 +14,11 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_gptimer(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c2 @pytest.mark.generic @pytest.mark.xtal_26mhz @pytest.mark.parametrize( @@ -29,5 +28,6 @@ def test_gptimer(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_gptimer_esp32c2_xtal_26mhz(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py b/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py index 7840f8d32e..b5b0bd880b 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,30 +14,40 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_i2c(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic_multi_device @pytest.mark.parametrize( 'count, config', [ - (2, 'defaults',), - (2, 'release',), - (2, 'iram_safe',), - (2, 'slave_v2',), + ( + 2, + 'defaults', + ), + ( + 2, + 'release', + ), + ( + 2, + 'iram_safe', + ), + ( + 2, + 'slave_v2', + ), ], - indirect=True + indirect=True, ) -def test_i2c_multi_device(case_tester) -> None: # type: ignore +@idf_parametrize( + 'target', + ['esp32', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32s2', 'esp32s3'], + indirect=['target'], +) +def test_i2c_multi_device(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True) diff --git a/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py b/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py index 138769c594..64332d4d27 100644 --- a/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py +++ b/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py @@ -1,18 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32s3 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -22,5 +14,10 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32s3', 'esp32h2', 'esp32p4', 'esp32c61'], + indirect=['target'], +) def test_i2s(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_i2s/test_apps/i2s_multi_dev/pytest_i2s_multi_dev.py b/components/esp_driver_i2s/test_apps/i2s_multi_dev/pytest_i2s_multi_dev.py index 000bb65e39..07683bb4ff 100644 --- a/components/esp_driver_i2s/test_apps/i2s_multi_dev/pytest_i2s_multi_dev.py +++ b/components/esp_driver_i2s/test_apps/i2s_multi_dev/pytest_i2s_multi_dev.py @@ -1,17 +1,17 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic_multi_device -@pytest.mark.parametrize('count', [ - 2, -], indirect=True) +@pytest.mark.parametrize( + 'count', + [ + 2, + ], + indirect=True, +) +@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) def test_i2s_multi_dev(case_tester) -> None: # type: ignore case_tester.run_all_multi_dev_cases(reset=True, timeout=30) diff --git a/components/esp_driver_i2s/test_apps/lp_i2s/pytest_lp_i2s.py b/components/esp_driver_i2s/test_apps/lp_i2s/pytest_lp_i2s.py index 25b21b0be9..1a900694b3 100644 --- a/components/esp_driver_i2s/test_apps/lp_i2s/pytest_lp_i2s.py +++ b/components/esp_driver_i2s/test_apps/lp_i2s/pytest_lp_i2s.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.lp_i2s @pytest.mark.parametrize( 'config', @@ -13,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_lp_i2s(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=200) diff --git a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/pytest_jpeg.py b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/pytest_jpeg.py index cdd75ead6a..cce6ce38d0 100644 --- a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/pytest_jpeg.py +++ b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/pytest_jpeg.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -13,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_jpeg(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py index 22687a67fc..4ba9f73c98 100644 --- a/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py +++ b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32s3'], - reason='skip due to duplication with test_ledc_psram') +@pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='skip due to duplication with test_ledc_psram') @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -16,11 +15,11 @@ from pytest_embedded_idf import IdfDut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_ledc(dut: IdfDut) -> None: dut.run_all_single_board_cases(reset=True) -@pytest.mark.esp32s3 @pytest.mark.octal_psram @pytest.mark.parametrize( 'config', @@ -30,21 +29,29 @@ def test_ledc(dut: IdfDut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_ledc_psram(dut: IdfDut) -> None: dut.run_all_single_board_cases(reset=True) -@pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32s3', 'esp32c61'], - reason='s3 multi device runner has no psram, c61 lack of runner IDF-10949') +@pytest.mark.temp_skip_ci( + targets=['esp32s3', 'esp32c61'], reason='s3 multi device runner has no psram, c61 lack of runner IDF-10949' +) @pytest.mark.generic_multi_device @pytest.mark.parametrize( 'count, config', [ - (2, 'iram_safe',), - (2, 'release',), + ( + 2, + 'iram_safe', + ), + ( + 2, + 'release', + ), ], - indirect=True + indirect=True, ) -def test_ledc_multi_device(case_tester) -> None: # type: ignore +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_ledc_multi_device(case_tester) -> None: # type: ignore case_tester.run_all_multi_dev_cases(reset=True) diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py b/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py index 8fde6c768c..4d66a3f069 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py @@ -1,15 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -19,5 +14,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) def test_mcpwm(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py b/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py index 3db44388b6..ed600ce33b 100644 --- a/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py +++ b/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py @@ -1,13 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -17,5 +14,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) def test_parlio(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_pcnt/test_apps/pulse_cnt/pytest_pulse_cnt.py b/components/esp_driver_pcnt/test_apps/pulse_cnt/pytest_pulse_cnt.py index 04566c1d5d..c20419bb2f 100644 --- a/components/esp_driver_pcnt/test_apps/pulse_cnt/pytest_pulse_cnt.py +++ b/components/esp_driver_pcnt/test_apps/pulse_cnt/pytest_pulse_cnt.py @@ -1,16 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -20,5 +14,8 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target'] +) def test_pulse_cnt(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_ppa/test_apps/pytest_ppa.py b/components/esp_driver_ppa/test_apps/pytest_ppa.py index 534d32cee1..bc0b85339b 100644 --- a/components/esp_driver_ppa/test_apps/pytest_ppa.py +++ b/components/esp_driver_ppa/test_apps/pytest_ppa.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -13,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_ppa(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py b/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py index cae5747513..09eb0f99bf 100644 --- a/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py +++ b/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py @@ -1,16 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -20,11 +14,13 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target'] +) def test_rmt(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s3 @pytest.mark.octal_psram @pytest.mark.parametrize( 'config', @@ -34,5 +30,6 @@ def test_rmt(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_rmt_psram(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/pytest_sdio.py b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/pytest_sdio.py index 1e123bd929..39da718262 100644 --- a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/pytest_sdio.py +++ b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/pytest_sdio.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os.path from typing import List @@ -16,8 +16,18 @@ def parameter_expand(existing_parameters: List[List[str]], value_list: List[str] return ret -esp32_32_param = [[f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', 'esp32|esp32']] -esp32_c6_param = [[f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', 'esp32|esp32c6']] +esp32_32_param = [ + [ + f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', + 'esp32|esp32', + ] +] +esp32_c6_param = [ + [ + f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', + 'esp32|esp32c6', + ] +] esp32_param_default = [pytest.param(*param) for param in parameter_expand(esp32_32_param, ['default|default'])] c6_param_default = [pytest.param(*param) for param in parameter_expand(esp32_c6_param, ['default|default'])] @@ -26,7 +36,7 @@ c6_param_retention = [pytest.param(*param) for param in parameter_expand(esp32_c # Normal tests -def test_sdio_flow(dut:Tuple[IdfDut, IdfDut]) -> None: +def test_sdio_flow(dut: Tuple[IdfDut, IdfDut]) -> None: dut[1].expect('Press ENTER to see the list of tests') dut[1].write('[sdio]') dut[1].expect('test_sdio: slave ready') @@ -38,24 +48,34 @@ def test_sdio_flow(dut:Tuple[IdfDut, IdfDut]) -> None: dut[0].expect_unity_test_output() -@pytest.mark.esp32c6 @pytest.mark.sdio_multidev_32_c6 -@pytest.mark.parametrize('count', [2,], indirect=True) +@pytest.mark.parametrize( + 'count', + [ + 2, + ], + indirect=True, +) @pytest.mark.parametrize('app_path, target, config', c6_param_default, indirect=True) -def test_sdio_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: +def test_sdio_esp32_esp32c6(dut: Tuple[IdfDut, IdfDut]) -> None: test_sdio_flow(dut) -@pytest.mark.esp32 @pytest.mark.sdio_master_slave -@pytest.mark.parametrize('count', [2,], indirect=True) +@pytest.mark.parametrize( + 'count', + [ + 2, + ], + indirect=True, +) @pytest.mark.parametrize('app_path, target, config', esp32_param_default, indirect=True) -def test_sdio_esp32_esp32(dut:Tuple[IdfDut, IdfDut]) -> None: +def test_sdio_esp32_esp32(dut: Tuple[IdfDut, IdfDut]) -> None: test_sdio_flow(dut) # From host speed tests -def test_sdio_speed_frhost_flow(dut:Tuple[IdfDut, IdfDut], expected_4b_speed:int, expected_1b_speed:int) -> None: +def test_sdio_speed_frhost_flow(dut: Tuple[IdfDut, IdfDut], expected_4b_speed: int, expected_1b_speed: int) -> None: dut[1].expect('Press ENTER to see the list of tests') dut[1].write('"SDIO_Slave: test from host (Performance)"') dut[1].expect('test_sdio: slave ready') @@ -66,32 +86,42 @@ def test_sdio_speed_frhost_flow(dut:Tuple[IdfDut, IdfDut], expected_4b_speed:int dut[0].expect('Probe using SD 4-bit') res = dut[0].expect(r'Throughput: compensated (\d+)') frhost_speed_4bit = res.group(1).decode('utf8') - assert (int(frhost_speed_4bit) > expected_4b_speed) + assert int(frhost_speed_4bit) > expected_4b_speed dut[0].expect('Probe using SD 1-bit') res = dut[0].expect(r'Throughput: compensated (\d+)') frhost_speed_1bit = res.group(1).decode('utf8') - assert (int(frhost_speed_1bit) > expected_1b_speed) + assert int(frhost_speed_1bit) > expected_1b_speed -@pytest.mark.esp32c6 @pytest.mark.sdio_multidev_32_c6 -@pytest.mark.parametrize('count', [2,], indirect=True) +@pytest.mark.parametrize( + 'count', + [ + 2, + ], + indirect=True, +) @pytest.mark.parametrize('app_path, target, config', c6_param_default, indirect=True) -def test_sdio_speed_frhost_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: +def test_sdio_speed_frhost_esp32_esp32c6(dut: Tuple[IdfDut, IdfDut]) -> None: test_sdio_speed_frhost_flow(dut, 10000, 4000) -@pytest.mark.esp32 @pytest.mark.sdio_master_slave -@pytest.mark.parametrize('count', [2,], indirect=True) +@pytest.mark.parametrize( + 'count', + [ + 2, + ], + indirect=True, +) @pytest.mark.parametrize('app_path, target, config', esp32_param_default, indirect=True) -def test_sdio_speed_frhost_esp32_esp32(dut:Tuple[IdfDut, IdfDut]) -> None: +def test_sdio_speed_frhost_esp32_esp32(dut: Tuple[IdfDut, IdfDut]) -> None: test_sdio_speed_frhost_flow(dut, 12200, 4000) # To host speed tests -def test_sdio_speed_tohost_flow(dut:Tuple[IdfDut, IdfDut], expected_4b_speed:int, expected_1b_speed:int) -> None: +def test_sdio_speed_tohost_flow(dut: Tuple[IdfDut, IdfDut], expected_4b_speed: int, expected_1b_speed: int) -> None: dut[1].expect('Press ENTER to see the list of tests') dut[1].write('"SDIO_Slave: test to host (Performance)"') dut[1].expect('test_sdio: slave ready') @@ -102,32 +132,42 @@ def test_sdio_speed_tohost_flow(dut:Tuple[IdfDut, IdfDut], expected_4b_speed:int dut[0].expect('Probe using SD 4-bit') res = dut[0].expect(r'Throughput: compensated (\d+)') tohost_speed_4bit = res.group(1).decode('utf8') - assert (int(tohost_speed_4bit) > expected_4b_speed) + assert int(tohost_speed_4bit) > expected_4b_speed dut[0].expect('Probe using SD 1-bit') res = dut[0].expect(r'Throughput: compensated (\d+)') tohost_speed_1bit = res.group(1).decode('utf8') - assert (int(tohost_speed_1bit) > expected_1b_speed) + assert int(tohost_speed_1bit) > expected_1b_speed -@pytest.mark.esp32c6 @pytest.mark.sdio_multidev_32_c6 -@pytest.mark.parametrize('count', [2,], indirect=True) +@pytest.mark.parametrize( + 'count', + [ + 2, + ], + indirect=True, +) @pytest.mark.parametrize('app_path, target, config', c6_param_default, indirect=True) -def test_sdio_speed_tohost_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: +def test_sdio_speed_tohost_esp32_esp32c6(dut: Tuple[IdfDut, IdfDut]) -> None: test_sdio_speed_tohost_flow(dut, 9000, 4000) -@pytest.mark.esp32 @pytest.mark.sdio_master_slave -@pytest.mark.parametrize('count', [2,], indirect=True) +@pytest.mark.parametrize( + 'count', + [ + 2, + ], + indirect=True, +) @pytest.mark.parametrize('app_path, target, config', esp32_param_default, indirect=True) -def test_sdio_speed_tohost_esp32_esp32(dut:Tuple[IdfDut, IdfDut]) -> None: +def test_sdio_speed_tohost_esp32_esp32(dut: Tuple[IdfDut, IdfDut]) -> None: test_sdio_speed_tohost_flow(dut, 12200, 4000) # Retention tests -def test_sdio_retention(dut:Tuple[IdfDut, IdfDut]) -> None: +def test_sdio_retention(dut: Tuple[IdfDut, IdfDut]) -> None: dut[1].expect('Press ENTER to see the list of tests') dut[1].write('[sdio_retention]') dut[1].expect('test_sdio: slave ready') @@ -139,9 +179,14 @@ def test_sdio_retention(dut:Tuple[IdfDut, IdfDut]) -> None: dut[0].expect_unity_test_output() -@pytest.mark.esp32c6 @pytest.mark.sdio_multidev_32_c6 -@pytest.mark.parametrize('count', [2,], indirect=True) +@pytest.mark.parametrize( + 'count', + [ + 2, + ], + indirect=True, +) @pytest.mark.parametrize('app_path, target, config', c6_param_retention, indirect=True) -def test_sdio_retention_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: +def test_sdio_retention_esp32_esp32c6(dut: Tuple[IdfDut, IdfDut]) -> None: test_sdio_retention(dut) diff --git a/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py b/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py index 0a464e7ab5..29c7de356f 100644 --- a/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py +++ b/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py @@ -1,7 +1,8 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize CONFIGS = [ 'iram_safe', @@ -9,16 +10,12 @@ CONFIGS = [ ] -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize( + 'target', + ['esp32', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32h2', 'esp32p4'], + indirect=['target'], +) def test_sdm(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='sdm') diff --git a/components/esp_driver_sdmmc/test_apps/sdmmc/pytest_sdmmc.py b/components/esp_driver_sdmmc/test_apps/sdmmc/pytest_sdmmc.py index 6feedee57e..14732597e9 100644 --- a/components/esp_driver_sdmmc/test_apps/sdmmc/pytest_sdmmc.py +++ b/components/esp_driver_sdmmc/test_apps/sdmmc/pytest_sdmmc.py @@ -1,13 +1,12 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.sdcard +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32p4'], indirect=['target']) def test_sdmmc(dut: IdfDut) -> None: # SDMMC driver can't be reinitialized if the test fails, # so we need to reset the board between tests to avoid failing diff --git a/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py b/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py index 723b9b08ab..dd632748cb 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py +++ b/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py @@ -1,15 +1,12 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C5 C61 GPSPI same, so testing on C5 is enough') -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.sdcard_spimode +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32c3', 'esp32p4', 'esp32c5'], indirect=['target']) def test_sdspi(dut: IdfDut) -> None: dut.run_all_single_board_cases(reset=True) diff --git a/components/esp_driver_spi/test_apps/master/pytest_spi_master.py b/components/esp_driver_spi/test_apps/master/pytest_spi_master.py index 691929a135..f877519b11 100644 --- a/components/esp_driver_spi/test_apps/master/pytest_spi_master.py +++ b/components/esp_driver_spi/test_apps/master/pytest_spi_master.py @@ -1,13 +1,23 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest - - +from pytest_embedded_idf.utils import idf_parametrize # If `test_env` is define, should not run on generic runner -@pytest.mark.supported_targets + + @pytest.mark.generic -@pytest.mark.parametrize('config', ['defaults', 'release', 'freertos_compliance', 'freertos_flash',], indirect=True) -def test_master_single_dev(case_tester) -> None: # type: ignore +@pytest.mark.parametrize( + 'config', + [ + 'defaults', + 'release', + 'freertos_compliance', + 'freertos_flash', + ], + indirect=True, +) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_master_single_dev(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if 'test_env' in case.attributes: continue @@ -15,10 +25,16 @@ def test_master_single_dev(case_tester) -> None: # type: ignore # Job for test_env `external_flash` just for esp32 only -@pytest.mark.esp32 @pytest.mark.flash_multi -@pytest.mark.parametrize('config', ['defaults',], indirect=True) -def test_master_esp_flash(case_tester) -> None: # type: ignore +@pytest.mark.parametrize( + 'config', + [ + 'defaults', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) +def test_master_esp_flash(case_tester) -> None: # type: ignore for case in case_tester.test_menu: # test case `spi_bus_lock_with_flash` use difference test env if case.attributes.get('test_env') == 'external_flash': @@ -28,20 +44,32 @@ def test_master_esp_flash(case_tester) -> None: # type: ignore # if `test_env` not defined, will run on `generic_multi_device` by default # TODO: [ESP32C61] IDF-10949 @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='no multi-dev runner') -@pytest.mark.supported_targets @pytest.mark.generic_multi_device @pytest.mark.parametrize( 'count, config', [ - (2, 'defaults',), - (2, 'release',), - (2, 'freertos_compliance',), - (2, 'freertos_flash',), + ( + 2, + 'defaults', + ), + ( + 2, + 'release', + ), + ( + 2, + 'freertos_compliance', + ), + ( + 2, + 'freertos_flash', + ), (2, 'iram_safe'), ], - indirect=True + indirect=True, ) -def test_master_multi_dev(case_tester) -> None: # type: ignore +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_master_multi_dev(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True) diff --git a/components/esp_driver_spi/test_apps/param/pytest_spi_param.py b/components/esp_driver_spi/test_apps/param/pytest_spi_param.py index d7df696410..c5ce4aa6f3 100644 --- a/components/esp_driver_spi/test_apps/param/pytest_spi_param.py +++ b/components/esp_driver_spi/test_apps/param/pytest_spi_param.py @@ -1,12 +1,13 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest - - +from pytest_embedded_idf.utils import idf_parametrize # If `test_env` is define, should not run on generic runner -@pytest.mark.supported_targets + + @pytest.mark.generic -def test_param_single_dev(case_tester) -> None: # type: ignore +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_param_single_dev(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if 'test_env' in case.attributes: continue @@ -16,10 +17,16 @@ def test_param_single_dev(case_tester) -> None: # type: ignore # if `test_env` not defined, will run on `generic_multi_device` by default # TODO: [ESP32C61] IDF-10949 @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='no multi-dev runner') -@pytest.mark.supported_targets @pytest.mark.generic_multi_device -@pytest.mark.parametrize('count', [2,], indirect=True) -def test_param_multi_dev(case_tester) -> None: # type: ignore +@pytest.mark.parametrize( + 'count', + [ + 2, + ], + indirect=True, +) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_param_multi_dev(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True) diff --git a/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py b/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py index 5b9f8823dc..fde2151a64 100644 --- a/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py +++ b/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py @@ -1,13 +1,20 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest - - +from pytest_embedded_idf.utils import idf_parametrize # If `test_env` is define, should not run on generic runner -@pytest.mark.supported_targets + + @pytest.mark.generic -@pytest.mark.parametrize('config', ['defaults',], indirect=True) -def test_slave_single_dev(case_tester) -> None: # type: ignore +@pytest.mark.parametrize( + 'config', + [ + 'defaults', + ], + indirect=True, +) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_slave_single_dev(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if 'test_env' in case.attributes: continue @@ -17,10 +24,10 @@ def test_slave_single_dev(case_tester) -> None: # type: ignore # if `test_env` not defined, will run on `generic_multi_device` by default # TODO: [ESP32C61] IDF-10949 @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='no multi-dev runner') -@pytest.mark.supported_targets @pytest.mark.generic_multi_device @pytest.mark.parametrize('count, config', [(2, 'defaults'), (2, 'iram_safe')], indirect=True) -def test_slave_multi_dev(case_tester) -> None: # type: ignore +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_slave_multi_dev(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True) diff --git a/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py b/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py index 5d09b75f06..53e7ee3b8e 100644 --- a/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py +++ b/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py @@ -1,20 +1,17 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest - - +from pytest_embedded_idf.utils import idf_parametrize # If `test_env` is define, should not run on generic runner -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 + + @pytest.mark.generic -def test_slave_hd_single_dev(case_tester) -> None: # type: ignore +@idf_parametrize( + 'target', + ['esp32s2', 'esp32s3', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], + indirect=['target'], +) +def test_slave_hd_single_dev(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if 'test_env' in case.attributes: continue @@ -22,17 +19,20 @@ def test_slave_hd_single_dev(case_tester) -> None: # type: ignore # if `test_env` not defined, will run on `generic_multi_device` by default -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic_multi_device -@pytest.mark.parametrize('count', [2,], indirect=True) -def test_slave_hd_multi_dev(case_tester) -> None: # type: ignore +@pytest.mark.parametrize( + 'count', + [ + 2, + ], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32s2', 'esp32s3', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], + indirect=['target'], +) +def test_slave_hd_multi_dev(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True) diff --git a/components/esp_driver_touch_sens/test_apps/touch_sens/pytest_touch_sens.py b/components/esp_driver_touch_sens/test_apps/touch_sens/pytest_touch_sens.py index 871cdb6baf..d2d3ce4608 100644 --- a/components/esp_driver_touch_sens/test_apps/touch_sens/pytest_touch_sens.py +++ b/components/esp_driver_touch_sens/test_apps/touch_sens/pytest_touch_sens.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 runners do not support touch pins') @pytest.mark.generic @pytest.mark.parametrize( @@ -15,5 +15,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_touch_sens(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py b/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py index 998cb08097..c40387a670 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py @@ -1,43 +1,41 @@ -# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut from pytest_embedded_idf.unity_tester import CaseTester +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'release', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5'], + indirect=['target'], +) def test_temperature_sensor_driver(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'iram_safe', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'iram_safe', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c6', 'esp32h2', 'esp32p4', 'esp32c5'], indirect=['target']) def test_temperature_sensor_cbs(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c6 @pytest.mark.two_duts @pytest.mark.parametrize('count', [2], indirect=True) @pytest.mark.parametrize( @@ -47,6 +45,7 @@ def test_temperature_sensor_cbs(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6'], indirect=['target']) def test_temperature_phy_cases(case_tester: CaseTester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'two_duts') == 'two_duts': diff --git a/components/esp_driver_uart/test_apps/rs485/pytest_rs485.py b/components/esp_driver_uart/test_apps/rs485/pytest_rs485.py index d539b0c151..58281a9274 100644 --- a/components/esp_driver_uart/test_apps/rs485/pytest_rs485.py +++ b/components/esp_driver_uart/test_apps/rs485/pytest_rs485.py @@ -1,11 +1,20 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.multi_dut_modbus_rs485 -@pytest.mark.parametrize('count, config', [(2, 'release',)], indirect=True) -def test_rs485_multi_dev(case_tester) -> None: # type: ignore +@pytest.mark.parametrize( + 'count, config', + [ + ( + 2, + 'release', + ) + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) +def test_rs485_multi_dev(case_tester) -> None: # type: ignore case_tester.run_all_multi_dev_cases(reset=True) diff --git a/components/esp_driver_uart/test_apps/uart/pytest_uart.py b/components/esp_driver_uart/test_apps/uart/pytest_uart.py index 68b2661cda..a123d36998 100644 --- a/components/esp_driver_uart/test_apps/uart/pytest_uart.py +++ b/components/esp_driver_uart/test_apps/uart/pytest_uart.py @@ -1,6 +1,7 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest +from pytest_embedded_idf.utils import idf_parametrize input_argv = { 'esp32': ['uart'], @@ -16,7 +17,6 @@ input_argv = { } -@pytest.mark.supported_targets @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='skip due to duplication with test_uart_single_dev_psram') @pytest.mark.generic @pytest.mark.parametrize( @@ -27,7 +27,8 @@ input_argv = { ], indirect=True, ) -def test_uart_single_dev(case_tester) -> None: # type: ignore +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_uart_single_dev(case_tester) -> None: # type: ignore dut = case_tester.first_dut chip_type = dut.app.target @@ -48,7 +49,6 @@ def test_uart_single_dev(case_tester) -> None: # type: ignore dut._run_normal_case(case, reset=True) -@pytest.mark.esp32s3 @pytest.mark.octal_psram @pytest.mark.parametrize( 'config', @@ -58,7 +58,8 @@ def test_uart_single_dev(case_tester) -> None: # type: ignore ], indirect=True, ) -def test_uart_single_dev_psram(case_tester) -> None: # type: ignore +@idf_parametrize('target', ['esp32s3'], indirect=['target']) +def test_uart_single_dev_psram(case_tester) -> None: # type: ignore dut = case_tester.first_dut for case in case_tester.test_menu: dut.serial.hard_reset() diff --git a/components/esp_driver_uart/test_apps/uart_vfs/pytest_uart_vfs.py b/components/esp_driver_uart/test_apps/uart_vfs/pytest_uart_vfs.py index 131d8c9423..7a281cc130 100644 --- a/components/esp_driver_uart/test_apps/uart_vfs/pytest_uart_vfs.py +++ b/components/esp_driver_uart/test_apps/uart_vfs/pytest_uart_vfs.py @@ -1,24 +1,34 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='skip due to duplication with test_uart_vfs_psram') @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'default', 'iram', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'iram', + ], + indirect=True, +) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_uart_vfs_default(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s3 @pytest.mark.quad_psram -@pytest.mark.parametrize('config', [ - 'default', 'iram', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'iram', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_uart_vfs_psram(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/pytest_usb_serial_jtag.py b/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/pytest_usb_serial_jtag.py index 859de671c1..b03ee9ed2b 100644 --- a/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/pytest_usb_serial_jtag.py +++ b/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/pytest_usb_serial_jtag.py @@ -1,13 +1,10 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.usb_serial_jtag @pytest.mark.parametrize( 'port, flash_port, config', @@ -16,21 +13,20 @@ from pytest_embedded import Dut ], indirect=True, ) -def test_usb_serial_jtag_dev(dut: Dut) -> None: # type: ignore +@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'], indirect=['target']) +def test_usb_serial_jtag_dev(dut: Dut) -> None: # type: ignore dut.expect_exact('Press ENTER to see the list of tests') - dut.write('\"test print via usb_serial_jtag driver multiple times in different tasks\"') + dut.write('"test print via usb_serial_jtag driver multiple times in different tasks"') for i in range(300 * 2): - dut.expect(r'Oh, hello world (\d), this test is for testing message and parse in python, time (\d+)', timeout=10) + dut.expect( + r'Oh, hello world (\d), this test is for testing message and parse in python, time (\d+)', timeout=10 + ) dut.expect('PASS') - dut.expect_exact('Enter next test, or \'enter\' to see menu') - dut.write('\"see if fsync appears to work\"') + dut.expect_exact("Enter next test, or 'enter' to see menu") + dut.write('"see if fsync appears to work"') dut.expect('PASS') -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.usb_serial_jtag @pytest.mark.parametrize( 'port, flash_port, config', @@ -39,8 +35,9 @@ def test_usb_serial_jtag_dev(dut: Dut) -> None: # type: ignore ], indirect=True, ) -def test_usb_serial_jtag_rom_dev(dut: Dut) -> None: # type: ignore +@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'], indirect=['target']) +def test_usb_serial_jtag_rom_dev(dut: Dut) -> None: # type: ignore dut.expect_exact('Press ENTER to see the list of tests') - dut.write('\"test rom printf work after driver installed\"') + dut.write('"test rom printf work after driver installed"') dut.expect(r'hi, espressif1', timeout=10) dut.expect(r'hi, espressif2', timeout=10) diff --git a/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag_vfs/pytest_usb_serial_jtag_vfs.py b/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag_vfs/pytest_usb_serial_jtag_vfs.py index fad239963a..56b70a9bd5 100644 --- a/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag_vfs/pytest_usb_serial_jtag_vfs.py +++ b/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag_vfs/pytest_usb_serial_jtag_vfs.py @@ -1,26 +1,23 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.usb_serial_jtag @pytest.mark.parametrize( 'port, flash_port, config', [ pytest.param('/dev/serial_ports/ttyACM-esp32', '/dev/serial_ports/ttyUSB-esp32', 'release'), ], - indirect=True,) + indirect=True, +) @pytest.mark.parametrize('test_message', ['test123456789!@#%^&*']) @idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'], indirect=['target']) def test_usj_vfs_select(dut: Dut, test_message: list) -> None: dut.expect_exact('Press ENTER to see the list of tests') - dut.write('\"test select read, write and timeout\"') + dut.write('"test select read, write and timeout"') dut.expect_exact('select timed out', timeout=2) dut.write(test_message) dut.expect_exact(test_message, timeout=2) diff --git a/components/esp_eth/test_apps/pytest_esp_eth.py b/components/esp_eth/test_apps/pytest_esp_eth.py index 8d5240e556..d05f3ed992 100644 --- a/components/esp_eth/test_apps/pytest_esp_eth.py +++ b/components/esp_eth/test_apps/pytest_esp_eth.py @@ -11,6 +11,7 @@ from typing import Iterator import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize from scapy.all import Ether from scapy.all import raw @@ -47,7 +48,7 @@ class EthTestIntf(object): logging.info('Use %s for testing', self.target_if) @contextlib.contextmanager - def configure_eth_if(self, eth_type:int=0) -> Iterator[socket.socket]: + def configure_eth_if(self, eth_type: int = 0) -> Iterator[socket.socket]: if eth_type == 0: eth_type = self.eth_type so = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(eth_type)) @@ -62,14 +63,14 @@ class EthTestIntf(object): so.settimeout(10) payload = bytearray(1010) for i, _ in enumerate(payload): - payload[i] = i & 0xff + payload[i] = i & 0xFF eth_frame = Ether(dst=mac, src=so.getsockname()[4], type=self.eth_type) / raw(payload) try: so.send(raw(eth_frame)) except Exception as e: raise e - def recv_resp_poke(self, mac:str, i:int=0) -> None: + def recv_resp_poke(self, mac: str, i: int = 0) -> None: eth_type_ctrl = self.eth_type + 1 with self.configure_eth_if(eth_type_ctrl) as so: so.settimeout(30) @@ -78,13 +79,13 @@ class EthTestIntf(object): eth_frame = Ether(so.recv(60)) except Exception as e: raise e - if mac == eth_frame.src and eth_frame.load[0] == 0xfa: + if mac == eth_frame.src and eth_frame.load[0] == 0xFA: if eth_frame.load[1] != i: raise RuntimeError('Missed Poke Packet') logging.info('Poke Packet received...') eth_frame.dst = eth_frame.src eth_frame.src = so.getsockname()[4] - eth_frame.load = bytes.fromhex('fb') # POKE_RESP code + eth_frame.load = bytes.fromhex('fb') # POKE_RESP code so.send(raw(eth_frame)) break else: @@ -94,9 +95,9 @@ class EthTestIntf(object): else: raise RuntimeError('No Poke Packet!') - def traffic_gen(self, mac: str, pipe_rcv:connection.Connection) -> None: + def traffic_gen(self, mac: str, pipe_rcv: connection.Connection) -> None: with self.configure_eth_if() as so: - payload = bytes.fromhex('ff') # DUMMY_TRAFFIC code + payload = bytes.fromhex('ff') # DUMMY_TRAFFIC code payload += bytes(1485) eth_frame = Ether(dst=mac, src=so.getsockname()[4], type=self.eth_type) / raw(payload) try: @@ -105,7 +106,7 @@ class EthTestIntf(object): except Exception as e: raise e - def eth_loopback(self, mac: str, pipe_rcv:connection.Connection) -> None: + def eth_loopback(self, mac: str, pipe_rcv: connection.Connection) -> None: with self.configure_eth_if(self.eth_type) as so: so.settimeout(30) try: @@ -160,7 +161,7 @@ def ethernet_l2_test(dut: IdfDut, test_if: str = '') -> None: raise RuntimeError('No broadcast received from expected DUT MAC addr') for i in range(0, 1010): - if eth_frame.load[i] != i & 0xff: + if eth_frame.load[i] != i & 0xFF: raise RuntimeError('Packet content mismatch') dut.expect_unity_test_output() @@ -174,7 +175,9 @@ def ethernet_l2_test(dut: IdfDut, test_if: str = '') -> None: # (there might be slight delay due to the RSTP execution) target_if.recv_resp_poke(mac=dut_mac) target_if.send_eth_packet('ff:ff:ff:ff:ff:ff') # broadcast frame - target_if.send_eth_packet('01:00:5e:00:00:00') # IPv4 multicast frame (some SPI Eth modules filter multicast other than IP) + target_if.send_eth_packet( + '01:00:5e:00:00:00' + ) # IPv4 multicast frame (some SPI Eth modules filter multicast other than IP) target_if.send_eth_packet(mac=dut_mac) # unicast frame dut.expect_unity_test_output(extra_before=res.group(1)) @@ -193,7 +196,13 @@ def ethernet_l2_test(dut: IdfDut, test_if: str = '') -> None: target_if.recv_resp_poke(dut_mac, rx_i) # Start/stop under heavy Rx traffic pipe_rcv, pipe_send = Pipe(False) - tx_proc = Process(target=target_if.traffic_gen, args=(dut_mac, pipe_rcv, )) + tx_proc = Process( + target=target_if.traffic_gen, + args=( + dut_mac, + pipe_rcv, + ), + ) tx_proc.start() try: dut.expect_exact('Ethernet Stopped') @@ -222,7 +231,13 @@ def ethernet_heap_alloc_test(dut: IdfDut, test_if: str = '') -> None: ) dut_mac = res.group(1).decode('utf-8') pipe_rcv, pipe_send = Pipe(False) - loopback_proc = Process(target=target_if.eth_loopback, args=(dut_mac, pipe_rcv, )) + loopback_proc = Process( + target=target_if.eth_loopback, + args=( + dut_mac, + pipe_rcv, + ), + ) loopback_proc.start() target_if.recv_resp_poke(mac=dut_mac) @@ -236,76 +251,96 @@ def ethernet_heap_alloc_test(dut: IdfDut, test_if: str = '') -> None: # ----------- IP101 ----------- -@pytest.mark.esp32 @pytest.mark.ethernet -@pytest.mark.parametrize('config', [ - 'default_ip101', - 'release_ip101', - 'single_core_ip101' -], indirect=True) +@pytest.mark.parametrize('config', ['default_ip101', 'release_ip101', 'single_core_ip101'], indirect=True) @pytest.mark.flaky(reruns=3, reruns_delay=5) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_ethernet(dut: IdfDut) -> None: ethernet_test(dut) -@pytest.mark.esp32 @pytest.mark.ethernet -@pytest.mark.parametrize('config', [ - 'default_ip101', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_ip101', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_emac(dut: IdfDut) -> None: ethernet_int_emac_test(dut) dut.serial.hard_reset() ethernet_heap_alloc_test(dut) -@pytest.mark.esp32 @pytest.mark.eth_ip101 -@pytest.mark.parametrize('config', [ - 'default_ip101', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_ip101', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_ip101(dut: IdfDut) -> None: ethernet_l2_test(dut) # ----------- IP101 ESP32P4 ----------- -@pytest.mark.esp32p4 @pytest.mark.eth_ip101 -@pytest.mark.parametrize('config', [ - 'default_ip101_esp32p4', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_ip101_esp32p4', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_esp32p4_ethernet(dut: IdfDut) -> None: ethernet_test(dut) dut.serial.hard_reset() ethernet_l2_test(dut) -@pytest.mark.esp32p4 @pytest.mark.eth_ip101 -@pytest.mark.parametrize('config', [ - 'default_ip101_esp32p4', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_ip101_esp32p4', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_esp32p4_emac(dut: IdfDut) -> None: ethernet_int_emac_test(dut) dut.serial.hard_reset() ethernet_heap_alloc_test(dut) -@pytest.mark.esp32p4 @pytest.mark.eth_ip101 -@pytest.mark.parametrize('config', [ - 'rmii_clko_esp32p4', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'rmii_clko_esp32p4', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_esp32p4_emac_clko(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='esp_emac_clk_out') # ----------- LAN8720 ----------- -@pytest.mark.esp32 @pytest.mark.eth_lan8720 -@pytest.mark.parametrize('config', [ - 'default_lan8720', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_lan8720', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_lan8720(dut: IdfDut) -> None: ethernet_test(dut) dut.serial.hard_reset() @@ -313,11 +348,15 @@ def test_esp_eth_lan8720(dut: IdfDut) -> None: # ----------- RTL8201 ----------- -@pytest.mark.esp32 @pytest.mark.eth_rtl8201 -@pytest.mark.parametrize('config', [ - 'default_rtl8201', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_rtl8201', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_rtl8201(dut: IdfDut) -> None: ethernet_test(dut) dut.serial.hard_reset() @@ -325,11 +364,15 @@ def test_esp_eth_rtl8201(dut: IdfDut) -> None: # ----------- KSZ8041 ----------- -@pytest.mark.esp32 @pytest.mark.eth_ksz8041 -@pytest.mark.parametrize('config', [ - 'default_ksz8041', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_ksz8041', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_ksz8041(dut: IdfDut) -> None: ethernet_test(dut) dut.serial.hard_reset() @@ -337,11 +380,15 @@ def test_esp_eth_ksz8041(dut: IdfDut) -> None: # ----------- DP83848 ----------- -@pytest.mark.esp32 @pytest.mark.eth_dp83848 -@pytest.mark.parametrize('config', [ - 'default_dp83848', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_dp83848', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_dp83848(dut: IdfDut) -> None: ethernet_test(dut) dut.serial.hard_reset() @@ -349,12 +396,16 @@ def test_esp_eth_dp83848(dut: IdfDut) -> None: # ----------- W5500 ----------- -@pytest.mark.esp32 @pytest.mark.eth_w5500 -@pytest.mark.parametrize('config', [ - 'default_w5500', - 'poll_w5500', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_w5500', + 'poll_w5500', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_w5500(dut: IdfDut) -> None: ethernet_test(dut) dut.serial.hard_reset() @@ -364,12 +415,16 @@ def test_esp_eth_w5500(dut: IdfDut) -> None: # ----------- KSZ8851SNL ----------- -@pytest.mark.esp32 @pytest.mark.eth_ksz8851snl -@pytest.mark.parametrize('config', [ - 'default_ksz8851snl', - 'poll_ksz8851snl', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_ksz8851snl', + 'poll_ksz8851snl', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_ksz8851snl(dut: IdfDut) -> None: ethernet_test(dut) dut.serial.hard_reset() @@ -379,12 +434,16 @@ def test_esp_eth_ksz8851snl(dut: IdfDut) -> None: # ----------- DM9051 ----------- -@pytest.mark.esp32 @pytest.mark.eth_dm9051 -@pytest.mark.parametrize('config', [ - 'default_dm9051', - 'poll_dm9051', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_dm9051', + 'poll_dm9051', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_dm9051(dut: IdfDut) -> None: ethernet_test(dut) dut.serial.hard_reset() diff --git a/components/esp_event/host_test/esp_event_unit_test/pytest_esp_event_linux.py b/components/esp_event/host_test/esp_event_unit_test/pytest_esp_event_linux.py index 7b289385f8..fd4b56e68a 100644 --- a/components/esp_event/host_test/esp_event_unit_test/pytest_esp_event_linux.py +++ b/components/esp_event/host_test/esp_event_unit_test/pytest_esp_event_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_esp_event_linux(dut: Dut) -> None: dut.expect_exact('All tests passed', timeout=5) diff --git a/components/esp_hid/test_apps/pytest_esp_hid.py b/components/esp_hid/test_apps/pytest_esp_hid.py index 664e29bf6f..f75ffbad34 100644 --- a/components/esp_hid/test_apps/pytest_esp_hid.py +++ b/components/esp_hid/test_apps/pytest_esp_hid.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c3 +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_esp_hid(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_http_client/test_apps/pytest_esp_http_client_ut.py b/components/esp_http_client/test_apps/pytest_esp_http_client_ut.py index b648571e56..6581b93cfa 100644 --- a/components/esp_http_client/test_apps/pytest_esp_http_client_ut.py +++ b/components/esp_http_client/test_apps/pytest_esp_http_client_ut.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_http_client(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_http_server/test_apps/pytest_esp_http_server_ut.py b/components/esp_http_server/test_apps/pytest_esp_http_server_ut.py index 613408c543..71cfe89396 100644 --- a/components/esp_http_server/test_apps/pytest_esp_http_server_ut.py +++ b/components/esp_http_server/test_apps/pytest_esp_http_server_ut.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_http_server(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_hw_support/test_apps/dma/pytest_dma.py b/components/esp_hw_support/test_apps/dma/pytest_dma.py index 035c39dd54..7e0d5b3de5 100644 --- a/components/esp_hw_support/test_apps/dma/pytest_dma.py +++ b/components/esp_hw_support/test_apps/dma/pytest_dma.py @@ -2,16 +2,9 @@ # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -20,11 +13,15 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize( + 'target', + ['esp32s2', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], + indirect=['target'], +) def test_dma(dut: Dut) -> None: dut.run_all_single_board_cases(reset=True) -@pytest.mark.esp32s3 @pytest.mark.octal_psram @pytest.mark.parametrize( 'config', @@ -33,11 +30,11 @@ def test_dma(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_dma_psram(dut: Dut) -> None: dut.run_all_single_board_cases(reset=True) -@pytest.mark.esp32p4 @pytest.mark.flash_encryption @pytest.mark.parametrize( 'config', @@ -46,11 +43,11 @@ def test_dma_psram(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_dma_ext_mem_encryption(dut: Dut) -> None: dut.run_all_single_board_cases(reset=True) -@pytest.mark.esp32s3 @pytest.mark.flash_encryption_f4r8 @pytest.mark.parametrize( 'config', @@ -59,5 +56,6 @@ def test_dma_ext_mem_encryption(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_dma_ext_mem_encryption_s3_f4r8(dut: Dut) -> None: dut.run_all_single_board_cases(reset=True) diff --git a/components/esp_hw_support/test_apps/dma2d/pytest_dma2d.py b/components/esp_hw_support/test_apps/dma2d/pytest_dma2d.py index 1fbdd0e0dd..090cb6be16 100644 --- a/components/esp_hw_support/test_apps/dma2d/pytest_dma2d.py +++ b/components/esp_hw_support/test_apps/dma2d/pytest_dma2d.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_dma2d(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py index 303f5bc685..beca94dde8 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py @@ -1,18 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.parametrize( - 'config', - [ - pytest.param('single_core_esp32', marks=[pytest.mark.esp32]), - pytest.param('default', marks=[pytest.mark.supported_targets]), - pytest.param('release', marks=[pytest.mark.supported_targets]), - ], - indirect=True, +@idf_parametrize( + 'config,target', + [('single_core_esp32', 'esp32'), ('default', 'supported_targets'), ('release', 'supported_targets')], + indirect=['config', 'target'], ) def test_esp_hw_support(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=180) diff --git a/components/esp_hw_support/test_apps/host_test_linux/pytest_esp_hw_support_linux.py b/components/esp_hw_support/test_apps/host_test_linux/pytest_esp_hw_support_linux.py index a2dce9a03e..aa9da8d2a5 100644 --- a/components/esp_hw_support/test_apps/host_test_linux/pytest_esp_hw_support_linux.py +++ b/components/esp_hw_support/test_apps/host_test_linux/pytest_esp_hw_support_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_esp_hw_support_linux(dut: Dut) -> None: dut.run_all_single_board_cases(group='!ignore', timeout=120) diff --git a/components/esp_hw_support/test_apps/mspi/pytest_flash_psram.py b/components/esp_hw_support/test_apps/mspi/pytest_flash_psram.py index b0284ea421..9e1ced0e12 100644 --- a/components/esp_hw_support/test_apps/mspi/pytest_flash_psram.py +++ b/components/esp_hw_support/test_apps/mspi/pytest_flash_psram.py @@ -1,39 +1,45 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import os import pathlib import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -MSPI_F8R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f8r8*')] +MSPI_F8R8_configs = [ + p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f8r8*') +] -@pytest.mark.esp32s3 @pytest.mark.MSPI_F8R8 @pytest.mark.parametrize('config', MSPI_F8R8_configs, indirect=True) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_flash8_psram8(dut: IdfDut) -> None: dut.run_all_single_board_cases() # For F4R8 board (Quad Flash and Octal PSRAM) -MSPI_F4R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r8*')] +MSPI_F4R8_configs = [ + p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r8*') +] -@pytest.mark.esp32s3 @pytest.mark.MSPI_F4R8 @pytest.mark.parametrize('config', MSPI_F4R8_configs, indirect=True) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_flash4_psram8(dut: IdfDut) -> None: dut.run_all_single_board_cases() # For F4R4 board (Quad Flash and Quad PSRAM) -MSPI_F4R4_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r4*')] +MSPI_F4R4_configs = [ + p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r4*') +] -@pytest.mark.esp32s3 @pytest.mark.MSPI_F4R4 @pytest.mark.parametrize('config', MSPI_F4R4_configs, indirect=True) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_flash4_psram4(dut: IdfDut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_hw_support/test_apps/mspi_psram_with_dfs/pytest_psram_with_dfs.py b/components/esp_hw_support/test_apps/mspi_psram_with_dfs/pytest_psram_with_dfs.py index 5680c21c53..2117144144 100644 --- a/components/esp_hw_support/test_apps/mspi_psram_with_dfs/pytest_psram_with_dfs.py +++ b/components/esp_hw_support/test_apps/mspi_psram_with_dfs/pytest_psram_with_dfs.py @@ -1,39 +1,45 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import os import pathlib import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -MSPI_F8R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f8r8*')] +MSPI_F8R8_configs = [ + p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f8r8*') +] -@pytest.mark.esp32s3 @pytest.mark.MSPI_F8R8 @pytest.mark.parametrize('config', MSPI_F8R8_configs, indirect=True) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_flash8_psram8_with_dfs(dut: IdfDut) -> None: dut.run_all_single_board_cases() # For F4R8 board (Quad Flash and Octal PSRAM) -MSPI_F4R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r8*')] +MSPI_F4R8_configs = [ + p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r8*') +] -@pytest.mark.esp32s3 @pytest.mark.MSPI_F4R8 @pytest.mark.parametrize('config', MSPI_F4R8_configs, indirect=True) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_flash4_psram8_with_dfs(dut: IdfDut) -> None: dut.run_all_single_board_cases() # For F4R4 board (Quad Flash and Quad PSRAM) -MSPI_F4R4_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r4*')] +MSPI_F4R4_configs = [ + p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r4*') +] -@pytest.mark.esp32s3 @pytest.mark.MSPI_F4R4 @pytest.mark.parametrize('config', MSPI_F4R4_configs, indirect=True) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_flash4_psram4_with_dfs(dut: IdfDut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_hw_support/test_apps/rtc_8md256/pytest_rtc_8md256.py b/components/esp_hw_support/test_apps/rtc_8md256/pytest_rtc_8md256.py index 0ef937c0f5..881a92c708 100644 --- a/components/esp_hw_support/test_apps/rtc_8md256/pytest_rtc_8md256.py +++ b/components/esp_hw_support/test_apps/rtc_8md256/pytest_rtc_8md256.py @@ -1,8 +1,8 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def deepsleep_test(dut: Dut, case_name: str) -> None: @@ -19,21 +19,15 @@ def deepsleep_test(dut: Dut, case_name: str) -> None: dut.expect(r'rst:.*\(%s\)' % reset_reason, timeout=10) -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c2 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c2'], indirect=['target']) def test_rtc_8md256_deepsleep(dut: Dut) -> None: deepsleep_test(dut, '"Can use 8MD256 as RTC clock source in deepsleep"') # Only targets with SOC_PM_SUPPORT_RTC_PERIPH_PD defined -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target']) def test_rtc_8md256_deepsleep_force_rtcperiph(dut: Dut) -> None: deepsleep_test(dut, '"Can use 8MD256 as RTC clock source in deepsleep (force rtc_periph)"') @@ -48,18 +42,13 @@ def lightsleep_test(dut: Dut, case_name: str) -> None: dut.expect(r'Returned from light sleep, reason: timer', timeout=10) -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c3'], indirect=['target']) def test_rtc_8md256_lightsleep(dut: Dut) -> None: lightsleep_test(dut, '"Can use 8MD256 as RTC clock source in lightsleep"') -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target']) def test_rtc_8md256_lightsleep_force_rtcperiph(dut: Dut) -> None: lightsleep_test(dut, '"Can use 8MD256 as RTC clock source in lightsleep (force rtc_periph)"') diff --git a/components/esp_hw_support/test_apps/rtc_clk/pytest_rtc_clk.py b/components/esp_hw_support/test_apps/rtc_clk/pytest_rtc_clk.py index 396e5139b5..867de3252f 100644 --- a/components/esp_hw_support/test_apps/rtc_clk/pytest_rtc_clk.py +++ b/components/esp_hw_support/test_apps/rtc_clk/pytest_rtc_clk.py @@ -1,32 +1,33 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 from typing import Any import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.esp32 +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_rtc_clk(dut: Dut) -> None: dut.run_all_single_board_cases(group='rtc_clk') -@pytest.mark.esp32 @pytest.mark.xtal32k +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_rtc_xtal32k(dut: Dut) -> None: dut.run_all_single_board_cases(attributes={'test_env': 'xtal32k'}) -@pytest.mark.esp32 @pytest.mark.no32kXtal +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_rtc_no_xtal32k(dut: Dut) -> None: dut.run_all_single_board_cases(attributes={'test_env': 'noXtal32k'}) @pytest.mark.generic -@pytest.mark.supported_targets # TODO: [ESP32P4] IDF-8973 [ESP32C5] IDF-10309 [ESP32C61] IDF-9274 IDF-10984 @pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'], reason='support TBD') +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_rtc_calib(case_tester: Any) -> None: case_tester.run_all_multi_stage_cases() diff --git a/components/esp_hw_support/test_apps/sleep_retention/pytest_retention.py b/components/esp_hw_support/test_apps/sleep_retention/pytest_retention.py index 3a4ca50f1e..db1f258bb9 100644 --- a/components/esp_hw_support/test_apps/sleep_retention/pytest_retention.py +++ b/components/esp_hw_support/test_apps/sleep_retention/pytest_retention.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import functools from typing import Callable @@ -7,12 +7,11 @@ from typing import List import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def target_list(targets: List[str]) -> Callable: - def decorator(func: Callable) -> Callable: - @functools.wraps(func) def wrapper(*args: List, **kwargs: Dict) -> Callable: return func(*args, **kwargs) # type: ignore @@ -31,5 +30,6 @@ retention_targets = ['esp32c6', 'esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'] @target_list(retention_targets) @pytest.mark.generic +@idf_parametrize('target', ['esp32c61', 'esp32c5', 'esp32p4', 'esp32h2', 'esp32c6'], indirect=['target']) def test_sleep_retention(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py b/components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py index b4d9f85aff..82b2cc0d0d 100644 --- a/components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py +++ b/components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='lack of runners for now') @pytest.mark.lp_i2s -def test_efuse(dut: Dut) -> None: +@idf_parametrize('target', ['esp32p4'], indirect=['target']) +def test_efuse_component_ut(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py b/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py index b4511844d1..769691feaf 100644 --- a/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py +++ b/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 from time import sleep from typing import Tuple import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize TEST_CONFIGS = [ pytest.param('default'), @@ -71,15 +72,10 @@ available_rtcio_nums = { } -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic_multi_device @pytest.mark.parametrize('count', [2], indirect=True) @pytest.mark.parametrize('config', TEST_CONFIGS, indirect=True) +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) def test_ext1_deepsleep(dut: Tuple[IdfDut, IdfDut]) -> None: wakee = dut[0] waker = dut[1] @@ -127,13 +123,10 @@ def test_ext1_deepsleep(dut: Tuple[IdfDut, IdfDut]) -> None: wakee.expect(f'io_wakeup_num = {gpio_num}', timeout=10) -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32p4 @pytest.mark.generic_multi_device @pytest.mark.parametrize('count', [2], indirect=True) @pytest.mark.parametrize('config', TEST_CONFIGS, indirect=True) +@idf_parametrize('target', ['esp32c2', 'esp32c3', 'esp32c6', 'esp32p4'], indirect=['target']) def test_rtcio_deepsleep(dut: Tuple[IdfDut, IdfDut]) -> None: wakee = dut[0] waker = dut[1] @@ -176,17 +169,14 @@ def test_rtcio_deepsleep(dut: Tuple[IdfDut, IdfDut]) -> None: wakee.expect(f'io_wakeup_num = {gpio_num}', timeout=10) -@pytest.mark.esp32 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic_multi_device @pytest.mark.parametrize('count', [2], indirect=True) @pytest.mark.parametrize('config', TEST_CONFIGS, indirect=True) +@idf_parametrize( + 'target', + ['esp32', 'esp32c2', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c6', 'esp32h2', 'esp32p4'], + indirect=['target'], +) def test_gpio_wakeup_enable_lightsleep(dut: Tuple[IdfDut, IdfDut]) -> None: wakee = dut[0] waker = dut[1] @@ -196,7 +186,6 @@ def test_gpio_wakeup_enable_lightsleep(dut: Tuple[IdfDut, IdfDut]) -> None: for wakeup_level in [1, 0]: for gpio_num in gpio_nums: - wakee.write('\r\n') wakee.expect('io_wakeup_test>', timeout=10) wakee.write(f'gpio -p {gpio_num} -l {wakeup_level}') diff --git a/components/esp_lcd/test_apps/i2c_lcd/pytest_i2c_lcd.py b/components/esp_lcd/test_apps/i2c_lcd/pytest_i2c_lcd.py index 610d15c48b..b1de534d7d 100644 --- a/components/esp_lcd/test_apps/i2c_lcd/pytest_i2c_lcd.py +++ b/components/esp_lcd/test_apps/i2c_lcd/pytest_i2c_lcd.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c3 @pytest.mark.i2c_oled @pytest.mark.parametrize( 'config', @@ -14,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_i2c_lcd(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_lcd/test_apps/i2c_lcd_legacy/pytest_i2c_lcd_legacy.py b/components/esp_lcd/test_apps/i2c_lcd_legacy/pytest_i2c_lcd_legacy.py index a2e09316a6..3b917fb4a1 100644 --- a/components/esp_lcd/test_apps/i2c_lcd_legacy/pytest_i2c_lcd_legacy.py +++ b/components/esp_lcd/test_apps/i2c_lcd_legacy/pytest_i2c_lcd_legacy.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c3 @pytest.mark.i2c_oled @pytest.mark.parametrize( 'config', @@ -14,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_i2c_lcd_legacy(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_lcd/test_apps/i80_lcd/pytest_i80_lcd.py b/components/esp_lcd/test_apps/i80_lcd/pytest_i80_lcd.py index 78d8b7df5f..f9e213cc13 100644 --- a/components/esp_lcd/test_apps/i80_lcd/pytest_i80_lcd.py +++ b/components/esp_lcd/test_apps/i80_lcd/pytest_i80_lcd.py @@ -1,13 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -16,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_i80_lcd(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/pytest_mipi_dsi_lcd.py b/components/esp_lcd/test_apps/mipi_dsi_lcd/pytest_mipi_dsi_lcd.py index 966e3fb36e..377628c176 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/pytest_mipi_dsi_lcd.py +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/pytest_mipi_dsi_lcd.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,6 +14,7 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='no runner') def test_dsi_lcd(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_lcd/test_apps/rgb_lcd/pytest_rgb_lcd.py b/components/esp_lcd/test_apps/rgb_lcd/pytest_rgb_lcd.py index a9d77166a4..766aae861e 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/pytest_rgb_lcd.py +++ b/components/esp_lcd/test_apps/rgb_lcd/pytest_rgb_lcd.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 @pytest.mark.octal_psram @pytest.mark.parametrize( 'config', @@ -14,11 +14,11 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_rgb_lcd_esp32s3(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -28,5 +28,6 @@ def test_rgb_lcd_esp32s3(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_rgb_lcd_esp32p4(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_lcd/test_apps/spi_lcd/pytest_spi_lcd.py b/components/esp_lcd/test_apps/spi_lcd/pytest_spi_lcd.py index 2cdeaf11e8..f2bf28d79a 100644 --- a/components/esp_lcd/test_apps/spi_lcd/pytest_spi_lcd.py +++ b/components/esp_lcd/test_apps/spi_lcd/pytest_spi_lcd.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -13,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_spi_lcd(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_mm/test_apps/mm/pytest_mmap.py b/components/esp_mm/test_apps/mm/pytest_mmap.py index 04accedf06..12413ed9cd 100644 --- a/components/esp_mm/test_apps/mm/pytest_mmap.py +++ b/components/esp_mm/test_apps/mm/pytest_mmap.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut - - +from pytest_embedded_idf.utils import idf_parametrize # normal mmu tests -@pytest.mark.supported_targets + + @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,6 +14,7 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_mmap(dut: Dut) -> None: dut.run_all_single_board_cases(group='mmu') @@ -28,7 +29,16 @@ PSRAM_RELEASE_CONFIGS = [ @pytest.mark.generic -@pytest.mark.parametrize('config', PSRAM_RELEASE_CONFIGS, indirect=True) +@idf_parametrize( + 'config,target', + [ + ('psram_release_esp32', 'esp32'), + ('psram_release_esp32s2', 'esp32s2'), + ('psram_release_esp32s3', 'esp32s3'), + ('psram_release_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_mmap_psram(dut: Dut) -> None: dut.run_all_single_board_cases(group='mmu') @@ -41,13 +51,14 @@ XIP_CONFIGS = [ @pytest.mark.generic -@pytest.mark.parametrize('config', XIP_CONFIGS, indirect=True) +@idf_parametrize( + 'config,target', [('xip_psram_esp32s2', 'esp32s2'), ('xip_psram_esp32s3', 'esp32s3')], indirect=['config', 'target'] +) def test_mmap_xip_psram(dut: Dut) -> None: dut.run_all_single_board_cases(group='mmu') # normal cache tests -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -56,19 +67,31 @@ def test_mmap_xip_psram(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_cache(dut: Dut) -> None: dut.run_all_single_board_cases(group='cache') # cache tests with psram enabled @pytest.mark.generic -@pytest.mark.parametrize('config', PSRAM_RELEASE_CONFIGS, indirect=True) +@idf_parametrize( + 'config,target', + [ + ('psram_release_esp32', 'esp32'), + ('psram_release_esp32s2', 'esp32s2'), + ('psram_release_esp32s3', 'esp32s3'), + ('psram_release_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_cache_psram(dut: Dut) -> None: dut.run_all_single_board_cases(group='cache') # cache tests with xip_psram @pytest.mark.generic -@pytest.mark.parametrize('config', XIP_CONFIGS, indirect=True) +@idf_parametrize( + 'config,target', [('xip_psram_esp32s2', 'esp32s2'), ('xip_psram_esp32s3', 'esp32s3')], indirect=['config', 'target'] +) def test_cache_xip_psram(dut: Dut) -> None: dut.run_all_single_board_cases(group='cache') diff --git a/components/esp_mm/test_apps/mmap_hw/pytest_mmap_hw.py b/components/esp_mm/test_apps/mmap_hw/pytest_mmap_hw.py index 1590f48d51..5859272740 100644 --- a/components/esp_mm/test_apps/mmap_hw/pytest_mmap_hw.py +++ b/components/esp_mm/test_apps/mmap_hw/pytest_mmap_hw.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_mmap_hw(dut: Dut) -> None: dut.run_all_single_board_cases(group='mmu', timeout=600) diff --git a/components/esp_netif/test_apps/test_app_esp_netif/pytest_esp_netif.py b/components/esp_netif/test_apps/test_app_esp_netif/pytest_esp_netif.py index 746316674f..cca9d2f1e2 100644 --- a/components/esp_netif/test_apps/test_app_esp_netif/pytest_esp_netif.py +++ b/components/esp_netif/test_apps/test_app_esp_netif/pytest_esp_netif.py @@ -1,16 +1,20 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'global_dns', - 'dns_per_netif', - 'loopback', # test config without LWIP -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'global_dns', + 'dns_per_netif', + 'loopback', # test config without LWIP + ], + indirect=True, +) +@idf_parametrize('target', ['esp32s2', 'esp32c3'], indirect=['target']) def test_esp_netif(dut: Dut) -> None: dut.expect_unity_test_output() diff --git a/components/esp_netif/test_apps/test_app_vfs_l2tap/pytest_esp_vfs_l2tap.py b/components/esp_netif/test_apps/test_app_vfs_l2tap/pytest_esp_vfs_l2tap.py index 966483b517..260c1fe445 100644 --- a/components/esp_netif/test_apps/test_app_vfs_l2tap/pytest_esp_vfs_l2tap.py +++ b/components/esp_netif/test_apps/test_app_vfs_l2tap/pytest_esp_vfs_l2tap.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_netif_vfs_l2tp(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_partition/host_test/partition_api_test/pytest_esp_partition_linux.py b/components/esp_partition/host_test/partition_api_test/pytest_esp_partition_linux.py index 6d3b8a6d5d..211df105ee 100644 --- a/components/esp_partition/host_test/partition_api_test/pytest_esp_partition_linux.py +++ b/components/esp_partition/host_test/partition_api_test/pytest_esp_partition_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_esp_partition_linux(dut: Dut) -> None: dut.expect_unity_test_output(timeout=5) diff --git a/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py b/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py index 2c246b9938..d3726fa3a1 100644 --- a/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py +++ b/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py @@ -1,61 +1,57 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.supported_targets @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='not supported yet') # TODO: [ESP32C61] IDF-9250 IDF-10985 -@pytest.mark.parametrize('config', [ - 'default', - 'slp_iram_opt', - 'limits', - 'options', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'slp_iram_opt', + 'limits', + 'options', + ], + indirect=True, +) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_pm(dut: Dut) -> None: dut.run_all_single_board_cases() # psram attr tests with xip_psram -@pytest.mark.esp32s2 @pytest.mark.generic @pytest.mark.parametrize( 'config', - [ - 'pm_xip_psram_esp32s2' - ], + ['pm_xip_psram_esp32s2'], indirect=True, ) +@idf_parametrize('target', ['esp32s2'], indirect=['target']) def test_esp_attr_xip_psram_esp32s2(dut: Dut) -> None: dut.run_all_single_board_cases() # psram attr tests with xip_psram -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize( 'config', - [ - 'pm_xip_psram_esp32s3' - ], + ['pm_xip_psram_esp32s3'], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_esp_attr_xip_psram_esp32s3(dut: Dut) -> None: dut.run_all_single_board_cases() # power down CPU and TOP domain in auto-lightsleep -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', - [ - 'pm_pd_top_sleep' - ], + ['pm_pd_top_sleep'], ) +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) def test_esp_pd_top_and_cpu_sleep(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_psram/test_apps/psram/pytest_psram.py b/components/esp_psram/test_apps/psram/pytest_psram.py index e13d48e803..3306b25e36 100644 --- a/components/esp_psram/test_apps/psram/pytest_psram.py +++ b/components/esp_psram/test_apps/psram/pytest_psram.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,11 +14,11 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_psram_esp32(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 @pytest.mark.psramv0 @pytest.mark.parametrize( 'config', @@ -28,11 +28,11 @@ def test_psram_esp32(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_psram_esp32_psramv0(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s2 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -42,11 +42,11 @@ def test_psram_esp32_psramv0(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s2'], indirect=['target']) def test_psram_esp32s2(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -56,11 +56,11 @@ def test_psram_esp32s2(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_psram_esp32s3(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s3 @pytest.mark.octal_psram @pytest.mark.parametrize( 'config', @@ -70,25 +70,22 @@ def test_psram_esp32s3(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_psram_esp32s3_octal(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', - [ - 'esp32p4_200m_release', - 'esp32p4_xip' - ], + ['esp32p4_200m_release', 'esp32p4_xip'], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_psram_esp32p4(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c5 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -98,11 +95,11 @@ def test_psram_esp32p4(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) def test_psram_esp32c5(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -112,5 +109,6 @@ def test_psram_esp32c5(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c61'], indirect=['target']) def test_psram_esp32c61(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_ringbuf/test_apps/pytest_esp_ringbuf.py b/components/esp_ringbuf/test_apps/pytest_esp_ringbuf.py index 47b0dde7d5..d3d91c3e7f 100644 --- a/components/esp_ringbuf/test_apps/pytest_esp_ringbuf.py +++ b/components/esp_ringbuf/test_apps/pytest_esp_ringbuf.py @@ -1,39 +1,52 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.parametrize('target', [ - 'esp32', - 'esp32s2', -]) -@pytest.mark.parametrize('config', [ - 'default', - 'ringbuf_flash', -]) +@pytest.mark.parametrize( + 'target', + [ + 'esp32', + 'esp32s2', + ], +) +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'ringbuf_flash', + ], +) def test_esp_ringbuf(dut: Dut) -> None: dut.run_all_single_board_cases() @pytest.mark.host_test @pytest.mark.qemu -@pytest.mark.parametrize('target', [ - 'esp32', - 'esp32c3', -]) -@pytest.mark.parametrize('config', [ - 'default', - 'ringbuf_flash', -]) +@pytest.mark.parametrize( + 'target', + [ + 'esp32', + 'esp32c3', + ], +) +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'ringbuf_flash', + ], +) def test_esp_ringbuf_qemu(dut: Dut) -> None: for case in dut.test_menu: if 'qemu-ignore' not in case.groups and not case.is_ignored and case.type == 'normal': dut._run_normal_case(case) -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_esp_ringbuf_posix_simulator(dut: Dut) -> None: dut.run_all_single_board_cases(group='linux') diff --git a/components/esp_rom/test_apps/linux_rom_apis/pytest_esp_rom_linux.py b/components/esp_rom/test_apps/linux_rom_apis/pytest_esp_rom_linux.py index c9985e1123..14ac9488fa 100644 --- a/components/esp_rom/test_apps/linux_rom_apis/pytest_esp_rom_linux.py +++ b/components/esp_rom/test_apps/linux_rom_apis/pytest_esp_rom_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_esp_rom_linux(dut: Dut) -> None: dut.expect_exact('All tests passed', timeout=5) diff --git a/components/esp_rom/test_apps/rom_impl_components/pytest_esp_rom_impl_components.py b/components/esp_rom/test_apps/rom_impl_components/pytest_esp_rom_impl_components.py index a400d9e69b..e182b7b201 100644 --- a/components/esp_rom/test_apps/rom_impl_components/pytest_esp_rom_impl_components.py +++ b/components/esp_rom/test_apps/rom_impl_components/pytest_esp_rom_impl_components.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,5 +14,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_rom_impl_components(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_rom/test_apps/rom_tests/pytest_esp_rom.py b/components/esp_rom/test_apps/rom_tests/pytest_esp_rom.py index 28b068c5ce..679f7762c7 100644 --- a/components/esp_rom/test_apps/rom_tests/pytest_esp_rom.py +++ b/components/esp_rom/test_apps/rom_tests/pytest_esp_rom.py @@ -1,24 +1,22 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c3 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32c3', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], + indirect=['target'], +) def test_esp_rom(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c3 @pytest.mark.host_test @pytest.mark.qemu +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_esp_rom_qemu(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_security/test_apps/crypto_drivers/pytest_crypto_drivers.py b/components/esp_security/test_apps/crypto_drivers/pytest_crypto_drivers.py index 44435595f0..a2eb9fd15a 100644 --- a/components/esp_security/test_apps/crypto_drivers/pytest_crypto_drivers.py +++ b/components/esp_security/test_apps/crypto_drivers/pytest_crypto_drivers.py @@ -1,16 +1,13 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.generic +@idf_parametrize( + 'target', ['esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5'], indirect=['target'] +) def test_crypto_drivers(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=180) diff --git a/components/esp_system/test_apps/cache_panic/pytest_cache_panic_test.py b/components/esp_system/test_apps/cache_panic/pytest_cache_panic_test.py index f107e348a0..fdb36a0f3c 100644 --- a/components/esp_system/test_apps/cache_panic/pytest_cache_panic_test.py +++ b/components/esp_system/test_apps/cache_panic/pytest_cache_panic_test.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_cache_panic(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_system/test_apps/console/pytest_esp_system_console_tests.py b/components/esp_system/test_apps/console/pytest_esp_system_console_tests.py index 35e97b093c..fa8a49cdfc 100644 --- a/components/esp_system/test_apps/console/pytest_esp_system_console_tests.py +++ b/components/esp_system/test_apps/console/pytest_esp_system_console_tests.py @@ -1,8 +1,9 @@ -# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pexpect import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def not_expect(dut: Dut, output_regex: str) -> None: @@ -24,28 +25,18 @@ JTAG_SERIAL_MARKS = [ @pytest.mark.generic -@pytest.mark.parametrize( - 'config', - [ - pytest.param('console_none', marks=pytest.mark.supported_targets), - ], - indirect=True -) +@idf_parametrize('config', ['console_none'], indirect=['config']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_system_console_no_output_uart(dut: Dut) -> None: not_expect(dut, r'2nd stage bootloader|Hello World') dut.expect('This message will be printed even with CONFIG_ESP_CONSOLE_NONE') @pytest.mark.usb_serial_jtag -@pytest.mark.parametrize( - 'port, flash_port, config', - [ - pytest.param('/dev/serial_ports/ttyACM-esp32', '/dev/serial_ports/ttyUSB-esp32', 'serial_jtag_only', marks=JTAG_SERIAL_MARKS), - pytest.param('/dev/serial_ports/ttyACM-esp32', '/dev/serial_ports/ttyUSB-esp32', 'serial_jtag_only_no_vfs', marks=JTAG_SERIAL_MARKS), - pytest.param('/dev/serial_ports/ttyACM-esp32', '/dev/serial_ports/ttyUSB-esp32', 'console_no_vfs', marks=JTAG_SERIAL_MARKS), - ], - indirect=True, -) +@idf_parametrize('config', ['serial_jtag_only', 'serial_jtag_only_no_vfs', 'console_no_vfs'], indirect=['config']) +@idf_parametrize('flash_port', ['/dev/serial_ports/ttyUSB-esp32'], indirect=['flash_port']) +@idf_parametrize('port', ['/dev/serial_ports/ttyACM-esp32'], indirect=['port']) +@idf_parametrize('target', ['esp32c2', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32s3'], indirect=['target']) def test_esp_system_console_only_serial_jtag(dut: Dut) -> None: dut.expect('2nd stage bootloader') dut.expect('Hello World') diff --git a/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py b/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py index 03c3ba980b..7dbd63cfbe 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py +++ b/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py @@ -1,19 +1,24 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.parametrize( - 'config', +@idf_parametrize( + 'config,target', [ - pytest.param('default', marks=[pytest.mark.supported_targets]), - pytest.param('pd_vddsdio', marks=[pytest.mark.supported_targets]), - pytest.param('psram', marks=[pytest.mark.esp32, pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32p4]), - pytest.param('psram_with_pd_top', marks=[pytest.mark.esp32p4]), - pytest.param('single_core_esp32', marks=[pytest.mark.esp32]), - ] + ('default', 'supported_targets'), + ('pd_vddsdio', 'supported_targets'), + ('psram', 'esp32'), + ('psram', 'esp32p4'), + ('psram', 'esp32s2'), + ('psram', 'esp32s3'), + ('psram_with_pd_top', 'esp32p4'), + ('single_core_esp32', 'esp32'), + ], + indirect=['config', 'target'], ) def test_esp_system(dut: Dut) -> None: # esp32p4 32MB PSRAM initialize in startup takes more than 30 sec @@ -21,12 +26,8 @@ def test_esp_system(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.parametrize( - 'config', - [ - pytest.param('default', marks=[pytest.mark.supported_targets]), - ] -) +@idf_parametrize('config', ['default'], indirect=['config']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_stack_smash_protection(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('"stack smashing protection"') diff --git a/components/esp_system/test_apps/linux_apis/pytest_esp_system_linux.py b/components/esp_system/test_apps/linux_apis/pytest_esp_system_linux.py index 811afecc86..a2ada0ea61 100644 --- a/components/esp_system/test_apps/linux_apis/pytest_esp_system_linux.py +++ b/components/esp_system/test_apps/linux_apis/pytest_esp_system_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_esp_system_linux(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=60) diff --git a/components/esp_timer/test_apps/pytest_esp_timer_ut.py b/components/esp_timer/test_apps/pytest_esp_timer_ut.py index e7c23e9234..c20b5e871f 100644 --- a/components/esp_timer/test_apps/pytest_esp_timer_ut.py +++ b/components/esp_timer/test_apps/pytest_esp_timer_ut.py @@ -1,7 +1,8 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize CONFIGS = [ pytest.param('general', marks=[pytest.mark.supported_targets]), @@ -18,22 +19,40 @@ CONFIGS = [ @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize( + 'config,target', + [ + ('general', 'supported_targets'), + ('release', 'supported_targets'), + ('single_core', 'esp32'), + ('freertos_compliance', 'esp32'), + ('isr_dispatch_esp32', 'esp32'), + ('isr_dispatch_esp32c3', 'esp32c3'), + ('cpu1_esp32', 'esp32'), + ('any_cpu_esp32', 'esp32'), + ('cpu1_esp32s3', 'esp32s3'), + ('any_cpu_esp32s3', 'esp32s3'), + ], + indirect=['config', 'target'], +) def test_esp_timer(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) -@pytest.mark.esp32 @pytest.mark.generic @pytest.mark.psram -@pytest.mark.parametrize('config', [ - 'psram', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'psram', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_timer_psram(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) -@pytest.mark.esp32c2 @pytest.mark.generic @pytest.mark.xtal_26mhz @pytest.mark.parametrize( @@ -43,5 +62,6 @@ def test_esp_timer_psram(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_esp_timer_esp32c2_xtal_26mhz(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) diff --git a/components/esp_wifi/test_apps/wifi_connect/pytest_wifi_connect.py b/components/esp_wifi/test_apps/wifi_connect/pytest_wifi_connect.py index ac724c1f05..f83ccf8859 100644 --- a/components/esp_wifi/test_apps/wifi_connect/pytest_wifi_connect.py +++ b/components/esp_wifi/test_apps/wifi_connect/pytest_wifi_connect.py @@ -1,23 +1,19 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded_idf.unity_tester import CaseTester +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.two_duts @pytest.mark.parametrize('count', [2], indirect=True) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'], indirect=['target'] +) def test_wifi_connect_cases(case_tester: CaseTester) -> None: # type: ignore case_tester.run_all_cases() -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( @@ -27,6 +23,7 @@ def test_wifi_connect_cases(case_tester: CaseTester) -> None: # type: ignore ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_wifi_connect_cases_esp32c2_xtal26m(case_tester: CaseTester) -> None: case_tester.run_all_cases() diff --git a/components/esp_wifi/test_apps/wifi_function/pytest_wifi_function.py b/components/esp_wifi/test_apps/wifi_function/pytest_wifi_function.py index 1014dbc37b..ec28081ac2 100644 --- a/components/esp_wifi/test_apps/wifi_function/pytest_wifi_function.py +++ b/components/esp_wifi/test_apps/wifi_function/pytest_wifi_function.py @@ -1,23 +1,19 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut - - -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32c5 +from pytest_embedded_idf.utils import idf_parametrize # @pytest.mark.esp32c2 # esp32c2 are using xtal_26mhz + + @pytest.mark.generic +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c6', 'esp32c61', 'esp32c5'], indirect=['target'] +) def test_wifi_unit_test(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c2 @pytest.mark.xtal_26mhz @pytest.mark.generic @pytest.mark.parametrize( @@ -27,6 +23,7 @@ def test_wifi_unit_test(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_wifi_unit_test_esp32c2_xtal26m(dut: Dut) -> None: dut.run_all_single_board_cases() @@ -49,9 +46,7 @@ def test_wifi_unit_test_esp32c2eco4_xtal26m(dut: Dut) -> None: @pytest.mark.generic @pytest.mark.parametrize( 'config, target', - [ - ('esp32c3eco7','esp32c3') - ], + [('esp32c3eco7', 'esp32c3')], indirect=True, ) def test_wifi_unit_test_esp32c3eco7(dut: Dut) -> None: diff --git a/components/espcoredump/test_apps/pytest_coredump.py b/components/espcoredump/test_apps/pytest_coredump.py index c3e241a991..d51b6ee47b 100644 --- a/components/espcoredump/test_apps/pytest_coredump.py +++ b/components/espcoredump/test_apps/pytest_coredump.py @@ -1,13 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c2 +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32c2'], indirect=['target']) def test_coredump(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/fatfs/host_test/pytest_fatfs_linux.py b/components/fatfs/host_test/pytest_fatfs_linux.py index 7b12c361a1..96cdd40207 100644 --- a/components/fatfs/host_test/pytest_fatfs_linux.py +++ b/components/fatfs/host_test/pytest_fatfs_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_fatfs_linux(dut: Dut) -> None: dut.expect_exact('All tests passed', timeout=120) diff --git a/components/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py b/components/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py index 3840e60f50..857bde5ef5 100644 --- a/components/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py +++ b/components/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_fatfs_flash_ro(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py b/components/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py index 9abd181502..2c0f85f780 100644 --- a/components/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py +++ b/components/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -15,20 +14,21 @@ from pytest_embedded import Dut 'fastseek', 'auto_fsync', 'no_dyn_buffers', - ] + ], ) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_fatfs_flash_wl_generic(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=240) -@pytest.mark.esp32 @pytest.mark.generic @pytest.mark.psram @pytest.mark.parametrize( 'config', [ 'psram', - ] + ], ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_fatfs_flash_wl_psram(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=180) diff --git a/components/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py b/components/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py index b83c4b72f1..7e042ef9e1 100644 --- a/components/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py +++ b/components/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py @@ -2,50 +2,49 @@ # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.sdcard_sdmode @pytest.mark.parametrize( 'config', [ 'default', 'release', - ] + ], ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_fatfs_sdcard_generic_sdmmc(dut: Dut) -> None: dut.run_all_single_board_cases(group='sdmmc', timeout=180) -@pytest.mark.esp32 @pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDFCI-2058, temporary lack runner') -@pytest.mark.esp32c3 @pytest.mark.sdcard_spimode @pytest.mark.parametrize( 'config', [ 'default', 'release', - ] + ], ) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_fatfs_sdcard_generic_sdspi(dut: Dut) -> None: dut.run_all_single_board_cases(group='sdspi', timeout=180) -@pytest.mark.esp32 @pytest.mark.sdcard_sdmode @pytest.mark.psram @pytest.mark.parametrize( 'config', [ 'psram', - ] + ], ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_fatfs_sdcard_psram_sdmmc(dut: Dut) -> None: dut.run_all_single_board_cases(group='sdmmc', timeout=180) -@pytest.mark.esp32 @pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDFCI-2058, temporary lack runner') @pytest.mark.sdcard_spimode @pytest.mark.psram @@ -53,7 +52,8 @@ def test_fatfs_sdcard_psram_sdmmc(dut: Dut) -> None: 'config', [ 'psram', - ] + ], ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_fatfs_sdcard_psram_sdspi(dut: Dut) -> None: dut.run_all_single_board_cases(group='sdspi', timeout=180) diff --git a/components/freertos/test_apps/freertos/pytest_freertos.py b/components/freertos/test_apps/freertos/pytest_freertos.py index c22f17b049..b9090c91ba 100644 --- a/components/freertos/test_apps/freertos/pytest_freertos.py +++ b/components/freertos/test_apps/freertos/pytest_freertos.py @@ -1,58 +1,84 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut - +from pytest_embedded_idf.utils import idf_parametrize CONFIGS = [ - pytest.param('default', marks=[pytest.mark.supported_targets,]), + pytest.param( + 'default', + marks=[ + pytest.mark.supported_targets, + ], + ), pytest.param('freertos_options', marks=[pytest.mark.supported_targets]), pytest.param('psram', marks=[pytest.mark.esp32, pytest.mark.esp32s3, pytest.mark.esp32p4, pytest.mark.esp32c5]), pytest.param('single_core', marks=[pytest.mark.esp32, pytest.mark.esp32p4]), # TODO: [ESP32C5] IDF-10335 # TODO: [ESP32C61] IDF-11146 - pytest.param('smp', marks=[ - pytest.mark.supported_targets, - pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5', 'esp32c61'], - reason='test failed/TBD IDF-8113') - ]), + pytest.param( + 'smp', + marks=[ + pytest.mark.supported_targets, + pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5', 'esp32c61'], reason='test failed/TBD IDF-8113'), + ], + ), pytest.param('tickless_idle', marks=[pytest.mark.supported_targets]), ] @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize( + 'config,target,markers', + [ + ('default', 'supported_targets'), + ('freertos_options', 'supported_targets'), + ('psram', 'esp32'), + ('psram', 'esp32c5'), + ('psram', 'esp32p4'), + ('psram', 'esp32s3'), + ('single_core', 'esp32'), + ('single_core', 'esp32p4'), + ( + 'smp', + 'supported_targets', + (pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5', 'esp32c61'], reason='test failed/TBD IDF-8113'),), + ), + ('tickless_idle', 'supported_targets'), + ], + indirect=['config', 'target'], +) def test_freertos(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', ['freertos_options'], indirect=True) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_task_notify_too_high_index_fails(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests.') - dut.write('\"Notify too high index fails\"') + dut.write('"Notify too high index fails"') dut.expect('assert failed: xTaskGenericNotify', timeout=5) dut.expect('uxIndexToNotify < [0-9]+') dut.expect_exact('Rebooting...') -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', ['freertos_options'], indirect=True) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_task_notify_wait_too_high_index_fails(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests.') - dut.write('\"Notify Wait too high index fails\"') + dut.write('"Notify Wait too high index fails"') dut.expect('assert failed: xTaskGenericNotifyWait', timeout=5) dut.expect('uxIndexToWait < [0-9]+', timeout=5) dut.expect_exact('Rebooting...') -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', ['default'], indirect=True) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_port_must_assert_in_isr(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests.') - dut.write('\"port must assert if in ISR context\"') + dut.write('"port must assert if in ISR context"') dut.expect('assert failed: vPortAssertIfInISR', timeout=5) dut.expect_exact('Rebooting...') diff --git a/components/hal/test_apps/crypto/pytest_crypto.py b/components/hal/test_apps/crypto/pytest_crypto.py index 64fe21473b..6fb8f6ee42 100644 --- a/components/hal/test_apps/crypto/pytest_crypto.py +++ b/components/hal/test_apps/crypto/pytest_crypto.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import binascii import os @@ -16,6 +16,7 @@ from cryptography.hazmat.primitives.serialization import load_pem_private_key from ecdsa import NIST256p from ecdsa.ellipticcurve import Point from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def load_ecdsa_key(filename: str) -> SECP256R1: @@ -34,10 +35,13 @@ def test_xts_aes_encryption(negotiated_key: bytes, plaintext_data: bytes, encryp 'espsecure.py', 'encrypt_flash_data', '--aes_xts', - '--keyfile', 'test/negotiated_key.bin', - '--address', '0x120000', - '--output', 'test/enc-data.bin', - 'test/plaintext.bin' + '--keyfile', + 'test/negotiated_key.bin', + '--address', + '0x120000', + '--output', + 'test/enc-data.bin', + 'test/plaintext.bin', ] result = subprocess.run(command, capture_output=True, text=True) assert result.returncode == 0, f'Command failed with error: {result.stderr}' @@ -79,7 +83,9 @@ def calculate_key_manager_ecdh0_negotiated_key(k2_G_hex: str, k1_ecdsa_key: str) return negotiated_key -def test_ecdsa_key(negotiated_key: bytes, digest: bytes, signature_r_le: bytes, signature_s_le: bytes, pubx: bytes, puby: bytes) -> None: +def test_ecdsa_key( + negotiated_key: bytes, digest: bytes, signature_r_le: bytes, signature_s_le: bytes, pubx: bytes, puby: bytes +) -> None: r = int.from_bytes(signature_r_le, 'little') s = int.from_bytes(signature_s_le, 'little') signature = utils.encode_dss_signature(r, s) @@ -103,8 +109,8 @@ def test_ecdsa_key(negotiated_key: bytes, digest: bytes, signature_r_le: bytes, raise -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_crypto(dut: Dut) -> None: # if the env variable IDF_FPGA_ENV is set, we would need a longer timeout # as tests for efuses burning security peripherals would be run @@ -157,9 +163,9 @@ def test_crypto(dut: Dut) -> None: dut.expect('Tests finished', timeout=timeout) -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', ['long_aes_operations'], indirect=True) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_crypto_long_aes_operations(dut: Dut) -> None: # if the env variable IDF_FPGA_ENV is set, we would need a longer timeout # as tests for efuses burning security peripherals would be run diff --git a/components/hal/test_apps/hal_utils/pytest_hal_utils.py b/components/hal/test_apps/hal_utils/pytest_hal_utils.py index c8e422e42c..c49b80b090 100644 --- a/components/hal/test_apps/hal_utils/pytest_hal_utils.py +++ b/components/hal/test_apps/hal_utils/pytest_hal_utils.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_hal_utils(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/heap/test_apps/heap_tests/pytest_heap.py b/components/heap/test_apps/heap_tests/pytest_heap.py index 6f0c710bc2..9d53f81392 100644 --- a/components/heap/test_apps/heap_tests/pytest_heap.py +++ b/components/heap/test_apps/heap_tests/pytest_heap.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.supported_targets @pytest.mark.nightly_run @pytest.mark.parametrize( 'config', @@ -13,24 +13,20 @@ from pytest_embedded import Dut 'no_poisoning', 'light_poisoning', 'comprehensive_poisoning', - ] + ], ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_heap_poisoning(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.host_test @pytest.mark.qemu @pytest.mark.parametrize( 'config, embedded_services', - [ - ('no_poisoning', 'idf,qemu'), - ('light_poisoning', 'idf,qemu'), - ('comprehensive_poisoning', 'idf,qemu') - ] + [('no_poisoning', 'idf,qemu'), ('light_poisoning', 'idf,qemu'), ('comprehensive_poisoning', 'idf,qemu')], ) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_heap_poisoning_qemu(dut: Dut) -> None: for case in dut.test_menu: if 'qemu-ignore' not in case.groups and not case.is_ignored and case.type == 'normal': @@ -38,13 +34,8 @@ def test_heap_poisoning_qemu(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.supported_targets -@pytest.mark.parametrize( - 'config', - [ - 'in_flash' - ] -) +@pytest.mark.parametrize('config', ['in_flash']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_heap_in_flash(dut: Dut) -> None: dut.run_all_single_board_cases() @@ -56,15 +47,9 @@ def test_heap_in_flash(dut: Dut) -> None: 'esp32', 'esp32s2', 'esp32s3', - ] -) -@pytest.mark.parametrize( - 'config', - [ - 'psram', - 'psram_all_ext' - ] + ], ) +@pytest.mark.parametrize('config', ['psram', 'psram_all_ext']) def test_heap(dut: Dut) -> None: dut.run_all_single_board_cases(group='psram') @@ -74,19 +59,11 @@ def test_heap(dut: Dut) -> None: 'target', [ 'esp32', - ] -) -@pytest.mark.parametrize( - 'config', - [ - 'misc_options' - ] + ], ) +@pytest.mark.parametrize('config', ['misc_options']) def test_heap_misc_options(dut: Dut) -> None: - dut.run_all_single_board_cases(name=[ - 'IRAM_8BIT capability test', - 'test allocation and free function hooks' - ]) + dut.run_all_single_board_cases(name=['IRAM_8BIT capability test', 'test allocation and free function hooks']) dut.expect_exact("Enter next test, or 'enter' to see menu") dut.write('"When enabled, allocation operation failure generates an abort"') @@ -98,15 +75,9 @@ def test_heap_misc_options(dut: Dut) -> None: 'target', [ 'esp32', - ] -) -@pytest.mark.parametrize( - 'config', - [ - 'heap_trace', - 'heap_trace_hashmap' - ] + ], ) +@pytest.mark.parametrize('config', ['heap_trace', 'heap_trace_hashmap']) def test_heap_trace_dump(dut: Dut) -> None: dut.run_all_single_board_cases(group='trace-dump&internal') dut.run_all_single_board_cases(group='trace-dump&external') @@ -115,13 +86,8 @@ def test_heap_trace_dump(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.supported_targets @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='support TBD') # TODO [ESP32C61] IDF-9858 IDF-10989 -@pytest.mark.parametrize( - 'config', - [ - 'mem_prot' - ] -) +@pytest.mark.parametrize('config', ['mem_prot']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_memory_protection(dut: Dut) -> None: dut.run_all_single_board_cases(group='heap&mem_prot', timeout=300) diff --git a/components/heap/test_apps/host_test_linux/pytest_heap_linux.py b/components/heap/test_apps/host_test_linux/pytest_heap_linux.py index 41e79ac944..2eea038880 100644 --- a/components/heap/test_apps/host_test_linux/pytest_heap_linux.py +++ b/components/heap/test_apps/host_test_linux/pytest_heap_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_heap_linux(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=60) diff --git a/components/linux/test_apps/linux_test/pytest_linux_test.py b/components/linux/test_apps/linux_test/pytest_linux_test.py index f0e77455b1..1d6d342758 100644 --- a/components/linux/test_apps/linux_test/pytest_linux_test.py +++ b/components/linux/test_apps/linux_test/pytest_linux_test.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_linux_component(dut: IdfDut) -> None: dut.expect_exact('Press ENTER to see the list of tests.') dut.write('![ignore]') diff --git a/components/log/host_test/log_test/pytest_log_linux.py b/components/log/host_test/log_test/pytest_log_linux.py index 0425762aa4..5f5ffd1051 100644 --- a/components/log/host_test/log_test/pytest_log_linux.py +++ b/components/log/host_test/log_test/pytest_log_linux.py @@ -1,17 +1,21 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test -@pytest.mark.parametrize('config', [ - 'default', - 'system_timestamp' - 'tag_level_linked_list', - 'tag_level_linked_list_and_array_cache', - 'tag_level_none', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'system_timestamptag_level_linked_list', + 'tag_level_linked_list_and_array_cache', + 'tag_level_none', + ], + indirect=True, +) +@idf_parametrize('target', ['linux'], indirect=['target']) def test_log_linux(dut: Dut) -> None: dut.expect_exact('All tests passed', timeout=5) diff --git a/components/log/test_apps/pytest_esp_log.py b/components/log/test_apps/pytest_esp_log.py index 33414b08ae..6bba43e28e 100644 --- a/components/log/test_apps/pytest_esp_log.py +++ b/components/log/test_apps/pytest_esp_log.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_log(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/lwip/test_apps/pytest_lwip.py b/components/lwip/test_apps/pytest_lwip.py index 02b4bc2ee8..35e0667986 100644 --- a/components/lwip/test_apps/pytest_lwip.py +++ b/components/lwip/test_apps/pytest_lwip.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_lwip(dut: Dut) -> None: dut.expect_unity_test_output() diff --git a/components/mbedtls/test_apps/pytest_mbedtls_ut.py b/components/mbedtls/test_apps/pytest_mbedtls_ut.py index 2cfeef9c97..f90d73a220 100644 --- a/components/mbedtls/test_apps/pytest_mbedtls_ut.py +++ b/components/mbedtls/test_apps/pytest_mbedtls_ut.py @@ -1,16 +1,16 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_mbedtls(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -19,15 +19,11 @@ def test_mbedtls(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_mbedtls_esp32_compiler_perf_opt(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -36,15 +32,11 @@ def test_mbedtls_esp32_compiler_perf_opt(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5'], indirect=['target']) def test_mbedtls_aes_no_hw(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -54,32 +46,35 @@ def test_mbedtls_aes_no_hw(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c61'], indirect=['target']) def test_mbedtls_psram(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', - [ - 'psram_esp32p4_200m', - 'psram_all_ext_esp32p4_200m' - ], + ['psram_esp32p4_200m', 'psram_all_ext_esp32p4_200m'], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_mbedtls_psram_esp32p4(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32h2 @pytest.mark.ecdsa_efuse -@pytest.mark.parametrize('config', ['ecdsa_sign',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'ecdsa_sign', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32h2'], indirect=['target']) def test_mbedtls_ecdsa_sign(dut: Dut) -> None: dut.run_all_single_board_cases(group='efuse_key') -@pytest.mark.esp32c2 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -88,11 +83,11 @@ def test_mbedtls_ecdsa_sign(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_mbedtls_rom_impl_esp32c2(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -101,5 +96,6 @@ def test_mbedtls_rom_impl_esp32c2(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_mbedtls_ds_rsa(dut: Dut) -> None: dut.run_all_single_board_cases(group='ds_rsa') diff --git a/components/mqtt/test_apps/test_mqtt/pytest_mqtt_ut.py b/components/mqtt/test_apps/test_mqtt/pytest_mqtt_ut.py index 300d53ec45..b7782e446e 100644 --- a/components/mqtt/test_apps/test_mqtt/pytest_mqtt_ut.py +++ b/components/mqtt/test_apps/test_mqtt/pytest_mqtt_ut.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_mqtt_client(dut: Dut) -> None: dut.expect_unity_test_output() diff --git a/components/mqtt/test_apps/test_mqtt5/pytest_mqtt5_ut.py b/components/mqtt/test_apps/test_mqtt5/pytest_mqtt5_ut.py index df15c392b8..b1e9011de8 100644 --- a/components/mqtt/test_apps/test_mqtt5/pytest_mqtt5_ut.py +++ b/components/mqtt/test_apps/test_mqtt5/pytest_mqtt5_ut.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_mqtt5_client(dut: Dut) -> None: dut.expect_unity_test_output() diff --git a/components/newlib/test_apps/newlib/pytest_newlib.py b/components/newlib/test_apps/newlib/pytest_newlib.py index 8b2c5cc450..f065b648dc 100644 --- a/components/newlib/test_apps/newlib/pytest_newlib.py +++ b/components/newlib/test_apps/newlib/pytest_newlib.py @@ -1,21 +1,22 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.parametrize( - 'config', +@idf_parametrize( + 'config,target', [ - pytest.param('default', marks=[pytest.mark.supported_targets]), - pytest.param('options', marks=[pytest.mark.supported_targets]), - pytest.param('single_core_esp32', marks=[pytest.mark.esp32]), - pytest.param('psram_esp32', marks=[pytest.mark.esp32]), - pytest.param('release_esp32', marks=[pytest.mark.esp32]), - pytest.param('release_esp32c2', marks=[pytest.mark.esp32c2]), + ('default', 'supported_targets'), + ('options', 'supported_targets'), + ('single_core_esp32', 'esp32'), + ('psram_esp32', 'esp32'), + ('release_esp32', 'esp32'), + ('release_esp32c2', 'esp32c2'), ], - indirect=True + indirect=['config', 'target'], ) def test_newlib(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/nvs_flash/host_test/nvs_host_test/pytest_nvs_host_linux.py b/components/nvs_flash/host_test/nvs_host_test/pytest_nvs_host_linux.py index bc3828ada2..195d7cee55 100644 --- a/components/nvs_flash/host_test/nvs_host_test/pytest_nvs_host_linux.py +++ b/components/nvs_flash/host_test/nvs_host_test/pytest_nvs_host_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_nvs_host_linux(dut: Dut) -> None: dut.expect_exact('All tests passed', timeout=60) diff --git a/components/nvs_flash/host_test/nvs_page_test/pytest_nvs_page_linux.py b/components/nvs_flash/host_test/nvs_page_test/pytest_nvs_page_linux.py index dc8b09d2a5..c916e3b904 100644 --- a/components/nvs_flash/host_test/nvs_page_test/pytest_nvs_page_linux.py +++ b/components/nvs_flash/host_test/nvs_page_test/pytest_nvs_page_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_nvs_page_linux(dut: Dut) -> None: dut.expect_unity_test_output(timeout=120) diff --git a/components/nvs_flash/test_apps/pytest_nvs_flash.py b/components/nvs_flash/test_apps/pytest_nvs_flash.py index 3d6171de17..aa75ca38aa 100644 --- a/components/nvs_flash/test_apps/pytest_nvs_flash.py +++ b/components/nvs_flash/test_apps/pytest_nvs_flash.py @@ -1,45 +1,49 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize CONFIGS_NVS_ENCR_FLASH_ENC = [ - pytest.param('nvs_encr_flash_enc_esp32', marks=[pytest.mark.esp32]), + pytest.param('nvs_encr_flash_enc_esp32', marks=[pytest.mark.esp32]), pytest.param('nvs_encr_flash_enc_esp32c3', marks=[pytest.mark.esp32c3]), ] -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic @pytest.mark.parametrize('config', ['default'], indirect=True) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_nvs_flash(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='!nvs_encr_hmac', timeout=120) -@pytest.mark.esp32c3 @pytest.mark.nvs_encr_hmac @pytest.mark.parametrize('config', ['nvs_encr_hmac_esp32c3'], indirect=True) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_nvs_flash_encr_hmac(dut: IdfDut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c3 @pytest.mark.nvs_encr_hmac @pytest.mark.parametrize('config', ['nvs_encr_hmac_no_cfg_esp32c3'], indirect=True) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_nvs_flash_encr_hmac_no_cfg(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='nvs_encr_hmac', timeout=120) @pytest.mark.flash_encryption -@pytest.mark.parametrize('config', CONFIGS_NVS_ENCR_FLASH_ENC, indirect=True) +@idf_parametrize( + 'config,target', + [('nvs_encr_flash_enc_esp32', 'esp32'), ('nvs_encr_flash_enc_esp32c3', 'esp32c3')], + indirect=['config', 'target'], +) def test_nvs_flash_encr_flash_enc(dut: IdfDut) -> None: # Erase the nvs_key partition dut.serial.erase_partition('nvs_key') dut.run_all_single_board_cases() -@pytest.mark.esp32 @pytest.mark.psram +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_nvs_flash_ram(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='nvs_ram') diff --git a/components/nvs_flash/test_apps_bootloader/pytest_nvs_bootloader_support.py b/components/nvs_flash/test_apps_bootloader/pytest_nvs_bootloader_support.py index b7562bf5a0..27ca8e38a7 100644 --- a/components/nvs_flash/test_apps_bootloader/pytest_nvs_bootloader_support.py +++ b/components/nvs_flash/test_apps_bootloader/pytest_nvs_bootloader_support.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic @pytest.mark.parametrize('config', ['default'], indirect=True) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_nvs_bootloader_support(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/perfmon/test_apps/pytest_perfmon_ut.py b/components/perfmon/test_apps/pytest_perfmon_ut.py index 32adeee597..e4d80a3c26 100644 --- a/components/perfmon/test_apps/pytest_perfmon_ut.py +++ b/components/perfmon/test_apps/pytest_perfmon_ut.py @@ -1,13 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target']) def test_perfmon_ut(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/protocomm/test_apps/pytest_protocomm_ut.py b/components/protocomm/test_apps/pytest_protocomm_ut.py index 1235f234c6..3af4ecdf93 100644 --- a/components/protocomm/test_apps/pytest_protocomm_ut.py +++ b/components/protocomm/test_apps/pytest_protocomm_ut.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_protocomm(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/pthread/test_apps/pthread_psram_tests/pytest_pthread_psram_tests.py b/components/pthread/test_apps/pthread_psram_tests/pytest_pthread_psram_tests.py index 9da7f7cba3..d5278c245a 100644 --- a/components/pthread/test_apps/pthread_psram_tests/pytest_pthread_psram_tests.py +++ b/components/pthread/test_apps/pthread_psram_tests/pytest_pthread_psram_tests.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic @pytest.mark.psram +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_pthread_psram(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=10) diff --git a/components/pthread/test_apps/pthread_unity_tests/pytest_pthread_unity_tests.py b/components/pthread/test_apps/pthread_unity_tests/pytest_pthread_unity_tests.py index a9472aa73d..1fca004095 100644 --- a/components/pthread/test_apps/pthread_unity_tests/pytest_pthread_unity_tests.py +++ b/components/pthread/test_apps/pthread_unity_tests/pytest_pthread_unity_tests.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.supported_targets @pytest.mark.parametrize( 'config', [ @@ -13,25 +13,20 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_pthread(dut: Dut) -> None: dut.run_all_single_board_cases(group='!thread-specific', timeout=300) @pytest.mark.generic -@pytest.mark.parametrize( - 'config', - [ - pytest.param('single_core_esp32', marks=[pytest.mark.esp32]), - pytest.param('single_core_esp32s3', marks=[pytest.mark.esp32s3]), - ], - indirect=True, +@idf_parametrize( + 'config,target', [('single_core_esp32', 'esp32'), ('single_core_esp32s3', 'esp32s3')], indirect=['config', 'target'] ) def test_pthread_single_core(dut: Dut) -> None: dut.run_all_single_board_cases(group='!thread-specific', timeout=300) @pytest.mark.generic -@pytest.mark.supported_targets @pytest.mark.parametrize( 'config', [ @@ -39,32 +34,28 @@ def test_pthread_single_core(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_pthread_tls(dut: Dut) -> None: dut.run_all_single_board_cases(group='thread-specific', timeout=300) @pytest.mark.generic -@pytest.mark.parametrize( - 'config', - [ - pytest.param('single_core_esp32_tls', marks=[pytest.mark.esp32]), - ], - indirect=True, -) +@idf_parametrize('config', ['single_core_esp32_tls'], indirect=['config']) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_pthread_single_core_tls(dut: Dut) -> None: dut.run_all_single_board_cases(group='thread-specific', timeout=300) @pytest.mark.host_test @pytest.mark.qemu -@pytest.mark.esp32 +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_pthread_qemu(dut: Dut) -> None: for case in dut.test_menu: if 'qemu-ignore' not in case.groups and case.type == 'normal': dut._run_normal_case(case, timeout=75) -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_pthread_linux(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) diff --git a/components/rt/test_apps/posix_rt_test/pytest_rt_mqueue_tests.py b/components/rt/test_apps/posix_rt_test/pytest_rt_mqueue_tests.py index f43f8abc22..283da57b9f 100644 --- a/components/rt/test_apps/posix_rt_test/pytest_rt_mqueue_tests.py +++ b/components/rt/test_apps/posix_rt_test/pytest_rt_mqueue_tests.py @@ -1,13 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32p4 -@pytest.mark.esp32s2 +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32p4', 'esp32s2'], indirect=['target']) def test_rt_mqueue(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py b/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py index c4db18d729..f35624fc21 100644 --- a/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py +++ b/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -16,15 +16,11 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_flash(dut: Dut) -> None: dut.run_all_single_board_cases(group='esp_flash') -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -33,15 +29,11 @@ def test_esp_flash(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c2', 'esp32c6', 'esp32h2'], indirect=['target']) def test_esp_flash_rom(dut: Dut) -> None: dut.run_all_single_board_cases(group='esp_flash') -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c2 @pytest.mark.flash_multi @pytest.mark.parametrize( 'config', @@ -50,11 +42,11 @@ def test_esp_flash_rom(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c2'], indirect=['target']) def test_esp_flash_multi(dut: Dut) -> None: dut.run_all_single_board_cases(group='esp_flash_multi', timeout=120) -@pytest.mark.esp32c2 @pytest.mark.generic @pytest.mark.xtal_26mhz @pytest.mark.parametrize( @@ -65,5 +57,6 @@ def test_esp_flash_multi(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_esp_flash_26mhz_c2(dut: Dut) -> None: dut.run_all_single_board_cases(group='esp_flash') diff --git a/components/spi_flash/test_apps/esp_flash_stress/pytest_esp_flash_stress.py b/components/spi_flash/test_apps/esp_flash_stress/pytest_esp_flash_stress.py index 686f4de695..c89d76e1e3 100644 --- a/components/spi_flash/test_apps/esp_flash_stress/pytest_esp_flash_stress.py +++ b/components/spi_flash/test_apps/esp_flash_stress/pytest_esp_flash_stress.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -13,11 +13,11 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_flash_stress(dut: Dut) -> None: dut.run_all_single_board_cases(group='esp_flash') -@pytest.mark.esp32s3 @pytest.mark.MSPI_F8R8 @pytest.mark.parametrize( 'config', @@ -26,11 +26,11 @@ def test_esp_flash_stress(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_esp_flash_stress_f8r8(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -39,11 +39,11 @@ def test_esp_flash_stress_f8r8(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_esp_flash_stress_rom_xip_psram(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c3 @pytest.mark.flash_suspend @pytest.mark.parametrize( 'config', @@ -52,5 +52,6 @@ def test_esp_flash_stress_rom_xip_psram(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_flash_auto_suspend_stress(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/spi_flash/test_apps/flash_encryption/pytest_flash_encrypted.py b/components/spi_flash/test_apps/flash_encryption/pytest_flash_encrypted.py index 58112e1432..11e654951b 100644 --- a/components/spi_flash/test_apps/flash_encryption/pytest_flash_encrypted.py +++ b/components/spi_flash/test_apps/flash_encryption/pytest_flash_encrypted.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.flash_encryption @pytest.mark.parametrize( 'config', @@ -15,11 +14,11 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_flash_encryption(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c3 @pytest.mark.flash_encryption @pytest.mark.parametrize( 'config', @@ -28,11 +27,11 @@ def test_flash_encryption(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_flash_encryption_rom_impl(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s3 @pytest.mark.flash_encryption_f4r8 @pytest.mark.parametrize( 'config', @@ -43,11 +42,11 @@ def test_flash_encryption_rom_impl(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_flash_encryption_f4r8(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s3 @pytest.mark.flash_encryption_f8r8 @pytest.mark.parametrize( 'config', @@ -56,5 +55,6 @@ def test_flash_encryption_f4r8(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_flash_encryption_f8r8(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/spi_flash/test_apps/flash_mmap/pytest_flash_mmap.py b/components/spi_flash/test_apps/flash_mmap/pytest_flash_mmap.py index 0e5a8078b0..ea73906afd 100644 --- a/components/spi_flash/test_apps/flash_mmap/pytest_flash_mmap.py +++ b/components/spi_flash/test_apps/flash_mmap/pytest_flash_mmap.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -13,15 +13,11 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_flash_mmap(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=30) -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -30,11 +26,11 @@ def test_flash_mmap(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c2', 'esp32c6', 'esp32h2'], indirect=['target']) def test_flash_mmap_rom_impl(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=30) -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -43,11 +39,11 @@ def test_flash_mmap_rom_impl(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_flash_mmap_xip_psram(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=30) -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -56,11 +52,11 @@ def test_flash_mmap_xip_psram(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_flash_mmap_psram(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=30) -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -69,5 +65,6 @@ def test_flash_mmap_psram(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_flash_mmap_xip_psram_rom_impl(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=30) diff --git a/components/spi_flash/test_apps/flash_suspend/pytest_flash_auto_suspend.py b/components/spi_flash/test_apps/flash_suspend/pytest_flash_auto_suspend.py index f24ef1b8bc..5ad42893c4 100644 --- a/components/spi_flash/test_apps/flash_suspend/pytest_flash_auto_suspend.py +++ b/components/spi_flash/test_apps/flash_suspend/pytest_flash_auto_suspend.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c3 @pytest.mark.flash_suspend @pytest.mark.parametrize( 'config', @@ -14,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_flash_auto_suspend(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=30) diff --git a/components/spi_flash/test_apps/mspi_test/pytest_mspi_test.py b/components/spi_flash/test_apps/mspi_test/pytest_mspi_test.py index ecf7413eb0..801369074d 100644 --- a/components/spi_flash/test_apps/mspi_test/pytest_mspi_test.py +++ b/components/spi_flash/test_apps/mspi_test/pytest_mspi_test.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -14,12 +14,11 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_mspi_bus(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -28,13 +27,11 @@ def test_mspi_bus(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_mspi_bus_xip_psram(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -43,5 +40,6 @@ def test_mspi_bus_xip_psram(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target']) def test_mspi_bus_psram(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/spiffs/host_test/pytest_spiffs_linux.py b/components/spiffs/host_test/pytest_spiffs_linux.py index 18dbd3f2cd..46e5e062fc 100644 --- a/components/spiffs/host_test/pytest_spiffs_linux.py +++ b/components/spiffs/host_test/pytest_spiffs_linux.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test @pytest.mark.parametrize('config', ['erase_check', 'no_erase_check']) +@idf_parametrize('target', ['linux'], indirect=['target']) def test_spiffs_linux(dut: Dut) -> None: dut.expect_unity_test_output(timeout=5) diff --git a/components/spiffs/test_apps/pytest_spiffs.py b/components/spiffs/test_apps/pytest_spiffs.py index ef4a26fe16..cbeb8c62b7 100644 --- a/components/spiffs/test_apps/pytest_spiffs.py +++ b/components/spiffs/test_apps/pytest_spiffs.py @@ -1,24 +1,32 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'default', - 'release', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'release', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_spiffs_generic(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) -@pytest.mark.esp32s3 @pytest.mark.quad_psram -@pytest.mark.parametrize('config', [ - 'psram', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'psram', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_spiffs_psram(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) diff --git a/components/tcp_transport/test_apps/pytest_tcp_transport_ut.py b/components/tcp_transport/test_apps/pytest_tcp_transport_ut.py index e61f61788b..39652cc5e3 100644 --- a/components/tcp_transport/test_apps/pytest_tcp_transport_ut.py +++ b/components/tcp_transport/test_apps/pytest_tcp_transport_ut.py @@ -1,7 +1,8 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize CONFIGS = [ pytest.param('default', marks=[pytest.mark.esp32, pytest.mark.esp32c3]), @@ -10,6 +11,10 @@ CONFIGS = [ @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize( + 'config,target', + [('default', 'esp32'), ('default', 'esp32c3'), ('psram_esp32', 'esp32')], + indirect=['config', 'target'], +) def test_tcp_transport_client(dut: Dut) -> None: dut.expect_unity_test_output() diff --git a/components/touch_element/test_apps/pytest_touch_element.py b/components/touch_element/test_apps/pytest_touch_element.py index 75b07625be..bb0b565a49 100644 --- a/components/touch_element/test_apps/pytest_touch_element.py +++ b/components/touch_element/test_apps/pytest_touch_element.py @@ -1,19 +1,16 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize( 'config', - [ - 'opt_o0', - 'opt_o2' - ], + ['opt_o0', 'opt_o2'], indirect=True, ) +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_touch_element(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py b/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py index 4ac24826f4..e7f20ac731 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py @@ -1,12 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -15,12 +13,11 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4'], indirect=['target']) def test_lp_core(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32c5 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -29,11 +26,11 @@ def test_lp_core(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c5', 'esp32p4'], indirect=['target']) def test_lp_core_xtal(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32p4 @pytest.mark.lp_i2s @pytest.mark.parametrize( 'config', @@ -42,17 +39,16 @@ def test_lp_core_xtal(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_lp_vad(dut: Dut) -> None: dut.run_all_single_board_cases(group='lp_vad') -@pytest.mark.esp32c6 # TODO: Enable LP I2C test for esp32p4 (IDF-9407) @pytest.mark.generic_multi_device -@pytest.mark.parametrize( - 'count', [2], indirect=True -) -def test_lp_core_multi_device(case_tester) -> None: # type: ignore +@pytest.mark.parametrize('count', [2], indirect=True) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) +def test_lp_core_multi_device(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True) diff --git a/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py b/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py index 1da7285165..5093ccd611 100644 --- a/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py +++ b/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py @@ -1,13 +1,12 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4'], indirect=['target']) def test_lp_core_hp_uart_print(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('"lp-print can output to hp-uart"') @@ -16,10 +15,8 @@ def test_lp_core_hp_uart_print(dut: Dut) -> None: dut.expect_exact('56') -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4'], indirect=['target']) def test_lp_core_panic(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('"LP-Core panic"') @@ -29,10 +26,8 @@ def test_lp_core_panic(dut: Dut) -> None: dut.expect_exact('ELF file SHA256:') -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4'], indirect=['target']) def test_lp_core_shared_mem(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('"LP-Core Shared-mem"') @@ -49,8 +44,8 @@ def test_lp_core_shared_mem(dut: Dut) -> None: dut.expect_exact('HP shared memory test passed') -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_lp_core_lp_rom(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('"LP-Core LP-ROM"') diff --git a/components/ulp/test_apps/ulp_fsm/pytest_ulp_fsm_app.py b/components/ulp/test_apps/ulp_fsm/pytest_ulp_fsm_app.py index 67c57f2ade..cf51a6b7fd 100644 --- a/components/ulp/test_apps/ulp_fsm/pytest_ulp_fsm_app.py +++ b/components/ulp/test_apps/ulp_fsm/pytest_ulp_fsm_app.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target']) def test_ulp_fsm(dut: Dut) -> None: dut.run_all_single_board_cases(reset=True) diff --git a/components/ulp/test_apps/ulp_riscv/pytest_ulp_riscv.py b/components/ulp/test_apps/ulp_riscv/pytest_ulp_riscv.py index 6553fb42d9..67604286a2 100644 --- a/components/ulp/test_apps/ulp_riscv/pytest_ulp_riscv.py +++ b/components/ulp/test_apps/ulp_riscv/pytest_ulp_riscv.py @@ -1,23 +1,20 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_ulp_riscv(dut: Dut) -> None: # type: ignore dut.run_all_single_board_cases() -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic_multi_device -@pytest.mark.parametrize( - 'count', [2], indirect=True -) -def test_ulp_riscv_multi_device(case_tester) -> None: # type: ignore +@pytest.mark.parametrize('count', [2], indirect=True) +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) +def test_ulp_riscv_multi_device(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True) diff --git a/components/usb/test_apps/hcd/pytest_usb_hcd.py b/components/usb/test_apps/hcd/pytest_usb_hcd.py index 4303fabd16..5276b05f39 100644 --- a/components/usb/test_apps/hcd/pytest_usb_hcd.py +++ b/components/usb/test_apps/hcd/pytest_usb_hcd.py @@ -1,18 +1,22 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut - +from pytest_embedded_idf.utils import idf_parametrize CONFIGS = [ pytest.param('default', marks=[pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32p4]), - pytest.param('esp32p4_psram', marks=[pytest.mark.esp32p4]) + pytest.param('esp32p4_psram', marks=[pytest.mark.esp32p4]), ] @pytest.mark.usb_host_flash_disk @pytest.mark.temp_skip_ci(targets=['esp32s2'], reason='lack of runners with usb_host_flash_disk tag') -@pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize( + 'config,target', + [('default', 'esp32p4'), ('default', 'esp32s2'), ('default', 'esp32s3'), ('esp32p4_psram', 'esp32p4')], + indirect=['config', 'target'], +) def test_usb_hcd(dut: Dut) -> None: if dut.target == 'esp32p4': dut.run_all_single_board_cases(group='high_speed', reset=True) diff --git a/components/usb/test_apps/phy/pytest_usb_phy.py b/components/usb/test_apps/phy/pytest_usb_phy.py index fef606d3f0..ff2f14039c 100644 --- a/components/usb/test_apps/phy/pytest_usb_phy.py +++ b/components/usb/test_apps/phy/pytest_usb_phy.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_usb_phy(dut: Dut) -> None: dut.run_all_single_board_cases(group='phy') diff --git a/components/usb/test_apps/usb_host/pytest_usb_host.py b/components/usb/test_apps/usb_host/pytest_usb_host.py index 0d6e260333..181bee2ff5 100644 --- a/components/usb/test_apps/usb_host/pytest_usb_host.py +++ b/components/usb/test_apps/usb_host/pytest_usb_host.py @@ -1,14 +1,13 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32s2'], reason='lack of runners with usb_host_flash_disk tag') @pytest.mark.usb_host_flash_disk +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_usb_host(dut: Dut) -> None: if dut.target == 'esp32p4': dut.run_all_single_board_cases(group='high_speed', reset=True) diff --git a/components/vfs/test_apps/pytest_vfs.py b/components/vfs/test_apps/pytest_vfs.py index 60661554cd..97fc242786 100644 --- a/components/vfs/test_apps/pytest_vfs.py +++ b/components/vfs/test_apps/pytest_vfs.py @@ -1,34 +1,45 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'default', 'iram', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'iram', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c2', 'esp32c3', 'esp32c6', 'esp32h2'], indirect=['target']) def test_vfs_default(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'ccomp', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'ccomp', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_vfs_ccomp(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32s3 @pytest.mark.quad_psram -@pytest.mark.parametrize('config', [ - 'psram', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'psram', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_vfs_psram(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/wear_levelling/host_test/pytest_wear_levelling_linux.py b/components/wear_levelling/host_test/pytest_wear_levelling_linux.py index 64e79de405..b25fb724e2 100644 --- a/components/wear_levelling/host_test/pytest_wear_levelling_linux.py +++ b/components/wear_levelling/host_test/pytest_wear_levelling_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_wear_levelling_linux(dut: Dut) -> None: dut.expect_exact('All tests passed', timeout=120) diff --git a/components/wear_levelling/test_apps/pytest_wear_levelling.py b/components/wear_levelling/test_apps/pytest_wear_levelling.py index a88d0be4fa..0ef1fcecbc 100644 --- a/components/wear_levelling/test_apps/pytest_wear_levelling.py +++ b/components/wear_levelling/test_apps/pytest_wear_levelling.py @@ -1,17 +1,21 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - '4k', - '512perf', - '512safe', - 'release', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + '4k', + '512perf', + '512safe', + 'release', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_wear_levelling(dut: Dut) -> None: dut.expect_unity_test_output() diff --git a/components/wpa_supplicant/test_apps/pytest_wpa_supplicant_ut.py b/components/wpa_supplicant/test_apps/pytest_wpa_supplicant_ut.py index 03abfd1340..67736ec77c 100644 --- a/components/wpa_supplicant/test_apps/pytest_wpa_supplicant_ut.py +++ b/components/wpa_supplicant/test_apps/pytest_wpa_supplicant_ut.py @@ -1,37 +1,31 @@ -# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut from pytest_embedded_idf.unity_tester import CaseTester +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32c5 +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c2', 'esp32c6', 'esp32c61', 'esp32c5'], + indirect=['target'], +) def test_wpa_supplicant_ut(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.two_duts @pytest.mark.parametrize( 'count', [ 2, ], - indirect=True + indirect=True, +) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'], indirect=['target'] ) def test_wpa_supplicant_ut_offchan(case_tester: CaseTester) -> None: for case in case_tester.test_menu: diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/pytest_ble_throughput_test.py b/examples/bluetooth/bluedroid/ble/ble_throughput/pytest_ble_throughput_test.py index 9e9d830064..0f3f7b8457 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/pytest_ble_throughput_test.py +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/pytest_ble_throughput_test.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os.path import time @@ -6,30 +6,35 @@ from typing import Tuple import pytest from pytest_embedded_idf.dut import IdfDut - - +from pytest_embedded_idf.utils import idf_parametrize # Case 1: gatt write throughput test -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 + + @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, config, erase_all', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', - 'write', 'y'), + 'count, app_path, config, erase_all', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', + 'write', + 'y', + ), ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32c6', 'esp32c61', 'esp32c5', 'esp32h2', 'esp32s3'], indirect=['target'] +) def test_gatt_write_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: server = dut[0] client = dut[1] - client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') - server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + client_addr = ( + client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + server_addr = ( + server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) client.expect_exact('GATT client register, status 0', timeout=30) server.expect_exact('GATT server register, status 0', timeout=30) @@ -49,22 +54,31 @@ def test_gatt_write_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> Non # Case 2: gatt write throughput test for ESP32C2 26mhz xtal -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_all', [ - (2, 'esp32c2|esp32c2', '74880', - f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', - 'esp32c2_xtal26m_write', 'y'), + 'count, target, baud, app_path, config, erase_all', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', + 'esp32c2_xtal26m_write', + 'y', + ), ], indirect=True, ) def test_c2_26mhz_xtal_write_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: server = dut[0] client = dut[1] - client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') - server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + client_addr = ( + client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + server_addr = ( + server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) client.expect_exact('GATT client register, status 0', timeout=30) server.expect_exact('GATT server register, status 0', timeout=30) @@ -84,27 +98,31 @@ def test_c2_26mhz_xtal_write_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut # Case 3: gatt notify throughput test -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, config, erase_all', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', - 'notify', 'y'), + 'count, app_path, config, erase_all', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', + 'notify', + 'y', + ), ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32c6', 'esp32c61', 'esp32c5', 'esp32h2', 'esp32s3'], indirect=['target'] +) def test_gatt_notify_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: server = dut[0] client = dut[1] - client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') - server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + client_addr = ( + client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + server_addr = ( + server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) client.expect_exact('GATT client register, status 0', timeout=30) server.expect_exact('GATT server register, status 0', timeout=30) @@ -126,22 +144,31 @@ def test_gatt_notify_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> No # Case 4: gatt notify throughput test for ESP32C2 26mhz xtal -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_all', [ - (2, 'esp32c2|esp32c2', '74880', - f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', - 'esp32c2_xtal26m_notify', 'y'), + 'count, target, baud, app_path, config, erase_all', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', + 'esp32c2_xtal26m_notify', + 'y', + ), ], indirect=True, ) def test_c2_26mhz_xtal_notify_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: server = dut[0] client = dut[1] - client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') - server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + client_addr = ( + client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + server_addr = ( + server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) client.expect_exact('GATT client register, status 0', timeout=30) server.expect_exact('GATT server register, status 0', timeout=30) diff --git a/examples/bluetooth/bluedroid/ble/pytest_ble_test.py b/examples/bluetooth/bluedroid/ble/pytest_ble_test.py index 776d9d4cf2..a84e328d81 100644 --- a/examples/bluetooth/bluedroid/ble/pytest_ble_test.py +++ b/examples/bluetooth/bluedroid/ble/pytest_ble_test.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os.path from typing import Tuple @@ -6,30 +6,35 @@ from typing import Tuple import pexpect import pytest from pytest_embedded_idf.dut import IdfDut - - +from pytest_embedded_idf.utils import idf_parametrize # Case 1: gatt client and gatt server test -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 + + @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, config, erase_all', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "gatt_server")}|{os.path.join(os.path.dirname(__file__), "gatt_client")}', - 'name', 'y'), + 'count, app_path, config, erase_all', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "gatt_server")}|{os.path.join(os.path.dirname(__file__), "gatt_client")}', + 'name', + 'y', + ), ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32c6', 'esp32c5', 'esp32h2', 'esp32s3', 'esp32c61'], indirect=['target'] +) def test_gatt_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: gatt_client = dut[1] gatt_server = dut[0] - gatt_client_addr = gatt_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') - gatt_server_addr = gatt_server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + gatt_client_addr = ( + gatt_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + gatt_server_addr = ( + gatt_server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) gatt_client.expect_exact('GATT client register, status 0', timeout=30) gatt_server.expect_exact('GATT server register, status 0', timeout=30) gatt_server.expect_exact('Advertising start successfully', timeout=30) @@ -53,22 +58,31 @@ def test_gatt_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # Case 2: gatt client and gatt server test for ESP32C2 26mhz xtal -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_all', [ - (2, 'esp32c2|esp32c2', '74880', - f'{os.path.join(os.path.dirname(__file__), "gatt_server")}|{os.path.join(os.path.dirname(__file__), "gatt_client")}', - 'esp32c2_xtal26m', 'y'), + 'count, target, baud, app_path, config, erase_all', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + f'{os.path.join(os.path.dirname(__file__), "gatt_server")}|{os.path.join(os.path.dirname(__file__), "gatt_client")}', + 'esp32c2_xtal26m', + 'y', + ), ], indirect=True, ) def test_c2_26mhz_xtal_gatt_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: gatt_client = dut[1] gatt_server = dut[0] - gatt_client_addr = gatt_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})').group(1).decode('utf8') - gatt_server_addr = gatt_server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})').group(1).decode('utf8') + gatt_client_addr = ( + gatt_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})').group(1).decode('utf8') + ) + gatt_server_addr = ( + gatt_server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})').group(1).decode('utf8') + ) gatt_client.expect_exact('GATT client register, status 0', timeout=30) gatt_server.expect_exact('GATT server register, status 0', timeout=30) gatt_server.expect_exact('Advertising start successfully', timeout=30) @@ -92,26 +106,30 @@ def test_c2_26mhz_xtal_gatt_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> N # Case 3: gatt security server and gatt security client test -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, config, erase_all', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "gatt_security_server")}|{os.path.join(os.path.dirname(__file__), "gatt_security_client")}', - 'name', 'y'), + 'count, app_path, config, erase_all', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "gatt_security_server")}|{os.path.join(os.path.dirname(__file__), "gatt_security_client")}', + 'name', + 'y', + ), ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32c6', 'esp32c5', 'esp32h2', 'esp32s3', 'esp32c61'], indirect=['target'] +) def test_gatt_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut], target: Tuple) -> None: gatt_security_client = dut[1] gatt_security_server = dut[0] - gatt_security_client_addr = gatt_security_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + gatt_security_client_addr = ( + gatt_security_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30) + .group(1) + .decode('utf8') + ) gatt_security_client.expect_exact('GATT client register, status 0', timeout=30) gatt_security_server.expect_exact('GATT server register, status 0', timeout=30) @@ -138,7 +156,9 @@ def test_gatt_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut], target: T if target == ('esp32', 'esp32'): gatt_security_server.expect_exact(f'Authentication complete, addr_type 1, addr ', timeout=30) else: - gatt_security_server.expect_exact(f'Authentication complete, addr_type 0, addr {gatt_security_client_addr}', timeout=30) + gatt_security_server.expect_exact( + f'Authentication complete, addr_type 0, addr {gatt_security_client_addr}', timeout=30 + ) gatt_security_client.expect_exact(f'Authentication complete, addr_type 1, addr ', timeout=30) gatt_security_server.expect_exact('Pairing successfully', timeout=30) gatt_security_server.expect_exact('Bonded devices number 1', timeout=30) @@ -153,21 +173,30 @@ def test_gatt_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut], target: T # Case 4: gatt security server and gatt security client test for ESP32C2 26mhz xtal -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_all', [ - (2, 'esp32c2|esp32c2', '74880', - f'{os.path.join(os.path.dirname(__file__), "gatt_security_server")}|{os.path.join(os.path.dirname(__file__), "gatt_security_client")}', - 'esp32c2_xtal26m', 'y'), + 'count, target, baud, app_path, config, erase_all', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + f'{os.path.join(os.path.dirname(__file__), "gatt_security_server")}|{os.path.join(os.path.dirname(__file__), "gatt_security_client")}', + 'esp32c2_xtal26m', + 'y', + ), ], indirect=True, ) def test_c2_26mhz_xtal_gatt_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: gatt_security_client = dut[1] gatt_security_server = dut[0] - gatt_security_client_addr = gatt_security_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + gatt_security_client_addr = ( + gatt_security_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30) + .group(1) + .decode('utf8') + ) gatt_security_client.expect_exact('GATT client register, status 0', timeout=30) gatt_security_server.expect_exact('GATT server register, status 0', timeout=30) @@ -188,7 +217,9 @@ def test_c2_26mhz_xtal_gatt_security_func(app_path: str, dut: Tuple[IdfDut, IdfD gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_PENC', timeout=30) gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_LID', timeout=30) gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_PID', timeout=30) - gatt_security_server.expect_exact(f'Authentication complete, addr_type 0, addr {gatt_security_client_addr}', timeout=30) + gatt_security_server.expect_exact( + f'Authentication complete, addr_type 0, addr {gatt_security_client_addr}', timeout=30 + ) gatt_security_client.expect_exact(f'Authentication complete, addr_type 1, addr ', timeout=30) gatt_security_server.expect_exact('Pairing successfully', timeout=30) gatt_security_server.expect_exact('Bonded devices number 1', timeout=30) @@ -203,27 +234,31 @@ def test_c2_26mhz_xtal_gatt_security_func(app_path: str, dut: Tuple[IdfDut, IdfD # Case 5: ble ibeacon test -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, config, erase_all', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}|{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}', - 'sender|receiver', 'y'), + 'count, app_path, config, erase_all', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}|{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}', + 'sender|receiver', + 'y', + ), ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32c6', 'esp32c5', 'esp32h2', 'esp32s3', 'esp32c61'], indirect=['target'] +) def test_ble_ibeacon_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: ibeacon_sender = dut[0] ibeacon_receiver = dut[1] - ibeacon_sender_addr = ibeacon_sender.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ibeacon_sender_addr = ( + ibeacon_sender.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30) + .group(1) + .decode('utf8') + ) ibeacon_sender.expect_exact('Advertising start successfully', timeout=30) ibeacon_receiver.expect_exact('Scanning start successfully', timeout=30) @@ -237,14 +272,19 @@ def test_ble_ibeacon_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # Case 5: ble ibeacon test for ESP32C2 26mhz xtal -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_all', [ - (2, 'esp32c2|esp32c2', '74880', - f'{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}|{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}', - 'esp32c2_xtal26m_sender|esp32c2_xtal26m_receiver', 'y'), + 'count, target, baud, app_path, config, erase_all', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + f'{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}|{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}', + 'esp32c2_xtal26m_sender|esp32c2_xtal26m_receiver', + 'y', + ), ], indirect=True, ) @@ -252,7 +292,11 @@ def test_c2_26mhz_ble_ibeacon_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> ibeacon_sender = dut[0] ibeacon_receiver = dut[1] - ibeacon_sender_addr = ibeacon_sender.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ibeacon_sender_addr = ( + ibeacon_sender.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30) + .group(1) + .decode('utf8') + ) ibeacon_sender.expect_exact('Advertising start successfully', timeout=30) ibeacon_receiver.expect_exact('Scanning start successfully', timeout=30) diff --git a/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py b/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py index d1c8d0afac..c3ea7a1517 100644 --- a/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py +++ b/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py @@ -1,33 +1,37 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os.path from typing import Tuple import pytest from pytest_embedded_idf.dut import IdfDut - - +from pytest_embedded_idf.utils import idf_parametrize # Case 1: ble50 security client and ble50 security server test -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 + + @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, config, erase_all', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "ble50_security_server")}|{os.path.join(os.path.dirname(__file__), "ble50_security_client")}', - 'name', 'y'), + 'count, app_path, config, erase_all', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "ble50_security_server")}|{os.path.join(os.path.dirname(__file__), "ble50_security_client")}', + 'name', + 'y', + ), ], indirect=True, ) +@idf_parametrize('target', ['esp32c3', 'esp32c6', 'esp32c5', 'esp32h2', 'esp32s3', 'esp32c61'], indirect=['target']) def test_ble50_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: server = dut[0] client = dut[1] - client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') - server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + client_addr = ( + client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + server_addr = ( + server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) server.expect_exact('Extended advertising params set, status 0', timeout=30) server.expect_exact('Extended advertising data set, status 0', timeout=30) @@ -46,22 +50,31 @@ def test_ble50_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # Case 2: ble50 security client and ble50 security server test for ESP32C2 26mhz xtal -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_all', [ - (2, 'esp32c2|esp32c2', '74880', - f'{os.path.join(os.path.dirname(__file__), "ble50_security_server")}|{os.path.join(os.path.dirname(__file__), "ble50_security_client")}', - 'esp32c2_xtal26m', 'y'), + 'count, target, baud, app_path, config, erase_all', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + f'{os.path.join(os.path.dirname(__file__), "ble50_security_server")}|{os.path.join(os.path.dirname(__file__), "ble50_security_client")}', + 'esp32c2_xtal26m', + 'y', + ), ], indirect=True, ) def test_c2_26mhz_xtal_ble50_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: server = dut[0] client = dut[1] - client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') - server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + client_addr = ( + client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + server_addr = ( + server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) server.expect_exact('Extended advertising params set, status 0', timeout=30) server.expect_exact('Extended advertising data set, status 0', timeout=30) @@ -80,21 +93,20 @@ def test_c2_26mhz_xtal_ble50_security_func(app_path: str, dut: Tuple[IdfDut, Idf # Case 3: period_adv and period_sync test -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, config, erase_all', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "periodic_adv")}|{os.path.join(os.path.dirname(__file__), "periodic_sync")}', - 'name', 'y'), + 'count, app_path, config, erase_all', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "periodic_adv")}|{os.path.join(os.path.dirname(__file__), "periodic_sync")}', + 'name', + 'y', + ), ], indirect=True, ) +@idf_parametrize('target', ['esp32c3', 'esp32c6', 'esp32c5', 'esp32h2', 'esp32s3', 'esp32c61'], indirect=['target']) def test_period_adv_sync_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: adv_dut = dut[0] sync_dut = dut[1] @@ -114,14 +126,19 @@ def test_period_adv_sync_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None # Case 4: period_adv and period_sync test for ESP32C2 26mhz xtal -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_all', [ - (2, 'esp32c2|esp32c2', '74880', - f'{os.path.join(os.path.dirname(__file__), "periodic_adv")}|{os.path.join(os.path.dirname(__file__), "periodic_sync")}', - 'esp32c2_xtal26m', 'y'), + 'count, target, baud, app_path, config, erase_all', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + f'{os.path.join(os.path.dirname(__file__), "periodic_adv")}|{os.path.join(os.path.dirname(__file__), "periodic_sync")}', + 'esp32c2_xtal26m', + 'y', + ), ], indirect=True, ) diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/pytest_classic_bt_cover_art_test.py b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/pytest_classic_bt_cover_art_test.py index 9ce09d54da..8e141cafac 100644 --- a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/pytest_classic_bt_cover_art_test.py +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/pytest_classic_bt_cover_art_test.py @@ -5,7 +5,6 @@ from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic @idf_parametrize('target', ['esp32'], indirect=['target']) def test_bt_avrcp_cover_art(dut: Dut) -> None: diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/pytest_classic_bt_metadata_test.py b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/pytest_classic_bt_metadata_test.py index 43ffb22648..1c01e7fff8 100644 --- a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/pytest_classic_bt_metadata_test.py +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/pytest_classic_bt_metadata_test.py @@ -5,7 +5,6 @@ from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic @idf_parametrize('target', ['esp32'], indirect=['target']) def test_bt_avrcp_metadata(dut: Dut) -> None: diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_discovery/pytest_classic_bt_discovery_test.py b/examples/bluetooth/bluedroid/classic_bt/bt_discovery/pytest_classic_bt_discovery_test.py index d68b55be8c..bb7cedca90 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_discovery/pytest_classic_bt_discovery_test.py +++ b/examples/bluetooth/bluedroid/classic_bt/bt_discovery/pytest_classic_bt_discovery_test.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_bt_discovery(dut: Dut) -> None: dut.expect_exact('Discovery started.') diff --git a/examples/bluetooth/bluedroid/classic_bt/pytest_classic_bt_test.py b/examples/bluetooth/bluedroid/classic_bt/pytest_classic_bt_test.py index dcd33dc889..1922d2e6b9 100644 --- a/examples/bluetooth/bluedroid/classic_bt/pytest_classic_bt_test.py +++ b/examples/bluetooth/bluedroid/classic_bt/pytest_classic_bt_test.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os.path from typing import Tuple @@ -6,16 +6,20 @@ from typing import Tuple import pexpect import pytest from pytest_embedded_idf.dut import IdfDut - - # Case 1: SPP -@pytest.mark.esp32 + + @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, target, erase_all, config', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "bt_spp_acceptor")}|{os.path.join(os.path.dirname(__file__), "bt_spp_initiator")}', - 'esp32|esp32', 'y', 'test'), + 'count, app_path, target, erase_all, config', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "bt_spp_acceptor")}|{os.path.join(os.path.dirname(__file__), "bt_spp_initiator")}', + 'esp32|esp32', + 'y', + 'test', + ), ], indirect=True, ) @@ -39,13 +43,16 @@ def test_bt_spp_only(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # Case 2: SPP_VFS -@pytest.mark.esp32 @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, target, config', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "bt_spp_vfs_acceptor")}|{os.path.join(os.path.dirname(__file__), "bt_spp_vfs_initiator")}', - 'esp32|esp32', 'test'), + 'count, app_path, target, config', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "bt_spp_vfs_acceptor")}|{os.path.join(os.path.dirname(__file__), "bt_spp_vfs_initiator")}', + 'esp32|esp32', + 'test', + ), ], indirect=True, ) @@ -64,13 +71,16 @@ def test_bt_spp_vfs(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # Case 3: HFP -@pytest.mark.esp32 @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, target, config', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "hfp_ag")}|{os.path.join(os.path.dirname(__file__), "hfp_hf")}', - 'esp32|esp32', 'all'), + 'count, app_path, target, config', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "hfp_ag")}|{os.path.join(os.path.dirname(__file__), "hfp_hf")}', + 'esp32|esp32', + 'all', + ), ], indirect=True, ) @@ -86,14 +96,17 @@ def test_bt_hfp(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # # Case 4: HID -@pytest.mark.esp32 @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, target, config', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "bt_hid_mouse_device")}|' - f'{os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")), "esp_hid_host")}', - 'esp32|esp32', 'test'), + 'count, app_path, target, config', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "bt_hid_mouse_device")}|' + f'{os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")), "esp_hid_host")}', + 'esp32|esp32', + 'test', + ), ], indirect=True, ) @@ -112,13 +125,16 @@ def test_bt_hid(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # Case 5: L2CAP -@pytest.mark.esp32 @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path, target, config', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "bt_l2cap_server")}|{os.path.join(os.path.dirname(__file__), "bt_l2cap_client")}', - 'esp32|esp32', 'test'), + 'count, app_path, target, config', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "bt_l2cap_server")}|{os.path.join(os.path.dirname(__file__), "bt_l2cap_client")}', + 'esp32|esp32', + 'test', + ), ], indirect=True, ) @@ -139,7 +155,6 @@ def test_bt_l2cap(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # case 6: A2DP Stream -@pytest.mark.esp32 @pytest.mark.two_duts @pytest.mark.parametrize( 'count, app_path, target, config', @@ -165,7 +180,6 @@ def test_bt_a2dp_stream(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # case 7: AVRCP absolute volume -@pytest.mark.esp32 @pytest.mark.two_duts @pytest.mark.parametrize( 'count, app_path, target, config', diff --git a/examples/bluetooth/nimble/pytest_nimble_test.py b/examples/bluetooth/nimble/pytest_nimble_test.py index ae336a9281..fd2b560890 100644 --- a/examples/bluetooth/nimble/pytest_nimble_test.py +++ b/examples/bluetooth/nimble/pytest_nimble_test.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os.path from typing import Tuple @@ -6,24 +6,24 @@ from typing import Tuple import pexpect import pytest from pytest_embedded_idf.dut import IdfDut - - +from pytest_embedded_idf.utils import idf_parametrize # Case 1: BLE power save test -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32 + + @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "power_save")}|{os.path.join(os.path.dirname(__file__), "blecent")}'), + 'count, app_path', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "power_save")}|{os.path.join(os.path.dirname(__file__), "blecent")}', + ), ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32c6', 'esp32h2', 'esp32c3', 'esp32s3', 'esp32c5', 'esp32c61', 'esp32'], indirect=['target'] +) def test_power_save_conn(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: peripheral = dut[0] central = dut[1] @@ -39,17 +39,21 @@ def test_power_save_conn(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # Case 2: BLE power save test for ESP32C2 -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'config, count, app_path, baud', [ - ('esp32c2_xtal26m', 2, - f'{os.path.join(os.path.dirname(__file__), "power_save")}|{os.path.join(os.path.dirname(__file__), "blecent")}', - '74880'), + 'config, count, app_path, baud', + [ + ( + 'esp32c2_xtal26m', + 2, + f'{os.path.join(os.path.dirname(__file__), "power_save")}|{os.path.join(os.path.dirname(__file__), "blecent")}', + '74880', + ), ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_power_save_conn_esp32c2_26mhz(dut: Tuple[IdfDut, IdfDut]) -> None: peripheral = dut[0] central = dut[1] diff --git a/examples/build_system/cmake/import_lib/pytest_import_lib.py b/examples/build_system/cmake/import_lib/pytest_import_lib.py index 2bb4845224..ab7f82cb56 100644 --- a/examples/build_system/cmake/import_lib/pytest_import_lib.py +++ b/examples/build_system/cmake/import_lib/pytest_import_lib.py @@ -1,14 +1,13 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest +from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_qemu.dut import QemuDut -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.host_test @pytest.mark.qemu +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_pytest_host(dut: QemuDut) -> None: dut.expect_exact('Initializing the filesystem') dut.expect_exact('Read XML data:') @@ -16,5 +15,5 @@ def test_pytest_host(dut: QemuDut) -> None: dut.expect_exact('To: Tove') dut.expect_exact('From: Jani') dut.expect_exact('Heading: Reminder') - dut.expect_exact('Body: Don\'t forget me this weekend!') + dut.expect_exact("Body: Don't forget me this weekend!") dut.expect_exact('Example end', timeout=20) diff --git a/examples/build_system/cmake/plugins/pytest_plugins.py b/examples/build_system/cmake/plugins/pytest_plugins.py index ece4ea019d..f2574fb60f 100644 --- a/examples/build_system/cmake/plugins/pytest_plugins.py +++ b/examples/build_system/cmake/plugins/pytest_plugins.py @@ -1,15 +1,14 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import textwrap import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_plugins(dut: Dut) -> None: log_text = textwrap.dedent(r""" Nihao plugin performing self-registration... diff --git a/examples/custom_bootloader/bootloader_hooks/pytest_custom_bootloader_hooks.py b/examples/custom_bootloader/bootloader_hooks/pytest_custom_bootloader_hooks.py index f96a8502eb..c3ff1589d1 100644 --- a/examples/custom_bootloader/bootloader_hooks/pytest_custom_bootloader_hooks.py +++ b/examples/custom_bootloader/bootloader_hooks/pytest_custom_bootloader_hooks.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_custom_bootloader_hooks_example(dut: Dut) -> None: # Expect to read both hooks messages dut.expect_exact('This hook is called BEFORE bootloader initialization') diff --git a/examples/custom_bootloader/bootloader_override/pytest_custom_bootloader_override.py b/examples/custom_bootloader/bootloader_override/pytest_custom_bootloader_override.py index 21a07ad0f3..39ffede0ef 100644 --- a/examples/custom_bootloader/bootloader_override/pytest_custom_bootloader_override.py +++ b/examples/custom_bootloader/bootloader_override/pytest_custom_bootloader_override.py @@ -1,13 +1,13 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut from pytest_embedded_idf.app import IdfApp +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_custom_bootloader_impl_example(app: IdfApp, dut: Dut) -> None: # Expect to read a message from the custom bootloader # This message is defined in the Kconfig file, retrieve it while deleting diff --git a/examples/cxx/exceptions/pytest_examples_cxx_exceptions.py b/examples/cxx/exceptions/pytest_examples_cxx_exceptions.py index 0aa17b4c57..93180c51ac 100644 --- a/examples/cxx/exceptions/pytest_examples_cxx_exceptions.py +++ b/examples/cxx/exceptions/pytest_examples_cxx_exceptions.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_examples_cpp_exceptions(dut: IdfDut) -> None: lines = [ 'app_main starting', diff --git a/examples/cxx/pthread/pytest_examples_cxx_pthread.py b/examples/cxx/pthread/pytest_examples_cxx_pthread.py index 904e273f05..9d54060645 100644 --- a/examples/cxx/pthread/pytest_examples_cxx_pthread.py +++ b/examples/cxx/pthread/pytest_examples_cxx_pthread.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_examples_cpp_pthread(dut: IdfDut) -> None: dut.expect( [ diff --git a/examples/cxx/rtti/pytest_examples_cxx_rtti.py b/examples/cxx/rtti/pytest_examples_cxx_rtti.py index d92432ae01..f48ef2f4f3 100644 --- a/examples/cxx/rtti/pytest_examples_cxx_rtti.py +++ b/examples/cxx/rtti/pytest_examples_cxx_rtti.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_cpp_rtti_example(dut: IdfDut) -> None: dut.expect_exact('Type name of std::cout is: std::ostream') dut.expect_exact('Type name of std::cin is: std::istream') diff --git a/examples/ethernet/basic/pytest_eth_basic.py b/examples/ethernet/basic/pytest_eth_basic.py index 74c5a2ac63..5fea6a5faa 100644 --- a/examples/ethernet/basic/pytest_eth_basic.py +++ b/examples/ethernet/basic/pytest_eth_basic.py @@ -1,21 +1,24 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import platform import subprocess import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.parametrize('config', [ - pytest.param('default_ip101', marks=[pytest.mark.ethernet_router]), - pytest.param('default_generic', marks=[pytest.mark.ethernet_router]), - pytest.param('default_dm9051', marks=[pytest.mark.eth_dm9051]), -], indirect=True) -def test_esp_eth_basic( - dut: Dut -) -> None: +@pytest.mark.parametrize( + 'config', + [ + pytest.param('default_ip101', marks=[pytest.mark.ethernet_router]), + pytest.param('default_generic', marks=[pytest.mark.ethernet_router]), + pytest.param('default_dm9051', marks=[pytest.mark.eth_dm9051]), + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) +def test_esp_eth_basic(dut: Dut) -> None: # wait for ip received dut_ip = dut.expect(r'esp_netif_handlers: .+ ip: (\d+\.\d+\.\d+\.\d+),').group(1) # ping it once diff --git a/examples/ethernet/iperf/pytest_eth_iperf.py b/examples/ethernet/iperf/pytest_eth_iperf.py index ad80a84ef0..3a40dd89b0 100644 --- a/examples/ethernet/iperf/pytest_eth_iperf.py +++ b/examples/ethernet/iperf/pytest_eth_iperf.py @@ -1,5 +1,14 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 +import os +import subprocess + +import pytest +from common_test_methods import get_host_ip4_by_dest_ip +from idf_iperf_test_util import IperfUtility +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize + """ Test case for iperf example. @@ -8,13 +17,6 @@ This test case might have problem running on Windows: - use `sudo killall iperf` to force kill iperf, didn't implement windows version """ -import os -import subprocess - -import pytest -from common_test_methods import get_host_ip4_by_dest_ip -from idf_iperf_test_util import IperfUtility -from pytest_embedded import Dut try: from typing import Any, Callable, Tuple, Optional @@ -26,11 +28,16 @@ NO_BANDWIDTH_LIMIT = -1 # iperf send bandwidth is not limited class IperfTestUtilityEth(IperfUtility.IperfTestUtility): - """ iperf test implementation """ - def __init__(self, dut: str, config_name: str, pc_nic_ip: str, pc_iperf_log_file: str, test_result:Any=None) -> None: - IperfUtility.IperfTestUtility.__init__(self, dut, config_name, 'None', 'None', pc_nic_ip, pc_iperf_log_file, test_result) + """iperf test implementation""" - def setup(self) -> Tuple[str,int]: + def __init__( + self, dut: str, config_name: str, pc_nic_ip: str, pc_iperf_log_file: str, test_result: Any = None + ) -> None: + IperfUtility.IperfTestUtility.__init__( + self, dut, config_name, 'None', 'None', pc_nic_ip, pc_iperf_log_file, test_result + ) + + def setup(self) -> Tuple[str, int]: """ setup iperf test: @@ -55,7 +62,7 @@ def test_esp_eth_iperf( check_performance: Callable[[str, float, str], None], udp_tx_bw_lim: Optional[int] = NO_BANDWIDTH_LIMIT, udp_rx_bw_lim: Optional[int] = NO_BANDWIDTH_LIMIT, - spi_eth: Optional[bool] = False + spi_eth: Optional[bool] = False, ) -> None: """ steps: | @@ -86,26 +93,36 @@ def test_esp_eth_iperf( # 4. log performance and compare with pass standard for throughput_type in test_result: - log_performance('{}_throughput'.format(throughput_type), - '{:.02f} Mbps'.format(test_result[throughput_type].get_best_throughput())) + log_performance( + '{}_throughput'.format(throughput_type), + '{:.02f} Mbps'.format(test_result[throughput_type].get_best_throughput()), + ) # do check after logging, otherwise test will exit immediately if check fail, some performance can't be logged. for throughput_type in test_result: if spi_eth: - check_performance('{}_eth_throughput_spi_eth'.format(throughput_type), - test_result[throughput_type].get_best_throughput(), - dut.target) + check_performance( + '{}_eth_throughput_spi_eth'.format(throughput_type), + test_result[throughput_type].get_best_throughput(), + dut.target, + ) else: - check_performance('{}_eth_throughput'.format(throughput_type), - test_result[throughput_type].get_best_throughput(), - dut.target) + check_performance( + '{}_eth_throughput'.format(throughput_type), + test_result[throughput_type].get_best_throughput(), + dut.target, + ) -@pytest.mark.esp32 @pytest.mark.ethernet_router -@pytest.mark.parametrize('config', [ - 'default_ip101', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_ip101', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_iperf_ip101( dut: Dut, log_performance: Callable[[str, object], None], @@ -114,11 +131,15 @@ def test_esp_eth_iperf_ip101( test_esp_eth_iperf(dut, log_performance, check_performance, udp_tx_bw_lim=90) -@pytest.mark.esp32p4 @pytest.mark.eth_ip101 -@pytest.mark.parametrize('config', [ - 'default_ip101_esp32p4', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_ip101_esp32p4', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_esp_eth_iperf_ip101_esp32p4( dut: Dut, log_performance: Callable[[str, object], None], @@ -127,11 +148,15 @@ def test_esp_eth_iperf_ip101_esp32p4( test_esp_eth_iperf(dut, log_performance, check_performance, udp_tx_bw_lim=96) -@pytest.mark.esp32 @pytest.mark.eth_lan8720 -@pytest.mark.parametrize('config', [ - 'default_lan8720', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_lan8720', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_iperf_lan8720( dut: Dut, log_performance: Callable[[str, object], None], @@ -140,11 +165,15 @@ def test_esp_eth_iperf_lan8720( test_esp_eth_iperf(dut, log_performance, check_performance, udp_tx_bw_lim=90) -@pytest.mark.esp32 @pytest.mark.eth_rtl8201 -@pytest.mark.parametrize('config', [ - 'default_rtl8201', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_rtl8201', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_iperf_rtl8201( dut: Dut, log_performance: Callable[[str, object], None], @@ -153,11 +182,15 @@ def test_esp_eth_iperf_rtl8201( test_esp_eth_iperf(dut, log_performance, check_performance, udp_tx_bw_lim=90) -@pytest.mark.esp32 @pytest.mark.eth_dp83848 -@pytest.mark.parametrize('config', [ - 'default_dp83848', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_dp83848', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_iperf_dp83848( dut: Dut, log_performance: Callable[[str, object], None], @@ -166,11 +199,15 @@ def test_esp_eth_iperf_dp83848( test_esp_eth_iperf(dut, log_performance, check_performance, udp_tx_bw_lim=90) -@pytest.mark.esp32 @pytest.mark.eth_ksz8041 -@pytest.mark.parametrize('config', [ - 'default_ksz8041', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_ksz8041', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_iperf_ksz8041( dut: Dut, log_performance: Callable[[str, object], None], @@ -179,11 +216,15 @@ def test_esp_eth_iperf_ksz8041( test_esp_eth_iperf(dut, log_performance, check_performance, udp_tx_bw_lim=90) -@pytest.mark.esp32 @pytest.mark.eth_dm9051 -@pytest.mark.parametrize('config', [ - 'default_dm9051', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_dm9051', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_iperf_dm9051( dut: Dut, log_performance: Callable[[str, object], None], @@ -192,11 +233,15 @@ def test_esp_eth_iperf_dm9051( test_esp_eth_iperf(dut, log_performance, check_performance, spi_eth=True, udp_rx_bw_lim=10) -@pytest.mark.esp32 @pytest.mark.eth_w5500 -@pytest.mark.parametrize('config', [ - 'default_w5500', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_w5500', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_iperf_w5500( dut: Dut, log_performance: Callable[[str, object], None], @@ -205,11 +250,15 @@ def test_esp_eth_iperf_w5500( test_esp_eth_iperf(dut, log_performance, check_performance, spi_eth=True, udp_rx_bw_lim=10) -@pytest.mark.esp32 @pytest.mark.eth_ksz8851snl -@pytest.mark.parametrize('config', [ - 'default_ksz8851snl', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_ksz8851snl', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_iperf_ksz8851snl( dut: Dut, log_performance: Callable[[str, object], None], diff --git a/examples/get-started/blink/pytest_blink.py b/examples/get-started/blink/pytest_blink.py index 8df33cfb83..3aca7520fa 100644 --- a/examples/get-started/blink/pytest_blink.py +++ b/examples/get-started/blink/pytest_blink.py @@ -1,14 +1,15 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import os import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_blink(dut: IdfDut) -> None: # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'blink.bin') diff --git a/examples/get-started/hello_world/pytest_hello_world.py b/examples/get-started/hello_world/pytest_hello_world.py index 3524fd9495..196c9605b3 100644 --- a/examples/get-started/hello_world/pytest_hello_world.py +++ b/examples/get-started/hello_world/pytest_hello_world.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import hashlib import logging @@ -6,29 +6,27 @@ from typing import Callable import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_qemu.app import QemuApp from pytest_embedded_qemu.dut import QemuDut -@pytest.mark.supported_targets -@pytest.mark.preview_targets @pytest.mark.generic -def test_hello_world( - dut: IdfDut, log_minimum_free_heap_size: Callable[..., None] -) -> None: +@idf_parametrize('target', ['supported_targets', 'preview_targets'], indirect=['target']) +def test_hello_world(dut: IdfDut, log_minimum_free_heap_size: Callable[..., None]) -> None: dut.expect('Hello world!') log_minimum_free_heap_size() -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_hello_world_linux(dut: IdfDut) -> None: dut.expect('Hello world!') -@pytest.mark.linux @pytest.mark.host_test @pytest.mark.macos_shell +@idf_parametrize('target', ['linux'], indirect=['target']) def test_hello_world_macos(dut: IdfDut) -> None: dut.expect('Hello world!') @@ -47,13 +45,11 @@ def verify_elf_sha256_embedding(app: QemuApp, sha256_reported: str) -> None: raise ValueError('ELF file SHA256 mismatch') -@pytest.mark.esp32 # we only support qemu on esp32 for now @pytest.mark.host_test @pytest.mark.qemu +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_hello_world_host(app: QemuApp, dut: QemuDut) -> None: - sha256_reported = ( - dut.expect(r'ELF file SHA256:\s+([a-f0-9]+)').group(1).decode('utf-8') - ) + sha256_reported = dut.expect(r'ELF file SHA256:\s+([a-f0-9]+)').group(1).decode('utf-8') verify_elf_sha256_embedding(app, sha256_reported) dut.expect('Hello world!') diff --git a/examples/ieee802154/ieee802154_cli/pytest_test_ieee802154.py b/examples/ieee802154/ieee802154_cli/pytest_test_ieee802154.py index 965780de69..d534772111 100644 --- a/examples/ieee802154/ieee802154_cli/pytest_test_ieee802154.py +++ b/examples/ieee802154/ieee802154_cli/pytest_test_ieee802154.py @@ -1,14 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import random import re from time import sleep -from typing import List, Tuple +from typing import List +from typing import Tuple import pexpect import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize def generate_shortaddr() -> str: @@ -33,7 +34,7 @@ def generate_extaddr() -> str: return extaddr -def dlt_pendingtable(ser:IdfDut, addr:str) -> None: +def dlt_pendingtable(ser: IdfDut, addr: str) -> None: if addr != '': addr_list = re.findall(r'0x([A-Za-z0-9]{2})', addr) addr_field = '0x' + ''.join(reversed(addr_list)) @@ -52,7 +53,7 @@ def dlt_pendingtable(ser:IdfDut, addr:str) -> None: sleep(0.1) -def add_pendingtable(ser:IdfDut, addr:str='') -> None: +def add_pendingtable(ser: IdfDut, addr: str = '') -> None: if len(addr.split(' ')) == 2 or len(addr.split(' ')) == 8: cmd = 'pending %s\n' % (addr) addr_list = re.findall(r'0x([A-Za-z0-9]{2})', addr) @@ -66,7 +67,7 @@ def add_pendingtable(ser:IdfDut, addr:str='') -> None: sleep(0.1) -def generate_wrong_PANID_addr(right:str) -> str: +def generate_wrong_PANID_addr(right: str) -> str: wrong = '' for i in right.split(' '): num = (int(i, 16) + random.randint(1, 255)) % 256 @@ -75,7 +76,9 @@ def generate_wrong_PANID_addr(right:str) -> str: return wrong -def set_mismatch_short_extern_addr_pendingtable(ser:IdfDut, addr:str, short:int=12, extern:int=12) -> List[List]: +def set_mismatch_short_extern_addr_pendingtable( + ser: IdfDut, addr: str, short: int = 12, extern: int = 12 +) -> List[List]: short_addr = [] extern_addr = [] cnt = 0 @@ -100,7 +103,7 @@ def set_mismatch_short_extern_addr_pendingtable(ser:IdfDut, addr:str, short:int= return [short_addr, extern_addr] -def dlt_short_extern_addr_in_pendingtable(ser:IdfDut, table:List, short:int=5, extern:int=5) -> None: +def dlt_short_extern_addr_in_pendingtable(ser: IdfDut, table: List, short: int = 5, extern: int = 5) -> None: cnt = 0 while cnt < short: dlt_pendingtable(ser, table[0][cnt]) @@ -110,13 +113,15 @@ def dlt_short_extern_addr_in_pendingtable(ser:IdfDut, table:List, short:int=5, e cnt = cnt + 1 -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'count, config', [ + 'count, config', + [ (2, 'release'), - ], indirect=True + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_txrx(dut: Tuple[IdfDut, IdfDut]) -> None: transmit = dut[0] receive = dut[1] @@ -147,12 +152,15 @@ def test_based_txrx(dut: Tuple[IdfDut, IdfDut]) -> None: assert 'Rx Done' not in str(tmp) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_energy(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -161,12 +169,15 @@ def test_based_energy(dut: IdfDut) -> None: transmit.expect('ed_scan_rss_value:', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_channel(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -176,12 +187,15 @@ def test_based_channel(dut: IdfDut) -> None: transmit.expect('current channel: 23', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_txpower(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -191,12 +205,15 @@ def test_based_txpower(dut: IdfDut) -> None: transmit.expect('current txpower: 13', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_promiscuous(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -210,12 +227,15 @@ def test_based_promiscuous(dut: IdfDut) -> None: transmit.expect('hardware promiscuous mode was disabled', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_panid(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -225,12 +245,15 @@ def test_based_panid(dut: IdfDut) -> None: transmit.expect('current panid: 0x60', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_shortaddr(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -240,12 +263,15 @@ def test_based_shortaddr(dut: IdfDut) -> None: transmit.expect('current shortaddr: 0x1234', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_extaddr(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -255,12 +281,15 @@ def test_based_extaddr(dut: IdfDut) -> None: transmit.expect('get extaddr: 0807060504030201', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_coordinator(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -274,12 +303,15 @@ def test_based_coordinator(dut: IdfDut) -> None: transmit.expect('hardware coordinator was disabled', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_pending(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -295,12 +327,15 @@ def test_based_pending(dut: IdfDut) -> None: transmit.expect('clear the pending address table', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_cca(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -312,13 +347,15 @@ def test_based_cca(dut: IdfDut) -> None: transmit.expect('threshold:-60 dB, mode: 0', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'count, config', [ + 'count, config', + [ (2, 'release'), - ], indirect=True + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_autoack(dut: Tuple[IdfDut, IdfDut]) -> None: transmit = dut[0] receive = dut[1] @@ -359,18 +396,20 @@ def test_based_autoack(dut: Tuple[IdfDut, IdfDut]) -> None: transmit.expect('02 00 00', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'count, config', [ + 'count, config', + [ (2, 'release'), - ], indirect=True + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_autopending(dut: Tuple[IdfDut, IdfDut]) -> None: transmit = dut[0] receive = dut[1] -# mode 0: CMD ID = 0x04 --> FP = 1 + # mode 0: CMD ID = 0x04 --> FP = 1 transmit.expect('ieee802154>', timeout=10) transmit.write('rx -r 0') transmit.expect('radio exit receive mode') @@ -397,11 +436,13 @@ def test_based_autopending(dut: Tuple[IdfDut, IdfDut]) -> None: receive.write('rx -r 1') receive.expect('RX Start', timeout=10) - transmit.write('tx 0x23 0x08 0x00 0x74 0x2E 0x49 0x26 0x04 0x53 0x04 0xe3 0x71 0xc2 0x36 0xf7 0xa5 0x2b 0x68 0x79 0x8c 0x72 0x50 0x8b 0x61 0x55 0x56') + transmit.write( + 'tx 0x23 0x08 0x00 0x74 0x2E 0x49 0x26 0x04 0x53 0x04 0xe3 0x71 0xc2 0x36 0xf7 0xa5 0x2b 0x68 0x79 0x8c 0x72 0x50 0x8b 0x61 0x55 0x56' + ) transmit.expect('Rx ack 5 bytes', timeout=10) transmit.expect('12 00 00', timeout=10) -# mode 0: CMD ID != 0x04 --> FP = 0 + # mode 0: CMD ID != 0x04 --> FP = 0 receive.write('pending -r') receive.expect('clear the pending address table', timeout=10) receive.write('promisc -d') @@ -426,7 +467,7 @@ def test_based_autopending(dut: Tuple[IdfDut, IdfDut]) -> None: transmit.expect('Rx ack 5 bytes', timeout=10) transmit.expect('02 00 0c', timeout=10) -# mode 1: CMD ID = 0x04, src addr in pending table --> FP = 1 + # mode 1: CMD ID = 0x04, src addr in pending table --> FP = 1 receive.write('pending -r') receive.expect('clear the pending address table', timeout=10) receive.write('promisc -d') @@ -459,7 +500,7 @@ def test_based_autopending(dut: Tuple[IdfDut, IdfDut]) -> None: transmit.expect('Rx ack 5 bytes', timeout=10) transmit.expect('12 00 00', timeout=10) -# mode 1: CMD ID = 0x04, src addr not in pending table --> FP = 0 + # mode 1: CMD ID = 0x04, src addr not in pending table --> FP = 0 receive.write('pending -r') receive.expect('clear the pending address table', timeout=10) receive.write('promisc -d') @@ -487,11 +528,13 @@ def test_based_autopending(dut: Tuple[IdfDut, IdfDut]) -> None: receive.write('rx -r 1') receive.expect('RX Start', timeout=10) - transmit.write('tx 0x2b 0x88 0x08 0xE3 0x9F 0x20 0x9E 0x18 0xE7 0x66 0xC4 0x17 0x92 0x8a 0xcd 0x4c 0xd0 0x20 0x40 0x0d 0x46 0x04 0xa0 0xe3 0x9c 0x57') + transmit.write( + 'tx 0x2b 0x88 0x08 0xE3 0x9F 0x20 0x9E 0x18 0xE7 0x66 0xC4 0x17 0x92 0x8a 0xcd 0x4c 0xd0 0x20 0x40 0x0d 0x46 0x04 0xa0 0xe3 0x9c 0x57' + ) transmit.expect('Rx ack 5 bytes', timeout=10) transmit.expect('02 00 08', timeout=10) -# mode 2: frame type is data, src addr in pending table --> FP = 1 + # mode 2: frame type is data, src addr in pending table --> FP = 1 receive.write('pending -r') receive.expect('clear the pending address table', timeout=10) receive.write('promisc -d') @@ -524,7 +567,7 @@ def test_based_autopending(dut: Tuple[IdfDut, IdfDut]) -> None: transmit.expect('Rx ack 5 bytes', timeout=10) transmit.expect('12 00 10', timeout=10) -# mode 2: frame type is data, src addr not in pending table --> FP = 0 + # mode 2: frame type is data, src addr not in pending table --> FP = 0 receive.write('pending -r') receive.expect('clear the pending address table', timeout=10) receive.write('promisc -d') @@ -557,12 +600,15 @@ def test_based_autopending(dut: Tuple[IdfDut, IdfDut]) -> None: transmit.expect('02 00 10', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_transmit_failed(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) @@ -579,12 +625,15 @@ def test_based_transmit_failed(dut: IdfDut) -> None: transmit.expect('08 09 00 00 00 00 00 00', timeout=10) -@pytest.mark.esp32c6 @pytest.mark.ieee802154 @pytest.mark.parametrize( - 'config', ['release',], - indirect=True + 'config', + [ + 'release', + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_based_initialize(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) diff --git a/examples/network/bridge/pytest_example_bridge.py b/examples/network/bridge/pytest_example_bridge.py index 6009f00274..d407464bc5 100644 --- a/examples/network/bridge/pytest_example_bridge.py +++ b/examples/network/bridge/pytest_example_bridge.py @@ -24,8 +24,7 @@ import pytest from common_test_methods import get_host_ip_by_interface from netmiko import ConnectHandler from pytest_embedded import Dut - - +from pytest_embedded_idf.utils import idf_parametrize # Testbed configuration ETHVM_ENDNODE_USER = 'ci.ethvm' @@ -84,9 +83,7 @@ class SwitchSsh: if self.type == self.EDGE_SWITCH_5XP: self.ssh_client = paramiko.SSHClient() self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - self.ssh_client.connect(hostname=self.host_ip, - username=usr, - password=passwd) + self.ssh_client.connect(hostname=self.host_ip, username=usr, password=passwd) else: edgeSwitch = { 'device_type': 'ubiquiti_edgeswitch', @@ -134,7 +131,10 @@ class SwitchSsh: def get_endnode_mac_by_interface(endnode: EndnodeSsh, if_name: str) -> str: ip_info = endnode.exec_cmd(f'ip addr show {if_name}') - regex = if_name + r':.*?link/ether ([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})' + regex = ( + if_name + + r':.*?link/ether ([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})' + ) mac_addr = re.search(regex, ip_info, re.DOTALL) if mac_addr is None: return '' @@ -175,7 +175,15 @@ def get_host_brcast_ip_by_interface(interface_name: str, ip_type: int = netiface return '' -def run_iperf(proto: str, endnode: EndnodeSsh, server_ip: str, bandwidth_lim:int=10, interval:int=5, server_if:str='', client_if:str='') -> float: +def run_iperf( + proto: str, + endnode: EndnodeSsh, + server_ip: str, + bandwidth_lim: int = 10, + interval: int = 5, + server_if: str = '', + client_if: str = '', +) -> float: if proto == 'tcp': proto = '' else: @@ -399,7 +407,9 @@ def eth_bridge_test(dut: Dut, dev_user: str, dev_password: str) -> None: logging.info('link up the port #2') switch1.switch_port_up(port_num_endnode) - dut.expect_exact(f'Ethernet ({p2_id}) Link Up') # Note: No "Ethernet Got IP Address" since DHCP Server is connected to port #1 + dut.expect_exact( + f'Ethernet ({p2_id}) Link Up' + ) # Note: No "Ethernet Got IP Address" since DHCP Server is connected to port #1 logging.info('link down both ports') switch1.switch_port_down(port_num_endnode) @@ -616,7 +626,6 @@ def setup_test_environment() -> Generator[None, None, None]: # Optional teardown after all tests... -@pytest.mark.esp32 @pytest.mark.eth_w5500 @pytest.mark.parametrize( 'config', @@ -625,5 +634,6 @@ def setup_test_environment() -> Generator[None, None, None]: ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None: eth_bridge_test(dut, dev_user, dev_password) diff --git a/examples/network/simple_sniffer/pytest_simple_sniffer.py b/examples/network/simple_sniffer/pytest_simple_sniffer.py index e78e8e8663..118f95c738 100644 --- a/examples/network/simple_sniffer/pytest_simple_sniffer.py +++ b/examples/network/simple_sniffer/pytest_simple_sniffer.py @@ -1,9 +1,9 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import pytest from common_test_methods import get_env_config_variable from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def _sniffer_packets_check(dut: Dut, channel: int, packet_num: int) -> None: @@ -37,13 +37,15 @@ def _sniffer_packets_check(dut: Dut, channel: int, packet_num: int) -> None: dut.expect('cmd_pcap: .pcap file close done') -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_ap -@pytest.mark.parametrize('config', [ - 'mem', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'mem', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_simple_sniffer(dut: Dut) -> None: dut.expect('sniffer>') channel = get_env_config_variable('wifi_ap', 'sniffer_channel', default=1) diff --git a/examples/network/vlan_support/pytest_vlan_napt.py b/examples/network/vlan_support/pytest_vlan_napt.py index 21a29b9b8b..d55ee54e4b 100644 --- a/examples/network/vlan_support/pytest_vlan_napt.py +++ b/examples/network/vlan_support/pytest_vlan_napt.py @@ -1,22 +1,27 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import ipaddress import subprocess import threading import time -from typing import Dict, Union +from typing import Dict +from typing import Union import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize from scapy import layers -from scapy.all import ICMP, IP, TCP, UDP, AsyncSniffer +from scapy.all import AsyncSniffer +from scapy.all import ICMP +from scapy.all import IP +from scapy.all import TCP +from scapy.all import UDP udp_port = 1234 tcp_port = 4321 -def run_cmd(command: str, secure: bool=False) -> str: +def run_cmd(command: str, secure: bool = False) -> str: if secure is False: print(f'Running: {command}') @@ -73,12 +78,16 @@ def setup_network(config: dict) -> None: def create_config(dut: Dut) -> dict: pc_iface = dut.app.sdkconfig.get('EXAMPLE_VLAN_PYTEST_PC_IFACE') - vlanClient_conf = {'id': str(dut.app.sdkconfig.get('EXAMPLE_ETHERNET_VLAN_ID')), - 'name': 'vlanClient', - 'ip': dut.app.sdkconfig.get('EXAMPLE_VLAN_STATIC_ADDR_DEF_GW')} - vlanServer_conf = {'id': str(dut.app.sdkconfig.get('EXAMPLE_EXTRA_ETHERNET_VLAN_ID')), - 'name': 'vlanServer', - 'ip': dut.app.sdkconfig.get('EXAMPLE_EXTRA_VLAN_STATIC_ADDR_DEF_GW')} + vlanClient_conf = { + 'id': str(dut.app.sdkconfig.get('EXAMPLE_ETHERNET_VLAN_ID')), + 'name': 'vlanClient', + 'ip': dut.app.sdkconfig.get('EXAMPLE_VLAN_STATIC_ADDR_DEF_GW'), + } + vlanServer_conf = { + 'id': str(dut.app.sdkconfig.get('EXAMPLE_EXTRA_ETHERNET_VLAN_ID')), + 'name': 'vlanServer', + 'ip': dut.app.sdkconfig.get('EXAMPLE_EXTRA_VLAN_STATIC_ADDR_DEF_GW'), + } esp_vlanClient_ip = dut.app.sdkconfig.get('EXAMPLE_VLAN_STATIC_IPV4_ADDR') esp_vlanServer_ip = dut.app.sdkconfig.get('EXAMPLE_EXTRA_VLAN_STATIC_IPV4_ADDR') @@ -89,31 +98,33 @@ def create_config(dut: Dut) -> dict: config: Dict[str, Union[str, dict, dict, str, str, list, list, list, list]] = { # Basic Configurations 'pc_iface': pc_iface, - 'vlanClient': vlanClient_conf, 'vlanServer': vlanServer_conf, - 'esp_vlanClient_ip': esp_vlanClient_ip, 'esp_vlanServer_ip': esp_vlanServer_ip, - - 'vlan_create_cmd_l': [f'ip netns add ns_vlanClient', - f"ip link add link {pc_iface} name {vlanClient_conf['name']} type vlan id {vlanClient_conf['id']}", - f"ip link set {vlanClient_conf['name']} netns ns_vlanClient", - f"ip netns exec ns_vlanClient ip addr add {vlanClient_conf['ip']}/255.255.255.0 dev {vlanClient_conf['name']}", - f"ip netns exec ns_vlanClient ip link set dev {vlanClient_conf['name']} up", - f"ip link add link {pc_iface} name {vlanServer_conf['name']} type vlan id {vlanServer_conf['id']}", - f"ip addr add {vlanServer_conf['ip']}/255.255.255.0 dev {vlanServer_conf['name']}", - f"ip link set dev {vlanServer_conf['name']} up"], - - 'vlan_destroy_cmd_l': [f"ip netns exec ns_vlanClient ip link set dev {vlanClient_conf['name']} down", - f"ip netns exec ns_vlanClient ip link delete {vlanClient_conf['name']}", - f"ip link set dev {vlanServer_conf['name']} down", - f"ip link delete {vlanServer_conf['name']}", - f'ip netns delete ns_vlanClient'], - - 'set_route_cmd_l': [f'ip netns exec ns_vlanClient ip route add {vlanServer_net_addr}/24 via {esp_vlanClient_ip}'], - - 'delete_route_cmd_l': [f'ip netns exec ns_vlanClient ip route delete {vlanServer_net_addr}/24 via {esp_vlanClient_ip}'], + 'vlan_create_cmd_l': [ + f'ip netns add ns_vlanClient', + f'ip link add link {pc_iface} name {vlanClient_conf["name"]} type vlan id {vlanClient_conf["id"]}', + f'ip link set {vlanClient_conf["name"]} netns ns_vlanClient', + f'ip netns exec ns_vlanClient ip addr add {vlanClient_conf["ip"]}/255.255.255.0 dev {vlanClient_conf["name"]}', + f'ip netns exec ns_vlanClient ip link set dev {vlanClient_conf["name"]} up', + f'ip link add link {pc_iface} name {vlanServer_conf["name"]} type vlan id {vlanServer_conf["id"]}', + f'ip addr add {vlanServer_conf["ip"]}/255.255.255.0 dev {vlanServer_conf["name"]}', + f'ip link set dev {vlanServer_conf["name"]} up', + ], + 'vlan_destroy_cmd_l': [ + f'ip netns exec ns_vlanClient ip link set dev {vlanClient_conf["name"]} down', + f'ip netns exec ns_vlanClient ip link delete {vlanClient_conf["name"]}', + f'ip link set dev {vlanServer_conf["name"]} down', + f'ip link delete {vlanServer_conf["name"]}', + f'ip netns delete ns_vlanClient', + ], + 'set_route_cmd_l': [ + f'ip netns exec ns_vlanClient ip route add {vlanServer_net_addr}/24 via {esp_vlanClient_ip}' + ], + 'delete_route_cmd_l': [ + f'ip netns exec ns_vlanClient ip route delete {vlanServer_net_addr}/24 via {esp_vlanClient_ip}' + ], } return config @@ -121,7 +132,6 @@ def create_config(dut: Dut) -> dict: # Ping Test def ping_test(config: dict) -> None: - setup_network(config) capture = AsyncSniffer(iface=config['vlanServer']['name'], filter='icmp', count=10) @@ -131,7 +141,11 @@ def ping_test(config: dict) -> None: time.sleep(1) # Run network test commands here - print(run_cmd_sec(f"ip netns exec ns_vlanClient ping -I {config['vlanClient']['ip']} {config['vlanServer']['ip']} -c 10")) + print( + run_cmd_sec( + f'ip netns exec ns_vlanClient ping -I {config["vlanClient"]["ip"]} {config["vlanServer"]["ip"]} -c 10' + ) + ) # Stop sniffing capture.join(timeout=20) @@ -147,12 +161,20 @@ def ping_test(config: dict) -> None: print('Failure: No packets captured') assert False - print(f"Captured: {len(vlanServer_pkt_list)} packets on interface {config['vlanServer']['name']}") + print(f'Captured: {len(vlanServer_pkt_list)} packets on interface {config["vlanServer"]["name"]}') for pkt in vlanServer_pkt_list: print('Summary: ', pkt.summary()) - if pkt[ICMP].type == 8 and pkt[IP].src == config['esp_vlanServer_ip'] and pkt[IP].dst == config['vlanServer']['ip']: + if ( + pkt[ICMP].type == 8 + and pkt[IP].src == config['esp_vlanServer_ip'] + and pkt[IP].dst == config['vlanServer']['ip'] + ): vlanServer_forward_flag = True - if pkt[ICMP].type == 0 and pkt[IP].src == config['vlanServer']['ip'] and pkt[IP].dst == config['esp_vlanServer_ip']: + if ( + pkt[ICMP].type == 0 + and pkt[IP].src == config['vlanServer']['ip'] + and pkt[IP].dst == config['esp_vlanServer_ip'] + ): vlanServer_return_flag = True assert vlanServer_forward_flag and vlanServer_return_flag @@ -170,7 +192,13 @@ def udp_client(serverip: str, port: int) -> None: def udp_server_client_comm(config: dict, port: int) -> None: - server_thread = threading.Thread(target=udp_server, args=(config['vlanServer']['ip'], port,)) + server_thread = threading.Thread( + target=udp_server, + args=( + config['vlanServer']['ip'], + port, + ), + ) client_thread = threading.Thread(target=udp_client, args=(config['vlanServer']['ip'], port)) server_thread.start() @@ -186,13 +214,9 @@ def udp_lfilter(packet: layers.l2.Ether) -> layers.l2.Ether: def udp_test(config: dict) -> None: - setup_network(config) - capture = AsyncSniffer(iface=config['vlanServer']['name'], - filter='udp', - lfilter=udp_lfilter, - count=10) + capture = AsyncSniffer(iface=config['vlanServer']['name'], filter='udp', lfilter=udp_lfilter, count=10) # Start sniffing capture.start() @@ -216,13 +240,21 @@ def udp_test(config: dict) -> None: print('Failure: No packets captured') assert False - print(f"Captured: {len(vlanServer_pkt_list)} packets on interface {config['vlanServer']['name']}") + print(f'Captured: {len(vlanServer_pkt_list)} packets on interface {config["vlanServer"]["name"]}') for pkt in vlanServer_pkt_list: print('Summary: ', pkt.summary()) if UDP in pkt: - if pkt[UDP].dport == udp_port and pkt[IP].src == config['esp_vlanServer_ip'] and pkt[IP].dst == config['vlanServer']['ip']: + if ( + pkt[UDP].dport == udp_port + and pkt[IP].src == config['esp_vlanServer_ip'] + and pkt[IP].dst == config['vlanServer']['ip'] + ): vlanServer_forward_flag = True - if pkt[UDP].sport == udp_port and pkt[IP].src == config['vlanServer']['ip'] and pkt[IP].dst == config['esp_vlanServer_ip']: + if ( + pkt[UDP].sport == udp_port + and pkt[IP].src == config['vlanServer']['ip'] + and pkt[IP].dst == config['esp_vlanServer_ip'] + ): vlanServer_return_flag = True assert vlanServer_forward_flag and vlanServer_return_flag @@ -240,7 +272,13 @@ def tcp_client(serverip: str, port: int) -> None: def tcp_server_client_comm(config: dict, port: int) -> None: - server_thread = threading.Thread(target=tcp_server, args=(config['vlanServer']['ip'], port,)) + server_thread = threading.Thread( + target=tcp_server, + args=( + config['vlanServer']['ip'], + port, + ), + ) client_thread = threading.Thread(target=tcp_client, args=(config['vlanServer']['ip'], port)) server_thread.start() @@ -256,13 +294,9 @@ def tcp_lfilter(packet: layers.l2.Ether) -> layers.l2.Ether: def tcp_test(config: dict) -> None: - setup_network(config) - capture = AsyncSniffer(iface=config['vlanServer']['name'], - filter='tcp', - lfilter=tcp_lfilter, - count=10) + capture = AsyncSniffer(iface=config['vlanServer']['name'], filter='tcp', lfilter=tcp_lfilter, count=10) # Start sniffing capture.start() @@ -286,36 +320,44 @@ def tcp_test(config: dict) -> None: print('Failure: No packets captured') assert False - print(f"Captured: {len(vlanServer_pkt_list)} packets on interface {config['vlanServer']['name']}") + print(f'Captured: {len(vlanServer_pkt_list)} packets on interface {config["vlanServer"]["name"]}') for pkt in vlanServer_pkt_list: print('Summary: ', pkt.summary()) if TCP in pkt: - if pkt[TCP].dport == tcp_port and pkt[IP].src == config['esp_vlanServer_ip'] and pkt[IP].dst == config['vlanServer']['ip']: + if ( + pkt[TCP].dport == tcp_port + and pkt[IP].src == config['esp_vlanServer_ip'] + and pkt[IP].dst == config['vlanServer']['ip'] + ): vlanServer_forward_flag = True - if pkt[TCP].sport == tcp_port and pkt[IP].src == config['vlanServer']['ip'] and pkt[IP].dst == config['esp_vlanServer_ip']: + if ( + pkt[TCP].sport == tcp_port + and pkt[IP].src == config['vlanServer']['ip'] + and pkt[IP].dst == config['esp_vlanServer_ip'] + ): vlanServer_return_flag = True assert vlanServer_forward_flag and vlanServer_return_flag -@pytest.mark.esp32 @pytest.mark.ethernet_vlan +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_vlan_napt_pingtest(dut: Dut) -> None: dut.expect('main_task: Returned from app_main()') test_conf = create_config(dut) ping_test(test_conf) -@pytest.mark.esp32 @pytest.mark.ethernet_vlan +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_vlan_napt_udptest(dut: Dut) -> None: dut.expect('main_task: Returned from app_main()') test_conf = create_config(dut) udp_test(test_conf) -@pytest.mark.esp32 @pytest.mark.ethernet_vlan +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_vlan_napt_tcptest(dut: Dut) -> None: dut.expect('main_task: Returned from app_main()') test_conf = create_config(dut) diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index 1de1ccee26..75e85d7635 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 # !/usr/bin/env python3 import copy @@ -16,61 +16,43 @@ import ot_ci_function as ocf import pexpect import pytest from pytest_embedded_idf.dut import IdfDut - # This file contains the test scripts for Thread: - # Case 1: Thread network formation and attaching # A Thread Border Router forms a Thread network, Thread devices attach to it, then test ping # connection between them. - # Case 2: Bidirectional IPv6 connectivity # Test IPv6 ping connection between Thread device and Linux Host (via Thread Border Router). - # Case 3: Multicast forwarding from Wi-Fi to Thread network # Thread device joins the multicast group, then test group communication from Wi-Fi to Thread network. - # Case 4: Multicast forwarding from Thread to Wi-Fi network # Linux Host joins the multicast group, test group communication from Thread to Wi-Fi network. - # Case 5: discover Service published by Thread device # Thread device publishes the service, Linux Host discovers the service on Wi-Fi network. - # Case 6: discover Service published by W-Fi device # Linux Host device publishes the service on Wi-Fi network, Thread device discovers the service. - # Case 7: ICMP communication via NAT64 # Thread device (IPV6) ping the host device (IPV4) via NAT64. - # Case 8: UDP communication via NAT64 # Thread device (IPV6) send udp message to the host device (IPV4) via NAT64. - # Case 9: TCP communication via NAT64 # Thread device (IPV6) send tcp message to the host device (IPV4) via NAT64. - # Case 10: Sleepy device test # Start a Thread sleepy device, wait it join the Thread network and check related flags. - # Case 11: Basic startup Test of BR # Test the basic startup and network formation of a Thread device. - # Case 12: Curl a website via DNS and NAT64 # A border router joins a Wi-Fi network and forms a Thread network, a Thread devices attached to it and curl # a website. - # Case 13: Meshcop discovery of Border Router # A border router joins a Wi-Fi network, forms a Thread network and publish a meshcop service. Linux Host device # discover the mescop service. - # Case 14: Curl a website over HTTPS via DNS and NAT64 # A border router joins a Wi-Fi network and forms a Thread network, a Thread devices attached to it and curl # a https website. - # Case 15: Thread network formation and attaching with TREL # A TREL device forms a Thread network, other TREL devices attach to it, then test ping connection between them. - # Case 16: Thread network BR lib check # Check BR library compatibility - # Case 17: Synchronized sleepy end device (SSED) test # Start a Thread ssed device, wait it join the Thread network and check related flags. @@ -100,15 +82,10 @@ ESPPORT1 = os.getenv('ESPPORT1') ESPPORT2 = os.getenv('ESPPORT2') ESPPORT3 = os.getenv('ESPPORT3') -PORT_MAPPING = { - 'ESPPORT1': 'esp32h2', - 'ESPPORT2': 'esp32s3', - 'ESPPORT3': 'esp32c6' -} +PORT_MAPPING = {'ESPPORT1': 'esp32h2', 'ESPPORT2': 'esp32s3', 'ESPPORT3': 'esp32c6'} # Case 1: Thread network formation and attaching -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -122,7 +99,7 @@ PORT_MAPPING = { f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), pytest.param( 'rcp_spi|cli|br_spi', @@ -132,7 +109,7 @@ PORT_MAPPING = { f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32h2|esp32c6|esp32s3', f'{ESPPORT1}|{ESPPORT3}|{ESPPORT2}', - id='h2-c6-s3' + id='h2-c6-s3', ), ], indirect=True, @@ -177,7 +154,7 @@ def test_thread_connect(dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: # / \ # / \ # Wi-FI_Host Thread_End_Device -def formBasicWiFiThreadNetwork(br:IdfDut, cli:IdfDut) -> None: +def formBasicWiFiThreadNetwork(br: IdfDut, cli: IdfDut) -> None: ocf.init_thread(br) ocf.init_thread(cli) otbr_wifi_para = copy.copy(default_br_wifi_para) @@ -188,11 +165,10 @@ def formBasicWiFiThreadNetwork(br:IdfDut, cli:IdfDut) -> None: otcli_thread_para.dataset = ocf.getDataset(br) otcli_thread_para.exaddr = '7766554433221101' ocf.joinThreadNetwork(cli, otcli_thread_para) - ocf.wait(cli,10) + ocf.wait(cli, 10) # Case 2: Bidirectional IPv6 connectivity -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -206,14 +182,14 @@ def formBasicWiFiThreadNetwork(br:IdfDut, cli:IdfDut) -> None: f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), ], indirect=True, ) def test_Bidirectional_IPv6_connectivity(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: br = dut[2] - cli = dut[1] + cli = dut[1] assert Init_interface dut[0].serial.stop_redirect_thread() @@ -250,7 +226,6 @@ def test_Bidirectional_IPv6_connectivity(Init_interface: bool, dut: Tuple[IdfDut # Case 3: Multicast forwarding from Wi-Fi to Thread network -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -264,14 +239,14 @@ def test_Bidirectional_IPv6_connectivity(Init_interface: bool, dut: Tuple[IdfDut f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), ], indirect=True, ) def test_multicast_forwarding_A(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: br = dut[2] - cli = dut[1] + cli = dut[1] assert Init_interface dut[0].serial.stop_redirect_thread() @@ -304,7 +279,6 @@ def test_multicast_forwarding_A(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, # Case 4: Multicast forwarding from Thread to Wi-Fi network -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -318,14 +292,14 @@ def test_multicast_forwarding_A(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), ], indirect=True, ) def test_multicast_forwarding_B(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: br = dut[2] - cli = dut[1] + cli = dut[1] assert Init_interface dut[0].serial.stop_redirect_thread() @@ -338,7 +312,7 @@ def test_multicast_forwarding_B(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, cli.expect('Done', timeout=5) ocf.wait(cli, 3) myudp = ocf.udp_parameter('INET6', '::', 5090, 'ff04::125', False, 15.0, b'') - udp_mission = threading.Thread(target=ocf.create_host_udp_server, args=(myudp, )) + udp_mission = threading.Thread(target=ocf.create_host_udp_server, args=(myudp,)) udp_mission.start() start_time = time.time() while not myudp.init_flag: @@ -359,7 +333,6 @@ def test_multicast_forwarding_B(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, # Case 5: discover dervice published by Thread device -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -373,7 +346,7 @@ def test_multicast_forwarding_B(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), ], indirect=True, @@ -382,7 +355,7 @@ def test_service_discovery_of_Thread_device( Init_interface: bool, Init_avahi: bool, dut: Tuple[IdfDut, IdfDut, IdfDut] ) -> None: br = dut[2] - cli = dut[1] + cli = dut[1] assert Init_interface assert Init_avahi dut[0].serial.stop_redirect_thread() @@ -421,7 +394,6 @@ def test_service_discovery_of_Thread_device( # Case 6: discover dervice published by Wi-Fi device -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -435,7 +407,7 @@ def test_service_discovery_of_Thread_device( f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), ], indirect=True, @@ -444,7 +416,7 @@ def test_service_discovery_of_WiFi_device( Init_interface: bool, Init_avahi: bool, dut: Tuple[IdfDut, IdfDut, IdfDut] ) -> None: br = dut[2] - cli = dut[1] + cli = dut[1] assert Init_interface assert Init_avahi dut[0].serial.stop_redirect_thread() @@ -492,7 +464,6 @@ def test_service_discovery_of_WiFi_device( # Case 7: ICMP communication via NAT64 -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -506,14 +477,14 @@ def test_service_discovery_of_WiFi_device( f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), ], indirect=True, ) def test_ICMP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: br = dut[2] - cli = dut[1] + cli = dut[1] assert Init_interface dut[0].serial.stop_redirect_thread() @@ -531,7 +502,6 @@ def test_ICMP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> # Case 8: UDP communication via NAT64 -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -545,14 +515,14 @@ def test_ICMP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), ], indirect=True, ) def test_UDP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: br = dut[2] - cli = dut[1] + cli = dut[1] assert Init_interface dut[0].serial.stop_redirect_thread() @@ -567,7 +537,7 @@ def test_UDP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> host_ipv4_address = ocf.get_host_ipv4_address() logging.info(f'host_ipv4_address: {host_ipv4_address}') myudp = ocf.udp_parameter('INET4', host_ipv4_address, 5090, '', False, 15.0, b'') - udp_mission = threading.Thread(target=ocf.create_host_udp_server, args=(myudp, )) + udp_mission = threading.Thread(target=ocf.create_host_udp_server, args=(myudp,)) udp_mission.start() start_time = time.time() while not myudp.init_flag: @@ -588,7 +558,6 @@ def test_UDP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> # Case 9: TCP communication via NAT64 -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -602,14 +571,14 @@ def test_UDP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), ], indirect=True, ) def test_TCP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: br = dut[2] - cli = dut[1] + cli = dut[1] assert Init_interface dut[0].serial.stop_redirect_thread() @@ -625,7 +594,7 @@ def test_TCP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> connect_address = ocf.get_ipv6_from_ipv4(host_ipv4_address, br) logging.info(f'connect_address is: {connect_address}') mytcp = ocf.tcp_parameter('INET4', host_ipv4_address, 12345, False, False, 15.0, b'') - tcp_mission = threading.Thread(target=ocf.create_host_tcp_server, args=(mytcp, )) + tcp_mission = threading.Thread(target=ocf.create_host_tcp_server, args=(mytcp,)) tcp_mission.start() start_time = time.time() while not mytcp.listen_flag: @@ -651,8 +620,6 @@ def test_TCP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> # Case 10: Sleepy device test -@pytest.mark.esp32h2 -@pytest.mark.esp32c6 @pytest.mark.openthread_sleep @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -665,7 +632,7 @@ def test_TCP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device/light_sleep")}', 'esp32h2|esp32c6', f'{ESPPORT1}|{ESPPORT3}', - id='h2-c6' + id='h2-c6', ), pytest.param( 'cli|sleepy', @@ -674,7 +641,7 @@ def test_TCP_NAT64(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device/light_sleep")}', 'esp32c6|esp32h2', f'{ESPPORT3}|{ESPPORT1}', - id='c6-h2' + id='c6-h2', ), ], indirect=True, @@ -714,7 +681,6 @@ def test_ot_sleepy_device(dut: Tuple[IdfDut, IdfDut]) -> None: # Case 11: Basic startup Test of BR -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -723,11 +689,10 @@ def test_ot_sleepy_device(dut: Tuple[IdfDut, IdfDut]) -> None: pytest.param( 'rcp_uart|br', 2, - f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' - f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', + f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32s3', f'{ESPPORT3}|{ESPPORT2}', - id='c6-s3' + id='c6-s3', ), ], indirect=True, @@ -756,7 +721,6 @@ def test_basic_startup(dut: Tuple[IdfDut, IdfDut]) -> None: # Case 12: Curl a website via DNS and NAT64 -@pytest.mark.supported_targets @pytest.mark.openthread_bbr @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -770,14 +734,14 @@ def test_basic_startup(dut: Tuple[IdfDut, IdfDut]) -> None: f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), ], indirect=True, ) def test_NAT64_DNS(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: br = dut[2] - cli = dut[1] + cli = dut[1] assert Init_interface dut[0].serial.stop_redirect_thread() @@ -799,7 +763,6 @@ def test_NAT64_DNS(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> # Case 13: Meshcop discovery of Border Router -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -808,11 +771,10 @@ def test_NAT64_DNS(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> pytest.param( 'rcp_uart|br', 2, - f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' - f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', + f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32s3', f'{ESPPORT3}|{ESPPORT2}', - id='c6-s3' + id='c6-s3', ), ], indirect=True, @@ -861,7 +823,6 @@ def test_br_meshcop(Init_interface: bool, Init_avahi: bool, dut: Tuple[IdfDut, I # Case 14: Curl a website over HTTPS via DNS and NAT64 -@pytest.mark.supported_targets @pytest.mark.openthread_bbr @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -875,14 +836,14 @@ def test_br_meshcop(Init_interface: bool, Init_avahi: bool, dut: Tuple[IdfDut, I f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', - id='c6-h2-s3' + id='c6-h2-s3', ), ], indirect=True, ) def test_https_NAT64_DNS(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: br = dut[2] - cli = dut[1] + cli = dut[1] assert Init_interface dut[0].serial.stop_redirect_thread() @@ -902,7 +863,6 @@ def test_https_NAT64_DNS(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut # Case 15: Thread network formation and attaching with TREL -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -915,7 +875,7 @@ def test_https_NAT64_DNS(Init_interface: bool, dut: Tuple[IdfDut, IdfDut, IdfDut f'|{os.path.join(os.path.dirname(__file__), "ot_trel")}', 'esp32c6|esp32s3', f'{ESPPORT3}|{ESPPORT2}', - id='c6-s3' + id='c6-s3', ), ], indirect=True, @@ -957,7 +917,6 @@ def test_trel_connect(dut: Tuple[IdfDut, IdfDut]) -> None: # Case 16: Thread network BR lib check -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( @@ -966,11 +925,10 @@ def test_trel_connect(dut: Tuple[IdfDut, IdfDut]) -> None: pytest.param( 'rcp_uart|br_libcheck', 2, - f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' - f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', + f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32s3', f'{ESPPORT3}|{ESPPORT2}', - id='c6-s3' + id='c6-s3', ), ], indirect=True, diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 6596339965..32bb0cf00b 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -285,6 +285,11 @@ examples/peripherals/mcpwm/mcpwm_sync: - if: SOC_MCPWM_SUPPORTED != 1 depends_components: - esp_driver_mcpwm + disable_test: + - if: IDF_TARGET in ["esp32c6", "esp32h2", "esp32p4"] + temporary: true + reason: pytest does not run those tests + examples/peripherals/parlio: disable: diff --git a/examples/peripherals/adc/continuous_read/pytest_adc_continuous.py b/examples/peripherals/adc/continuous_read/pytest_adc_continuous.py index c891db39e8..1464273b15 100644 --- a/examples/peripherals/adc/continuous_read/pytest_adc_continuous.py +++ b/examples/peripherals/adc/continuous_read/pytest_adc_continuous.py @@ -1,17 +1,14 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded.dut import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32c5 @pytest.mark.adc +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32c5'], indirect=['target'] +) def test_adc_continuous(dut: Dut) -> None: res = dut.expect(r'TASK: ret is 0, ret_num is (\d+) bytes') num = res.group(1).decode('utf8') diff --git a/examples/peripherals/adc/oneshot_read/pytest_adc_oneshot.py b/examples/peripherals/adc/oneshot_read/pytest_adc_oneshot.py index 4fb24a6d3c..fdf95eed39 100644 --- a/examples/peripherals/adc/oneshot_read/pytest_adc_oneshot.py +++ b/examples/peripherals/adc/oneshot_read/pytest_adc_oneshot.py @@ -1,22 +1,18 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded.dut import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32c5 @pytest.mark.adc +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32c5'], indirect=['target'] +) def test_adc_oneshot(dut: Dut) -> None: dut.expect(r'EXAMPLE: ADC1 Channel\[(\d+)\] Raw Data: (\d+)', timeout=5) -@pytest.mark.esp32c2 @pytest.mark.adc @pytest.mark.xtal_26mhz @pytest.mark.parametrize( @@ -26,5 +22,6 @@ def test_adc_oneshot(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_adc_oneshot_esp32c2_xtal_26mhz(dut: Dut) -> None: dut.expect(r'EXAMPLE: ADC1 Channel\[(\d+)\] Raw Data: (\d+)', timeout=5) diff --git a/examples/peripherals/analog_comparator/pytest_ana_cmpr_example.py b/examples/peripherals/analog_comparator/pytest_ana_cmpr_example.py index 0c7b5c2b02..64e7fab77c 100644 --- a/examples/peripherals/analog_comparator/pytest_ana_cmpr_example.py +++ b/examples/peripherals/analog_comparator/pytest_ana_cmpr_example.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -15,9 +14,12 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32h2', 'esp32p4'], indirect=['target']) def test_ana_cmpr_example(dut: Dut) -> None: sdkconfig = dut.app.sdkconfig - dut.expect(r'ana_cmpr_example: Analog Comparator source gpio ([0-9]+), external reference gpio ([0-9]+)', timeout=10) + dut.expect( + r'ana_cmpr_example: Analog Comparator source gpio ([0-9]+), external reference gpio ([0-9]+)', timeout=10 + ) if sdkconfig['EXAMPLE_INTERNAL_REF']: dut.expect('ana_cmpr_example: Allocate Analog Comparator with internal reference', timeout=10) dut.expect(r'ana_cmpr_example: Analog comparator enabled, reference voltage: [0-9]+% \* VDD', timeout=10) diff --git a/examples/peripherals/camera/dvp_isp_dsi/pytest_dvp_isp_dsi.py b/examples/peripherals/camera/dvp_isp_dsi/pytest_dvp_isp_dsi.py index 7eb81af001..db177ff556 100644 --- a/examples/peripherals/camera/dvp_isp_dsi/pytest_dvp_isp_dsi.py +++ b/examples/peripherals/camera/dvp_isp_dsi/pytest_dvp_isp_dsi.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_dvp_isp_dsi(dut: Dut) -> None: dut.expect_exact('Calling app_main()') diff --git a/examples/peripherals/camera/mipi_isp_dsi/pytest_mipi_isp_dsi.py b/examples/peripherals/camera/mipi_isp_dsi/pytest_mipi_isp_dsi.py index 44da4af5ef..528f5bd4d4 100644 --- a/examples/peripherals/camera/mipi_isp_dsi/pytest_mipi_isp_dsi.py +++ b/examples/peripherals/camera/mipi_isp_dsi/pytest_mipi_isp_dsi.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_mipi_isp_dsi(dut: Dut) -> None: dut.expect_exact('Calling app_main()') diff --git a/examples/peripherals/dac/dac_continuous/dac_audio/pytest_dac_audio.py b/examples/peripherals/dac/dac_continuous/dac_audio/pytest_dac_audio.py index e8940823a2..f22fe82084 100644 --- a/examples/peripherals/dac/dac_continuous/dac_audio/pytest_dac_audio.py +++ b/examples/peripherals/dac/dac_continuous/dac_audio/pytest_dac_audio.py @@ -1,8 +1,8 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def dac_example_expect(dut: Dut, mode: str) -> None: @@ -13,8 +13,6 @@ def dac_example_expect(dut: Dut, mode: str) -> None: dut.expect('Play count: 2', timeout=10) -@pytest.mark.esp32 -@pytest.mark.esp32s2 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -24,6 +22,7 @@ def dac_example_expect(dut: Dut, mode: str) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target']) def test_dac_audio_example(dut: Dut) -> None: sdkconfig = dut.app.sdkconfig if sdkconfig['EXAMPLE_DAC_WRITE_SYNC']: diff --git a/examples/peripherals/dac/dac_continuous/signal_generator/pytest_dac_continuous.py b/examples/peripherals/dac/dac_continuous/signal_generator/pytest_dac_continuous.py index 1abbe71b40..64f6114e4a 100644 --- a/examples/peripherals/dac/dac_continuous/signal_generator/pytest_dac_continuous.py +++ b/examples/peripherals/dac/dac_continuous/signal_generator/pytest_dac_continuous.py @@ -1,8 +1,8 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def test_dac_continuous_output(dut: Dut, mode: str, chan0_io: str, chan1_io: str) -> None: @@ -21,8 +21,6 @@ def test_dac_continuous_output(dut: Dut, mode: str, chan0_io: str, chan1_io: str dut.expect(r'dac continuous\({}\): sine wave start'.format(mode), timeout=20) -@pytest.mark.esp32 -@pytest.mark.esp32s2 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -32,6 +30,7 @@ def test_dac_continuous_output(dut: Dut, mode: str, chan0_io: str, chan1_io: str ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target']) def test_dac_continuous_example_with_dma(dut: Dut) -> None: sdkconfig = dut.app.sdkconfig if dut.target == 'esp32': diff --git a/examples/peripherals/dac/dac_cosine_wave/pytest_dac_cosine_wave.py b/examples/peripherals/dac/dac_cosine_wave/pytest_dac_cosine_wave.py index 22d432d12b..4684a350bf 100644 --- a/examples/peripherals/dac/dac_cosine_wave/pytest_dac_cosine_wave.py +++ b/examples/peripherals/dac/dac_cosine_wave/pytest_dac_cosine_wave.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.adc +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_dac_cosine_wave_example_with_12bit_adc(dut: Dut) -> None: res = [] for _ in range(30): @@ -19,8 +19,8 @@ def test_dac_cosine_wave_example_with_12bit_adc(dut: Dut) -> None: assert max(chan0_val) - min(chan0_val) > 1000 -@pytest.mark.esp32s2 @pytest.mark.adc +@idf_parametrize('target', ['esp32s2'], indirect=['target']) def test_dac_cosine_wave_example_with_13bit_adc(dut: Dut) -> None: res = [] for _ in range(30): diff --git a/examples/peripherals/dac/dac_oneshot/pytest_dac_oneshot.py b/examples/peripherals/dac/dac_oneshot/pytest_dac_oneshot.py index ed6fe07fd3..aa8d9b49c9 100644 --- a/examples/peripherals/dac/dac_oneshot/pytest_dac_oneshot.py +++ b/examples/peripherals/dac/dac_oneshot/pytest_dac_oneshot.py @@ -1,13 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target']) def test_dac_oneshot_example(dut: Dut) -> None: res = [] for _ in range(10): diff --git a/examples/peripherals/gpio/generic_gpio/pytest_generic_gpio_example.py b/examples/peripherals/gpio/generic_gpio/pytest_generic_gpio_example.py index 076a227db2..e329f494f2 100644 --- a/examples/peripherals/gpio/generic_gpio/pytest_generic_gpio_example.py +++ b/examples/peripherals/gpio/generic_gpio/pytest_generic_gpio_example.py @@ -1,16 +1,14 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - from typing import Callable import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic -def test_generic_gpio_example( - dut: Dut, log_minimum_free_heap_size: Callable[..., None] -) -> None: +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_generic_gpio_example(dut: Dut, log_minimum_free_heap_size: Callable[..., None]) -> None: log_minimum_free_heap_size() dut.expect(r'cnt: \d+') diff --git a/examples/peripherals/i2c/i2c_tools/pytest_examples_i2c_tools.py b/examples/peripherals/i2c/i2c_tools/pytest_examples_i2c_tools.py index cc152e0070..d5d02e8f3a 100644 --- a/examples/peripherals/i2c/i2c_tools/pytest_examples_i2c_tools.py +++ b/examples/peripherals/i2c/i2c_tools/pytest_examples_i2c_tools.py @@ -1,13 +1,14 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize EXPECT_TIMEOUT = 20 -@pytest.mark.esp32 @pytest.mark.ccs811 +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_i2ctools_example(dut: IdfDut) -> None: dut.expect_exact('i2c-tools>', timeout=EXPECT_TIMEOUT) # Get i2c address diff --git a/examples/peripherals/i2s/i2s_basic/i2s_pdm/pytest_i2s_pdm.py b/examples/peripherals/i2s/i2s_basic/i2s_pdm/pytest_i2s_pdm.py index dccedddf1b..09dd59f351 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_pdm/pytest_i2s_pdm.py +++ b/examples/peripherals/i2s/i2s_basic/i2s_pdm/pytest_i2s_pdm.py @@ -1,49 +1,43 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c61 @pytest.mark.generic -@pytest.mark.parametrize( - 'config', - ['pdm_tx'], - indirect=True +@pytest.mark.parametrize('config', ['pdm_tx'], indirect=True) +@idf_parametrize( + 'target', + ['esp32', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c61'], + indirect=['target'], ) def test_i2s_pdm_tx_example(dut: Dut) -> None: dut.expect(r'I2S PDM TX example start', timeout=5) dut.expect(r'---------------------------', timeout=5) dut.expect(r'i2s_common: tx channel is registered on I2S0 successfully', timeout=5) - dut.expect(r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' - r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', timeout=5) + dut.expect( + r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' + r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', + timeout=5, + ) dut.expect(r'i2s_pdm: The tx channel on I2S0 has been initialized to PDM TX mode successfully', timeout=5) dut.expect(r'i2s_common: i2s tx channel enabled', timeout=5) dut.expect(r'Playing bass `twinkle twinkle little star`', timeout=5) -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic -@pytest.mark.parametrize( - 'config', - ['pdm_rx'], - indirect=True -) +@pytest.mark.parametrize('config', ['pdm_rx'], indirect=True) +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32p4'], indirect=['target']) def test_i2s_pdm_rx_example(dut: Dut) -> None: dut.expect(r'I2S PDM RX example start', timeout=5) dut.expect(r'---------------------------', timeout=5) dut.expect(r'i2s_common: rx channel is registered on I2S0 successfully', timeout=5) - dut.expect(r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' - r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', timeout=5) + dut.expect( + r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' + r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', + timeout=5, + ) dut.expect(r'i2s_common: i2s rx channel enabled', timeout=5) dut.expect(r'Read Task: i2s read ([0-9]+) bytes', timeout=5) dut.expect(r'-----------------------------------', timeout=5) diff --git a/examples/peripherals/i2s/i2s_basic/i2s_std/pytest_i2s_std.py b/examples/peripherals/i2s/i2s_basic/i2s_std/pytest_i2s_std.py index d6f5bd34e2..9a7ef64722 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_std/pytest_i2s_std.py +++ b/examples/peripherals/i2s/i2s_basic/i2s_std/pytest_i2s_std.py @@ -1,33 +1,32 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c61 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c61'], + indirect=['target'], +) def test_i2s_basic_example(dut: Dut) -> None: - dut.expect(r'i2s_common: tx channel is registered on I2S0 successfully', timeout=5) dut.expect(r'i2s_common: rx channel is registered on I2S0 successfully', timeout=5) - dut.expect(r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' - r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', timeout=5) + dut.expect( + r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' + r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', + timeout=5, + ) dut.expect(r'i2s_std: The tx channel on I2S0 has been initialized to STD mode successfully', timeout=5) - dut.expect(r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' - r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', timeout=5) + dut.expect( + r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' + r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', + timeout=5, + ) dut.expect(r'i2s_std: The rx channel on I2S0 has been initialized to STD mode successfully', timeout=5) - chan_enable_pattern = [ - r'i2s_common: i2s tx channel enabled', - r'i2s_common: i2s rx channel enabled' - ] + chan_enable_pattern = [r'i2s_common: i2s tx channel enabled', r'i2s_common: i2s rx channel enabled'] dut.expect(chan_enable_pattern, timeout=5) dut.expect(chan_enable_pattern, timeout=5) dut.expect(r'Write Task: i2s write ([0-9]+) bytes', timeout=5) diff --git a/examples/peripherals/i2s/i2s_basic/i2s_tdm/pytest_i2s_tdm.py b/examples/peripherals/i2s/i2s_basic/i2s_tdm/pytest_i2s_tdm.py index a338654fa1..c586b1337f 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_tdm/pytest_i2s_tdm.py +++ b/examples/peripherals/i2s/i2s_basic/i2s_tdm/pytest_i2s_tdm.py @@ -1,31 +1,30 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c61 @pytest.mark.generic +@idf_parametrize( + 'target', ['esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c61'], indirect=['target'] +) def test_i2s_tdm_example(dut: Dut) -> None: - dut.expect(r'i2s_common: tx channel is registered on I2S0 successfully', timeout=5) dut.expect(r'i2s_common: rx channel is registered on I2S0 successfully', timeout=5) - dut.expect(r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' - r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', timeout=5) + dut.expect( + r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' + r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', + timeout=5, + ) dut.expect(r'i2s_tdm: The tx channel on I2S0 has been initialized to TDM mode successfully', timeout=5) - dut.expect(r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' - r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', timeout=5) + dut.expect( + r'i2s_common: DMA malloc info: dma_desc_num = ([0-9]+), ' + r'dma_desc_buf_size = dma_frame_num \* slot_num \* data_bit_width = ([0-9]+)', + timeout=5, + ) dut.expect(r'i2s_tdm: The rx channel on I2S0 has been initialized to TDM mode successfully', timeout=5) - chan_enable_pattern = [ - r'i2s_common: i2s tx channel enabled', - r'i2s_common: i2s rx channel enabled' - ] + chan_enable_pattern = [r'i2s_common: i2s tx channel enabled', r'i2s_common: i2s rx channel enabled'] dut.expect(chan_enable_pattern, timeout=5) dut.expect(chan_enable_pattern, timeout=5) dut.expect(r'Write Task: i2s write ([0-9]+) bytes', timeout=5) diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/pytest_i2s_es7210_tdm.py b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/pytest_i2s_es7210_tdm.py index 4f44422087..470ea7ef6d 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/pytest_i2s_es7210_tdm.py +++ b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/pytest_i2s_es7210_tdm.py @@ -1,15 +1,12 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.generic +@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2'], indirect=['target']) def test_i2s_es7210_tdm_example(dut: Dut) -> None: dut.expect_exact('example: Create I2S receive channel') dut.expect_exact('example: Configure I2S receive channel to TDM mode') diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/pytest_i2s_es8311.py b/examples/peripherals/i2s/i2s_codec/i2s_es8311/pytest_i2s_es8311.py index dceab56958..34621e578b 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/pytest_i2s_es8311.py +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/pytest_i2s_es8311.py @@ -1,26 +1,22 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c61 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c61'], + indirect=['target'], +) def test_i2s_es8311_example_generic(dut: Dut) -> None: dut.expect('i2s es8311 codec example start') dut.expect('-----------------------------') dut.expect('i2s_es8311: i2s driver init success') -@pytest.mark.esp32s3 @pytest.mark.es8311 @pytest.mark.parametrize( 'config', @@ -29,6 +25,7 @@ def test_i2s_es8311_example_generic(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_i2s_es8311_example_korvo2_v3(dut: Dut) -> None: dut.expect(r'i2s es8311 codec example start') dut.expect(r'-----------------------------') diff --git a/examples/peripherals/i2s/i2s_recorder/pytest_i2s_record.py b/examples/peripherals/i2s/i2s_recorder/pytest_i2s_record.py index 5c1a92c2fc..2a35f8310a 100644 --- a/examples/peripherals/i2s/i2s_recorder/pytest_i2s_record.py +++ b/examples/peripherals/i2s/i2s_recorder/pytest_i2s_record.py @@ -1,13 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32p4'], indirect=['target']) def test_i2s_recorder_generic(dut: Dut) -> None: dut.expect('PDM microphone recording example start') dut.expect('--------------------------------------') diff --git a/examples/peripherals/lcd/mipi_dsi/pytest_mipi_dsi_panel_lvgl.py b/examples/peripherals/lcd/mipi_dsi/pytest_mipi_dsi_panel_lvgl.py index 94c111ac79..d62150f2e0 100644 --- a/examples/peripherals/lcd/mipi_dsi/pytest_mipi_dsi_panel_lvgl.py +++ b/examples/peripherals/lcd/mipi_dsi/pytest_mipi_dsi_panel_lvgl.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_mipi_dsi_lcd_lvgl(dut: Dut) -> None: dut.expect_exact('Calling app_main()') diff --git a/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py b/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py index d9af5c60c3..62f20952e9 100644 --- a/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py +++ b/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 @pytest.mark.octal_psram @pytest.mark.parametrize( 'config', @@ -15,6 +15,7 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_rgb_lcd_lvgl_esp32s3(dut: Dut) -> None: dut.expect_exact('example: Turn off LCD backlight') dut.expect_exact('example: Install RGB LCD panel driver') @@ -26,7 +27,6 @@ def test_rgb_lcd_lvgl_esp32s3(dut: Dut) -> None: dut.expect_exact('example: Display LVGL UI') -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -37,6 +37,7 @@ def test_rgb_lcd_lvgl_esp32s3(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_rgb_lcd_lvgl_esp32p4(dut: Dut) -> None: dut.expect_exact('example: Turn off LCD backlight') dut.expect_exact('example: Install RGB LCD panel driver') diff --git a/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/pytest_bdc_speed_control.py b/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/pytest_bdc_speed_control.py index 95579418bd..3100e7e1df 100644 --- a/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/pytest_bdc_speed_control.py +++ b/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/pytest_bdc_speed_control.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_bdc_speed_control_example(dut: Dut) -> None: dut.expect_exact('example: Create DC motor') dut.expect_exact('example: Init pcnt driver to decode rotary signal') diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/pytest_bldc_hall_control.py b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/pytest_bldc_hall_control.py index ccc6a4e34e..f1859a49e3 100644 --- a/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/pytest_bldc_hall_control.py +++ b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/pytest_bldc_hall_control.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_bldc_hall_control_example(dut: Dut) -> None: dut.expect_exact('example: Disable MOSFET gate') dut.expect_exact('example: Create MCPWM timer') diff --git a/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/pytest_hc_sr04.py b/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/pytest_hc_sr04.py index f677a255a9..ef2626c83b 100644 --- a/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/pytest_hc_sr04.py +++ b/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/pytest_hc_sr04.py @@ -1,16 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32c6', 'esp32c5', 'esp32h2', 'esp32p4'], indirect=['target']) def test_hc_sr04_example(dut: Dut) -> None: dut.expect_exact('example: Install capture timer') dut.expect_exact('example: Install capture channel') diff --git a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/pytest_foc_open_loop.py b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/pytest_foc_open_loop.py index 2e7735c8eb..2b8ffe5be3 100644 --- a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/pytest_foc_open_loop.py +++ b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/pytest_foc_open_loop.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_open_foc(dut: Dut) -> None: dut.expect_exact('example_foc: Hello FOC') dut.expect_exact('example_foc: Inverter init OK') diff --git a/examples/peripherals/mcpwm/mcpwm_servo_control/pytest_servo_mg996r.py b/examples/peripherals/mcpwm/mcpwm_servo_control/pytest_servo_mg996r.py index 11a7d01cd8..87b9c3b548 100644 --- a/examples/peripherals/mcpwm/mcpwm_servo_control/pytest_servo_mg996r.py +++ b/examples/peripherals/mcpwm/mcpwm_servo_control/pytest_servo_mg996r.py @@ -1,16 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) def test_servo_mg996r_example(dut: Dut) -> None: dut.expect_exact('example: Create timer and operator') dut.expect_exact('example: Connect timer and operator') diff --git a/examples/peripherals/mcpwm/mcpwm_sync/pytest_mcpwm_sync.py b/examples/peripherals/mcpwm/mcpwm_sync/pytest_mcpwm_sync.py index 23ba1a4e34..2d275fa594 100644 --- a/examples/peripherals/mcpwm/mcpwm_sync/pytest_mcpwm_sync.py +++ b/examples/peripherals/mcpwm/mcpwm_sync/pytest_mcpwm_sync.py @@ -1,21 +1,16 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - pytest.param('gpio', marks=[pytest.mark.esp32, pytest.mark.esp32s3]), - pytest.param('tez', marks=[pytest.mark.esp32, pytest.mark.esp32s3]), - pytest.param('soft', marks=[pytest.mark.esp32s3]), -], indirect=True) +@idf_parametrize( + 'config,target', + [('gpio', 'esp32'), ('gpio', 'esp32s3'), ('tez', 'esp32'), ('tez', 'esp32s3'), ('soft', 'esp32s3')], + indirect=['config', 'target'], +) def test_mcpwm_sync_example(dut: Dut) -> None: dut.expect_exact('example: Create timers') dut.expect_exact('example: Create operators') diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/pytest_logic_analyzer.py b/examples/peripherals/parlio/parlio_rx/logic_analyzer/pytest_logic_analyzer.py index 2d6bc17398..1d95a40a17 100644 --- a/examples/peripherals/parlio/parlio_rx/logic_analyzer/pytest_logic_analyzer.py +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/pytest_logic_analyzer.py @@ -1,13 +1,10 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -16,6 +13,7 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) def test_logic_analyzer_flash_stream(dut: Dut) -> None: dut.expect(r'flash_fat: Probe data partition base addr: \w+ size: \w+') dut.expect(r'flash_fat: flash FATFS mounted') diff --git a/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/pytest_simple_rgb_led_matrix.py b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/pytest_simple_rgb_led_matrix.py index 940d78c615..61e632006d 100644 --- a/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/pytest_simple_rgb_led_matrix.py +++ b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/pytest_simple_rgb_led_matrix.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c6 @pytest.mark.generic +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_simple_rgb_led_matrix_example(dut: Dut) -> None: dut.expect_exact('example: Install fast GPIO bundle for line address control') dut.expect_exact('example: Install parallel IO TX unit') diff --git a/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py b/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py index 144fa82be3..5c0ffdf5e7 100644 --- a/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py +++ b/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py @@ -1,17 +1,14 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded.dut import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target'] +) def test_rotary_encoder(dut: Dut) -> None: dut.expect_exact('install pcnt unit') dut.expect_exact('set glitch filter') diff --git a/examples/peripherals/ppa/ppa_dsi/pytest_ppa_dsi.py b/examples/peripherals/ppa/ppa_dsi/pytest_ppa_dsi.py index 65eece5657..e4ccde4176 100644 --- a/examples/peripherals/ppa/ppa_dsi/pytest_ppa_dsi.py +++ b/examples/peripherals/ppa/ppa_dsi/pytest_ppa_dsi.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_ppa_dsi(dut: Dut) -> None: dut.expect_exact('Calling app_main()') diff --git a/examples/peripherals/rmt/dshot_esc/pytest_dshot_esc.py b/examples/peripherals/rmt/dshot_esc/pytest_dshot_esc.py index 3f2470cea4..ad99440722 100644 --- a/examples/peripherals/rmt/dshot_esc/pytest_dshot_esc.py +++ b/examples/peripherals/rmt/dshot_esc/pytest_dshot_esc.py @@ -1,18 +1,16 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], + indirect=['target'], +) def test_dshot_esc_example(dut: Dut) -> None: dut.expect_exact('example: Create RMT TX channel') dut.expect_exact('example: Install Dshot ESC encoder') diff --git a/examples/peripherals/rmt/ir_nec_transceiver/pytest_ir_nec.py b/examples/peripherals/rmt/ir_nec_transceiver/pytest_ir_nec.py index 7c6979a62a..75bace0569 100644 --- a/examples/peripherals/rmt/ir_nec_transceiver/pytest_ir_nec.py +++ b/examples/peripherals/rmt/ir_nec_transceiver/pytest_ir_nec.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.ir_transceiver +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_ir_nec_example(dut: Dut) -> None: dut.expect_exact('example: create RMT RX channel') dut.expect_exact('example: register RX done callback') diff --git a/examples/peripherals/rmt/led_strip/pytest_led_strip.py b/examples/peripherals/rmt/led_strip/pytest_led_strip.py index e7f73b87a8..60714e611d 100644 --- a/examples/peripherals/rmt/led_strip/pytest_led_strip.py +++ b/examples/peripherals/rmt/led_strip/pytest_led_strip.py @@ -1,18 +1,16 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], + indirect=['target'], +) def test_led_strip_example(dut: Dut) -> None: dut.expect_exact('example: Create RMT TX channel') dut.expect_exact('example: Install led strip encoder') diff --git a/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py b/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py index 3ba73406f0..bab9319bcb 100644 --- a/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py +++ b/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py @@ -1,17 +1,14 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', ['esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target'] +) def test_musical_buzzer_example(dut: Dut) -> None: dut.expect_exact('example: Create RMT TX channel') dut.expect_exact('example: Install musical score encoder') diff --git a/examples/peripherals/rmt/onewire/pytest_onewire.py b/examples/peripherals/rmt/onewire/pytest_onewire.py index 3204c21ed9..0883189e8a 100644 --- a/examples/peripherals/rmt/onewire/pytest_onewire.py +++ b/examples/peripherals/rmt/onewire/pytest_onewire.py @@ -1,18 +1,16 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], + indirect=['target'], +) def test_onewire_example(dut: Dut) -> None: dut.expect_exact('example: 1-Wire bus installed on GPIO') dut.expect_exact('example: Device iterator created, start searching') diff --git a/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py b/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py index 4a730b2019..d7e6fbf263 100644 --- a/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py +++ b/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py @@ -1,15 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32s3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) def test_stepper_motor_example(dut: Dut) -> None: dut.expect_exact('example: Initialize EN + DIR GPIO') dut.expect_exact('example: Create RMT TX channel') diff --git a/examples/peripherals/sdio/pytest_sdio_test.py b/examples/peripherals/sdio/pytest_sdio_test.py index 487d8d35f6..89c9863066 100644 --- a/examples/peripherals/sdio/pytest_sdio_test.py +++ b/examples/peripherals/sdio/pytest_sdio_test.py @@ -1,13 +1,13 @@ -# SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import os from typing import Tuple import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.sdio_master_slave @pytest.mark.parametrize( 'count, app_path', @@ -16,6 +16,7 @@ from pytest_embedded_idf import IdfDut ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_example_sdio_communication(dut: Tuple[IdfDut, IdfDut]) -> None: """ Configurations diff --git a/examples/peripherals/sigma_delta/sdm_dac/pytest_sdm_dac_example.py b/examples/peripherals/sigma_delta/sdm_dac/pytest_sdm_dac_example.py index 6155a182a0..727144e2ce 100644 --- a/examples/peripherals/sigma_delta/sdm_dac/pytest_sdm_dac_example.py +++ b/examples/peripherals/sigma_delta/sdm_dac/pytest_sdm_dac_example.py @@ -1,18 +1,16 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], + indirect=['target'], +) def test_sdm_dac_example(dut: Dut) -> None: dut.expect(r'sdm_dac: Sigma-delta output is attached to GPIO \w+') dut.expect(r'sdm_dac: Timer allocated with resolution \w+ Hz') diff --git a/examples/peripherals/sigma_delta/sdm_led/pytest_sdm_led_example.py b/examples/peripherals/sigma_delta/sdm_led/pytest_sdm_led_example.py index c30c7d274e..5dda8d8c0c 100644 --- a/examples/peripherals/sigma_delta/sdm_led/pytest_sdm_led_example.py +++ b/examples/peripherals/sigma_delta/sdm_led/pytest_sdm_led_example.py @@ -1,18 +1,16 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], + indirect=['target'], +) def test_sdm_led_example(dut: Dut) -> None: dut.expect_exact('sdm_led: Install sigma delta channel') dut.expect_exact('sdm_led: Enable sigma delta channel') diff --git a/examples/peripherals/temperature_sensor/temp_sensor/pytest_temp_sensor_example.py b/examples/peripherals/temperature_sensor/temp_sensor/pytest_temp_sensor_example.py index 00ff68d768..6801d6ab9a 100644 --- a/examples/peripherals/temperature_sensor/temp_sensor/pytest_temp_sensor_example.py +++ b/examples/peripherals/temperature_sensor/temp_sensor/pytest_temp_sensor_example.py @@ -1,18 +1,16 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded.dut import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5'], + indirect=['target'], +) def test_temp_sensor_example(dut: Dut) -> None: dut.expect_exact('Install temperature sensor') dut.expect_exact('Enable temperature sensor') diff --git a/examples/peripherals/temperature_sensor/temp_sensor_monitor/pytest_temp_sensor_monitor_example.py b/examples/peripherals/temperature_sensor/temp_sensor_monitor/pytest_temp_sensor_monitor_example.py index 375605701a..5238a7c27e 100644 --- a/examples/peripherals/temperature_sensor/temp_sensor_monitor/pytest_temp_sensor_monitor_example.py +++ b/examples/peripherals/temperature_sensor/temp_sensor_monitor/pytest_temp_sensor_monitor_example.py @@ -1,14 +1,12 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded.dut import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.generic +@idf_parametrize('target', ['esp32c6', 'esp32h2', 'esp32p4', 'esp32c5'], indirect=['target']) def test_temp_sensor_monitor_example(dut: Dut) -> None: dut.expect_exact('Install temperature sensor') dut.expect_exact('Enable temperature sensor') diff --git a/examples/peripherals/timer_group/gptimer/pytest_gptimer_example.py b/examples/peripherals/timer_group/gptimer/pytest_gptimer_example.py index db52faffe3..f4de1bb418 100644 --- a/examples/peripherals/timer_group/gptimer/pytest_gptimer_example.py +++ b/examples/peripherals/timer_group/gptimer/pytest_gptimer_example.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_gptimer_example(dut: Dut) -> None: dut.expect_exact('Create timer handle', timeout=5) dut.expect_exact('Start timer, stop it at alarm event', timeout=5) diff --git a/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py b/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py index 2756fe0fa2..b1e2a34978 100644 --- a/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py +++ b/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py @@ -1,15 +1,12 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], indirect=['target']) def test_gptimer_capture(dut: Dut) -> None: dut.expect_exact('Configure trig gpio') dut.expect_exact('Configure echo gpio') diff --git a/examples/peripherals/timer_group/wiegand_interface/pytest_wiegand.py b/examples/peripherals/timer_group/wiegand_interface/pytest_wiegand.py index 8e7f391aeb..44da87aa12 100644 --- a/examples/peripherals/timer_group/wiegand_interface/pytest_wiegand.py +++ b/examples/peripherals/timer_group/wiegand_interface/pytest_wiegand.py @@ -1,19 +1,16 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32p4'], + indirect=['target'], +) def test_gptimer_wiegand(dut: Dut) -> None: dut.expect_exact('example: Configure wiegand interface') dut.expect_exact('example: send wiegand data') diff --git a/examples/peripherals/touch_sensor/touch_element/touch_button/pytest_touch_button.py b/examples/peripherals/touch_sensor/touch_element/touch_button/pytest_touch_button.py index 013bf9dbb0..847b81cfc9 100644 --- a/examples/peripherals/touch_sensor/touch_element/touch_button/pytest_touch_button.py +++ b/examples/peripherals/touch_sensor/touch_element/touch_button/pytest_touch_button.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_touch_button(dut: Dut) -> None: dut.expect_exact('Touch Button Example: Touch element library installed') dut.expect_exact('Touch Button Example: Touch button installed') diff --git a/examples/peripherals/touch_sensor/touch_element/touch_element_waterproof/pytest_touch_element_waterproof.py b/examples/peripherals/touch_sensor/touch_element/touch_element_waterproof/pytest_touch_element_waterproof.py index 7e1e25e008..5da4089816 100644 --- a/examples/peripherals/touch_sensor/touch_element/touch_element_waterproof/pytest_touch_element_waterproof.py +++ b/examples/peripherals/touch_sensor/touch_element/touch_element_waterproof/pytest_touch_element_waterproof.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_touch_element_waterproof(dut: Dut) -> None: dut.expect_exact('Touch Element Waterproof Example: Touch Element library install') dut.expect_exact('Touch Element Waterproof Example: Touch Element waterproof install') diff --git a/examples/peripherals/touch_sensor/touch_element/touch_elements_combination/pytest_touch_elements_combination.py b/examples/peripherals/touch_sensor/touch_element/touch_elements_combination/pytest_touch_elements_combination.py index d91e4fba80..64e6cdf107 100644 --- a/examples/peripherals/touch_sensor/touch_element/touch_elements_combination/pytest_touch_elements_combination.py +++ b/examples/peripherals/touch_sensor/touch_element/touch_elements_combination/pytest_touch_elements_combination.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_touch_elements_combination(dut: Dut) -> None: dut.expect_exact('Touch Elements Combination Example: Touch element library installed') dut.expect_exact('Touch Elements Combination Example: Touch button installed') diff --git a/examples/peripherals/touch_sensor/touch_element/touch_matrix/pytest_touch_matrix.py b/examples/peripherals/touch_sensor/touch_element/touch_matrix/pytest_touch_matrix.py index cc6efd44e5..837fc91412 100644 --- a/examples/peripherals/touch_sensor/touch_element/touch_matrix/pytest_touch_matrix.py +++ b/examples/peripherals/touch_sensor/touch_element/touch_matrix/pytest_touch_matrix.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_touch_matrix(dut: Dut) -> None: dut.expect_exact('Touch Matrix Example: Touch element library installed') dut.expect_exact('Touch Matrix Example: Touch matrix installed') diff --git a/examples/peripherals/touch_sensor/touch_element/touch_slider/pytest_touch_slider.py b/examples/peripherals/touch_sensor/touch_element/touch_slider/pytest_touch_slider.py index 18edc4f240..86943f5859 100644 --- a/examples/peripherals/touch_sensor/touch_element/touch_slider/pytest_touch_slider.py +++ b/examples/peripherals/touch_sensor/touch_element/touch_slider/pytest_touch_slider.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_touch_slider(dut: Dut) -> None: dut.expect_exact('Touch Slider Example: Touch element library installed') dut.expect_exact('Touch Slider Example: Touch slider installed') diff --git a/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_interrupt/pytest_touch_pad_interrupt_v1.py b/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_interrupt/pytest_touch_pad_interrupt_v1.py index 816b9c2e99..81a922e197 100644 --- a/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_interrupt/pytest_touch_pad_interrupt_v1.py +++ b/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_interrupt/pytest_touch_pad_interrupt_v1.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_touch_pad_interrupt_v1(dut: Dut) -> None: dut.expect_exact('Touch pad: Initializing touch pad') dut.expect(r'test init: touch pad \[\d+\] val is \d+') diff --git a/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_read/pytest_touch_pad_read_v1.py b/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_read/pytest_touch_pad_read_v1.py index 72fd5efa22..2a0ada6349 100644 --- a/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_read/pytest_touch_pad_read_v1.py +++ b/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_read/pytest_touch_pad_read_v1.py @@ -1,12 +1,15 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_touch_pad_read_v1(dut: Dut) -> None: dut.expect_exact('Touch Sensor filter mode read, the output format is:') - dut.expect(r'T0:\[\s*\d+,\s*\d+\] T1:\[\s*\d+,\s*\d+\] T2:\[\s*\d+,\s*\d+\] T3:\[\s*\d+,\s*\d+\] T4:\[\s*\d+,\s*\d+\]' - r' T5:\[\s*\d+,\s*\d+\] T6:\[\s*\d+,\s*\d+\] T7:\[\s*\d+,\s*\d+\] T8:\[\s*\d+,\s*\d+\] T9:\[\s*\d+,\s*\d+\]') + dut.expect( + r'T0:\[\s*\d+,\s*\d+\] T1:\[\s*\d+,\s*\d+\] T2:\[\s*\d+,\s*\d+\] T3:\[\s*\d+,\s*\d+\] T4:\[\s*\d+,\s*\d+\]' + r' T5:\[\s*\d+,\s*\d+\] T6:\[\s*\d+,\s*\d+\] T7:\[\s*\d+,\s*\d+\] T8:\[\s*\d+,\s*\d+\] T9:\[\s*\d+,\s*\d+\]' + ) diff --git a/examples/peripherals/touch_sensor/touch_sensor_v2/touch_pad_interrupt/pytest_touch_pad_interrupt_v2.py b/examples/peripherals/touch_sensor/touch_sensor_v2/touch_pad_interrupt/pytest_touch_pad_interrupt_v2.py index 890b110e91..d7701d38c1 100644 --- a/examples/peripherals/touch_sensor/touch_sensor_v2/touch_pad_interrupt/pytest_touch_pad_interrupt_v2.py +++ b/examples/peripherals/touch_sensor/touch_sensor_v2/touch_pad_interrupt/pytest_touch_pad_interrupt_v2.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_touch_pad_interrupt_v2(dut: Dut) -> None: dut.expect_exact('Touch pad: Initializing touch pad') dut.expect_exact('Touch pad: Denoise function init') diff --git a/examples/peripherals/touch_sensor/touch_sensor_v2/touch_pad_read/pytest_touch_pad_read_v2.py b/examples/peripherals/touch_sensor/touch_sensor_v2/touch_pad_read/pytest_touch_pad_read_v2.py index 4c58c67492..23a31242a7 100644 --- a/examples/peripherals/touch_sensor/touch_sensor_v2/touch_pad_read/pytest_touch_pad_read_v2.py +++ b/examples/peripherals/touch_sensor/touch_sensor_v2/touch_pad_read/pytest_touch_pad_read_v2.py @@ -1,13 +1,15 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_touch_pad_read_v2(dut: Dut) -> None: dut.expect_exact('touch read: Denoise function init') - dut.expect(r'T1: \[\d+\] T2: \[\d+\] T3: \[\d+\] T4: \[\d+\] T5: \[\d+\] T6: \[\d+\] T7: \[\d+\] T8: \[\d+\] T9: \[\d+\]' - r' T10: \[\d+\] T11: \[\d+\] T12: \[\d+\] T13: \[\d+\] T14: \[\d+\]') + dut.expect( + r'T1: \[\d+\] T2: \[\d+\] T3: \[\d+\] T4: \[\d+\] T5: \[\d+\] T6: \[\d+\] T7: \[\d+\] T8: \[\d+\] T9: \[\d+\]' + r' T10: \[\d+\] T11: \[\d+\] T12: \[\d+\] T13: \[\d+\] T14: \[\d+\]' + ) diff --git a/examples/peripherals/touch_sensor/touch_sensor_v3/pytest_touch_sens_v3.py b/examples/peripherals/touch_sensor/touch_sensor_v3/pytest_touch_sens_v3.py index f03c56c2ff..50844b0d05 100644 --- a/examples/peripherals/touch_sensor/touch_sensor_v3/pytest_touch_sens_v3.py +++ b/examples/peripherals/touch_sensor/touch_sensor_v3/pytest_touch_sens_v3.py @@ -1,12 +1,13 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 runners do not support touch pins') @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_touch_sens_v3(dut: Dut) -> None: dut.expect_exact('Initial benchmark and new threshold are:') dut.expect(r'\[CH [0-9]+\] 0: [0-9]+, [0-9]+') diff --git a/examples/peripherals/twai/twai_alert_and_recovery/pytest_twai_alert_recovery_example.py b/examples/peripherals/twai/twai_alert_and_recovery/pytest_twai_alert_recovery_example.py index 200fb60709..d2f915df17 100644 --- a/examples/peripherals/twai/twai_alert_and_recovery/pytest_twai_alert_recovery_example.py +++ b/examples/peripherals/twai/twai_alert_and_recovery/pytest_twai_alert_recovery_example.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.twai_transceiver +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_twai_alert_recovery_example(dut: Dut) -> None: dut.expect_exact('TWAI Alert and Recovery: Driver installed') dut.expect_exact('TWAI Alert and Recovery: Driver uninstalled') diff --git a/examples/peripherals/twai/twai_network/pytest_twai_network_example.py b/examples/peripherals/twai/twai_network/pytest_twai_network_example.py index 6eb3f43327..2476dc5250 100644 --- a/examples/peripherals/twai/twai_network/pytest_twai_network_example.py +++ b/examples/peripherals/twai/twai_network/pytest_twai_network_example.py @@ -1,14 +1,14 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import os.path from threading import Thread from typing import Tuple import pytest from pytest_embedded import Dut - +from pytest_embedded_idf.utils import idf_parametrize # Define tuple of strings to expect for each DUT. + master_expect = ('TWAI Master: Driver installed', 'TWAI Master: Driver uninstalled') slave_expect = ('TWAI Slave: Driver installed', 'TWAI Slave: Driver uninstalled') listen_only_expect = ( @@ -21,9 +21,7 @@ def dut_thread_callback(**kwargs) -> None: # type: ignore # Parse keyword arguments dut = kwargs['dut'] # Get DUT from kwargs expected = kwargs['expected'] - result = kwargs[ - 'result' - ] # Get result[out] from kwargs. MUST be of mutable type e.g. list + result = kwargs['result'] # Get result[out] from kwargs. MUST be of mutable type e.g. list # Must reset again as flashing during start_app will reset multiple times, causing unexpected results dut.reset() @@ -35,7 +33,6 @@ def dut_thread_callback(**kwargs) -> None: # type: ignore result[0] = True -@pytest.mark.esp32 @pytest.mark.skip(reason="there's not a good approach to sync multiple DUTs") @pytest.mark.twai_network @pytest.mark.parametrize( @@ -50,6 +47,7 @@ def dut_thread_callback(**kwargs) -> None: # type: ignore ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_twai_network_example(dut: Tuple[Dut, Dut, Dut]) -> None: dut_master = dut[0] dut_slave = dut[1] @@ -66,15 +64,9 @@ def test_twai_network_example(dut: Tuple[Dut, Dut, Dut]) -> None: } # Create thread for each dut - dut_master_thread = Thread( - target=dut_thread_callback, name='Master Thread', kwargs=master_kwargs - ) - dut_slave_thread = Thread( - target=dut_thread_callback, name='Slave Thread', kwargs=slave_kwargs - ) - dut_listen_only_thread = Thread( - target=dut_thread_callback, name='Listen Only Thread', kwargs=listen_only_kwargs - ) + dut_master_thread = Thread(target=dut_thread_callback, name='Master Thread', kwargs=master_kwargs) + dut_slave_thread = Thread(target=dut_thread_callback, name='Slave Thread', kwargs=slave_kwargs) + dut_listen_only_thread = Thread(target=dut_thread_callback, name='Listen Only Thread', kwargs=listen_only_kwargs) # Start each thread dut_listen_only_thread.start() diff --git a/examples/peripherals/twai/twai_self_test/pytest_twai_self_test_example.py b/examples/peripherals/twai/twai_self_test/pytest_twai_self_test_example.py index ea139a4e35..85981e80f3 100644 --- a/examples/peripherals/twai/twai_self_test/pytest_twai_self_test_example.py +++ b/examples/peripherals/twai/twai_self_test/pytest_twai_self_test_example.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.twai_transceiver +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_twai_self_test_example(dut: Dut) -> None: dut.expect_exact('TWAI Self Test: Driver installed') dut.expect_exact('TWAI Self Test: Driver uninstalled') diff --git a/examples/peripherals/uart/uart_async_rxtxtasks/pytest_async_rxtxtasks.py b/examples/peripherals/uart/uart_async_rxtxtasks/pytest_async_rxtxtasks.py index b039660e56..23ee49a011 100644 --- a/examples/peripherals/uart/uart_async_rxtxtasks/pytest_async_rxtxtasks.py +++ b/examples/peripherals/uart/uart_async_rxtxtasks/pytest_async_rxtxtasks.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_uart_async_rxtxtasks_example(dut: Dut) -> None: dut.expect_exact('TX_TASK: Wrote 11 bytes') diff --git a/examples/peripherals/uart/uart_events/pytest_events.py b/examples/peripherals/uart/uart_events/pytest_events.py index fb4a8a4611..3180c8b51e 100644 --- a/examples/peripherals/uart/uart_events/pytest_events.py +++ b/examples/peripherals/uart/uart_events/pytest_events.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_uart_events_example(dut: Dut) -> None: dut.expect_exact('Returned from app_main()') dut.write('a') diff --git a/examples/peripherals/uart/uart_select/pytest_uart_select.py b/examples/peripherals/uart/uart_select/pytest_uart_select.py index eb37f26cee..d1a7136b6a 100644 --- a/examples/peripherals/uart/uart_select/pytest_uart_select.py +++ b/examples/peripherals/uart/uart_select/pytest_uart_select.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_uart_select_example(dut: Dut) -> None: dut.expect_exact('uart_select_example: Timeout has been reached and nothing has been received') dut.write('a') diff --git a/examples/peripherals/usb/device/tusb_composite_msc_serialdevice/pytest_usb_device_composite.py b/examples/peripherals/usb/device/tusb_composite_msc_serialdevice/pytest_usb_device_composite.py index 5ff64a8de7..edbcfaee32 100644 --- a/examples/peripherals/usb/device/tusb_composite_msc_serialdevice/pytest_usb_device_composite.py +++ b/examples/peripherals/usb/device/tusb_composite_msc_serialdevice/pytest_usb_device_composite.py @@ -1,18 +1,17 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 from time import sleep import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize from serial import Serial from serial.tools.list_ports import comports -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='lack of runners with usb_device tag') @pytest.mark.usb_device +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_usb_composite_device_serial_example(dut: Dut) -> None: dut.expect_exact('Hello World!') dut.expect_exact('USB Composite initialization') diff --git a/examples/peripherals/usb/device/tusb_console/pytest_usb_device_console.py b/examples/peripherals/usb/device/tusb_console/pytest_usb_device_console.py index 879b6a9e2e..55334ea442 100644 --- a/examples/peripherals/usb/device/tusb_console/pytest_usb_device_console.py +++ b/examples/peripherals/usb/device/tusb_console/pytest_usb_device_console.py @@ -1,18 +1,17 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 from time import sleep import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize from serial import Serial from serial.tools.list_ports import comports -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='lack of runners with usb_device tag') @pytest.mark.usb_device +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_usb_device_console_example(dut: Dut) -> None: dut.expect_exact('USB initialization DONE') dut.expect_exact('example: log -> UART') diff --git a/examples/peripherals/usb/device/tusb_hid/pytest_usb_device_hid.py b/examples/peripherals/usb/device/tusb_hid/pytest_usb_device_hid.py index eacb17ccf5..08650a3ff4 100644 --- a/examples/peripherals/usb/device/tusb_hid/pytest_usb_device_hid.py +++ b/examples/peripherals/usb/device/tusb_hid/pytest_usb_device_hid.py @@ -1,14 +1,13 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='lack of runners with usb_device tag') @pytest.mark.usb_device +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_usb_device_hid_example(dut: Dut) -> None: dut.expect_exact('USB initialization DONE') dut.expect_exact('Sending Keyboard report') diff --git a/examples/peripherals/usb/device/tusb_midi/pytest_usb_device_midi.py b/examples/peripherals/usb/device/tusb_midi/pytest_usb_device_midi.py index b3eb2a2ca3..4497cf8506 100644 --- a/examples/peripherals/usb/device/tusb_midi/pytest_usb_device_midi.py +++ b/examples/peripherals/usb/device/tusb_midi/pytest_usb_device_midi.py @@ -1,14 +1,13 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='lack of runners with usb_device tag') @pytest.mark.usb_device +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_usb_device_midi_example(dut: Dut) -> None: dut.expect_exact('USB initialization DONE') dut.expect_exact('MIDI write task init') diff --git a/examples/peripherals/usb/device/tusb_msc/pytest_usb_device_msc.py b/examples/peripherals/usb/device/tusb_msc/pytest_usb_device_msc.py index ca792f328f..714701723e 100644 --- a/examples/peripherals/usb/device/tusb_msc/pytest_usb_device_msc.py +++ b/examples/peripherals/usb/device/tusb_msc/pytest_usb_device_msc.py @@ -1,14 +1,13 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='lack of runners with usb_device tag') @pytest.mark.usb_device +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_usb_device_msc_example(dut: Dut) -> None: dut.expect('Mount storage') dut.expect('TinyUSB Driver installed') diff --git a/examples/peripherals/usb/device/tusb_ncm/pytest_usb_device_ncm.py b/examples/peripherals/usb/device/tusb_ncm/pytest_usb_device_ncm.py index b01a9c47a8..de4d1cf8e0 100644 --- a/examples/peripherals/usb/device/tusb_ncm/pytest_usb_device_ncm.py +++ b/examples/peripherals/usb/device/tusb_ncm/pytest_usb_device_ncm.py @@ -1,22 +1,24 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import subprocess import time import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='lack of runners with usb_device tag') @pytest.mark.usb_device +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_usb_device_ncm_example(dut: Dut) -> None: - netif_mac = dut.expect(r'Network interface HW address: ([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})') + netif_mac = dut.expect( + r'Network interface HW address: ([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})' + ) netif_mac = netif_mac.group(1).decode('utf-8') dut.expect_exact('USB NCM and WiFi initialized and started') dut.expect_exact('Returned from app_main()') - time.sleep(1) # Wait 1s for the network interface to appear + time.sleep(1) # Wait 1s for the network interface to appear out_bytes = subprocess.check_output('ifconfig', shell=True, timeout=5) out_str = out_bytes.decode('utf-8') print('expected network interface HW address: ', netif_mac) diff --git a/examples/peripherals/usb/device/tusb_serial_device/pytest_usb_device_serial.py b/examples/peripherals/usb/device/tusb_serial_device/pytest_usb_device_serial.py index 9a5e25550c..b572c2687e 100644 --- a/examples/peripherals/usb/device/tusb_serial_device/pytest_usb_device_serial.py +++ b/examples/peripherals/usb/device/tusb_serial_device/pytest_usb_device_serial.py @@ -1,18 +1,17 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 from time import sleep import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize from serial import Serial from serial.tools.list_ports import comports -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='lack of runners with usb_device tag') @pytest.mark.usb_device +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_usb_device_serial_example(dut: Dut) -> None: dut.expect_exact('USB initialization DONE') sleep(2) # Some time for the OS to enumerate our USB device diff --git a/examples/peripherals/usb/host/msc/pytest_usb_host_msc.py b/examples/peripherals/usb/host/msc/pytest_usb_host_msc.py index cb9e8c78e5..5209a07224 100644 --- a/examples/peripherals/usb/host/msc/pytest_usb_host_msc.py +++ b/examples/peripherals/usb/host/msc/pytest_usb_host_msc.py @@ -1,18 +1,22 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut - +from pytest_embedded_idf.utils import idf_parametrize CONFIGS = [ pytest.param('default', marks=[pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32p4]), - pytest.param('esp32p4_psram', marks=[pytest.mark.esp32p4]) + pytest.param('esp32p4_psram', marks=[pytest.mark.esp32p4]), ] @pytest.mark.usb_host_flash_disk @pytest.mark.temp_skip_ci(targets=['esp32s2'], reason='lack of runners with usb_host_flash_disk tag') -@pytest.mark.parametrize('config', CONFIGS, indirect=True) +@idf_parametrize( + 'config,target', + [('default', 'esp32p4'), ('default', 'esp32s2'), ('default', 'esp32s3'), ('esp32p4_psram', 'esp32p4')], + indirect=['config', 'target'], +) def test_usb_host_msc_example(dut: Dut) -> None: # Check whether the USB-DWC DMA capable memory is allocated in PSRAM usb_dwc_in_psram = bool(dut.app.sdkconfig.get('USB_HOST_DWC_DMA_CAP_MEMORY_IN_PSRAM')) diff --git a/examples/peripherals/usb/host/usb_host_lib/pytest_usb_host_lib.py b/examples/peripherals/usb/host/usb_host_lib/pytest_usb_host_lib.py index 4f1e0a3168..93ebcebb01 100644 --- a/examples/peripherals/usb/host/usb_host_lib/pytest_usb_host_lib.py +++ b/examples/peripherals/usb/host/usb_host_lib/pytest_usb_host_lib.py @@ -1,14 +1,13 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.temp_skip_ci(targets=['esp32s2'], reason='lack of runners with usb_host_flash_disk tag') @pytest.mark.usb_host_flash_disk +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_usb_host_lib_example(dut: Dut) -> None: # register client dut.expect_exact('CLASS: Registering Client') diff --git a/examples/peripherals/usb_serial_jtag/usb_serial_jtag_echo/pytest_usj_echo_example.py b/examples/peripherals/usb_serial_jtag/usb_serial_jtag_echo/pytest_usj_echo_example.py index 0bda957d04..293e60fe56 100644 --- a/examples/peripherals/usb_serial_jtag/usb_serial_jtag_echo/pytest_usj_echo_example.py +++ b/examples/peripherals/usb_serial_jtag/usb_serial_jtag_echo/pytest_usj_echo_example.py @@ -1,21 +1,22 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 from time import sleep import pytest import serial.tools.list_ports from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c6 # usb_serial_jtag is very similar, test C6 is enough. @pytest.mark.usj_device +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_usb_device_serial_echo_example(dut: Dut) -> None: dut.expect_exact('USB_SERIAL_JTAG init done') sleep(2) ports = list(serial.tools.list_ports.comports()) for p in ports: - if (p.device == '/dev/ttyACM0'): # Get the usb_serial_jtag port + if p.device == '/dev/ttyACM0': # Get the usb_serial_jtag port with serial.Serial(p.device) as s: s.write(b'hi, espressif\n') sleep(1) diff --git a/examples/protocols/esp_http_client/pytest_esp_http_client.py b/examples/protocols/esp_http_client/pytest_esp_http_client.py index 32157657fb..1e1d485bf9 100644 --- a/examples/protocols/esp_http_client/pytest_esp_http_client.py +++ b/examples/protocols/esp_http_client/pytest_esp_http_client.py @@ -1,14 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.httpbin +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_esp_http_client(dut: Dut) -> None: """ steps: | @@ -55,11 +56,15 @@ def test_examples_protocol_esp_http_client(dut: Dut) -> None: dut.expect('Finish http example') -@pytest.mark.esp32 @pytest.mark.httpbin -@pytest.mark.parametrize('config', [ - 'ssldyn', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'ssldyn', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_esp_http_client_dynamic_buffer(dut: Dut) -> None: # test mbedtls dynamic resource # check and log bin size @@ -101,13 +106,18 @@ def test_examples_protocol_esp_http_client_dynamic_buffer(dut: Dut) -> None: dut.expect('Finish http example') -@pytest.mark.linux @pytest.mark.host_test # Currently we are just testing the build for esp_http_client on Linux target. So skipping the test run. # Later we will enable the test run for Linux target as well. @pytest.mark.skipif('config.getvalue("target") == "linux"', reason='Do not run on Linux') -@pytest.mark.parametrize('config', [ - 'default', 'ssldyn', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'ssldyn', + ], + indirect=True, +) +@idf_parametrize('target', ['linux'], indirect=['target']) def test_examples_protocol_esp_http_client_linux(dut: Dut) -> None: dut.expect('Finish http example', timeout=60) diff --git a/examples/protocols/esp_local_ctrl/pytest_esp_local_ctrl.py b/examples/protocols/esp_local_ctrl/pytest_esp_local_ctrl.py index bfd59b66cb..11aadf31a3 100644 --- a/examples/protocols/esp_local_ctrl/pytest_esp_local_ctrl.py +++ b/examples/protocols/esp_local_ctrl/pytest_esp_local_ctrl.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os @@ -9,6 +9,7 @@ import pexpect import pytest from common_test_methods import get_env_config_variable from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def get_sdk_path() -> str: @@ -19,27 +20,24 @@ def get_sdk_path() -> str: class CustomProcess(object): - def __init__(self, cmd: str, logfile: str, verbose:bool =True) -> None: + def __init__(self, cmd: str, logfile: str, verbose: bool = True) -> None: self.verbose = verbose self.f = open(logfile, 'w', encoding='utf-8') if self.verbose: logging.info('Starting {} > {}'.format(cmd, self.f.name)) self.pexpect_proc = pexpect.spawn(cmd, timeout=60, logfile=self.f, encoding='utf-8', codec_errors='ignore') - def __enter__(self): # type: ignore + def __enter__(self): # type: ignore return self def close(self) -> None: self.pexpect_proc.terminate(force=True) - def __exit__(self, type, value, traceback): # type: ignore + def __exit__(self, type, value, traceback): # type: ignore self.close() self.f.close() -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_router @pytest.mark.parametrize( 'config', @@ -49,8 +47,8 @@ class CustomProcess(object): ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_esp_local_ctrl(config: str, dut: Dut) -> None: - rel_project_path = os.path.join('examples', 'protocols', 'esp_local_ctrl') idf_path = get_sdk_path() @@ -75,20 +73,28 @@ def test_examples_esp_local_ctrl(config: str, dut: Dut) -> None: # Running mDNS services in docker is not a trivial task. Therefore, the script won't connect to the host name but # to IP address. However, the certificates were generated for the host name and will be rejected. if config == 'default': - cmd = ' '.join([sys.executable, os.path.join(idf_path, rel_project_path, 'scripts/esp_local_ctrl.py'), - '--sec_ver 2', - '--sec2_username wifiprov', - '--sec2_pwd abcd1234', - '--name', dut_ip, - '--dont-check-hostname']) # don't reject the certificate because of the hostname + cmd = ' '.join([ + sys.executable, + os.path.join(idf_path, rel_project_path, 'scripts/esp_local_ctrl.py'), + '--sec_ver 2', + '--sec2_username wifiprov', + '--sec2_pwd abcd1234', + '--name', + dut_ip, + '--dont-check-hostname', + ]) # don't reject the certificate because of the hostname elif config == 'http': - cmd = ' '.join([sys.executable, os.path.join(idf_path, rel_project_path, 'scripts/esp_local_ctrl.py'), - '--sec_ver 2', - '--transport http', - '--sec2_username wifiprov', - '--sec2_pwd abcd1234', - '--name', dut_ip, - '--dont-check-hostname']) + cmd = ' '.join([ + sys.executable, + os.path.join(idf_path, rel_project_path, 'scripts/esp_local_ctrl.py'), + '--sec_ver 2', + '--transport http', + '--sec2_username wifiprov', + '--sec2_pwd abcd1234', + '--name', + dut_ip, + '--dont-check-hostname', + ]) esp_local_ctrl_log = os.path.join(idf_path, rel_project_path, 'esp_local_ctrl.log') with CustomProcess(cmd, esp_local_ctrl_log) as ctrl_py: @@ -100,7 +106,7 @@ def test_examples_esp_local_ctrl(config: str, dut: Dut) -> None: ctrl_py.pexpect_proc.expect(re.compile(r'\[ 2\] property1\s+INT32\s+{}'.format(prop1))) ctrl_py.pexpect_proc.expect(re.compile(r'\[ 3\] property2\s+BOOLEAN\s+Read-Only\s+(True)|(False)')) ctrl_py.pexpect_proc.expect(re.compile(r'\[ 4\] property3\s+STRING\s+{}'.format(prop3))) - ctrl_py.pexpect_proc.expect_exact('Select properties to set (0 to re-read, \'q\' to quit) :') + ctrl_py.pexpect_proc.expect_exact("Select properties to set (0 to re-read, 'q' to quit) :") property1 = 123456789 property3 = '' diff --git a/examples/protocols/http_request/pytest_http_request.py b/examples/protocols/http_request/pytest_http_request.py index b9bf0d5cf8..1aa0c8a09f 100644 --- a/examples/protocols/http_request/pytest_http_request.py +++ b/examples/protocols/http_request/pytest_http_request.py @@ -1,23 +1,23 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import logging import os import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_http_request(dut: Dut) -> None: """ steps: | 1. join AP/Ethernet 2. connect to example.com - 3. check conneciton success + 3. check connection success """ # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'http_request.bin') diff --git a/examples/protocols/http_server/advanced_tests/pytest_http_server_advanced.py b/examples/protocols/http_server/advanced_tests/pytest_http_server_advanced.py index 79f031fe4f..bb1315aa56 100644 --- a/examples/protocols/http_server/advanced_tests/pytest_http_server_advanced.py +++ b/examples/protocols/http_server/advanced_tests/pytest_http_server_advanced.py @@ -1,15 +1,13 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - -from __future__ import division, print_function, unicode_literals - import logging import os import sys import pytest +from pytest_embedded_idf.utils import idf_parametrize try: from idf_http_server_test import test as client @@ -32,12 +30,9 @@ from pytest_embedded import Dut # features to this component. -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_router +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_protocol_http_server_advanced(dut: Dut) -> None: - # Get binary file binary_file = os.path.join(dut.app.binary_path, 'tests.bin') bin_size = os.path.getsize(binary_file) @@ -57,9 +52,12 @@ def test_examples_protocol_http_server_advanced(dut: Dut) -> None: got_port = dut.expect(r"(?:[\s\S]*)Started HTTP server on port: '(\d+)'", timeout=30)[1].decode() - result = dut.expect(r"(?:[\s\S]*)Max URI handlers: '(\d+)'(?:[\s\S]*)Max Open Sessions: " # noqa: W605 - r"'(\d+)'(?:[\s\S]*)Max Header Length: '(\d+)'(?:[\s\S]*)Max URI Length: " - r"'(\d+)'(?:[\s\S]*)Max Stack Size: '(\d+)'", timeout=15) + result = dut.expect( + r"(?:[\s\S]*)Max URI handlers: '(\d+)'(?:[\s\S]*)Max Open Sessions: " # noqa: W605 + r"'(\d+)'(?:[\s\S]*)Max Header Length: '(\d+)'(?:[\s\S]*)Max URI Length: " + r"'(\d+)'(?:[\s\S]*)Max Stack Size: '(\d+)'", + timeout=15, + ) # max_uri_handlers = int(result[1]) max_sessions = int(result[2]) max_hdr_len = int(result[3]) diff --git a/examples/protocols/http_server/captive_portal/pytest_captive_portal.py b/examples/protocols/http_server/captive_portal/pytest_captive_portal.py index d08b20df06..326792520d 100644 --- a/examples/protocols/http_server/captive_portal/pytest_captive_portal.py +++ b/examples/protocols/http_server/captive_portal/pytest_captive_portal.py @@ -1,10 +1,7 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - -from __future__ import print_function - import http.client import logging import os @@ -14,6 +11,7 @@ import sys import pexpect import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize try: import wifi_tools @@ -68,12 +66,11 @@ def test_captive_page(ip: str, port: str, uri: str) -> bool: return True -@pytest.mark.esp32 @pytest.mark.wifi_wlan @pytest.mark.temp_skip_ci(targets=['esp32'], reason='unstable case') @pytest.mark.xfail(reason='Runner unable to connect to target over WiFi', run=False) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_example_captive_portal(dut: Dut) -> None: - # Get binary file binary_file = os.path.join(dut.app.binary_path, 'captive_portal.bin') bin_size = os.path.getsize(binary_file) @@ -103,7 +100,9 @@ def test_example_captive_portal(dut: Dut) -> None: except RuntimeError as err: logging.info('error: {}'.format(err)) try: - got_ip = dut.expect(r'DHCP server assigned IP to a station, IP is: (\d+.\d+.\d+.\d+)', timeout=60)[1].decode() + got_ip = dut.expect(r'DHCP server assigned IP to a station, IP is: (\d+.\d+.\d+.\d+)', timeout=60)[ + 1 + ].decode() logging.info('got_ip: {}'.format(got_ip)) if ip != got_ip: raise RuntimeError('SoftAP connected to another host! {} != {}'.format(ip, got_ip)) diff --git a/examples/protocols/http_server/file_serving/pytest_http_server_file_serving.py b/examples/protocols/http_server/file_serving/pytest_http_server_file_serving.py index ff0c0e8ef5..33cd47d6ed 100644 --- a/examples/protocols/http_server/file_serving/pytest_http_server_file_serving.py +++ b/examples/protocols/http_server/file_serving/pytest_http_server_file_serving.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import hashlib import http.client @@ -9,6 +9,7 @@ import os import sys import pytest +from pytest_embedded_idf.utils import idf_parametrize try: from idf_http_server_test import adder as client @@ -20,13 +21,16 @@ from common_test_methods import get_env_config_variable from pytest_embedded import Dut -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_router -@pytest.mark.parametrize('config', ['spiffs',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'spiffs', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_protocol_http_server_file_serving(dut: Dut) -> None: - # Get binary file binary_file = os.path.join(dut.app.binary_path, 'file_server.bin') bin_size = os.path.getsize(binary_file) @@ -73,7 +77,7 @@ def test_examples_protocol_http_server_file_serving(dut: Dut) -> None: logging.info('Passed the test to uploaded file on the file server') # Download the uploaded file from the file server - logging.info("\nTesting for Download of \"existing\" file from the file server") + logging.info('\nTesting for Download of "existing" file from the file server') download_data = client.getreq(conn, '/' + str(upload_file_name)) @@ -91,7 +95,7 @@ def test_examples_protocol_http_server_file_serving(dut: Dut) -> None: raise RuntimeError('The md5 hash of the downloaded file does not match with that of the uploaded file') # Upload existing file on the file server - logging.info("\nTesting the upload of \"already existing\" file on the file server") + logging.info('\nTesting the upload of "already existing" file on the file server') client.postreq(conn, '/upload/' + str(upload_file_name), data=None) try: dut.expect('File already exists : /data/' + str(upload_file_name), timeout=10) @@ -112,7 +116,7 @@ def test_examples_protocol_http_server_file_serving(dut: Dut) -> None: conn = client.start_session(got_ip, got_port) # Delete the existing file from the file server - logging.info("\nTesting the deletion of \"existing\" file on the file server") + logging.info('\nTesting the deletion of "existing" file on the file server') client.postreq(conn, '/delete/' + str(upload_file_name), data=None) try: dut.expect('Deleting file : /' + str(upload_file_name), timeout=10) @@ -123,7 +127,7 @@ def test_examples_protocol_http_server_file_serving(dut: Dut) -> None: conn = client.start_session(got_ip, got_port) # Try to delete non existing file from the file server - logging.info("\nTesting the deletion of \"non existing\" file on the file server") + logging.info('\nTesting the deletion of "non existing" file on the file server') client.postreq(conn, '/delete/' + str(upload_file_name), data=None) try: dut.expect('File does not exist : /' + str(upload_file_name), timeout=10) @@ -134,7 +138,7 @@ def test_examples_protocol_http_server_file_serving(dut: Dut) -> None: conn = client.start_session(got_ip, got_port) # Try to download non existing file from the file server - logging.info("\nTesting for Download of \"non existing\" file from the file server") + logging.info('\nTesting for Download of "non existing" file from the file server') download_data = client.getreq(conn, '/' + str(upload_file_name)) diff --git a/examples/protocols/http_server/persistent_sockets/pytest_http_server_persistence.py b/examples/protocols/http_server/persistent_sockets/pytest_http_server_persistence.py index 9d19d77f20..e03222c880 100644 --- a/examples/protocols/http_server/persistent_sockets/pytest_http_server_persistence.py +++ b/examples/protocols/http_server/persistent_sockets/pytest_http_server_persistence.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import logging import os @@ -8,6 +8,7 @@ import random import sys import pytest +from pytest_embedded_idf.utils import idf_parametrize try: from idf_http_server_test import adder as client @@ -23,19 +24,16 @@ from pytest_embedded import Dut # > make print_flash_cmd | tail -n 1 > build/download.config -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_router +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_protocol_http_server_persistence(dut: Dut) -> None: - # Get binary file binary_file = os.path.join(dut.app.binary_path, 'persistent_sockets.bin') bin_size = os.path.getsize(binary_file) logging.info('http_server_bin_size : {}KB'.format(bin_size // 1024)) # Upload binary and start testing - logging.info('Starting http_server persistance test app') + logging.info('Starting http_server persistence test app') # Parse IP address of STA logging.info('Waiting to connect with AP') @@ -70,7 +68,7 @@ def test_examples_protocol_http_server_persistence(dut: Dut) -> None: dut.expect('Logging out', timeout=30) # Test PUT request and initialize session context - num = random.randint(0,100) + num = random.randint(0, 100) client.putreq(conn, '/adder', str(num)) visitor += 1 dut.expect('/adder visitor count = ' + str(visitor), timeout=30) @@ -78,7 +76,7 @@ def test_examples_protocol_http_server_persistence(dut: Dut) -> None: dut.expect('PUT allocating new session', timeout=30) # Retest PUT request and change session context value - num = random.randint(0,100) + num = random.randint(0, 100) logging.info('Adding: {}'.format(num)) client.putreq(conn, '/adder', str(num)) visitor += 1 @@ -95,7 +93,7 @@ def test_examples_protocol_http_server_persistence(dut: Dut) -> None: pass # Test POST request and session persistence - random_nums = [random.randint(0,100) for _ in range(100)] + random_nums = [random.randint(0, 100) for _ in range(100)] for num in random_nums: logging.info('Adding: {}'.format(num)) client.postreq(conn, '/adder', str(num)) @@ -120,7 +118,7 @@ def test_examples_protocol_http_server_persistence(dut: Dut) -> None: logging.info('Validating user context data') # Start another session to check user context data client.start_session(got_ip, got_port) - num = random.randint(0,100) + num = random.randint(0, 100) client.putreq(conn, '/adder', str(num)) visitor += 1 dut.expect('/adder visitor count = ' + str(visitor), timeout=30) diff --git a/examples/protocols/http_server/simple/pytest_http_server_simple.py b/examples/protocols/http_server/simple/pytest_http_server_simple.py index 0827bdb60e..5daabd9fe9 100644 --- a/examples/protocols/http_server/simple/pytest_http_server_simple.py +++ b/examples/protocols/http_server/simple/pytest_http_server_simple.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import logging import os @@ -12,6 +12,7 @@ import threading import time import pytest +from pytest_embedded_idf.utils import idf_parametrize try: from idf_http_server_test import client @@ -44,7 +45,7 @@ class http_client_thread(threading.Thread): except socket.timeout: self.exc = 1 - def join(self, timeout=None): # type: ignore + def join(self, timeout=None): # type: ignore threading.Thread.join(self) if self.exc: raise socket.timeout @@ -55,12 +56,9 @@ class http_client_thread(threading.Thread): # > make print_flash_cmd | tail -n 1 > build/download.config -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_router +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_protocol_http_server_simple(dut: Dut) -> None: - # Get binary file binary_file = os.path.join(dut.app.binary_path, 'simple.bin') bin_size = os.path.getsize(binary_file) @@ -110,7 +108,7 @@ def test_examples_protocol_http_server_simple(dut: Dut) -> None: dut.expect('Registering /hello and /echo URIs', timeout=30) # Generate random data of 10KB - random_data = ''.join(string.printable[random.randint(0,len(string.printable)) - 1] for _ in range(10 * 1024)) + random_data = ''.join(string.printable[random.randint(0, len(string.printable)) - 1] for _ in range(10 * 1024)) logging.info('Test /echo POST handler with random data') if not client.test_post_handler(got_ip, got_port, random_data): raise RuntimeError @@ -120,7 +118,9 @@ def test_examples_protocol_http_server_simple(dut: Dut) -> None: if not client.test_custom_uri_query(got_ip, got_port, queries): raise RuntimeError - dut.expect_exact('Found URL query => query1=http%3A%2F%2Ffoobar&query3=abcd%2B1234%20xyz&query2=Esp%21%40%20%23%2471', timeout=30) + dut.expect_exact( + 'Found URL query => query1=http%3A%2F%2Ffoobar&query3=abcd%2B1234%20xyz&query2=Esp%21%40%20%23%2471', timeout=30 + ) dut.expect_exact('Found URL query parameter => query1=http%3A%2F%2Ffoobar', timeout=30) dut.expect_exact('Decoded query parameter => http://foobar', timeout=30) dut.expect_exact('Found URL query parameter => query3=abcd%2B1234%20xyz', timeout=30) @@ -129,12 +129,9 @@ def test_examples_protocol_http_server_simple(dut: Dut) -> None: dut.expect_exact('Decoded query parameter => Esp!@ #$71', timeout=30) -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_router +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_protocol_http_server_lru_purge_enable(dut: Dut) -> None: - # Get binary file binary_file = os.path.join(dut.app.binary_path, 'simple.bin') bin_size = os.path.getsize(binary_file) diff --git a/examples/protocols/http_server/ws_echo_server/pytest_ws_server_example.py b/examples/protocols/http_server/ws_echo_server/pytest_ws_server_example.py index 7c6d0ade8c..f5d35f1926 100644 --- a/examples/protocols/http_server/ws_echo_server/pytest_ws_server_example.py +++ b/examples/protocols/http_server/ws_echo_server/pytest_ws_server_example.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import logging import os @@ -8,6 +8,7 @@ import os import pytest from common_test_methods import get_env_config_variable from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize try: import websocket @@ -18,7 +19,7 @@ except ImportError: OPCODE_TEXT = 0x1 OPCODE_BIN = 0x2 OPCODE_PING = 0x9 -OPCODE_PONG = 0xa +OPCODE_PONG = 0xA class WsClient: @@ -32,13 +33,13 @@ class WsClient: self.ws.connect('ws://{}:{}/{}'.format(self.ip, self.port, self.uri)) return self - def __exit__(self, exc_type, exc_value, traceback): # type: ignore + def __exit__(self, exc_type, exc_value, traceback): # type: ignore self.ws.close() - def read(self): # type: ignore + def read(self): # type: ignore return self.ws.recv_data(control_frame=True) - def write(self, data='', opcode=OPCODE_TEXT): # type: ignore + def write(self, data='', opcode=OPCODE_TEXT): # type: ignore if opcode == OPCODE_BIN: return self.ws.send_binary(data.encode()) if opcode == OPCODE_PING: @@ -46,8 +47,8 @@ class WsClient: return self.ws.send(data) -@pytest.mark.esp32 @pytest.mark.wifi_router +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_http_ws_echo_server(dut: Dut) -> None: # Get binary file binary_file = os.path.join(dut.app.binary_path, 'ws_echo_server.bin') @@ -96,8 +97,8 @@ def test_examples_protocol_http_ws_echo_server(dut: Dut) -> None: raise RuntimeError('Failed to receive correct opcode:{} or data:{}'.format(opcode, data)) -@pytest.mark.esp32 @pytest.mark.wifi_router +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_ws_auth_handshake(dut: Dut) -> None: """ Test that connecting to /ws does NOT print the handshake success log. diff --git a/examples/protocols/https_mbedtls/pytest_https_mbedtls.py b/examples/protocols/https_mbedtls/pytest_https_mbedtls.py index 8fd2e2a313..4cccbcbf34 100644 --- a/examples/protocols/https_mbedtls/pytest_https_mbedtls.py +++ b/examples/protocols/https_mbedtls/pytest_https_mbedtls.py @@ -1,17 +1,17 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import logging import os import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_https_mbedtls(dut: Dut) -> None: """ steps: | diff --git a/examples/protocols/https_request/pytest_https_request.py b/examples/protocols/https_request/pytest_https_request.py index 340945937e..fcc76cf885 100644 --- a/examples/protocols/https_request/pytest_https_request.py +++ b/examples/protocols/https_request/pytest_https_request.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import http.server import logging @@ -12,13 +12,15 @@ import pexpect import pytest from common_test_methods import get_host_ip4_by_dest_ip from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize from RangeHTTPServer import RangeRequestHandler -def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]: +def https_request_handler() -> Callable[..., http.server.BaseHTTPRequestHandler]: """ Returns a request handler class that handles broken pipe exception """ + class RequestHandler(RangeRequestHandler): protocol_version = 'HTTP/1.1' @@ -46,7 +48,6 @@ def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]: def start_https_server(server_file: str, key_file: str, server_ip: str, server_port: int) -> None: - requestHandler = https_request_handler() httpd = http.server.HTTPServer((server_ip, server_port), requestHandler) @@ -57,12 +58,18 @@ def start_https_server(server_file: str, key_file: str, server_ip: str, server_p httpd.serve_forever() -@pytest.mark.esp32 @pytest.mark.ethernet -@pytest.mark.parametrize('config', ['cli_ses_tkt',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'cli_ses_tkt', + ], + indirect=True, +) @pytest.mark.parametrize('erase_nvs', ['y'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_https_request_cli_session_tickets(dut: Dut) -> None: - logging.info("Testing for \"esp_tls client session tickets\"") + logging.info('Testing for "esp_tls client session tickets"') # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'https_request.bin') @@ -89,38 +96,44 @@ def test_examples_protocol_https_request_cli_session_tickets(dut: Dut) -> None: dut.expect('Start https_request example', timeout=30) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port))) dut.write('https://' + host_ip + ':' + str(server_port)) - logging.info("Testing for \"https_request using saved session\"") + logging.info('Testing for "https_request using saved session"') # Check for connection using already saved client session try: dut.expect('https_request to local server', timeout=30) - dut.expect(['Connection established...', - 'Reading HTTP response...', - 'HTTP/1.1 200 OK', - 'connection closed'], expect_all=True) + dut.expect( + ['Connection established...', 'Reading HTTP response...', 'HTTP/1.1 200 OK', 'connection closed'], + expect_all=True, + ) except Exception: - logging.info("Failed to connect to local https server\"") + logging.info('Failed to connect to local https server"') raise try: dut.expect('https_request using saved client session', timeout=20) - dut.expect(['Connection established...', - 'Reading HTTP response...', - 'HTTP/1.1 200 OK', - 'connection closed'], expect_all=True) + dut.expect( + ['Connection established...', 'Reading HTTP response...', 'HTTP/1.1 200 OK', 'connection closed'], + expect_all=True, + ) except Exception: - logging.info("Failed the test for \"https_request using saved client session\"") + logging.info('Failed the test for "https_request using saved client session"') raise - logging.info("Passed the test for \"https_request using saved client session\"") + logging.info('Passed the test for "https_request using saved client session"') finally: thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet -@pytest.mark.parametrize('config', ['ssldyn',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'ssldyn', + ], + indirect=True, +) @pytest.mark.parametrize('erase_nvs', ['y'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_https_request_dynamic_buffers(dut: Dut) -> None: # Check for connection using crt bundle with mbedtls dynamic resource enabled # check and log bin size @@ -136,24 +149,23 @@ def test_examples_protocol_https_request_dynamic_buffers(dut: Dut) -> None: raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet') # only check if one connection is established - logging.info("Testing for \"https_request using crt bundle\" with mbedtls dynamic resource enabled") + logging.info('Testing for "https_request using crt bundle" with mbedtls dynamic resource enabled') try: dut.expect('https_request using crt bundle', timeout=30) - dut.expect(['Connection established...', - 'Reading HTTP response...', - 'HTTP/1.1 200 OK', - 'connection closed'], expect_all=True) + dut.expect( + ['Connection established...', 'Reading HTTP response...', 'HTTP/1.1 200 OK', 'connection closed'], + expect_all=True, + ) except Exception: - logging.info("Failed the test for \"https_request using crt bundle\" when mbedtls dynamic resource was enabled") + logging.info('Failed the test for "https_request using crt bundle" when mbedtls dynamic resource was enabled') raise - logging.info("Passed the test for \"https_request using crt bundle\" when mbedtls dynamic resource was enabled") + logging.info('Passed the test for "https_request using crt bundle" when mbedtls dynamic resource was enabled') -@pytest.mark.esp32 @pytest.mark.ethernet @pytest.mark.parametrize('erase_nvs', ['y'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_https_request(dut: Dut) -> None: - """ steps: | 1. join AP @@ -175,64 +187,69 @@ def test_examples_protocol_https_request(dut: Dut) -> None: raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet') # Check for connection using crt bundle - logging.info("Testing for \"https_request using crt bundle\"") + logging.info('Testing for "https_request using crt bundle"') try: dut.expect('https_request using crt bundle', timeout=30) - dut.expect(['Certificate validated', - 'Connection established...', - 'Reading HTTP response...', - 'HTTP/1.1 200 OK', - 'connection closed'], expect_all=True) + dut.expect( + [ + 'Certificate validated', + 'Connection established...', + 'Reading HTTP response...', + 'HTTP/1.1 200 OK', + 'connection closed', + ], + expect_all=True, + ) except Exception: - logging.info("Failed the test for \"https_request using crt bundle\"") + logging.info('Failed the test for "https_request using crt bundle"') raise - logging.info("Passed the test for \"https_request using crt bundle\"") + logging.info('Passed the test for "https_request using crt bundle"') # Check for connection using cacert_buf - logging.info("Testing for \"https_request using cacert_buf\"") + logging.info('Testing for "https_request using cacert_buf"') try: dut.expect('https_request using cacert_buf', timeout=20) - dut.expect(['Connection established...', - 'Reading HTTP response...', - 'HTTP/1.1 200 OK', - 'connection closed'], expect_all=True) + dut.expect( + ['Connection established...', 'Reading HTTP response...', 'HTTP/1.1 200 OK', 'connection closed'], + expect_all=True, + ) except Exception: - logging.info("Passed the test for \"https_request using cacert_buf\"") + logging.info('Passed the test for "https_request using cacert_buf"') raise - logging.info("Passed the test for \"https_request using cacert_buf\"") + logging.info('Passed the test for "https_request using cacert_buf"') # Check for connection using global ca_store - logging.info("Testing for \"https_request using global ca_store\"") + logging.info('Testing for "https_request using global ca_store"') try: dut.expect('https_request using global ca_store', timeout=20) - dut.expect(['Connection established...', - 'Reading HTTP response...', - 'HTTP/1.1 200 OK', - 'connection closed'], expect_all=True) + dut.expect( + ['Connection established...', 'Reading HTTP response...', 'HTTP/1.1 200 OK', 'connection closed'], + expect_all=True, + ) except Exception: - logging.info("Failed the test for \"https_request using global ca_store\"") + logging.info('Failed the test for "https_request using global ca_store"') raise - logging.info("Passed the test for \"https_request using global ca_store\"") + logging.info('Passed the test for "https_request using global ca_store"') # Check for connection using specified server supported ciphersuites - logging.info("Testing for \"https_request using server supported ciphersuites\"") + logging.info('Testing for "https_request using server supported ciphersuites"') try: dut.expect('https_request using server supported ciphersuites', timeout=20) - dut.expect(['Connection established...', - 'Reading HTTP response...', - 'HTTP/1.1 200 OK', - 'connection closed'], expect_all=True) + dut.expect( + ['Connection established...', 'Reading HTTP response...', 'HTTP/1.1 200 OK', 'connection closed'], + expect_all=True, + ) except Exception: - logging.info("Failed the test for \"https_request using server supported ciphersuites\"") + logging.info('Failed the test for "https_request using server supported ciphersuites"') raise - logging.info("Passed the test for \"https_request using server supported ciphersuites\"") + logging.info('Passed the test for "https_request using server supported ciphersuites"') # Check for connection using specified server unsupported ciphersuites - logging.info("Testing for \"https_request using server unsupported ciphersuites\"") + logging.info('Testing for "https_request using server unsupported ciphersuites"') try: dut.expect('https_request using server unsupported ciphersuites', timeout=20) dut.expect('Connection failed...', timeout=30) except Exception: - logging.info("Failed the test for \"https_request using server unsupported ciphersuites\"") + logging.info('Failed the test for "https_request using server unsupported ciphersuites"') raise - logging.info("Passed the test for \"https_request using server unsupported ciphersuites\"") + logging.info('Passed the test for "https_request using server unsupported ciphersuites"') diff --git a/examples/protocols/https_server/simple/pytest_https_server_simple.py b/examples/protocols/https_server/simple/pytest_https_server_simple.py index 2c97cbc9b5..43245583ed 100644 --- a/examples/protocols/https_server/simple/pytest_https_server_simple.py +++ b/examples/protocols/https_server/simple/pytest_https_server_simple.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import http.client import logging @@ -10,6 +10,7 @@ import ssl import pytest from common_test_methods import get_env_config_variable from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize server_cert_pem = ( '-----BEGIN CERTIFICATE-----\n' @@ -34,68 +35,70 @@ server_cert_pem = ( '-----END CERTIFICATE-----\n' ) -client_cert_pem = '-----BEGIN CERTIFICATE-----\n' \ - 'MIID7TCCAtWgAwIBAgIUBdm7RStsshnl3CCpknSJhXQK4GcwDQYJKoZIhvcNAQEL\n' \ - 'BQAwgYUxCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdKaWFuZ3N1MQ8wDQYDVQQHDAZT\n' \ - 'dXpob3UxEjAQBgNVBAoMCUVzcHJlc3NpZjEMMAoGA1UECwwDY29tMRIwEAYDVQQD\n' \ - 'DAkxMjcuMC4wLjExHTAbBgkqhkiG9w0BCQEWDmVzcDMyeEBlc3AuY29tMB4XDTIx\n' \ - 'MTAwNTExMTMxMFoXDTMxMTAwMzExMTMxMFowgYUxCzAJBgNVBAYTAkNOMRAwDgYD\n' \ - 'VQQIDAdKaWFuZ3N1MQ8wDQYDVQQHDAZTdXpob3UxEjAQBgNVBAoMCUVzcHJlc3Np\n' \ - 'ZjEMMAoGA1UECwwDY29tMRIwEAYDVQQDDAkxMjcuMC4wLjExHTAbBgkqhkiG9w0B\n' \ - 'CQEWDmVzcDMyeEBlc3AuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\n' \ - 'AQEAu2nP0HPtgKvRUwFuOs72caf4oyeK33OVfa6fGGttr/QYyw9PrwtdFDyEWEiI\n' \ - '4P4hnxNC+bvNSYtJUzF9EmkqrUtKxhBsRVTKWOqumcgtiMWOxpdVKl0936ne2Pqh\n' \ - 'SweddrQwvPDFuB3hRikRX11+d5vkjFBV9FoZobKHWemDkXSc2R99xRie5PJoEfoz\n' \ - 'rmu5zjCaPHxzkyZsmH4MILfTuhUGc/Eye9Nl+lpY5KLjM14ZMQLK1CHRuI/oqCN6\n' \ - '1WQrgUY5EyXGe0jXHTVhlL2RN8njxJ/4r3JnK/BQkcXTIMPOP8jIv9Sy1HhxfXKy\n' \ - 'HzLqOBn0Ft+mOADrpAWX8WnwUQIDAQABo1MwUTAdBgNVHQ4EFgQUpu4d8d+IywjB\n' \ - 'HMiKX84L+1ri8BIwHwYDVR0jBBgwFoAUpu4d8d+IywjBHMiKX84L+1ri8BIwDwYD\n' \ - 'VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAXm5Hn/aKKO3RnHqqfxok\n' \ - 'Hbw5yA2L2T6VPj2puI0Sh5GW62INjM0Kszy3L5mQqLUSsjcEcFAZmpeo14ytPRLG\n' \ - 'o6+WG/4er3hBA7D8oDni7hp8Qs+/EtNuEuoU+qQiKsT2DvA5rafT7laNfvjgqaoJ\n' \ - 'YMTCvzKLnMBaglB+qC9grgvJwMN0RTzHyY6UySdNZmcf5QXWLWjsX8E8/u4iSq8l\n' \ - 'eZlddTjh7HGGEOim7AkvKR9VYAvKGOV+FvUzCxPpoTr6kS2NGwnR7QnvKADECtLj\n' \ - 'gf+hW1FalMn0yTVspg4+BNbIThh0thbsvPDUTekMNfaRKKHZpJP2Ty3LkCbANLBR\n' \ - 'tQ==\n' \ - '-----END CERTIFICATE-----\n' +client_cert_pem = ( + '-----BEGIN CERTIFICATE-----\n' + 'MIID7TCCAtWgAwIBAgIUBdm7RStsshnl3CCpknSJhXQK4GcwDQYJKoZIhvcNAQEL\n' + 'BQAwgYUxCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdKaWFuZ3N1MQ8wDQYDVQQHDAZT\n' + 'dXpob3UxEjAQBgNVBAoMCUVzcHJlc3NpZjEMMAoGA1UECwwDY29tMRIwEAYDVQQD\n' + 'DAkxMjcuMC4wLjExHTAbBgkqhkiG9w0BCQEWDmVzcDMyeEBlc3AuY29tMB4XDTIx\n' + 'MTAwNTExMTMxMFoXDTMxMTAwMzExMTMxMFowgYUxCzAJBgNVBAYTAkNOMRAwDgYD\n' + 'VQQIDAdKaWFuZ3N1MQ8wDQYDVQQHDAZTdXpob3UxEjAQBgNVBAoMCUVzcHJlc3Np\n' + 'ZjEMMAoGA1UECwwDY29tMRIwEAYDVQQDDAkxMjcuMC4wLjExHTAbBgkqhkiG9w0B\n' + 'CQEWDmVzcDMyeEBlc3AuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\n' + 'AQEAu2nP0HPtgKvRUwFuOs72caf4oyeK33OVfa6fGGttr/QYyw9PrwtdFDyEWEiI\n' + '4P4hnxNC+bvNSYtJUzF9EmkqrUtKxhBsRVTKWOqumcgtiMWOxpdVKl0936ne2Pqh\n' + 'SweddrQwvPDFuB3hRikRX11+d5vkjFBV9FoZobKHWemDkXSc2R99xRie5PJoEfoz\n' + 'rmu5zjCaPHxzkyZsmH4MILfTuhUGc/Eye9Nl+lpY5KLjM14ZMQLK1CHRuI/oqCN6\n' + '1WQrgUY5EyXGe0jXHTVhlL2RN8njxJ/4r3JnK/BQkcXTIMPOP8jIv9Sy1HhxfXKy\n' + 'HzLqOBn0Ft+mOADrpAWX8WnwUQIDAQABo1MwUTAdBgNVHQ4EFgQUpu4d8d+IywjB\n' + 'HMiKX84L+1ri8BIwHwYDVR0jBBgwFoAUpu4d8d+IywjBHMiKX84L+1ri8BIwDwYD\n' + 'VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAXm5Hn/aKKO3RnHqqfxok\n' + 'Hbw5yA2L2T6VPj2puI0Sh5GW62INjM0Kszy3L5mQqLUSsjcEcFAZmpeo14ytPRLG\n' + 'o6+WG/4er3hBA7D8oDni7hp8Qs+/EtNuEuoU+qQiKsT2DvA5rafT7laNfvjgqaoJ\n' + 'YMTCvzKLnMBaglB+qC9grgvJwMN0RTzHyY6UySdNZmcf5QXWLWjsX8E8/u4iSq8l\n' + 'eZlddTjh7HGGEOim7AkvKR9VYAvKGOV+FvUzCxPpoTr6kS2NGwnR7QnvKADECtLj\n' + 'gf+hW1FalMn0yTVspg4+BNbIThh0thbsvPDUTekMNfaRKKHZpJP2Ty3LkCbANLBR\n' + 'tQ==\n' + '-----END CERTIFICATE-----\n' +) -client_key_pem = '-----BEGIN PRIVATE KEY-----\n' \ - 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC7ac/Qc+2Aq9FT\n' \ - 'AW46zvZxp/ijJ4rfc5V9rp8Ya22v9BjLD0+vC10UPIRYSIjg/iGfE0L5u81Ji0lT\n' \ - 'MX0SaSqtS0rGEGxFVMpY6q6ZyC2IxY7Gl1UqXT3fqd7Y+qFLB512tDC88MW4HeFG\n' \ - 'KRFfXX53m+SMUFX0WhmhsodZ6YORdJzZH33FGJ7k8mgR+jOua7nOMJo8fHOTJmyY\n' \ - 'fgwgt9O6FQZz8TJ702X6WljkouMzXhkxAsrUIdG4j+ioI3rVZCuBRjkTJcZ7SNcd\n' \ - 'NWGUvZE3yePEn/ivcmcr8FCRxdMgw84/yMi/1LLUeHF9crIfMuo4GfQW36Y4AOuk\n' \ - 'BZfxafBRAgMBAAECggEBAJuJZ1UCwRtGfUS8LTVVSiZtVuZhDNoB3REfeR4VGkUq\n' \ - '+eCcZm9JqQgAaX2zRRYlEtYocC8+c1MT69jFe51p9mc302ipfJHVmtFMg3dRMKkP\n' \ - '/DxIn/+2voD/Q9kjt/TC7yXyyXglApKZCbrmnmpc93ZgxL7GdW+Dzz3pIne2WuC9\n' \ - 'T6ie71R8X60sau6ApMgkUq6On0f21v/VLkNU67tQJGBF6Q1HE8PK7Ptun3WSBVNm\n' \ - 'FNNJKRBwiqfWXe9hPlqqCWayYBrojSqJJXn5Xd6n5XzLDPzAXuPlkPF3VwWeXGam\n' \ - '3RBZA26gwv50E1PeiUQOipkR57J+O9j/oA07AnhsxPkCgYEA8RMvE3ImZTkPVqdX\n' \ - '72E2A5ScJswVvZelnRS/mG8U+8UlvevAu5MYr717DHKHy3yOw/u7wbkqk6KEIcyz\n' \ - 'ctNPBPqTweaZ28eEY/+lXSdQaWLD2UgZC8JIcMOSeFugghEHeBaxLzUYBNDToE3q\n' \ - '1El2HJ7W14QuTA+CEtCEb+tc7ssCgYEAxwQkBTT8A7mOEE0phfUACqaBuAXld+zu\n' \ - 'I3PNJDIhg1ZABEJ9vo9+3duFDoEHVsJOetijrBBxf/XAvi3bTJ+gAjcA54cGpkxz\n' \ - '6ssbFWZeC9exyo0ILKn33o716GrCvQn1kmuF2gasmAcrOVsMygawR7P02oasDP/X\n' \ - 'UckbZdqofdMCgYEAom0GfteePv0e9Idzm/mnZuot+4Xt7/vIvflIze+p96hxMXEy\n' \ - 'Pi9xppbH3S8dh2C44Bsv+epEYYxR8mP1VBxDVVtvSmmQqJ/Y93c7d3QRna/JvQ/y\n' \ - 'sBWKsU9T1HwHvRq0KZlAcEoZkMUSkSNuYPHN/qKWpkaM2vpn7T1Ivg+aYdkCgYA/\n' \ - 'CGO0NnzfXSTOqvHM2LVDqksJkuyD2Enwdpvxq+MLawTplHmpIl/HOuDgoCNH6lDa\n' \ - '/cSRGcApDBgY5ANCOIiASxWBPzXu8+X+5odUdtCwpYdNJPAC3W6BUfw2uaGmKAJc\n' \ - 'dqu1S0nc+OBK0Tiyv/2TKD8T+3WAxINZBv4je2bEOwKBgEavm5zTN9NILJsJCf9k\n' \ - 'te7+uDFuyoNWkL1vmMPuJYVC1QMVq1yr3DSaxA19BG9P4ZyOMOwVlPVWA+LofD4D\n' \ - 'S+w4Jjl2KDI4tSLUr6bsAJWdDfmrmGmRN3Kpds4RXaymV3rjj7qRk1J+ivtwo89s\n' \ - 'Vj+VslYzxw7FKKmnBgh/qGbJ\n' \ - '-----END PRIVATE KEY-----\n' +client_key_pem = ( + '-----BEGIN PRIVATE KEY-----\n' + 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC7ac/Qc+2Aq9FT\n' + 'AW46zvZxp/ijJ4rfc5V9rp8Ya22v9BjLD0+vC10UPIRYSIjg/iGfE0L5u81Ji0lT\n' + 'MX0SaSqtS0rGEGxFVMpY6q6ZyC2IxY7Gl1UqXT3fqd7Y+qFLB512tDC88MW4HeFG\n' + 'KRFfXX53m+SMUFX0WhmhsodZ6YORdJzZH33FGJ7k8mgR+jOua7nOMJo8fHOTJmyY\n' + 'fgwgt9O6FQZz8TJ702X6WljkouMzXhkxAsrUIdG4j+ioI3rVZCuBRjkTJcZ7SNcd\n' + 'NWGUvZE3yePEn/ivcmcr8FCRxdMgw84/yMi/1LLUeHF9crIfMuo4GfQW36Y4AOuk\n' + 'BZfxafBRAgMBAAECggEBAJuJZ1UCwRtGfUS8LTVVSiZtVuZhDNoB3REfeR4VGkUq\n' + '+eCcZm9JqQgAaX2zRRYlEtYocC8+c1MT69jFe51p9mc302ipfJHVmtFMg3dRMKkP\n' + '/DxIn/+2voD/Q9kjt/TC7yXyyXglApKZCbrmnmpc93ZgxL7GdW+Dzz3pIne2WuC9\n' + 'T6ie71R8X60sau6ApMgkUq6On0f21v/VLkNU67tQJGBF6Q1HE8PK7Ptun3WSBVNm\n' + 'FNNJKRBwiqfWXe9hPlqqCWayYBrojSqJJXn5Xd6n5XzLDPzAXuPlkPF3VwWeXGam\n' + '3RBZA26gwv50E1PeiUQOipkR57J+O9j/oA07AnhsxPkCgYEA8RMvE3ImZTkPVqdX\n' + '72E2A5ScJswVvZelnRS/mG8U+8UlvevAu5MYr717DHKHy3yOw/u7wbkqk6KEIcyz\n' + 'ctNPBPqTweaZ28eEY/+lXSdQaWLD2UgZC8JIcMOSeFugghEHeBaxLzUYBNDToE3q\n' + '1El2HJ7W14QuTA+CEtCEb+tc7ssCgYEAxwQkBTT8A7mOEE0phfUACqaBuAXld+zu\n' + 'I3PNJDIhg1ZABEJ9vo9+3duFDoEHVsJOetijrBBxf/XAvi3bTJ+gAjcA54cGpkxz\n' + '6ssbFWZeC9exyo0ILKn33o716GrCvQn1kmuF2gasmAcrOVsMygawR7P02oasDP/X\n' + 'UckbZdqofdMCgYEAom0GfteePv0e9Idzm/mnZuot+4Xt7/vIvflIze+p96hxMXEy\n' + 'Pi9xppbH3S8dh2C44Bsv+epEYYxR8mP1VBxDVVtvSmmQqJ/Y93c7d3QRna/JvQ/y\n' + 'sBWKsU9T1HwHvRq0KZlAcEoZkMUSkSNuYPHN/qKWpkaM2vpn7T1Ivg+aYdkCgYA/\n' + 'CGO0NnzfXSTOqvHM2LVDqksJkuyD2Enwdpvxq+MLawTplHmpIl/HOuDgoCNH6lDa\n' + '/cSRGcApDBgY5ANCOIiASxWBPzXu8+X+5odUdtCwpYdNJPAC3W6BUfw2uaGmKAJc\n' + 'dqu1S0nc+OBK0Tiyv/2TKD8T+3WAxINZBv4je2bEOwKBgEavm5zTN9NILJsJCf9k\n' + 'te7+uDFuyoNWkL1vmMPuJYVC1QMVq1yr3DSaxA19BG9P4ZyOMOwVlPVWA+LofD4D\n' + 'S+w4Jjl2KDI4tSLUr6bsAJWdDfmrmGmRN3Kpds4RXaymV3rjj7qRk1J+ivtwo89s\n' + 'Vj+VslYzxw7FKKmnBgh/qGbJ\n' + '-----END PRIVATE KEY-----\n' +) success_response = '

Hello Secure World!

' -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_router +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_protocol_https_server_simple(dut: Dut) -> None: """ steps: | @@ -143,7 +146,7 @@ def test_examples_protocol_https_server_simple(dut: Dut) -> None: conn = http.client.HTTPSConnection(got_ip, got_port, context=ssl_context) logging.info('Performing SSL handshake with the server') - conn.request('GET','/') + conn.request('GET', '/') resp = conn.getresponse() dut.expect('performing session handshake') got_resp = resp.read().decode('utf-8') @@ -159,7 +162,9 @@ def test_examples_protocol_https_server_simple(dut: Dut) -> None: serial_number = dut.expect(r'serial number\s*:([^\n]*)', timeout=5)[0] issuer_name = dut.expect(r'issuer name\s*:([^\n]*)', timeout=5)[0] - expiry = dut.expect(r'expires on ((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode() + expiry = dut.expect(r'expires on ((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[ + 1 + ].decode() logging.info('Serial No. {}'.format(serial_number)) logging.info('Issuer Name {}'.format(issuer_name)) @@ -171,11 +176,15 @@ def test_examples_protocol_https_server_simple(dut: Dut) -> None: logging.info('SSL connection test successful\nClosing the connection') -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_router -@pytest.mark.parametrize('config', ['dynamic_buffer',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'dynamic_buffer', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_protocol_https_server_simple_dynamic_buffers(dut: Dut) -> None: # Test with mbedTLS dynamic buffer feature @@ -214,7 +223,7 @@ def test_examples_protocol_https_server_simple_dynamic_buffers(dut: Dut) -> None conn = http.client.HTTPSConnection(got_ip, got_port, context=ssl_context) logging.info('Performing SSL handshake with the server') - conn.request('GET','/') + conn.request('GET', '/') resp = conn.getresponse() dut.expect('performing session handshake') got_resp = resp.read().decode('utf-8') @@ -230,7 +239,9 @@ def test_examples_protocol_https_server_simple_dynamic_buffers(dut: Dut) -> None serial_number = dut.expect(r'serial number\s*:([^\n]*)', timeout=5)[0] issuer_name = dut.expect(r'issuer name\s*:([^\n]*)', timeout=5)[0] - expiry = dut.expect(r'expires on\s*:((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode() + expiry = dut.expect(r'expires on\s*:((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[ + 1 + ].decode() logging.info('Serial No. : {}'.format(serial_number)) logging.info('Issuer Name : {}'.format(issuer_name)) diff --git a/examples/protocols/https_server/wss_server/pytest_https_wss_server.py b/examples/protocols/https_server/wss_server/pytest_https_wss_server.py index 9f6dd4de75..148cbddbb6 100644 --- a/examples/protocols/https_server/wss_server/pytest_https_wss_server.py +++ b/examples/protocols/https_server/wss_server/pytest_https_wss_server.py @@ -1,26 +1,25 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - -from __future__ import division, print_function, unicode_literals - import logging import os import threading import time from types import TracebackType -from typing import Any, Optional +from typing import Any +from typing import Optional import pytest import websocket from common_test_methods import get_env_config_variable from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize OPCODE_TEXT = 0x1 OPCODE_BIN = 0x2 OPCODE_PING = 0x9 -OPCODE_PONG = 0xa +OPCODE_PONG = 0xA CORRECT_ASYNC_DATA = 'Hello client' @@ -28,9 +27,9 @@ class WsClient: def __init__(self, ip, port, ca_file): # type: (str, int, str) -> None self.port = port self.ip = ip - sslopt = {'ca_certs':ca_file, 'check_hostname': False} + sslopt = {'ca_certs': ca_file, 'check_hostname': False} self.ws = websocket.WebSocket(sslopt=sslopt) - # Set timeout to 10 seconds to avoid conection failure at the time of handshake + # Set timeout to 10 seconds to avoid connection failure at the time of handshake self.ws.settimeout(10) def __enter__(self): # type: ignore @@ -106,10 +105,9 @@ def test_multiple_client_keep_alive_and_async_response(ip, port, ca_file): # ty t.join() -@pytest.mark.esp32 @pytest.mark.wifi_router +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_https_wss_server(dut: Dut) -> None: - # Get binary file binary_file = os.path.join(dut.app.binary_path, 'wss_server.bin') bin_size = os.path.getsize(binary_file) @@ -172,8 +170,10 @@ def test_examples_protocol_https_wss_server(dut: Dut) -> None: logging.info('Failed the test for keep alive,\nthe client got abruptly disconnected') raise - # keepalive timeout is 10 seconds so do not respond for (10 + 1) senconds - logging.info('Testing if client is disconnected if it does not respond for 10s i.e. keep_alive timeout (approx time = 11s)') + # keepalive timeout is 10 seconds so do not respond for (10 + 1) seconds + logging.info( + 'Testing if client is disconnected if it does not respond for 10s i.e. keep_alive timeout (approx time = 11s)' + ) try: dut.expect('Client not alive, closing fd {}'.format(client_fd), timeout=20) dut.expect('Client disconnected {}'.format(client_fd)) diff --git a/examples/protocols/https_x509_bundle/pytest_https_x509_bundle.py b/examples/protocols/https_x509_bundle/pytest_https_x509_bundle.py index ec3f115bd8..c3b3eb24f5 100644 --- a/examples/protocols/https_x509_bundle/pytest_https_x509_bundle.py +++ b/examples/protocols/https_x509_bundle/pytest_https_x509_bundle.py @@ -1,14 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_https_x509_bundle(dut: Dut) -> None: """ steps: | @@ -28,9 +29,15 @@ def test_examples_protocol_https_x509_bundle(dut: Dut) -> None: dut.expect('Completed {} connections'.format(num_URLS), timeout=60) -@pytest.mark.esp32 @pytest.mark.ethernet -@pytest.mark.parametrize('config', ['ssldyn',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'ssldyn', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_https_x509_bundle_dynamic_buffer(dut: Dut) -> None: # test mbedtls dynamic resource # check and log bin size @@ -45,9 +52,15 @@ def test_examples_protocol_https_x509_bundle_dynamic_buffer(dut: Dut) -> None: @pytest.mark.qemu -@pytest.mark.esp32 @pytest.mark.host_test -@pytest.mark.parametrize('config', ['default_crt_bundle',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default_crt_bundle', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_https_x509_bundle_default_crt_bundle_stress_test(dut: Dut) -> None: # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin') diff --git a/examples/protocols/icmp_echo/pytest_icmp_echo.py b/examples/protocols/icmp_echo/pytest_icmp_echo.py index 298e894537..6a049486bc 100644 --- a/examples/protocols/icmp_echo/pytest_icmp_echo.py +++ b/examples/protocols/icmp_echo/pytest_icmp_echo.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import logging import os @@ -6,6 +6,7 @@ import os import pytest from common_test_methods import get_env_config_variable from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def _run_test(dut: Dut) -> None: @@ -27,41 +28,46 @@ def _run_test(dut: Dut) -> None: # expect at least two packets (there could be lost packets) ip = dut.expect(r'64 bytes from (\d+\.\d+\.\d+\.\d+) icmp_seq=\d ttl=\d+ time=\d+ ms')[1].decode() - dut.expect(fr'64 bytes from {ip} icmp_seq=[2-5] ttl=\d+ time=') + dut.expect(rf'64 bytes from {ip} icmp_seq=[2-5] ttl=\d+ time=') dut.expect(r'5 packets transmitted, [2-5] received, \d{1,3}% packet loss') dut.write('') dut.expect('esp>') -@pytest.mark.esp32 -@pytest.mark.esp32c2 -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_ap +@idf_parametrize( + 'target', + ['esp32', 'esp32c2', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'], + indirect=['target'], +) def test_protocols_icmp_echo(dut: Dut) -> None: _run_test(dut) -@pytest.mark.esp32c2 @pytest.mark.wifi_ap @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'config, baud', [ + 'config, baud', + [ ('c2_xtal26m', '74880'), - ], indirect=True + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_protocols_icmp_echo_esp32c2_26mhz(dut: Dut) -> None: _run_test(dut) -@pytest.mark.esp32 @pytest.mark.wifi_router -@pytest.mark.parametrize('config', ['ipv6_only',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'ipv6_only', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_protocols_icmp_echo_ipv6_only(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') @@ -82,7 +88,7 @@ def test_protocols_icmp_echo_ipv6_only(dut: Dut) -> None: # expect at least two packets (there could be lost packets) ip = dut.expect(r'64 bytes from ([0-9a-fA-F:]+) icmp_seq=\d ttl=\d+ time=\d+ ms')[1].decode() - dut.expect(fr'64 bytes from {ip} icmp_seq=[2-5] ttl=\d+ time=') + dut.expect(rf'64 bytes from {ip} icmp_seq=[2-5] ttl=\d+ time=') dut.expect(r'5 packets transmitted, [2-5] received, \d{1,3}% packet loss') dut.write('') diff --git a/examples/protocols/l2tap/pytest_example_l2tap_echo.py b/examples/protocols/l2tap/pytest_example_l2tap_echo.py index af01196faa..f4718bc0af 100644 --- a/examples/protocols/l2tap/pytest_example_l2tap_echo.py +++ b/examples/protocols/l2tap/pytest_example_l2tap_echo.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import contextlib import logging @@ -9,6 +9,7 @@ from typing import Iterator import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize from scapy.all import Ether from scapy.all import raw @@ -50,7 +51,7 @@ def configure_eth_if(eth_type: int, target_if: str = '') -> Iterator[socket.sock so.close() -def send_recv_eth_frame(payload_str: str, eth_type: int, dest_mac: str, eth_if: str='') -> str: +def send_recv_eth_frame(payload_str: str, eth_type: int, dest_mac: str, eth_if: str = '') -> str: with configure_eth_if(eth_type, eth_if) as so: so.settimeout(10) eth_frame = Ether(dst=dest_mac, src=so.getsockname()[4], type=eth_type) / raw(payload_str.encode()) @@ -70,7 +71,7 @@ def send_recv_eth_frame(payload_str: str, eth_type: int, dest_mac: str, eth_if: return str(eth_frame_repl.load.decode().rstrip('\x00')) -def recv_eth_frame(eth_type: int, eth_if: str='') -> str: +def recv_eth_frame(eth_type: int, eth_if: str = '') -> str: with configure_eth_if(eth_type, eth_if) as so: so.settimeout(10) try: @@ -109,9 +110,9 @@ def actual_test(dut: Dut, test_if: str = '') -> None: raise Exception('Echoed message does not match!') -@pytest.mark.esp32 # internally tested using ESP32 with IP101 but may support all targets with SPI Ethernet @pytest.mark.eth_ip101 @pytest.mark.flaky(reruns=3, reruns_delay=5) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_netif_l2tap_example(dut: Dut) -> None: actual_test(dut) @@ -121,12 +122,12 @@ if __name__ == '__main__': message_1 = 'ESP32 test message with EthType ' + hex(ETH_TYPE_1) message_2 = 'ESP32 test message with EthType ' + hex(ETH_TYPE_2) # Usage: pytest_example_l2tap_echo.py [] [] - if sys.argv[2:]: # if two arguments provided: + if sys.argv[2:]: # if two arguments provided: send_recv_eth_frame(message_1, ETH_TYPE_1, sys.argv[1], sys.argv[2]) send_recv_eth_frame(message_2, ETH_TYPE_2, sys.argv[1], sys.argv[2]) - elif sys.argv[1:]: # if one argument provided: + elif sys.argv[1:]: # if one argument provided: send_recv_eth_frame(message_1, ETH_TYPE_1, sys.argv[1]) send_recv_eth_frame(message_2, ETH_TYPE_2, sys.argv[1]) - else: # if no argument provided: + else: # if no argument provided: send_recv_eth_frame(message_1, ETH_TYPE_1, 'ff:ff:ff:ff:ff:ff') send_recv_eth_frame(message_2, ETH_TYPE_2, 'ff:ff:ff:ff:ff:ff') diff --git a/examples/protocols/mqtt/ssl/pytest_mqtt_ssl.py b/examples/protocols/mqtt/ssl/pytest_mqtt_ssl.py index 36de017ccb..2ca3465d50 100644 --- a/examples/protocols/mqtt/ssl/pytest_mqtt_ssl.py +++ b/examples/protocols/mqtt/ssl/pytest_mqtt_ssl.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os @@ -12,6 +12,7 @@ import paho.mqtt.client as mqtt import pexpect import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize event_client_connected = Event() event_stop_client = Event() @@ -52,7 +53,9 @@ def on_message(client, userdata, msg): # type: (mqtt.Client, tuple, mqtt.client recv_binary = binary + '.received' with open(recv_binary, 'w', encoding='utf-8') as fw: fw.write(msg.payload) - raise ValueError('Received binary (saved as: {}) does not match the original file: {}'.format(recv_binary, binary)) + raise ValueError( + 'Received binary (saved as: {}) does not match the original file: {}'.format(recv_binary, binary) + ) payload = msg.payload.decode() if ( @@ -67,8 +70,8 @@ def on_message(client, userdata, msg): # type: (mqtt.Client, tuple, mqtt.client message_log += 'Received data:' + msg.topic + ' ' + payload + '\n' -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_mqtt_ssl(dut): # type: (Dut) -> None broker_url = '' broker_port = 0 @@ -101,14 +104,16 @@ def test_examples_protocol_mqtt_ssl(dut): # type: (Dut) -> None client.on_connect = on_connect client.on_message = on_message client.user_data_set((binary_file, bin_size)) - client.tls_set(None, - None, - None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None) + client.tls_set(None, None, None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None) client.tls_insecure_set(True) print('Connecting...') client.connect(broker_url, broker_port, 60) except Exception: - print('ENV_TEST_FAILURE: Unexpected error while connecting to broker {}: {}:'.format(broker_url, sys.exc_info()[0])) + print( + 'ENV_TEST_FAILURE: Unexpected error while connecting to broker {}: {}:'.format( + broker_url, sys.exc_info()[0] + ) + ) raise # Starting a py-client in a separate thread thread1 = Thread(target=mqtt_client_task, args=(client,)) diff --git a/examples/protocols/mqtt/tcp/pytest_mqtt_tcp.py b/examples/protocols/mqtt/tcp/pytest_mqtt_tcp.py index 2786a76b97..7809e656f6 100644 --- a/examples/protocols/mqtt/tcp/pytest_mqtt_tcp.py +++ b/examples/protocols/mqtt/tcp/pytest_mqtt_tcp.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os @@ -12,6 +12,7 @@ import pexpect import pytest from common_test_methods import get_host_ip4_by_dest_ip from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize msgid = -1 @@ -25,13 +26,15 @@ def mqqt_server_sketch(my_ip, port): # type: (str, str) -> None s.settimeout(60) s.bind((my_ip, port)) s.listen(1) - q,addr = s.accept() + q, addr = s.accept() q.settimeout(30) print('connection accepted') except Exception: - print('Local server on {}:{} listening/accepting failure: {}' - 'Possibly check permissions or firewall settings' - 'to accept connections on this address'.format(my_ip, port, sys.exc_info()[0])) + print( + 'Local server on {}:{} listening/accepting failure: {}' + 'Possibly check permissions or firewall settings' + 'to accept connections on this address'.format(my_ip, port, sys.exc_info()[0]) + ) raise data = q.recv(1024) # check if received initial empty message @@ -49,8 +52,8 @@ def mqqt_server_sketch(my_ip, port): # type: (str, str) -> None print('server closed') -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_mqtt_qos1(dut: Dut) -> None: global msgid """ @@ -73,7 +76,7 @@ def test_examples_protocol_mqtt_qos1(dut: Dut) -> None: # 2. start mqtt broker sketch host_ip = get_host_ip4_by_dest_ip(ip_address) - thread1 = Thread(target=mqqt_server_sketch, args=(host_ip,1883)) + thread1 = Thread(target=mqqt_server_sketch, args=(host_ip, 1883)) thread1.start() data_write = 'mqtt://' + host_ip @@ -85,8 +88,10 @@ def test_examples_protocol_mqtt_qos1(dut: Dut) -> None: msgid_enqueued = dut.expect(b'outbox: ENQUEUE msgid=([0-9]+)', timeout=30).group(1).decode() msgid_deleted = dut.expect(b'outbox: DELETED msgid=([0-9]+)', timeout=30).group(1).decode() # 4. check the msgid of received data are the same as that of enqueued and deleted from outbox - if (msgid_enqueued == str(msgid) and msgid_deleted == str(msgid)): + if msgid_enqueued == str(msgid) and msgid_deleted == str(msgid): print('PASS: Received correct msg id') else: print('Failure!') - raise ValueError('Mismatch of msgid: received: {}, enqueued {}, deleted {}'.format(msgid, msgid_enqueued, msgid_deleted)) + raise ValueError( + 'Mismatch of msgid: received: {}, enqueued {}, deleted {}'.format(msgid, msgid_enqueued, msgid_deleted) + ) diff --git a/examples/protocols/mqtt/ws/pytest_mqtt_ws_example.py b/examples/protocols/mqtt/ws/pytest_mqtt_ws_example.py index 392139c37e..f475cbfa79 100644 --- a/examples/protocols/mqtt/ws/pytest_mqtt_ws_example.py +++ b/examples/protocols/mqtt/ws/pytest_mqtt_ws_example.py @@ -1,16 +1,18 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os import re import sys -from threading import Event, Thread +from threading import Event +from threading import Thread import paho.mqtt.client as mqtt import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize event_client_connected = Event() event_stop_client = Event() @@ -43,8 +45,8 @@ def on_message(client, userdata, msg): # type: (mqtt.Client, tuple, mqtt.client message_log += 'Received data:' + msg.topic + ' ' + payload + '\n' -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_mqtt_ws(dut): # type: (Dut) -> None broker_url = '' broker_port = 0 @@ -77,7 +79,11 @@ def test_examples_protocol_mqtt_ws(dut): # type: (Dut) -> None print('Connecting...') client.connect(broker_url, broker_port, 60) except Exception: - print('ENV_TEST_FAILURE: Unexpected error while connecting to broker {}: {}:'.format(broker_url, sys.exc_info()[0])) + print( + 'ENV_TEST_FAILURE: Unexpected error while connecting to broker {}: {}:'.format( + broker_url, sys.exc_info()[0] + ) + ) raise # Starting a py-client in a separate thread thread1 = Thread(target=mqtt_client_task, args=(client,)) diff --git a/examples/protocols/mqtt/wss/pytest_mqtt_wss_example.py b/examples/protocols/mqtt/wss/pytest_mqtt_wss_example.py index 05eff5e515..838d2313ea 100644 --- a/examples/protocols/mqtt/wss/pytest_mqtt_wss_example.py +++ b/examples/protocols/mqtt/wss/pytest_mqtt_wss_example.py @@ -1,18 +1,20 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os import re import ssl import sys -from threading import Event, Thread +from threading import Event +from threading import Thread import paho.mqtt.client as mqtt import pexpect import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize event_client_connected = Event() event_stop_client = Event() @@ -45,8 +47,8 @@ def on_message(client, userdata, msg): # type: (mqtt.Client, tuple, mqtt.client message_log += 'Received data:' + msg.topic + ' ' + payload + '\n' -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_mqtt_wss(dut): # type: (Dut) -> None broker_url = '' broker_port = 0 @@ -76,13 +78,15 @@ def test_examples_protocol_mqtt_wss(dut): # type: (Dut) -> None client = mqtt.Client(transport='websockets') client.on_connect = on_connect client.on_message = on_message - client.tls_set(None, - None, - None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None) + client.tls_set(None, None, None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None) print('Connecting...') client.connect(broker_url, broker_port, 60) except Exception: - print('ENV_TEST_FAILURE: Unexpected error while connecting to broker {}: {}:'.format(broker_url, sys.exc_info()[0])) + print( + 'ENV_TEST_FAILURE: Unexpected error while connecting to broker {}: {}:'.format( + broker_url, sys.exc_info()[0] + ) + ) raise # Starting a py-client in a separate thread thread1 = Thread(target=mqtt_client_task, args=(client,)) diff --git a/examples/protocols/mqtt5/pytest_mqtt5.py b/examples/protocols/mqtt5/pytest_mqtt5.py index 603be68c12..a658350648 100644 --- a/examples/protocols/mqtt5/pytest_mqtt5.py +++ b/examples/protocols/mqtt5/pytest_mqtt5.py @@ -1,23 +1,23 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import logging import os import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_mqtt5(dut: Dut) -> None: """ steps: | 1. join AP 2. connect to mqtt://mqtt.eclipseprojects.io - 3. check conneciton success + 3. check connection success """ # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'mqtt5.bin') diff --git a/examples/protocols/sntp/pytest_sntp.py b/examples/protocols/sntp/pytest_sntp.py index 6191fd7ae7..da9758d2b2 100644 --- a/examples/protocols/sntp/pytest_sntp.py +++ b/examples/protocols/sntp/pytest_sntp.py @@ -1,17 +1,18 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import datetime import logging -from typing import Any, Tuple +from typing import Any +from typing import Tuple import pytest from common_test_methods import get_env_config_variable from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.wifi_ap +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_get_time_from_sntp_server(dut: Dut) -> None: dut.expect('Time is not set yet. Connecting to WiFi and getting time over NTP.') if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True: diff --git a/examples/protocols/sockets/tcp_client/pytest_tcp_client.py b/examples/protocols/sockets/tcp_client/pytest_tcp_client.py index 395cebec99..fd5eb31eb5 100644 --- a/examples/protocols/sockets/tcp_client/pytest_tcp_client.py +++ b/examples/protocols/sockets/tcp_client/pytest_tcp_client.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import logging import socket @@ -9,12 +9,14 @@ from common_test_methods import get_host_ip4_by_dest_ip from common_test_methods import get_host_ip6_by_dest_ip from common_test_methods import get_my_interface_by_dest_ip from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize try: from run_tcp_server import TcpServer except ImportError: import os import sys + sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'scripts'))) from run_tcp_server import TcpServer @@ -22,15 +24,12 @@ except ImportError: PORT = 3333 -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_router +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32c2', 'esp32c3', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'], + indirect=['target'], +) def test_examples_tcp_client_ipv4(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') @@ -51,14 +50,10 @@ def test_examples_tcp_client_ipv4(dut: Dut) -> None: dut.expect('OK: Message from ESP32') -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_router +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32c2', 'esp32c3', 'esp32s3', 'esp32c6', 'esp32c61'], indirect=['target'] +) def test_examples_tcp_client_ipv6(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') diff --git a/examples/protocols/sockets/tcp_server/pytest_tcp_server.py b/examples/protocols/sockets/tcp_server/pytest_tcp_server.py index fd1bb907f0..f65a2b5edc 100644 --- a/examples/protocols/sockets/tcp_server/pytest_tcp_server.py +++ b/examples/protocols/sockets/tcp_server/pytest_tcp_server.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import logging import time @@ -8,12 +8,14 @@ import pytest from common_test_methods import get_env_config_variable from common_test_methods import get_my_interface_by_dest_ip from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize try: from run_tcp_client import tcp_client except ImportError: import os import sys + sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'scripts'))) from run_tcp_client import tcp_client @@ -22,15 +24,12 @@ PORT = 3333 MESSAGE = 'Data to ESP' -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_router +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32c2', 'esp32c3', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'], + indirect=['target'], +) def test_examples_tcp_server_ipv4(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') @@ -51,14 +50,16 @@ def test_examples_tcp_server_ipv4(dut: Dut) -> None: dut.expect(MESSAGE) -@pytest.mark.esp32c2 @pytest.mark.wifi_router @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'config, baud', [ + 'config, baud', + [ ('c2_xtal26m', '74880'), - ], indirect=True + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_examples_tcp_server_ipv4_esp32c2_26mhz(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') @@ -79,14 +80,10 @@ def test_examples_tcp_server_ipv4_esp32c2_26mhz(dut: Dut) -> None: dut.expect(MESSAGE) -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_router +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32c2', 'esp32c3', 'esp32s3', 'esp32c6', 'esp32c61'], indirect=['target'] +) def test_examples_tcp_server_ipv6(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') @@ -111,14 +108,10 @@ def test_examples_tcp_server_ipv6(dut: Dut) -> None: dut.expect(MESSAGE) -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_router +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32c2', 'esp32c3', 'esp32s3', 'esp32c6', 'esp32c61'], indirect=['target'] +) def test_examples_tcp_server_ipv6_only(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') diff --git a/examples/protocols/sockets/udp_client/pytest_udp_client.py b/examples/protocols/sockets/udp_client/pytest_udp_client.py index c16885b1b4..1027e401f0 100644 --- a/examples/protocols/sockets/udp_client/pytest_udp_client.py +++ b/examples/protocols/sockets/udp_client/pytest_udp_client.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import logging import socket @@ -10,12 +10,14 @@ from common_test_methods import get_host_ip6_by_dest_ip from common_test_methods import get_my_interface_by_dest_ip from pexpect.exceptions import TIMEOUT from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize try: from run_udp_server import UdpServer except ImportError: import os import sys + sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'scripts'))) from run_udp_server import UdpServer @@ -24,15 +26,12 @@ PORT = 3333 MAX_RETRIES = 3 -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_router +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32c2', 'esp32c3', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'], + indirect=['target'], +) def test_examples_udp_client_ipv4(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') @@ -60,14 +59,10 @@ def test_examples_udp_client_ipv4(dut: Dut) -> None: raise ValueError('Failed to send/recv udp packets.') -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_router +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32c2', 'esp32c3', 'esp32s3', 'esp32c6', 'esp32c61'], indirect=['target'] +) def test_examples_udp_client_ipv6(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') diff --git a/examples/protocols/sockets/udp_server/pytest_udp_server.py b/examples/protocols/sockets/udp_server/pytest_udp_server.py index d3905e55be..ac69fbf037 100644 --- a/examples/protocols/sockets/udp_server/pytest_udp_server.py +++ b/examples/protocols/sockets/udp_server/pytest_udp_server.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import logging @@ -6,12 +6,14 @@ import pytest from common_test_methods import get_env_config_variable from common_test_methods import get_my_interface_by_dest_ip from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize try: from run_udp_client import udp_client except ImportError: import os import sys + sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'scripts'))) from run_udp_client import udp_client @@ -21,15 +23,12 @@ MESSAGE = 'Data to ESP' MAX_RETRIES = 3 -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_router +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32c2', 'esp32c3', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'], + indirect=['target'], +) def test_examples_udp_server_ipv4(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') @@ -54,14 +53,10 @@ def test_examples_udp_server_ipv4(dut: Dut) -> None: dut.expect(MESSAGE) -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_router +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32c2', 'esp32c3', 'esp32s3', 'esp32c6', 'esp32c61'], indirect=['target'] +) def test_examples_udp_server_ipv6(dut: Dut) -> None: # Parse IP address of STA logging.info('Waiting to connect with AP') diff --git a/examples/protocols/static_ip/pytest_static_ip.py b/examples/protocols/static_ip/pytest_static_ip.py index aecc2b5fed..ce62471f89 100644 --- a/examples/protocols/static_ip/pytest_static_ip.py +++ b/examples/protocols/static_ip/pytest_static_ip.py @@ -1,15 +1,18 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.eth_ip101 -@pytest.mark.parametrize('config', [ - 'default_ip101', -], indirect=True) -def test_static_ip( - dut: Dut -) -> None: +@pytest.mark.parametrize( + 'config', + [ + 'default_ip101', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) +def test_static_ip(dut: Dut) -> None: dut.expect(r'Resolved IPv4 address: (\d+\.\d+\.\d+\.\d+)') diff --git a/examples/provisioning/wifi_prov_mgr/pytest_wifi_prov_mgr.py b/examples/provisioning/wifi_prov_mgr/pytest_wifi_prov_mgr.py index 45704df07f..277e6be77f 100644 --- a/examples/provisioning/wifi_prov_mgr/pytest_wifi_prov_mgr.py +++ b/examples/provisioning/wifi_prov_mgr/pytest_wifi_prov_mgr.py @@ -1,14 +1,13 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - -from __future__ import print_function - import logging import os import sys +from pytest_embedded_idf.utils import idf_parametrize + try: import esp_prov except ImportError: @@ -25,7 +24,7 @@ logging.basicConfig(level=logging.INFO) esp_prov.config_throw_except = True -def test_wifi_prov_mgr(dut: Dut, sec_ver: int) -> None: +def test_wifi_prov_mgr(dut: Dut, sec_ver: int) -> None: # Check if BT memory is released before provisioning starts dut.expect('wifi_prov_scheme_ble: BT memory released', timeout=60) @@ -41,12 +40,12 @@ def test_wifi_prov_mgr(dut: Dut, sec_ver: int) -> None: ap_password = 'mypassword' logging.info('Getting security') - if (sec_ver == 1): + if sec_ver == 1: pop = 'abcd1234' sec2_username = None sec2_password = None security = esp_prov.get_security(sec_ver, sec2_username, sec2_password, pop, verbose) - elif (sec_ver == 2): + elif sec_ver == 2: pop = None sec2_username = 'wifiprov' sec2_password = 'abcd1234' @@ -91,18 +90,22 @@ def test_wifi_prov_mgr(dut: Dut, sec_ver: int) -> None: dut.expect('wifi_prov_scheme_ble: BTDM memory released', timeout=30) -@pytest.mark.esp32 @pytest.mark.generic -@pytest.mark.parametrize('config', ['security1',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'security1', + ], + indirect=True, +) @pytest.mark.xfail(reason='Runner unable to connect to target over Bluetooth', run=False) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_wifi_prov_mgr_sec1(dut: Dut) -> None: - test_wifi_prov_mgr(dut, 1) -@pytest.mark.esp32 @pytest.mark.generic @pytest.mark.xfail(reason='Runner unable to connect to target over Bluetooth', run=False) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_wifi_prov_mgr_sec2(dut: Dut) -> None: - test_wifi_prov_mgr(dut, 2) diff --git a/examples/security/flash_encryption/pytest_flash_encryption.py b/examples/security/flash_encryption/pytest_flash_encryption.py index 3879bbf350..0ea65384ee 100644 --- a/examples/security/flash_encryption/pytest_flash_encryption.py +++ b/examples/security/flash_encryption/pytest_flash_encryption.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import binascii from collections import namedtuple @@ -7,8 +7,7 @@ from io import BytesIO import espsecure import pytest from pytest_embedded import Dut - - +from pytest_embedded_idf.utils import idf_parametrize # To prepare a test runner for this example: # 1. Generate zero flash encryption key: # dd if=/dev/zero of=key.bin bs=1 count=32 @@ -16,6 +15,8 @@ from pytest_embedded import Dut # espefuse.py --do-not-confirm -p $ESPPORT burn_efuse FLASH_CRYPT_CONFIG 0xf # espefuse.py --do-not-confirm -p $ESPPORT burn_efuse FLASH_CRYPT_CNT 0x1 # espefuse.py --do-not-confirm -p $ESPPORT burn_key flash_encryption key.bin + + def _test_flash_encryption(dut: Dut) -> None: # Erase the nvs_key partition dut.serial.erase_partition('nvs_key') @@ -35,14 +36,19 @@ def _test_flash_encryption(dut: Dut) -> None: aes_xts = True # Emulate espsecure encrypt_flash_data command - EncryptFlashDataArgs = namedtuple('EncryptFlashDataArgs', ['output', 'plaintext_file', 'address', 'keyfile', 'flash_crypt_conf', 'aes_xts']) + EncryptFlashDataArgs = namedtuple( + 'EncryptFlashDataArgs', ['output', 'plaintext_file', 'address', 'keyfile', 'flash_crypt_conf', 'aes_xts'] + ) args = EncryptFlashDataArgs(BytesIO(), BytesIO(plain_data), flash_addr, BytesIO(key_bytes), 0xF, aes_xts) espsecure.encrypt_flash_data(args) expected_ciphertext = args.output.getvalue() hex_ciphertext = binascii.hexlify(expected_ciphertext).decode('ascii') - expected_str = (' '.join(hex_ciphertext[i:i + 2] for i in range(0, 16, 2)) + ' ' + - ' '.join(hex_ciphertext[i:i + 2] for i in range(16, 32, 2))) + expected_str = ( + ' '.join(hex_ciphertext[i: i + 2] for i in range(0, 16, 2)) + + ' ' + + ' '.join(hex_ciphertext[i: i + 2] for i in range(16, 32, 2)) + ) lines = [ 'FLASH_CRYPT_CNT eFuse value is 1', @@ -62,20 +68,18 @@ def _test_flash_encryption(dut: Dut) -> None: # The status of NVS encryption for the "nvs" partition 'NVS partition "nvs" is encrypted.', # The status of NVS encryption for the "custom_nvs" partition - 'NVS partition "custom_nvs" is encrypted.' + 'NVS partition "custom_nvs" is encrypted.', ] for line in lines: dut.expect(line, timeout=20) -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.flash_encryption +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_examples_security_flash_encryption(dut: Dut) -> None: _test_flash_encryption(dut) -@pytest.mark.esp32c3 @pytest.mark.flash_encryption @pytest.mark.parametrize( 'config', @@ -84,5 +88,6 @@ def test_examples_security_flash_encryption(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_examples_security_flash_encryption_rom_impl(dut: Dut) -> None: _test_flash_encryption(dut) diff --git a/examples/security/hmac_soft_jtag/pytest_jtag_example.py b/examples/security/hmac_soft_jtag/pytest_jtag_example.py index 9d7a73e19a..c37b5967d1 100644 --- a/examples/security/hmac_soft_jtag/pytest_jtag_example.py +++ b/examples/security/hmac_soft_jtag/pytest_jtag_example.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # # SPDX-License-Identifier: CC0-1.0 import logging import os @@ -8,6 +8,7 @@ import signal import pexpect import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize def run_gdb_test(dut: IdfDut) -> str: @@ -28,10 +29,9 @@ def run_gdb_test(dut: IdfDut) -> str: p.kill(signal.SIGKILL) -@pytest.mark.esp32c6 @pytest.mark.jtag_re_enable +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_jtag_re_enable(dut: IdfDut) -> None: - dut.expect_exact('esp32c6>', timeout=30) logging.info('Initially:') diff --git a/examples/security/nvs_encryption_hmac/pytest_nvs_encr_hmac.py b/examples/security/nvs_encryption_hmac/pytest_nvs_encr_hmac.py index 06fe8cb73a..b8c454688f 100644 --- a/examples/security/nvs_encryption_hmac/pytest_nvs_encr_hmac.py +++ b/examples/security/nvs_encryption_hmac/pytest_nvs_encr_hmac.py @@ -1,25 +1,30 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -STR_KEY_VAL = ['Lorem ipsum dolor sit amet, consectetur adipiscing elit.', - 'Fusce quis risus justo.', - 'Suspendisse egestas in nisi sit amet auctor.', - 'Pellentesque rhoncus dictum sodales.', - 'In justo erat, viverra at interdum eget, interdum vel dui.'] +STR_KEY_VAL = [ + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + 'Fusce quis risus justo.', + 'Suspendisse egestas in nisi sit amet auctor.', + 'Pellentesque rhoncus dictum sodales.', + 'In justo erat, viverra at interdum eget, interdum vel dui.', +] -ENCR_TEXT_ARR = ['fe ff ff ff 00 00 00 00 fe ff ff ff ff ff ff ff', - 'ca 8b c3 bb 2d c2 33 d6 6b d4 a7 3d 31 0e 9c 36', - 'bd c1 2a 10 87 44 5e 1c 4b 2c 7c 5d ac 97 48 63'] +ENCR_TEXT_ARR = [ + 'fe ff ff ff 00 00 00 00 fe ff ff ff ff ff ff ff', + 'ca 8b c3 bb 2d c2 33 d6 6b d4 a7 3d 31 0e 9c 36', + 'bd c1 2a 10 87 44 5e 1c 4b 2c 7c 5d ac 97 48 63', +] -@pytest.mark.esp32c3 @pytest.mark.nvs_encr_hmac @pytest.mark.parametrize('config', ['nvs_encr_hmac'], indirect=True) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_nvs_flash_encr_keys_hmac(dut: IdfDut) -> None: # Logging example binary details binary_file = os.path.join(dut.app.binary_path, 'nvs_encryption_hmac.bin') diff --git a/examples/storage/emmc/pytest_emmc_example.py b/examples/storage/emmc/pytest_emmc_example.py index 070c5f0e53..57341f105c 100644 --- a/examples/storage/emmc/pytest_emmc_example.py +++ b/examples/storage/emmc/pytest_emmc_example.py @@ -1,15 +1,13 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 - - import logging import re import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s3 @pytest.mark.emmc @pytest.mark.parametrize( 'config', @@ -20,6 +18,7 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_examples_sd_card_sdmmc(dut: Dut) -> None: dut.expect('example: Initializing eMMC', timeout=20) dut.expect('example: Using SDMMC peripheral', timeout=10) @@ -35,12 +34,14 @@ def test_examples_sd_card_sdmmc(dut: Dut) -> None: logging.info('Card {} {} {}MHz {} found'.format(name, _type, speed, size)) - message_list = ('Opening file /eMMC/hello.txt', - 'File written', - 'Renaming file /eMMC/hello.txt to /eMMC/foo.txt', - 'Reading file /eMMC/foo.txt', - "Read from file: 'Hello {}!'".format(name), - 'Card unmounted') + message_list = ( + 'Opening file /eMMC/hello.txt', + 'File written', + 'Renaming file /eMMC/hello.txt to /eMMC/foo.txt', + 'Reading file /eMMC/foo.txt', + "Read from file: 'Hello {}!'".format(name), + 'Card unmounted', + ) for msg in message_list: dut.expect(msg, timeout=10) diff --git a/examples/storage/fatfs/ext_flash/pytest_fatfs_ext_flash.py b/examples/storage/fatfs/ext_flash/pytest_fatfs_ext_flash.py index 56dd334a49..f072d5e5ff 100644 --- a/examples/storage/fatfs/ext_flash/pytest_fatfs_ext_flash.py +++ b/examples/storage/fatfs/ext_flash/pytest_fatfs_ext_flash.py @@ -1,17 +1,20 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.external_flash +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_ext_flash_fatfs(dut: Dut) -> None: - message_list = ('Initialized external Flash', - 'partition \'nvs\'', - 'partition \'storage\'', - 'File written', - 'Read from file: \'Written using ESP-IDF') + message_list = ( + 'Initialized external Flash', + "partition 'nvs'", + "partition 'storage'", + 'File written', + "Read from file: 'Written using ESP-IDF", + ) for msg in message_list: dut.expect(msg, timeout=20) diff --git a/examples/storage/fatfs/fatfsgen/pytest_fatfs_fatfsgen_example.py b/examples/storage/fatfs/fatfsgen/pytest_fatfs_fatfsgen_example.py index e0966604eb..0c7621d674 100644 --- a/examples/storage/fatfs/fatfsgen/pytest_fatfs_fatfsgen_example.py +++ b/examples/storage/fatfs/fatfsgen/pytest_fatfs_fatfsgen_example.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import os import re @@ -7,16 +7,22 @@ from typing import List import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize idf_path = os.environ['IDF_PATH'] # get value of IDF_PATH from environment parttool_dir = os.path.join(idf_path, 'components', 'partition_table') -@pytest.mark.esp32 @pytest.mark.generic -@pytest.mark.parametrize('config', ['test_read_only_partition_gen_ln', - 'test_read_write_partition_gen_ln', - ], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'test_read_only_partition_gen_ln', + 'test_read_write_partition_gen_ln', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_fatfs_fatfsgen(config: str, dut: Dut) -> None: # Expects list of strings sequentially def expect_all(msg_list: List[str], to: int) -> None: @@ -37,7 +43,9 @@ def test_examples_fatfs_fatfsgen(config: str, dut: Dut) -> None: def evaluate_dates(date_reference: datetime, date_actual: datetime, days_tolerance: int) -> None: td = date_actual - date_reference if abs(td.days) > days_tolerance: - raise Exception(f'Too big date difference. Actual: {date_actual}, reference: {date_reference}, tolerance: {days_tolerance} day(s)') + raise Exception( + f'Too big date difference. Actual: {date_actual}, reference: {date_reference}, tolerance: {days_tolerance} day(s)' + ) # Expect timeout timeout = 20 @@ -49,24 +57,33 @@ def test_examples_fatfs_fatfsgen(config: str, dut: Dut) -> None: if config in ['test_read_write_partition_gen']: filename_expected = f'/spiflash/{filename}' - expect_all(['example: Mounting FAT filesystem', - 'example: Opening file', - 'example: File written', - 'example: Reading file', - 'example: Read from file: \'This is written by the device\'', - 'example: Reading file'], timeout) - date_act = expect_date(f'The file \'{filename_expected}\' was modified at date: ', timeout) + expect_all( + [ + 'example: Mounting FAT filesystem', + 'example: Opening file', + 'example: File written', + 'example: Reading file', + "example: Read from file: 'This is written by the device'", + 'example: Reading file', + ], + timeout, + ) + date_act = expect_date(f"The file '{filename_expected}' was modified at date: ", timeout) evaluate_dates(date_ref, date_act, tolerance) - expect_all(['example: Read from file: \'This is generated on the host\'', - 'example: Unmounting FAT filesystem', - 'example: Done'], timeout) + expect_all( + [ + "example: Read from file: 'This is generated on the host'", + 'example: Unmounting FAT filesystem', + 'example: Done', + ], + timeout, + ) elif config in ['test_read_only_partition_gen']: filename_expected = f'/spiflash/{filename}' - expect_all(['example: Mounting FAT filesystem', - 'example: Reading file'], timeout) - date_act = expect_date(f'The file \'{filename_expected}\' was modified at date: ', timeout) + expect_all(['example: Mounting FAT filesystem', 'example: Reading file'], timeout) + date_act = expect_date(f"The file '{filename_expected}' was modified at date: ", timeout) evaluate_dates(date_ref, date_act, tolerance) - expect_all(['example: Read from file: \'this is test\'', - 'example: Unmounting FAT filesystem', - 'example: Done'], timeout) + expect_all( + ["example: Read from file: 'this is test'", 'example: Unmounting FAT filesystem', 'example: Done'], timeout + ) diff --git a/examples/storage/fatfs/fs_operations/pytest_fatfs_fs_operations_example.py b/examples/storage/fatfs/fs_operations/pytest_fatfs_fs_operations_example.py index 4067c80d13..aa9c26cd2d 100644 --- a/examples/storage/fatfs/fs_operations/pytest_fatfs_fs_operations_example.py +++ b/examples/storage/fatfs/fs_operations/pytest_fatfs_fs_operations_example.py @@ -1,14 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 from datetime import datetime from typing import List import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_fatfs_fs_operations(config: str, dut: Dut) -> None: # Expects list of strings sequentially def expect_all(msg_list: List[str], to: int) -> None: @@ -38,7 +39,7 @@ def test_examples_fatfs_fs_operations(config: str, dut: Dut) -> None: 'example: File stats:', 'File size:', ], - 5 + 5, ) original = parse_date() @@ -50,7 +51,7 @@ def test_examples_fatfs_fs_operations(config: str, dut: Dut) -> None: 'example: Force cached data and metadata to the filesystem', 'File size:', ], - 5 + 5, ) updated = parse_date() @@ -76,5 +77,5 @@ def test_examples_fatfs_fs_operations(config: str, dut: Dut) -> None: 'example: Listing files in /spiflash/new_dir:', 'hello_renamed.txt', ], - 5 + 5, ) diff --git a/examples/storage/fatfs/getting_started/pytest_fatfs_getting_started_example.py b/examples/storage/fatfs/getting_started/pytest_fatfs_getting_started_example.py index e7f9d7d78a..48ad6fdc1b 100644 --- a/examples/storage/fatfs/getting_started/pytest_fatfs_getting_started_example.py +++ b/examples/storage/fatfs/getting_started/pytest_fatfs_getting_started_example.py @@ -1,17 +1,18 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_fatfs_getting_started(dut: Dut) -> None: dut.expect('example: Mounting FAT filesystem', timeout=90) dut.expect('example: Filesystem mounted', timeout=90) dut.expect('example: Opening file', timeout=90) dut.expect('example: File written', timeout=90) dut.expect('example: Reading file', timeout=90) - dut.expect('example: Read from file: \'Hello World!\'', timeout=90) + dut.expect("example: Read from file: 'Hello World!'", timeout=90) dut.expect('example: Unmounting FAT filesystem', timeout=90) dut.expect('example: Done', timeout=90) diff --git a/examples/storage/nvs_bootloader/pytest_nvs_bootloader.py b/examples/storage/nvs_bootloader/pytest_nvs_bootloader.py index 66e2a50286..ac7f5c5581 100644 --- a/examples/storage/nvs_bootloader/pytest_nvs_bootloader.py +++ b/examples/storage/nvs_bootloader/pytest_nvs_bootloader.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_nvs_bootloader_example(dut: Dut) -> None: # Expect to read hooks messages and data from NVS partition dut.expect_exact('Before reading from NVS partition') diff --git a/examples/storage/nvs_rw_blob/pytest_nvs_rw_blob.py b/examples/storage/nvs_rw_blob/pytest_nvs_rw_blob.py index 78fe25a3ff..31b693496b 100644 --- a/examples/storage/nvs_rw_blob/pytest_nvs_rw_blob.py +++ b/examples/storage/nvs_rw_blob/pytest_nvs_rw_blob.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import random @@ -8,11 +8,11 @@ from typing import List import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_examples_nvs_rw_blob(dut: Dut) -> None: def expect_start_msg(index: int) -> None: dut.expect('Restart counter = {}'.format(index), timeout=10) diff --git a/examples/storage/nvs_rw_value/pytest_nvs_rw_value.py b/examples/storage/nvs_rw_value/pytest_nvs_rw_value.py index 6d918b130a..f6f2c86237 100644 --- a/examples/storage/nvs_rw_value/pytest_nvs_rw_value.py +++ b/examples/storage/nvs_rw_value/pytest_nvs_rw_value.py @@ -1,15 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging from itertools import zip_longest import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_examples_nvs_rw_value(dut: Dut) -> None: dut.serial.erase_flash() dut.serial.flash() diff --git a/examples/storage/nvs_rw_value_cxx/pytest_nvs_rw_value_cxx.py b/examples/storage/nvs_rw_value_cxx/pytest_nvs_rw_value_cxx.py index 1666d62c4d..048fddc453 100644 --- a/examples/storage/nvs_rw_value_cxx/pytest_nvs_rw_value_cxx.py +++ b/examples/storage/nvs_rw_value_cxx/pytest_nvs_rw_value_cxx.py @@ -1,15 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging from itertools import zip_longest import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_examples_nvs_rw_value_cxx(dut: Dut) -> None: dut.serial.erase_flash() dut.serial.flash() diff --git a/examples/storage/nvsgen/pytest_nvsgen_example.py b/examples/storage/nvsgen/pytest_nvsgen_example.py index dd18f2b40a..57e1007edb 100644 --- a/examples/storage/nvsgen/pytest_nvsgen_example.py +++ b/examples/storage/nvsgen/pytest_nvsgen_example.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_nvsgen_example(dut: Dut) -> None: dut.expect('Reading values from NVS', timeout=10) dut.expect('Reading values from NVS done - all OK', timeout=10) diff --git a/examples/storage/partition_api/partition_find/pytest_partition_find_example.py b/examples/storage/partition_api/partition_find/pytest_partition_find_example.py index 5121657b4c..b3ecc0a021 100644 --- a/examples/storage/partition_api/partition_find/pytest_partition_find_example.py +++ b/examples/storage/partition_api/partition_find/pytest_partition_find_example.py @@ -1,39 +1,48 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import re import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_partition_find_example(dut: Dut) -> None: def expect_partition(name: str, offset: int, size: int) -> None: - dut.expect(re.compile(str.encode("found partition '{}' at offset {:#x} with size {:#x}".format(name, offset, size))), timeout=5) + dut.expect( + re.compile(str.encode("found partition '{}' at offset {:#x} with size {:#x}".format(name, offset, size))), + timeout=5, + ) def expect_find_partition(_type: str, subtype: str, label: str, name: str, offset: int, size: int) -> None: - dut.expect(re.compile(str.encode('Find partition with type {}, subtype {}, label {}'.format(_type, subtype, label))), timeout=5) + dut.expect( + re.compile(str.encode('Find partition with type {}, subtype {}, label {}'.format(_type, subtype, label))), + timeout=5, + ) expect_partition(name, offset, size) dut.expect('----------------Find partitions---------------', timeout=20) - expect_find_partition('ESP_PARTITION_TYPE_DATA', 'ESP_PARTITION_SUBTYPE_DATA_NVS', 'NULL', - 'nvs', 0x9000, 0x6000) - expect_find_partition('ESP_PARTITION_TYPE_DATA', 'ESP_PARTITION_SUBTYPE_DATA_PHY', 'NULL', - 'phy_init', 0xf000, 0x1000) - expect_find_partition('ESP_PARTITION_TYPE_APP', 'ESP_PARTITION_SUBTYPE_APP_FACTORY', 'NULL', - 'factory', 0x10000, 0x100000) - expect_find_partition('ESP_PARTITION_TYPE_DATA', 'ESP_PARTITION_SUBTYPE_DATA_FAT', 'NULL', - 'storage1', 0x110000, 0x40000) + expect_find_partition('ESP_PARTITION_TYPE_DATA', 'ESP_PARTITION_SUBTYPE_DATA_NVS', 'NULL', 'nvs', 0x9000, 0x6000) + expect_find_partition( + 'ESP_PARTITION_TYPE_DATA', 'ESP_PARTITION_SUBTYPE_DATA_PHY', 'NULL', 'phy_init', 0xF000, 0x1000 + ) + expect_find_partition( + 'ESP_PARTITION_TYPE_APP', 'ESP_PARTITION_SUBTYPE_APP_FACTORY', 'NULL', 'factory', 0x10000, 0x100000 + ) + expect_find_partition( + 'ESP_PARTITION_TYPE_DATA', 'ESP_PARTITION_SUBTYPE_DATA_FAT', 'NULL', 'storage1', 0x110000, 0x40000 + ) dut.expect('Find second FAT partition by specifying the label', timeout=5) - expect_find_partition('ESP_PARTITION_TYPE_DATA', 'ESP_PARTITION_SUBTYPE_DATA_FAT', 'storage2', - 'storage2', 0x150000, 0x40000) + expect_find_partition( + 'ESP_PARTITION_TYPE_DATA', 'ESP_PARTITION_SUBTYPE_DATA_FAT', 'storage2', 'storage2', 0x150000, 0x40000 + ) - dut.expect('----------------Iterate through partitions---------------',timeout=5) + dut.expect('----------------Iterate through partitions---------------', timeout=5) dut.expect('Iterating through app partitions...', timeout=5) expect_partition('factory', 0x10000, 0x100000) @@ -41,7 +50,7 @@ def test_partition_find_example(dut: Dut) -> None: dut.expect('Iterating through data partitions...', timeout=5) expect_partition('nvs', 0x9000, 0x6000) - expect_partition('phy_init', 0xf000, 0x1000) + expect_partition('phy_init', 0xF000, 0x1000) expect_partition('storage1', 0x110000, 0x40000) expect_partition('storage2', 0x150000, 0x40000) diff --git a/examples/storage/partition_api/partition_mmap/pytest_partition_mmap_example.py b/examples/storage/partition_api/partition_mmap/pytest_partition_mmap_example.py index 6496365d11..87295f6c65 100644 --- a/examples/storage/partition_api/partition_mmap/pytest_partition_mmap_example.py +++ b/examples/storage/partition_api/partition_mmap/pytest_partition_mmap_example.py @@ -1,22 +1,24 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import re import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_partition_mmap_example(dut: Dut) -> None: # ESP_ERROR_CHECK or assert will cause abort on error and "Example end" won't be received - message_list = (rb'Written sample data to partition: ESP-IDF Partition Memory Map Example', - rb'Mapped partition to data memory address \S+', - rb'Read sample data from partition using mapped memory: ESP-IDF Partition Memory Map Example', - rb'Data matches', - rb'Unmapped partition from data memory', - rb'Example end') + message_list = ( + rb'Written sample data to partition: ESP-IDF Partition Memory Map Example', + rb'Mapped partition to data memory address \S+', + rb'Read sample data from partition using mapped memory: ESP-IDF Partition Memory Map Example', + rb'Data matches', + rb'Unmapped partition from data memory', + rb'Example end', + ) for msg in message_list: dut.expect(re.compile(msg), timeout=20) diff --git a/examples/storage/partition_api/partition_ops/pytest_partition_ops_example.py b/examples/storage/partition_api/partition_ops/pytest_partition_ops_example.py index 98e2789d8b..ffb8d483eb 100644 --- a/examples/storage/partition_api/partition_ops/pytest_partition_ops_example.py +++ b/examples/storage/partition_api/partition_ops/pytest_partition_ops_example.py @@ -1,20 +1,22 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import re import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_partition_ops_example(dut: Dut) -> None: # ESP_ERROR_CHECK or assert will cause abort on error and "Example end" won't be received - message_list = (rb'Written data: ESP-IDF Partition Operations Example \(Read, Erase, Write\)', - rb'Read data: ESP-IDF Partition Operations Example \(Read, Erase, Write\)', - rb'Erased data', - rb'Example end') + message_list = ( + rb'Written data: ESP-IDF Partition Operations Example \(Read, Erase, Write\)', + rb'Read data: ESP-IDF Partition Operations Example \(Read, Erase, Write\)', + rb'Erased data', + rb'Example end', + ) for msg in message_list: dut.expect(re.compile(msg), timeout=20) diff --git a/examples/storage/parttool/pytest_parttool_example.py b/examples/storage/parttool/pytest_parttool_example.py index 0f4cfc5f11..0669a418da 100644 --- a/examples/storage/parttool/pytest_parttool_example.py +++ b/examples/storage/parttool/pytest_parttool_example.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import os import subprocess @@ -6,10 +6,11 @@ import sys import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_parttool(dut: Dut) -> None: # Verify factory firmware dut.expect('Partitions Tool Example') @@ -32,10 +33,12 @@ def test_examples_parttool(dut: Dut) -> None: PARTTOOL = os.path.join(idf_path, 'components', 'partition_table', 'parttool.py') BASE_CMD = [sys.executable, PARTTOOL, '--port', dut.serial.port] - cmds = ['read_partition --partition-type=data --partition-subtype=nvs --output custom1.bin', - 'erase_partition --partition-name=custom', - 'write_partition --partition-name=custom --input custom.bin', - 'get_partition_info --partition-boot-default --info size'] + cmds = [ + 'read_partition --partition-type=data --partition-subtype=nvs --output custom1.bin', + 'erase_partition --partition-name=custom', + 'write_partition --partition-name=custom --input custom.bin', + 'get_partition_info --partition-boot-default --info size', + ] for cmd in cmds: subprocess.check_call(BASE_CMD + cmd.split()) diff --git a/examples/storage/perf_benchmark/pytest_perf_benchmark_example.py b/examples/storage/perf_benchmark/pytest_perf_benchmark_example.py index defa143f89..61b9d95ddf 100644 --- a/examples/storage/perf_benchmark/pytest_perf_benchmark_example.py +++ b/examples/storage/perf_benchmark/pytest_perf_benchmark_example.py @@ -1,19 +1,16 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32c5', 'esp32c61'], reason='not support yet') # TODO: [ESP32C5] IDF-10314 [ESP32C61] IDF-10977 +@pytest.mark.temp_skip_ci( + targets=['esp32c5', 'esp32c61'], reason='not support yet' +) # TODO: [ESP32C5] IDF-10314 [ESP32C61] IDF-10977 @pytest.mark.generic -@pytest.mark.parametrize( - 'config', - [ - 'spiflash' - ], - indirect=True -) +@pytest.mark.parametrize('config', ['spiflash'], indirect=True) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_examples_perf_benchmark_spiflash(dut: Dut) -> None: # SPI flash dut.expect('example: Mountig WL layer...', timeout=10) @@ -30,7 +27,6 @@ def test_examples_perf_benchmark_spiflash(dut: Dut) -> None: dut.expect('example: LittleFS partition unmounted', timeout=240) # SPI flash has slow write speed -@pytest.mark.esp32 @pytest.mark.sdcard_sdmode @pytest.mark.parametrize( 'config', @@ -40,6 +36,7 @@ def test_examples_perf_benchmark_spiflash(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_perf_benchmark_sdcard_sdmmc(dut: Dut) -> None: # SD card dut.expect('example: Mounting SD card - raw access', timeout=10) @@ -53,11 +50,7 @@ def test_examples_perf_benchmark_sdcard_sdmmc(dut: Dut) -> None: dut.expect('example: SD card unmounted - LittleFS', timeout=180) -@pytest.mark.esp32 @pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDFCI-2059, temporary lack runner') -@pytest.mark.esp32c3 -@pytest.mark.esp32s2 -@pytest.mark.esp32c5 @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C5 C61 GPSPI same, so testing on C5 is enough') @pytest.mark.sdcard_spimode @pytest.mark.parametrize( @@ -67,6 +60,7 @@ def test_examples_perf_benchmark_sdcard_sdmmc(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s2', 'esp32c5'], indirect=['target']) def test_examples_perf_benchmark_sdcard_spi(dut: Dut) -> None: # SD card dut.expect('example: Mounting SD card - raw access', timeout=10) diff --git a/examples/storage/sd_card/sdmmc/pytest_sdmmc_card_example.py b/examples/storage/sd_card/sdmmc/pytest_sdmmc_card_example.py index d6bbb9bb55..276e38b5fb 100644 --- a/examples/storage/sd_card/sdmmc/pytest_sdmmc_card_example.py +++ b/examples/storage/sd_card/sdmmc/pytest_sdmmc_card_example.py @@ -1,14 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import re import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.sdcard_sdmode +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_sd_card_sdmmc(dut: Dut) -> None: dut.expect('example: Initializing SD card', timeout=20) dut.expect('example: Using SDMMC peripheral', timeout=10) @@ -24,18 +25,22 @@ def test_examples_sd_card_sdmmc(dut: Dut) -> None: logging.info('Card {} {} {}MHz {} found'.format(name, _type, speed, size)) - message_list1 = ('Opening file /sdcard/hello.txt', - 'File written', - 'Renaming file /sdcard/hello.txt to /sdcard/foo.txt', - 'Reading file /sdcard/foo.txt', - "Read from file: 'Hello {}!'".format(name)) + message_list1 = ( + 'Opening file /sdcard/hello.txt', + 'File written', + 'Renaming file /sdcard/hello.txt to /sdcard/foo.txt', + 'Reading file /sdcard/foo.txt', + "Read from file: 'Hello {}!'".format(name), + ) sd_card_format = re.compile(str.encode('Formatting card, allocation unit size=\\S+')) - message_list2 = ("file doesn't exist, formatting done", - 'Opening file /sdcard/nihao.txt', - 'File written', - 'Reading file /sdcard/nihao.txt', - "Read from file: 'Nihao {}!'".format(name), - 'Card unmounted') + message_list2 = ( + "file doesn't exist, formatting done", + 'Opening file /sdcard/nihao.txt', + 'File written', + 'Reading file /sdcard/nihao.txt', + "Read from file: 'Nihao {}!'".format(name), + 'Card unmounted', + ) for msg in message_list1: dut.expect_exact(msg, timeout=30) diff --git a/examples/storage/sd_card/sdspi/pytest_sdspi_card_example.py b/examples/storage/sd_card/sdspi/pytest_sdspi_card_example.py index 4cfac08bf1..43b076d65c 100644 --- a/examples/storage/sd_card/sdspi/pytest_sdspi_card_example.py +++ b/examples/storage/sd_card/sdspi/pytest_sdspi_card_example.py @@ -1,19 +1,16 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import re import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C5 C61 GPSPI same, so testing on C5 is enough') -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.sdcard_spimode +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32c3', 'esp32p4', 'esp32c5'], indirect=['target']) def test_examples_sd_card_sdspi(dut: Dut) -> None: dut.expect('example: Initializing SD card', timeout=20) dut.expect('example: Using SPI peripheral', timeout=20) @@ -29,18 +26,22 @@ def test_examples_sd_card_sdspi(dut: Dut) -> None: logging.info('Card {} {} {}MHz {} found'.format(name, _type, speed, size)) - message_list1 = ('Opening file /sdcard/hello.txt', - 'File written', - 'Renaming file /sdcard/hello.txt to /sdcard/foo.txt', - 'Reading file /sdcard/foo.txt', - "Read from file: 'Hello {}!'".format(name)) + message_list1 = ( + 'Opening file /sdcard/hello.txt', + 'File written', + 'Renaming file /sdcard/hello.txt to /sdcard/foo.txt', + 'Reading file /sdcard/foo.txt', + "Read from file: 'Hello {}!'".format(name), + ) sd_card_format = re.compile(str.encode('Formatting card, allocation unit size=\\S+')) - message_list2 = ("file doesn't exist, formatting done", - 'Opening file /sdcard/nihao.txt', - 'File written', - 'Reading file /sdcard/nihao.txt', - "Read from file: 'Nihao {}!'".format(name), - 'Card unmounted') + message_list2 = ( + "file doesn't exist, formatting done", + 'Opening file /sdcard/nihao.txt', + 'File written', + 'Reading file /sdcard/nihao.txt', + "Read from file: 'Nihao {}!'".format(name), + 'Card unmounted', + ) for msg in message_list1: dut.expect_exact(msg, timeout=30) diff --git a/examples/storage/semihost_vfs/pytest_semihost_vfs.py b/examples/storage/semihost_vfs/pytest_semihost_vfs.py index 5317331ceb..a5dce35730 100644 --- a/examples/storage/semihost_vfs/pytest_semihost_vfs.py +++ b/examples/storage/semihost_vfs/pytest_semihost_vfs.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import os import shutil @@ -8,6 +8,7 @@ from itertools import zip_longest import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize TEMP_DIR = tempfile.mkdtemp() HOST_FILE_NAME = 'host_file.txt' @@ -24,6 +25,7 @@ def prepare() -> t.Generator[None, None, None]: @pytest.mark.jtag +@idf_parametrize('target', ['esp32'], indirect=['target']) @pytest.mark.parametrize( 'embedded_services, no_gdb, openocd_cli_args', [ @@ -31,9 +33,9 @@ def prepare() -> t.Generator[None, None, None]: 'esp,idf,jtag', 'y', f'-c \'set ESP_SEMIHOST_BASEDIR "{TEMP_DIR}"\' -f board/esp32-wrover-kit-3.3v.cfg', - marks=[pytest.mark.esp32], ), - ], ids=[ + ], + ids=[ 'esp32', ], indirect=True, diff --git a/examples/storage/spiffs/pytest_spiffs_example.py b/examples/storage/spiffs/pytest_spiffs_example.py index 19d8dcfe52..59cd7ae39e 100644 --- a/examples/storage/spiffs/pytest_spiffs_example.py +++ b/examples/storage/spiffs/pytest_spiffs_example.py @@ -1,23 +1,25 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import re import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_examples_spiffs(dut: Dut) -> None: - message_list = (rb'example: Initializing SPIFFS', - rb'example: Partition size: total: \d+, used: \d+', - rb'example: Opening file', - rb'example: File written', - rb'example: Renaming file', - rb'example: Reading file', - rb'example: Read from file: \'Hello World!\'', - rb'example: SPIFFS unmounted') + message_list = ( + rb'example: Initializing SPIFFS', + rb'example: Partition size: total: \d+, used: \d+', + rb'example: Opening file', + rb'example: File written', + rb'example: Renaming file', + rb'example: Reading file', + rb'example: Read from file: \'Hello World!\'', + rb'example: SPIFFS unmounted', + ) for msg in message_list: dut.expect(re.compile(msg), timeout=60) diff --git a/examples/storage/spiffsgen/pytest_spiffsgen_example.py b/examples/storage/spiffsgen/pytest_spiffsgen_example.py index 1394cd2f52..6b45553737 100644 --- a/examples/storage/spiffsgen/pytest_spiffsgen_example.py +++ b/examples/storage/spiffsgen/pytest_spiffsgen_example.py @@ -1,14 +1,15 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import hashlib import os import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_spiffsgen_example(dut: Dut) -> None: # Test with default build configurations base_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'spiffs_image') diff --git a/examples/storage/wear_levelling/pytest_wear_levelling_example.py b/examples/storage/wear_levelling/pytest_wear_levelling_example.py index 60b10f5e0b..90b9254507 100644 --- a/examples/storage/wear_levelling/pytest_wear_levelling_example.py +++ b/examples/storage/wear_levelling/pytest_wear_levelling_example.py @@ -1,29 +1,30 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import re import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_wear_levelling_example(dut: Dut) -> None: - - message_list = ('example: Mounting FAT filesystem', - 'example: Opening file', - 'example: File written', - 'example: Reading file', - re.compile(str.encode('example: Read from file: \'hello world, from ESP-IDF \\S+\'')), - re.compile(str.encode('vfs_fat_spiflash: Formatting FATFS partition, allocation unit size=\\S+')), - 'example: file does not exist, format done', - 'example: Opening file', - 'example: File written', - 'example: Reading file', - re.compile(str.encode('example: Read from file: \'nihao shijie, from ESP-IDF \\S+\'')), - 'example: Unmounting FAT filesystem', - 'example: Done') + message_list = ( + 'example: Mounting FAT filesystem', + 'example: Opening file', + 'example: File written', + 'example: Reading file', + re.compile(str.encode("example: Read from file: 'hello world, from ESP-IDF \\S+'")), + re.compile(str.encode('vfs_fat_spiflash: Formatting FATFS partition, allocation unit size=\\S+')), + 'example: file does not exist, format done', + 'example: Opening file', + 'example: File written', + 'example: Reading file', + re.compile(str.encode("example: Read from file: 'nihao shijie, from ESP-IDF \\S+'")), + 'example: Unmounting FAT filesystem', + 'example: Done', + ) for msg in message_list: dut.expect(msg, timeout=20) diff --git a/examples/system/base_mac_address/pytest_base_mac_address.py b/examples/system/base_mac_address/pytest_base_mac_address.py index 3d7fedb30b..2780c125f9 100644 --- a/examples/system/base_mac_address/pytest_base_mac_address.py +++ b/examples/system/base_mac_address/pytest_base_mac_address.py @@ -1,23 +1,25 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_base_mac_address(dut: Dut) -> None: def get_hex_r(num_bytes: int) -> str: return r', '.join((r'0x([0-9a-f]{1,2})',) * num_bytes) + hex_r = get_hex_r(6) dut.expect_exact('BASE_MAC: Base MAC Address read from EFUSE BLK0') mac_m = dut.expect(r'BASE_MAC: Using "' + hex_r + r'" as base MAC address', timeout=5).groups() def get_expected_mac_string(increment: int, target: str) -> str: - ''' + """ Return the string representation of the MAC address mac_m with the last octet incremented. mac_m is an array of strings in hexa-decimal format without the '0x' prefix. - ''' + """ # as a result of some esp32s2 chips burned with one MAC address by mistake, # there are some MAC address are reserved for this bug fix. # related mistake MAC address is 0x7cdfa1003000~0x7cdfa1005fff, @@ -30,9 +32,11 @@ def test_base_mac_address(dut: Dut) -> None: mac_bytes += int('1d000', 16) hex_string = f'{mac_bytes:x}' # Format the new string to match the expected output from the app (includes stripping leading zeroes) - return ', '.join('0x{}'.format(hex_string[i:i + 2].lstrip('0')) for i in range(0, len(hex_string), 2)) + return ', '.join('0x{}'.format(hex_string[i: i + 2].lstrip('0')) for i in range(0, len(hex_string), 2)) - return ', '.join(['0x{}'.format(m.decode('utf8')) for m in mac_m[:-1]] + [hex((int(mac_m[-1], 16) + increment) & 0xFF)]) + return ', '.join( + ['0x{}'.format(m.decode('utf8')) for m in mac_m[:-1]] + [hex((int(mac_m[-1], 16) + increment) & 0xFF)] + ) sdkconfig = dut.app.sdkconfig diff --git a/examples/system/console/advanced/pytest_console_advanced.py b/examples/system/console/advanced/pytest_console_advanced.py index 55ebbbc0d4..b767a21854 100644 --- a/examples/system/console/advanced/pytest_console_advanced.py +++ b/examples/system/console/advanced/pytest_console_advanced.py @@ -1,14 +1,14 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 from time import sleep import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_console_advanced(dut: Dut) -> None: sleep(2) # Some time for the OS to enumerate our USB device diff --git a/examples/system/console/basic/pytest_console_basic.py b/examples/system/console/basic/pytest_console_basic.py index 5e1c575a28..46f48a12f9 100644 --- a/examples/system/console/basic/pytest_console_basic.py +++ b/examples/system/console/basic/pytest_console_basic.py @@ -1,17 +1,20 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'history', - 'nohistory', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'history', + 'nohistory', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_console_basic(config: str, dut: Dut) -> None: if config == 'history': dut.expect('Command history enabled') diff --git a/examples/system/deep_sleep/pytest_deep_sleep.py b/examples/system/deep_sleep/pytest_deep_sleep.py index 59464b7b60..320abeaf6e 100644 --- a/examples/system/deep_sleep/pytest_deep_sleep.py +++ b/examples/system/deep_sleep/pytest_deep_sleep.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import time import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize touch_wake_up_support = ['esp32', 'esp32s2'] @@ -29,8 +30,10 @@ CONFIGS = [ ] -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', [('esp32_singlecore', 'esp32'), ('basic', 'supported_targets')], indirect=['config', 'target'] +) def test_deep_sleep(dut: Dut) -> None: def expect_enable_deep_sleep_touch() -> None: # different targets configure different wake pin(s) diff --git a/examples/system/deep_sleep_wake_stub/pytest_deep_sleep_wake_stub.py b/examples/system/deep_sleep_wake_stub/pytest_deep_sleep_wake_stub.py index 1316540278..cd0ae196c7 100644 --- a/examples/system/deep_sleep_wake_stub/pytest_deep_sleep_wake_stub.py +++ b/examples/system/deep_sleep_wake_stub/pytest_deep_sleep_wake_stub.py @@ -1,21 +1,24 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import time import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 @pytest.mark.generic -@pytest.mark.parametrize('config', ['default',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default', + ], + indirect=True, +) +@idf_parametrize( + 'target', ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32c5', 'esp32h2'], indirect=['target'] +) def test_deep_sleep_wake_stub(config: str, dut: Dut) -> None: if config == 'default': dut.expect_exact('Enabling timer wakeup, 10s', timeout=10) diff --git a/examples/system/efuse/pytest_system_efuse_example.py b/examples/system/efuse/pytest_system_efuse_example.py index 6d20510459..962b181463 100644 --- a/examples/system/efuse/pytest_system_efuse_example.py +++ b/examples/system/efuse/pytest_system_efuse_example.py @@ -1,62 +1,68 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_qemu.dut import QemuDut def basic_efuse_example(dut: Dut) -> None: dut.expect(r'example: Coding Scheme (3/4)|(NONE)|(REPEAT)|(RS \(Reed-Solomon coding\))', timeout=20) - dut.expect(['example: read efuse fields', - r'example: 1. read MAC address: {}'.format(r':'.join((r'[0-9a-f]{2}',) * 6)), - 'example: 2. read secure_version: 0', - 'example: 3. read custom fields', - 'example: module_version = 0', - 'example: device_role = None', - 'example: setting_1 = 0', - 'example: setting_2 = 0', - 'example: custom_secure_version = 0', - 'example: This example does not burn any efuse in reality only virtually', - 'example: Write operations in efuse fields are performed virtually', - 'example: write custom efuse fields', - 'efuse: Virtual efuses enabled: Not really burning eFuses', - 'example: module_version = 1', - 'example: device_role = Slave', - 'example: setting_1 = 3', - 'example: setting_2 = 4', - 'example: custom_secure_version = 5', - 'example: Done'], expect_all=True) + dut.expect( + [ + 'example: read efuse fields', + r'example: 1. read MAC address: {}'.format(r':'.join((r'[0-9a-f]{2}',) * 6)), + 'example: 2. read secure_version: 0', + 'example: 3. read custom fields', + 'example: module_version = 0', + 'example: device_role = None', + 'example: setting_1 = 0', + 'example: setting_2 = 0', + 'example: custom_secure_version = 0', + 'example: This example does not burn any efuse in reality only virtually', + 'example: Write operations in efuse fields are performed virtually', + 'example: write custom efuse fields', + 'efuse: Virtual efuses enabled: Not really burning eFuses', + 'example: module_version = 1', + 'example: device_role = Slave', + 'example: setting_1 = 3', + 'example: setting_2 = 4', + 'example: custom_secure_version = 5', + 'example: Done', + ], + expect_all=True, + ) @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 +@idf_parametrize('target', ['esp32', 'esp32c2', 'esp32c3'], indirect=['target']) def test_examples_efuse(dut: Dut) -> None: basic_efuse_example(dut) -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_examples_efuse_linux(dut: Dut) -> None: basic_efuse_example(dut) @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.parametrize('config', ['virt_flash_enc',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'virt_flash_enc', + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize( + 'target', + ['esp32', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c61', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3'], + indirect=['target'], +) def test_examples_efuse_with_virt_flash_enc(dut: Dut) -> None: # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'bootloader', 'bootloader.bin') @@ -106,9 +112,15 @@ def test_examples_efuse_with_virt_flash_enc(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.esp32s2 -@pytest.mark.parametrize('config', ['virt_flash_enc_aes_256',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'virt_flash_enc_aes_256', + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('target', ['esp32s2'], indirect=['target']) def test_examples_efuse_with_virt_flash_enc_aes_256(dut: Dut) -> None: # Only ESP32-S2 has support AES-256 FLASH_ENCRYPTION key # check and log bin size @@ -147,19 +159,20 @@ def test_examples_efuse_with_virt_flash_enc_aes_256(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.parametrize('config', ['virt_flash_enc',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'virt_flash_enc', + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize( + 'target', + ['esp32', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c61', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3'], + indirect=['target'], +) def test_examples_efuse_with_virt_flash_enc_pre_loaded(dut: Dut) -> None: - print(' - Erase flash') dut.serial.erase_flash() @@ -216,17 +229,19 @@ def test_examples_efuse_with_virt_flash_enc_pre_loaded(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.parametrize('config', ['virt_flash_enc_release',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'virt_flash_enc_release', + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize( + 'target', + ['esp32', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c61', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3'], + indirect=['target'], +) def test_examples_efuse_with_virt_flash_enc_release(dut: Dut) -> None: # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'bootloader', 'bootloader.bin') @@ -273,9 +288,15 @@ def test_examples_efuse_with_virt_flash_enc_release(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.parametrize('config', ['virt_secure_boot_v1',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'virt_secure_boot_v1', + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_efuse_with_virt_secure_boot_v1(dut: Dut) -> None: # only for ESP32 # check and log bin size @@ -321,9 +342,15 @@ def test_examples_efuse_with_virt_secure_boot_v1(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.parametrize('config', ['virt_secure_boot_v1',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'virt_secure_boot_v1', + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_efuse_with_virt_secure_boot_v1_pre_loaded(dut: Dut) -> None: print(' - Erase flash') dut.serial.erase_flash() @@ -373,10 +400,16 @@ def test_examples_efuse_with_virt_secure_boot_v1_pre_loaded(dut: Dut) -> None: dut.expect('example: Done') -@pytest.mark.esp32 @pytest.mark.esp32eco3 -@pytest.mark.parametrize('config', [('virt_secure_boot_v2'),], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + ('virt_secure_boot_v2'), + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_efuse_with_virt_secure_boot_v2(dut: Dut) -> None: # only for ESP32 ECO3 binary_file = os.path.join(dut.app.binary_path, 'bootloader', 'bootloader.bin') @@ -487,12 +520,17 @@ def test_examples_efuse_with_virt_secure_boot_v2(dut: Dut) -> None: dut.expect('example: Done') -@pytest.mark.esp32 @pytest.mark.esp32eco3 -@pytest.mark.parametrize('config', [('virt_secure_boot_v2'),], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + ('virt_secure_boot_v2'), + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_efuse_with_virt_secure_boot_v2_pre_loaded(dut: Dut) -> None: - print(' - Erase flash') dut.serial.erase_flash() print(' - Flash bootloader and app') @@ -550,18 +588,14 @@ def test_examples_efuse_with_virt_secure_boot_v2_pre_loaded(dut: Dut) -> None: dut.expect('example: Done') -@pytest.mark.esp32c3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize('config', ['virt_secure_boot_v2'], indirect=True) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize( + 'target', + ['esp32c3', 'esp32c2', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4', 'esp32s2', 'esp32s3'], + indirect=['target'], +) def test_examples_efuse_with_virt_secure_boot_v2_esp32xx(dut: Dut) -> None: # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'bootloader', 'bootloader.bin') @@ -625,18 +659,14 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx(dut: Dut) -> None: dut.expect('example: Done') -@pytest.mark.esp32c3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize('config', ['virt_secure_boot_v2'], indirect=True) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize( + 'target', + ['esp32c3', 'esp32c2', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4', 'esp32s2', 'esp32s3'], + indirect=['target'], +) def test_example_efuse_with_virt_secure_boot_v2_esp32xx_pre_loaded(dut: Dut) -> None: print(' - Erase flash') dut.serial.erase_flash() @@ -655,7 +685,12 @@ def test_example_efuse_with_virt_secure_boot_v2_esp32xx_pre_loaded(dut: Dut) -> # Resets eFuse, which enables Secure boot feature # Resets eFuses, which control digest slots if dut.app.sdkconfig.get('SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS'): - dut.serial.erase_field_on_emul_efuse_by_name(['SECURE_BOOT_EN', 'SECURE_BOOT_KEY_REVOKE0', 'SECURE_BOOT_KEY_REVOKE1', 'SECURE_BOOT_KEY_REVOKE2']) + dut.serial.erase_field_on_emul_efuse_by_name([ + 'SECURE_BOOT_EN', + 'SECURE_BOOT_KEY_REVOKE0', + 'SECURE_BOOT_KEY_REVOKE1', + 'SECURE_BOOT_KEY_REVOKE2', + ]) else: dut.serial.erase_field_on_emul_efuse_by_name(['SECURE_BOOT_EN']) @@ -701,9 +736,15 @@ def test_example_efuse_with_virt_secure_boot_v2_esp32xx_pre_loaded(dut: Dut) -> @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.parametrize('config', ['virt_sb_v1_and_fe',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'virt_sb_v1_and_fe', + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_efuse_with_virt_sb_v1_and_fe(dut: Dut) -> None: # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'bootloader', 'bootloader.bin') @@ -765,10 +806,16 @@ def test_examples_efuse_with_virt_sb_v1_and_fe(dut: Dut) -> None: dut.expect('example: Done') -@pytest.mark.esp32 @pytest.mark.esp32eco3 -@pytest.mark.parametrize('config', ['virt_sb_v2_and_fe',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'virt_sb_v2_and_fe', + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_efuse_with_virt_sb_v2_and_fe(dut: Dut) -> None: # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'bootloader', 'bootloader.bin') @@ -847,10 +894,15 @@ def test_examples_efuse_with_virt_sb_v2_and_fe(dut: Dut) -> None: dut.expect('example: Done') -@pytest.mark.esp32 @pytest.mark.host_test @pytest.mark.qemu -@pytest.mark.parametrize('config', ['virt_sb_v2_and_fe.esp32.qemu',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'virt_sb_v2_and_fe.esp32.qemu', + ], + indirect=True, +) @pytest.mark.parametrize( 'qemu_extra_args', [ @@ -860,6 +912,7 @@ def test_examples_efuse_with_virt_sb_v2_and_fe(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_efuse_with_virt_sb_v2_and_fe_qemu(dut: QemuDut) -> None: try: dut.expect('secure_boot_v2: Secure boot V2 is not enabled yet and eFuse digest keys are not set') @@ -930,17 +983,14 @@ def test_examples_efuse_with_virt_sb_v2_and_fe_qemu(dut: QemuDut) -> None: efuse_file.write(bytearray.fromhex(esp32eco3_efuses)) -@pytest.mark.esp32c3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) @pytest.mark.parametrize('config', ['virt_sb_v2_and_fe'], indirect=True) +@idf_parametrize( + 'target', + ['esp32c3', 'esp32c2', 'esp32c5', 'esp32c61', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3'], + indirect=['target'], +) def test_examples_efuse_with_virt_sb_v2_and_fe_esp32xx(dut: Dut) -> None: # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'bootloader', 'bootloader.bin') diff --git a/examples/system/esp_event/default_event_loop/pytest_esp_event_default.py b/examples/system/esp_event/default_event_loop/pytest_esp_event_default.py index 507a4ba083..15d1400210 100644 --- a/examples/system/esp_event/default_event_loop/pytest_esp_event_default.py +++ b/examples/system/esp_event/default_event_loop/pytest_esp_event_default.py @@ -1,25 +1,30 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import pytest from pytest_embedded import Dut - +from pytest_embedded_idf.utils import idf_parametrize # Timer events + TIMER_EVENT_LIMIT = 3 -TIMER_EXPIRY_HANDLING = 'TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed {} out of ' + str(TIMER_EVENT_LIMIT) + ' times' +TIMER_EXPIRY_HANDLING = ( + 'TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed {} out of ' + str(TIMER_EVENT_LIMIT) + ' times' +) # Task events TASK_ITERATION_LIMIT = 5 TASK_UNREGISTRATION_LIMIT = 3 -TASK_ITERATION_POST = 'TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, {} out of ' + str(TASK_ITERATION_LIMIT) +TASK_ITERATION_POST = 'TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, {} out of ' + str( + TASK_ITERATION_LIMIT +) TASK_ITERATION_HANDLING = 'TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed {} times' -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_default_event_loop_example_iteration_events(dut: Dut) -> None: logging.info('Checking iteration events posting and handling') dut.expect_exact('setting up') @@ -34,8 +39,13 @@ def test_default_event_loop_example_iteration_events(dut: Dut) -> None: dut.expect_exact(TASK_ITERATION_HANDLING.format(iteration)) dut.expect_exact('TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler') elif iteration == TASK_UNREGISTRATION_LIMIT: - dut.expect(['TASK_EVENTS:TASK_ITERATION_EVENT: unregistering task_iteration_handler', - 'TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler'], expect_all=True) + dut.expect( + [ + 'TASK_EVENTS:TASK_ITERATION_EVENT: unregistering task_iteration_handler', + 'TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler', + ], + expect_all=True, + ) logging.info('Unregistered handler at iteration {} out of {}'.format(iteration, TASK_ITERATION_LIMIT)) else: dut.expect_exact('TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler') @@ -46,8 +56,8 @@ def test_default_event_loop_example_iteration_events(dut: Dut) -> None: logging.info('Deleted task event source') -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_default_event_loop_example_timer_events(dut: Dut) -> None: logging.info('Checking timer events posting and handling') diff --git a/examples/system/esp_event/user_event_loops/pytest_esp_event_user.py b/examples/system/esp_event/user_event_loops/pytest_esp_event_user.py index 33275591f1..2d74ebd417 100644 --- a/examples/system/esp_event/user_event_loops/pytest_esp_event_user.py +++ b/examples/system/esp_event/user_event_loops/pytest_esp_event_user.py @@ -1,21 +1,22 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import logging import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize TASK_ITERATION_LIMIT = 10 -TASK_ITERATION_POSTING = 'posting TASK_EVENTS:TASK_ITERATION_EVENT to {}, iteration {} out of ' + str(TASK_ITERATION_LIMIT) +TASK_ITERATION_POSTING = 'posting TASK_EVENTS:TASK_ITERATION_EVENT to {}, iteration {} out of ' + str( + TASK_ITERATION_LIMIT +) TASK_ITERATION_HANDLING = 'handling TASK_EVENTS:TASK_ITERATION_EVENT from {}, iteration {}' -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_event_user_event_loops(dut: Dut) -> None: - dut.expect_exact('setting up') dut.expect_exact('starting event source') dut.expect_exact('starting application task') @@ -23,7 +24,7 @@ def test_esp_event_user_event_loops(dut: Dut) -> None: for iteration in range(1, TASK_ITERATION_LIMIT + 1): loop = None - if (iteration % 2 == 0): + if iteration % 2 == 0: loop = 'loop_with_task' else: loop = 'loop_without_task' diff --git a/examples/system/esp_timer/pytest_esp_timer.py b/examples/system/esp_timer/pytest_esp_timer.py index 98bdd1232c..b466e8176f 100644 --- a/examples/system/esp_timer/pytest_esp_timer.py +++ b/examples/system/esp_timer/pytest_esp_timer.py @@ -1,9 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize STARTING_TIMERS_REGEX = r'Started timers, time since boot: (\d+) us' @@ -27,17 +28,16 @@ LIGHT_SLEEP_TIME = 500000 ONE_SHOT_TIMER_PERIOD = 5000000 -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', [ 'rtc', ], - indirect=True + indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_timer(dut: Dut) -> None: - match = dut.expect(STARTING_TIMERS_REGEX) start_time = int(match.group(1)) logging.info('Start time: {} us'.format(start_time)) @@ -78,8 +78,7 @@ def test_esp_timer(dut: Dut) -> None: sleep_exit_time = int(match.group(1)) sleep_time = sleep_exit_time - sleep_enter_time - logging.info('Enter sleep: {}, exit sleep: {}, slept: {}'.format( - sleep_enter_time, sleep_exit_time, sleep_time)) + logging.info('Enter sleep: {}, exit sleep: {}, slept: {}'.format(sleep_enter_time, sleep_exit_time, sleep_time)) assert -2000 < sleep_time - LIGHT_SLEEP_TIME < 1000 diff --git a/examples/system/eventfd/pytest_eventfd.py b/examples/system/eventfd/pytest_eventfd.py index a192a159c0..8c6851de9c 100644 --- a/examples/system/eventfd/pytest_eventfd.py +++ b/examples/system/eventfd/pytest_eventfd.py @@ -1,16 +1,16 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import os import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_eventfd(dut: Dut) -> None: - dut.expect_exact('main_task: Calling app_main()') exp_list_5seconds = [ diff --git a/examples/system/flash_suspend/pytest_flash_suspend.py b/examples/system/flash_suspend/pytest_flash_suspend.py index 603233dc52..533b223761 100644 --- a/examples/system/flash_suspend/pytest_flash_suspend.py +++ b/examples/system/flash_suspend/pytest_flash_suspend.py @@ -1,15 +1,19 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded.dut import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c3 @pytest.mark.flash_suspend -@pytest.mark.parametrize('config', [ - 'flash_suspend', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'flash_suspend', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_flash_suspend_example(dut: Dut) -> None: dut.expect_exact('found partition') res = dut.expect(r'During Erase, ISR callback function\(in flash\) response time:\s+(\d+(\.\d{1,2})) us') diff --git a/examples/system/freertos/basic_freertos_smp_usage/pytest_smp_examples.py b/examples/system/freertos/basic_freertos_smp_usage/pytest_smp_examples.py index fa7ac3b547..c933ea0162 100644 --- a/examples/system/freertos/basic_freertos_smp_usage/pytest_smp_examples.py +++ b/examples/system/freertos/basic_freertos_smp_usage/pytest_smp_examples.py @@ -1,15 +1,13 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.generic -def test_creating_task( - dut: IdfDut -) -> None: +@idf_parametrize('target', ['esp32c3', 'esp32s3'], indirect=['target']) +def test_creating_task(dut: IdfDut) -> None: dut.expect(r'esp32(?:[a-zA-Z]\d)?>') # test creating_task dut.write('create_task') @@ -22,12 +20,9 @@ def test_creating_task( dut.expect(expected_patterns, expect_all=True) -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.generic -def test_queue( - dut: IdfDut -) -> None: +@idf_parametrize('target', ['esp32c3', 'esp32s3'], indirect=['target']) +def test_queue(dut: IdfDut) -> None: dut.expect(r'esp32(?:[a-zA-Z]\d)?>') # test queue tasks verify_amount = 5 @@ -40,12 +35,9 @@ def test_queue( dut.expect('queue example: received data = ' + str(data)) -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.generic -def test_locks( - dut: IdfDut -) -> None: +@idf_parametrize('target', ['esp32c3', 'esp32s3'], indirect=['target']) +def test_locks(dut: IdfDut) -> None: dut.expect(r'esp32(?:[a-zA-Z]\d)?>') # test locks dut.write('lock') @@ -59,12 +51,9 @@ def test_locks( dut.expect(expected_patterns, expect_all=True) -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.generic -def test_task_notification( - dut: IdfDut -) -> None: +@idf_parametrize('target', ['esp32c3', 'esp32s3'], indirect=['target']) +def test_task_notification(dut: IdfDut) -> None: dut.expect(r'esp32(?:[a-zA-Z]\d)?>') # test task notification dut.write('task_notification') @@ -73,12 +62,9 @@ def test_task_notification( dut.expect('task notify example: rcv_task is processing this task notification') -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.generic -def test_batch_proc_example( - dut: IdfDut -) -> None: +@idf_parametrize('target', ['esp32c3', 'esp32s3'], indirect=['target']) +def test_batch_proc_example(dut: IdfDut) -> None: dut.expect(r'esp32(?:[a-zA-Z]\d)?>') # test batch processing example dut.write('batch_processing') diff --git a/examples/system/freertos/real_time_stats/pytest_freertos_real_time_stats.py b/examples/system/freertos/real_time_stats/pytest_freertos_real_time_stats.py index d0dbad2d1e..2e478e5dcc 100644 --- a/examples/system/freertos/real_time_stats/pytest_freertos_real_time_stats.py +++ b/examples/system/freertos/real_time_stats/pytest_freertos_real_time_stats.py @@ -1,13 +1,12 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_freertos_real_time_stats(dut: Dut) -> None: - for _ in range(0, 3): dut.expect_exact('Real time stats obtained') diff --git a/examples/system/himem/pytest_himem.py b/examples/system/himem/pytest_himem.py index fe37860b01..99ffcbf6c2 100644 --- a/examples/system/himem/pytest_himem.py +++ b/examples/system/himem/pytest_himem.py @@ -1,16 +1,21 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_himem(dut: Dut) -> None: - - mem = dut.expect(r'esp_himem: Initialized. Using last \d+ 32KB address blocks for bank ' - r'switching on (\d+) KB of physical memory.').group(1).decode('utf8') + mem = ( + dut.expect( + r'esp_himem: Initialized. Using last \d+ 32KB address blocks for bank ' + r'switching on (\d+) KB of physical memory.' + ) + .group(1) + .decode('utf8') + ) dut.expect(r'Himem has {}KiB of memory, \d+KiB of which is free.'.format(mem), timeout=10) dut.expect_exact('Testing the free memory...') diff --git a/examples/system/ipc/ipc_isr/riscv/pytest_ipc_isr_riscv.py b/examples/system/ipc/ipc_isr/riscv/pytest_ipc_isr_riscv.py index 17e981e051..f9dbe6e042 100644 --- a/examples/system/ipc/ipc_isr/riscv/pytest_ipc_isr_riscv.py +++ b/examples/system/ipc/ipc_isr/riscv/pytest_ipc_isr_riscv.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_ipc_isr_riscv(dut: Dut) -> None: dut.expect_exact('example: Start') dut.expect_exact('example: MSTATUS = 0x11880') diff --git a/examples/system/ipc/ipc_isr/xtensa/pytest_ipc_isr_xtensa.py b/examples/system/ipc/ipc_isr/xtensa/pytest_ipc_isr_xtensa.py index 6a8ecdc40c..8795826799 100644 --- a/examples/system/ipc/ipc_isr/xtensa/pytest_ipc_isr_xtensa.py +++ b/examples/system/ipc/ipc_isr/xtensa/pytest_ipc_isr_xtensa.py @@ -1,14 +1,13 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s3'], indirect=['target']) def test_ipc_isr_xtensa(dut: Dut) -> None: - dut.expect_exact('example: Start') dut.expect_exact('example: PS_INTLEVEL = 0x5') dut.expect_exact('example: PS_EXCM = 0x0') diff --git a/examples/system/light_sleep/pytest_light_sleep.py b/examples/system/light_sleep/pytest_light_sleep.py index 698138469e..186c8db0af 100644 --- a/examples/system/light_sleep/pytest_light_sleep.py +++ b/examples/system/light_sleep/pytest_light_sleep.py @@ -1,16 +1,16 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import time import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_light_sleep(dut: Dut) -> None: - ENTERING_SLEEP_STR = 'Entering light sleep' EXIT_SLEEP_REGEX = r'Returned from light sleep, reason: (\w+), t=(\d+) ms, slept for (\d+) ms' EXIT_SLEEP_PIN_REGEX = r'Returned from light sleep, reason: (pin), t=(\d+) ms, slept for (\d+) ms' @@ -35,7 +35,11 @@ def test_light_sleep(dut: Dut) -> None: logging.info('Got second sleep period, wakeup from {}, slept for {}'.format(match.group(1), match.group(3))) # sleep time error should be less than 1ms # TODO: Need to update sleep overhead_out time for esp32c5 (PM-209) - assert match.group(1).decode('utf8') == 'timer' and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 2 and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1 + assert ( + match.group(1).decode('utf8') == 'timer' + and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 2 + and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1 + ) # this time we'll test gpio wakeup dut.expect_exact(ENTERING_SLEEP_STR) @@ -63,5 +67,9 @@ def test_light_sleep(dut: Dut) -> None: match = dut.expect(EXIT_SLEEP_REGEX) # TODO: Need to support dynamically change retention overhead for chips which support pmu (PM-232) - assert match.group(1).decode('utf8') == 'timer' and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 2 and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1 + assert ( + match.group(1).decode('utf8') == 'timer' + and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 2 + and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1 + ) logging.info('Woke up from timer again') diff --git a/examples/system/nmi_isr/pytest_nmi_isr.py b/examples/system/nmi_isr/pytest_nmi_isr.py index 7119f6023d..9380b423a1 100644 --- a/examples/system/nmi_isr/pytest_nmi_isr.py +++ b/examples/system/nmi_isr/pytest_nmi_isr.py @@ -1,13 +1,12 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target']) def test_nmi_isr(dut: Dut) -> None: dut.expect_exact('example: Start') dut.expect_exact('example: Success') diff --git a/examples/system/ota/advanced_https_ota/pytest_advanced_ota.py b/examples/system/ota/advanced_https_ota/pytest_advanced_ota.py index 3f4c9f3843..bc6c2d53ab 100644 --- a/examples/system/ota/advanced_https_ota/pytest_advanced_ota.py +++ b/examples/system/ota/advanced_https_ota/pytest_advanced_ota.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import http.server import multiprocessing @@ -16,16 +16,18 @@ import pytest from common_test_methods import get_env_config_variable from common_test_methods import get_host_ip4_by_dest_ip from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize from RangeHTTPServer import RangeRequestHandler server_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_certs/server_cert.pem') key_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_certs/server_key.pem') -def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]: +def https_request_handler() -> Callable[..., http.server.BaseHTTPRequestHandler]: """ Returns a request handler class that handles broken pipe exception """ + class RequestHandler(RangeRequestHandler): def finish(self) -> None: try: @@ -59,14 +61,25 @@ def start_https_server(ota_image_dir: str, server_ip: str, server_port: int) -> def start_chunked_server(ota_image_dir: str, server_port: int) -> subprocess.Popen: os.chdir(ota_image_dir) - chunked_server = subprocess.Popen(['openssl', 's_server', '-WWW', '-key', key_file, '-cert', server_file, '-port', str(server_port)]) + chunked_server = subprocess.Popen([ + 'openssl', + 's_server', + '-WWW', + '-key', + key_file, + '-cert', + server_file, + '-port', + str(server_port), + ]) return chunked_server -def redirect_handler_factory(url: str) -> Callable[...,http.server.BaseHTTPRequestHandler]: +def redirect_handler_factory(url: str) -> Callable[..., http.server.BaseHTTPRequestHandler]: """ Returns a request handler class that redirects to supplied `url` """ + class RedirectHandler(http.server.SimpleHTTPRequestHandler): def do_GET(self) -> None: print('Sending resp, URL: ' + url) @@ -85,7 +98,9 @@ def redirect_handler_factory(url: str) -> Callable[...,http.server.BaseHTTPReque def start_redirect_server(ota_image_dir: str, server_ip: str, server_port: int, redirection_port: int) -> None: os.chdir(ota_image_dir) - redirectHandler = redirect_handler_factory('https://' + server_ip + ':' + str(redirection_port) + '/advanced_https_ota.bin') + redirectHandler = redirect_handler_factory( + 'https://' + server_ip + ':' + str(redirection_port) + '/advanced_https_ota.bin' + ) httpd = http.server.HTTPServer((server_ip, server_port), redirectHandler) @@ -96,8 +111,8 @@ def start_redirect_server(ota_image_dir: str, server_ip: str, server_port: int, httpd.serve_forever() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example(dut: Dut) -> None: """ This is a positive test case, which downloads complete binary file multiple number of times. @@ -134,8 +149,8 @@ def test_examples_protocol_advanced_https_ota_example(dut: Dut) -> None: thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_truncated_bin(dut: Dut) -> None: """ Working of OTA if binary file is truncated is validated in this test case. @@ -185,8 +200,8 @@ def test_examples_protocol_advanced_https_ota_example_truncated_bin(dut: Dut) -> thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_truncated_header(dut: Dut) -> None: """ Working of OTA if headers of binary file are truncated is validated in this test case. @@ -236,8 +251,8 @@ def test_examples_protocol_advanced_https_ota_example_truncated_header(dut: Dut) thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_random(dut: Dut) -> None: """ Working of OTA if random data is added in binary file are validated in this test case. @@ -260,7 +275,7 @@ def test_examples_protocol_advanced_https_ota_example_random(dut: Dut) -> None: # in some cases it may generate 0xE9 which will result in failure of testcase. output_file.write(struct.pack('B', 0)) for i in range(random_bin_size - 1): - output_file.write(struct.pack('B', random.randrange(0,255,1))) + output_file.write(struct.pack('B', random.randrange(0, 255, 1))) # Start server thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port)) thread1.daemon = True @@ -287,8 +302,8 @@ def test_examples_protocol_advanced_https_ota_example_random(dut: Dut) -> None: thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_invalid_chip_id(dut: Dut) -> None: """ Working of OTA if binary file have invalid chip id is validated in this test case. @@ -311,7 +326,7 @@ def test_examples_protocol_advanced_https_ota_example_invalid_chip_id(dut: Dut) with open(binary_file, 'rb+') as f: data = list(f.read(random_bin_size)) # Changing Chip id - data[13] = 0xfe + data[13] = 0xFE with open(random_binary_file, 'wb+') as output_file: output_file.write(bytearray(data)) # Start server @@ -340,8 +355,8 @@ def test_examples_protocol_advanced_https_ota_example_invalid_chip_id(dut: Dut) thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_chunked(dut: Dut) -> None: """ This is a positive test case, which downloads complete binary file multiple number of times. @@ -376,8 +391,8 @@ def test_examples_protocol_advanced_https_ota_example_chunked(dut: Dut) -> None: chunked_server.kill() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_redirect_url(dut: Dut) -> None: """ This is a positive test case, which starts a server and a redirection server. @@ -407,9 +422,14 @@ def test_examples_protocol_advanced_https_ota_example_redirect_url(dut: Dut) -> host_ip = get_host_ip4_by_dest_ip(ip_address) thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) thread1.daemon = True - thread2 = multiprocessing.Process(target=start_redirect_server, args=(dut.app.binary_path, host_ip, redirection_server_port, redirection_server_port1)) + thread2 = multiprocessing.Process( + target=start_redirect_server, + args=(dut.app.binary_path, host_ip, redirection_server_port, redirection_server_port1), + ) thread2.daemon = True - thread3 = multiprocessing.Process(target=start_redirect_server, args=(dut.app.binary_path, host_ip, redirection_server_port1, server_port)) + thread3 = multiprocessing.Process( + target=start_redirect_server, args=(dut.app.binary_path, host_ip, redirection_server_port1, server_port) + ) thread3.daemon = True thread1.start() thread2.start() @@ -417,7 +437,9 @@ def test_examples_protocol_advanced_https_ota_example_redirect_url(dut: Dut) -> time.sleep(1) try: - print('writing to device: {}'.format('https://' + host_ip + ':' + str(redirection_server_port) + '/' + bin_name)) + print( + 'writing to device: {}'.format('https://' + host_ip + ':' + str(redirection_server_port) + '/' + bin_name) + ) dut.write('https://' + host_ip + ':' + str(redirection_server_port) + '/' + bin_name) dut.expect('upgrade successful. Rebooting ...', timeout=150) # after reboot @@ -429,10 +451,16 @@ def test_examples_protocol_advanced_https_ota_example_redirect_url(dut: Dut) -> thread3.terminate() -@pytest.mark.esp32 @pytest.mark.flash_encryption_ota -@pytest.mark.parametrize('config', ['anti_rollback',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'anti_rollback', + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_anti_rollback(dut: Dut) -> None: """ Working of OTA when anti_rollback is enabled and security version of new image is less than current one. @@ -486,7 +514,9 @@ def test_examples_protocol_advanced_https_ota_example_anti_rollback(dut: Dut) -> # Negative Case dut.expect('Starting Advanced OTA example', timeout=30) # Use modified image with secure_version=0 - print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + anti_rollback_bin_name)) + print( + 'writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + anti_rollback_bin_name) + ) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + anti_rollback_bin_name) dut.expect('New firmware security version is less than eFuse programmed, 0 < 1', timeout=30) try: @@ -497,9 +527,15 @@ def test_examples_protocol_advanced_https_ota_example_anti_rollback(dut: Dut) -> thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota -@pytest.mark.parametrize('config', ['partial_download',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'partial_download', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_partial_request(dut: Dut) -> None: """ This is a positive test case, to test OTA workflow with Range HTTP header. @@ -544,11 +580,15 @@ def test_examples_protocol_advanced_https_ota_example_partial_request(dut: Dut) thread1.terminate() -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_high_traffic -@pytest.mark.parametrize('config', ['nimble',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'nimble', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_nimble_gatts(dut: Dut) -> None: """ Run an OTA image update while a BLE GATT Server is running in background. This GATT server will be using NimBLE Host stack. @@ -595,11 +635,15 @@ def test_examples_protocol_advanced_https_ota_example_nimble_gatts(dut: Dut) -> thread1.terminate() -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_high_traffic -@pytest.mark.parametrize('config', ['bluedroid',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'bluedroid', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_bluedroid_gatts(dut: Dut) -> None: """ Run an OTA image update while a BLE GATT Server is running in background. This GATT server will be using Bluedroid Host stack. @@ -647,8 +691,8 @@ def test_examples_protocol_advanced_https_ota_example_bluedroid_gatts(dut: Dut) thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_openssl_aligned_bin(dut: Dut) -> None: """ This is a test case for esp_http_client_read with binary size multiple of 289 bytes @@ -671,7 +715,7 @@ def test_examples_protocol_advanced_https_ota_example_openssl_aligned_bin(dut: D with open(os.path.join(dut.app.binary_path, aligned_bin_name), 'wb+') as output_file: output_file.write(f.read(bin_size)) for _ in range(dummy_data_size): - output_file.write(struct.pack('B', random.randrange(0,255,1))) + output_file.write(struct.pack('B', random.randrange(0, 255, 1))) # Start server chunked_server = start_chunked_server(dut.app.binary_path, 8070) try: diff --git a/examples/system/ota/native_ota_example/pytest_native_ota.py b/examples/system/ota/native_ota_example/pytest_native_ota.py index ebf5c6d1e3..86a16f2555 100644 --- a/examples/system/ota/native_ota_example/pytest_native_ota.py +++ b/examples/system/ota/native_ota_example/pytest_native_ota.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import http.server import multiprocessing @@ -15,56 +15,61 @@ import pexpect import pytest from common_test_methods import get_host_ip4_by_dest_ip from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -server_cert = '-----BEGIN CERTIFICATE-----\n' \ - 'MIIDWDCCAkACCQCbF4+gVh/MLjANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJJ\n'\ - 'TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD\n'\ - 'VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j\n'\ - 'b20wHhcNMjEwNzEyMTIzNjI3WhcNNDEwNzA3MTIzNjI3WjBuMQswCQYDVQQGEwJJ\n'\ - 'TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD\n'\ - 'VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j\n'\ - 'b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhxF/y7bygndxPwiWL\n'\ - 'SwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQuc32W\n'\ - 'ukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2mKRbQ\n'\ - 'S5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO2fEz\n'\ - 'YaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnvL6Oz\n'\ - '3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdOAoap\n'\ - 'rFTRAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAItw24y565k3C/zENZlxyzto44ud\n'\ - 'IYPQXN8Fa2pBlLe1zlSIyuaA/rWQ+i1daS8nPotkCbWZyf5N8DYaTE4B0OfvoUPk\n'\ - 'B5uGDmbuk6akvlB5BGiYLfQjWHRsK9/4xjtIqN1H58yf3QNROuKsPAeywWS3Fn32\n'\ - '3//OpbWaClQePx6udRYMqAitKR+QxL7/BKZQsX+UyShuq8hjphvXvk0BW8ONzuw9\n'\ - 'RcoORxM0FzySYjeQvm4LhzC/P3ZBhEq0xs55aL2a76SJhq5hJy7T/Xz6NFByvlrN\n'\ - 'lFJJey33KFrAf5vnV9qcyWFIo7PYy2VsaaEjFeefr7q3sTFSMlJeadexW2Y=\n'\ - '-----END CERTIFICATE-----\n' +server_cert = ( + '-----BEGIN CERTIFICATE-----\n' + 'MIIDWDCCAkACCQCbF4+gVh/MLjANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJJ\n' + 'TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD\n' + 'VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j\n' + 'b20wHhcNMjEwNzEyMTIzNjI3WhcNNDEwNzA3MTIzNjI3WjBuMQswCQYDVQQGEwJJ\n' + 'TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD\n' + 'VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j\n' + 'b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhxF/y7bygndxPwiWL\n' + 'SwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQuc32W\n' + 'ukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2mKRbQ\n' + 'S5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO2fEz\n' + 'YaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnvL6Oz\n' + '3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdOAoap\n' + 'rFTRAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAItw24y565k3C/zENZlxyzto44ud\n' + 'IYPQXN8Fa2pBlLe1zlSIyuaA/rWQ+i1daS8nPotkCbWZyf5N8DYaTE4B0OfvoUPk\n' + 'B5uGDmbuk6akvlB5BGiYLfQjWHRsK9/4xjtIqN1H58yf3QNROuKsPAeywWS3Fn32\n' + '3//OpbWaClQePx6udRYMqAitKR+QxL7/BKZQsX+UyShuq8hjphvXvk0BW8ONzuw9\n' + 'RcoORxM0FzySYjeQvm4LhzC/P3ZBhEq0xs55aL2a76SJhq5hJy7T/Xz6NFByvlrN\n' + 'lFJJey33KFrAf5vnV9qcyWFIo7PYy2VsaaEjFeefr7q3sTFSMlJeadexW2Y=\n' + '-----END CERTIFICATE-----\n' +) -server_key = '-----BEGIN PRIVATE KEY-----\n'\ - 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhxF/y7bygndxP\n'\ - 'wiWLSwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQu\n'\ - 'c32WukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2m\n'\ - 'KRbQS5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO\n'\ - '2fEzYaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnv\n'\ - 'L6Oz3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdO\n'\ - 'AoaprFTRAgMBAAECggEAE0HCxV/N1Q1h+1OeDDGL5+74yjKSFKyb/vTVcaPCrmaH\n'\ - 'fPvp0ddOvMZJ4FDMAsiQS6/n4gQ7EKKEnYmwTqj4eUYW8yxGUn3f0YbPHbZT+Mkj\n'\ - 'z5woi3nMKi/MxCGDQZX4Ow3xUQlITUqibsfWcFHis8c4mTqdh4qj7xJzehD2PVYF\n'\ - 'gNHZsvVj6MltjBDAVwV1IlGoHjuElm6vuzkfX7phxcA1B4ZqdYY17yCXUnvui46z\n'\ - 'Xn2kUTOOUCEgfgvGa9E+l4OtdXi5IxjaSraU+dlg2KsE4TpCuN2MEVkeR5Ms3Y7Q\n'\ - 'jgJl8vlNFJDQpbFukLcYwG7rO5N5dQ6WWfVia/5XgQKBgQD74at/bXAPrh9NxPmz\n'\ - 'i1oqCHMDoM9sz8xIMZLF9YVu3Jf8ux4xVpRSnNy5RU1gl7ZXbpdgeIQ4v04zy5aw\n'\ - '8T4tu9K3XnR3UXOy25AK0q+cnnxZg3kFQm+PhtOCKEFjPHrgo2MUfnj+EDddod7N\n'\ - 'JQr9q5rEFbqHupFPpWlqCa3QmQKBgQDldWUGokNaEpmgHDMnHxiibXV5LQhzf8Rq\n'\ - 'gJIQXb7R9EsTSXEvsDyqTBb7PHp2Ko7rZ5YQfyf8OogGGjGElnPoU/a+Jij1gVFv\n'\ - 'kZ064uXAAISBkwHdcuobqc5EbG3ceyH46F+FBFhqM8KcbxJxx08objmh58+83InN\n'\ - 'P9Qr25Xw+QKBgEGXMHuMWgQbSZeM1aFFhoMvlBO7yogBTKb4Ecpu9wI5e3Kan3Al\n'\ - 'pZYltuyf+VhP6XG3IMBEYdoNJyYhu+nzyEdMg8CwXg+8LC7FMis/Ve+o7aS5scgG\n'\ - '1to/N9DK/swCsdTRdzmc/ZDbVC+TuVsebFBGYZTyO5KgqLpezqaIQrTxAoGALFCU\n'\ - '10glO9MVyl9H3clap5v+MQ3qcOv/EhaMnw6L2N6WVT481tnxjW4ujgzrFcE4YuxZ\n'\ - 'hgwYu9TOCmeqopGwBvGYWLbj+C4mfSahOAs0FfXDoYazuIIGBpuv03UhbpB1Si4O\n'\ - 'rJDfRnuCnVWyOTkl54gKJ2OusinhjztBjcrV1XkCgYEA3qNi4uBsPdyz9BZGb/3G\n'\ - 'rOMSw0CaT4pEMTLZqURmDP/0hxvTk1polP7O/FYwxVuJnBb6mzDa0xpLFPTpIAnJ\n'\ - 'YXB8xpXU69QVh+EBbemdJWOd+zp5UCfXvb2shAeG3Tn/Dz4cBBMEUutbzP+or0nG\n'\ - 'vSXnRLaxQhooWm+IuX9SuBQ=\n'\ - '-----END PRIVATE KEY-----\n' +server_key = ( + '-----BEGIN PRIVATE KEY-----\n' + 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhxF/y7bygndxP\n' + 'wiWLSwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQu\n' + 'c32WukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2m\n' + 'KRbQS5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO\n' + '2fEzYaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnv\n' + 'L6Oz3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdO\n' + 'AoaprFTRAgMBAAECggEAE0HCxV/N1Q1h+1OeDDGL5+74yjKSFKyb/vTVcaPCrmaH\n' + 'fPvp0ddOvMZJ4FDMAsiQS6/n4gQ7EKKEnYmwTqj4eUYW8yxGUn3f0YbPHbZT+Mkj\n' + 'z5woi3nMKi/MxCGDQZX4Ow3xUQlITUqibsfWcFHis8c4mTqdh4qj7xJzehD2PVYF\n' + 'gNHZsvVj6MltjBDAVwV1IlGoHjuElm6vuzkfX7phxcA1B4ZqdYY17yCXUnvui46z\n' + 'Xn2kUTOOUCEgfgvGa9E+l4OtdXi5IxjaSraU+dlg2KsE4TpCuN2MEVkeR5Ms3Y7Q\n' + 'jgJl8vlNFJDQpbFukLcYwG7rO5N5dQ6WWfVia/5XgQKBgQD74at/bXAPrh9NxPmz\n' + 'i1oqCHMDoM9sz8xIMZLF9YVu3Jf8ux4xVpRSnNy5RU1gl7ZXbpdgeIQ4v04zy5aw\n' + '8T4tu9K3XnR3UXOy25AK0q+cnnxZg3kFQm+PhtOCKEFjPHrgo2MUfnj+EDddod7N\n' + 'JQr9q5rEFbqHupFPpWlqCa3QmQKBgQDldWUGokNaEpmgHDMnHxiibXV5LQhzf8Rq\n' + 'gJIQXb7R9EsTSXEvsDyqTBb7PHp2Ko7rZ5YQfyf8OogGGjGElnPoU/a+Jij1gVFv\n' + 'kZ064uXAAISBkwHdcuobqc5EbG3ceyH46F+FBFhqM8KcbxJxx08objmh58+83InN\n' + 'P9Qr25Xw+QKBgEGXMHuMWgQbSZeM1aFFhoMvlBO7yogBTKb4Ecpu9wI5e3Kan3Al\n' + 'pZYltuyf+VhP6XG3IMBEYdoNJyYhu+nzyEdMg8CwXg+8LC7FMis/Ve+o7aS5scgG\n' + '1to/N9DK/swCsdTRdzmc/ZDbVC+TuVsebFBGYZTyO5KgqLpezqaIQrTxAoGALFCU\n' + '10glO9MVyl9H3clap5v+MQ3qcOv/EhaMnw6L2N6WVT481tnxjW4ujgzrFcE4YuxZ\n' + 'hgwYu9TOCmeqopGwBvGYWLbj+C4mfSahOAs0FfXDoYazuIIGBpuv03UhbpB1Si4O\n' + 'rJDfRnuCnVWyOTkl54gKJ2OusinhjztBjcrV1XkCgYEA3qNi4uBsPdyz9BZGb/3G\n' + 'rOMSw0CaT4pEMTLZqURmDP/0hxvTk1polP7O/FYwxVuJnBb6mzDa0xpLFPTpIAnJ\n' + 'YXB8xpXU69QVh+EBbemdJWOd+zp5UCfXvb2shAeG3Tn/Dz4cBBMEUutbzP+or0nG\n' + 'vSXnRLaxQhooWm+IuX9SuBQ=\n' + '-----END PRIVATE KEY-----\n' +) def create_file(server_file: str, file_data: str) -> None: @@ -82,10 +87,11 @@ def get_ca_cert(ota_image_dir: str) -> Tuple[str, str]: return server_file, key_file -def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]: +def https_request_handler() -> Callable[..., http.server.BaseHTTPRequestHandler]: """ Returns a request handler class that handles broken pipe exception """ + class RequestHandler(http.server.SimpleHTTPRequestHandler): def finish(self) -> None: try: @@ -119,12 +125,22 @@ def start_https_server(ota_image_dir: str, server_ip: str, server_port: int) -> def start_chunked_server(ota_image_dir: str, server_port: int) -> subprocess.Popen: server_file, key_file = get_ca_cert(ota_image_dir) - chunked_server = subprocess.Popen(['openssl', 's_server', '-WWW', '-key', key_file, '-cert', server_file, '-port', str(server_port)]) + chunked_server = subprocess.Popen([ + 'openssl', + 's_server', + '-WWW', + '-key', + key_file, + '-cert', + server_file, + '-port', + str(server_port), + ]) return chunked_server -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_native_ota_example(dut: Dut) -> None: """ This is a positive test case, which downloads complete binary file multiple number of times. @@ -162,8 +178,8 @@ def test_examples_protocol_native_ota_example(dut: Dut) -> None: thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_native_ota_example_truncated_bin(dut: Dut) -> None: """ Working of OTA if binary file is truncated is validated in this test case. @@ -212,8 +228,8 @@ def test_examples_protocol_native_ota_example_truncated_bin(dut: Dut) -> None: thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_native_ota_example_truncated_header(dut: Dut) -> None: """ Working of OTA if headers of binary file are truncated is validated in this test case. @@ -261,8 +277,8 @@ def test_examples_protocol_native_ota_example_truncated_header(dut: Dut) -> None thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_native_ota_example_random(dut: Dut) -> None: """ Working of OTA if random data is added in binary file are validated in this test case. @@ -286,7 +302,7 @@ def test_examples_protocol_native_ota_example_random(dut: Dut) -> None: with open(binary_file, 'wb+') as output_file: output_file.write(struct.pack('B', 0)) for _ in range(random_bin_size - 1): - output_file.write(struct.pack('B', random.randrange(0,255,1))) + output_file.write(struct.pack('B', random.randrange(0, 255, 1))) # Start server thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port)) thread1.daemon = True @@ -310,8 +326,8 @@ def test_examples_protocol_native_ota_example_random(dut: Dut) -> None: thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_native_ota_example_chunked(dut: Dut) -> None: """ This is a positive test case, which downloads complete binary file multiple number of times. diff --git a/examples/system/ota/otatool/pytest_otatool.py b/examples/system/ota/otatool/pytest_otatool.py index a8fe39976a..428fc9d25f 100644 --- a/examples/system/ota/otatool/pytest_otatool.py +++ b/examples/system/ota/otatool/pytest_otatool.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import os import subprocess @@ -6,12 +6,21 @@ import sys import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.parametrize('config', [ - pytest.param('default', marks=[pytest.mark.supported_targets, pytest.mark.generic, pytest.mark.temp_skip(targets=['esp32c2'], reason='must have 4MB')]), - pytest.param('default', marks=[pytest.mark.esp32c2, pytest.mark.generic, pytest.mark.flash_4mb]), -], indirect=True) +@idf_parametrize('config', ['default'], indirect=['config']) +@idf_parametrize( + 'target,markers', + [ + ( + 'supported_targets', + (pytest.mark.temp_skip(targets=['esp32c2'], reason='must have 4MB'), pytest.mark.generic), + ), + ('esp32c2', (pytest.mark.generic, pytest.mark.flash_4mb)), + ], + indirect=['target'], +) def test_otatool_example(dut: Dut) -> None: # Verify factory firmware dut.expect('OTA Tool Example') diff --git a/examples/system/ota/pre_encrypted_ota/pytest_pre_encrypted_ota.py b/examples/system/ota/pre_encrypted_ota/pytest_pre_encrypted_ota.py index c232173574..31460bec9f 100644 --- a/examples/system/ota/pre_encrypted_ota/pytest_pre_encrypted_ota.py +++ b/examples/system/ota/pre_encrypted_ota/pytest_pre_encrypted_ota.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import http.server import multiprocessing @@ -11,6 +11,7 @@ import pexpect import pytest from common_test_methods import get_host_ip4_by_dest_ip from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize from RangeHTTPServer import RangeRequestHandler server_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'server_certs/ca_cert.pem') @@ -18,10 +19,11 @@ key_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'server_cert enc_bin_name = 'pre_encrypted_ota_secure.bin' -def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]: +def https_request_handler() -> Callable[..., http.server.BaseHTTPRequestHandler]: """ Returns a request handler class that handles broken pipe exception """ + class RequestHandler(RangeRequestHandler): def finish(self) -> None: try: @@ -53,8 +55,8 @@ def start_https_server(ota_image_dir: str, server_ip: str, server_port: int) -> httpd.serve_forever() -@pytest.mark.esp32 @pytest.mark.ethernet_ota +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_pre_encrypted_ota_example(dut: Dut) -> None: server_port = 8001 # Start server @@ -82,9 +84,15 @@ def test_examples_protocol_pre_encrypted_ota_example(dut: Dut) -> None: thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota -@pytest.mark.parametrize('config', ['partial_download',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'partial_download', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_pre_encrypted_ota_example_partial_request(dut: Dut) -> None: server_port = 8001 # Size of partial HTTP request diff --git a/examples/system/ota/simple_ota_example/pytest_simple_ota.py b/examples/system/ota/simple_ota_example/pytest_simple_ota.py index 43b4f50f8e..365f671360 100644 --- a/examples/system/ota/simple_ota_example/pytest_simple_ota.py +++ b/examples/system/ota/simple_ota_example/pytest_simple_ota.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import http.server import multiprocessing @@ -13,6 +13,7 @@ from typing import Tuple import pexpect import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize try: from common_test_methods import get_env_config_variable, get_host_ip4_by_dest_ip @@ -21,61 +22,71 @@ except ModuleNotFoundError: sys.path.insert(0, idf_path + '/tools/ci/python_packages') from common_test_methods import get_env_config_variable, get_host_ip4_by_dest_ip -server_cert = '-----BEGIN CERTIFICATE-----\n' \ - 'MIIDWDCCAkACCQCbF4+gVh/MLjANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJJ\n'\ - 'TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD\n'\ - 'VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j\n'\ - 'b20wHhcNMjEwNzEyMTIzNjI3WhcNNDEwNzA3MTIzNjI3WjBuMQswCQYDVQQGEwJJ\n'\ - 'TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD\n'\ - 'VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j\n'\ - 'b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhxF/y7bygndxPwiWL\n'\ - 'SwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQuc32W\n'\ - 'ukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2mKRbQ\n'\ - 'S5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO2fEz\n'\ - 'YaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnvL6Oz\n'\ - '3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdOAoap\n'\ - 'rFTRAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAItw24y565k3C/zENZlxyzto44ud\n'\ - 'IYPQXN8Fa2pBlLe1zlSIyuaA/rWQ+i1daS8nPotkCbWZyf5N8DYaTE4B0OfvoUPk\n'\ - 'B5uGDmbuk6akvlB5BGiYLfQjWHRsK9/4xjtIqN1H58yf3QNROuKsPAeywWS3Fn32\n'\ - '3//OpbWaClQePx6udRYMqAitKR+QxL7/BKZQsX+UyShuq8hjphvXvk0BW8ONzuw9\n'\ - 'RcoORxM0FzySYjeQvm4LhzC/P3ZBhEq0xs55aL2a76SJhq5hJy7T/Xz6NFByvlrN\n'\ - 'lFJJey33KFrAf5vnV9qcyWFIo7PYy2VsaaEjFeefr7q3sTFSMlJeadexW2Y=\n'\ - '-----END CERTIFICATE-----\n' +server_cert = ( + '-----BEGIN CERTIFICATE-----\n' + 'MIIDWDCCAkACCQCbF4+gVh/MLjANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJJ\n' + 'TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD\n' + 'VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j\n' + 'b20wHhcNMjEwNzEyMTIzNjI3WhcNNDEwNzA3MTIzNjI3WjBuMQswCQYDVQQGEwJJ\n' + 'TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD\n' + 'VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j\n' + 'b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhxF/y7bygndxPwiWL\n' + 'SwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQuc32W\n' + 'ukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2mKRbQ\n' + 'S5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO2fEz\n' + 'YaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnvL6Oz\n' + '3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdOAoap\n' + 'rFTRAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAItw24y565k3C/zENZlxyzto44ud\n' + 'IYPQXN8Fa2pBlLe1zlSIyuaA/rWQ+i1daS8nPotkCbWZyf5N8DYaTE4B0OfvoUPk\n' + 'B5uGDmbuk6akvlB5BGiYLfQjWHRsK9/4xjtIqN1H58yf3QNROuKsPAeywWS3Fn32\n' + '3//OpbWaClQePx6udRYMqAitKR+QxL7/BKZQsX+UyShuq8hjphvXvk0BW8ONzuw9\n' + 'RcoORxM0FzySYjeQvm4LhzC/P3ZBhEq0xs55aL2a76SJhq5hJy7T/Xz6NFByvlrN\n' + 'lFJJey33KFrAf5vnV9qcyWFIo7PYy2VsaaEjFeefr7q3sTFSMlJeadexW2Y=\n' + '-----END CERTIFICATE-----\n' +) -server_key = '-----BEGIN PRIVATE KEY-----\n'\ - 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhxF/y7bygndxP\n'\ - 'wiWLSwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQu\n'\ - 'c32WukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2m\n'\ - 'KRbQS5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO\n'\ - '2fEzYaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnv\n'\ - 'L6Oz3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdO\n'\ - 'AoaprFTRAgMBAAECggEAE0HCxV/N1Q1h+1OeDDGL5+74yjKSFKyb/vTVcaPCrmaH\n'\ - 'fPvp0ddOvMZJ4FDMAsiQS6/n4gQ7EKKEnYmwTqj4eUYW8yxGUn3f0YbPHbZT+Mkj\n'\ - 'z5woi3nMKi/MxCGDQZX4Ow3xUQlITUqibsfWcFHis8c4mTqdh4qj7xJzehD2PVYF\n'\ - 'gNHZsvVj6MltjBDAVwV1IlGoHjuElm6vuzkfX7phxcA1B4ZqdYY17yCXUnvui46z\n'\ - 'Xn2kUTOOUCEgfgvGa9E+l4OtdXi5IxjaSraU+dlg2KsE4TpCuN2MEVkeR5Ms3Y7Q\n'\ - 'jgJl8vlNFJDQpbFukLcYwG7rO5N5dQ6WWfVia/5XgQKBgQD74at/bXAPrh9NxPmz\n'\ - 'i1oqCHMDoM9sz8xIMZLF9YVu3Jf8ux4xVpRSnNy5RU1gl7ZXbpdgeIQ4v04zy5aw\n'\ - '8T4tu9K3XnR3UXOy25AK0q+cnnxZg3kFQm+PhtOCKEFjPHrgo2MUfnj+EDddod7N\n'\ - 'JQr9q5rEFbqHupFPpWlqCa3QmQKBgQDldWUGokNaEpmgHDMnHxiibXV5LQhzf8Rq\n'\ - 'gJIQXb7R9EsTSXEvsDyqTBb7PHp2Ko7rZ5YQfyf8OogGGjGElnPoU/a+Jij1gVFv\n'\ - 'kZ064uXAAISBkwHdcuobqc5EbG3ceyH46F+FBFhqM8KcbxJxx08objmh58+83InN\n'\ - 'P9Qr25Xw+QKBgEGXMHuMWgQbSZeM1aFFhoMvlBO7yogBTKb4Ecpu9wI5e3Kan3Al\n'\ - 'pZYltuyf+VhP6XG3IMBEYdoNJyYhu+nzyEdMg8CwXg+8LC7FMis/Ve+o7aS5scgG\n'\ - '1to/N9DK/swCsdTRdzmc/ZDbVC+TuVsebFBGYZTyO5KgqLpezqaIQrTxAoGALFCU\n'\ - '10glO9MVyl9H3clap5v+MQ3qcOv/EhaMnw6L2N6WVT481tnxjW4ujgzrFcE4YuxZ\n'\ - 'hgwYu9TOCmeqopGwBvGYWLbj+C4mfSahOAs0FfXDoYazuIIGBpuv03UhbpB1Si4O\n'\ - 'rJDfRnuCnVWyOTkl54gKJ2OusinhjztBjcrV1XkCgYEA3qNi4uBsPdyz9BZGb/3G\n'\ - 'rOMSw0CaT4pEMTLZqURmDP/0hxvTk1polP7O/FYwxVuJnBb6mzDa0xpLFPTpIAnJ\n'\ - 'YXB8xpXU69QVh+EBbemdJWOd+zp5UCfXvb2shAeG3Tn/Dz4cBBMEUutbzP+or0nG\n'\ - 'vSXnRLaxQhooWm+IuX9SuBQ=\n'\ - '-----END PRIVATE KEY-----\n' +server_key = ( + '-----BEGIN PRIVATE KEY-----\n' + 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhxF/y7bygndxP\n' + 'wiWLSwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQu\n' + 'c32WukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2m\n' + 'KRbQS5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO\n' + '2fEzYaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnv\n' + 'L6Oz3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdO\n' + 'AoaprFTRAgMBAAECggEAE0HCxV/N1Q1h+1OeDDGL5+74yjKSFKyb/vTVcaPCrmaH\n' + 'fPvp0ddOvMZJ4FDMAsiQS6/n4gQ7EKKEnYmwTqj4eUYW8yxGUn3f0YbPHbZT+Mkj\n' + 'z5woi3nMKi/MxCGDQZX4Ow3xUQlITUqibsfWcFHis8c4mTqdh4qj7xJzehD2PVYF\n' + 'gNHZsvVj6MltjBDAVwV1IlGoHjuElm6vuzkfX7phxcA1B4ZqdYY17yCXUnvui46z\n' + 'Xn2kUTOOUCEgfgvGa9E+l4OtdXi5IxjaSraU+dlg2KsE4TpCuN2MEVkeR5Ms3Y7Q\n' + 'jgJl8vlNFJDQpbFukLcYwG7rO5N5dQ6WWfVia/5XgQKBgQD74at/bXAPrh9NxPmz\n' + 'i1oqCHMDoM9sz8xIMZLF9YVu3Jf8ux4xVpRSnNy5RU1gl7ZXbpdgeIQ4v04zy5aw\n' + '8T4tu9K3XnR3UXOy25AK0q+cnnxZg3kFQm+PhtOCKEFjPHrgo2MUfnj+EDddod7N\n' + 'JQr9q5rEFbqHupFPpWlqCa3QmQKBgQDldWUGokNaEpmgHDMnHxiibXV5LQhzf8Rq\n' + 'gJIQXb7R9EsTSXEvsDyqTBb7PHp2Ko7rZ5YQfyf8OogGGjGElnPoU/a+Jij1gVFv\n' + 'kZ064uXAAISBkwHdcuobqc5EbG3ceyH46F+FBFhqM8KcbxJxx08objmh58+83InN\n' + 'P9Qr25Xw+QKBgEGXMHuMWgQbSZeM1aFFhoMvlBO7yogBTKb4Ecpu9wI5e3Kan3Al\n' + 'pZYltuyf+VhP6XG3IMBEYdoNJyYhu+nzyEdMg8CwXg+8LC7FMis/Ve+o7aS5scgG\n' + '1to/N9DK/swCsdTRdzmc/ZDbVC+TuVsebFBGYZTyO5KgqLpezqaIQrTxAoGALFCU\n' + '10glO9MVyl9H3clap5v+MQ3qcOv/EhaMnw6L2N6WVT481tnxjW4ujgzrFcE4YuxZ\n' + 'hgwYu9TOCmeqopGwBvGYWLbj+C4mfSahOAs0FfXDoYazuIIGBpuv03UhbpB1Si4O\n' + 'rJDfRnuCnVWyOTkl54gKJ2OusinhjztBjcrV1XkCgYEA3qNi4uBsPdyz9BZGb/3G\n' + 'rOMSw0CaT4pEMTLZqURmDP/0hxvTk1polP7O/FYwxVuJnBb6mzDa0xpLFPTpIAnJ\n' + 'YXB8xpXU69QVh+EBbemdJWOd+zp5UCfXvb2shAeG3Tn/Dz4cBBMEUutbzP+or0nG\n' + 'vSXnRLaxQhooWm+IuX9SuBQ=\n' + '-----END PRIVATE KEY-----\n' +) OTA_0_ADDRESS = '0x20000' OTA_1_ADDRESS = '0x1d0000' -def start_https_server(ota_image_dir: str, server_ip: str, server_port: int, server_file: Optional[str] = None, key_file: Optional[str] = None) -> None: +def start_https_server( + ota_image_dir: str, + server_ip: str, + server_port: int, + server_file: Optional[str] = None, + key_file: Optional[str] = None, +) -> None: os.chdir(ota_image_dir) if server_file is None: @@ -111,7 +122,18 @@ def start_tls1_3_server(ota_image_dir: str, server_port: int) -> subprocess.Pope key_file_handle.write(server_key) key_file_handle.close() - chunked_server = subprocess.Popen(['openssl', 's_server', '-tls1_3', '-WWW', '-key', key_file, '-cert', server_file, '-port', str(server_port)]) + chunked_server = subprocess.Popen([ + 'openssl', + 's_server', + '-tls1_3', + '-WWW', + '-key', + key_file, + '-cert', + server_file, + '-port', + str(server_port), + ]) return chunked_server @@ -148,10 +170,8 @@ def setting_connection(dut: Dut, env_name: Optional[str] = None) -> Any: return get_host_ip4_by_dest_ip(ip_address) -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_high_traffic +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_protocol_simple_ota_example(dut: Dut) -> None: """ steps: | @@ -183,9 +203,15 @@ def test_examples_protocol_simple_ota_example(dut: Dut) -> None: thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota -@pytest.mark.parametrize('config', ['spiram',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'spiram', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_simple_ota_example_ethernet_with_spiram_config(dut: Dut) -> None: """ steps: | @@ -212,12 +238,17 @@ def test_examples_protocol_simple_ota_example_ethernet_with_spiram_config(dut: D thread1.terminate() -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.flash_encryption_wifi_high_traffic @pytest.mark.nightly_run -@pytest.mark.parametrize('config', ['flash_enc_wifi',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'flash_enc_wifi', + ], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Dut) -> None: """ steps: | @@ -242,7 +273,11 @@ def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Du dut.expect(f'Loaded app from partition at offset {FACTORY_ADDRESS}', timeout=30) dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10) # Parse IP address of STA - env_name = 'flash_encryption_wifi_high_traffic' if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True else None + env_name = ( + 'flash_encryption_wifi_high_traffic' + if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True + else None + ) host_ip = setting_connection(dut, env_name) dut.expect('Starting OTA example task', timeout=30) @@ -257,10 +292,18 @@ def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Du thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota -@pytest.mark.parametrize('config', ['on_update_no_sb_ecdsa',], indirect=True) -def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_update_no_secure_boot_ecdsa(dut: Dut) -> None: +@pytest.mark.parametrize( + 'config', + [ + 'on_update_no_sb_ecdsa', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) +def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_update_no_secure_boot_ecdsa( + dut: Dut, +) -> None: """ steps: | 1. join AP/Ethernet @@ -293,9 +336,15 @@ def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_updat thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota -@pytest.mark.parametrize('config', ['on_update_no_sb_rsa',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'on_update_no_sb_rsa', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_update_no_secure_boot_rsa(dut: Dut) -> None: """ steps: | @@ -332,9 +381,15 @@ def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_updat thread1.terminate() -@pytest.mark.esp32 @pytest.mark.ethernet_ota -@pytest.mark.parametrize('config', ['tls1_3',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'tls1_3', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_simple_ota_example_tls1_3(dut: Dut) -> None: """ steps: | @@ -365,7 +420,6 @@ def test_examples_protocol_simple_ota_example_tls1_3(dut: Dut) -> None: tls1_3_server.kill() -@pytest.mark.esp32 @pytest.mark.ethernet_ota @pytest.mark.parametrize( 'config', @@ -374,6 +428,7 @@ def test_examples_protocol_simple_ota_example_tls1_3(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_simple_ota_example_tls1_2_dynamic(dut: Dut) -> None: """ steps: | @@ -406,13 +461,17 @@ def test_examples_protocol_simple_ota_example_tls1_2_dynamic(dut: Dut) -> None: if __name__ == '__main__': - if sys.argv[2:]: # if two or more arguments provided: + if sys.argv[2:]: # if two or more arguments provided: # Usage: pytest_simple_ota.py [cert_dir] this_dir = os.path.dirname(os.path.realpath(__file__)) bin_dir = os.path.join(this_dir, sys.argv[1]) port = int(sys.argv[2]) cert_dir = bin_dir if not sys.argv[3:] else os.path.join(this_dir, sys.argv[3]) # optional argument print(f'Starting HTTPS server at "https://0.0.0.0:{port}"') - start_https_server(bin_dir, '', port, - server_file=os.path.join(cert_dir, 'ca_cert.pem'), - key_file=os.path.join(cert_dir, 'ca_key.pem')) + start_https_server( + bin_dir, + '', + port, + server_file=os.path.join(cert_dir, 'ca_cert.pem'), + key_file=os.path.join(cert_dir, 'ca_key.pem'), + ) diff --git a/examples/system/perfmon/pytest_perfmon.py b/examples/system/perfmon/pytest_perfmon.py index ca3142411a..9f19e5885f 100644 --- a/examples/system/perfmon/pytest_perfmon.py +++ b/examples/system/perfmon/pytest_perfmon.py @@ -1,16 +1,13 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target']) def test_perfmon(dut: Dut) -> None: - dut.expect('example: Start') dut.expect('example: Start test with printing all available statistic') dut.expect('example: Start test with user defined statistic') diff --git a/examples/system/pthread/pytest_pthread.py b/examples/system/pthread/pytest_pthread.py index 2852bb1039..5ef80d000b 100644 --- a/examples/system/pthread/pytest_pthread.py +++ b/examples/system/pthread/pytest_pthread.py @@ -1,14 +1,13 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_pthread(dut: Dut) -> None: - # Note: this test doesn't really confirm anything, except that threads are created # and stdout is not being corrupted by multiple threads printing ot it. dut.expect(r'Created thread 0x[\da-f]+') diff --git a/examples/system/rt_mqueue/pytest_rt_mqueue.py b/examples/system/rt_mqueue/pytest_rt_mqueue.py index 893553de85..a926be6ced 100644 --- a/examples/system/rt_mqueue/pytest_rt_mqueue.py +++ b/examples/system/rt_mqueue/pytest_rt_mqueue.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_rt_mqueue_example(dut: Dut) -> None: dut.expect_exact('sending: 0') dut.expect_exact('received: 0') diff --git a/examples/system/select/pytest_select.py b/examples/system/select/pytest_select.py index 367739d8eb..f6854c15ec 100644 --- a/examples/system/select/pytest_select.py +++ b/examples/system/select/pytest_select.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import os @@ -6,24 +6,28 @@ from typing import List import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def get_socket_msgs(i: int) -> List[str]: msg = 'Socket message S{}'.format(i) - return ['uart_select_example: {} bytes were written to socket: {}'.format(len(msg), msg), - 'uart_select_example: {} bytes were received through socket: {}'.format(len(msg), msg)] + return [ + 'uart_select_example: {} bytes were written to socket: {}'.format(len(msg), msg), + 'uart_select_example: {} bytes were received through socket: {}'.format(len(msg), msg), + ] def get_uart_msgs(i: int) -> List[str]: msg = 'UART message U{}'.format(i) - return ['uart_select_example: {} bytes were sent to UART1: {}'.format(len(msg), msg), - 'uart_select_example: {} bytes were received through UART1: {}'.format(len(msg), msg)] + return [ + 'uart_select_example: {} bytes were sent to UART1: {}'.format(len(msg), msg), + 'uart_select_example: {} bytes were received through UART1: {}'.format(len(msg), msg), + ] -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_examples_select(dut: Dut) -> None: - dut.expect_exact('main_task: Calling app_main()', timeout=30) exp_list = [] diff --git a/examples/system/startup_time/pytest_startup_time.py b/examples/system/startup_time/pytest_startup_time.py index a2eff33822..ffe16e94b1 100644 --- a/examples/system/startup_time/pytest_startup_time.py +++ b/examples/system/startup_time/pytest_startup_time.py @@ -1,19 +1,23 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'defaults', - 'always_skip', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'defaults', + 'always_skip', + ], + indirect=True, +) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_startup_time_example(dut: Dut) -> None: - res = dut.expect(r'\((\d+)\) [^:]+: App started!') time = int(res[1]) diff --git a/examples/system/sysview_tracing_heap_log/pytest_sysview_tracing_heap_log.py b/examples/system/sysview_tracing_heap_log/pytest_sysview_tracing_heap_log.py index ccd0339101..6e65fc14f2 100644 --- a/examples/system/sysview_tracing_heap_log/pytest_sysview_tracing_heap_log.py +++ b/examples/system/sysview_tracing_heap_log/pytest_sysview_tracing_heap_log.py @@ -52,7 +52,8 @@ def _test_examples_sysview_tracing_heap_log(openocd_dut: 'OpenOCD', idf_path: st with open(gdb_logfile, encoding='utf-8') as fr: # pylint: disable=protected-access gdb_pexpect_proc = pexpect.fdpexpect.fdspawn(fr.fileno()) gdb_pexpect_proc.expect_exact( - 'Thread 2 "main" hit Temporary breakpoint 1, heap_trace_start (mode_param', timeout=10) # should be (mode_param=HEAP_TRACE_ALL) # TODO GCC-329 + 'Thread 2 "main" hit Temporary breakpoint 1, heap_trace_start (mode_param', timeout=10 + ) # should be (mode_param=HEAP_TRACE_ALL) # TODO GCC-329 gdb_pexpect_proc.expect_exact('Thread 2 "main" hit Temporary breakpoint 2, heap_trace_stop ()', timeout=10) diff --git a/examples/system/task_watchdog/pytest_task_watchdog.py b/examples/system/task_watchdog/pytest_task_watchdog.py index 0627967675..45b04e22bd 100644 --- a/examples/system/task_watchdog/pytest_task_watchdog.py +++ b/examples/system/task_watchdog/pytest_task_watchdog.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_task_watchdog(dut: Dut) -> None: - dut.expect_exact('Example complete') diff --git a/examples/system/ulp/lp_core/build_system/pytest_lp_core_build_sys.py b/examples/system/ulp/lp_core/build_system/pytest_lp_core_build_sys.py index b472914316..d2a14a0153 100644 --- a/examples/system/ulp/lp_core/build_system/pytest_lp_core_build_sys.py +++ b/examples/system/ulp/lp_core/build_system/pytest_lp_core_build_sys.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4'], indirect=['target']) def test_lp_core_build_sys(dut: IdfDut) -> None: dut.expect('Sum calculated by ULP using external library func: 11') diff --git a/examples/system/ulp/lp_core/gpio_intr_pulse_counter/pytest_lp_core_pcnt.py b/examples/system/ulp/lp_core/gpio_intr_pulse_counter/pytest_lp_core_pcnt.py index a4d8c0c2e4..3b89bb5ce8 100644 --- a/examples/system/ulp/lp_core/gpio_intr_pulse_counter/pytest_lp_core_pcnt.py +++ b/examples/system/ulp/lp_core/gpio_intr_pulse_counter/pytest_lp_core_pcnt.py @@ -1,19 +1,18 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c6 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32c6', 'esp32p4'], indirect=['target']) def test_lp_core_pcnt(dut: Dut) -> None: - res = dut.expect(r'ULP will wake up processor after every (\d+) pulses') wakeup_limit = res.group(1).decode('utf-8') - assert (int(wakeup_limit) > 0) + assert int(wakeup_limit) > 0 logging.info(f'Wake-up limit: {wakeup_limit} pulses') dut.expect_exact('Not a ULP wakeup, initializing it!') @@ -27,4 +26,4 @@ def test_lp_core_pcnt(dut: Dut) -> None: # Check that pulse count is correct, we could have gotten pulses between triggering # the wakeup signal and printing the count, but it should at be equal to or greater - assert (int(pulse_count) >= int(wakeup_limit)) + assert int(pulse_count) >= int(wakeup_limit) diff --git a/examples/system/ulp/lp_core/inter_cpu_critical_section/pytest_lp_core_critical_section.py b/examples/system/ulp/lp_core/inter_cpu_critical_section/pytest_lp_core_critical_section.py index e67f1b9aaf..f0a5508f16 100644 --- a/examples/system/ulp/lp_core/inter_cpu_critical_section/pytest_lp_core_critical_section.py +++ b/examples/system/ulp/lp_core/inter_cpu_critical_section/pytest_lp_core_critical_section.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 @pytest.mark.generic +@idf_parametrize('target', ['esp32c5', 'esp32c6'], indirect=['target']) def test_lp_core_critical_section_main_1_task(dut: Dut) -> None: dut.expect("LP CPU's increment starts, shared counter = 0") dut.expect(r'core 0 started, cnt = \d+') @@ -14,8 +14,8 @@ def test_lp_core_critical_section_main_1_task(dut: Dut) -> None: dut.expect('increment ends, shared counter = 200000') -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_lp_core_critical_section_main_2_tasks(dut: Dut) -> None: dut.expect("LP CPU's increment starts, shared counter = 0") dut.expect(r'core 0 started, cnt = \d+') diff --git a/examples/system/ulp/lp_core/interrupt/pytest_lp_core_intr.py b/examples/system/ulp/lp_core/interrupt/pytest_lp_core_intr.py index 3dbcc88c8e..4e043b1a59 100644 --- a/examples/system/ulp/lp_core/interrupt/pytest_lp_core_intr.py +++ b/examples/system/ulp/lp_core/interrupt/pytest_lp_core_intr.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4'], indirect=['target']) def test_lp_core_intr(dut: Dut) -> None: dut.expect('Triggered 10 interrupts on the LP-Core, LP-Core received 10 interrupts') diff --git a/examples/system/ulp/ulp_fsm/ulp/pytest_ulp_fsm.py b/examples/system/ulp/ulp_fsm/ulp/pytest_ulp_fsm.py index e577ad4a57..0efdefeec1 100644 --- a/examples/system/ulp/ulp_fsm/ulp/pytest_ulp_fsm.py +++ b/examples/system/ulp/ulp_fsm/ulp/pytest_ulp_fsm.py @@ -1,17 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import logging import time import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target']) def test_example_ulp_fsm(dut: Dut) -> None: dut.expect_exact('Not ULP wakeup') dut.expect_exact('Entering deep sleep') @@ -30,8 +28,9 @@ def test_example_ulp_fsm(dut: Dut) -> None: dut.expect_exact('ULP wakeup, saving pulse count', timeout=5) logging.info('Woke up...') init_count = int(dut.expect(r'Read pulse count from NVS:\s+(\d+)', timeout=5).group(1), 10) - assert nvs_value in (init_count, None), ('Read count is {} and previously written value is {}' - ''.format(init_count, nvs_value)) + assert nvs_value in (init_count, None), 'Read count is {} and previously written value is {}'.format( + init_count, nvs_value + ) inc = int(dut.expect(r'Pulse count from ULP:\s+(\d+)', timeout=5).group(1), 10) assert inc in (5, 6), 'pulse count is {}'.format(inc) diff --git a/examples/system/ulp/ulp_fsm/ulp_adc/pytest_ulp_fsm_adc.py b/examples/system/ulp/ulp_fsm/ulp_adc/pytest_ulp_fsm_adc.py index d703c4fb1f..2dcc689de7 100644 --- a/examples/system/ulp/ulp_fsm/ulp_adc/pytest_ulp_fsm_adc.py +++ b/examples/system/ulp/ulp_fsm/ulp_adc/pytest_ulp_fsm_adc.py @@ -1,17 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import logging import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s3'], indirect=['target']) def test_example_ulp_fsm_adc(dut: Dut) -> None: - dut.expect_exact('Not ULP wakeup') dut.expect_exact('Entering deep sleep') diff --git a/examples/system/ulp/ulp_riscv/gpio/pytest_ulp_riscv_gpio.py b/examples/system/ulp/ulp_riscv/gpio/pytest_ulp_riscv_gpio.py index e4b41cb2e0..2bd4c02ac3 100644 --- a/examples/system/ulp/ulp_riscv/gpio/pytest_ulp_riscv_gpio.py +++ b/examples/system/ulp/ulp_riscv/gpio/pytest_ulp_riscv_gpio.py @@ -1,18 +1,16 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import time import pexpect import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_ulp_riscv_gpio(dut: Dut) -> None: - dut.expect_exact('Not a ULP-RISC-V wakeup, initializing it!') dut.expect_exact('Entering in deep sleep') diff --git a/examples/system/ulp/ulp_riscv/interrupts/pytest_ulp_riscv_interrupts.py b/examples/system/ulp/ulp_riscv/interrupts/pytest_ulp_riscv_interrupts.py index c0bf9928ae..7420d983d9 100644 --- a/examples/system/ulp/ulp_riscv/interrupts/pytest_ulp_riscv_interrupts.py +++ b/examples/system/ulp/ulp_riscv/interrupts/pytest_ulp_riscv_interrupts.py @@ -1,17 +1,15 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import time import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target']) def test_ulp_riscv_interrupts(dut: Dut) -> None: - dut.expect_exact('Not a ULP RISC-V wakeup, initializing it!') dut.expect_exact('Entering in deep sleep') diff --git a/examples/system/unit_test/pytest_unittest.py b/examples/system/unit_test/pytest_unittest.py index e27dc4298c..07d725e644 100644 --- a/examples/system/unit_test/pytest_unittest.py +++ b/examples/system/unit_test/pytest_unittest.py @@ -1,14 +1,13 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_unit_test(dut: Dut) -> None: - def get_reg_nums(number: int) -> str: return r'\d{1,2}\s+' * number diff --git a/examples/system/xip_from_psram/pytest_xip_from_psram.py b/examples/system/xip_from_psram/pytest_xip_from_psram.py index 53398620f1..a6950c043a 100644 --- a/examples/system/xip_from_psram/pytest_xip_from_psram.py +++ b/examples/system/xip_from_psram/pytest_xip_from_psram.py @@ -1,14 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded.dut import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 @pytest.mark.generic # in order to build the default sdkconfig(the CI won't build the sdkconfig.defaults if there is a sdkconfig.ci.xx) @pytest.mark.parametrize( @@ -18,6 +14,7 @@ from pytest_embedded.dut import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4', 'esp32c5', 'esp32c61'], indirect=['target']) def test_xip_from_psram_example_generic(dut: Dut) -> None: dut.expect_exact('found partition') @@ -30,7 +27,6 @@ def test_xip_from_psram_example_generic(dut: Dut) -> None: assert float(response_time) <= 12 -@pytest.mark.esp32s3 @pytest.mark.MSPI_F4R8 @pytest.mark.parametrize( 'config', @@ -39,6 +35,7 @@ def test_xip_from_psram_example_generic(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_xip_from_psram_example_f4r8(dut: Dut) -> None: dut.expect_exact('found partition') @@ -51,7 +48,6 @@ def test_xip_from_psram_example_f4r8(dut: Dut) -> None: assert float(response_time) <= 12 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -60,6 +56,7 @@ def test_xip_from_psram_example_f4r8(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_xip_from_psram_example_p4_200m(dut: Dut) -> None: dut.expect_exact('found partition') diff --git a/examples/wifi/getting_started/pytest_wifi_getting_started.py b/examples/wifi/getting_started/pytest_wifi_getting_started.py index 3ce6e5d655..42622d5ba0 100644 --- a/examples/wifi/getting_started/pytest_wifi_getting_started.py +++ b/examples/wifi/getting_started/pytest_wifi_getting_started.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os.path from typing import Tuple import pytest from pytest_embedded_idf.dut import IdfDut - +from pytest_embedded_idf.utils import idf_parametrize # @pytest.mark.supported_targets # This test should support all targets, even between different target types # For now our CI only support multi dut with esp32 @@ -20,19 +20,19 @@ from pytest_embedded_idf.dut import IdfDut # ) -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.two_duts @pytest.mark.parametrize( - 'count, app_path', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "softAP")}|{os.path.join(os.path.dirname(__file__), "station")}'), - ], indirect=True + 'count, app_path', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "softAP")}|{os.path.join(os.path.dirname(__file__), "station")}', + ), + ], + indirect=True, +) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'], indirect=['target'] ) def test_wifi_getting_started(dut: Tuple[IdfDut, IdfDut]) -> None: softap = dut[0] @@ -49,15 +49,21 @@ def test_wifi_getting_started(dut: Tuple[IdfDut, IdfDut]) -> None: softap.expect('station .+ join, AID=', timeout=60) -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, config, baud, app_path', [ - (2, 'esp32c2_xtal26m', '74880', - f'{os.path.join(os.path.dirname(__file__), "softAP")}|{os.path.join(os.path.dirname(__file__), "station")}'), - ], indirect=True + 'count, config, baud, app_path', + [ + ( + 2, + 'esp32c2_xtal26m', + '74880', + f'{os.path.join(os.path.dirname(__file__), "softAP")}|{os.path.join(os.path.dirname(__file__), "station")}', + ), + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_wifi_getting_started_esp32c2_xtal_26mhz(dut: Tuple[IdfDut, IdfDut]) -> None: softap = dut[0] station = dut[1] diff --git a/examples/wifi/iperf/pytest_iperf.py b/examples/wifi/iperf/pytest_iperf.py index 334a41d9c6..ffddffe3a6 100644 --- a/examples/wifi/iperf/pytest_iperf.py +++ b/examples/wifi/iperf/pytest_iperf.py @@ -1,5 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 +import os +from typing import Callable + +import pytest +from common_test_methods import get_env_config_variable +from common_test_methods import get_host_ip_by_interface +from idf_iperf_test_util import IperfUtility +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize + """ Test case for iperf example. @@ -15,30 +25,20 @@ The test env wifi_iperf do need the following config:: pc_nic: "eth1" """ -import os -from typing import Callable - -import pytest -from common_test_methods import get_env_config_variable -from common_test_methods import get_host_ip_by_interface -from idf_iperf_test_util import IperfUtility -from pytest_embedded import Dut # configurations RETRY_COUNT_FOR_BEST_PERFORMANCE = 2 -NO_BANDWIDTH_LIMIT = -1 # iperf send bandwith is not limited +NO_BANDWIDTH_LIMIT = -1 # iperf send bandwidth is not limited # Use default value `99` for config with best performance. BEST_PERFORMANCE_CONFIG = '99' -@pytest.mark.esp32 @pytest.mark.temp_skip_ci(targets=['esp32s2', 'esp32c3', 'esp32s3'], reason='lack of runners (run only for ESP32)') @pytest.mark.timeout(1200) @pytest.mark.wifi_iperf -@pytest.mark.parametrize('config', [ - BEST_PERFORMANCE_CONFIG -], indirect=True) +@pytest.mark.parametrize('config', [BEST_PERFORMANCE_CONFIG], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_wifi_throughput_basic( dut: Dut, log_performance: Callable[[str, str], None], @@ -69,8 +69,9 @@ def test_wifi_throughput_basic( 'udp_rx': IperfUtility.TestResult('udp', 'rx', BEST_PERFORMANCE_CONFIG), } - test_utility = IperfUtility.IperfTestUtility(dut, BEST_PERFORMANCE_CONFIG, ap_info['ssid'], ap_info['password'], - pc_nic_ip, pc_iperf_log_file, test_result) + test_utility = IperfUtility.IperfTestUtility( + dut, BEST_PERFORMANCE_CONFIG, ap_info['ssid'], ap_info['password'], pc_nic_ip, pc_iperf_log_file, test_result + ) # 3. run test for TCP Tx, Rx and UDP Tx, Rx for _ in range(RETRY_COUNT_FOR_BEST_PERFORMANCE): @@ -78,10 +79,13 @@ def test_wifi_throughput_basic( # 4. log performance and compare with pass standard for throughput_type in test_result: - log_performance('{}_throughput'.format(throughput_type), - '{:.02f} Mbps'.format(test_result[throughput_type].get_best_throughput())) + log_performance( + '{}_throughput'.format(throughput_type), + '{:.02f} Mbps'.format(test_result[throughput_type].get_best_throughput()), + ) # do check after logging, otherwise test will exit immediately if check fail, some performance can't be logged. for throughput_type in test_result: - check_performance('{}_throughput'.format(throughput_type), - test_result[throughput_type].get_best_throughput(), dut.target) + check_performance( + '{}_throughput'.format(throughput_type), test_result[throughput_type].get_best_throughput(), dut.target + ) diff --git a/examples/wifi/power_save/pytest_wifi_power_save.py b/examples/wifi/power_save/pytest_wifi_power_save.py index e9832e864f..bed25c5201 100644 --- a/examples/wifi/power_save/pytest_wifi_power_save.py +++ b/examples/wifi/power_save/pytest_wifi_power_save.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import logging @@ -6,6 +6,7 @@ import pexpect import pytest from common_test_methods import get_env_config_variable from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize bad_event_str = [ 'bcn_timeout', @@ -40,20 +41,16 @@ def _run_test(dut: Dut) -> None: raise RuntimeError('Failed to get ip in power save mode') -@pytest.mark.esp32 -@pytest.mark.esp32c2 -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 @pytest.mark.wifi_ap +@idf_parametrize( + 'target', + ['esp32', 'esp32c2', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c6', 'esp32c5', 'esp32c61'], + indirect=['target'], +) def test_wifi_power_save(dut: Dut) -> None: _run_test(dut) -@pytest.mark.esp32c6 @pytest.mark.wifi_ap @pytest.mark.parametrize( 'config', @@ -62,18 +59,21 @@ def test_wifi_power_save(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_wifi_power_save_pd_top(dut: Dut) -> None: _run_test(dut) -@pytest.mark.esp32c2 @pytest.mark.wifi_ap @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'config, baud', [ + 'config, baud', + [ ('c2_xtal26m', '74880'), - ], indirect=True + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_wifi_power_save_esp32c2_26mhz(dut: Dut) -> None: _run_test(dut) @@ -96,9 +96,7 @@ def test_wifi_power_save_esp32c2eco4_26mhz(dut: Dut) -> None: @pytest.mark.esp32c3eco7 @pytest.mark.parametrize( 'config, target', - [ - ('c3eco7','esp32c3') - ], + [('c3eco7', 'esp32c3')], indirect=True, ) def test_wifi_power_save_esp32c3eco7(dut: Dut) -> None: diff --git a/examples/zigbee/light_sample/pytest_esp_zigbee.py b/examples/zigbee/light_sample/pytest_esp_zigbee.py index 0d24a7f636..346afce5cd 100644 --- a/examples/zigbee/light_sample/pytest_esp_zigbee.py +++ b/examples/zigbee/light_sample/pytest_esp_zigbee.py @@ -1,46 +1,47 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 # !/usr/bin/env python3 - import pathlib import time from typing import Tuple import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize CURRENT_DIR_LIGHT = str(pathlib.Path(__file__).parent / 'HA_on_off_light') CURRENT_DIR_SWITCH = str(pathlib.Path(__file__).parent / 'HA_on_off_switch') pytest_build_dir = CURRENT_DIR_LIGHT + '|' + CURRENT_DIR_SWITCH -@pytest.mark.esp32h2 @pytest.mark.zigbee_multi_dut @pytest.mark.parametrize( - ' count, app_path, erase_all', [ + ' count, app_path, erase_all', + [ (2, pytest_build_dir, 'y'), ], indirect=True, ) # config Zigbee network -def test_config_zigbee_network(dut:Tuple[Dut, Dut]) -> None: +@idf_parametrize('target', ['esp32h2'], indirect=['target']) +def test_config_zigbee_network(dut: Tuple[Dut, Dut]) -> None: light = dut[0] switch = dut[1] time.sleep(3) - switch.expect('ESP_ZB_ON_OFF_SWITCH: Formed network successfully',timeout=30) + switch.expect('ESP_ZB_ON_OFF_SWITCH: Formed network successfully', timeout=30) # get the switch extpanid - switch_node_expanid = switch.expect(r'Extended PAN ID: (([a-z0-9]{2}:?){8})',timeout=3)[1].decode() - switch_node_expanid = switch_node_expanid.replace(':','') + switch_node_expanid = switch.expect(r'Extended PAN ID: (([a-z0-9]{2}:?){8})', timeout=3)[1].decode() + switch_node_expanid = switch_node_expanid.replace(':', '') # get the switch panid - switch_node_panid = switch.expect(r'PAN ID: 0x([a-z0-9]+:?)',timeout=2)[1].decode() + switch_node_panid = switch.expect(r'PAN ID: 0x([a-z0-9]+:?)', timeout=2)[1].decode() # new device commissioned successfully - switch.expect(r'New device commissioned or rejoined \(short: 0x([a-z0-9]+)[^a-z0-9]',timeout=30)[1].decode() + switch.expect(r'New device commissioned or rejoined \(short: 0x([a-z0-9]+)[^a-z0-9]', timeout=30)[1].decode() # get the light node extpanid - light.expect('ESP_ZB_ON_OFF_LIGHT: Joined network successfully',timeout=20) - light_node_expanid = light.expect(r'Extended PAN ID: (([a-z0-9]{2}:?){8})',timeout=3)[1].decode() - light_node_expanid = light_node_expanid.replace(':','') + light.expect('ESP_ZB_ON_OFF_LIGHT: Joined network successfully', timeout=20) + light_node_expanid = light.expect(r'Extended PAN ID: (([a-z0-9]{2}:?){8})', timeout=3)[1].decode() + light_node_expanid = light_node_expanid.replace(':', '') # get the light panid - light_node_panid = light.expect(r'PAN ID: 0x([a-z0-9]+:?)',timeout=2)[1].decode() + light_node_panid = light.expect(r'PAN ID: 0x([a-z0-9]+:?)', timeout=2)[1].decode() # make sure the light node join the network that switch node formed (same expanid) - if ((light_node_expanid != switch_node_expanid) or (light_node_panid != switch_node_panid)): + if (light_node_expanid != switch_node_expanid) or (light_node_panid != switch_node_panid): assert False diff --git a/tools/test_apps/build_system/ld_non_contiguous_memory/pytest_ld_non_contiguous_memory.py b/tools/test_apps/build_system/ld_non_contiguous_memory/pytest_ld_non_contiguous_memory.py index 3bb473f033..a5010dc6fd 100644 --- a/tools/test_apps/build_system/ld_non_contiguous_memory/pytest_ld_non_contiguous_memory.py +++ b/tools/test_apps/build_system/ld_non_contiguous_memory/pytest_ld_non_contiguous_memory.py @@ -1,15 +1,15 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut - +from pytest_embedded_idf.utils import idf_parametrize TEST_APP_IN_FLASH = [pytest.param('app_in_flash', marks=pytest.mark.esp32p4)] -@pytest.mark.esp32p4 @pytest.mark.generic -@pytest.mark.parametrize('config', TEST_APP_IN_FLASH, indirect=True) +@idf_parametrize('config', ['app_in_flash'], indirect=['config']) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_ld_non_contiguous_memory(dut: Dut) -> None: dut.expect_exact('buf2 placed in low sram') dut.expect_exact('buf1 placed in high sram') diff --git a/tools/test_apps/linux_compatible/linux_freertos/pytest_linux_freertos.py b/tools/test_apps/linux_compatible/linux_freertos/pytest_linux_freertos.py index c510573ff0..184042cecc 100644 --- a/tools/test_apps/linux_compatible/linux_freertos/pytest_linux_freertos.py +++ b/tools/test_apps/linux_compatible/linux_freertos/pytest_linux_freertos.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_linux_freertos_SMP(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests.') dut.write('![ignore]') diff --git a/tools/test_apps/peripherals/i2c_wifi/pytest_i2c_wifi.py b/tools/test_apps/peripherals/i2c_wifi/pytest_i2c_wifi.py index 84511f4c25..4ac1f2b045 100644 --- a/tools/test_apps/peripherals/i2c_wifi/pytest_i2c_wifi.py +++ b/tools/test_apps/peripherals/i2c_wifi/pytest_i2c_wifi.py @@ -1,16 +1,13 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 @pytest.mark.generic +@idf_parametrize( + 'target', ['esp32', 'esp32c2', 'esp32c3', 'esp32c6', 'esp32s2', 'esp32s3', 'esp32c5'], indirect=['target'] +) def test_i2c_wifi_startup(dut: IdfDut) -> None: dut.expect_exact('I2C-WIFI test success') diff --git a/tools/test_apps/phy/phy_multi_init_data_test/pytest_phy_multi_init_data.py b/tools/test_apps/phy/phy_multi_init_data_test/pytest_phy_multi_init_data.py index 569901a065..daa4ffc744 100644 --- a/tools/test_apps/phy/phy_multi_init_data_test/pytest_phy_multi_init_data.py +++ b/tools/test_apps/phy/phy_multi_init_data_test/pytest_phy_multi_init_data.py @@ -1,20 +1,20 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@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', [ - 'phy_multiple_init_data', - 'phy_multiple_init_data_embed', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'phy_multiple_init_data', + 'phy_multiple_init_data_embed', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c2', 'esp32c3', 'esp32c6', 'esp32s2', 'esp32s3'], indirect=['target']) def test_phy_multi_init_data_bin(dut: IdfDut, config: str) -> None: if config == 'phy_multiple_init_data': dut.expect_exact('Support multiple PHY init data bins') diff --git a/tools/test_apps/phy/phy_tsens/pytest_phy_tsens.py b/tools/test_apps/phy/phy_tsens/pytest_phy_tsens.py index 98cf8de02d..232e51b9b0 100644 --- a/tools/test_apps/phy/phy_tsens/pytest_phy_tsens.py +++ b/tools/test_apps/phy/phy_tsens/pytest_phy_tsens.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import random import string @@ -7,6 +7,7 @@ from typing import Tuple import pexpect import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def run_phy_tsens_test(dut: Tuple[Dut, Dut]) -> None: @@ -143,13 +144,9 @@ def run_phy_tsens_test_with_light_sleep(dut: Tuple[Dut, Dut]) -> None: assert 0 < float(temp_val) < 70 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.two_duts @pytest.mark.parametrize('count', [2], indirect=True) +@idf_parametrize('target', ['esp32c3', 'esp32c6', 'esp32c5', 'esp32s2', 'esp32s3'], indirect=['target']) def test_phy_tsens_coexist(dut: Tuple[Dut, Dut]) -> None: for _dut in dut: _dut.expect('esp>') @@ -166,7 +163,6 @@ def test_phy_tsens_coexist(dut: Tuple[Dut, Dut]) -> None: run_phy_tsens_test_with_light_sleep(dut) -@pytest.mark.esp32c2 @pytest.mark.two_duts @pytest.mark.xtal_26mhz @pytest.mark.parametrize( @@ -176,6 +172,7 @@ def test_phy_tsens_coexist(dut: Tuple[Dut, Dut]) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_phy_tsens_coexist_c2_xtal26m(dut: Tuple[Dut, Dut]) -> None: for _dut in dut: _dut.expect('esp>') diff --git a/tools/test_apps/protocols/mqtt/publish_connect_test/pytest_mqtt_app.py b/tools/test_apps/protocols/mqtt/publish_connect_test/pytest_mqtt_app.py index 237701894b..a967ee2683 100644 --- a/tools/test_apps/protocols/mqtt/publish_connect_test/pytest_mqtt_app.py +++ b/tools/test_apps/protocols/mqtt/publish_connect_test/pytest_mqtt_app.py @@ -1,6 +1,5 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 - import contextlib import logging import os @@ -9,31 +8,49 @@ import socketserver import ssl import subprocess from threading import Thread -from typing import Any, Callable, Dict, Optional +from typing import Any +from typing import Callable +from typing import Dict +from typing import Optional import pytest from common_test_methods import get_host_ip4_by_dest_ip from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize SERVER_PORT = 2222 def _path(f): # type: (str) -> str - return os.path.join(os.path.dirname(os.path.realpath(__file__)),f) + return os.path.join(os.path.dirname(os.path.realpath(__file__)), f) def set_server_cert_cn(ip): # type: (str) -> None arg_list = [ - ['openssl', 'req', '-out', _path('srv.csr'), '-key', _path('server.key'),'-subj', '/CN={}'.format(ip), '-new'], - ['openssl', 'x509', '-req', '-in', _path('srv.csr'), '-CA', _path('ca.crt'), - '-CAkey', _path('ca.key'), '-CAcreateserial', '-out', _path('srv.crt'), '-days', '360']] + ['openssl', 'req', '-out', _path('srv.csr'), '-key', _path('server.key'), '-subj', '/CN={}'.format(ip), '-new'], + [ + 'openssl', + 'x509', + '-req', + '-in', + _path('srv.csr'), + '-CA', + _path('ca.crt'), + '-CAkey', + _path('ca.key'), + '-CAcreateserial', + '-out', + _path('srv.crt'), + '-days', + '360', + ], + ] for args in arg_list: if subprocess.check_call(args) != 0: raise RuntimeError('openssl command {} failed'.format(args)) class MQTTHandler(socketserver.StreamRequestHandler): - def handle(self) -> None: logging.info(' - connection from: {}'.format(self.client_address)) data = bytearray(self.request.recv(1024)) @@ -56,12 +73,14 @@ class TlsServer(socketserver.TCPServer): allow_reuse_address = True allow_reuse_port = True - def __init__(self, - port:int = SERVER_PORT, - ServerHandler: Callable[[Any, Any, Any], socketserver.BaseRequestHandler] = MQTTHandler, - client_cert:bool=False, - refuse_connection:bool=False, - use_alpn:bool=False): + def __init__( + self, + port: int = SERVER_PORT, + ServerHandler: Callable[[Any, Any, Any], socketserver.BaseRequestHandler] = MQTTHandler, + client_cert: bool = False, + refuse_connection: bool = False, + use_alpn: bool = False, + ): self.refuse_connection = refuse_connection self.context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) self.ssl_error = '' @@ -73,7 +92,7 @@ class TlsServer(socketserver.TCPServer): if use_alpn: self.context.set_alpn_protocols(['mymqtt', 'http/1.1']) self.server_thread = Thread(target=self.serve_forever) - super().__init__(('',port), ServerHandler) + super().__init__(('', port), ServerHandler) def server_activate(self) -> None: self.socket = self.context.wrap_socket(self.socket, server_side=True) @@ -125,14 +144,16 @@ def get_test_cases(dut: Dut) -> Any: cases = {} try: # Get connection test cases configuration: symbolic names for test cases - for case in ['EXAMPLE_CONNECT_CASE_NO_CERT', - 'EXAMPLE_CONNECT_CASE_SERVER_CERT', - 'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH', - 'EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT', - 'EXAMPLE_CONNECT_CASE_SERVER_DER_CERT', - 'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD', - 'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT', - 'EXAMPLE_CONNECT_CASE_NO_CERT_ALPN']: + for case in [ + 'EXAMPLE_CONNECT_CASE_NO_CERT', + 'EXAMPLE_CONNECT_CASE_SERVER_CERT', + 'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH', + 'EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT', + 'EXAMPLE_CONNECT_CASE_SERVER_DER_CERT', + 'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD', + 'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT', + 'EXAMPLE_CONNECT_CASE_NO_CERT_ALPN', + ]: cases[case] = dut.app.sdkconfig.get(case) except Exception: logging.error('ENV_TEST_FAILURE: Some mandatory CONNECTION test case not found in sdkconfig') @@ -147,7 +168,7 @@ def get_dut_ip(dut: Dut) -> Any: @contextlib.contextmanager -def connect_dut(dut: Dut, uri:str, case_id:int) -> Any: +def connect_dut(dut: Dut, uri: str, case_id: int) -> Any: dut.write('connection_setup') dut.write(f'connect {uri} {case_id}') dut.expect(f'Test case:{case_id} started') @@ -157,12 +178,16 @@ def connect_dut(dut: Dut, uri:str, case_id:int) -> Any: dut.write('disconnect') -def run_cases(dut:Dut, uri:str, cases:Dict[str, int]) -> None: +def run_cases(dut: Dut, uri: str, cases: Dict[str, int]) -> None: try: dut.write('init') dut.write(f'start') dut.write(f'disconnect') - for case in ['EXAMPLE_CONNECT_CASE_NO_CERT', 'EXAMPLE_CONNECT_CASE_SERVER_CERT', 'EXAMPLE_CONNECT_CASE_SERVER_DER_CERT']: + for case in [ + 'EXAMPLE_CONNECT_CASE_NO_CERT', + 'EXAMPLE_CONNECT_CASE_SERVER_CERT', + 'EXAMPLE_CONNECT_CASE_SERVER_DER_CERT', + ]: # All these cases connect to the server with no server verification or with server only verification with TlsServer(), connect_dut(dut, uri, cases[case]): logging.info(f'Running {case}: default server - expect to connect normally') @@ -172,9 +197,13 @@ def run_cases(dut:Dut, uri:str, cases:Dict[str, int]) -> None: dut.expect(f'MQTT_EVENT_ERROR: Test={cases[case]}', timeout=30) dut.expect('MQTT ERROR: 0x5') # expecting 0x5 ... connection not authorized error with TlsServer(client_cert=True) as server, connect_dut(dut, uri, cases[case]): - logging.info(f'Running {case}: server with client verification - handshake error since client presents no client certificate') + logging.info( + f'Running {case}: server with client verification - handshake error since client presents no client certificate' + ) dut.expect(f'MQTT_EVENT_ERROR: Test={cases[case]}', timeout=30) - dut.expect('ESP-TLS ERROR: ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED') # expect ... handshake error (PEER_DID_NOT_RETURN_A_CERTIFICATE) + dut.expect( + 'ESP-TLS ERROR: ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED' + ) # expect ... handshake error (PEER_DID_NOT_RETURN_A_CERTIFICATE) assert 'PEER_DID_NOT_RETURN_A_CERTIFICATE' in server.last_ssl_error() for case in ['EXAMPLE_CONNECT_CASE_MUTUAL_AUTH', 'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD']: @@ -187,15 +216,21 @@ def run_cases(dut:Dut, uri:str, cases:Dict[str, int]) -> None: with TlsServer() as s, connect_dut(dut, uri, cases[case]): logging.info(f'Running {case}: invalid server certificate on default server - expect ssl handshake error') dut.expect(f'MQTT_EVENT_ERROR: Test={cases[case]}', timeout=30) - dut.expect('ESP-TLS ERROR: ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED') # expect ... handshake error (TLSV1_ALERT_UNKNOWN_CA) - if re.match('.*alert.*unknown.*ca',s.last_ssl_error(), flags=re.I) is None: + dut.expect( + 'ESP-TLS ERROR: ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED' + ) # expect ... handshake error (TLSV1_ALERT_UNKNOWN_CA) + if re.match('.*alert.*unknown.*ca', s.last_ssl_error(), flags=re.I) is None: raise Exception(f'Unexpected ssl error from the server: {s.last_ssl_error()}') case = 'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT' with TlsServer(client_cert=True) as s, connect_dut(dut, uri, cases[case]): - logging.info(f'Running {case}: Invalid client certificate on server with client verification - expect ssl handshake error') + logging.info( + f'Running {case}: Invalid client certificate on server with client verification - expect ssl handshake error' + ) dut.expect(f'MQTT_EVENT_ERROR: Test={cases[case]}', timeout=30) - dut.expect('ESP-TLS ERROR: ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED') # expect ... handshake error (CERTIFICATE_VERIFY_FAILED) + dut.expect( + 'ESP-TLS ERROR: ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED' + ) # expect ... handshake error (CERTIFICATE_VERIFY_FAILED) if 'CERTIFICATE_VERIFY_FAILED' not in s.last_ssl_error(): raise Exception('Unexpected ssl error from the server {}'.format(s.last_ssl_error())) @@ -214,8 +249,8 @@ def run_cases(dut:Dut, uri:str, cases:Dict[str, int]) -> None: dut.write('destroy') -@pytest.mark.esp32 @pytest.mark.ethernet +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_mqtt_connect( dut: Dut, log_performance: Callable[[str, object], None], diff --git a/tools/test_apps/protocols/mqtt/publish_connect_test/pytest_mqtt_publish_app.py b/tools/test_apps/protocols/mqtt/publish_connect_test/pytest_mqtt_publish_app.py index 544c0b7027..b6c0af19b0 100644 --- a/tools/test_apps/protocols/mqtt/publish_connect_test/pytest_mqtt_publish_app.py +++ b/tools/test_apps/protocols/mqtt/publish_connect_test/pytest_mqtt_publish_app.py @@ -1,6 +1,5 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 - import contextlib import difflib import logging @@ -9,23 +8,32 @@ import random import re import ssl import string -from itertools import count, product -from threading import Event, Lock -from typing import Any, Dict, List, Tuple, no_type_check +from itertools import count +from itertools import product +from threading import Event +from threading import Lock +from typing import Any +from typing import Dict +from typing import List +from typing import no_type_check +from typing import Tuple import paho.mqtt.client as mqtt import pexpect import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize DEFAULT_MSG_SIZE = 16 # Publisher class creating a python client to send/receive published data from esp-mqtt client class MqttPublisher(mqtt.Client): - def __init__(self, repeat, published, publish_cfg, log_details=False): # type: (MqttPublisher, int, int, dict, bool) -> None - self.sample_string = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(DEFAULT_MSG_SIZE)) + self.sample_string = ''.join( + random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) + for _ in range(DEFAULT_MSG_SIZE) + ) self.log_details = log_details self.repeat = repeat self.publish_cfg = publish_cfg @@ -42,7 +50,7 @@ class MqttPublisher(mqtt.Client): if self.log_details: logging.info(text) - def on_connect(self, mqttc: Any, obj: Any, flags: Any, rc:int) -> None: + def on_connect(self, mqttc: Any, obj: Any, flags: Any, rc: int) -> None: self.event_client_connected.set() def on_connect_fail(self, mqttc: Any, obj: Any) -> None: @@ -58,12 +66,14 @@ class MqttPublisher(mqtt.Client): self.event_client_got_all.set() else: differences = len(list(filter(lambda data: data[0] != data[1], zip(payload, self.expected_data)))) - logging.error(f'Payload differ in {differences} positions from expected data. received size: {len(payload)} expected size:' - f'{len(self.expected_data)}') + logging.error( + f'Payload differ in {differences} positions from expected data. received size: {len(payload)} expected size:' + f'{len(self.expected_data)}' + ) logging.info(f'Repetitions: {payload.count(self.sample_string)}') logging.info(f'Pattern: {self.sample_string}') - logging.info(f'First : {payload[:DEFAULT_MSG_SIZE]}') - logging.info(f'Last : {payload[-DEFAULT_MSG_SIZE:]}') + logging.info(f'First : {payload[:DEFAULT_MSG_SIZE]}') # noqa: E203 + logging.info(f'Last : {payload[-DEFAULT_MSG_SIZE:]}') # noqa: E203 matcher = difflib.SequenceMatcher(a=payload, b=self.expected_data) for match in matcher.get_matching_blocks(): logging.info(f'Match: {match}') @@ -97,9 +107,10 @@ class MqttPublisher(mqtt.Client): self.loop_stop() -def get_configurations(dut: Dut) -> Dict[str,Any]: +def get_configurations(dut: Dut) -> Dict[str, Any]: publish_cfg = {} try: + @no_type_check def get_broker_from_dut(dut, config_option): # logging.info('Option:', config_option, dut.app.sdkconfig.get(config_option)) @@ -107,13 +118,20 @@ def get_configurations(dut: Dut) -> Dict[str,Any]: if value is None: return None, None return value.group(1), int(value.group(2)) + # Get publish test configuration - publish_cfg['publish_topic'] = dut.app.sdkconfig.get('EXAMPLE_SUBSCRIBE_TOPIC').replace('"','') - publish_cfg['subscribe_topic'] = dut.app.sdkconfig.get('EXAMPLE_PUBLISH_TOPIC').replace('"','') - publish_cfg['broker_host_ssl'], publish_cfg['broker_port_ssl'] = get_broker_from_dut(dut, 'EXAMPLE_BROKER_SSL_URI') - publish_cfg['broker_host_tcp'], publish_cfg['broker_port_tcp'] = get_broker_from_dut(dut, 'EXAMPLE_BROKER_TCP_URI') + publish_cfg['publish_topic'] = dut.app.sdkconfig.get('EXAMPLE_SUBSCRIBE_TOPIC').replace('"', '') + publish_cfg['subscribe_topic'] = dut.app.sdkconfig.get('EXAMPLE_PUBLISH_TOPIC').replace('"', '') + publish_cfg['broker_host_ssl'], publish_cfg['broker_port_ssl'] = get_broker_from_dut( + dut, 'EXAMPLE_BROKER_SSL_URI' + ) + publish_cfg['broker_host_tcp'], publish_cfg['broker_port_tcp'] = get_broker_from_dut( + dut, 'EXAMPLE_BROKER_TCP_URI' + ) publish_cfg['broker_host_ws'], publish_cfg['broker_port_ws'] = get_broker_from_dut(dut, 'EXAMPLE_BROKER_WS_URI') - publish_cfg['broker_host_wss'], publish_cfg['broker_port_wss'] = get_broker_from_dut(dut, 'EXAMPLE_BROKER_WSS_URI') + publish_cfg['broker_host_wss'], publish_cfg['broker_port_wss'] = get_broker_from_dut( + dut, 'EXAMPLE_BROKER_WSS_URI' + ) except Exception: logging.info('ENV_TEST_FAILURE: Some mandatory PUBLISH test case not found in sdkconfig') @@ -123,7 +141,7 @@ def get_configurations(dut: Dut) -> Dict[str,Any]: @contextlib.contextmanager -def connected_and_subscribed(dut:Dut, transport:str, pattern:str, pattern_repetitions:int) -> Any: +def connected_and_subscribed(dut: Dut, transport: str, pattern: str, pattern_repetitions: int) -> Any: dut.write(f'publish_setup {transport} {pattern} {pattern_repetitions}') dut.write(f'start') dut.expect(re.compile(rb'MQTT_EVENT_SUBSCRIBED'), timeout=60) @@ -136,16 +154,17 @@ def get_scenarios() -> List[Dict[str, int]]: # Initialize message sizes and repeat counts (if defined in the environment) for i in count(0): # Check env variable: MQTT_PUBLISH_MSG_{len|repeat}_{x} - env_dict = {var:'MQTT_PUBLISH_MSG_' + var + '_' + str(i) for var in ['len', 'repeat']} + env_dict = {var: 'MQTT_PUBLISH_MSG_' + var + '_' + str(i) for var in ['len', 'repeat']} if os.getenv(env_dict['len']) and os.getenv(env_dict['repeat']): scenarios.append({var: int(os.getenv(env_dict[var])) for var in ['len', 'repeat']}) # type: ignore continue break - if not scenarios: # No message sizes present in the env - set defaults - scenarios = [{'len':0, 'repeat':5}, # zero-sized messages - {'len':2, 'repeat':5}, # short messages - {'len':200, 'repeat':3}, # long messages - ] + if not scenarios: # No message sizes present in the env - set defaults + scenarios = [ + {'len': 0, 'repeat': 5}, # zero-sized messages + {'len': 2, 'repeat': 5}, # short messages + {'len': 200, 'repeat': 3}, # long messages + ] return scenarios @@ -166,14 +185,20 @@ def run_publish_test_case(dut: Dut, test_case: Any, publish_cfg: Any) -> None: publish_cfg['queue'] = enqueue publish_cfg['transport'] = transport test_timeout = get_timeout(test_case) - logging.info(f'Starting Publish test: transport:{transport}, qos:{qos}, nr_of_msgs:{published},' - f' msg_size:{repeat*DEFAULT_MSG_SIZE}, enqueue:{enqueue}') - with MqttPublisher(repeat, published, publish_cfg) as publisher, connected_and_subscribed(dut, transport, publisher.sample_string, scenario['len']): + logging.info( + f'Starting Publish test: transport:{transport}, qos:{qos}, nr_of_msgs:{published},' + f' msg_size:{repeat * DEFAULT_MSG_SIZE}, enqueue:{enqueue}' + ) + with MqttPublisher(repeat, published, publish_cfg) as publisher, connected_and_subscribed( + dut, transport, publisher.sample_string, scenario['len'] + ): msgs_published: List[mqtt.MQTTMessageInfo] = [] dut.write(f'publish {publisher.published} {qos} {enqueue}') - assert publisher.event_client_got_all.wait(timeout=test_timeout), (f'Not all data received from ESP32: {transport} ' - f'qos={qos} received: {publisher.received} ' - f'expected: {publisher.published}') + assert publisher.event_client_got_all.wait(timeout=test_timeout), ( + f'Not all data received from ESP32: {transport} ' + f'qos={qos} received: {publisher.received} ' + f'expected: {publisher.published}' + ) logging.info(' - all data received from ESP32') payload = publisher.sample_string * publisher.repeat for _ in range(publisher.published): @@ -194,7 +219,7 @@ def run_publish_test_case(dut: Dut, test_case: Any, publish_cfg: Any) -> None: logging.info('ESP32 received all data from runner') -stress_scenarios = [{'len':20, 'repeat':50}] # many medium sized +stress_scenarios = [{'len': 20, 'repeat': 50}] # many medium sized transport_cases = ['tcp', 'ws', 'wss', 'ssl'] qos_cases = [0, 1, 2] enqueue_cases = [0, 1] @@ -208,10 +233,10 @@ test_cases = make_cases(get_scenarios()) stress_test_cases = make_cases(stress_scenarios) -@pytest.mark.esp32 @pytest.mark.ethernet @pytest.mark.nightly_run @pytest.mark.parametrize('test_case', test_cases) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_mqtt_publish(dut: Dut, test_case: Any) -> None: publish_cfg = get_configurations(dut) dut.expect(re.compile(rb'mqtt>'), timeout=30) @@ -219,10 +244,10 @@ def test_mqtt_publish(dut: Dut, test_case: Any) -> None: run_publish_test_case(dut, test_case, publish_cfg) -@pytest.mark.esp32 @pytest.mark.ethernet @pytest.mark.nightly_run @pytest.mark.parametrize('test_case', stress_test_cases) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_mqtt_publish_stress(dut: Dut, test_case: Any) -> None: publish_cfg = get_configurations(dut) dut.expect(re.compile(rb'mqtt>'), timeout=30) diff --git a/tools/test_apps/security/secure_boot/pytest_secure_boot.py b/tools/test_apps/security/secure_boot/pytest_secure_boot.py index 6bd5ae69cd..994bd577ca 100644 --- a/tools/test_apps/security/secure_boot/pytest_secure_boot.py +++ b/tools/test_apps/security/secure_boot/pytest_secure_boot.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import os import struct @@ -6,7 +6,7 @@ import zlib import pytest from pytest_embedded import Dut - +from pytest_embedded_idf.utils import idf_parametrize # To prepare a runner for these tests, # 1. Connect an FPGA with C3 image # 2. Use a COM port for programming and export it as ESPPORT @@ -28,7 +28,9 @@ def corrupt_signature(signed_bootloader, seed=0, corrupt_sig=True, corrupt_crc=F # if corrupt_block is CORRUPT_ALL_BLOCKS, corrupt all blocks # otherwise, only corrupt the one with that index set - corr_sig_blocks = tuple(new_blocks[n] if corrupt_block in [CORRUPT_ALL_BLOCKS, n] else sig_blocks[n] for n in range(3)) + corr_sig_blocks = tuple( + new_blocks[n] if corrupt_block in [CORRUPT_ALL_BLOCKS, n] else sig_blocks[n] for n in range(3) + ) return image + b''.join(corr_sig_blocks) + signature[3648:] @@ -37,8 +39,8 @@ def corrupt_sig_block(sig_block, seed=0, corrupt_sig=True, corrupt_crc=False): # type: (bytes, int, bool, bool) -> bytes assert len(sig_block) == 1216 magic = sig_block[0] - assert magic in [0xe7, 0xff] - if magic != 0xe7: + assert magic in [0xE7, 0xFF] + if magic != 0xE7: return sig_block # not valid data = sig_block[:812] new_sig = sig = sig_block[812:1196] @@ -58,7 +60,7 @@ def corrupt_sig_block(sig_block, seed=0, corrupt_sig=True, corrupt_crc=False): assert new_sig != sig if not corrupt_crc: - crc = struct.pack(' None: # Test secure boot flow. # Correctly signed bootloader + correctly signed app should work -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 +@idf_parametrize('target', ['esp32c3', 'esp32c5', 'esp32c61', 'esp32s3', 'esp32p4'], indirect=['target']) def test_examples_security_secure_boot(dut: Dut) -> None: dut_start_secure_app(dut) dut.expect('Secure Boot is enabled', timeout=10) @@ -93,14 +91,10 @@ def test_examples_security_secure_boot(dut: Dut) -> None: # Test efuse key index and key block combination. # Any key index can be written to any key block and should work -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 # Increasing the test timeout to 1200s as the test runs for 18 iterations # and thus the default 600s timeout is not sufficient @pytest.mark.timeout(1200) +@idf_parametrize('target', ['esp32c3', 'esp32c5', 'esp32c61', 'esp32s3', 'esp32p4'], indirect=['target']) def test_examples_security_secure_boot_key_combo(dut: Dut) -> None: dut_start_secure_app(dut) dut.expect('Secure Boot is enabled', timeout=10) @@ -117,11 +111,7 @@ def test_examples_security_secure_boot_key_combo(dut: Dut) -> None: # Test secure boot key revoke. # If a key is revoked, bootloader signed with that key should fail verification -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 +@idf_parametrize('target', ['esp32c3', 'esp32c5', 'esp32c61', 'esp32s3', 'esp32p4'], indirect=['target']) def test_examples_security_secure_boot_key_revoke(dut: Dut) -> None: dut_start_secure_app(dut) dut.expect('Secure Boot is enabled', timeout=10) @@ -138,14 +128,10 @@ def test_examples_security_secure_boot_key_revoke(dut: Dut) -> None: # Test bootloader signature corruption. # Corrupt one byte at a time of bootloader signature and test that the verification fails -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.timeout(18000) # Increasing the test timeout to 18000s as the test runs for 384 iterations # and thus the default 600s timeout is not sufficient +@idf_parametrize('target', ['esp32c3', 'esp32c5', 'esp32c61', 'esp32s3', 'esp32p4'], indirect=['target']) def test_examples_security_secure_boot_corrupt_bl_sig(dut: Dut) -> None: dut_start_secure_app(dut) dut.expect('Secure Boot is enabled', timeout=10) @@ -177,14 +163,10 @@ def test_examples_security_secure_boot_corrupt_bl_sig(dut: Dut) -> None: # Test app signature corruption. # Corrupt app signature, one byte at a time, and test that the verification fails -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.timeout(18000) # Increasing the test timeout to 18000s as the test runs for 385 iterations # and thus the default 600s timeout is not sufficient +@idf_parametrize('target', ['esp32c3', 'esp32c5', 'esp32c61', 'esp32s3', 'esp32p4'], indirect=['target']) def test_examples_security_secure_boot_corrupt_app_sig(dut: Dut) -> None: dut_start_secure_app(dut) dut.expect('Secure Boot is enabled', timeout=10) @@ -223,6 +205,11 @@ def test_examples_security_secure_boot_corrupt_app_sig(dut: Dut) -> None: dut.secure_boot_burn_en_bit() dut.secure_boot_burn_digest('test_rsa_3072_key.pem', 0, 0) - dut.expect('Sig block 0 invalid: {}'.format('CRC mismatch' if dut.target == 'esp32p4' or dut.target == 'esp32c5' else 'Stored CRC ends'), timeout=2) + dut.expect( + 'Sig block 0 invalid: {}'.format( + 'CRC mismatch' if dut.target == 'esp32p4' or dut.target == 'esp32c5' else 'Stored CRC ends' + ), + timeout=2, + ) dut.expect('Secure boot signature verification failed', timeout=2) dut.expect('No bootable app partitions in the partition table', timeout=2) diff --git a/tools/test_apps/security/signed_app_no_secure_boot/pytest_signed_app_no_secure_boot.py b/tools/test_apps/security/signed_app_no_secure_boot/pytest_signed_app_no_secure_boot.py index 686b7cdeda..241cd73f5e 100644 --- a/tools/test_apps/security/signed_app_no_secure_boot/pytest_signed_app_no_secure_boot.py +++ b/tools/test_apps/security/signed_app_no_secure_boot/pytest_signed_app_no_secure_boot.py @@ -1,12 +1,14 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32c2', 'esp32c3'], indirect=['target']) def test_examples_security_on_update_no_secure_boot(dut: Dut) -> None: - dut.expect("This app is not signed, but check signature on update is enabled in config. It won't be possible to verify any update.", timeout=10) + dut.expect( + "This app is not signed, but check signature on update is enabled in config. It won't be possible to verify any update.", + timeout=10, + ) diff --git a/tools/test_apps/storage/fatfsgen/pytest_fatfsgen_example.py b/tools/test_apps/storage/fatfsgen/pytest_fatfsgen_example.py index 3366337467..4803d94a3f 100644 --- a/tools/test_apps/storage/fatfsgen/pytest_fatfsgen_example.py +++ b/tools/test_apps/storage/fatfsgen/pytest_fatfsgen_example.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import os import re @@ -12,6 +12,7 @@ from time import sleep import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize idf_path = os.environ['IDF_PATH'] # get value of IDF_PATH from environment parttool_dir = os.path.join(idf_path, 'components', 'partition_table') @@ -25,28 +26,31 @@ FileStructure = t.Dict[str, t.Union[t.Optional[str], 'FileStructure']] class DirectoryStructureError(Exception): - '''Base exception for directory structure errors.''' + """Base exception for directory structure errors.""" + pass class MissingStructureError(DirectoryStructureError): - '''Raised when a directory or file is missing.''' + """Raised when a directory or file is missing.""" + pass class ContentMismatchError(DirectoryStructureError): - '''Raised when a file's content does not match the expected content.''' + """Raised when a file's content does not match the expected content.""" + pass class IOErrorInStructure(DirectoryStructureError): - '''Raised when an I/O error occurs during structure validation.''' + """Raised when an I/O error occurs during structure validation.""" + pass -def validate_directory_structure(base_path: str, - expected_structure: FileStructure) -> None: - ''' +def validate_directory_structure(base_path: str, expected_structure: FileStructure) -> None: + """ Checks if the directory structure and file contents match the expected structure. @@ -63,26 +67,22 @@ def validate_directory_structure(base_path: str, their structure. :raises DirectoryStructureError: If the structure or contents do not match. - ''' + """ + def normalize_case(items: t.List[str]) -> t.Dict[str, str]: return {item.lower(): item for item in items} def escape_output(text: str) -> str: - return (text.replace('"', '\"') - .replace('\n', '\\n') - .replace('\t', '\\t') - .replace('\r', '\\r')) + return text.replace('"', '"').replace('\n', '\\n').replace('\t', '\\t').replace('\r', '\\r') - def validate_structure(current_path: str, - structure: FileStructure) -> None: + def validate_structure(current_path: str, structure: FileStructure) -> None: current_items = os.listdir(current_path) normalized_items = normalize_case(current_items) for name, substructure in structure.items(): expected_name = normalized_items.get(name.lower()) if not expected_name: - raise MissingStructureError( - f'Missing item: {os.path.join(current_path, name)}') + raise MissingStructureError(f'Missing item: {os.path.join(current_path, name)}') full_path = os.path.join(current_path, expected_name) @@ -102,35 +102,37 @@ def validate_directory_structure(base_path: str, f'Found: "{escape_output(content)}"' ) except OSError as e: - raise IOErrorInStructure( - f'Error reading file {full_path}: {e}') + raise IOErrorInStructure(f'Error reading file {full_path}: {e}') # Folder elif isinstance(substructure, dict): if not os.path.isdir(full_path): - raise MissingStructureError( - f'Missing directory: {full_path}') + raise MissingStructureError(f'Missing directory: {full_path}') # Recursively check the subdirectory validate_structure(full_path, substructure) else: - raise DirectoryStructureError( - f'Invalid structure definition for {name}.') + raise DirectoryStructureError(f'Invalid structure definition for {name}.') validate_structure(base_path, expected_structure) -@pytest.mark.esp32 @pytest.mark.generic -@pytest.mark.parametrize('config', ['test_read_only_partition_gen', - 'test_read_only_partition_gen_default_dt', - 'test_read_only_partition_gen_ln', - 'test_read_only_partition_gen_ln_default_dt', - 'test_read_write_partition_gen', - 'test_read_write_partition_gen_default_dt', - 'test_read_write_partition_gen_ln', - 'test_read_write_partition_gen_ln_default_dt', - ], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'test_read_only_partition_gen', + 'test_read_only_partition_gen_default_dt', + 'test_read_only_partition_gen_ln', + 'test_read_only_partition_gen_ln_default_dt', + 'test_read_write_partition_gen', + 'test_read_write_partition_gen_default_dt', + 'test_read_write_partition_gen_ln', + 'test_read_write_partition_gen_ln_default_dt', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_fatfsgen(config: str, dut: Dut) -> None: # Default timeout timeout = 120 @@ -146,8 +148,7 @@ def test_examples_fatfsgen(config: str, dut: Dut) -> None: # Expects prefix string followed by date in the format 'yyyy-mm-dd' def expect_date(prefix: str, timeout: int = timeout) -> datetime: expect_str = prefix + '(\\d+)-(\\d+)-(\\d+)' - match_ = dut.expect(re.compile(str.encode(expect_str)), - timeout=timeout) + match_ = dut.expect(re.compile(str.encode(expect_str)), timeout=timeout) year_ = int(match_[1].decode()) month_ = int(match_[2].decode()) day_ = int(match_[3].decode()) @@ -157,18 +158,17 @@ def test_examples_fatfsgen(config: str, dut: Dut) -> None: # between date_reference and date_actual. # Raises exception if difference exceeds date_tolerance # 30 days by default, - def check_dates(date_reference: datetime, - date_actual: datetime, - days_date_tolerance: int = 30) -> None: + def check_dates(date_reference: datetime, date_actual: datetime, days_date_tolerance: int = 30) -> None: td = date_actual - date_reference if abs(td.days) > days_date_tolerance: - raise Exception(f'Too big date difference. \ + raise Exception( + f'Too big date difference. \ Actual: {date_actual}, \ reference: {date_reference}, \ - date_tolerance: {days_date_tolerance} day(s)') + date_tolerance: {days_date_tolerance} day(s)' + ) - fatfs_parser_path = os.path.join(idf_path, 'components', - 'fatfs', 'fatfsparse.py') + fatfs_parser_path = os.path.join(idf_path, 'components', 'fatfs', 'fatfsparse.py') config_read_only = '_read_only' in config config_long_names = '_ln' in config @@ -177,29 +177,27 @@ def test_examples_fatfsgen(config: str, dut: Dut) -> None: expect('example: Mounting FAT filesystem') if not config_read_only: - expect_all(['example: Opening file', - 'example: File written', - 'example: Reading file', - 'example: Read from file: ' - + '\'This is written by the device\''], 30) + expect_all( + [ + 'example: Opening file', + 'example: File written', + 'example: Reading file', + 'example: Read from file: ' + "'This is written by the device'", + ], + 30, + ) expect('example: Reading file') - stat_filename = 'sublongnames/testlongfilenames.txt' \ - if config_long_names \ - else 'sub/test.txt' + stat_filename = 'sublongnames/testlongfilenames.txt' if config_long_names else 'sub/test.txt' - modification_date = expect_date( - f'The file \'/spiflash/{stat_filename}\' was modified at date: ') + modification_date = expect_date(f"The file '/spiflash/{stat_filename}' was modified at date: ") - date_ref = datetime(1980, 1, 1) \ - if config_default_date \ - else datetime.today() + date_ref = datetime(1980, 1, 1) if config_default_date else datetime.today() check_dates(date_ref, modification_date) - expect_all(['example: Unmounting FAT filesystem', - 'example: Done']) + expect_all(['example: Unmounting FAT filesystem', 'example: Done']) dut.serial.close() sleep(1) @@ -207,11 +205,9 @@ def test_examples_fatfsgen(config: str, dut: Dut) -> None: target = ParttoolTarget(dut.serial.port, 1843200) target.read_partition(PartitionName('storage'), 'temp.img') if config_long_names: - run(['python', fatfs_parser_path, '--long-name-support', 'temp.img'], - stderr=STDOUT) + run(['python', fatfs_parser_path, '--long-name-support', 'temp.img'], stderr=STDOUT) else: - run(['python', fatfs_parser_path, 'temp.img'], - stderr=STDOUT) + run(['python', fatfs_parser_path, 'temp.img'], stderr=STDOUT) long_names_read_only: FileStructure = { 'sublongnames': { @@ -227,9 +223,7 @@ def test_examples_fatfsgen(config: str, dut: Dut) -> None: 'hello.txt': 'This is generated on the host\n', } - file_structure: FileStructure = long_names_read_only \ - if config_long_names \ - else short_names_read_only + file_structure: FileStructure = long_names_read_only if config_long_names else short_names_read_only if not config_read_only and not config_long_names: file_structure['inner.txt'] = 'This is written by the device' diff --git a/tools/test_apps/storage/partition_table_readonly/pytest_partition_table_readonly.py b/tools/test_apps/storage/partition_table_readonly/pytest_partition_table_readonly.py index 79ce7443cc..428461cfb4 100644 --- a/tools/test_apps/storage/partition_table_readonly/pytest_partition_table_readonly.py +++ b/tools/test_apps/storage/partition_table_readonly/pytest_partition_table_readonly.py @@ -1,31 +1,31 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic @pytest.mark.parametrize( 'config', [ 'default', ], - indirect=True) + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_partition_table_readonly(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.flash_encryption @pytest.mark.parametrize( 'config', [ 'encrypted', ], - indirect=True) + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_partition_table_readonly_flash_encryption(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120) diff --git a/tools/test_apps/storage/std_filesystem/pytest_std_filesystem.py b/tools/test_apps/storage/std_filesystem/pytest_std_filesystem.py index 82468d1e41..1e644e2a07 100644 --- a/tools/test_apps/storage/std_filesystem/pytest_std_filesystem.py +++ b/tools/test_apps/storage/std_filesystem/pytest_std_filesystem.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.qemu @pytest.mark.host_test -@pytest.mark.esp32 -@pytest.mark.esp32c3 +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_std_filesystem(dut: Dut) -> None: dut.expect_exact('All tests passed', timeout=200) diff --git a/tools/test_apps/system/eh_frame/pytest_eh_frame.py b/tools/test_apps/system/eh_frame/pytest_eh_frame.py index 3a3b083b46..7a645b74bd 100644 --- a/tools/test_apps/system/eh_frame/pytest_eh_frame.py +++ b/tools/test_apps/system/eh_frame/pytest_eh_frame.py @@ -1,17 +1,14 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', ['esp32c2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], indirect=['target'] +) def test_eh_frame_wdt(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.confirm_write('"Test task wdt can print backtrace with eh-frame"', expect_str=f'Running') @@ -20,14 +17,10 @@ def test_eh_frame_wdt(dut: Dut) -> None: dut.expect(r'Backtrace: (0x[a-fA-F0-9]+:0x[a-fA-F0-9]+\s*){3,}') -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize( + 'target', ['esp32c2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], indirect=['target'] +) def test_eh_frame_panic(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.confirm_write('"Test panic can print backtrace with eh-frame"', expect_str=f'Running') diff --git a/tools/test_apps/system/esp_intr_dump/pytest_esp_intr_dump.py b/tools/test_apps/system/esp_intr_dump/pytest_esp_intr_dump.py index 9beab78984..7832cd5bf2 100644 --- a/tools/test_apps/system/esp_intr_dump/pytest_esp_intr_dump.py +++ b/tools/test_apps/system/esp_intr_dump/pytest_esp_intr_dump.py @@ -1,16 +1,17 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize PROMPT = 'test_intr_dump>' -@pytest.mark.esp32 @pytest.mark.qemu @pytest.mark.host_test +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_intr_dump_nonshared(dut: Dut) -> None: dut.expect_exact(PROMPT, timeout=30) @@ -22,9 +23,9 @@ def test_esp_intr_dump_nonshared(dut: Dut) -> None: dut.expect(r'(\d+)\s+3\s+Level\s+Used: GPIO') -@pytest.mark.esp32 @pytest.mark.qemu @pytest.mark.host_test +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_intr_dump_shared(dut: Dut) -> None: dut.expect_exact(PROMPT, timeout=30) @@ -47,8 +48,8 @@ def test_esp_intr_dump_shared(dut: Dut) -> None: # TODO: IDF-9512, Update the expected output of dual core RISC-V chips when the issue is resolved -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_intr_dump_expected_output(dut: Dut) -> None: dut.expect_exact(PROMPT, timeout=30) dut.write('intr_dump\n') diff --git a/tools/test_apps/system/gdb_loadable_elf/pytest_gdb_loadable_elf.py b/tools/test_apps/system/gdb_loadable_elf/pytest_gdb_loadable_elf.py index 18ef8b800a..74f1c75204 100644 --- a/tools/test_apps/system/gdb_loadable_elf/pytest_gdb_loadable_elf.py +++ b/tools/test_apps/system/gdb_loadable_elf/pytest_gdb_loadable_elf.py @@ -1,19 +1,16 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 - import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.parametrize('offset', [ - pytest.param('0x40007d54', marks=[pytest.mark.esp32]), - # pytest.param('0x4000f6e2', marks=[pytest.mark.esp32s2]), - # pytest.param('0x40047654', marks=[pytest.mark.esp32c3]), -]) -@pytest.mark.parametrize('embedded_services, skip_autoflash, erase_all', [ - ('esp,idf,jtag', 'y', 'y'), -], indirect=True) @pytest.mark.jtag +@idf_parametrize('embedded_services', ['esp,idf,jtag'], indirect=['embedded_services']) +@idf_parametrize('erase_all', ['y'], indirect=['erase_all']) +@idf_parametrize('offset', ['0x40007d54']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_loadable_elf(dut: IdfDut, offset: str) -> None: dut.gdb.write('mon reset halt') dut.gdb.write(f'thb *{offset}') diff --git a/tools/test_apps/system/gdbstub_runtime/pytest_runtime.py b/tools/test_apps/system/gdbstub_runtime/pytest_runtime.py index f2c3fa2c08..7eddb1886f 100644 --- a/tools/test_apps/system/gdbstub_runtime/pytest_runtime.py +++ b/tools/test_apps/system/gdbstub_runtime/pytest_runtime.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os import os.path as path import sys import pytest +from pytest_embedded_idf.utils import idf_parametrize sys.path.append(path.expandvars(path.join('$IDF_PATH', 'tools', 'test_apps', 'system', 'panic'))) from test_panic_util import PanicTestDut # noqa: E402 @@ -19,8 +20,8 @@ def get_line_number(lookup: str, offset: int = 0) -> int: return -1 -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_gdbstub_runtime(dut: PanicTestDut) -> None: dut.expect_exact('tested app is running.') dut.write(b'\x03') # send Ctrl-C @@ -73,7 +74,9 @@ def test_gdbstub_runtime(dut: PanicTestDut) -> None: # 4200ae5c: f99ff0ef jal ra,4200adf4 # 4200ae60: a011 j 4200ae64 <----------- here after return from foo() # } - assert payload['frame']['line'] == str(get_line_number('label_3:', 1) if dut.is_xtensa else get_line_number('foo();', 0)) + assert payload['frame']['line'] == str( + get_line_number('label_3:', 1) if dut.is_xtensa else get_line_number('foo();', 0) + ) assert payload['frame']['func'] == 'app_main' assert payload['stopped-threads'] == 'all' @@ -156,11 +159,9 @@ def test_gdbstub_runtime(dut: PanicTestDut) -> None: assert payload['stopped-threads'] == 'all' -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic @pytest.mark.temp_skip_ci(targets=['esp32', 'esp32s2', 'esp32s3'], reason='fix IDF-7927') +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target']) def test_gdbstub_runtime_xtensa_stepping_bug(dut: PanicTestDut) -> None: dut.expect_exact('tested app is running.') dut.write(b'\x03') # send Ctrl-C diff --git a/tools/test_apps/system/longjmp_test/pytest_longjmp.py b/tools/test_apps/system/longjmp_test/pytest_longjmp.py index d7e136b569..50f6557de6 100644 --- a/tools/test_apps/system/longjmp_test/pytest_longjmp.py +++ b/tools/test_apps/system/longjmp_test/pytest_longjmp.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target']) def test_sys_longjmp(dut: Dut) -> None: dut.expect_exact('Test successful') diff --git a/tools/test_apps/system/memprot/pytest_memprot.py b/tools/test_apps/system/memprot/pytest_memprot.py index 985ebd3ee8..f5d16cfaf9 100644 --- a/tools/test_apps/system/memprot/pytest_memprot.py +++ b/tools/test_apps/system/memprot/pytest_memprot.py @@ -1,9 +1,10 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize MEM_TEST_UNICORE = { 'esp32s2': [ @@ -13,18 +14,10 @@ MEM_TEST_UNICORE = { ['DRAM0_RTCFAST', 'WR'], ['PERI1_RTCSLOW', 'WR'], ['PERI2_RTCSLOW_0', 'WRX'], - ['PERI2_RTCSLOW_1', 'WRX'] - ], - 'esp32c3': [ - ['IRAM0_SRAM', 'WRX'], - ['DRAM0_SRAM', 'WR'], - ['IRAM0_RTCFAST', 'WRX'] - ], - 'esp32s3': [ - ['IRAM0_SRAM (core 0)', 'WRX'], - ['DRAM0_SRAM (core 0)', 'WR'], - ['IRAM0_RTCFAST (core 0)', 'WRX'] + ['PERI2_RTCSLOW_1', 'WRX'], ], + 'esp32c3': [['IRAM0_SRAM', 'WRX'], ['DRAM0_SRAM', 'WR'], ['IRAM0_RTCFAST', 'WRX']], + 'esp32s3': [['IRAM0_SRAM (core 0)', 'WRX'], ['DRAM0_SRAM (core 0)', 'WR'], ['IRAM0_RTCFAST (core 0)', 'WRX']], } MEM_TEST_MULTICORE = { @@ -34,17 +27,14 @@ MEM_TEST_MULTICORE = { ['IRAM0_RTCFAST (core 0)', 'WRX'], ['IRAM0_SRAM (core 1)', 'WRX'], ['DRAM0_SRAM (core 1)', 'WR'], - ['IRAM0_RTCFAST (core 1)', 'WRX'] + ['IRAM0_RTCFAST (core 1)', 'WRX'], ] } -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32c3'], indirect=['target']) def test_sys_memprot(dut: Dut) -> None: - current_target = dut.target unicore = dut.app.sdkconfig.get('FREERTOS_UNICORE') diff --git a/tools/test_apps/system/mmu_page_size/pytest_mmu_page_size.py b/tools/test_apps/system/mmu_page_size/pytest_mmu_page_size.py index 5986beab7d..3f59bb5421 100644 --- a/tools/test_apps/system/mmu_page_size/pytest_mmu_page_size.py +++ b/tools/test_apps/system/mmu_page_size/pytest_mmu_page_size.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os @@ -6,12 +6,12 @@ import pytest from artifacts_handler import ArtifactType from idf_ci_utils import IDF_PATH from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.generic @pytest.mark.parametrize('config', ['32K'], indirect=True) +@idf_parametrize('target', ['esp32c6', 'esp32h2'], indirect=['target']) def test_app_mmu_page_size_32k_and_bootloader_mmu_page_size_64k(dut: Dut, app_downloader, config) -> None: # type: ignore dut.expect('App is running') @@ -31,10 +31,9 @@ def test_app_mmu_page_size_32k_and_bootloader_mmu_page_size_64k(dut: Dut, app_do dut.expect('Image verified successfully', timeout=30) -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.generic @pytest.mark.parametrize('config', ['64K'], indirect=True) +@idf_parametrize('target', ['esp32c6', 'esp32h2'], indirect=['target']) def test_app_mmu_page_size_64k_and_bootloader_mmu_page_size_32k(dut: Dut, app_downloader, config) -> None: # type: ignore dut.expect('App is running') diff --git a/tools/test_apps/system/panic/pytest_panic.py b/tools/test_apps/system/panic/pytest_panic.py index 199cbf3803..9ea882babd 100644 --- a/tools/test_apps/system/panic/pytest_panic.py +++ b/tools/test_apps/system/panic/pytest_panic.py @@ -10,6 +10,7 @@ from typing import Union import pexpect import pytest +from pytest_embedded_idf.utils import idf_parametrize from test_panic_util import PanicTestDut TARGETS_XTENSA_SINGLE_CORE = [ @@ -108,7 +109,7 @@ CONFIG_COREDUMP_SUMMARY = [pytest.param('coredump_flash_elf_sha', marks=TARGETS_ CONFIG_COREDUMP_SUMMARY_FLASH_ENCRYPTED = [ pytest.param('coredump_flash_encrypted', marks=[pytest.mark.esp32, pytest.mark.esp32c3]), - pytest.param('coredump_flash_encrypted_coredump_plain', marks=[pytest.mark.esp32, pytest.mark.esp32c3]) + pytest.param('coredump_flash_encrypted_coredump_plain', marks=[pytest.mark.esp32, pytest.mark.esp32c3]), ] # Panic abort information will start with this string. @@ -149,8 +150,13 @@ def expect_coredump_uart_write_logs(dut: PanicTestDut, check_cpu_reset: Optional return coredump_base64 -def common_test(dut: PanicTestDut, config: str, expected_backtrace: Optional[List[str]] = None, check_cpu_reset: Optional[bool] = True, - expected_coredump: Optional[Sequence[Union[str, Pattern[Any]]]] = None) -> None: +def common_test( + dut: PanicTestDut, + config: str, + expected_backtrace: Optional[List[str]] = None, + check_cpu_reset: Optional[bool] = True, + expected_coredump: Optional[Sequence[Union[str, Pattern[Any]]]] = None, +) -> None: if 'gdbstub' in config: if 'coredump' in config: uart_str = dut.expect(dut.COREDUMP_CHECKSUM, return_what_before_match=True).decode('utf-8') @@ -183,13 +189,87 @@ def common_test(dut: PanicTestDut, config: str, expected_backtrace: Optional[Lis dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) def test_task_wdt_cpu0(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) - dut.expect_exact( - 'Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:' - ) + dut.expect_exact('Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:') dut.expect_exact('CPU 0: main') if dut.is_xtensa: # on Xtensa, dumping registers on abort is not necessary, we only need to dump the backtrace @@ -203,29 +283,37 @@ def test_task_wdt_cpu0(dut: PanicTestDut, config: str, test_func_name: str) -> N dut.expect_elf_sha256() dut.expect_none('Guru Meditation') - coredump_pattern = (PANIC_ABORT_PREFIX + - 'Task watchdog got triggered. ' - 'The following tasks/users did not reset the watchdog in time:\n - ') + coredump_pattern = ( + PANIC_ABORT_PREFIX + 'Task watchdog got triggered. ' + 'The following tasks/users did not reset the watchdog in time:\n - ' + ) if dut.is_multi_core: coredump_pattern += 'IDLE0 (CPU 0)' else: coredump_pattern += 'IDLE (CPU 0)' common_test( - dut, - config, - expected_backtrace=get_default_backtrace(test_func_name), - expected_coredump=[coredump_pattern] + dut, config, expected_backtrace=get_default_backtrace(test_func_name), expected_coredump=[coredump_pattern] ) -@pytest.mark.parametrize('config', CONFIGS_DUAL_CORE, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config', + [ + 'coredump_flash_bin_crc', + 'coredump_flash_elf_sha', + 'coredump_uart_bin_crc', + 'coredump_uart_elf_crc', + 'gdbstub', + 'panic', + ], + indirect=['config'], +) +@idf_parametrize('target', ['esp32', 'esp32p4', 'esp32s3'], indirect=['target']) def test_task_wdt_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) - dut.expect_exact( - 'Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:' - ) + dut.expect_exact('Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:') dut.expect_exact('CPU 1: Infinite loop') expected_backtrace = ['infinite_loop', 'vPortTaskWrapper'] if dut.is_xtensa: @@ -241,18 +329,25 @@ def test_task_wdt_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> N dut.expect_elf_sha256() dut.expect_none('Guru Meditation') - coredump_pattern = (PANIC_ABORT_PREFIX + - 'Task watchdog got triggered. ' - 'The following tasks/users did not reset the watchdog in time:\n - IDLE1 (CPU 1)') - common_test( - dut, - config, - expected_backtrace=expected_backtrace, - expected_coredump=[coredump_pattern] + coredump_pattern = ( + PANIC_ABORT_PREFIX + 'Task watchdog got triggered. ' + 'The following tasks/users did not reset the watchdog in time:\n - IDLE1 (CPU 1)' ) + common_test(dut, config, expected_backtrace=expected_backtrace, expected_coredump=[coredump_pattern]) -@pytest.mark.parametrize('config', CONFIGS_EXTRAM_STACK, indirect=True) +@idf_parametrize( + 'config,target,markers', + [ + ('coredump_flash_extram_stack_heap_esp32', 'esp32', (pytest.mark.psram,)), + ('coredump_flash_extram_stack_heap_esp32s2', 'esp32s2', (pytest.mark.generic,)), + ('coredump_flash_extram_stack_heap_esp32s3', 'esp32s3', (pytest.mark.quad_psram,)), + ('coredump_flash_extram_stack_bss_esp32', 'esp32', (pytest.mark.psram,)), + ('coredump_flash_extram_stack_bss_esp32s2', 'esp32s2', (pytest.mark.generic,)), + ('coredump_flash_extram_stack_bss_esp32s3', 'esp32s3', (pytest.mark.quad_psram,)), + ], + indirect=['config', 'target'], +) def test_panic_extram_stack(dut: PanicTestDut, config: str) -> None: if 'heap' in config: dut.run_test_func('test_panic_extram_stack_heap') @@ -268,24 +363,95 @@ def test_panic_extram_stack(dut: PanicTestDut, config: str) -> None: coredump_pattern = re.compile('.coredump.tasks.data (0x3[fF][8-9a-bA-B][0-9a-fA-F]{5}) (0x[a-fA-F0-9]+) RW') elif dut.target == 'esp32s2': # ESP32-S2 External data memory range [0x3f500000-0x3ff80000) - coredump_pattern = re.compile('.coredump.tasks.data (0x3[fF][5-9a-fA-F][0-7][0-9a-fA-F]{4}) (0x[a-fA-F0-9]+) RW') + coredump_pattern = re.compile( + '.coredump.tasks.data (0x3[fF][5-9a-fA-F][0-7][0-9a-fA-F]{4}) (0x[a-fA-F0-9]+) RW' + ) else: # ESP32-S3 External data memory range [0x3c000000-0x3e000000) coredump_pattern = re.compile('.coredump.tasks.data (0x3[c-dC-D][0-9a-fA-F]{6}) (0x[a-fA-F0-9]+) RW') - common_test( - dut, - config, - expected_backtrace=None, - expected_coredump=[coredump_pattern] - ) + common_test(dut, config, expected_backtrace=None, expected_coredump=[coredump_pattern]) -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic -def test_int_wdt( - dut: PanicTestDut, target: str, config: str, test_func_name: str -) -> None: +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) +def test_int_wdt(dut: PanicTestDut, target: str, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Interrupt wdt timeout on CPU0') dut.expect_reg_dump(0) @@ -305,11 +471,85 @@ def test_int_wdt( common_test(dut, config, expected_backtrace=get_default_backtrace(test_func_name)) -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic -def test_int_wdt_cache_disabled( - dut: PanicTestDut, target: str, config: str, test_func_name: str -) -> None: +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) +def test_int_wdt_cache_disabled(dut: PanicTestDut, target: str, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Interrupt wdt timeout on CPU0') dut.expect_reg_dump(0) @@ -329,8 +569,84 @@ def test_int_wdt_cache_disabled( common_test(dut, config, expected_backtrace=get_default_backtrace(test_func_name)) -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) def test_cache_error(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.target in ['esp32c3', 'esp32c2']: @@ -356,13 +672,87 @@ def test_cache_error(dut: PanicTestDut, config: str, test_func_name: str) -> Non # 'test_cache_error' missing from GDB backtrace on ESP32-S2 and ESP-S3, IDF-6561 expected_backtrace = ['die', 'app_main', 'main_task', 'vPortTaskWrapper'] - common_test( - dut, config, expected_backtrace=expected_backtrace, check_cpu_reset=(dut.target != 'esp32') - ) + common_test(dut, config, expected_backtrace=expected_backtrace, check_cpu_reset=(dut.target != 'esp32')) -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) def test_stack_overflow(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.is_xtensa: @@ -382,11 +772,85 @@ def test_stack_overflow(dut: PanicTestDut, config: str, test_func_name: str) -> common_test(dut, config, expected_backtrace=get_default_backtrace(test_func_name)) -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic -def test_instr_fetch_prohibited( - dut: PanicTestDut, config: str, test_func_name: str -) -> None: +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) +def test_instr_fetch_prohibited(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.is_xtensa: dut.expect_gme('InstrFetchProhibited') @@ -411,11 +875,85 @@ def test_instr_fetch_prohibited( ) -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic -def test_illegal_instruction( - dut: PanicTestDut, config: str, test_func_name: str -) -> None: +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) +def test_illegal_instruction(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.is_xtensa: dut.expect_gme('IllegalInstruction') @@ -449,20 +987,248 @@ def check_x_prohibited(dut: PanicTestDut, config: str, test_func_name: str, oper common_test(dut, config, expected_backtrace=get_default_backtrace(test_func_name)) -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) def test_storeprohibited(dut: PanicTestDut, config: str, test_func_name: str) -> None: check_x_prohibited(dut, config, test_func_name, 'Store') -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) def test_loadprohibited(dut: PanicTestDut, config: str, test_func_name: str) -> None: check_x_prohibited(dut, config, test_func_name, 'Load') -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) def test_abort(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) regex_pattern = rb'abort\(\) was called at PC [0-9xa-f]+ on core 0' @@ -478,17 +1244,29 @@ def test_abort(dut: PanicTestDut, config: str, test_func_name: str) -> None: common_test( dut, config, - expected_backtrace=[ - 'panic_abort', - 'esp_system_abort', - 'abort' - ] + get_default_backtrace(test_func_name), - expected_coredump=[coredump_pattern] + expected_backtrace=['panic_abort', 'esp_system_abort', 'abort'] + get_default_backtrace(test_func_name), + expected_coredump=[coredump_pattern], ) -@pytest.mark.parametrize('config', CONFIGS_UBSAN, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('gdbstub', 'supported_targets'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) def test_ub(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) regex_pattern = rb'Undefined behavior of type out_of_bounds' @@ -507,16 +1285,91 @@ def test_ub(dut: PanicTestDut, config: str, test_func_name: str) -> None: 'panic_abort', 'esp_system_abort', '__ubsan_default_handler', - '__ubsan_handle_out_of_bounds' - ] + get_default_backtrace(test_func_name) + '__ubsan_handle_out_of_bounds', + ] + + get_default_backtrace(test_func_name), ) -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic -def test_abort_cache_disabled( - dut: PanicTestDut, config: str, test_func_name: str -) -> None: +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) +def test_abort_cache_disabled(dut: PanicTestDut, config: str, test_func_name: str) -> None: if dut.target == 'esp32s2': pytest.xfail(reason='Crashes in itoa which is not in ROM, IDF-3572') dut.run_test_func(test_func_name) @@ -533,17 +1386,89 @@ def test_abort_cache_disabled( common_test( dut, config, - expected_backtrace=[ - 'panic_abort', - 'esp_system_abort', - 'abort' - ] + get_default_backtrace(test_func_name), - expected_coredump=[coredump_pattern] + expected_backtrace=['panic_abort', 'esp_system_abort', 'abort'] + get_default_backtrace(test_func_name), + expected_coredump=[coredump_pattern], ) -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) def test_assert(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) regex_pattern = rb'assert failed:[\s\w()]*?\s[.\w/]*\.(?:c|cpp|h|hpp):\d.*$' @@ -559,20 +1484,90 @@ def test_assert(dut: PanicTestDut, config: str, test_func_name: str) -> None: common_test( dut, config, - expected_backtrace=[ - 'panic_abort', - 'esp_system_abort', - '__assert_func' - ] + get_default_backtrace(test_func_name), - expected_coredump=[coredump_pattern] + expected_backtrace=['panic_abort', 'esp_system_abort', '__assert_func'] + get_default_backtrace(test_func_name), + expected_coredump=[coredump_pattern], ) -@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.generic -def test_assert_cache_disabled( - dut: PanicTestDut, config: str, test_func_name: str -) -> None: +@idf_parametrize( + 'config,target', + [ + ('coredump_flash_bin_crc', 'supported_targets'), + ('coredump_flash_elf_sha', 'esp32'), + ('coredump_flash_elf_sha', 'esp32c2'), + ('coredump_flash_elf_sha', 'esp32c3'), + ('coredump_flash_elf_sha', 'esp32c5'), + ('coredump_flash_elf_sha', 'esp32c6'), + ('coredump_flash_elf_sha', 'esp32c61'), + ('coredump_flash_elf_sha', 'esp32h2'), + ('coredump_flash_elf_sha', 'esp32p4'), + ('coredump_flash_elf_sha', 'esp32s2'), + ('coredump_flash_elf_sha', 'esp32s3'), + ('coredump_flash_elf_soft_sha', 'esp32'), + ('coredump_flash_elf_soft_sha', 'esp32c2'), + ('coredump_flash_elf_soft_sha', 'esp32c3'), + ('coredump_flash_elf_soft_sha', 'esp32c5'), + ('coredump_flash_elf_soft_sha', 'esp32c6'), + ('coredump_flash_elf_soft_sha', 'esp32c61'), + ('coredump_flash_elf_soft_sha', 'esp32h2'), + ('coredump_flash_elf_soft_sha', 'esp32p4'), + ('coredump_flash_elf_soft_sha', 'esp32s2'), + ('coredump_flash_elf_soft_sha', 'esp32s3'), + ('coredump_uart_bin_crc', 'esp32'), + ('coredump_uart_bin_crc', 'esp32c2'), + ('coredump_uart_bin_crc', 'esp32c3'), + ('coredump_uart_bin_crc', 'esp32c5'), + ('coredump_uart_bin_crc', 'esp32c6'), + ('coredump_uart_bin_crc', 'esp32c61'), + ('coredump_uart_bin_crc', 'esp32h2'), + ('coredump_uart_bin_crc', 'esp32p4'), + ('coredump_uart_bin_crc', 'esp32s2'), + ('coredump_uart_bin_crc', 'esp32s3'), + ('coredump_uart_elf_crc', 'esp32'), + ('coredump_uart_elf_crc', 'esp32c2'), + ('coredump_uart_elf_crc', 'esp32c3'), + ('coredump_uart_elf_crc', 'esp32c5'), + ('coredump_uart_elf_crc', 'esp32c6'), + ('coredump_uart_elf_crc', 'esp32c61'), + ('coredump_uart_elf_crc', 'esp32h2'), + ('coredump_uart_elf_crc', 'esp32p4'), + ('coredump_uart_elf_crc', 'esp32s2'), + ('coredump_uart_elf_crc', 'esp32s3'), + ('coredump_flash_custom_stack', 'esp32'), + ('coredump_flash_custom_stack', 'esp32c2'), + ('coredump_flash_custom_stack', 'esp32c3'), + ('coredump_flash_custom_stack', 'esp32c5'), + ('coredump_flash_custom_stack', 'esp32c6'), + ('coredump_flash_custom_stack', 'esp32c61'), + ('coredump_flash_custom_stack', 'esp32h2'), + ('coredump_flash_custom_stack', 'esp32p4'), + ('coredump_flash_custom_stack', 'esp32s2'), + ('coredump_flash_custom_stack', 'esp32s3'), + ('gdbstub', 'esp32'), + ('gdbstub', 'esp32c2'), + ('gdbstub', 'esp32c3'), + ('gdbstub', 'esp32c5'), + ('gdbstub', 'esp32c6'), + ('gdbstub', 'esp32c61'), + ('gdbstub', 'esp32h2'), + ('gdbstub', 'esp32p4'), + ('gdbstub', 'esp32s2'), + ('gdbstub', 'esp32s3'), + ('panic', 'esp32'), + ('panic', 'esp32c2'), + ('panic', 'esp32c3'), + ('panic', 'esp32c5'), + ('panic', 'esp32c6'), + ('panic', 'esp32c61'), + ('panic', 'esp32h2'), + ('panic', 'esp32p4'), + ('panic', 'esp32s2'), + ('panic', 'esp32s3'), + ], + indirect=['config', 'target'], +) +def test_assert_cache_disabled(dut: PanicTestDut, config: str, test_func_name: str) -> None: if dut.target == 'esp32s2': pytest.xfail(reason='Crashes in itoa which is not in ROM, IDF-3572') dut.run_test_func(test_func_name) @@ -589,19 +1584,17 @@ def test_assert_cache_disabled( common_test( dut, config, - expected_backtrace=[ - 'panic_abort', - 'esp_system_abort', - '__assert_func' - ] + get_default_backtrace(test_func_name), - expected_coredump=[coredump_pattern] + expected_backtrace=['panic_abort', 'esp_system_abort', '__assert_func'] + get_default_backtrace(test_func_name), + expected_coredump=[coredump_pattern], ) def cache_error_log_check(dut: PanicTestDut) -> None: if dut.is_xtensa: if dut.target == 'esp32s3': - dut.expect_exact("Guru Meditation Error: Core / panic'ed (Cache disabled but cached memory region accessed)") + dut.expect_exact( + "Guru Meditation Error: Core / panic'ed (Cache disabled but cached memory region accessed)" + ) dut.expect_exact('Write back error occurred while dcache tries to write back to flash') dut.expect_exact('The following backtrace may not indicate the code that caused Cache invalid access') else: @@ -615,18 +1608,16 @@ def cache_error_log_check(dut: PanicTestDut) -> None: @pytest.mark.generic -@pytest.mark.supported_targets @pytest.mark.parametrize('config', ['panic'], indirect=True) -def test_assert_cache_write_back_error_can_print_backtrace( - dut: PanicTestDut, config: str, test_func_name: str -) -> None: +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_assert_cache_write_back_error_can_print_backtrace(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) cache_error_log_check(dut) @pytest.mark.generic -@pytest.mark.supported_targets @pytest.mark.parametrize('config', ['panic'], indirect=True) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_assert_cache_write_back_error_can_print_backtrace2( dut: PanicTestDut, config: str, test_func_name: str ) -> None: @@ -634,9 +1625,9 @@ def test_assert_cache_write_back_error_can_print_backtrace2( cache_error_log_check(dut) -@pytest.mark.esp32 @pytest.mark.generic @pytest.mark.parametrize('config', ['panic_delay'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_panic_delay(dut: PanicTestDut) -> None: dut.run_test_func('test_storeprohibited') try: @@ -653,8 +1644,8 @@ def test_panic_delay(dut: PanicTestDut) -> None: @pytest.mark.parametrize('config', ['panic'], indirect=True) -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_panic_handler_stuck0(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -666,10 +1657,8 @@ def test_panic_handler_stuck0(dut: PanicTestDut, config: str, test_func_name: st @pytest.mark.parametrize('config', ['panic'], indirect=True) -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32p4'], indirect=['target']) def test_panic_handler_stuck1(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -681,8 +1670,8 @@ def test_panic_handler_stuck1(dut: PanicTestDut, config: str, test_func_name: st @pytest.mark.parametrize('config', ['panic'], indirect=True) -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_panic_handler_crash0(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -700,10 +1689,8 @@ def test_panic_handler_crash0(dut: PanicTestDut, config: str, test_func_name: st @pytest.mark.parametrize('config', ['panic'], indirect=True) -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32p4'], indirect=['target']) def test_panic_handler_crash1(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -734,7 +1721,7 @@ CONFIGS_MEMPROT_IDRAM = [ pytest.param('memprot_esp32c6', marks=[pytest.mark.esp32c6]), pytest.param('memprot_esp32c61', marks=[pytest.mark.esp32c61]), pytest.param('memprot_esp32h2', marks=[pytest.mark.esp32h2]), - pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4]) + pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4]), ] CONFIGS_MEMPROT_DCACHE = [ @@ -747,7 +1734,7 @@ CONFIGS_MEMPROT_RTC_FAST_MEM = [ pytest.param('memprot_esp32c5', marks=[pytest.mark.esp32c5]), pytest.param('memprot_esp32c6', marks=[pytest.mark.esp32c6]), pytest.param('memprot_esp32h2', marks=[pytest.mark.esp32h2]), - pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4]) + pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4]), ] CONFIGS_MEMPROT_RTC_SLOW_MEM = [ @@ -759,20 +1746,20 @@ CONFIGS_MEMPROT_FLASH_IDROM = [ pytest.param('memprot_esp32c6', marks=[pytest.mark.esp32c6]), pytest.param('memprot_esp32c61', marks=[pytest.mark.esp32c61]), pytest.param('memprot_esp32h2', marks=[pytest.mark.esp32h2]), - pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4]) + pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4]), ] CONFIGS_MEMPROT_SPIRAM_XIP_IROM_ALIGNMENT_HEAP = [ pytest.param('memprot_spiram_xip_esp32c5', marks=[pytest.mark.esp32c5]), pytest.param('memprot_spiram_xip_esp32c61', marks=[pytest.mark.esp32c61]), - pytest.param('memprot_spiram_xip_esp32p4', marks=[pytest.mark.esp32p4]) + pytest.param('memprot_spiram_xip_esp32p4', marks=[pytest.mark.esp32p4]), ] CONFIGS_MEMPROT_SPIRAM_XIP_DROM_ALIGNMENT_HEAP = [ pytest.param('memprot_spiram_xip_esp32s3', marks=[pytest.mark.esp32s3]), pytest.param('memprot_spiram_xip_esp32c5', marks=[pytest.mark.esp32c5]), pytest.param('memprot_spiram_xip_esp32c61', marks=[pytest.mark.esp32c61]), - pytest.param('memprot_spiram_xip_esp32p4', marks=[pytest.mark.esp32p4]) + pytest.param('memprot_spiram_xip_esp32p4', marks=[pytest.mark.esp32p4]), ] CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA = [ @@ -780,12 +1767,13 @@ CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA = [ pytest.param('memprot_esp32c6', marks=[pytest.mark.esp32c6]), pytest.param('memprot_esp32c61', marks=[pytest.mark.esp32c61]), pytest.param('memprot_esp32h2', marks=[pytest.mark.esp32h2]), - pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4]) + pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4]), ] -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_DCACHE, indirect=True) @pytest.mark.generic +@idf_parametrize('config', ['memprot_esp32s2'], indirect=['config']) +@idf_parametrize('target', ['esp32s2'], indirect=['target']) def test_dcache_read_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_exact(r'Test error: Test function has returned') @@ -793,9 +1781,10 @@ def test_dcache_read_violation(dut: PanicTestDut, test_func_name: str) -> None: # TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_DCACHE, indirect=True) @pytest.mark.generic @pytest.mark.xfail('config.getvalue("target") == "esp32s2"', reason='Incorrect panic reason may be observed', run=False) +@idf_parametrize('config', ['memprot_esp32s2'], indirect=['config']) +@idf_parametrize('target', ['esp32s2'], indirect=['target']) def test_dcache_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Memory protection fault') @@ -805,8 +1794,21 @@ def test_dcache_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_IDRAM, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32s2', 'esp32s2'), + ('memprot_esp32c3', 'esp32c3'), + ('memprot_esp32c2', 'esp32c2'), + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_iram_reg1_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -825,8 +1827,21 @@ def test_iram_reg1_write_violation(dut: PanicTestDut, test_func_name: str) -> No dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_IDRAM, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32s2', 'esp32s2'), + ('memprot_esp32c3', 'esp32c3'), + ('memprot_esp32c2', 'esp32c2'), + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_iram_reg2_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -850,8 +1865,21 @@ def test_iram_reg2_write_violation(dut: PanicTestDut, test_func_name: str) -> No dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_IDRAM, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32s2', 'esp32s2'), + ('memprot_esp32c3', 'esp32c3'), + ('memprot_esp32c2', 'esp32c2'), + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_iram_reg3_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -876,9 +1904,22 @@ def test_iram_reg3_write_violation(dut: PanicTestDut, test_func_name: str) -> No # TODO: IDF-6820: ESP32-S2 -> Fix incorrect panic reason: Unhandled debug exception -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_IDRAM, indirect=True) @pytest.mark.generic @pytest.mark.xfail('config.getvalue("target") == "esp32s2"', reason='Incorrect panic reason may be observed', run=False) +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32s2', 'esp32s2'), + ('memprot_esp32c3', 'esp32c3'), + ('memprot_esp32c2', 'esp32c2'), + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_iram_reg4_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -903,9 +1944,24 @@ def test_iram_reg4_write_violation(dut: PanicTestDut, test_func_name: str) -> No # TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_IDRAM, indirect=True) @pytest.mark.generic -@pytest.mark.xfail('config.getvalue("target") == "esp32s2"', reason='Multiple panic reasons for the same test may surface', run=False) +@pytest.mark.xfail( + 'config.getvalue("target") == "esp32s2"', reason='Multiple panic reasons for the same test may surface', run=False +) +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32s2', 'esp32s2'), + ('memprot_esp32c3', 'esp32c3'), + ('memprot_esp32c2', 'esp32c2'), + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -923,9 +1979,24 @@ def test_dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> # TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_IDRAM, indirect=True) @pytest.mark.generic -@pytest.mark.xfail('config.getvalue("target") == "esp32s2"', reason='Multiple panic reasons for the same test may surface', run=False) +@pytest.mark.xfail( + 'config.getvalue("target") == "esp32s2"', reason='Multiple panic reasons for the same test may surface', run=False +) +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32s2', 'esp32s2'), + ('memprot_esp32c3', 'esp32c3'), + ('memprot_esp32c2', 'esp32c2'), + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -941,17 +2012,42 @@ def test_dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_RTC_FAST_MEM, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32s2', 'esp32s2'), + ('memprot_esp32c3', 'esp32c3'), + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_rtc_fast_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_exact(r'Test error: Test function has returned') dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_RTC_FAST_MEM, indirect=True) @pytest.mark.generic -@pytest.mark.skipif('config.getvalue("target") in ["esp32c5", "esp32c6", "esp32h2", "esp32p4"]', reason='Not a violation condition, no PMS peripheral case') +@pytest.mark.skipif( + 'config.getvalue("target") in ["esp32c5", "esp32c6", "esp32h2", "esp32p4"]', + reason='Not a violation condition, no PMS peripheral case', +) +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32s2', 'esp32s2'), + ('memprot_esp32c3', 'esp32c3'), + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_rtc_fast_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Memory protection fault') @@ -971,9 +2067,22 @@ def test_rtc_fast_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) # TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_RTC_FAST_MEM, indirect=True) @pytest.mark.generic -@pytest.mark.xfail('config.getvalue("target") == "esp32s2"', reason='Multiple panic reasons for the same test may surface', run=False) +@pytest.mark.xfail( + 'config.getvalue("target") == "esp32s2"', reason='Multiple panic reasons for the same test may surface', run=False +) +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32s2', 'esp32s2'), + ('memprot_esp32c3', 'esp32c3'), + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_rtc_fast_reg3_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) @@ -997,8 +2106,9 @@ def test_rtc_fast_reg3_execute_violation(dut: PanicTestDut, test_func_name: str) dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_RTC_SLOW_MEM, indirect=True) @pytest.mark.generic +@idf_parametrize('config', ['memprot_esp32s2'], indirect=['config']) +@idf_parametrize('target', ['esp32s2'], indirect=['target']) def test_rtc_slow_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Memory protection fault') @@ -1008,8 +2118,9 @@ def test_rtc_slow_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_RTC_SLOW_MEM, indirect=True) @pytest.mark.generic +@idf_parametrize('config', ['memprot_esp32s2'], indirect=['config']) +@idf_parametrize('target', ['esp32s2'], indirect=['target']) def test_rtc_slow_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Memory protection fault') @@ -1019,8 +2130,18 @@ def test_rtc_slow_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_FLASH_IDROM, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_irom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Store access fault') @@ -1028,8 +2149,18 @@ def test_irom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> Non dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_FLASH_IDROM, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_drom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Store access fault') @@ -1037,8 +2168,18 @@ def test_drom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> Non dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_FLASH_IDROM, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_drom_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Instruction access fault') @@ -1046,8 +2187,16 @@ def test_drom_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> N dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_SPIRAM_XIP_IROM_ALIGNMENT_HEAP, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('memprot_spiram_xip_esp32c5', 'esp32c5'), + ('memprot_spiram_xip_esp32c61', 'esp32c61'), + ('memprot_spiram_xip_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_spiram_xip_irom_alignment_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) try: @@ -1058,8 +2207,17 @@ def test_spiram_xip_irom_alignment_reg_execute_violation(dut: PanicTestDut, test dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_SPIRAM_XIP_DROM_ALIGNMENT_HEAP, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('memprot_spiram_xip_esp32s3', 'esp32s3'), + ('memprot_spiram_xip_esp32c5', 'esp32c5'), + ('memprot_spiram_xip_esp32c61', 'esp32c61'), + ('memprot_spiram_xip_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_spiram_xip_drom_alignment_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) try: @@ -1074,7 +2232,17 @@ def test_spiram_xip_drom_alignment_reg_execute_violation(dut: PanicTestDut, test @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA, indirect=True) +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_invalid_memory_region_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Store access fault') @@ -1082,8 +2250,18 @@ def test_invalid_memory_region_write_violation(dut: PanicTestDut, test_func_name dut.expect_cpu_reset() -@pytest.mark.parametrize('config', CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config,target', + [ + ('memprot_esp32c5', 'esp32c5'), + ('memprot_esp32c6', 'esp32c6'), + ('memprot_esp32c61', 'esp32c61'), + ('memprot_esp32h2', 'esp32h2'), + ('memprot_esp32p4', 'esp32p4'), + ], + indirect=['config', 'target'], +) def test_invalid_memory_region_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Instruction access fault') @@ -1091,9 +2269,9 @@ def test_invalid_memory_region_execute_violation(dut: PanicTestDut, test_func_na dut.expect_cpu_reset() -@pytest.mark.esp32 @pytest.mark.generic @pytest.mark.parametrize('config', ['gdbstub_coredump'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_gdbstub_coredump(dut: PanicTestDut) -> None: test_func_name = 'test_storeprohibited' dut.run_test_func(test_func_name) @@ -1101,7 +2279,7 @@ def test_gdbstub_coredump(dut: PanicTestDut) -> None: def test_hw_stack_guard_cpu(dut: PanicTestDut, cpu: int) -> None: - dut.expect_exact(f'Guru Meditation Error: Core {cpu} panic\'ed (Stack protection fault).') + dut.expect_exact(f"Guru Meditation Error: Core {cpu} panic'ed (Stack protection fault).") dut.expect_none('ASSIST_DEBUG is not triggered BUT interrupt occurred!') dut.expect_exact(f'Detected in task "HWSG{cpu}"') addr = dut.expect('at 0x([0-9a-fA-F]{8})') @@ -1118,25 +2296,37 @@ def test_hw_stack_guard_cpu(dut: PanicTestDut, cpu: int) -> None: @pytest.mark.temp_skip_ci(targets=['esp32c5', 'esp32c61'], reason='TODO: IDF-8662 and IDF-9269') -@pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config', + ['coredump_flash_bin_crc', 'coredump_uart_bin_crc', 'coredump_uart_elf_crc', 'gdbstub', 'panic'], + indirect=['config'], +) +@idf_parametrize( + 'target', ['esp32c2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], indirect=['target'] +) def test_hw_stack_guard_cpu0(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) test_hw_stack_guard_cpu(dut, 0) common_test(dut, config) -@pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD_DUAL_CORE, indirect=True) @pytest.mark.generic +@idf_parametrize( + 'config', + ['coredump_flash_bin_crc', 'coredump_uart_bin_crc', 'coredump_uart_elf_crc', 'gdbstub', 'panic'], + indirect=['config'], +) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_hw_stack_guard_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) test_hw_stack_guard_cpu(dut, 1) common_test(dut, config) -@pytest.mark.esp32 @pytest.mark.parametrize('config', ['panic'], indirect=True) @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_illegal_access(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.is_xtensa: @@ -1148,8 +2338,9 @@ def test_illegal_access(dut: PanicTestDut, config: str, test_func_name: str) -> dut.expect_none('Guru Meditation') -@pytest.mark.parametrize('config', CONFIG_CAPTURE_DRAM, indirect=True) @pytest.mark.generic +@idf_parametrize('config', ['coredump_flash_capture_dram'], indirect=['config']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_capture_dram(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) regex_pattern = rb'assert failed:[\s\w()]*?\s[.\w/]*\.(?:c|cpp|h|hpp):\d.*$' @@ -1196,19 +2387,22 @@ def _test_coredump_summary(dut: PanicTestDut, flash_encrypted: bool, coredump_en @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIG_COREDUMP_SUMMARY, indirect=True) +@idf_parametrize('config', ['coredump_flash_elf_sha'], indirect=['config']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_coredump_summary(dut: PanicTestDut) -> None: _test_coredump_summary(dut, False, False) @pytest.mark.flash_encryption -@pytest.mark.parametrize('config', CONFIG_COREDUMP_SUMMARY_FLASH_ENCRYPTED, indirect=True) +@idf_parametrize('config', ['coredump_flash_encrypted', 'coredump_flash_encrypted_coredump_plain'], indirect=['config']) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_coredump_summary_flash_encrypted(dut: PanicTestDut, config: str) -> None: _test_coredump_summary(dut, True, config == 'coredump_flash_encrypted') -@pytest.mark.parametrize('config', [pytest.param('coredump_flash_elf_sha', marks=TARGETS_ALL)], indirect=True) @pytest.mark.generic +@idf_parametrize('config', ['coredump_flash_elf_sha'], indirect=['config']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_tcb_corrupted(dut: PanicTestDut, target: str, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.is_xtensa: @@ -1227,25 +2421,22 @@ def test_tcb_corrupted(dut: PanicTestDut, target: str, config: str, test_func_na # TCB NAME # ---------- ---------------- if dut.is_multi_core: - regex_patterns = [rb'[0-9xa-fA-F] main', - rb'[0-9xa-fA-F] ipc0', - rb'[0-9xa-fA-F] ipc1'] + regex_patterns = [ + rb'[0-9xa-fA-F] main', + rb'[0-9xa-fA-F] ipc0', + rb'[0-9xa-fA-F] ipc1', + ] else: regex_patterns = [rb'[0-9xa-fA-F] main'] coredump_pattern = [re.compile(pattern.decode('utf-8')) for pattern in regex_patterns] - common_test( - dut, - config, - expected_backtrace=None, - expected_coredump=coredump_pattern - ) + common_test(dut, config, expected_backtrace=None, expected_coredump=coredump_pattern) @pytest.mark.generic -@pytest.mark.supported_targets @pytest.mark.parametrize('config', ['panic_halt'], indirect=True) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_panic_halt(dut: PanicTestDut) -> None: dut.run_test_func('test_panic_halt') dut.expect_exact('CPU halted.', timeout=30) 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 index 8329cfc3f6..c49df127f1 100644 --- 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 @@ -1,53 +1,70 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32c61 @pytest.mark.generic -@pytest.mark.parametrize('config', ['pure_ram',], indirect=True,) +@pytest.mark.parametrize( + 'config', + [ + 'pure_ram', + ], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c2', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32c61'], + indirect=['target'], +) def test_pure_ram_loadable_app(dut: IdfDut) -> None: dut.expect('main_task: Calling app_main()', timeout=10) dut.expect('Time since boot: 3 seconds...', timeout=10) -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32c61 @pytest.mark.generic -@pytest.mark.parametrize('config', ['defaults',], indirect=True,) +@pytest.mark.parametrize( + 'config', + [ + 'defaults', + ], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32', 'esp32s2', 'esp32s3', 'esp32c2', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32c61'], + indirect=['target'], +) def test_ram_loadable_app(dut: IdfDut) -> None: dut.expect('spi_flash: detected chip', timeout=10) dut.expect('Time since boot: 3 seconds...', timeout=30) # Tests with ram_app runners -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.ram_app -@pytest.mark.parametrize('config', ['defaults',], indirect=True,) +@pytest.mark.parametrize( + 'config', + [ + 'defaults', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32p4', 'esp32c5'], indirect=['target']) def test_ram_loadable_app_with_ram_app_runner(dut: IdfDut) -> None: dut.expect('spi_flash: detected chip', timeout=10) dut.expect('Time since boot: 3 seconds...', timeout=30) -@pytest.mark.esp32p4 -@pytest.mark.esp32c5 @pytest.mark.ram_app -@pytest.mark.parametrize('config', ['pure_ram',], indirect=True,) +@pytest.mark.parametrize( + 'config', + [ + 'pure_ram', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32p4', 'esp32c5'], indirect=['target']) def test_pure_ram_loadable_app_with_ram_app_runner(dut: IdfDut) -> None: dut.expect('main_task: Calling app_main()', timeout=10) dut.expect('Time since boot: 3 seconds...', timeout=10) diff --git a/tools/test_apps/system/rtc_mem_reserve/pytest_rtc_mem_reserve.py b/tools/test_apps/system/rtc_mem_reserve/pytest_rtc_mem_reserve.py index 3a4e4de34a..5ccd07d284 100644 --- a/tools/test_apps/system/rtc_mem_reserve/pytest_rtc_mem_reserve.py +++ b/tools/test_apps/system/rtc_mem_reserve/pytest_rtc_mem_reserve.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_rtc_mem_reserve(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/tools/test_apps/system/startup/pytest_startup.py b/tools/test_apps/system/startup/pytest_startup.py index 75dbf1ecbe..dc33558172 100644 --- a/tools/test_apps/system/startup/pytest_startup.py +++ b/tools/test_apps/system/startup/pytest_startup.py @@ -1,31 +1,39 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.parametrize('config', [ - pytest.param('flash_80m_qio', marks=[pytest.mark.supported_targets]), - pytest.param('no_vfs', marks=[pytest.mark.supported_targets]), - pytest.param('no_vfs_partial', marks=[pytest.mark.supported_targets]), - pytest.param('opt_o0', marks=[pytest.mark.supported_targets]), - pytest.param('opt_o2', marks=[pytest.mark.supported_targets]), - pytest.param('stack_check_verbose_log', marks=[pytest.mark.supported_targets]), - pytest.param('sram1_iram', marks=[pytest.mark.esp32]), - pytest.param('main_task_cpu1', marks=[pytest.mark.esp32, pytest.mark.esp32s3]), -], indirect=True) +@idf_parametrize( + 'config,target', + [ + ('flash_80m_qio', 'supported_targets'), + ('no_vfs', 'supported_targets'), + ('no_vfs_partial', 'supported_targets'), + ('opt_o0', 'supported_targets'), + ('opt_o2', 'supported_targets'), + ('stack_check_verbose_log', 'supported_targets'), + ('sram1_iram', 'esp32'), + ('main_task_cpu1', 'esp32'), + ('main_task_cpu1', 'esp32s3'), + ], + indirect=['config', 'target'], +) def test_sys_startup(dut: Dut) -> None: dut.expect_exact('app_main running') -@pytest.mark.esp32 -@pytest.mark.esp32s3 @pytest.mark.generic -@pytest.mark.parametrize('config', [ - 'single_core_variant', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'single_core_variant', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32', 'esp32s3'], indirect=['target']) def test_sys_startup_single_core_variant(dut: Dut) -> None: dut.expect('Running on single core variant of a chip, but app is built with multi-core support.') dut.expect(r'abort\(\) was called at PC [0-9xa-f]+ on core 0') diff --git a/tools/test_apps/system/test_watchpoint/pytest_watchpoint.py b/tools/test_apps/system/test_watchpoint/pytest_watchpoint.py index 0d61d757b3..cba08c560d 100644 --- a/tools/test_apps/system/test_watchpoint/pytest_watchpoint.py +++ b/tools/test_apps/system/test_watchpoint/pytest_watchpoint.py @@ -1,12 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_watchpoint(dut: Dut) -> None: dut.expect_exact('stacks clean', timeout=3) diff --git a/tools/test_apps/system/unicore_bootloader/pytest_unicore_bootloader.py b/tools/test_apps/system/unicore_bootloader/pytest_unicore_bootloader.py index da16ff07db..89fd8a2cb0 100644 --- a/tools/test_apps/system/unicore_bootloader/pytest_unicore_bootloader.py +++ b/tools/test_apps/system/unicore_bootloader/pytest_unicore_bootloader.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os import re @@ -7,13 +7,12 @@ import pytest from artifacts_handler import ArtifactType from idf_ci_utils import IDF_PATH from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', ['multicore', 'multicore_psram'], indirect=True) +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32p4'], indirect=['target']) def test_multicore_app_and_unicore_bootloader(dut: Dut, app_downloader, config) -> None: # type: ignore dut.expect('Multicore bootloader') dut.expect('Multicore app') @@ -37,11 +36,9 @@ def test_multicore_app_and_unicore_bootloader(dut: Dut, app_downloader, config) dut.expect('NVS test done\n') -@pytest.mark.esp32 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', ['unicore', 'unicore_psram'], indirect=True) +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32p4'], indirect=['target']) def test_unicore_app_and_multicore_bootloader(dut: Dut, app_downloader, config) -> None: # type: ignore dut.expect('Unicore bootloader') dut.expect('Unicore app')