From daf2d31008446592c66479e11484d79b94ef1d92 Mon Sep 17 00:00:00 2001 From: "igor.udot" Date: Mon, 24 Feb 2025 10:18:03 +0800 Subject: [PATCH] test: format all test scripts --- .../test_app_update/pytest_app_update_ut.py | 22 +- .../pytest_bootloader_support.py | 10 +- .../rtc_custom_section/pytest_rtc_mem.py | 16 +- .../basic_unit_test/pytest_basic_unit_test.py | 6 +- .../memory_release/pytest_memory_release.py | 18 +- .../test_apps/console/pytest_console.py | 249 ++- .../exception/pytest_cxx_exception.py | 7 +- .../pytest_cxx_exception_no_except.py | 10 +- .../test_apps/general/pytest_cxx_general.py | 19 +- .../cxx/test_apps/rtti/pytest_cxx_rtti.py | 7 +- .../legacy_dac_driver/pytest_legacy_dac.py | 7 +- .../pytest_legacy_i2s_adc_dac.py | 6 +- .../legacy_i2s_driver/pytest_legacy_i2s.py | 17 +- .../legacy_adc_driver/pytest_legacy_adc.py | 18 +- .../pytest_legacy_mcpwm.py | 10 +- .../legacy_pcnt_driver/pytest_legacy_pcnt.py | 13 +- .../pytest_legacy_rmt_driver.py | 26 +- .../pytest_legacy_temp_sensor_driver.py | 27 +- .../pytest_legacy_sigma_delta.py | 19 +- .../pytest_legacy_timer_driver.py | 15 +- .../touch_sensor_v1/pytest_touch_sensor_v1.py | 5 +- .../touch_sensor_v2/pytest_touch_sensor_v2.py | 6 +- .../driver/test_apps/twai/pytest_twai.py | 35 +- components/efuse/test_apps/pytest_efuse.py | 13 +- .../esp-tls/test_apps/pytest_esp-tls.py | 5 +- .../esp_adc/test_apps/adc/pytest_adc.py | 41 +- .../test_apps/pytest_esp_app_format.py | 9 +- .../test_apps/pytest_esp_bootloader_format.py | 5 +- .../test_apps/esp_common/pytest_esp_common.py | 50 +- .../analog_comparator/pytest_ana_cmpr.py | 8 +- .../bitscrambler/pytest_bitscrambler.py | 4 +- .../test_apps/csi/pytest_csi.py | 5 +- .../test_apps/dvp/pytest_dvp.py | 5 +- .../test_apps/isp_dvp/pytest_isp_dvp.py | 5 +- .../test_apps/dac/pytest_dac.py | 7 +- .../test_apps/gpio/pytest_gpio.py | 15 +- .../gpio_extensions/pytest_gpio_extensions.py | 31 +- .../test_apps/gptimer/pytest_gptimer.py | 8 +- .../test_apps/i2c_test_apps/pytest_i2c.py | 40 +- .../test_apps/i2s/pytest_i2s.py | 17 +- .../i2s_multi_dev/pytest_i2s_multi_dev.py | 20 +- .../test_apps/lp_i2s/pytest_lp_i2s.py | 5 +- .../test_apps/jpeg_test_apps/pytest_jpeg.py | 5 +- .../test_apps/ledc/pytest_ledc.py | 31 +- .../test_apps/mcpwm/pytest_mcpwm.py | 10 +- .../test_apps/parlio/pytest_parlio_unity.py | 8 +- .../test_apps/pulse_cnt/pytest_pulse_cnt.py | 13 +- .../esp_driver_ppa/test_apps/pytest_ppa.py | 5 +- .../test_apps/rmt/pytest_rmt.py | 15 +- .../sdio/sdio_common_tests/pytest_sdio.py | 109 +- .../sigma_delta/pytest_sigma_delta.py | 17 +- .../test_apps/sdmmc/pytest_sdmmc.py | 7 +- .../test_apps/sdspi/pytest_sdspi.py | 9 +- .../test_apps/master/pytest_spi_master.py | 54 +- .../test_apps/param/pytest_spi_param.py | 23 +- .../test_apps/slave/pytest_spi_slave.py | 15 +- .../test_apps/slave_hd/pytest_spi_slave_hd.py | 38 +- .../test_apps/touch_sens/pytest_touch_sens.py | 7 +- .../pytest_temperature_sensor.py | 50 +- .../test_apps/rs485/pytest_rs485.py | 19 +- .../test_apps/uart/pytest_uart.py | 11 +- .../test_apps/uart_vfs/pytest_uart_vfs.py | 30 +- .../usb_serial_jtag/pytest_usb_serial_jtag.py | 29 +- .../pytest_usb_serial_jtag_vfs.py | 13 +- .../esp_eth/test_apps/pytest_esp_eth.py | 187 +- .../pytest_esp_event_linux.py | 5 +- .../esp_event/test_apps/pytest_esp_event.py | 16 +- .../esp_hid/test_apps/pytest_esp_hid.py | 7 +- .../test_apps/pytest_esp_http_client_ut.py | 6 +- .../test_apps/pytest_esp_http_server_ut.py | 6 +- .../test_apps/dma/pytest_dma.py | 18 +- .../test_apps/dma2d/pytest_dma2d.py | 6 +- .../pytest_esp_hw_support.py | 15 +- .../pytest_esp_hw_support_linux.py | 5 +- .../test_apps/mspi/pytest_flash_psram.py | 26 +- .../pytest_psram_with_dfs.py | 22 +- .../test_apps/rtc_8md256/pytest_rtc_8md256.py | 23 +- .../test_apps/rtc_clk/pytest_rtc_clk.py | 11 +- .../sleep_retention/pytest_retention.py | 26 +- .../test_apps/vad_wakeup/pytest_wakeup_vad.py | 5 +- .../wakeup_tests/pytest_wakeup_tests.py | 25 +- .../test_apps/i2c_lcd/pytest_i2c_lcd.py | 6 +- .../i2c_lcd_legacy/pytest_i2c_lcd_legacy.py | 6 +- .../test_apps/i80_lcd/pytest_i80_lcd.py | 8 +- .../mipi_dsi_lcd/pytest_mipi_dsi_lcd.py | 5 +- .../test_apps/parlio_lcd/pytest_parlio_lcd.py | 7 +- .../test_apps/rgb_lcd/pytest_rgb_lcd.py | 7 +- .../test_apps/spi_lcd/pytest_spi_lcd.py | 5 +- components/esp_mm/test_apps/mm/pytest_mmap.py | 41 +- .../test_apps/mmap_hw/pytest_mmap_hw.py | 6 +- .../test_app_esp_netif/pytest_esp_netif.py | 20 +- .../pytest_esp_vfs_l2tap.py | 27 +- .../pytest_esp_partition_linux.py | 5 +- .../esp_pm/test_apps/esp_pm/pytest_esp_pm.py | 42 +- .../esp_psram/test_apps/psram/pytest_psram.py | 24 +- .../test_apps/pytest_esp_ringbuf.py | 49 +- .../linux_rom_apis/pytest_esp_rom_linux.py | 5 +- .../pytest_esp_rom_impl_components.py | 5 +- .../test_apps/rom_tests/pytest_esp_rom.py | 18 +- .../crypto_drivers/pytest_crypto_drivers.py | 13 +- .../cache_panic/pytest_cache_panic_test.py | 5 +- .../pytest_esp_system_console_tests.py | 43 +- .../pytest_esp_system_unity_tests.py | 38 +- .../linux_apis/pytest_esp_system_linux.py | 5 +- .../test_apps/tee_cli_app/pytest_tee_cli.py | 20 +- .../tee_test_fw/pytest_esp_tee_ut.py | 121 +- .../test_apps/pytest_esp_timer_ut.py | 34 +- .../usb_cdc_vfs/pytest_usb_cdc_vfs.py | 6 +- .../wifi_connect/pytest_wifi_connect.py | 15 +- .../wifi_function/pytest_wifi_function.py | 19 +- .../espcoredump/test_apps/pytest_coredump.py | 8 +- .../fatfs/host_test/pytest_fatfs_linux.py | 5 +- .../flash_ro/pytest_fatfs_flash_ro.py | 6 +- .../flash_wl/pytest_fatfs_flash_wl.py | 12 +- .../test_apps/sdcard/pytest_fatfs_sdcard.py | 21 +- .../test_apps/freertos/pytest_freertos.py | 61 +- .../hal/test_apps/crypto/pytest_crypto.py | 22 +- .../test_apps/hal_utils/pytest_hal_utils.py | 5 +- .../heap/test_apps/heap_tests/pytest_heap.py | 73 +- .../host_test_linux/pytest_heap_linux.py | 5 +- .../test_apps/linux_test/pytest_linux_test.py | 5 +- .../host_test/log_test/pytest_log_linux.py | 37 +- components/log/test_apps/pytest_esp_log.py | 6 +- components/lwip/test_apps/pytest_lwip.py | 5 +- .../mbedtls/test_apps/pytest_mbedtls_ut.py | 38 +- .../test_apps/test_mqtt/pytest_mqtt_ut.py | 5 +- .../test_apps/test_mqtt5/pytest_mqtt5_ut.py | 5 +- .../newlib/test_apps/newlib/pytest_newlib.py | 23 +- .../nvs_host_test/pytest_nvs_host_linux.py | 5 +- .../nvs_page_test/pytest_nvs_page_linux.py | 5 +- .../nvs_flash/test_apps/pytest_nvs_flash.py | 20 +- .../pytest_nvs_bootloader_support.py | 11 +- .../perfmon/test_apps/pytest_perfmon_ut.py | 8 +- .../test_apps/pytest_protocomm_ut.py | 6 +- .../pytest_pthread_psram_tests.py | 5 +- .../pytest_pthread_unity_tests.py | 29 +- .../posix_rt_test/pytest_rt_mqueue_tests.py | 8 +- .../test_apps/esp_flash/pytest_esp_flash.py | 21 +- .../pytest_esp_flash_stress.py | 11 +- .../pytest_flash_encrypted.py | 12 +- .../test_apps/flash_mmap/pytest_flash_mmap.py | 15 +- .../pytest_flash_auto_suspend.py | 5 +- .../test_apps/mspi_test/pytest_mspi_test.py | 12 +- .../spiffs/host_test/pytest_spiffs_linux.py | 5 +- components/spiffs/test_apps/pytest_spiffs.py | 30 +- .../test_apps/pytest_tcp_transport_ut.py | 9 +- .../test_apps/pytest_touch_element.py | 11 +- .../pytest_lp_core_basic.py | 37 +- .../lp_core_hp_uart/pytest_lp_core_hp_uart.py | 17 +- .../test_apps/ulp_fsm/pytest_ulp_fsm_app.py | 8 +- .../test_apps/ulp_riscv/pytest_ulp_riscv.py | 15 +- components/usb/test_apps/enum/pytest_enum.py | 3 +- .../usb/test_apps/hcd/pytest_usb_hcd.py | 7 +- .../usb/test_apps/phy/pytest_usb_phy.py | 5 +- .../usb/test_apps/usb_host/pytest_usb_host.py | 7 +- components/vfs/test_apps/pytest_vfs.py | 43 +- .../host_test/pytest_wear_levelling_linux.py | 5 +- .../test_apps/pytest_wear_levelling.py | 22 +- .../test_apps/pytest_wpa_supplicant_ut.py | 29 +- .../pytest_ble_throughput_test.py | 113 +- .../bluedroid/ble/pytest_ble_test.py | 243 +-- .../bluedroid/ble_50/pytest_ble50_test.py | 141 +- .../pytest_classic_bt_discovery_test.py | 5 +- .../classic_bt/pytest_classic_bt_test.py | 87 +- .../bluetooth/nimble/pytest_nimble_test.py | 40 +- .../cmake/import_lib/pytest_import_lib.py | 9 +- .../cmake/plugins/pytest_plugins.py | 7 +- .../pytest_bootloader_extra_dir.py | 5 +- .../pytest_custom_bootloader_hooks.py | 6 +- .../pytest_custom_bootloader_multiboot.py | 6 +- .../pytest_custom_bootloader_override.py | 6 +- .../pytest_examples_cxx_exceptions.py | 5 +- .../pthread/pytest_examples_cxx_pthread.py | 5 +- examples/cxx/rtti/pytest_examples_cxx_rtti.py | 5 +- examples/ethernet/basic/pytest_eth_basic.py | 23 +- examples/ethernet/iperf/pytest_eth_iperf.py | 149 +- examples/get-started/blink/pytest_blink.py | 5 +- .../hello_world/pytest_hello_world.py | 21 +- .../ieee802154_cli/pytest_test_ieee802154.py | 171 +- .../network/bridge/pytest_example_bridge.py | 108 +- .../simple_sniffer/pytest_simple_sniffer.py | 24 +- .../network/vlan_support/pytest_vlan_napt.py | 158 +- examples/openthread/pytest_otbr.py | 126 +- .../continuous_read/pytest_adc_continuous.py | 13 +- .../adc/oneshot_read/pytest_adc_oneshot.py | 15 +- .../pytest_ana_cmpr_example.py | 12 +- .../pytest_bitscrambler_loopback_example.py | 4 +- .../camera/dvp_isp_dsi/pytest_dvp_isp_dsi.py | 5 +- .../mipi_isp_dsi/pytest_mipi_isp_dsi.py | 5 +- .../dac_audio/pytest_dac_audio.py | 7 +- .../signal_generator/pytest_dac_continuous.py | 7 +- .../dac_cosine_wave/pytest_dac_cosine_wave.py | 8 +- .../dac/dac_oneshot/pytest_dac_oneshot.py | 7 +- .../pytest_generic_gpio_example.py | 10 +- .../i2c_tools/pytest_examples_i2c_tools.py | 5 +- .../i2s/i2s_advance/i2s_usb/pytest_i2s_usb.py | 5 +- .../i2s/i2s_basic/i2s_pdm/pytest_i2s_pdm.py | 49 +- .../i2s/i2s_basic/i2s_std/pytest_i2s_std.py | 49 +- .../i2s/i2s_basic/i2s_tdm/pytest_i2s_tdm.py | 45 +- .../i2s_es7210_tdm/pytest_i2s_es7210_tdm.py | 9 +- .../i2s_codec/i2s_es8311/pytest_i2s_es8311.py | 19 +- .../i2s/i2s_recorder/pytest_i2s_record.py | 7 +- .../mipi_dsi/pytest_mipi_dsi_panel_lvgl.py | 5 +- .../lcd/rgb_panel/pytest_rgb_panel_lvgl.py | 7 +- .../pytest_bdc_speed_control.py | 6 +- .../pytest_bldc_hall_control.py | 6 +- .../mcpwm_capture_hc_sr04/pytest_hc_sr04.py | 10 +- .../pytest_foc_open_loop.py | 6 +- .../pytest_servo_mg996r.py | 10 +- .../mcpwm/mcpwm_sync/pytest_mcpwm_sync.py | 19 +- .../logic_analyzer/pytest_logic_analyzer.py | 8 +- .../pytest_simple_rgb_led_matrix.py | 5 +- .../rotary_encoder/pytest_rotary_encoder.py | 13 +- .../peripherals/ppa/ppa_dsi/pytest_ppa_dsi.py | 5 +- .../rmt/dshot_esc/pytest_dshot_esc.py | 16 +- .../rmt/ir_nec_transceiver/pytest_ir_nec.py | 6 +- .../rmt/led_strip/pytest_led_strip.py | 16 +- .../musical_buzzer/pytest_musical_buzzer.py | 13 +- .../peripherals/rmt/onewire/pytest_onewire.py | 16 +- .../rmt/stepper_motor/pytest_stepper_motor.py | 9 +- examples/peripherals/sdio/pytest_sdio_test.py | 5 +- .../sdm_dac/pytest_sdm_dac_example.py | 16 +- .../sdm_led/pytest_sdm_led_example.py | 16 +- .../temp_sensor/pytest_temp_sensor_example.py | 17 +- .../pytest_temp_sensor_monitor_example.py | 9 +- .../gptimer/pytest_gptimer_example.py | 8 +- .../pytest_gptimer_capture_example.py | 9 +- .../wiegand_interface/pytest_wiegand.py | 17 +- .../touch_button/pytest_touch_button.py | 6 +- .../pytest_touch_element_waterproof.py | 6 +- .../pytest_touch_elements_combination.py | 6 +- .../touch_matrix/pytest_touch_matrix.py | 6 +- .../touch_slider/pytest_touch_slider.py | 6 +- .../pytest_touch_sens_basic.py | 6 +- .../pytest_twai_alert_recovery_example.py | 6 +- .../pytest_twai_self_test_example.py | 6 +- .../pytest_async_rxtxtasks.py | 3 +- .../uart/uart_events/pytest_events.py | 3 +- .../uart/uart_select/pytest_uart_select.py | 3 +- .../pytest_usb_device_composite.py | 7 +- .../tusb_console/pytest_usb_device_console.py | 7 +- .../device/tusb_hid/pytest_usb_device_hid.py | 7 +- .../tusb_midi/pytest_usb_device_midi.py | 7 +- .../device/tusb_msc/pytest_usb_device_msc.py | 7 +- .../device/tusb_ncm/pytest_usb_device_ncm.py | 12 +- .../pytest_usb_device_serial.py | 7 +- .../usb/host/msc/pytest_usb_host_msc.py | 11 +- .../host/usb_host_lib/pytest_usb_host_lib.py | 7 +- .../pytest_usj_echo_example.py | 7 +- .../esp_http_client/pytest_esp_http_client.py | 30 +- .../esp_local_ctrl/pytest_esp_local_ctrl.py | 50 +- .../http_request/pytest_http_request.py | 8 +- .../pytest_http_server_advanced.py | 20 +- .../pytest_http_server_async.py | 3 +- .../captive_portal/pytest_captive_portal.py | 13 +- .../pytest_http_server_file_serving.py | 26 +- .../pytest_http_server_persistence.py | 18 +- .../simple/pytest_http_server_simple.py | 29 +- .../pytest_ws_server_example.py | 18 +- .../https_mbedtls/pytest_https_mbedtls.py | 6 +- .../https_request/pytest_https_request.py | 216 +-- .../simple/pytest_https_server_simple.py | 179 +- .../wss_server/pytest_https_wss_server.py | 24 +- .../pytest_https_x509_bundle.py | 25 +- .../protocols/icmp_echo/pytest_icmp_echo.py | 38 +- .../l2tap/pytest_example_l2tap_echo.py | 17 +- .../protocols/mqtt/ssl/pytest_mqtt_ssl.py | 19 +- .../protocols/mqtt/tcp/pytest_mqtt_tcp.py | 23 +- .../mqtt/ws/pytest_mqtt_ws_example.py | 14 +- .../mqtt/wss/pytest_mqtt_wss_example.py | 18 +- examples/protocols/mqtt5/pytest_mqtt5.py | 8 +- examples/protocols/sntp/pytest_sntp.py | 9 +- .../sockets/tcp_client/pytest_tcp_client.py | 27 +- .../sockets/tcp_server/pytest_tcp_server.py | 45 +- .../sockets/udp_client/pytest_udp_client.py | 27 +- .../sockets/udp_server/pytest_udp_server.py | 27 +- .../protocols/static_ip/pytest_static_ip.py | 19 +- .../wifi_prov_mgr/pytest_wifi_prov_mgr.py | 27 +- .../pytest_flash_encryption.py | 25 +- .../hmac_soft_jtag/pytest_jtag_example.py | 15 +- .../pytest_nvs_encr_hmac.py | 25 +- .../tee_attestation/pytest_tee_attestation.py | 5 +- .../tee/tee_basic/pytest_tee_basic.py | 5 +- .../tee_secure_ota/pytest_tee_secure_ota.py | 12 +- .../pytest_tee_secure_storage.py | 5 +- .../pytest_custom_flash_example.py | 5 +- examples/storage/emmc/pytest_emmc_example.py | 21 +- .../fatfs/ext_flash/pytest_fatfs_ext_flash.py | 17 +- .../fatfsgen/pytest_fatfs_fatfsgen_example.py | 61 +- .../pytest_fatfs_fs_operations_example.py | 11 +- .../pytest_fatfs_getting_started_example.py | 7 +- .../nvs_bootloader/pytest_nvs_bootloader.py | 8 +- .../storage/nvs_rw_blob/pytest_nvs_rw_blob.py | 6 +- .../nvs_rw_value/pytest_nvs_rw_value.py | 6 +- .../pytest_nvs_rw_value_cxx.py | 6 +- .../storage/nvsgen/pytest_nvsgen_example.py | 5 +- .../pytest_partition_find_example.py | 43 +- .../pytest_partition_mmap_example.py | 20 +- .../pytest_partition_ops_example.py | 16 +- .../parttool/pytest_parttool_example.py | 15 +- .../pytest_perf_benchmark_example.py | 20 +- .../sdmmc/pytest_sdmmc_card_example.py | 31 +- .../sdspi/pytest_sdspi_card_example.py | 35 +- .../semihost_vfs/pytest_semihost_vfs.py | 8 +- .../storage/spiffs/pytest_spiffs_example.py | 24 +- .../spiffsgen/pytest_spiffsgen_example.py | 5 +- .../pytest_wear_levelling_example.py | 35 +- .../app_trace_basic/pytest_app_trace_basic.py | 31 +- .../pytest_base_mac_address.py | 16 +- .../advanced/pytest_console_advanced.py | 6 +- .../console/basic/pytest_console_basic.py | 19 +- .../system/deep_sleep/pytest_deep_sleep.py | 5 +- .../pytest_deep_sleep_wake_stub.py | 21 +- .../efuse/pytest_system_efuse_example.py | 248 +-- .../pytest_esp_event_default.py | 26 +- .../user_event_loops/pytest_esp_event_user.py | 13 +- examples/system/esp_timer/pytest_esp_timer.py | 11 +- examples/system/eventfd/pytest_eventfd.py | 6 +- .../flash_suspend/pytest_flash_suspend.py | 16 +- .../pytest_smp_examples.py | 38 +- .../pytest_freertos_real_time_stats.py | 7 +- examples/system/gcov/pytest_gcov.py | 5 +- examples/system/himem/pytest_himem.py | 17 +- .../ipc/ipc_isr/riscv/pytest_ipc_isr_riscv.py | 5 +- .../ipc_isr/xtensa/pytest_ipc_isr_xtensa.py | 7 +- .../system/light_sleep/pytest_light_sleep.py | 18 +- examples/system/nmi_isr/pytest_nmi_isr.py | 7 +- .../advanced_https_ota/pytest_advanced_ota.py | 118 +- .../native_ota_example/pytest_native_ota.py | 130 +- examples/system/ota/otatool/pytest_otatool.py | 19 +- .../partitions_ota/pytest_partitions_ota.py | 136 +- .../simple_ota_example/pytest_simple_ota.py | 201 ++- examples/system/perfmon/pytest_perfmon.py | 9 +- examples/system/pthread/pytest_pthread.py | 7 +- examples/system/rt_mqueue/pytest_rt_mqueue.py | 5 +- examples/system/select/pytest_select.py | 18 +- .../startup_time/pytest_startup_time.py | 18 +- .../sysview_tracing/pytest_sysview_tracing.py | 5 +- .../pytest_sysview_tracing_heap_log.py | 8 +- .../task_watchdog/pytest_task_watchdog.py | 7 +- .../build_system/pytest_lp_core_build_sys.py | 7 +- .../pytest_lp_core_pcnt.py | 11 +- .../pytest_lp_core_critical_section.py | 8 +- .../lp_core/interrupt/pytest_lp_core_intr.py | 7 +- .../system/ulp/ulp_fsm/ulp/pytest_ulp_fsm.py | 13 +- .../ulp/ulp_fsm/ulp_adc/pytest_ulp_fsm_adc.py | 8 +- .../ulp_riscv/gpio/pytest_ulp_riscv_gpio.py | 8 +- .../interrupts/pytest_ulp_riscv_interrupts.py | 8 +- examples/system/unit_test/pytest_unittest.py | 7 +- .../xip_from_psram/pytest_xip_from_psram.py | 13 +- .../pytest_wifi_getting_started.py | 42 +- .../station/pytest_wifi_station.py | 20 +- examples/wifi/iperf/pytest_iperf.py | 28 +- .../wifi/power_save/pytest_wifi_power_save.py | 26 +- .../zigbee/light_sample/pytest_esp_zigbee.py | 31 +- .../pytest_ld_non_contiguous_memory.py | 8 +- .../linux_freertos/pytest_linux_freertos.py | 6 +- .../peripherals/i2c_wifi/pytest_i2c_wifi.py | 13 +- .../pytest_phy_multi_init_data.py | 22 +- .../phy/phy_tsens/pytest_phy_tsens.py | 12 +- .../publish_connect_test/pytest_mqtt_app.py | 101 +- .../pytest_mqtt_publish_app.py | 93 +- .../secure_boot/pytest_secure_boot.py | 53 +- .../pytest_signed_app_no_secure_boot.py | 12 +- .../fatfsgen/pytest_fatfsgen_example.py | 120 +- .../pytest_partition_table_readonly.py | 16 +- .../std_filesystem/pytest_std_filesystem.py | 6 +- .../system/eh_frame/pytest_eh_frame.py | 23 +- .../esp_intr_dump/pytest_esp_intr_dump.py | 9 +- tools/test_apps/system/gdb/pytest_gdb.py | 28 +- .../pytest_gdb_loadable_elf.py | 17 +- .../gdbstub_runtime/pytest_gdbstub_runtime.py | 15 +- .../system/longjmp_test/pytest_longjmp.py | 7 +- .../system/memprot/pytest_memprot.py | 24 +- .../mmu_page_size/pytest_mmu_page_size.py | 9 +- tools/test_apps/system/panic/pytest_panic.py | 1504 +++++++++++++++-- .../pytest_ram_loadable_app.py | 67 +- .../rtc_mem_reserve/pytest_rtc_mem_reserve.py | 5 +- .../system/startup/pytest_startup.py | 42 +- .../test_watchpoint/pytest_watchpoint.py | 7 +- .../pytest_unicore_bootloader.py | 11 +- 381 files changed, 6180 insertions(+), 4289 deletions(-) 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 087216c2ad..a8fe757fe1 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-2025 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,14 +52,11 @@ 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) -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -64,5 +65,6 @@ def test_app_update_xip_psram_rom_impl(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3', 'esp32p4'], indirect=['target']) def test_app_update_with_rollback(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..59e3d4cf6a 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-2025 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..1ccf193dfb 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-2025 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..98e7cd8a6e 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-2025 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..d5d70fcd2b 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-2025 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..cac89e155d 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-2025 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..e89f3c561a 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-2025 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..ba8849827b 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-2025 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..f480ed673c 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-2025 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..40ec38cbd0 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-2025 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..5e4f4baf3c 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-2025 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..a7332243db 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-2025 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..76d2a0d1ad 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-2025 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..a7acc58b25 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-2025 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_mcpwm_driver/pytest_legacy_mcpwm.py b/components/driver/test_apps/legacy_mcpwm_driver/pytest_legacy_mcpwm.py index a8a9e25bd1..b415ffed0a 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-2025 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..8d2045f4eb 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-2025 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..6512651cfa 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-2025 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 85359b8ca7..47646ffe48 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,21 +1,22 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 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.esp32c61 @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', 'esp32c61'], + 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..9a6b264285 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-2025 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..503d591c83 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-2025 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..edb264bb7d 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-2025 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..1c0ff4364d 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-2025 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 9113bb1a6e..8e73a13167 100644 --- a/components/driver/test_apps/twai/pytest_twai.py +++ b/components/driver/test_apps/twai/pytest_twai.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging import subprocess @@ -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.serial.hard_reset() dut.expect_exact('Press ENTER to see the list of tests') @@ -75,13 +68,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', @@ -90,6 +76,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.serial.hard_reset() 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..6d823e62cb 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-2025 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..553912ef8b 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-2025 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 94133182ae..365b9ad1c5 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-2025 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,19 +27,19 @@ 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) -@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', [ - 'gdma_iram_safe', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'gdma_iram_safe', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32c5', 'esp32p4'], indirect=['target']) def test_adc_gdma_iram(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..843ceb825a 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-2025 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..43891cea30 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-2025 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..726657be42 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-2025 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 d9eeb38699..3efcc580a0 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,13 +1,10 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 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.esp32c5 -@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -17,5 +14,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'], indirect=['target']) def test_ana_cmpr(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py b/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py index d73d1fed4b..ba6490743f 100644 --- a/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py +++ b/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py @@ -2,10 +2,10 @@ # 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.esp32c5 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4', 'esp32c5'], indirect=['target']) def test_bitscrambler(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..3be2c9557f 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-2025 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/dvp/pytest_dvp.py b/components/esp_driver_cam/test_apps/dvp/pytest_dvp.py index 139f1c0694..2c6f832922 100644 --- a/components/esp_driver_cam/test_apps/dvp/pytest_dvp.py +++ b/components/esp_driver_cam/test_apps/dvp/pytest_dvp.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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(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..211e25d4de 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-2025 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..5a282e1cd8 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-2025 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..008e15003d 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-2025 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 a92700388d..a6cb431bf5 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-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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,31 +10,23 @@ 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') 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..f87e448e5e 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-2025 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 fbcfd363e9..de7106b1fe 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 @@ -2,9 +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.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..2f7ac561f3 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-2025 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..06ba3a2bfe 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-2025 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 2c7e4ffa8a..db2527a9ec 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,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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 +@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..2ee2e26ae3 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-2025 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..b3e6f5052e 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-2025 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..e200d22e5c 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-2025 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..9150b19700 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-2025 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..54290a9201 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-2025 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..5622c6be44 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-2025 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 15f27cf1ac..4a9612aa79 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-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 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..5def5f9c29 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-2025 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..7f614064ab 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-2025 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..dfc410e7b2 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-2025 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..4c187b2d12 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-2025 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 8cfd75be17..80d958b3c3 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,22 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 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', ['release', 'freertos_compliance', 'freertos_flash',], indirect=True) -def test_master_single_dev(case_tester) -> None: # type: ignore +@pytest.mark.parametrize( + 'config', + [ + '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 +24,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', ['release',], indirect=True) -def test_master_esp_flash(case_tester) -> None: # type: ignore +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + 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,19 +43,28 @@ 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, 'release',), - (2, 'freertos_compliance',), - (2, 'freertos_flash',), + ( + 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..049c6ec316 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-2025 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 d1ace584c8..b037f7499e 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,14 @@ -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 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', ['release', 'iram_safe'], indirect=True) -def test_slave_single_dev(case_tester) -> None: # type: ignore +@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 +18,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, 'release'), (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 20a055f566..22c5163812 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,21 +1,18 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 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 @pytest.mark.parametrize('config', ['release'], indirect=True) -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 @@ -23,17 +20,14 @@ 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, config', [(2, 'release')], indirect=True) -def test_slave_hd_multi_dev(case_tester) -> None: # type: ignore +@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 c1205a9117..f2cb32df50 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,12 +1,10 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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 @pytest.mark.parametrize( 'config', @@ -16,5 +14,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32s2', 'esp32s3', '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 bb4111bfca..c5880f8058 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,48 +1,44 @@ -# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 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.esp32c61 @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', 'esp32c61'], + 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.esp32c61 @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', 'esp32c61'], 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.esp32c61 @pytest.mark.wifi_two_dut @pytest.mark.parametrize('count', [2], indirect=True) +@idf_parametrize('target', ['esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32c61'], 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', 'wifi_two_dut') == 'wifi_two_dut': 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..72dcff04e2 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-2025 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..da106d3d95 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-2025 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..4852f3ea6d 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-2025 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..d96301173f 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-2025 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 897f3179ee..165a54fb97 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,24 +1,23 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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_release(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 07b45872ef..2f61a900da 100644 --- a/components/esp_eth/test_apps/pytest_esp_eth.py +++ b/components/esp_eth/test_apps/pytest_esp_eth.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import contextlib import logging @@ -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 @@ -45,7 +46,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)) @@ -60,14 +61,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) @@ -76,13 +77,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: @@ -92,9 +93,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: @@ -103,7 +104,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: @@ -158,7 +159,7 @@ def ethernet_l2_test(dut: IdfDut) -> 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() @@ -172,7 +173,9 @@ def ethernet_l2_test(dut: IdfDut) -> 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)) @@ -191,7 +194,13 @@ def ethernet_l2_test(dut: IdfDut) -> 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() dut.expect_exact('Ethernet Stopped') pipe_send.send(0) # just send some dummy data @@ -219,7 +228,13 @@ def ethernet_heap_alloc_test(dut: IdfDut) -> 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) @@ -233,55 +248,67 @@ def ethernet_heap_alloc_test(dut: IdfDut) -> 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() @@ -289,11 +316,15 @@ def test_esp32p4_emac(dut: IdfDut) -> None: # ----------- 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() @@ -301,11 +332,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() @@ -313,11 +348,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() @@ -325,11 +364,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() @@ -337,12 +380,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() @@ -352,12 +399,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() @@ -367,12 +418,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..79b2c2ebbb 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-2025 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_event/test_apps/pytest_esp_event.py b/components/esp_event/test_apps/pytest_esp_event.py index ff04ca3a55..a8b47ca347 100644 --- a/components/esp_event/test_apps/pytest_esp_event.py +++ b/components/esp_event/test_apps/pytest_esp_event.py @@ -2,37 +2,35 @@ # 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_event(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.host_test @pytest.mark.qemu @pytest.mark.xfail('config.getvalue("target") == "esp32c3"', reason='Unstable on QEMU, needs investigation') +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_esp_event_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_event_posix_simulator(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests.') dut.write('*') dut.expect(r'\d{2} Tests 0 Failures 0 Ignored', timeout=120) -@pytest.mark.esp32 @pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_event_profiling(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests.') dut.write('"profiling reports valid values"') @@ -40,7 +38,7 @@ def test_esp_event_profiling(dut: Dut) -> None: # with an execution time superior to 0 us matches = dut.expect(r'HANDLER .+ inv:[1-9][0-9]{0,} time:[1-9][0-9]{0,} us', timeout=2) matches_arr = matches.group().split(b'\r\n') - assert (len(matches_arr) == 3) + assert len(matches_arr) == 3 dut.expect('1 Tests 0 Failures 0 Ignored', timeout=120) dut.expect_exact("Enter next test, or 'enter' to see menu") @@ -48,7 +46,7 @@ def test_esp_event_profiling(dut: Dut) -> None: # look for 1 handlers never invoked matches = dut.expect(r'HANDLER .+ inv:0 time:0 us', timeout=2) matches_arr = matches.group().split(b'\r\n') - assert (len(matches_arr) == 1) + assert len(matches_arr) == 1 dut.expect('1 Tests 0 Failures 0 Ignored', timeout=120) dut.expect_exact("Enter next test, or 'enter' to see menu") diff --git a/components/esp_hid/test_apps/pytest_esp_hid.py b/components/esp_hid/test_apps/pytest_esp_hid.py index 664e29bf6f..c59350344e 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-2025 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..ec91799b88 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-2025 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..073c7eafae 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-2025 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 1d741f14fb..e70adf3476 100644 --- a/components/esp_hw_support/test_apps/dma/pytest_dma.py +++ b/components/esp_hw_support/test_apps/dma/pytest_dma.py @@ -1,17 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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.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,5 +30,6 @@ 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) 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..314949f222 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-2025 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..c874e8f204 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-2025 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..9c3bd55273 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-2025 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 6704041ebb..41be9d93c5 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,44 +1,53 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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.esp32s3_f8r8*')] +MSPI_F8R8_configs = [ + p.name.replace('sdkconfig.ci.', '') + for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.esp32s3_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.esp32s3_f4r8*')] +MSPI_F4R8_configs = [ + p.name.replace('sdkconfig.ci.', '') + for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.esp32s3_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.esp32s3_f4r4*')] +MSPI_F4R4_configs = [ + p.name.replace('sdkconfig.ci.', '') + for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.esp32s3_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() -@pytest.mark.esp32p4 @pytest.mark.flash_120m @pytest.mark.parametrize( 'config', @@ -47,5 +56,6 @@ def test_flash4_psram4(dut: IdfDut) -> None: ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_flash_psram_esp32p4(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..985699e131 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-2025 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..1942b0623d 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-2025 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..baae55ba3d 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-2025 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..b515a68d39 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,35 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 -import functools -from typing import Callable -from typing import Dict -from typing import List - import pytest from pytest_embedded import Dut - - -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 - - for target in targets: - wrapper = pytest.mark.__getattr__(target)(wrapper) - - return wrapper - - return decorator +from pytest_embedded_idf.utils import idf_parametrize # SOC_PAU_SUPPORTED == 1 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 2fe20c476a..3413396876 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-2025 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 +@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 b99d1345a4..f621c295e0 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,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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'), @@ -36,14 +36,10 @@ available_rtcio_nums = { } -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @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'], indirect=['target']) def test_ext1_deepsleep(dut: Tuple[IdfDut, IdfDut]) -> None: wakee = dut[0] waker = dut[1] @@ -86,12 +82,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.generic_multi_device @pytest.mark.parametrize('count', [2], indirect=True) @pytest.mark.parametrize('config', TEST_CONFIGS, indirect=True) +@idf_parametrize('target', ['esp32c2', 'esp32c3', 'esp32c6'], indirect=['target']) def test_rtcio_deepsleep(dut: Tuple[IdfDut, IdfDut]) -> None: wakee = dut[0] waker = dut[1] @@ -134,16 +128,12 @@ 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.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'], indirect=['target'] +) def test_gpio_wakeup_enable_lightsleep(dut: Tuple[IdfDut, IdfDut]) -> None: wakee = dut[0] waker = dut[1] @@ -153,7 +143,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..1848e7344e 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-2025 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..d0aa353142 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-2025 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..f8bf0548d2 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-2025 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 7e4dc07e7d..04f1620759 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-2025 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 +14,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_dsi_lcd(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_lcd/test_apps/parlio_lcd/pytest_parlio_lcd.py b/components/esp_lcd/test_apps/parlio_lcd/pytest_parlio_lcd.py index f3fb114c9f..56097d32b1 100644 --- a/components/esp_lcd/test_apps/parlio_lcd/pytest_parlio_lcd.py +++ b/components/esp_lcd/test_apps/parlio_lcd/pytest_parlio_lcd.py @@ -1,12 +1,10 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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.esp32h2 -@pytest.mark.esp32c5 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -15,5 +13,6 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32p4', 'esp32h2', 'esp32c5'], indirect=['target']) def test_parlio_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..fb1b6e1fc8 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-2025 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..26ad646b73 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-2025 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..d696bee32d 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-2025 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..bddb0d4f39 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-2025 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..64d3b025d9 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-2025 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 a93a9a9e34..1a9f547da8 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,22 +1,31 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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 -@pytest.mark.parametrize('config', [ - 'defaults', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'defaults', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_esp_netif_vfs_l2tp(dut: Dut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32p4 @pytest.mark.eth_ip101 -@pytest.mark.parametrize('config', [ - 'defaults', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'defaults', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_esp_netif_vfs_l2tp_p4(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..7f2b68dc35 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-2025 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..2cd49b5884 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-2025 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..cf5d41b7d4 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-2025 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..ca44dcfa16 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-2025 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..0d2a4b48fd 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-2025 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..4efbe677c0 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-2025 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..0bc7bfef1a 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-2025 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..8e697da9af 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-2025 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..4c169b54e9 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-2025 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 2625d583ac..e7506c0da8 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 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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,26 +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), - ], - indirect=True, -) +@idf_parametrize('config', ['serial_jtag_only'], 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') @@ -54,26 +47,18 @@ def test_esp_system_console_only_serial_jtag(dut: Dut) -> 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_no_vfs', marks=JTAG_SERIAL_MARKS), - ], - indirect=True, -) +@idf_parametrize('config', ['serial_jtag_only_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_no_vfs(dut: Dut) -> None: dut.expect('2nd stage bootloader') dut.expect('Hello World') @pytest.mark.generic -@pytest.mark.parametrize( - 'config', - [ - pytest.param('simple', marks=pytest.mark.supported_targets), - ], - indirect=True -) +@idf_parametrize('config', ['simple'], indirect=['config']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_esp_system_console_correct_open_and_close(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 f0fc1bb0a4..3d0d92f227 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 @@ -2,18 +2,23 @@ # 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"') @@ -35,13 +36,8 @@ def test_stack_smash_protection(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.parametrize( - 'config', - [ - # Testing this feature on a single RISC-V target is enough - pytest.param('framepointer', marks=[pytest.mark.esp32c3]), - ] -) +@idf_parametrize('config', ['framepointer'], indirect=['config']) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_frame_pointer_backtracing(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('"Backtrace detects corrupted frames"') 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..279dc5b237 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-2025 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_tee/test_apps/tee_cli_app/pytest_tee_cli.py b/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py index ef948dbc7b..35ebd12a42 100644 --- a/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py +++ b/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import hashlib import http.server @@ -21,6 +21,7 @@ from ecdsa.curves import NIST256p from ecdsa.keys import VerifyingKey from ecdsa.util import sigdecode_der from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize from RangeHTTPServer import RangeRequestHandler TEST_MSG = 'hello world' @@ -34,8 +35,8 @@ key_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_certs/ ########################### -@pytest.mark.esp32c6 @pytest.mark.generic +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_tee_cli_secure_storage(dut: Dut) -> None: # Dumping the REE binary size binary_file = os.path.join(dut.app.binary_path, 'tee_cli.bin') @@ -80,9 +81,10 @@ def test_tee_cli_secure_storage(dut: Dut) -> None: dut.write(f'tee_sec_stg_decrypt {sec_stg_slots.get(i)} {test_msg_cipher} {test_msg_tag}') test_msg_decipher = dut.expect(r'Decrypted plaintext -\s*([0-9a-fA-F]{64})', timeout=30)[1].decode() - assert (test_msg_decipher == test_msg_hash) + assert test_msg_decipher == test_msg_hash time.sleep(1) + ######################## # ESP-TEE: Attestation # ######################## @@ -119,8 +121,8 @@ def verify_att_token_signature(att_tk: str) -> Any: return vk.verify_digest(signature, digest, sigdecode=sigdecode_der) -@pytest.mark.esp32c6 @pytest.mark.generic +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_tee_cli_attestation(dut: Dut) -> None: # Dumping the REE binary size binary_file = os.path.join(dut.app.binary_path, 'tee_cli.bin') @@ -141,15 +143,17 @@ def test_tee_cli_attestation(dut: Dut) -> None: att_tk = dut.expect(r"'(.*?)'", timeout=30)[1].decode() assert verify_att_token_signature(att_tk) + ####################################### # ESP-TEE: Over-the-Air (OTA) updates # ####################################### -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: @@ -174,14 +178,12 @@ def start_https_server(ota_image_dir: str, server_ip: str, server_port: int) -> requestHandler = https_request_handler() httpd = http.server.HTTPServer((server_ip, server_port), requestHandler) - httpd.socket = ssl.wrap_socket(httpd.socket, - keyfile=key_file, - certfile=server_file, server_side=True) + httpd.socket = ssl.wrap_socket(httpd.socket, keyfile=key_file, certfile=server_file, server_side=True) httpd.serve_forever() -@pytest.mark.esp32c6 @pytest.mark.wifi_high_traffic +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_tee_cli_secure_ota_wifi(dut: Dut) -> None: """ This is a positive test case, which downloads complete binary file multiple number of times. diff --git a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py index 6bbed77791..ec47009f7f 100644 --- a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py +++ b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py @@ -6,19 +6,13 @@ from typing import Dict import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -CONFIGS_DEFAULT = [ - pytest.param('default', marks=[pytest.mark.esp32c6]) -] +CONFIGS_DEFAULT = [pytest.param('default', marks=[pytest.mark.esp32c6])] -CONFIGS_OTA = [ - pytest.param('ota', marks=[pytest.mark.esp32c6]) -] +CONFIGS_OTA = [pytest.param('ota', marks=[pytest.mark.esp32c6])] -CONFIGS_ALL = [ - pytest.param('default', marks=[pytest.mark.esp32c6]), - pytest.param('ota', marks=[pytest.mark.esp32c6]) -] +CONFIGS_ALL = [pytest.param('default', marks=[pytest.mark.esp32c6]), pytest.param('ota', marks=[pytest.mark.esp32c6])] TEE_VIOLATION_TEST_EXC_RSN: Dict[str, Any] = { 'esp32c6': { @@ -27,7 +21,7 @@ TEE_VIOLATION_TEST_EXC_RSN: Dict[str, Any] = { ('IRAM', 'W1'): 'Store access fault', ('IRAM', 'W2'): 'Store access fault', ('DRAM', 'X1'): 'Instruction access fault', - ('DRAM', 'X2'): 'Instruction access fault' + ('DRAM', 'X2'): 'Instruction access fault', } } @@ -53,20 +47,23 @@ TEST_PARTITION_LABEL = 'test' @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_DEFAULT, indirect=True) +@idf_parametrize('config', ['default'], indirect=['config']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='basic') @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_ALL, indirect=True) +@idf_parametrize('config', ['default', 'ota'], indirect=['config']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_crypto_aes(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='aes') dut.run_all_single_board_cases(group='aes-gcm') @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_ALL, indirect=True) +@idf_parametrize('config', ['default', 'ota'], indirect=['config']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_crypto_sha(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='mbedtls') dut.run_all_single_board_cases(group='hw_crypto') @@ -74,7 +71,8 @@ def test_esp_tee_crypto_sha(dut: IdfDut) -> None: # NOTE: Stress testing the AES performance case for interrupt-related edge-cases @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_ALL, indirect=True) +@idf_parametrize('config', ['default', 'ota'], indirect=['config']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_aes_perf(dut: IdfDut) -> None: # start test for i in range(24): @@ -85,32 +83,36 @@ def test_esp_tee_aes_perf(dut: IdfDut) -> None: dut.write('"mbedtls AES performance"') dut.expect_unity_test_output(timeout=60) + # ---------------- TEE Exceptions generation Tests ---------------- @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_DEFAULT, indirect=True) +@idf_parametrize('config', ['default'], indirect=['config']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_apm_violation(dut: IdfDut) -> None: for check in TEE_APM_VIOLATION_EXC_CHK: dut.expect_exact('Press ENTER to see the list of tests') dut.write(f'"Test APM violation interrupt: {check}"') - exc = dut.expect(r"Core ([01]) panic\'ed \(([^)]+)\)", timeout=30).group(2).decode() + exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() if exc != 'Authority exception': raise RuntimeError('Incorrect exception received!') @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_DEFAULT, indirect=True) +@idf_parametrize('config', ['default'], indirect=['config']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_illegal_instruction(dut: IdfDut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write(f'"Test TEE-TEE violation: Illegal Instruction"') - exc = dut.expect(r"Core ([01]) panic\'ed \(([^)]+)\)", timeout=30).group(2).decode() + exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() if exc != 'Illegal instruction': raise RuntimeError('Incorrect exception received!') @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_DEFAULT, indirect=True) +@idf_parametrize('config', ['default'], indirect=['config']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_violation_checks(dut: IdfDut) -> None: checks_list = TEE_VIOLATION_TEST_EXC_RSN[dut.target] for test in checks_list: @@ -120,13 +122,14 @@ def test_esp_tee_violation_checks(dut: IdfDut) -> None: continue dut.expect_exact('Press ENTER to see the list of tests') dut.write(f'"Test TEE-TEE violation: {memory} ({access_type})"') - actual_exc = dut.expect(r"Core ([01]) panic\'ed \(([^)]+)\)", timeout=30).group(2).decode() + actual_exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() if actual_exc != expected_exc: raise RuntimeError('Incorrect exception received!') @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_DEFAULT, indirect=True) +@idf_parametrize('config', ['default'], indirect=['config']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_isolation_checks(dut: IdfDut) -> None: checks_list = REE_ISOLATION_TEST_EXC_RSN[dut.target] for test in checks_list: @@ -136,11 +139,12 @@ def test_esp_tee_isolation_checks(dut: IdfDut) -> None: continue dut.expect_exact('Press ENTER to see the list of tests') dut.write(f'"Test REE-TEE isolation: {memory} ({access_type})"') - actual_exc = dut.expect(r"Core ([01]) panic\'ed \(([^)]+)\)", timeout=30).group(2).decode() + actual_exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() if actual_exc != expected_exc: raise RuntimeError('Incorrect exception received!') dut.expect('Exception origin: U-mode') + # ---------------- TEE Flash Protection Tests ---------------- @@ -154,7 +158,7 @@ class TeeFlashAccessApi(Enum): def check_panic_or_reset(dut: IdfDut) -> None: try: - exc = dut.expect(r"Core ([01]) panic\'ed \(([^)]+)\)", timeout=5).group(2).decode() + exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=5).group(2).decode() if exc not in {'Cache error', 'Authority exception'}: raise RuntimeError('Flash operation incorrect exception') except Exception: @@ -167,7 +171,7 @@ def check_panic_or_reset(dut: IdfDut) -> None: def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFlashAccessApi) -> None: exp_seq = { TeeFlashAccessApi.ESP_PARTITION: ['read', 'program_page', 'program_page', 'erase_sector'], - TeeFlashAccessApi.ESP_FLASH: ['program_page', 'read', 'erase_sector', 'program_page'] + TeeFlashAccessApi.ESP_FLASH: ['program_page', 'read', 'erase_sector', 'program_page'], } for stage in range(1, stages + 1): @@ -178,7 +182,9 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl if 1 < stage <= stages: if api in exp_seq: try: - match = dut.expect(r'\[_ss_spi_flash_hal_(\w+)\] Illegal flash access at \s*(0x[0-9a-fA-F]+)', timeout=5) + match = dut.expect( + r'\[_ss_spi_flash_hal_(\w+)\] Illegal flash access at \s*(0x[0-9a-fA-F]+)', timeout=5 + ) fault_api = match.group(1).decode() if fault_api != exp_seq[api][stage - 2]: raise RuntimeError('Flash operation address check failed') @@ -186,7 +192,7 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl # NOTE: The esp_partition_read API handles both decrypted # and plaintext reads. When flash encryption is enabled, # it uses the MMU HAL instead of the SPI flash HAL. - exc = dut.expect(r"Core ([01]) panic\'ed \(([^)]+)\)", timeout=5).group(2).decode() + exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=5).group(2).decode() if exc != 'Cache error': raise RuntimeError('Flash operation incorrect exception') else: @@ -197,8 +203,9 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_flash_prot_esp_partition_mmap(dut: IdfDut) -> None: # Flash the bootloader, TEE and REE firmware dut.serial.custom_flash() @@ -213,8 +220,9 @@ def test_esp_tee_flash_prot_esp_partition_mmap(dut: IdfDut) -> None: @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_flash_prot_spi_flash_mmap(dut: IdfDut) -> None: # Flash the bootloader, TEE and REE firmware dut.serial.custom_flash() @@ -229,8 +237,9 @@ def test_esp_tee_flash_prot_spi_flash_mmap(dut: IdfDut) -> None: @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_flash_prot_esp_rom_spiflash(dut: IdfDut) -> None: # Flash the bootloader, TEE and REE firmware dut.serial.custom_flash() @@ -245,8 +254,9 @@ def test_esp_tee_flash_prot_esp_rom_spiflash(dut: IdfDut) -> None: @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_flash_prot_esp_partition(dut: IdfDut) -> None: # Flash the bootloader, TEE and REE firmware dut.serial.custom_flash() @@ -261,8 +271,9 @@ def test_esp_tee_flash_prot_esp_partition(dut: IdfDut) -> None: @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_flash_prot_esp_flash(dut: IdfDut) -> None: # Flash the bootloader, TEE and REE firmware dut.serial.custom_flash() @@ -275,11 +286,13 @@ def test_esp_tee_flash_prot_esp_flash(dut: IdfDut) -> None: else: continue + # ---------------- TEE Local OTA tests ---------------- @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_ota_negative(dut: IdfDut) -> None: # start test dut.expect_exact('Press ENTER to see the list of tests') @@ -291,8 +304,9 @@ def test_esp_tee_ota_negative(dut: IdfDut) -> None: @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_ota_corrupted_img(dut: IdfDut) -> None: # Flashing the TEE app to the non-secure app's passive partition dut.serial.custom_flash_w_test_tee_img_gen() @@ -328,8 +342,9 @@ def tee_ota_stage_checks(dut: IdfDut, stage: TeeOtaStage, offset: str) -> None: @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_ota_reboot_without_ota_end(dut: IdfDut) -> None: # Flashing the TEE app to the non-secure app's passive partition dut.serial.custom_flash_w_test_tee_img_gen() @@ -352,8 +367,9 @@ def test_esp_tee_ota_reboot_without_ota_end(dut: IdfDut) -> None: @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_ota_valid_img(dut: IdfDut) -> None: # Flashing the TEE app to the non-secure app's passive partition dut.serial.custom_flash_w_test_tee_img_gen() @@ -384,8 +400,9 @@ def test_esp_tee_ota_valid_img(dut: IdfDut) -> None: @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_ota_rollback(dut: IdfDut) -> None: # Flashing the TEE app to the non-secure app's passive partition dut.serial.custom_flash_w_test_tee_img_rb() @@ -416,24 +433,28 @@ def test_esp_tee_ota_rollback(dut: IdfDut) -> None: # erasing TEE otadata dut.serial.erase_partition('tee_otadata') + # ---------------- TEE Secure Storage tests ---------------- @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_secure_storage(dut: IdfDut) -> None: # Flash image and erase the secure_storage partition dut.serial.custom_flash_with_empty_sec_stg() dut.run_all_single_board_cases(group='secure_storage') + # ---------------- TEE Attestation tests ---------------- @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) -@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_esp_tee_attestation(dut: IdfDut) -> None: # Flash image and erase the secure_storage partition dut.serial.custom_flash_with_empty_sec_stg() 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..26e520e27b 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-2025 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_vfs_console/test_apps/usb_cdc_vfs/pytest_usb_cdc_vfs.py b/components/esp_vfs_console/test_apps/usb_cdc_vfs/pytest_usb_cdc_vfs.py index b6c8503d45..5d3d30021f 100644 --- a/components/esp_vfs_console/test_apps/usb_cdc_vfs/pytest_usb_cdc_vfs.py +++ b/components/esp_vfs_console/test_apps/usb_cdc_vfs/pytest_usb_cdc_vfs.py @@ -2,17 +2,19 @@ # 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.usb_device @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'], indirect=['target']) def test_usb_cdc_vfs_default(dut: Dut, test_message: str) -> None: # test run: test_usb_cdc_select dut.expect_exact('test_usb_cdc_select', timeout=2) 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 8f52ec69e3..db91ffbcbf 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-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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.wifi_two_dut @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.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( @@ -27,5 +23,6 @@ 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 bdaa31ad27..6d39624d92 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-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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,5 +23,6 @@ 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() diff --git a/components/espcoredump/test_apps/pytest_coredump.py b/components/espcoredump/test_apps/pytest_coredump.py index c3e241a991..8685495c35 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-2025 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..e14e927a34 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-2025 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..0339f8b6b3 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-2025 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..add0149f51 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-2025 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 b49aece201..b0657186d2 100644 --- a/components/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py +++ b/components/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py @@ -1,52 +1,50 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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.sdcard_sdmode @pytest.mark.parametrize( 'config', [ 'default', 'release', - ] + ], ) +@idf_parametrize('target', ['esp32', 'esp32c3'], 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 @@ -54,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 15d798b931..6ea7c3cf78 100644 --- a/components/freertos/test_apps/freertos/pytest_freertos.py +++ b/components/freertos/test_apps/freertos/pytest_freertos.py @@ -1,57 +1,88 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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', 'esp32h21'], - reason='test failed/TBD IDF-8113') - ]), + pytest.param( + 'smp', + marks=[ + pytest.mark.supported_targets, + pytest.mark.temp_skip_ci( + targets=['esp32p4', 'esp32c5', 'esp32c61', 'esp32h21'], reason='test failed/TBD IDF-8113' + ), + ], + ), ] @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', 'esp32h21'], reason='test failed/TBD IDF-8113' + ), + ), + ), + ], + 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..0b8f3dab83 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-2025 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..16d1a2b39f 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-2025 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 e36de539b1..eaa23700be 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-2025 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"') @@ -94,14 +71,15 @@ def test_heap_misc_options(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.parametrize( - 'config', +@idf_parametrize( + 'config,target', [ - pytest.param('heap_trace_esp32', marks=[pytest.mark.esp32]), - pytest.param('heap_trace_hashmap_esp32', marks=[pytest.mark.esp32]), - pytest.param('heap_trace_esp32c3', marks=[pytest.mark.esp32c3]), - pytest.param('heap_trace_hashmap_esp32c3', marks=[pytest.mark.esp32c3]) - ] + ('heap_trace_esp32', 'esp32'), + ('heap_trace_hashmap_esp32', 'esp32'), + ('heap_trace_esp32c3', 'esp32c3'), + ('heap_trace_hashmap_esp32c3', 'esp32c3'), + ], + indirect=['config', 'target'], ) def test_heap_trace_dump(dut: Dut) -> None: dut.run_all_single_board_cases(group='trace-dump&internal') @@ -111,13 +89,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..582cbf2f56 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-2025 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..15cf390d9d 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-2025 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 c60206131c..ffd06d72fb 100644 --- a/components/log/host_test/log_test/pytest_log_linux.py +++ b/components/log/host_test/log_test/pytest_log_linux.py @@ -1,24 +1,29 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 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', - 'v1_color', - 'v2_color', - 'v2_no_color_no_support', - 'v2_no_timestamp', - 'v2_no_timestamp_no_support', - 'v2_rtos_timestamp', - 'v2_system_full_timestamp', - 'v2_system_timestamp', - 'tag_level_linked_list', - 'tag_level_linked_list_and_array_cache', - 'tag_level_none', -], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'default', + 'v1_color', + 'v2_color', + 'v2_no_color_no_support', + 'v2_no_timestamp', + 'v2_no_timestamp_no_support', + 'v2_rtos_timestamp', + 'v2_system_full_timestamp', + 'v2_system_timestamp', + 'tag_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..faa55a0030 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-2025 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..962dbd794b 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-2025 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 3614c8dcaa..3f640a94e8 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-2025 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,5 +83,6 @@ 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() 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..429b857470 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-2025 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..7e38dfac8d 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-2025 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 6b66d16736..36c142a74d 100644 --- a/components/newlib/test_apps/newlib/pytest_newlib.py +++ b/components/newlib/test_apps/newlib/pytest_newlib.py @@ -1,22 +1,23 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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('picolibc', 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'), + ('picolibc', '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..37b8275a7e 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-2025 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..0e30e463bf 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-2025 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..35af7f4d22 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-2025 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 b44656e19d..6ff278636f 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 @@ -2,35 +2,34 @@ # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded_idf.dut import IdfDut +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: IdfDut) -> None: dut.run_all_single_board_cases(group='!nvs_encrypted_bootloader', timeout=120) -@pytest.mark.esp32c3 @pytest.mark.nvs_encr_hmac @pytest.mark.parametrize('config', ['nvs_enc_hmac'], indirect=True) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_nvs_bootloader_support_encr_hmac(dut: IdfDut) -> None: dut.run_all_single_board_cases() -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.flash_encryption @pytest.mark.parametrize('config', ['nvs_enc_flash_enc'], indirect=True) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_nvs_bootloader_support_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.esp32c3 @pytest.mark.nvs_encr_hmac @pytest.mark.parametrize('config', ['nvs_enc_hmac_no_cfg'], indirect=True) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_nvs_bootloader_support_encr_hmac_no_cfg(dut: IdfDut) -> 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..2a810f2a87 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-2025 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..7d741121b3 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-2025 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..43ab9c38e7 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-2025 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..5e6aba09c9 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-2025 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..a4729a7292 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-2025 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 cc2c4edac3..423e01c440 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 @@ -2,9 +2,9 @@ # 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,17 +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.esp32c5 -@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -35,15 +29,13 @@ def test_esp_flash(dut: Dut) -> None: ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32s3', 'esp32c3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32c5', 'esp32c61'], 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', @@ -52,11 +44,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( @@ -67,5 +59,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..d34314230c 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-2025 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..c85f9ffd6c 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-2025 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..68c4f23038 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 @@ -2,9 +2,9 @@ # 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 281403f885..09d1bda04d 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,10 +1,10 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 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', @@ -15,5 +15,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..020dfbf34d 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-2025 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..2d1ddfe6f7 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-2025 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..318e0d9f83 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-2025 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..04f50051eb 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-2025 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..b2db9c40df 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-2025 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 4d0c7f570e..653341e7e1 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 @@ -3,11 +3,9 @@ import pytest from pytest_embedded import Dut from pytest_embedded_idf import CaseTester +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -16,12 +14,11 @@ from pytest_embedded_idf import CaseTester ], 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', @@ -30,11 +27,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', @@ -43,16 +40,14 @@ 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 -) +@pytest.mark.parametrize('count', [2], indirect=True) @pytest.mark.parametrize( 'config', [ @@ -60,18 +55,23 @@ def test_lp_vad(dut: Dut) -> None: ], indirect=True, ) -def test_lp_core_multi_device(case_tester) -> None: # type: ignore +@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) @pytest.mark.generic_multi_device -@pytest.mark.parametrize('target', [ - 'esp32c5', - 'esp32c6', - 'esp32p4', -], indirect=True) +@pytest.mark.parametrize( + 'target', + [ + 'esp32c5', + 'esp32c6', + 'esp32p4', + ], + indirect=True, +) @pytest.mark.parametrize( 'config', [ @@ -81,10 +81,7 @@ def test_lp_core_multi_device(case_tester) -> None: # type: ignore ) @pytest.mark.parametrize('count', [2], indirect=True) def test_lp_uart_wakeup_modes(case_tester: CaseTester) -> None: - relevant_cases = [ - case for case in case_tester.test_menu - if {'wakeup', 'uart'}.issubset(case.groups) - ] + relevant_cases = [case for case in case_tester.test_menu if {'wakeup', 'uart'}.issubset(case.groups)] assert len(relevant_cases) == 12, ( f"Expected 12 test cases with groups 'wakeup' and 'uart', but found {len(relevant_cases)}." ) 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..72e91019cc 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-2025 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 9db9abb6a9..c41d7d4f0d 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,13 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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() 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..dacb99920d 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-2025 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/enum/pytest_enum.py b/components/usb/test_apps/enum/pytest_enum.py index ac834f948a..024f9f8016 100644 --- a/components/usb/test_apps/enum/pytest_enum.py +++ b/components/usb/test_apps/enum/pytest_enum.py @@ -2,9 +2,10 @@ # 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.temp_skip_ci(targets=['esp32s3'], reason='only to run locally') +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_usb_enum(dut: Dut) -> None: dut.run_all_single_board_cases(group='mock_enum_device', timeout=250) # some tests take more than default timeout diff --git a/components/usb/test_apps/hcd/pytest_usb_hcd.py b/components/usb/test_apps/hcd/pytest_usb_hcd.py index 4bb9ea888c..9b0f3048f1 100644 --- a/components/usb/test_apps/hcd/pytest_usb_hcd.py +++ b/components/usb/test_apps/hcd/pytest_usb_hcd.py @@ -2,15 +2,14 @@ # 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_hcd(dut: Dut) -> None: - if (dut.target == 'esp32s3'): + if dut.target == 'esp32s3': dut.run_all_single_board_cases(group='full_speed', reset=True) else: 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..586730c428 100644 --- a/components/usb/test_apps/phy/pytest_usb_phy.py +++ b/components/usb/test_apps/phy/pytest_usb_phy.py @@ -2,11 +2,10 @@ # 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 95dd043de6..8d712c673f 100644 --- a/components/usb/test_apps/usb_host/pytest_usb_host.py +++ b/components/usb/test_apps/usb_host/pytest_usb_host.py @@ -2,15 +2,14 @@ # 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 == 'esp32s3'): + if dut.target == 'esp32s3': dut.run_all_single_board_cases(group='full_speed', reset=True) else: 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..038e405e29 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-2025 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..6c952b16f1 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-2025 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..98287957a8 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-2025 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 5968529522..0b535dd157 100644 --- a/components/wpa_supplicant/test_apps/pytest_wpa_supplicant_ut.py +++ b/components/wpa_supplicant/test_apps/pytest_wpa_supplicant_ut.py @@ -1,32 +1,30 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 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.wifi_two_dut @pytest.mark.parametrize( 'count', [ 2, ], - indirect=True + indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_wpa_supplicant_ut_offchan(case_tester: CaseTester) -> None: for case in case_tester.test_menu: if case.attributes.get('test_env') == 'wifi_two_dut': @@ -34,15 +32,18 @@ def test_wpa_supplicant_ut_offchan(case_tester: CaseTester) -> None: # test when external bss segment is enabled -@pytest.mark.esp32s3 @pytest.mark.wifi_two_dut @pytest.mark.parametrize( 'count, config', [ - (2, 'ext_esp32s3',), + ( + 2, + 'ext_esp32s3', + ), ], - indirect=True + indirect=True, ) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) def test_wpa_supplicant_ut_psram(case_tester: CaseTester) -> None: for case in case_tester.test_menu: if case.attributes.get('test_env') == 'wifi_two_dut': 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 e99fc108a9..a19cb8ed78 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-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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(EXAMPLE_CI_ID = 2) -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 + + @pytest.mark.wifi_two_dut @pytest.mark.parametrize( - 'count, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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(EXAMPLE_CI_ID = 2) -@pytest.mark.esp32c2 @pytest.mark.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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(EXAMPLE_CI_ID = 1) -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 @pytest.mark.wifi_two_dut @pytest.mark.parametrize( - 'count, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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(EXAMPLE_CI_ID = 1) -@pytest.mark.esp32c2 @pytest.mark.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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 f2d020c6d1..7ac6ec61fc 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-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os.path from typing import Tuple @@ -7,31 +7,36 @@ import pexpect import pytest from pytest_embedded import Dut from pytest_embedded_idf.dut import IdfDut - - +from pytest_embedded_idf.utils import idf_parametrize # Case 1: gatt client and gatt server test # EXAMPLE_CI_ID=3 -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 + + @pytest.mark.wifi_two_dut @pytest.mark.parametrize( - 'count, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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) @@ -56,22 +61,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 # EXAMPLE_CI_ID=3 -@pytest.mark.esp32c2 @pytest.mark.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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) @@ -96,26 +110,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 # EXAMPLE_CI_ID=5 -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 @pytest.mark.wifi_two_dut @pytest.mark.parametrize( - 'count, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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) @@ -142,7 +160,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) @@ -158,21 +178,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 # EXAMPLE_CI_ID=5 -@pytest.mark.esp32c2 @pytest.mark.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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) @@ -193,7 +222,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) @@ -208,27 +239,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.wifi_two_dut @pytest.mark.parametrize( - 'count, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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) @@ -242,14 +277,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.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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, ) @@ -257,7 +297,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) @@ -272,27 +316,31 @@ def test_c2_26mhz_ble_ibeacon_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> # Case 6: gatt client and gatt server config test # EXAMPLE_CI_ID=4 -@pytest.mark.esp32 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 @pytest.mark.wifi_two_dut @pytest.mark.parametrize( - 'count, app_path, config, erase_nvs', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "gatt_server")}|{os.path.join(os.path.dirname(__file__), "gatt_client")}', - 'cfg_test', 'y'), + 'count, app_path, config, erase_nvs', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "gatt_server")}|{os.path.join(os.path.dirname(__file__), "gatt_client")}', + 'cfg_test', + 'y', + ), ], indirect=True, ) +@idf_parametrize( + 'target', ['esp32', 'esp32c3', 'esp32c6', 'esp32c5', 'esp32h2', 'esp32s3', 'esp32c61'], indirect=['target'] +) def test_gatt_config_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) @@ -317,22 +365,31 @@ def test_gatt_config_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # Case 7: gatt client and gatt server config test for ESP32C2 26mhz xtal # EXAMPLE_CI_ID=3 -@pytest.mark.esp32c2 @pytest.mark.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_nvs', [ - (2, 'esp32c2|esp32c2', '74880', - f'{os.path.join(os.path.dirname(__file__), "gatt_server")}|{os.path.join(os.path.dirname(__file__), "gatt_client")}', - 'esp32c2_cfg_test', 'y'), + 'count, target, baud, app_path, config, erase_nvs', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + f'{os.path.join(os.path.dirname(__file__), "gatt_server")}|{os.path.join(os.path.dirname(__file__), "gatt_client")}', + 'esp32c2_cfg_test', + 'y', + ), ], indirect=True, ) def test_c2_26mhz_xtal_gatt_config_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) @@ -356,16 +413,13 @@ def test_c2_26mhz_xtal_gatt_config_func(app_path: str, dut: Tuple[IdfDut, IdfDut # Case 8: BLE init deinit loop test -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c61 -@pytest.mark.esp32 @pytest.mark.generic -@pytest.mark.parametrize('config, app_path', [('init_deinit', - f'{os.path.join(os.path.dirname(__file__), "gatt_client")}')], indirect=True) +@pytest.mark.parametrize( + 'config, app_path', [('init_deinit', f'{os.path.join(os.path.dirname(__file__), "gatt_client")}')], indirect=True +) +@idf_parametrize( + 'target', ['esp32c6', 'esp32h2', 'esp32c3', 'esp32s3', 'esp32c5', 'esp32c61', 'esp32'], indirect=['target'] +) def test_bluedroid_host_init_deinit(dut: Dut) -> None: all_hp = [] dut.expect_exact('Bluetooth MAC:') @@ -377,17 +431,16 @@ def test_bluedroid_host_init_deinit(dut: Dut) -> None: # # Case 9: BLE init deinit loop test for ESP32C2 26mhz xtal -@pytest.mark.esp32c2 @pytest.mark.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'baud, app_path, config', [ - ('74880', - f'{os.path.join(os.path.dirname(__file__), "gatt_client")}', - 'esp32c2_init_deinit'), + 'baud, app_path, config', + [ + ('74880', f'{os.path.join(os.path.dirname(__file__), "gatt_client")}', 'esp32c2_init_deinit'), ], indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_c2_26mhz_bluedroid_host_init_deinit(dut: Dut) -> None: all_hp = [] dut.expect_exact('Bluetooth MAC:') diff --git a/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py b/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py index b3b42a6a3c..d48aef51ac 100644 --- a/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py +++ b/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py @@ -1,34 +1,38 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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 # EXAMPLE_CI_ID=6 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 + + @pytest.mark.wifi_two_dut @pytest.mark.parametrize( - 'count, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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) @@ -48,22 +52,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 # EXAMPLE_CI_ID=6 -@pytest.mark.esp32c2 @pytest.mark.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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) @@ -83,21 +96,20 @@ def test_c2_26mhz_xtal_ble50_security_func(app_path: str, dut: Tuple[IdfDut, Idf # Case 3: period_adv and period_sync test # EXAMPLE_CI_ID=8 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 @pytest.mark.wifi_two_dut @pytest.mark.parametrize( - 'count, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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] @@ -118,14 +130,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 # EXAMPLE_CI_ID=8 -@pytest.mark.esp32c2 @pytest.mark.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_nvs', [ - (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_nvs', + [ + ( + 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, ) @@ -149,26 +166,29 @@ def test_c2_26mhz_xtal_period_adv_sync_func(app_path: str, dut: Tuple[IdfDut, Id # Case 5: ble50 security client and ble50 security server config test # EXAMPLE_CI_ID=7 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32c5 -@pytest.mark.esp32h2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c61 @pytest.mark.wifi_two_dut @pytest.mark.parametrize( - 'count, app_path, config, erase_nvs', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "ble50_security_server")}|{os.path.join(os.path.dirname(__file__), "ble50_security_client")}', - 'cfg_test', 'y'), + 'count, app_path, config, erase_nvs', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "ble50_security_server")}|{os.path.join(os.path.dirname(__file__), "ble50_security_client")}', + 'cfg_test', + 'y', + ), ], indirect=True, ) +@idf_parametrize('target', ['esp32c3', 'esp32c6', 'esp32c5', 'esp32h2', 'esp32s3', 'esp32c61'], indirect=['target']) def test_ble50_security_config_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) @@ -190,22 +210,31 @@ def test_ble50_security_config_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) - # Case 6: ble50 security client and ble50 security server config test for ESP32C2 26mhz xtal # EXAMPLE_CI_ID=7 -@pytest.mark.esp32c2 @pytest.mark.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'count, target, baud, app_path, config, erase_nvs', [ - (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_cfg_test', 'y'), + 'count, target, baud, app_path, config, erase_nvs', + [ + ( + 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_cfg_test', + 'y', + ), ], indirect=True, ) def test_c2_26mhz_xtal_ble50_security_config_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) 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..08bee890f0 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-2025 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 07e1e27f31..4154dce414 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-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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.wifi_two_dut @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.wifi_two_dut @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: A2DP -@pytest.mark.esp32 @pytest.mark.wifi_two_dut @pytest.mark.parametrize( - 'count, app_path, target, config', [ - (2, - f'{os.path.join(os.path.dirname(__file__), "a2dp_sink")}|{os.path.join(os.path.dirname(__file__), "a2dp_source")}', - 'esp32|esp32', 'test'), + 'count, app_path, target, config', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "a2dp_sink")}|{os.path.join(os.path.dirname(__file__), "a2dp_source")}', + 'esp32|esp32', + 'test', + ), ], indirect=True, ) @@ -87,13 +97,16 @@ def test_bt_a2dp(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # Case 4: HFP -@pytest.mark.esp32 @pytest.mark.wifi_two_dut @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, ) @@ -109,14 +122,17 @@ def test_bt_hfp(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # # Case 5: HID -@pytest.mark.esp32 @pytest.mark.wifi_two_dut @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, ) @@ -135,13 +151,16 @@ def test_bt_hid(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: # Case 6: L2CAP -@pytest.mark.esp32 @pytest.mark.wifi_two_dut @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, ) diff --git a/examples/bluetooth/nimble/pytest_nimble_test.py b/examples/bluetooth/nimble/pytest_nimble_test.py index 76ab824842..47eb5488ef 100644 --- a/examples/bluetooth/nimble/pytest_nimble_test.py +++ b/examples/bluetooth/nimble/pytest_nimble_test.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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.wifi_two_dut @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.wifi_two_dut @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..95f86b0807 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-2025 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..61fec11187 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-2025 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_extra_dir/pytest_bootloader_extra_dir.py b/examples/custom_bootloader/bootloader_extra_dir/pytest_bootloader_extra_dir.py index 217ce76f8e..274e392cd8 100644 --- a/examples/custom_bootloader/bootloader_extra_dir/pytest_bootloader_extra_dir.py +++ b/examples/custom_bootloader/bootloader_extra_dir/pytest_bootloader_extra_dir.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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_extra_component(dut: Dut) -> None: dut.expect_exact('This function is called from an extra component') 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..5c32d93293 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-2025 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_multiboot/pytest_custom_bootloader_multiboot.py b/examples/custom_bootloader/bootloader_multiboot/pytest_custom_bootloader_multiboot.py index f9a9a5cf98..35f013612f 100644 --- a/examples/custom_bootloader/bootloader_multiboot/pytest_custom_bootloader_multiboot.py +++ b/examples/custom_bootloader/bootloader_multiboot/pytest_custom_bootloader_multiboot.py @@ -1,13 +1,13 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.generic +@idf_parametrize('target', ['esp32c3', 'esp32s3'], indirect=['target']) def test_custom_bootloader_multiboot_example(app: IdfApp, dut: Dut) -> None: # Expect to see all three partitions in the list dut.expect_exact('default') 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..3ed72b3f3a 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-2025 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..f62a8ae866 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-2025 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..c52438184a 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-2025 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..e6d81bd99b 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-2025 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..d9109007ac 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-2025 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..25a4718275 100644 --- a/examples/ethernet/iperf/pytest_eth_iperf.py +++ b/examples/ethernet/iperf/pytest_eth_iperf.py @@ -1,5 +1,7 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 +from pytest_embedded_idf.utils import idf_parametrize + """ Test case for iperf example. @@ -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..55be95a566 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-2025 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 30b63b638c..eb02bd7782 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-2025 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,14 +45,11 @@ def verify_elf_sha256_embedding(app: QemuApp, sha256_reported: str) -> None: raise ValueError('ELF file SHA256 mismatch') -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.host_test @pytest.mark.qemu +@idf_parametrize('target', ['esp32', 'esp32c3'], 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..9e9dd4f18f 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-2025 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 419cce09ab..007f4c2d2b 100644 --- a/examples/network/bridge/pytest_example_bridge.py +++ b/examples/network/bridge/pytest_example_bridge.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import ipaddress import logging @@ -17,8 +17,9 @@ 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 + BR_PORTS_NUM = 2 IPERF_BW_LIM = 6 MIN_UDP_THROUGHPUT = 5 @@ -30,9 +31,7 @@ class EndnodeSsh: self.host_ip = host_ip 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) self.executor: ThreadPoolExecutor self.async_result: Future @@ -69,9 +68,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', @@ -119,7 +116,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 '' @@ -160,7 +160,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: @@ -168,19 +176,29 @@ def run_iperf(proto: str, endnode: EndnodeSsh, server_ip: str, bandwidth_lim:int if ipaddress.ip_address(server_ip).is_multicast: # Configure Multicast Server - server_proc = subprocess.Popen(['iperf', '-u', '-s', '-i', '1', '-t', '%i' % interval, '-B', '%s%%%s' - % (server_ip, server_if)], text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + server_proc = subprocess.Popen( + ['iperf', '-u', '-s', '-i', '1', '-t', '%i' % interval, '-B', '%s%%%s' % (server_ip, server_if)], + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) # Configure Multicast Client endnode_ip = get_endnode_ip_by_interface(endnode, client_if) if endnode_ip == '': raise RuntimeError('End node IP address not found') - client_res = endnode.exec_cmd('iperf -u -c %s -t %i -i 1 -b %iM --ttl 5 -B %s' % (server_ip, interval, bandwidth_lim, endnode_ip)) + client_res = endnode.exec_cmd( + 'iperf -u -c %s -t %i -i 1 -b %iM --ttl 5 -B %s' % (server_ip, interval, bandwidth_lim, endnode_ip) + ) if server_proc.wait(10) is None: # Process did not finish. server_proc.terminate() else: # Configure Server - server_proc = subprocess.Popen(['iperf', '%s' % proto, '-s', '-i', '1', '-t', '%i' % interval], text=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + server_proc = subprocess.Popen( + ['iperf', '%s' % proto, '-s', '-i', '1', '-t', '%i' % interval], + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) # Configure Client client_res = endnode.exec_cmd('iperf %s -c %s -t %i -i 1 -b %iM' % (proto, server_ip, interval, bandwidth_lim)) if server_proc.wait(10) is None: # Process did not finish. @@ -239,16 +257,16 @@ def send_brcast_msg_endnode_to_host(endnode: EndnodeSsh, host_brcast_ip: str, te return nc_host_out -@pytest.mark.esp32 @pytest.mark.eth_w5500 -@pytest.mark.parametrize('config', [ - 'w5500', -], indirect=True) -def test_esp_eth_bridge( - dut: Dut, - dev_user: str, - dev_password: str -) -> None: +@pytest.mark.parametrize( + 'config', + [ + 'w5500', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) +def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None: # ------------------------------ # # Pre-test testbed configuration # # ------------------------------ # @@ -263,18 +281,15 @@ def test_esp_eth_bridge( port_num = int(sw_info.group(2)) port_num_endnode = int(port_num) + 1 # endnode address is always + 1 to the host - endnode = EndnodeSsh(f'10.10.{sw_num}.{port_num_endnode}', - dev_user, - dev_password) - switch1 = SwitchSsh(f'10.10.{sw_num}.100', - dev_user, - dev_password, - SwitchSsh.EDGE_SWITCH_10XP) + endnode = EndnodeSsh(f'10.10.{sw_num}.{port_num_endnode}', dev_user, dev_password) + switch1 = SwitchSsh(f'10.10.{sw_num}.100', dev_user, dev_password, SwitchSsh.EDGE_SWITCH_10XP) # Collect all addresses in our network # ------------------------------------ # Bridge (DUT) MAC - br_mac = dut.expect(r'esp_netif_br_glue: ([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})') + br_mac = dut.expect( + r'esp_netif_br_glue: ([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})' + ) br_mac = br_mac.group(1).decode('utf-8') logging.info('ESP Bridge MAC %s', br_mac) # Get unique identification of each Ethernet port @@ -350,7 +365,9 @@ def test_esp_eth_bridge( 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) @@ -369,30 +386,43 @@ def test_esp_eth_bridge( # unicast UDP bandwidth_udp = run_iperf('udp', endnode, host_ip, IPERF_BW_LIM, 5) if bandwidth_udp < MIN_UDP_THROUGHPUT: - logging.warning('Unicast UDP bandwidth was less than expected. Trying again over longer period to compensate transient drops.') + logging.warning( + 'Unicast UDP bandwidth was less than expected. Trying again over longer period to compensate transient drops.' + ) bandwidth_udp = run_iperf('udp', endnode, host_ip, IPERF_BW_LIM, 60) logging.info('Unicast UDP average bandwidth: %s Mbits/s', bandwidth_udp) # unicast TCP bandwidth_tcp = run_iperf('tcp', endnode, host_ip, IPERF_BW_LIM, 5) if bandwidth_tcp < MIN_TCP_THROUGHPUT: - logging.warning('Unicast TCP bandwidth was less than expected. Trying again over longer period to compensate transient drops.') + logging.warning( + 'Unicast TCP bandwidth was less than expected. Trying again over longer period to compensate transient drops.' + ) bandwidth_tcp = run_iperf('tcp', endnode, host_ip, IPERF_BW_LIM, 60) logging.info('Unicast TCP average bandwidth: %s Mbits/s', bandwidth_tcp) # multicast UDP bandwidth_mcast_udp = run_iperf('udp', endnode, '224.0.1.4', IPERF_BW_LIM, 5, host_if, endnode_if) if bandwidth_mcast_udp < MIN_UDP_THROUGHPUT: - logging.warning('Multicast UDP bandwidth was less than expected. Trying again over longer period to compensate transient drops.') + logging.warning( + 'Multicast UDP bandwidth was less than expected. Trying again over longer period to compensate transient drops.' + ) bandwidth_mcast_udp = run_iperf('udp', endnode, '224.0.1.4', IPERF_BW_LIM, 60, host_if, endnode_if) logging.info('Multicast UDP average bandwidth: %s Mbits/s', bandwidth_mcast_udp) if bandwidth_udp < MIN_UDP_THROUGHPUT: - raise RuntimeError('Unicast UDP throughput expected %.2f, actual %.2f' % (MIN_UDP_THROUGHPUT, bandwidth_udp) + ' Mbits/s') + raise RuntimeError( + 'Unicast UDP throughput expected %.2f, actual %.2f' % (MIN_UDP_THROUGHPUT, bandwidth_udp) + ' Mbits/s' + ) if bandwidth_tcp < MIN_TCP_THROUGHPUT: - raise RuntimeError('Unicast TCP throughput expected %.2f, actual %.2f' % (MIN_TCP_THROUGHPUT, bandwidth_tcp) + ' Mbits/s') + raise RuntimeError( + 'Unicast TCP throughput expected %.2f, actual %.2f' % (MIN_TCP_THROUGHPUT, bandwidth_tcp) + ' Mbits/s' + ) if bandwidth_mcast_udp < MIN_UDP_THROUGHPUT: - raise RuntimeError('Multicast UDP throughput expected %.2f, actual %.2f' % (MIN_UDP_THROUGHPUT, bandwidth_mcast_udp) + ' Mbits/s') + raise RuntimeError( + 'Multicast UDP throughput expected %.2f, actual %.2f' % (MIN_UDP_THROUGHPUT, bandwidth_mcast_udp) + + ' Mbits/s' + ) # ------------------------------------------------ # TEST Objective 4: adding/deleting entries in FDB diff --git a/examples/network/simple_sniffer/pytest_simple_sniffer.py b/examples/network/simple_sniffer/pytest_simple_sniffer.py index ec4808c5e4..12ad33fe06 100644 --- a/examples/network/simple_sniffer/pytest_simple_sniffer.py +++ b/examples/network/simple_sniffer/pytest_simple_sniffer.py @@ -3,6 +3,7 @@ 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: @@ -36,18 +37,19 @@ 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.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 -@pytest.mark.esp32s2 -@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', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32s2', '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..c646e5b370 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-2025 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 9c0e8cf017..45c1b31fd7 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -91,15 +91,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=1) @pytest.mark.parametrize( @@ -113,7 +108,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', @@ -123,12 +118,12 @@ 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, ) -def test_thread_connect(dut:Tuple[IdfDut, IdfDut, IdfDut]) -> None: +def test_thread_connect(dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: br = dut[2] cli_h2 = dut[1] dut[0].serial.stop_redirect_thread() @@ -168,7 +163,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) @@ -179,11 +174,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=1) @pytest.mark.parametrize( @@ -197,14 +191,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: +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() @@ -236,7 +230,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=1) @pytest.mark.parametrize( @@ -250,14 +243,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: +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() @@ -290,7 +283,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=1) @pytest.mark.parametrize( @@ -304,14 +296,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: +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() @@ -324,7 +316,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: @@ -345,7 +337,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=1) @pytest.mark.parametrize( @@ -359,14 +350,16 @@ 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, ) -def test_service_discovery_of_Thread_device(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: +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() @@ -405,7 +398,6 @@ def test_service_discovery_of_Thread_device(Init_interface:bool, Init_avahi:bool # Case 6: discover dervice published by Wi-Fi device -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( @@ -419,14 +411,16 @@ def test_service_discovery_of_Thread_device(Init_interface:bool, Init_avahi:bool 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_service_discovery_of_WiFi_device(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None: +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() @@ -474,7 +468,6 @@ def test_service_discovery_of_WiFi_device(Init_interface:bool, Init_avahi:bool, # Case 7: ICMP communication via NAT64 -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( @@ -488,14 +481,14 @@ def test_service_discovery_of_WiFi_device(Init_interface:bool, Init_avahi:bool, 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: +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() @@ -513,7 +506,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=1) @pytest.mark.parametrize( @@ -527,14 +519,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: +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() @@ -549,7 +541,7 @@ def test_UDP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N host_ipv4_address = ocf.get_host_ipv4_address() print('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: @@ -570,7 +562,6 @@ def test_UDP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N # Case 9: TCP communication via NAT64 -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( @@ -584,14 +575,14 @@ def test_UDP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N 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: +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() @@ -607,7 +598,7 @@ def test_TCP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N connect_address = ocf.get_ipv6_from_ipv4(host_ipv4_address, br) print('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: @@ -633,8 +624,6 @@ def test_TCP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N # Case 10: Sleepy device test -@pytest.mark.esp32h2 -@pytest.mark.esp32c6 @pytest.mark.openthread_sleep @pytest.mark.parametrize( 'config, count, app_path, target, port', @@ -646,7 +635,7 @@ def test_TCP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N 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', @@ -655,7 +644,7 @@ def test_TCP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N 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, @@ -693,7 +682,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=1) @pytest.mark.parametrize( @@ -702,11 +690,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, @@ -735,7 +722,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=1) @pytest.mark.parametrize( @@ -749,14 +735,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: +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() @@ -777,7 +763,6 @@ def test_NAT64_DNS(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N # Case 13: Meshcop discovery of Border Router -@pytest.mark.supported_targets @pytest.mark.openthread_br @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( @@ -786,16 +771,15 @@ def test_NAT64_DNS(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N 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, ) -def test_br_meshcop(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, IdfDut]) -> None: +def test_br_meshcop(Init_interface: bool, Init_avahi: bool, dut: Tuple[IdfDut, IdfDut]) -> None: br = dut[1] assert Init_interface assert Init_avahi @@ -839,7 +823,6 @@ def test_br_meshcop(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, Idf # 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=1) @pytest.mark.parametrize( @@ -853,14 +836,14 @@ def test_br_meshcop(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, Idf 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: +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() @@ -879,7 +862,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=1) @pytest.mark.parametrize( @@ -892,7 +874,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, @@ -934,7 +916,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=1) @pytest.mark.parametrize( @@ -943,11 +924,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/adc/continuous_read/pytest_adc_continuous.py b/examples/peripherals/adc/continuous_read/pytest_adc_continuous.py index c891db39e8..53dbbdb8ea 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-2025 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..9702550ffa 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-2025 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 e9196eb6f8..6d512fc864 100644 --- a/examples/peripherals/analog_comparator/pytest_ana_cmpr_example.py +++ b/examples/peripherals/analog_comparator/pytest_ana_cmpr_example.py @@ -1,13 +1,10 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 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.esp32c5 -@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -17,9 +14,12 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'], 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/bitscrambler/pytest_bitscrambler_loopback_example.py b/examples/peripherals/bitscrambler/pytest_bitscrambler_loopback_example.py index df9bbf7617..7ade762b0f 100644 --- a/examples/peripherals/bitscrambler/pytest_bitscrambler_loopback_example.py +++ b/examples/peripherals/bitscrambler/pytest_bitscrambler_loopback_example.py @@ -2,11 +2,11 @@ # 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.esp32c5 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4', 'esp32c5'], indirect=['target']) def test_bitscrambler_loopback_example(dut: Dut) -> None: dut.expect_exact('BitScrambler example main', timeout=5) dut.expect_exact('BitScrambler program complete. Input 40, output 40 bytes') 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..63bad81e79 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-2025 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..569ced9a11 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-2025 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..4c4561c7fe 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-2025 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..d64cc10568 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-2025 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..2e4ab8ce3f 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-2025 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..3a44d53282 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-2025 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..a43eeb5bae 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-2025 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..52989ef804 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-2025 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_advance/i2s_usb/pytest_i2s_usb.py b/examples/peripherals/i2s/i2s_advance/i2s_usb/pytest_i2s_usb.py index 4a673b6833..034f1d56f2 100644 --- a/examples/peripherals/i2s/i2s_advance/i2s_usb/pytest_i2s_usb.py +++ b/examples/peripherals/i2s/i2s_advance/i2s_usb/pytest_i2s_usb.py @@ -2,11 +2,10 @@ # 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.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_i2s_usb_example(dut: Dut) -> None: dut.expect(r'initial MCLK: [0-9]+ Hz') 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 836c411a6d..2a7529f44e 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 @@ -2,50 +2,47 @@ # 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_pdm: Clock division info: \[sclk\] ([0-9]+) Hz ' - r'\[mdiv\] ([0-9]+) ([0-9]+)/([0-9]+) \[mclk\] ([0-9]+) Hz \[bdiv\] ([0-9]+) \[bclk\] ([0-9]+) Hz', 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: Clock division info: \[sclk\] ([0-9]+) Hz ' + r'\[mdiv\] ([0-9]+) ([0-9]+)/([0-9]+) \[mclk\] ([0-9]+) Hz \[bdiv\] ([0-9]+) \[bclk\] ([0-9]+) Hz', + 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 c4bbda6e53..9d7fbbbd5b 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 @@ -2,36 +2,41 @@ # 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_std: Clock division info: \[sclk\] ([0-9]+) Hz ' - r'\[mdiv\] ([0-9]+) ([0-9]+)/([0-9]+) \[mclk\] ([0-9]+) Hz \[bdiv\] ([0-9]+) \[bclk\] ([0-9]+) Hz', 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: Clock division info: \[sclk\] ([0-9]+) Hz ' + r'\[mdiv\] ([0-9]+) ([0-9]+)/([0-9]+) \[mclk\] ([0-9]+) Hz \[bdiv\] ([0-9]+) \[bclk\] ([0-9]+) Hz', + 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_std: Clock division info: \[sclk\] ([0-9]+) Hz ' - r'\[mdiv\] ([0-9]+) ([0-9]+)/([0-9]+) \[mclk\] ([0-9]+) Hz \[bdiv\] ([0-9]+) \[bclk\] ([0-9]+) Hz', 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: Clock division info: \[sclk\] ([0-9]+) Hz ' + r'\[mdiv\] ([0-9]+) ([0-9]+)/([0-9]+) \[mclk\] ([0-9]+) Hz \[bdiv\] ([0-9]+) \[bclk\] ([0-9]+) Hz', + 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 ecc130510c..65bf9da7be 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 @@ -2,34 +2,39 @@ # 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_tdm: Clock division info: \[sclk\] ([0-9]+) Hz ' - r'\[mdiv\] ([0-9]+) ([0-9]+)/([0-9]+) \[mclk\] ([0-9]+) Hz \[bdiv\] ([0-9]+) \[bclk\] ([0-9]+) Hz', 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: Clock division info: \[sclk\] ([0-9]+) Hz ' + r'\[mdiv\] ([0-9]+) ([0-9]+)/([0-9]+) \[mclk\] ([0-9]+) Hz \[bdiv\] ([0-9]+) \[bclk\] ([0-9]+) Hz', + 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_tdm: Clock division info: \[sclk\] ([0-9]+) Hz ' - r'\[mdiv\] ([0-9]+) ([0-9]+)/([0-9]+) \[mclk\] ([0-9]+) Hz \[bdiv\] ([0-9]+) \[bclk\] ([0-9]+) Hz', 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: Clock division info: \[sclk\] ([0-9]+) Hz ' + r'\[mdiv\] ([0-9]+) ([0-9]+)/([0-9]+) \[mclk\] ([0-9]+) Hz \[bdiv\] ([0-9]+) \[bclk\] ([0-9]+) Hz', + 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..0fda2176f5 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-2025 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 54404601b0..b9eb9d85f1 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-2025 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('I \\(([0-9]+)\\) i2s_es8311: i2s driver init success') -@pytest.mark.esp32s3 @pytest.mark.generic @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_bsp(dut: Dut) -> None: dut.expect('i2s es8311 codec example start') dut.expect('-----------------------------') diff --git a/examples/peripherals/i2s/i2s_recorder/pytest_i2s_record.py b/examples/peripherals/i2s/i2s_recorder/pytest_i2s_record.py index 5c1a92c2fc..be6b9f241b 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-2025 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 53a65f9950..c2ef947776 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-2025 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_rgb_lcd_lvgl(dut: Dut) -> None: dut.expect_exact('example: Install MIPI DSI LCD control panel') 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..972e00feac 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-2025 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..e298450400 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-2025 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..0fbdabd061 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-2025 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..141b0c83ff 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-2025 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..b3d1068824 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-2025 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..0f92ed3336 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-2025 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..aa632e16b5 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-2025 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..1899df802b 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-2025 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 9376556578..1c1127f565 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,11 +1,12 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 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 29d17f4c81..4d6c2271f7 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-2025 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..f8a55926c1 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-2025 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..4356000120 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-2025 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..209d836867 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-2025 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..d38b0f60cc 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-2025 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..bfbfb04a6d 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-2025 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..3571b45cbc 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-2025 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..aa538f42aa 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-2025 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..dea3c707fa 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-2025 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..99d1837f46 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-2025 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..7e5aa2f87a 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-2025 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 7cccdee2fe..df1727e3f4 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,19 +1,16 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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.esp32c61 @pytest.mark.generic +@idf_parametrize( + 'target', + ['esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'], + 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 458741547c..f5cccf04ac 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,15 +1,12 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 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.esp32c61 @pytest.mark.generic +@idf_parametrize('target', ['esp32c6', 'esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'], 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 29a534d611..835b540e21 100644 --- a/examples/peripherals/timer_group/gptimer/pytest_gptimer_example.py +++ b/examples/peripherals/timer_group/gptimer/pytest_gptimer_example.py @@ -1,12 +1,12 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 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) @@ -27,7 +27,7 @@ def test_gptimer_example(dut: Dut) -> None: dut.expect_exact('Stop timer') dut.expect_exact('Start timer, update alarm value dynamically') - for i in range(1,5): + for i in range(1, 5): res = dut.expect(r'Timer alarmed, count=(\d+)', timeout=5) alarm_count = res.group(1).decode('utf8') assert (i * 1000000 - 20) < int(alarm_count) < (i * 1000000 + 20) 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..559955d047 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-2025 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..50e23ceded 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-2025 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..0b6e6959b9 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-2025 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..d87760af97 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-2025 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..96d2f7c702 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-2025 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..e3d836e58f 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-2025 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..26a073d08d 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-2025 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_sens_basic/pytest_touch_sens_basic.py b/examples/peripherals/touch_sensor/touch_sens_basic/pytest_touch_sens_basic.py index b5b91f410a..3f02c3fbeb 100644 --- a/examples/peripherals/touch_sensor/touch_sens_basic/pytest_touch_sens_basic.py +++ b/examples/peripherals/touch_sensor/touch_sens_basic/pytest_touch_sens_basic.py @@ -2,13 +2,11 @@ # 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.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32p4'], indirect=['target']) def test_touch_sens(dut: Dut) -> None: dut.expect(r'Touch \[CH [0-9]+\] enabled on GPIO[0-9]+') dut.expect_exact('Initial benchmark and new threshold are:') 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..e86b71c064 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-2025 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_self_test/pytest_twai_self_test_example.py b/examples/peripherals/twai/twai_self_test/pytest_twai_self_test_example.py index ea139a4e35..39a0243050 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-2025 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..ac08448929 100644 --- a/examples/peripherals/uart/uart_async_rxtxtasks/pytest_async_rxtxtasks.py +++ b/examples/peripherals/uart/uart_async_rxtxtasks/pytest_async_rxtxtasks.py @@ -2,9 +2,10 @@ # 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..eb83282253 100644 --- a/examples/peripherals/uart/uart_events/pytest_events.py +++ b/examples/peripherals/uart/uart_events/pytest_events.py @@ -2,10 +2,11 @@ # 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..e9f6717bf5 100644 --- a/examples/peripherals/uart/uart_select/pytest_uart_select.py +++ b/examples/peripherals/uart/uart_select/pytest_uart_select.py @@ -2,10 +2,11 @@ # 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..2c42a9235a 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-2025 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..8860dbff92 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-2025 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..986b293fe8 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-2025 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..9c6a576246 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-2025 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..3503b0e62d 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-2025 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..ce60d13eb3 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-2025 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..f1dd71ef11 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-2025 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 cae9851d4c..6ee2bbdd00 100644 --- a/examples/peripherals/usb/host/msc/pytest_usb_host_msc.py +++ b/examples/peripherals/usb/host/msc/pytest_usb_host_msc.py @@ -1,14 +1,13 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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_msc_example(dut: Dut) -> None: # Get wMaxPacketSize to get USB device speed max_packet_size = int(dut.expect(r'wMaxPacketSize (\d{2,3})')[1].decode()) @@ -21,10 +20,10 @@ def test_usb_host_msc_example(dut: Dut) -> None: read_throughput = float(dut.expect(r'example: Read speed ([0-9]*[.]?[0-9]+) MiB')[1].decode()) # Set write and read throughput limits - if (max_packet_size == 512): # wMaxPacketSize = 512 for HS + if max_packet_size == 512: # wMaxPacketSize = 512 for HS write_throughput_limit = 4.9 read_throughput_limit = 11.5 - else: # wMaxPacketSize = 64 for FS + else: # wMaxPacketSize = 64 for FS write_throughput_limit = 0.9 read_throughput_limit = 1.0 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..b3907df7af 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-2025 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..6a4b68a5cb 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-2025 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 dc22927201..c329a16503 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-2025 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: | @@ -56,11 +57,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 @@ -103,13 +108,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..92820a6f2c 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-2025 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..b2a871e983 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-2025 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..7dba01c69a 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-2025 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/async_handlers/pytest_http_server_async.py b/examples/protocols/http_server/async_handlers/pytest_http_server_async.py index 1021fbbdc2..bebd7937b1 100644 --- a/examples/protocols/http_server/async_handlers/pytest_http_server_async.py +++ b/examples/protocols/http_server/async_handlers/pytest_http_server_async.py @@ -7,10 +7,11 @@ import time 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_http_server_async_handler(dut: Dut) -> None: # Get binary file binary_file = os.path.join(dut.app.binary_path, 'simple.bin') 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..60c051aa77 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-2025 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..64326435be 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-2025 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..e44704ec7a 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-2025 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 8de35734ed..828e833ccf 100644 --- a/examples/protocols/http_server/simple/pytest_http_server_simple.py +++ b/examples/protocols/http_server/simple/pytest_http_server_simple.py @@ -12,6 +12,7 @@ import threading import time import pytest +from pytest_embedded_idf.utils import idf_parametrize try: import http.client @@ -45,18 +46,15 @@ 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 -@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) @@ -106,7 +104,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 @@ -116,7 +114,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) @@ -125,12 +125,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) @@ -169,9 +166,15 @@ def test_examples_protocol_http_server_lru_purge_enable(dut: Dut) -> None: t.join() -@pytest.mark.esp32 @pytest.mark.wifi_router -@pytest.mark.parametrize('config', ['sse',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'sse', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_http_server_sse(dut: Dut) -> None: # Get binary file binary_file = os.path.join(dut.app.binary_path, 'simple.bin') 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 9dd1bf4c49..4a3b4c1443 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,16 +1,14 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - -from __future__ import division, print_function, unicode_literals - import logging 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 @@ -21,7 +19,7 @@ except ImportError: OPCODE_TEXT = 0x1 OPCODE_BIN = 0x2 OPCODE_PING = 0x9 -OPCODE_PONG = 0xa +OPCODE_PONG = 0xA class WsClient: @@ -30,17 +28,17 @@ class WsClient: self.ip = ip self.ws = websocket.WebSocket() - def __enter__(self): # type: ignore + def __enter__(self): # type: ignore self.ws.connect('ws://{}:{}/ws'.format(self.ip, self.port)) 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: @@ -48,8 +46,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') diff --git a/examples/protocols/https_mbedtls/pytest_https_mbedtls.py b/examples/protocols/https_mbedtls/pytest_https_mbedtls.py index 8fd2e2a313..0027bb8cc2 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-2025 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 e24bff59fd..456c5ede88 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-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import http.server import logging @@ -13,13 +13,15 @@ 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 -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' @@ -47,7 +49,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) @@ -58,12 +59,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') @@ -90,38 +97,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 @@ -137,24 +150,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 @@ -176,77 +188,84 @@ 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"') -@pytest.mark.esp32c2 @pytest.mark.wifi_ap @pytest.mark.xtal_26mhz @pytest.mark.parametrize( - 'config, baud', [ + 'config, baud', + [ ('esp32c2_rom_mbedtls', '74880'), - ], indirect=True + ], + indirect=True, ) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) def test_examples_protocol_https_request_rom_impl(dut: Dut) -> None: # Connect to AP if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True: @@ -268,64 +287,69 @@ def test_examples_protocol_https_request_rom_impl(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 98179cfca7..1ae348ec2b 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-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import http.client import logging @@ -10,89 +10,94 @@ 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'\ - 'MIIDKzCCAhOgAwIBAgIUBxM3WJf2bP12kAfqhmhhjZWv0ukwDQYJKoZIhvcNAQEL\n'\ - 'BQAwJTEjMCEGA1UEAwwaRVNQMzIgSFRUUFMgc2VydmVyIGV4YW1wbGUwHhcNMTgx\n'\ - 'MDE3MTEzMjU3WhcNMjgxMDE0MTEzMjU3WjAlMSMwIQYDVQQDDBpFU1AzMiBIVFRQ\n'\ - 'UyBzZXJ2ZXIgZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n'\ - 'ALBint6nP77RCQcmKgwPtTsGK0uClxg+LwKJ3WXuye3oqnnjqJCwMEneXzGdG09T\n'\ - 'sA0SyNPwrEgebLCH80an3gWU4pHDdqGHfJQa2jBL290e/5L5MB+6PTs2NKcojK/k\n'\ - 'qcZkn58MWXhDW1NpAnJtjVniK2Ksvr/YIYSbyD+JiEs0MGxEx+kOl9d7hRHJaIzd\n'\ - 'GF/vO2pl295v1qXekAlkgNMtYIVAjUy9CMpqaQBCQRL+BmPSJRkXBsYk8GPnieS4\n'\ - 'sUsp53DsNvCCtWDT6fd9D1v+BB6nDk/FCPKhtjYOwOAZlX4wWNSZpRNr5dfrxKsb\n'\ - 'jAn4PCuR2akdF4G8WLUeDWECAwEAAaNTMFEwHQYDVR0OBBYEFMnmdJKOEepXrHI/\n'\ - 'ivM6mVqJgAX8MB8GA1UdIwQYMBaAFMnmdJKOEepXrHI/ivM6mVqJgAX8MA8GA1Ud\n'\ - 'EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADiXIGEkSsN0SLSfCF1VNWO3\n'\ - 'emBurfOcDq4EGEaxRKAU0814VEmU87btIDx80+z5Dbf+GGHCPrY7odIkxGNn0DJY\n'\ - 'W1WcF+DOcbiWoUN6DTkAML0SMnp8aGj9ffx3x+qoggT+vGdWVVA4pgwqZT7Ybntx\n'\ - 'bkzcNFW0sqmCv4IN1t4w6L0A87ZwsNwVpre/j6uyBw7s8YoJHDLRFT6g7qgn0tcN\n'\ - 'ZufhNISvgWCVJQy/SZjNBHSpnIdCUSJAeTY2mkM4sGxY0Widk8LnjydxZUSxC3Nl\n'\ - 'hb6pnMh3jRq4h0+5CZielA4/a+TdrNPv/qok67ot/XJdY3qHCCd8O2b14OVq9jo=\n'\ - '-----END CERTIFICATE-----\n' +server_cert_pem = ( + '-----BEGIN CERTIFICATE-----\n' + 'MIIDKzCCAhOgAwIBAgIUBxM3WJf2bP12kAfqhmhhjZWv0ukwDQYJKoZIhvcNAQEL\n' + 'BQAwJTEjMCEGA1UEAwwaRVNQMzIgSFRUUFMgc2VydmVyIGV4YW1wbGUwHhcNMTgx\n' + 'MDE3MTEzMjU3WhcNMjgxMDE0MTEzMjU3WjAlMSMwIQYDVQQDDBpFU1AzMiBIVFRQ\n' + 'UyBzZXJ2ZXIgZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n' + 'ALBint6nP77RCQcmKgwPtTsGK0uClxg+LwKJ3WXuye3oqnnjqJCwMEneXzGdG09T\n' + 'sA0SyNPwrEgebLCH80an3gWU4pHDdqGHfJQa2jBL290e/5L5MB+6PTs2NKcojK/k\n' + 'qcZkn58MWXhDW1NpAnJtjVniK2Ksvr/YIYSbyD+JiEs0MGxEx+kOl9d7hRHJaIzd\n' + 'GF/vO2pl295v1qXekAlkgNMtYIVAjUy9CMpqaQBCQRL+BmPSJRkXBsYk8GPnieS4\n' + 'sUsp53DsNvCCtWDT6fd9D1v+BB6nDk/FCPKhtjYOwOAZlX4wWNSZpRNr5dfrxKsb\n' + 'jAn4PCuR2akdF4G8WLUeDWECAwEAAaNTMFEwHQYDVR0OBBYEFMnmdJKOEepXrHI/\n' + 'ivM6mVqJgAX8MB8GA1UdIwQYMBaAFMnmdJKOEepXrHI/ivM6mVqJgAX8MA8GA1Ud\n' + 'EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADiXIGEkSsN0SLSfCF1VNWO3\n' + 'emBurfOcDq4EGEaxRKAU0814VEmU87btIDx80+z5Dbf+GGHCPrY7odIkxGNn0DJY\n' + 'W1WcF+DOcbiWoUN6DTkAML0SMnp8aGj9ffx3x+qoggT+vGdWVVA4pgwqZT7Ybntx\n' + 'bkzcNFW0sqmCv4IN1t4w6L0A87ZwsNwVpre/j6uyBw7s8YoJHDLRFT6g7qgn0tcN\n' + 'ZufhNISvgWCVJQy/SZjNBHSpnIdCUSJAeTY2mkM4sGxY0Widk8LnjydxZUSxC3Nl\n' + 'hb6pnMh3jRq4h0+5CZielA4/a+TdrNPv/qok67ot/XJdY3qHCCd8O2b14OVq9jo=\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_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: | @@ -140,7 +145,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') @@ -156,7 +161,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)) @@ -168,11 +175,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 @@ -211,7 +222,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') @@ -227,7 +238,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..2d81d4441e 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-2025 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..52e48ce783 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-2025 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..3637c134be 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-2025 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 dce7e72ff7..3defccbbed 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-2025 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 @@ -18,7 +19,7 @@ ETH_TYPE_3 = 0x2223 @contextlib.contextmanager -def configure_eth_if(eth_type: int, target_if: str='') -> Iterator[socket.socket]: +def configure_eth_if(eth_type: int, target_if: str = '') -> Iterator[socket.socket]: if target_if == '': # try to determine which interface to use netifs = os.listdir('/sys/class/net/') @@ -42,7 +43,7 @@ def configure_eth_if(eth_type: int, target_if: str='') -> Iterator[socket.socket 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()) @@ -62,7 +63,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: @@ -101,9 +102,9 @@ def actual_test(dut: Dut) -> 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) @@ -113,12 +114,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 d27cc65b78..c34cea6e50 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-2025 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() @@ -50,7 +51,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 not event_client_received_correct.is_set() and payload == 'data': @@ -61,8 +64,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 @@ -95,14 +98,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..f8deb23ff6 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-2025 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..3ad6bd7426 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-2025 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..cb4a22e370 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-2025 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..dc7063e956 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-2025 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..c50eb8fbd5 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-2025 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..dd300295f7 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-2025 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..b1e083cb7b 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-2025 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..1670d8e334 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-2025 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..8d21569037 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-2025 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..f5bd527257 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-2025 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..1ab2343f32 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-2025 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..114e63e3a7 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-2025 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 01b90c6251..020505da88 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-2025 Espressif Systems (Shanghai) CO LTD # # SPDX-License-Identifier: CC0-1.0 import logging import os @@ -8,15 +8,13 @@ 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) -> None: - with open(os.path.join(dut.logdir, 'ocd.txt'), 'w', encoding='utf-8') as ocd_log, \ - pexpect.spawn(f'openocd -f board/esp32c6-builtin.cfg', - timeout=60, - logfile=ocd_log, - encoding='utf-8', - codec_errors='ignore') as p: + with open(os.path.join(dut.logdir, 'ocd.txt'), 'w', encoding='utf-8') as ocd_log, pexpect.spawn( + f'openocd -f board/esp32c6-builtin.cfg', timeout=60, logfile=ocd_log, encoding='utf-8', codec_errors='ignore' + ) as p: try: p.expect(re.compile(r'JTAG tap: esp32c6.cpu tap/device found'), timeout=5) logging.info('JTAG is enabled.') @@ -29,10 +27,9 @@ def run_gdb_test(dut: IdfDut) -> None: 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..463f3d191c 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-2025 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/security/tee/tee_attestation/pytest_tee_attestation.py b/examples/security/tee/tee_attestation/pytest_tee_attestation.py index 9909750bd9..debb2431ae 100644 --- a/examples/security/tee/tee_attestation/pytest_tee_attestation.py +++ b/examples/security/tee/tee_attestation/pytest_tee_attestation.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import hashlib import json @@ -11,6 +11,7 @@ from ecdsa.curves import NIST256p from ecdsa.keys import VerifyingKey from ecdsa.util import sigdecode_der from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize def verify_att_token_signature(att_tk: str) -> Any: @@ -44,8 +45,8 @@ def verify_att_token_signature(att_tk: str) -> Any: return vk.verify_digest(signature, digest, sigdecode=sigdecode_der) -@pytest.mark.esp32c6 @pytest.mark.generic +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_example_tee_attestation(dut: Dut) -> None: # Erase the TEE secure_storage partition dut.serial.erase_partition('secure_storage') diff --git a/examples/security/tee/tee_basic/pytest_tee_basic.py b/examples/security/tee/tee_basic/pytest_tee_basic.py index 5887e5406a..d4f858164f 100644 --- a/examples/security/tee/tee_basic/pytest_tee_basic.py +++ b/examples/security/tee/tee_basic/pytest_tee_basic.py @@ -1,14 +1,15 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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.esp32c6 @pytest.mark.generic +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_example_tee_basic(dut: Dut) -> None: # Logging example binary details binary_files = [ diff --git a/examples/security/tee/tee_secure_ota/pytest_tee_secure_ota.py b/examples/security/tee/tee_secure_ota/pytest_tee_secure_ota.py index 0bf3e7b530..a628d9b390 100644 --- a/examples/security/tee/tee_secure_ota/pytest_tee_secure_ota.py +++ b/examples/security/tee/tee_secure_ota/pytest_tee_secure_ota.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import http.server import multiprocessing @@ -13,16 +13,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: @@ -47,14 +49,12 @@ def start_https_server(ota_image_dir: str, server_ip: str, server_port: int) -> requestHandler = https_request_handler() httpd = http.server.HTTPServer((server_ip, server_port), requestHandler) - httpd.socket = ssl.wrap_socket(httpd.socket, - keyfile=key_file, - certfile=server_file, server_side=True) + httpd.socket = ssl.wrap_socket(httpd.socket, keyfile=key_file, certfile=server_file, server_side=True) httpd.serve_forever() -@pytest.mark.esp32c6 @pytest.mark.wifi_high_traffic +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_examples_tee_secure_ota_example(dut: Dut) -> None: """ This is a positive test case, which downloads complete binary file multiple number of times. diff --git a/examples/security/tee/tee_secure_storage/pytest_tee_secure_storage.py b/examples/security/tee/tee_secure_storage/pytest_tee_secure_storage.py index 42ed68b7d1..3e6c4c34ae 100644 --- a/examples/security/tee/tee_secure_storage/pytest_tee_secure_storage.py +++ b/examples/security/tee/tee_secure_storage/pytest_tee_secure_storage.py @@ -1,11 +1,12 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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.esp32c6 @pytest.mark.generic +@idf_parametrize('target', ['esp32c6'], indirect=['target']) def test_example_tee_secure_storage(dut: Dut) -> None: # Start test dut.expect('TEE Secure Storage', timeout=30) diff --git a/examples/storage/custom_flash_driver/pytest_custom_flash_example.py b/examples/storage/custom_flash_driver/pytest_custom_flash_example.py index 2e37dfe0df..29187efe29 100644 --- a/examples/storage/custom_flash_driver/pytest_custom_flash_example.py +++ b/examples/storage/custom_flash_driver/pytest_custom_flash_example.py @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 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.generic @pytest.mark.parametrize( 'config', @@ -13,6 +13,7 @@ from pytest_embedded import Dut ], indirect=True, ) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_examples_custom_flash_driver(dut: Dut) -> None: dut.expect(r'Using overridden bootloader_flash_unlock', timeout=20) dut.expect(r'Using overridden bootloader_flash_qio, the list number is \d+', timeout=20) diff --git a/examples/storage/emmc/pytest_emmc_example.py b/examples/storage/emmc/pytest_emmc_example.py index 070c5f0e53..15f5b01981 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-2025 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..6c07065f90 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-2025 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..6ae3df4819 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-2025 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..f619a42eb5 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-2025 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..127f21a0a6 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-2025 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 562693141c..6ea2a692c9 100644 --- a/examples/storage/nvs_bootloader/pytest_nvs_bootloader.py +++ b/examples/storage/nvs_bootloader/pytest_nvs_bootloader.py @@ -2,10 +2,11 @@ # 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') @@ -20,16 +21,15 @@ def test_nvs_bootloader_example(dut: Dut) -> None: dut.expect_exact('User application is loaded and running.') -@pytest.mark.esp32c3 @pytest.mark.nvs_encr_hmac @pytest.mark.parametrize('config', ['nvs_enc_hmac'], indirect=True) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) def test_nvs_bootloader_example_nvs_encr_hmac(dut: Dut) -> None: test_nvs_bootloader_example(dut) -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.flash_encryption @pytest.mark.parametrize('config', ['nvs_enc_flash_enc'], indirect=True) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_nvs_bootloader_example_flash_enc(dut: Dut) -> None: test_nvs_bootloader_example(dut) 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..d1da1bad64 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-2025 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..657f8c60a1 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-2025 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..20e301b38f 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-2025 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..69f8796e48 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-2025 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..dd13deed75 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-2025 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..e58587f157 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-2025 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..985d67d936 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-2025 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..f73ff17364 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-2025 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 ebe60cdc73..7bd3c2be76 100644 --- a/examples/storage/perf_benchmark/pytest_perf_benchmark_example.py +++ b/examples/storage/perf_benchmark/pytest_perf_benchmark_example.py @@ -1,19 +1,14 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 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'], reason='not support yet') # TODO: [ESP32C5] IDF-10314 @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 +25,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 +34,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 +48,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 +58,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..7449c9d0ea 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-2025 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..086b6c70b7 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-2025 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..755372fe32 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-2025 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..7f6739a8dc 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-2025 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..3c4f72edd3 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-2025 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..82f7c7ec3c 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-2025 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/app_trace_basic/pytest_app_trace_basic.py b/examples/system/app_trace_basic/pytest_app_trace_basic.py index 47214bc94a..61ca074736 100644 --- a/examples/system/app_trace_basic/pytest_app_trace_basic.py +++ b/examples/system/app_trace_basic/pytest_app_trace_basic.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import time import pexpect import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_jtag import OpenOcd @@ -23,22 +24,18 @@ def apptrace_wait_stop(openocd: OpenOcd, timeout: int = 30) -> None: time.sleep(1) -@pytest.mark.parametrize( - 'embedded_services, no_gdb', +@idf_parametrize('embedded_services', ['esp,idf,jtag'], indirect=['embedded_services']) +@idf_parametrize('no_gdb', ['y'], indirect=['no_gdb']) +@idf_parametrize( + 'openocd_cli_args,port,target,markers', [ - ('esp,idf,jtag', 'y'), + (None, None, 'esp32', (pytest.mark.jtag,)), + ('-f board/esp32s2-kaluga-1.cfg', None, 'esp32s2', (pytest.mark.jtag,)), + ('-f board/esp32c2-ftdi.cfg', None, 'esp32c2', (pytest.mark.jtag,)), + ('-f board/esp32s3-builtin.cfg', '/dev/serial_ports/ttyACM-esp32', 'esp32s3', (pytest.mark.usb_serial_jtag,)), + ('-f board/esp32c3-builtin.cfg', '/dev/serial_ports/ttyACM-esp32', 'esp32c3', (pytest.mark.usb_serial_jtag,)), ], - indirect=True, -) -@pytest.mark.parametrize( - 'port, openocd_cli_args', [ - pytest.param(None, None, marks=[pytest.mark.esp32, pytest.mark.jtag]), - pytest.param(None, '-f board/esp32s2-kaluga-1.cfg', marks=[pytest.mark.esp32s2, pytest.mark.jtag]), - pytest.param(None, '-f board/esp32c2-ftdi.cfg', marks=[pytest.mark.esp32c2, pytest.mark.jtag]), - pytest.param('/dev/serial_ports/ttyACM-esp32', '-f board/esp32s3-builtin.cfg', marks=[pytest.mark.esp32s3, pytest.mark.usb_serial_jtag]), - pytest.param('/dev/serial_ports/ttyACM-esp32', '-f board/esp32c3-builtin.cfg', marks=[pytest.mark.esp32c3, pytest.mark.usb_serial_jtag]), - ], - indirect=True + indirect=['openocd_cli_args', 'port', 'target'], ) def test_examples_app_trace_basic(dut: IdfDut, openocd: OpenOcd) -> None: dut.openocd.write('reset') @@ -68,6 +65,4 @@ def test_examples_app_trace_basic(dut: IdfDut, openocd: OpenOcd) -> None: found = True break if found is not True: - raise RuntimeError( - '"{}" could not be found in {}'.format(log_str, 'apptrace.log') - ) + raise RuntimeError('"{}" could not be found in {}'.format(log_str, 'apptrace.log')) 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..58fedf6005 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-2025 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..d4f564b03a 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-2025 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..c2c2e77e28 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-2025 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 97ecbd7a71..7a22b10c05 100644 --- a/examples/system/deep_sleep/pytest_deep_sleep.py +++ b/examples/system/deep_sleep/pytest_deep_sleep.py @@ -5,6 +5,7 @@ import time import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize CONFIGS = [ pytest.param('esp32_singlecore', marks=[pytest.mark.esp32]), @@ -26,8 +27,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: expect_items = ['Enabling timer wakeup, 20s'] 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..789fbfa6d8 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-2025 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..aad16d0466 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-2025 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..196e6f4f46 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-2025 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..d9b022c45f 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-2025 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..cc6fa7bd41 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-2025 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..8b90b4b6e1 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-2025 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..591b6d4ce3 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-2025 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..84eb66927c 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-2025 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..f4d7745b82 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-2025 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/gcov/pytest_gcov.py b/examples/system/gcov/pytest_gcov.py index b1cc3db772..5ecd772825 100644 --- a/examples/system/gcov/pytest_gcov.py +++ b/examples/system/gcov/pytest_gcov.py @@ -1,14 +1,14 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import os.path import time import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_jtag import OpenOcd -@pytest.mark.esp32 @pytest.mark.jtag @pytest.mark.parametrize( 'embedded_services, no_gdb', @@ -17,6 +17,7 @@ from pytest_embedded_jtag import OpenOcd ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_gcov(dut: IdfDut, openocd: OpenOcd) -> None: # create the generated .gcda folder, otherwise would have error: failed to open file. # normally this folder would be created via `idf.py build`. but in CI the non-related files would not be preserved diff --git a/examples/system/himem/pytest_himem.py b/examples/system/himem/pytest_himem.py index fe37860b01..5fb5127442 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-2025 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..4128c2c896 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-2025 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..f1cbb07ff5 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-2025 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..84946901af 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-2025 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..cd8f4a66e1 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-2025 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 d3a823c1cc..799955573a 100644 --- a/examples/system/ota/advanced_https_ota/pytest_advanced_ota.py +++ b/examples/system/ota/advanced_https_ota/pytest_advanced_ota.py @@ -16,6 +16,7 @@ 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 NVS_PARTITION = 'nvs' @@ -40,10 +41,11 @@ def restart_device_with_random_delay(dut: Dut, min_delay: int = 10, max_delay: i print('Device restarted after random delay.') -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: @@ -77,14 +79,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) @@ -103,7 +116,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) @@ -114,8 +129,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. @@ -152,9 +167,9 @@ def test_examples_protocol_advanced_https_ota_example(dut: Dut) -> None: thread1.terminate() -@pytest.mark.esp32 @pytest.mark.wifi_router @pytest.mark.parametrize('config', ['ota_resumption'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_ota_resumption(dut: Dut) -> None: """ This is a positive test case, which stops the download midway and resumes downloading again. @@ -235,8 +250,8 @@ def test_examples_protocol_advanced_https_ota_example_ota_resumption(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_bin(dut: Dut) -> None: """ Working of OTA if binary file is truncated is validated in this test case. @@ -286,8 +301,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. @@ -337,8 +352,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. @@ -361,7 +376,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 @@ -388,8 +403,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. @@ -412,7 +427,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 @@ -441,8 +456,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. @@ -477,8 +492,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. @@ -508,9 +523,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() @@ -518,7 +538,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 @@ -530,10 +552,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. @@ -587,7 +615,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: @@ -598,9 +628,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. @@ -645,9 +681,15 @@ def test_examples_protocol_advanced_https_ota_example_partial_request(dut: Dut) thread1.terminate() -@pytest.mark.esp32 @pytest.mark.wifi_router -@pytest.mark.parametrize('config', ['ota_resumption_partial_download',], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'ota_resumption_partial_download', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_protocol_advanced_https_ota_example_ota_resumption_partial_download_request(dut: Dut) -> None: """ This is a positive test case, to test OTA workflow with Range HTTP header. @@ -732,11 +774,15 @@ def test_examples_protocol_advanced_https_ota_example_ota_resumption_partial_dow 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. @@ -783,11 +829,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. @@ -835,8 +885,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 @@ -859,7 +909,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..aef61b5341 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-2025 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 a8f1e3c16d..fc4f623aac 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-2025 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.generic, pytest.mark.temp_skip(targets=['esp32c2'], reason='must have 4MB')), + ), + ('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/partitions_ota/pytest_partitions_ota.py b/examples/system/ota/partitions_ota/pytest_partitions_ota.py index f34820aade..acf574faa7 100644 --- a/examples/system/ota/partitions_ota/pytest_partitions_ota.py +++ b/examples/system/ota/partitions_ota/pytest_partitions_ota.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import http.server import multiprocessing @@ -11,6 +11,7 @@ from typing import Optional 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 @@ -19,69 +20,70 @@ 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' +) -@pytest.mark.esp32 # This chip should be >= v3.0 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 @pytest.mark.wifi_high_traffic -@pytest.mark.parametrize('config', [ - 'on_update_no_sb_ecdsa', - 'on_update_no_sb_rsa', - 'virt_sb_v2_and_fe', - 'virt_sb_v2_and_fe_2' -], indirect=True) +@pytest.mark.parametrize( + 'config', + ['on_update_no_sb_ecdsa', 'on_update_no_sb_rsa', 'virt_sb_v2_and_fe', 'virt_sb_v2_and_fe_2'], + indirect=True, +) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) @pytest.mark.timeout(2400) +@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3'], indirect=['target']) def test_examples_partitions_ota(dut: Dut) -> None: print(' - Erase flash') dut.serial.erase_flash() @@ -92,16 +94,12 @@ def test_examples_partitions_ota(dut: Dut) -> None: update_partitions(dut, 'wifi_high_traffic') -@pytest.mark.esp32 -@pytest.mark.esp32c3 @pytest.mark.flash_encryption_wifi_high_traffic @pytest.mark.nightly_run @pytest.mark.timeout(2400) -@pytest.mark.parametrize('config', [ - 'flash_enc_wifi', - 'flash_enc_wifi_2' -], indirect=True) +@pytest.mark.parametrize('config', ['flash_enc_wifi', 'flash_enc_wifi_2'], indirect=True) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_examples_partitions_ota_with_flash_encryption_wifi(dut: Dut) -> None: dut.serial.erase_flash() dut.serial.flash() @@ -146,7 +144,13 @@ def setting_connection(dut: Dut, env_name: Optional[str]) -> Any: return get_host_ip4_by_dest_ip(ip_address) -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: @@ -171,7 +175,7 @@ def start_https_server(ota_image_dir: str, server_ip: str, server_port: int, ser 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_partition_ota.py [cert_dir] image_dir = os.path.dirname(os.path.realpath(__file__)) bin_dir = os.path.join(image_dir, sys.argv[1]) 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 861f2525b6..d48080890b 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-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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: | @@ -366,13 +421,17 @@ def test_examples_protocol_simple_ota_example_tls1_3(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..600c3a0049 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-2025 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..9b533d8058 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-2025 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..0a1bfc909d 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-2025 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..c0811806ab 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-2025 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..82ccd5fd3f 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-2025 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/pytest_sysview_tracing.py b/examples/system/sysview_tracing/pytest_sysview_tracing.py index 6af3e02c71..570d941039 100644 --- a/examples/system/sysview_tracing/pytest_sysview_tracing.py +++ b/examples/system/sysview_tracing/pytest_sysview_tracing.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import re import time @@ -6,9 +6,9 @@ import time import pexpect.fdpexpect import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.jtag @pytest.mark.parametrize( 'embedded_services', @@ -17,6 +17,7 @@ from pytest_embedded_idf import IdfDut ], indirect=True, ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_sysview_tracing(dut: IdfDut) -> None: def dut_expect_task_event() -> None: dut.expect(re.compile(rb'example: Task\[0x3[0-9A-Fa-f]+\]: received event \d+'), timeout=30) 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 c6147f52d5..79871369d5 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 @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import os.path import time @@ -6,12 +6,13 @@ import time import pexpect.fdpexpect import pytest from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.jtag @pytest.mark.parametrize('config', ['app_trace_jtag'], indirect=True) @pytest.mark.parametrize('embedded_services', ['esp,idf,jtag'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_examples_sysview_tracing_heap_log(idf_path: str, dut: IdfDut) -> None: # Construct trace log paths trace_log = [ @@ -52,5 +53,6 @@ def test_examples_sysview_tracing_heap_log(idf_path: str, dut: IdfDut) -> None: with open(dut.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..73d9699099 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-2025 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..b9089f97eb 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-2025 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..8b3e00f60f 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-2025 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..8fabae0eb9 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-2025 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..622198c941 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-2025 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..cc921eb64d 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-2025 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..9f6c725a85 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-2025 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..86eb9eccde 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-2025 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..dd2efea254 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-2025 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..1360c14d97 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-2025 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..e63392dac7 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-2025 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 4df50381ba..bc19c5c85e 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-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 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.wifi_two_dut @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.wifi_two_dut @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/getting_started/station/pytest_wifi_station.py b/examples/wifi/getting_started/station/pytest_wifi_station.py index b63ba12355..5a93da1631 100644 --- a/examples/wifi/getting_started/station/pytest_wifi_station.py +++ b/examples/wifi/getting_started/station/pytest_wifi_station.py @@ -6,8 +6,9 @@ from typing import Tuple import pytest from pytest_embedded import Dut - +from pytest_embedded_idf.utils import idf_parametrize # diff of esp32s2/esp32s3 ~45K, others ~50K + DIFF_THRESHOLD = { 'esp32s2': 40 * 1000, 'esp32s3': 40 * 1000, @@ -15,19 +16,12 @@ DIFF_THRESHOLD = { } -@pytest.mark.esp32 -@pytest.mark.esp32c2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -@pytest.mark.esp32c6 -@pytest.mark.esp32c61 @pytest.mark.wifi_two_dut -@pytest.mark.parametrize( - 'count, config, skip_autoflash', [ - (2, 'default|enable_softap', 'y') - ], indirect=True +@pytest.mark.parametrize('count, config, skip_autoflash', [(2, 'default|enable_softap', 'y')], indirect=True) +@idf_parametrize( + 'target', + ['esp32', 'esp32c2', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'], + indirect=['target'], ) def test_wifi_sdkconfig_disable_softap_save_binary_size( dut: Tuple[Dut, Dut], diff --git a/examples/wifi/iperf/pytest_iperf.py b/examples/wifi/iperf/pytest_iperf.py index 334a41d9c6..5858a4af22 100644 --- a/examples/wifi/iperf/pytest_iperf.py +++ b/examples/wifi/iperf/pytest_iperf.py @@ -1,5 +1,7 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 +from pytest_embedded_idf.utils import idf_parametrize + """ Test case for iperf example. @@ -26,19 +28,17 @@ 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 6f41921611..6b87e9a90e 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-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 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,17 +59,20 @@ 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) diff --git a/examples/zigbee/light_sample/pytest_esp_zigbee.py b/examples/zigbee/light_sample/pytest_esp_zigbee.py index 0d24a7f636..868fd0d2fc 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-2025 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..b04713fc78 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-2025 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..d4eb999dbd 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-2025 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..e57717bd24 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-2025 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..fc73bb074e 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-2025 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 99d71ee545..ff194f265d 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-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 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,14 +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.esp32c61 @pytest.mark.wifi_two_dut @pytest.mark.parametrize('count', [2], indirect=True) +@idf_parametrize('target', ['esp32c3', 'esp32c6', 'esp32c5', 'esp32s2', 'esp32s3', 'esp32c61'], indirect=['target']) def test_phy_tsens_coexist(dut: Tuple[Dut, Dut]) -> None: for _dut in dut: _dut.expect('esp>') @@ -167,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.wifi_two_dut @pytest.mark.xtal_26mhz @pytest.mark.parametrize( @@ -177,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..70da7ebfd1 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-2025 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 b2df800002..4eb25d1f1e 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,4 +1,4 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import contextlib import difflib @@ -22,13 +22,13 @@ 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, config, log_details=False): # type: (MqttPublisher, dict, bool) -> None self.log_details = log_details self.config = config @@ -40,7 +40,9 @@ class MqttPublisher(mqtt.Client): self.event_client_subscribed = Event() self.event_client_got_all = Event() transport = 'websockets' if self.config['transport'] in ['ws', 'wss'] else 'tcp' - client_id = 'MqttTestRunner' + ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(5)) + client_id = 'MqttTestRunner' + ''.join( + random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(5) + ) super().__init__(client_id, userdata=0, transport=transport) def print_details(self, text): # type: (str) -> None @@ -53,7 +55,7 @@ class MqttPublisher(mqtt.Client): logging.info(f'Subscribed to {self.config["subscribe_topic"]} successfully with QoS: {granted_qos}') self.event_client_subscribed.set() - 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: @@ -67,8 +69,10 @@ 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.config["pattern"])}') logging.info(f'Pattern: {self.config["pattern"]}') logging.info(f'First: {payload[:DEFAULT_MSG_SIZE]}') @@ -107,9 +111,10 @@ class MqttPublisher(mqtt.Client): self.loop_stop() -def get_configurations(dut: Dut, test_case: Any) -> Dict[str,Any]: +def get_configurations(dut: Dut, test_case: Any) -> Dict[str, Any]: publish_cfg = {} try: + @no_type_check def get_config_from_dut(dut, config_option): # logging.info('Option:', config_option, dut.app.sdkconfig.get(config_option)) @@ -117,11 +122,18 @@ def get_configurations(dut: Dut, test_case: Any) -> Dict[str,Any]: if value is None: return None, None return value.group(1), int(value.group(2)) + # Get publish test configuration - publish_cfg['broker_host_ssl'], publish_cfg['broker_port_ssl'] = get_config_from_dut(dut, 'EXAMPLE_BROKER_SSL_URI') - publish_cfg['broker_host_tcp'], publish_cfg['broker_port_tcp'] = get_config_from_dut(dut, 'EXAMPLE_BROKER_TCP_URI') + publish_cfg['broker_host_ssl'], publish_cfg['broker_port_ssl'] = get_config_from_dut( + dut, 'EXAMPLE_BROKER_SSL_URI' + ) + publish_cfg['broker_host_tcp'], publish_cfg['broker_port_tcp'] = get_config_from_dut( + dut, 'EXAMPLE_BROKER_TCP_URI' + ) publish_cfg['broker_host_ws'], publish_cfg['broker_port_ws'] = get_config_from_dut(dut, 'EXAMPLE_BROKER_WS_URI') - publish_cfg['broker_host_wss'], publish_cfg['broker_port_wss'] = get_config_from_dut(dut, 'EXAMPLE_BROKER_WSS_URI') + publish_cfg['broker_host_wss'], publish_cfg['broker_port_wss'] = get_config_from_dut( + dut, 'EXAMPLE_BROKER_WSS_URI' + ) except Exception: logging.info('ENV_TEST_FAILURE: Some mandatory PUBLISH test case not found in sdkconfig') @@ -133,9 +145,13 @@ def get_configurations(dut: Dut, test_case: Any) -> Dict[str,Any]: publish_cfg['qos'] = qos publish_cfg['enqueue'] = enqueue publish_cfg['transport'] = transport - publish_cfg['pattern'] = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(DEFAULT_MSG_SIZE)) + publish_cfg['pattern'] = ''.join( + random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(DEFAULT_MSG_SIZE) + ) publish_cfg['test_timeout'] = get_timeout(test_case) - unique_topic = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(DEFAULT_MSG_SIZE)) + unique_topic = ''.join( + random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(DEFAULT_MSG_SIZE) + ) publish_cfg['subscribe_topic'] = 'test/subscribe_to/' + unique_topic publish_cfg['publish_topic'] = 'test/subscribe_to/' + unique_topic logging.info(f'configuration: {publish_cfg}') @@ -143,7 +159,7 @@ def get_configurations(dut: Dut, test_case: Any) -> Dict[str,Any]: @contextlib.contextmanager -def connected_and_subscribed(dut:Dut) -> Any: +def connected_and_subscribed(dut: Dut) -> Any: dut.write('start') dut.expect(re.compile(rb'MQTT_EVENT_SUBSCRIBED'), timeout=60) yield @@ -155,16 +171,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 = [{'msg_len':0, 'nr_of_msgs':5}, # zero-sized messages - {'msg_len':2, 'nr_of_msgs':5}, # short messages - {'msg_len':200, 'nr_of_msgs':3}, # long messages - ] + if not scenarios: # No message sizes present in the env - set defaults + scenarios = [ + {'msg_len': 0, 'nr_of_msgs': 5}, # zero-sized messages + {'msg_len': 2, 'nr_of_msgs': 5}, # short messages + {'msg_len': 200, 'nr_of_msgs': 3}, # long messages + ] return scenarios @@ -181,17 +198,23 @@ def get_timeout(test_case: Any) -> int: def run_publish_test_case(dut: Dut, config: Any) -> None: - logging.info(f'Starting Publish test: transport:{config["transport"]}, qos:{config["qos"]},' - f'nr_of_msgs:{config["scenario"]["nr_of_msgs"]},' - f' msg_size:{config["scenario"]["msg_len"] * DEFAULT_MSG_SIZE}, enqueue:{config["enqueue"]}') - dut.write(f'publish_setup {config["transport"]} {config["publish_topic"]} {config["subscribe_topic"]} {config["pattern"]} {config["scenario"]["msg_len"]}') + logging.info( + f'Starting Publish test: transport:{config["transport"]}, qos:{config["qos"]},' + f'nr_of_msgs:{config["scenario"]["nr_of_msgs"]},' + f' msg_size:{config["scenario"]["msg_len"] * DEFAULT_MSG_SIZE}, enqueue:{config["enqueue"]}' + ) + dut.write( + f'publish_setup {config["transport"]} {config["publish_topic"]} {config["subscribe_topic"]} {config["pattern"]} {config["scenario"]["msg_len"]}' + ) with MqttPublisher(config) as publisher, connected_and_subscribed(dut): assert publisher.event_client_subscribed.wait(timeout=config['test_timeout']), 'Runner failed to subscribe' msgs_published: List[mqtt.MQTTMessageInfo] = [] dut.write(f'publish {config["scenario"]["nr_of_msgs"]} {config["qos"]} {config["enqueue"]}') - assert publisher.event_client_got_all.wait(timeout=config['test_timeout']), (f'Not all data received from ESP32: {config["transport"]} ' - f'qos={config["qos"]} received: {publisher.received} ' - f'expected: {config["scenario"]["nr_of_msgs"]}') + assert publisher.event_client_got_all.wait(timeout=config['test_timeout']), ( + f'Not all data received from ESP32: {config["transport"]} ' + f'qos={config["qos"]} received: {publisher.received} ' + f'expected: {config["scenario"]["nr_of_msgs"]}' + ) logging.info(' - all data received from ESP32') payload = config['pattern'] * config['scenario']['msg_len'] for _ in range(config['scenario']['nr_of_msgs']): @@ -214,15 +237,17 @@ def run_publish_test_case(dut: Dut, config: Any) -> None: logging.info('ESP32 received all data from runner') -stress_scenarios = [{'msg_len':20, 'nr_of_msgs':30}] # many medium sized +stress_scenarios = [{'msg_len': 20, 'nr_of_msgs': 30}] # many medium sized transport_cases = ['tcp', 'ws', 'wss', 'ssl'] qos_cases = [0, 1, 2] enqueue_cases = [0, 1] local_broker_supported_transports = ['tcp'] -local_broker_scenarios = [{'msg_len':0, 'nr_of_msgs':5}, # zero-sized messages - {'msg_len':5, 'nr_of_msgs':20}, # short messages - {'msg_len':500, 'nr_of_msgs':10}, # long messages - {'msg_len':20, 'nr_of_msgs':20}] # many medium sized +local_broker_scenarios = [ + {'msg_len': 0, 'nr_of_msgs': 5}, # zero-sized messages + {'msg_len': 5, 'nr_of_msgs': 20}, # short messages + {'msg_len': 500, 'nr_of_msgs': 10}, # long messages + {'msg_len': 20, 'nr_of_msgs': 20}, +] # many medium sized def make_cases(transport: Any, scenarios: List[Dict[str, int]]) -> List[Tuple[str, int, int, Dict[str, int]]]: @@ -233,10 +258,10 @@ test_cases = make_cases(transport_cases, get_scenarios()) stress_test_cases = make_cases(transport_cases, stress_scenarios) -@pytest.mark.esp32 @pytest.mark.ethernet @pytest.mark.parametrize('test_case', test_cases) @pytest.mark.parametrize('config', ['default'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_mqtt_publish(dut: Dut, test_case: Any) -> None: publish_cfg = get_configurations(dut, test_case) dut.expect(re.compile(rb'mqtt>'), timeout=30) @@ -244,11 +269,11 @@ def test_mqtt_publish(dut: Dut, test_case: Any) -> None: run_publish_test_case(dut, publish_cfg) -@pytest.mark.esp32 @pytest.mark.ethernet_stress @pytest.mark.nightly_run @pytest.mark.parametrize('test_case', stress_test_cases) @pytest.mark.parametrize('config', ['default'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_mqtt_publish_stress(dut: Dut, test_case: Any) -> None: publish_cfg = get_configurations(dut, test_case) dut.expect(re.compile(rb'mqtt>'), timeout=30) @@ -256,10 +281,10 @@ def test_mqtt_publish_stress(dut: Dut, test_case: Any) -> None: run_publish_test_case(dut, publish_cfg) -@pytest.mark.esp32 @pytest.mark.ethernet @pytest.mark.parametrize('test_case', make_cases(local_broker_supported_transports, local_broker_scenarios)) @pytest.mark.parametrize('config', ['local_broker'], indirect=True) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_mqtt_publish_local(dut: Dut, test_case: Any) -> None: if test_case[0] not in local_broker_supported_transports: pytest.skip(f'Skipping transport: {test_case[0]}...') 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..1ade287187 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-2025 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] @@ -53,12 +55,12 @@ def corrupt_sig_block(sig_block, seed=0, corrupt_sig=True, corrupt_crc=False): new_byte = sig[corrupt_idx] ^ corrupt_delta - new_sig = sig[0:corrupt_idx] + bytes([new_byte]) + sig[corrupt_idx + 1:] + new_sig = sig[0:corrupt_idx] + bytes([new_byte]) + sig[corrupt_idx + 1 :] 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..9a73e10e26 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-2025 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 9d8d9a6951..563554ab30 100644 --- a/tools/test_apps/storage/fatfsgen/pytest_fatfsgen_example.py +++ b/tools/test_apps/storage/fatfsgen/pytest_fatfsgen_example.py @@ -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 - a bit overkill, but better than failing tests timeout = 60 @@ -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..c5fc758638 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-2025 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..7567611604 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-2025 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..f70b715e35 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-2025 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..cccfdbedeb 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-2025 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/pytest_gdb.py b/tools/test_apps/system/gdb/pytest_gdb.py index f43bb74556..18b4ac573c 100644 --- a/tools/test_apps/system/gdb/pytest_gdb.py +++ b/tools/test_apps/system/gdb/pytest_gdb.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import json import logging @@ -12,14 +12,13 @@ from typing import Optional import pexpect import pytest from pytest_embedded_idf import IdfDut - +from pytest_embedded_idf.utils import idf_parametrize MAX_RETRIES = 3 RETRY_DELAY = 3 # seconds def run_openocd(dut: IdfDut) -> Optional[Popen]: - desc_path = os.path.join(dut.app.binary_path, 'project_description.json') try: with open(desc_path, 'r') as f: @@ -79,14 +78,17 @@ def _test_idf_gdb(dut: IdfDut) -> None: assert ocd try: - with open(os.path.join(dut.logdir, 'gdb.txt'), 'w') as gdb_log, \ - pexpect.spawn(f'idf.py -B {dut.app.binary_path} gdb --batch', - timeout=60, - logfile=gdb_log, - encoding='utf-8', - codec_errors='ignore') as p: + with open(os.path.join(dut.logdir, 'gdb.txt'), 'w') as gdb_log, pexpect.spawn( + f'idf.py -B {dut.app.binary_path} gdb --batch', + timeout=60, + logfile=gdb_log, + encoding='utf-8', + codec_errors='ignore', + ) as p: p.expect(re.compile(r'add symbol table from file.*bootloader.elf')) - p.expect(re.compile(r'add symbol table from file.*rom.elf')) # if fail here: add target support here https://github.com/espressif/esp-rom-elfs + p.expect( + re.compile(r'add symbol table from file.*rom.elf') + ) # if fail here: add target support here https://github.com/espressif/esp-rom-elfs p.expect_exact('hit Temporary breakpoint 1, app_main ()') finally: # Check if the process is still running @@ -95,15 +97,13 @@ def _test_idf_gdb(dut: IdfDut) -> None: ocd.kill() -@pytest.mark.esp32 -@pytest.mark.esp32s2 @pytest.mark.jtag +@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target']) def test_idf_gdb(dut: IdfDut) -> None: _test_idf_gdb(dut) -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.usb_serial_jtag +@idf_parametrize('target', ['esp32c6', 'esp32h2'], indirect=['target']) def test_idf_gdb_usj(dut: IdfDut) -> None: _test_idf_gdb(dut) 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..c28d96a1f5 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-2025 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_gdbstub_runtime.py b/tools/test_apps/system/gdbstub_runtime/pytest_gdbstub_runtime.py index 2f994fedb9..afa68d1b53 100644 --- a/tools/test_apps/system/gdbstub_runtime/pytest_gdbstub_runtime.py +++ b/tools/test_apps/system/gdbstub_runtime/pytest_gdbstub_runtime.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os import os.path as path @@ -7,6 +7,7 @@ from typing import Any from typing import Dict 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 @@ -38,8 +39,8 @@ def run_and_break(dut: PanicTestDut, cmd: str) -> Dict[Any, Any]: return payload -@pytest.mark.esp32p4 @pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_hwloop_jump(dut: PanicTestDut) -> None: start_gdb(dut) @@ -97,8 +98,8 @@ def test_hwloop_jump(dut: PanicTestDut) -> None: assert payload['stopped-threads'] == 'all' -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_gdbstub_runtime(dut: PanicTestDut) -> None: start_gdb(dut) @@ -131,7 +132,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' @@ -198,11 +201,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: start_gdb(dut) diff --git a/tools/test_apps/system/longjmp_test/pytest_longjmp.py b/tools/test_apps/system/longjmp_test/pytest_longjmp.py index 5499509c49..84f81dd724 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-2025 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_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..c639fb770e 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-2025 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 d4cb1104af..3ccaf74aca 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-2025 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') @@ -30,10 +30,9 @@ def test_app_mmu_page_size_32k_and_bootloader_mmu_page_size_64k(dut: Dut, app_do dut.expect('Partition test done') -@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 331dcea0be..31b9de6090 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') @@ -182,13 +188,84 @@ 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', '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'), + ('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 @@ -202,29 +279,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: @@ -240,18 +325,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') @@ -267,24 +359,92 @@ 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', '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'), + ('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) @@ -304,11 +464,82 @@ 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', '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'), + ('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) @@ -328,8 +559,81 @@ 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', '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'), + ('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 +660,84 @@ 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', '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'), + ('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 +757,82 @@ 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', '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'), + ('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 +857,82 @@ 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', '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'), + ('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 +966,239 @@ 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', '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'), + ('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', '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'), + ('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', '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'), + ('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 +1214,86 @@ 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, 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', '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'), + ('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_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' @@ -508,17 +1313,89 @@ 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), - expected_coredump=[coredump_pattern] + '__ubsan_handle_out_of_bounds', + ] + + get_default_backtrace(test_func_name), + expected_coredump=[coredump_pattern], ) -@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', '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'), + ('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) @@ -535,17 +1412,86 @@ 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', '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'), + ('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.*$' @@ -561,20 +1507,87 @@ 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', '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'), + ('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) @@ -591,12 +1604,8 @@ 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], ) @@ -614,18 +1623,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.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: @@ -642,8 +1649,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) @@ -655,10 +1662,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) @@ -670,8 +1675,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) @@ -689,10 +1694,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) @@ -723,7 +1726,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 = [ @@ -736,7 +1739,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 = [ @@ -748,7 +1751,7 @@ 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_INVALID_REGION_PROTECTION_USING_PMA = [ @@ -756,12 +1759,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') @@ -769,9 +1773,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') @@ -781,8 +1786,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) @@ -801,8 +1819,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) @@ -826,8 +1857,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) @@ -852,9 +1896,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) @@ -879,9 +1936,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) @@ -899,9 +1971,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) @@ -917,17 +2004,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') @@ -947,9 +2059,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) @@ -973,8 +2098,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') @@ -984,8 +2110,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') @@ -995,8 +2122,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') @@ -1004,8 +2141,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') @@ -1013,8 +2160,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') @@ -1022,8 +2179,18 @@ def test_drom_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> N 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_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Store access fault') @@ -1031,8 +2198,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') @@ -1040,9 +2217,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) @@ -1050,7 +2227,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})') @@ -1066,25 +2243,37 @@ def test_hw_stack_guard_cpu(dut: PanicTestDut, cpu: int) -> None: assert end_addr > start_addr -@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: @@ -1096,8 +2285,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.*$' @@ -1144,19 +2334,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: @@ -1174,24 +2367,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.parametrize('config', CONFIGS_BACKTRACE, indirect=True) @pytest.mark.generic +@idf_parametrize('config', ['framepointer'], indirect=['config']) +@idf_parametrize('target', ['esp32c3', 'esp32p4'], indirect=['target']) def test_panic_print_backtrace(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' @@ -1201,9 +2392,4 @@ def test_panic_print_backtrace(dut: PanicTestDut, config: str, test_func_name: s dut.expect_none(['Guru Meditation', 'Re-entered core dump']) coredump_pattern = re.compile(PANIC_ABORT_PREFIX + regex_pattern.decode('utf-8')) - common_test( - dut, - config, - expected_backtrace=None, - expected_coredump=[coredump_pattern] - ) + common_test(dut, config, expected_backtrace=None, expected_coredump=[coredump_pattern]) 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..c01afe1777 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-2025 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..a03a14f070 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-2025 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..3a3dea1905 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-2025 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..2f6e7d2fc9 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-2025 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 3e6ba5b11a..f30e7c7fee 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-2025 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') -@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')