ci: apply common-scripts CI refactor

Squashes these original commits for release/v5.4 backport traceability:
- 9b289dc5ad6 ci: apply idf-ci 1.x
- 381df980d57 ci: remove pip-cache and other unused jobs
- 32375a0a15e ci: apply common-scripts CI refactor
This commit is contained in:
Fu Hanxi
2026-08-17 14:13:15 +02:00
parent 78acf95a61
commit b47f9850c7
156 changed files with 2376 additions and 7642 deletions

View File

@@ -11,7 +11,7 @@ https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/esp-ble-m
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example implements Bluetooth Mesh node that supports On/Off and Level models.
It has suport for both Advertising Bearer and GATT Bearer.
It has support for both Advertising Bearer and GATT Bearer.
For more information on NimBLE MESH, please visit [NimBLE_MESH](https://mynewt.apache.org/latest/network/mesh/index.html#bluetooth-mesh).

View File

@@ -1,22 +1,24 @@
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import os.path
from pathlib import Path
from typing import Tuple
import pexpect
import pytest
from pytest_embedded_idf.dut import IdfDut
from pytest_embedded_idf.utils import idf_parametrize
CUR_DIR = Path(__file__).parent.resolve()
# Case 1: BLE power save test
@pytest.mark.two_duts
@pytest.mark.parametrize(
'count, app_path',
[
(
2,
f'{os.path.join(os.path.dirname(__file__), "power_save")}|{os.path.join(os.path.dirname(__file__), "blecent")}',
f'{str(CUR_DIR / "power_save")}|{str(CUR_DIR / "blecent")}',
),
],
indirect=True,
@@ -47,7 +49,7 @@ def test_power_save_conn(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None:
(
'esp32c2_xtal26m',
2,
f'{os.path.join(os.path.dirname(__file__), "power_save")}|{os.path.join(os.path.dirname(__file__), "blecent")}',
f'{str(CUR_DIR / "power_save")}|{str(CUR_DIR / "blecent")}',
'74880',
),
],
@@ -71,21 +73,21 @@ def test_power_save_conn_esp32c2_26mhz(dut: Tuple[IdfDut, IdfDut]) -> None:
# Case 2: BLE power save test for ESP32C2ECO4
@pytest.mark.two_duts
@pytest.mark.xtal_26mhz
@pytest.mark.esp32c2eco4
@pytest.mark.esp32c2_rev2
@pytest.mark.parametrize(
'config, count, target, app_path, baud',
[
(
'esp32c2eco4_xtal26m',
'esp32c2_rev2_xtal26m',
2,
'esp32c2',
f'{os.path.join(os.path.dirname(__file__), "power_save")}|{os.path.join(os.path.dirname(__file__), "blecent")}',
f'{str(CUR_DIR / "power_save")}|{str(CUR_DIR / "blecent")}',
'74880',
),
],
indirect=True,
)
def test_power_save_conn_esp32c2eco4(dut: Tuple[IdfDut, IdfDut]) -> None:
def test_power_save_conn_esp32c2_rev2(dut: Tuple[IdfDut, IdfDut]) -> None:
peripheral = dut[0]
central = dut[1]
@@ -101,20 +103,20 @@ def test_power_save_conn_esp32c2eco4(dut: Tuple[IdfDut, IdfDut]) -> None:
# Case 2: BLE power save test for ESP32C3ECO7
@pytest.mark.two_duts
@pytest.mark.esp32c3eco7
@pytest.mark.esp32c3_rev1
@pytest.mark.parametrize(
'config, count, target, app_path',
[
(
'esp32c3eco7',
'esp32c3_rev1',
2,
'esp32c3',
f'{os.path.join(os.path.dirname(__file__), "power_save")}|{os.path.join(os.path.dirname(__file__), "blecent")}',
f'{str(CUR_DIR / "power_save")}|{str(CUR_DIR / "blecent")}',
),
],
indirect=True,
)
def test_power_save_conn_esp32c3eco7(dut: Tuple[IdfDut, IdfDut]) -> None:
def test_power_save_conn_esp32c3_rev1(dut: Tuple[IdfDut, IdfDut]) -> None:
peripheral = dut[0]
central = dut[1]

View File

@@ -5,7 +5,6 @@ from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_qemu.dut import QemuDut
@pytest.mark.host_test
@pytest.mark.qemu
@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target'])
def test_pytest_host(dut: QemuDut) -> None:

View File

@@ -1,8 +1,10 @@
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
from __future__ import annotations
import hashlib
import logging
from typing import Callable
from collections.abc import Callable
import pytest
from pytest_embedded_idf.dut import IdfDut
@@ -18,14 +20,12 @@ def test_hello_world(dut: IdfDut, log_minimum_free_heap_size: Callable[..., None
log_minimum_free_heap_size()
@pytest.mark.host_test
@idf_parametrize('target', ['linux'], indirect=['target'])
def test_hello_world_linux(dut: IdfDut) -> None:
dut.expect('Hello world!')
@pytest.mark.host_test
@pytest.mark.macos_shell
@pytest.mark.macos
@idf_parametrize('target', ['linux'], indirect=['target'])
def test_hello_world_macos(dut: IdfDut) -> None:
dut.expect('Hello world!')
@@ -45,7 +45,6 @@ def verify_elf_sha256_embedding(app: QemuApp, sha256_reported: str) -> None:
raise ValueError('ELF file SHA256 mismatch')
@pytest.mark.host_test
@pytest.mark.qemu
@idf_parametrize('target', ['esp32'], indirect=['target'])
def test_hello_world_host(app: QemuApp, dut: QemuDut) -> None:

View File

@@ -1,5 +1,7 @@
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
from __future__ import annotations
import base64
import io
import ipaddress
@@ -9,14 +11,10 @@ import re
import socket
import subprocess
import time
from collections.abc import Generator
from concurrent.futures import Future
from concurrent.futures import ThreadPoolExecutor
from typing import Generator
from typing import List
from typing import Match
from typing import Optional
from typing import Tuple
from typing import Union
from re import Match
import netifaces
import paramiko # type: ignore
@@ -25,9 +23,12 @@ from common_test_methods import get_host_ip_by_interface
from netmiko import ConnectHandler
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
# Testbed configuration
ETHVM_ENDNODE_USER = 'ci.ethvm'
ETHERNET_TEST_USER = os.getenv('ETHERNET_TEST_USER')
ETHERNET_TEST_PASSWORD = os.getenv('ETHERNET_TEST_PASSWORD')
BR_PORTS_NUM = 2
IPERF_BW_LIM = 6
@@ -36,7 +37,7 @@ MIN_TCP_THROUGHPUT = 4
class EndnodeSsh:
def __init__(self, host_ip: str, usr: str, passwd: Optional[str] = None):
def __init__(self, host_ip: str, usr: str, passwd: str | None = None):
key_string = os.getenv('CI_ETHVM_KEY')
key = None
if key_string:
@@ -93,7 +94,7 @@ class SwitchSsh:
}
self.ssh_client = ConnectHandler(**edgeSwitch)
def exec_cmd(self, cmd: Union[str, List[str]]) -> str:
def exec_cmd(self, cmd: str | list[str]) -> str:
if self.type == self.EDGE_SWITCH_5XP:
_, stdout, stderr = self.ssh_client.exec_command(cmd)
@@ -192,7 +193,17 @@ def run_iperf(
if ipaddress.ip_address(server_ip).is_multicast:
# Configure Multicast Server
server_proc = subprocess.Popen(
['iperf', '-u', '-s', '-i', '1', '-t', str(interval), '-B', f'{server_ip}%{server_if}'],
[
'iperf',
'-u',
'-s',
'-i',
'1',
'-t',
str(interval),
'-B',
f'{server_ip}%{server_if}',
],
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
@@ -284,14 +295,14 @@ def send_brcast_msg_endnode_to_host(endnode: EndnodeSsh, host_brcast_ip: str, po
return nc_host_out
def get_legacy_host_name_match() -> Optional[Match[str]]:
def get_legacy_host_name_match() -> Match[str] | None:
host_name = socket.gethostname()
regex = r'ethVM-(\d+)-(\d+)'
host_name_match = re.search(regex, host_name, re.DOTALL)
return host_name_match
def get_host_info() -> Tuple[int, int]:
def get_host_info() -> tuple[int, int]:
# Get switch configuration info from the hostname (legacy runners)
sw_info = get_legacy_host_name_match()
if sw_info is not None:
@@ -635,5 +646,10 @@ def setup_test_environment() -> Generator[None, None, None]:
indirect=True,
)
@idf_parametrize('target', ['esp32'], indirect=['target'])
@pytest.mark.parametrize(
'dev_user, dev_password',
[(ETHERNET_TEST_USER, ETHERNET_TEST_PASSWORD)],
indirect=True,
)
def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None:
eth_bridge_test(dut, dev_user, dev_password)

View File

@@ -8,16 +8,19 @@ import random
import re
import secrets
import subprocess
import sys
import threading
import time
from typing import Generator
from typing import Optional
from typing import Tuple
import ot_ci_function as ocf
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
import ot_ci_function as ocf # noqa: E402
import pexpect
import pytest
from pytest_embedded_idf.dut import IdfDut
# This file contains the test scripts for Thread:
# Case 1: Thread network formation and attaching
# A Thread Border Router forms a Thread network, Thread devices attach to it, then test ping

View File

@@ -4,11 +4,6 @@ import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
CONFIGS = [
pytest.param('default', marks=[pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32p4]),
pytest.param('esp32p4_psram', marks=[pytest.mark.esp32p4]),
]
@pytest.mark.usb_host_flash_disk
@pytest.mark.temp_skip_ci(targets=['esp32s2'], reason='lack of runners with usb_host_flash_disk tag')

View File

@@ -18,7 +18,7 @@ def test_examples_protocol_esp_http_client(dut: Dut) -> None:
"""
binary_file = os.path.join(dut.app.binary_path, 'esp_http_client_example.bin')
bin_size = os.path.getsize(binary_file)
logging.info('esp_http_client_bin_size : {}KB'.format(bin_size // 1024))
logging.info(f'esp_http_client_bin_size : {bin_size // 1024}KB')
# start test
dut.expect('Connected to AP, begin http example', timeout=30)
dut.expect(r'HTTP GET Status = 200, content_length = (\d)')
@@ -70,7 +70,7 @@ def test_examples_protocol_esp_http_client_dynamic_buffer(dut: Dut) -> None:
# check and log bin size
binary_file = os.path.join(dut.app.binary_path, 'esp_http_client_example.bin')
bin_size = os.path.getsize(binary_file)
logging.info('esp_http_client_bin_size : {}KB'.format(bin_size // 1024))
logging.info(f'esp_http_client_bin_size : {bin_size // 1024}KB')
dut.expect('Connected to AP, begin http example', timeout=30)
dut.expect(r'HTTP GET Status = 200, content_length = (\d)')
@@ -106,7 +106,6 @@ def test_examples_protocol_esp_http_client_dynamic_buffer(dut: Dut) -> None:
dut.expect('Finish http example')
@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')

View File

@@ -20,13 +20,13 @@ def test_examples_protocol_https_x509_bundle(dut: Dut) -> None:
# check and log bin size
binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin')
bin_size = os.path.getsize(binary_file)
logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024))
logging.info(f'https_x509_bundle_bin_size : {bin_size // 1024}KB')
dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)
# start test
num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode())
for _ in range(num_URLS):
dut.expect(r'Connection established to ([\s\S]*)', timeout=30)
dut.expect('Completed {} connections'.format(num_URLS), timeout=60)
dut.expect(f'Completed {num_URLS} connections', timeout=60)
@pytest.mark.ethernet
@@ -43,16 +43,15 @@ def test_examples_protocol_https_x509_bundle_dynamic_buffer(dut: Dut) -> None:
# check and log bin size
binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin')
bin_size = os.path.getsize(binary_file)
logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024))
logging.info(f'https_x509_bundle_bin_size : {bin_size // 1024}KB')
dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)
# start test
num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode())
dut.expect(r'Connection established to ([\s\S]*)', timeout=30)
dut.expect('Completed {} connections'.format(num_URLS), timeout=60)
dut.expect(f'Completed {num_URLS} connections', timeout=60)
@pytest.mark.qemu
@pytest.mark.host_test
@pytest.mark.parametrize(
'config',
[
@@ -61,14 +60,16 @@ def test_examples_protocol_https_x509_bundle_dynamic_buffer(dut: Dut) -> None:
indirect=True,
)
@idf_parametrize('target', ['esp32'], indirect=['target'])
def test_examples_protocol_https_x509_bundle_default_crt_bundle_stress_test(dut: Dut) -> None:
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')
bin_size = os.path.getsize(binary_file)
logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024))
logging.info(f'https_x509_bundle_bin_size : {bin_size // 1024}KB')
dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)
# start test
num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode())
for _ in range(num_URLS):
dut.expect(r'Connection established to ([\s\S]*)', timeout=60)
dut.expect('Completed {} connections'.format(num_URLS), timeout=180)
dut.expect(f'Completed {num_URLS} connections', timeout=180)

View File

@@ -2,8 +2,8 @@
# BSD Socket API Examples
This directory contains simple examples demonstrating BSD Socket API.
Each example, contains README.md file with mode detailed informations about that particular example.
For more general informations about all examples, see the README.md file in the upper level 'examples' directory.
Each example, contains README.md file with mode detailed information about that particular example.
For more general information about all examples, see the README.md file in the upper level 'examples' directory.
Examples:
* UDP Client - The application creates UDP socket and sends message to the predefined port and IP address. After the server's reply, the application prints received reply as ASCII text, waits for 2 seconds and sends another message.
@@ -56,7 +56,7 @@ They can also be run locally. Ref: [ESP-IDF Tests with Pytest Guide](https://doc
Example:
```bash
$ cd $IDF_PATH
$ bash install.sh --enable-pytest
$ bash install.sh --enable-ci
$ . ./export.sh
$ cd examples/protocols/sockets/tcp_client
$ python $IDF_PATH/tools/ci/ci_build_apps.py . --target esp32 -vv --pytest-apps
@@ -112,7 +112,7 @@ Please make sure that when using the Local Link address, an interface id is incl
* On the host
- Interface name suffix is present when passing the address as a string, for example `fe80::260a:XXX:XXX:XXX%en0`
- The interface id is present when passing the endpoint as tupple, for example `socket.connect(('fd00::260a:XXXX:XXXX:XXXX', 3333, 0, 3))`
- The interface id is present when passing the endpoint as tuple, for example `socket.connect(('fd00::260a:XXXX:XXXX:XXXX', 3333, 0, 3))`
## Hardware Required

View File

@@ -10,26 +10,6 @@ from pytest_embedded_idf.utils import idf_parametrize
touch_wake_up_support = ['esp32', 'esp32s2']
CONFIGS = [
pytest.param('esp32_singlecore', marks=[pytest.mark.esp32]),
pytest.param(
'basic',
marks=[
pytest.mark.esp32,
pytest.mark.esp32s2,
pytest.mark.esp32s3,
pytest.mark.esp32c3,
pytest.mark.esp32c5,
pytest.mark.esp32c6,
pytest.mark.esp32c61,
pytest.mark.esp32h2,
pytest.mark.esp32p4,
pytest.mark.esp32c2,
],
),
]
@pytest.mark.generic
@idf_parametrize(
'config,target', [('esp32_singlecore', 'esp32'), ('basic', 'supported_targets')], indirect=['config', 'target']
@@ -42,11 +22,11 @@ def test_deep_sleep(dut: Dut) -> None:
'esp32s2': [9],
}[dut.target]
logging.info('Expecting to see wakeup configured on pad(s): {}'.format(wake_pads))
logging.info(f'Expecting to see wakeup configured on pad(s): {wake_pads}')
expect_items = ['Enabling timer wakeup, 20s']
for pad in wake_pads:
expect_items += [r'Touch pad #{} average: \d+, wakeup threshold set to \d+.'.format(pad)]
expect_items += [rf'Touch pad #{pad} average: \d+, wakeup threshold set to \d+.']
expect_items += ['Enabling touch pad wakeup']
for exp in expect_items:
@@ -69,7 +49,7 @@ def test_deep_sleep(dut: Dut) -> None:
dut.expect_exact('boot: ESP-IDF') # first output that's the same on all chips
sleep_time = time.time() - start_sleep
logging.info('Host measured sleep time at {:.2f}s'.format(sleep_time))
logging.info(f'Host measured sleep time at {sleep_time:.2f}s')
assert 18 < sleep_time < 22 # note: high tolerance as measuring time on the host may have some timing skew
dut.expect_exact('boot: Fast booting app from partition', timeout=2)

View File

@@ -10,7 +10,10 @@ 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(
r'example: Coding Scheme (3/4)|(NONE)|(REPEAT)|(RS \(Reed-Solomon coding\))',
timeout=20,
)
dut.expect(
[
'example: read efuse fields',
@@ -43,7 +46,6 @@ def test_examples_efuse(dut: Dut) -> None:
basic_efuse_example(dut)
@pytest.mark.host_test
@idf_parametrize('target', ['linux'], indirect=['target'])
def test_examples_efuse_linux(dut: Dut) -> None:
basic_efuse_example(dut)
@@ -60,14 +62,24 @@ def test_examples_efuse_linux(dut: Dut) -> None:
@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True)
@idf_parametrize(
'target',
['esp32', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c61', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3'],
[
'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')
bin_size = os.path.getsize(binary_file)
logging.info('{}_bootloader_virt_flash_enc_bin_size: {}KB'.format(dut.app.target, bin_size // 1024))
logging.info(f'{dut.app.target}_bootloader_virt_flash_enc_bin_size: {bin_size // 1024}KB')
print(' - Erase flash')
dut.serial.erase_flash()
@@ -126,7 +138,7 @@ def test_examples_efuse_with_virt_flash_enc_aes_256(dut: Dut) -> None:
# check and log bin size
binary_file = os.path.join(dut.app.binary_path, 'bootloader', 'bootloader.bin')
bin_size = os.path.getsize(binary_file)
logging.info('{}_bootloader_virt_flash_enc_aes_256_bin_size: {}KB'.format(dut.app.target, bin_size // 1024))
logging.info(f'{dut.app.target}_bootloader_virt_flash_enc_aes_256_bin_size: {bin_size // 1024}KB')
print(' - Erase flash')
dut.serial.erase_flash()
@@ -169,7 +181,17 @@ def test_examples_efuse_with_virt_flash_enc_aes_256(dut: Dut) -> None:
@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True)
@idf_parametrize(
'target',
['esp32', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c61', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3'],
[
'esp32',
'esp32c2',
'esp32c3',
'esp32c5',
'esp32c61',
'esp32c6',
'esp32h2',
'esp32s2',
'esp32s3',
],
indirect=['target'],
)
def test_examples_efuse_with_virt_flash_enc_pre_loaded(dut: Dut) -> None:
@@ -239,14 +261,24 @@ def test_examples_efuse_with_virt_flash_enc_pre_loaded(dut: Dut) -> None:
@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True)
@idf_parametrize(
'target',
['esp32', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c61', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3'],
[
'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')
bin_size = os.path.getsize(binary_file)
logging.info('{}_bootloader_virt_flash_enc_release_bin_size: {}KB'.format(dut.app.target, bin_size // 1024))
logging.info(f'{dut.app.target}_bootloader_virt_flash_enc_release_bin_size: {bin_size // 1024}KB')
dut.serial.erase_flash()
@@ -302,7 +334,7 @@ def test_examples_efuse_with_virt_secure_boot_v1(dut: Dut) -> None:
# check and log bin size
binary_file = os.path.join(dut.app.binary_path, 'bootloader', 'bootloader.bin')
bin_size = os.path.getsize(binary_file)
logging.info('{}_bootloader_virt_secure_boot_v1_bin_size: {}KB'.format(dut.app.target, bin_size // 1024))
logging.info(f'{dut.app.target}_bootloader_virt_secure_boot_v1_bin_size: {bin_size // 1024}KB')
print(' - Erase flash')
dut.serial.erase_flash()
@@ -400,7 +432,7 @@ def test_examples_efuse_with_virt_secure_boot_v1_pre_loaded(dut: Dut) -> None:
dut.expect('example: Done')
@pytest.mark.esp32eco3
@pytest.mark.esp32_rev3
@pytest.mark.parametrize(
'config',
[
@@ -414,7 +446,7 @@ 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')
bin_size = os.path.getsize(binary_file)
logging.info('{}_bootloader_secure_boot_v2_bin_size: {}KB'.format(dut.app.target, bin_size // 1024))
logging.info(f'{dut.app.target}_bootloader_secure_boot_v2_bin_size: {bin_size // 1024}KB')
print(' - Erase flash')
dut.serial.erase_flash()
@@ -520,7 +552,7 @@ def test_examples_efuse_with_virt_secure_boot_v2(dut: Dut) -> None:
dut.expect('example: Done')
@pytest.mark.esp32eco3
@pytest.mark.esp32_rev3
@pytest.mark.parametrize(
'config',
[
@@ -593,14 +625,24 @@ def test_examples_efuse_with_virt_secure_boot_v2_pre_loaded(dut: Dut) -> None:
@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True)
@idf_parametrize(
'target',
['esp32c3', 'esp32c2', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4', 'esp32s2', 'esp32s3'],
[
'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')
bin_size = os.path.getsize(binary_file)
logging.info('{}_bootloader_virt_secure_boot_v2_bin_size: {}KB'.format(dut.app.target, bin_size // 1024))
logging.info(f'{dut.app.target}_bootloader_virt_secure_boot_v2_bin_size: {bin_size // 1024}KB')
print(' - Erase flash')
dut.serial.erase_flash()
@@ -616,13 +658,13 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx(dut: Dut) -> None:
signed_scheme = 'ECDSA'
else:
signed_scheme = 'RSA-PSS'
dut.expect('secure_boot_v2: Verifying with %s...' % signed_scheme)
dut.expect(f'secure_boot_v2: Verifying with {signed_scheme}...')
dut.expect('secure_boot_v2: Signature verified successfully!')
dut.expect('secure_boot_v2: enabling secure boot v2...')
dut.expect('Verifying image signature...')
dut.expect('secure_boot_v2: Secure boot V2 is not enabled yet and eFuse digest keys are not set')
dut.expect('secure_boot_v2: Verifying with %s...' % signed_scheme)
dut.expect(f'secure_boot_v2: Verifying with {signed_scheme}...')
dut.expect('secure_boot_v2: Signature verified successfully!')
dut.expect('secure_boot_v2: Secure boot digests absent, generating..')
dut.expect('secure_boot_v2: Digests successfully calculated, 1 valid signatures')
@@ -651,7 +693,7 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx(dut: Dut) -> None:
dut.serial.hard_reset()
dut.expect('Loading virtual efuse blocks from flash')
dut.expect('Verifying image signature...')
dut.expect('secure_boot_v2: Verifying with %s...' % signed_scheme)
dut.expect(f'secure_boot_v2: Verifying with {signed_scheme}...')
dut.expect('secure_boot_v2: Signature verified successfully!')
dut.expect('secure_boot_v2: enabling secure boot v2...')
dut.expect('secure_boot_v2: secure boot v2 is already enabled, continuing..')
@@ -664,7 +706,17 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx(dut: Dut) -> None:
@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True)
@idf_parametrize(
'target',
['esp32c3', 'esp32c2', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4', 'esp32s2', 'esp32s3'],
[
'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:
@@ -685,12 +737,14 @@ 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'])
@@ -704,7 +758,7 @@ def test_example_efuse_with_virt_secure_boot_v2_esp32xx_pre_loaded(dut: Dut) ->
else:
signed_scheme = 'RSA-PSS'
dut.expect('secure_boot_v2: Verifying with %s...' % signed_scheme)
dut.expect(f'secure_boot_v2: Verifying with {signed_scheme}...')
dut.expect('secure_boot_v2: Signature verified successfully!')
dut.expect('secure_boot_v2: Secure boot digests already present')
dut.expect('secure_boot_v2: Using pre-loaded public key digest in eFuse')
@@ -727,7 +781,7 @@ def test_example_efuse_with_virt_secure_boot_v2_esp32xx_pre_loaded(dut: Dut) ->
dut.serial.hard_reset()
dut.expect('Loading virtual efuse blocks from flash')
dut.expect('Verifying image signature...')
dut.expect('secure_boot_v2: Verifying with %s...' % signed_scheme)
dut.expect(f'secure_boot_v2: Verifying with {signed_scheme}...')
dut.expect('secure_boot_v2: Signature verified successfully!')
dut.expect('secure_boot_v2: enabling secure boot v2...')
dut.expect('secure_boot_v2: secure boot v2 is already enabled, continuing..')
@@ -749,7 +803,7 @@ 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')
bin_size = os.path.getsize(binary_file)
logging.info('{}_bootloader_virt_sb_v1_and_fe_bin_size: {}KB'.format(dut.app.target, bin_size // 1024))
logging.info(f'{dut.app.target}_bootloader_virt_sb_v1_and_fe_bin_size: {bin_size // 1024}KB')
print(' - Erase flash')
dut.serial.erase_flash()
@@ -806,7 +860,7 @@ def test_examples_efuse_with_virt_sb_v1_and_fe(dut: Dut) -> None:
dut.expect('example: Done')
@pytest.mark.esp32eco3
@pytest.mark.esp32_rev3
@pytest.mark.parametrize(
'config',
[
@@ -820,7 +874,7 @@ 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')
bin_size = os.path.getsize(binary_file)
logging.info('{}_bootloader_virt_sb_v2_and_fe_bin_size: {}KB'.format(dut.app.target, bin_size // 1024))
logging.info(f'{dut.app.target}_bootloader_virt_sb_v2_and_fe_bin_size: {bin_size // 1024}KB')
print(' - Erase flash')
dut.serial.erase_flash()
@@ -894,7 +948,6 @@ def test_examples_efuse_with_virt_sb_v2_and_fe(dut: Dut) -> None:
dut.expect('example: Done')
@pytest.mark.host_test
@pytest.mark.qemu
@pytest.mark.parametrize(
'config',
@@ -906,7 +959,8 @@ def test_examples_efuse_with_virt_sb_v2_and_fe(dut: Dut) -> None:
@pytest.mark.parametrize(
'qemu_extra_args',
[
f'-drive file={os.path.join(os.path.dirname(__file__), "test", "esp32eco3_efuses.bin")},if=none,format=raw,id=efuse '
f'-drive file={os.path.join(os.path.dirname(__file__), "test", "esp32_rev3_efuses.bin")},'
'if=none,format=raw,id=efuse '
'-global driver=nvram.esp32.efuse,property=drive,value=efuse '
'-global driver=timer.esp32.timg,property=wdt_disable,value=true',
],
@@ -976,11 +1030,14 @@ def test_examples_efuse_with_virt_sb_v2_and_fe_qemu(dut: QemuDut) -> None:
finally:
# the above example test burns the efuses, and hence the efuses file which the
# qemu uses to emulate the efuses, "test/esp32eco3_efuses.bin", gets modified.
# qemu uses to emulate the efuses, "test/esp32_rev3_efuses.bin", gets modified.
# Thus, restore the efuses file values back to the default ESP32-ECO3 efuses values.
with open(os.path.join(os.path.dirname(__file__), 'test', 'esp32eco3_efuses.bin'), 'wb') as efuse_file:
esp32eco3_efuses = '0' * 26 + '8' + '0' * 17 + '1' + '0' * 203
efuse_file.write(bytearray.fromhex(esp32eco3_efuses))
with open(
os.path.join(os.path.dirname(__file__), 'test', 'esp32_rev3_efuses.bin'),
'wb',
) as efuse_file:
esp32_rev3_efuses = '0' * 26 + '8' + '0' * 17 + '1' + '0' * 203
efuse_file.write(bytearray.fromhex(esp32_rev3_efuses))
@pytest.mark.generic
@@ -988,14 +1045,23 @@ def test_examples_efuse_with_virt_sb_v2_and_fe_qemu(dut: QemuDut) -> None:
@pytest.mark.parametrize('config', ['virt_sb_v2_and_fe'], indirect=True)
@idf_parametrize(
'target',
['esp32c3', 'esp32c2', 'esp32c5', 'esp32c61', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3'],
[
'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')
bin_size = os.path.getsize(binary_file)
logging.info('{}_bootloader_virt_sb_v2_and_fe_bin_size: {}KB'.format(dut.app.target, bin_size // 1024))
logging.info(f'{dut.app.target}_bootloader_virt_sb_v2_and_fe_bin_size: {bin_size // 1024}KB')
dut.serial.erase_flash()
@@ -1012,13 +1078,13 @@ def test_examples_efuse_with_virt_sb_v2_and_fe_esp32xx(dut: Dut) -> None:
signed_scheme = 'ECDSA'
else:
signed_scheme = 'RSA-PSS'
dut.expect('secure_boot_v2: Verifying with %s...' % signed_scheme)
dut.expect(f'secure_boot_v2: Verifying with {signed_scheme}...')
dut.expect('secure_boot_v2: Signature verified successfully!')
dut.expect('secure_boot_v2: enabling secure boot v2...')
dut.expect('Verifying image signature...')
dut.expect('secure_boot_v2: Secure boot V2 is not enabled yet and eFuse digest keys are not set')
dut.expect('secure_boot_v2: Verifying with %s...' % signed_scheme)
dut.expect(f'secure_boot_v2: Verifying with {signed_scheme}...')
dut.expect('secure_boot_v2: Signature verified successfully!')
dut.expect('secure_boot_v2: Secure boot digests absent, generating..')
dut.expect('secure_boot_v2: Digests successfully calculated, 1 valid signatures')
@@ -1057,20 +1123,20 @@ def test_examples_efuse_with_virt_sb_v2_and_fe_esp32xx(dut: Dut) -> None:
dut.expect('boot: Secure boot permanently enabled')
dut.expect('Verifying image signature...')
dut.expect('secure_boot_v2: Verifying with %s...' % signed_scheme)
dut.expect(f'secure_boot_v2: Verifying with {signed_scheme}...')
dut.expect('secure_boot_v2: Signature verified successfully!')
dut.expect('flash_encrypt: bootloader encrypted successfully')
dut.expect('flash_encrypt: partition table encrypted and loaded successfully')
dut.expect('Verifying image signature...')
dut.expect('secure_boot_v2: Verifying with %s...' % signed_scheme)
dut.expect(f'secure_boot_v2: Verifying with {signed_scheme}...')
dut.expect('secure_boot_v2: Signature verified successfully!')
dut.expect('flash_encrypt: Flash encryption completed', timeout=90)
dut.expect('Resetting with flash encryption enabled...')
dut.expect('Loading virtual efuse blocks from flash')
dut.expect('Verifying image signature...')
dut.expect('secure_boot_v2: Verifying with %s...' % signed_scheme)
dut.expect(f'secure_boot_v2: Verifying with {signed_scheme}...')
dut.expect('secure_boot_v2: Signature verified successfully!')
dut.expect('secure_boot_v2: enabling secure boot v2...')
dut.expect('secure_boot_v2: secure boot v2 is already enabled, continuing..')

View File

@@ -6,6 +6,7 @@ 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
@@ -82,13 +83,13 @@ def test_wifi_getting_started_esp32c2_xtal_26mhz(dut: Tuple[IdfDut, IdfDut]) ->
@pytest.mark.two_duts
@pytest.mark.xtal_26mhz
@pytest.mark.esp32c2eco4
@pytest.mark.esp32c2_rev2
@pytest.mark.parametrize(
'count, config, target, baud, app_path',
[
(
2,
'esp32c2eco4_xtal26m',
'esp32c2_rev2_xtal26m',
'esp32c2',
'74880',
f'{os.path.join(os.path.dirname(__file__), "softAP")}|{os.path.join(os.path.dirname(__file__), "station")}',
@@ -96,7 +97,7 @@ def test_wifi_getting_started_esp32c2_xtal_26mhz(dut: Tuple[IdfDut, IdfDut]) ->
],
indirect=True,
)
def test_wifi_getting_started_esp32c2eco4_xtal_26mhz(dut: Tuple[IdfDut, IdfDut]) -> None:
def test_wifi_getting_started_esp32c2_rev2_xtal_26mhz(dut: Tuple[IdfDut, IdfDut]) -> None:
softap = dut[0]
station = dut[1]
@@ -113,20 +114,20 @@ def test_wifi_getting_started_esp32c2eco4_xtal_26mhz(dut: Tuple[IdfDut, IdfDut])
@pytest.mark.two_duts
@pytest.mark.esp32c3eco7
@pytest.mark.esp32c3_rev1
@pytest.mark.parametrize(
'count, config, target, app_path',
[
(
2,
'esp32c3eco7',
'esp32c3_rev1',
'esp32c3',
f'{os.path.join(os.path.dirname(__file__), "softAP")}|{os.path.join(os.path.dirname(__file__), "station")}',
),
],
indirect=True,
)
def test_wifi_getting_started_esp32c3eco7(dut: Tuple[IdfDut, IdfDut]) -> None:
def test_wifi_getting_started_esp32c3_rev1(dut: Tuple[IdfDut, IdfDut]) -> None:
softap = dut[0]
station = dut[1]

View File

@@ -93,24 +93,24 @@ def test_wifi_power_save_esp32c2_26mhz(dut: Dut) -> None:
@pytest.mark.wifi_ap
@pytest.mark.xtal_26mhz
@pytest.mark.esp32c2eco4
@pytest.mark.esp32c2_rev2
@pytest.mark.parametrize(
'config, baud, target',
[
('c2eco4_xtal26m', '74880', 'esp32c2'),
('esp32c2_rev2_xtal26m', '74880', 'esp32c2'),
],
indirect=True,
)
def test_wifi_power_save_esp32c2eco4_26mhz(dut: Dut) -> None:
def test_wifi_power_save_esp32c2_rev2_26mhz(dut: Dut) -> None:
_run_test(dut)
@pytest.mark.wifi_ap
@pytest.mark.esp32c3eco7
@pytest.mark.esp32c3_rev1
@pytest.mark.parametrize(
'config, target',
[('c3eco7', 'esp32c3')],
[('esp32c3_rev1', 'esp32c3')],
indirect=True,
)
def test_wifi_power_save_esp32c3eco7(dut: Dut) -> None:
def test_wifi_power_save_esp32c3_rev1(dut: Dut) -> None:
_run_test(dut)