feat(ble): added pytest for ble power save example

This commit is contained in:
cjin
2024-01-09 21:01:59 +08:00
parent 5ad9e404dc
commit cf2c7a433d
10 changed files with 157 additions and 4 deletions

View File

@ -222,6 +222,22 @@ examples/bluetooth/nimble/ble_phy:
depends_filepatterns: depends_filepatterns:
- examples/bluetooth/nimble/common/**/* - examples/bluetooth/nimble/common/**/*
examples/bluetooth/nimble/blecent:
<<: *bt_default_depends
disable:
- if: SOC_BLE_SUPPORTED != 1
depends_components:
- bt
- esp_phy
- esp_event
- esp_coex
- esp_pm
depends_filepatterns:
- examples/bluetooth/nimble/common/**/*
- examples/bluetooth/nimble/blecent/**/*
- examples/bluetooth/nimble/power_save/**/*
- examples/bluetooth/nimble/pytest_nimble_test.py
examples/bluetooth/nimble/blemesh: examples/bluetooth/nimble/blemesh:
<<: *bt_default_depends <<: *bt_default_depends
enable: enable:
@ -266,6 +282,9 @@ examples/bluetooth/nimble/power_save:
- esp_pm - esp_pm
depends_filepatterns: depends_filepatterns:
- examples/bluetooth/nimble/common/**/* - examples/bluetooth/nimble/common/**/*
- examples/bluetooth/nimble/blecent/**/*
- examples/bluetooth/nimble/power_save/**/*
- examples/bluetooth/nimble/pytest_nimble_test.py
examples/bluetooth/nimble/throughput_app: examples/bluetooth/nimble/throughput_app:
<<: *bt_default_depends <<: *bt_default_depends

View File

@ -28,4 +28,12 @@ menu "Example Configuration"
prompt "Enable Link Encryption" prompt "Enable Link Encryption"
help help
This enables bonding and encryption after connection has been established. This enables bonding and encryption after connection has been established.
config EXAMPLE_USE_CI_ADDRESS
bool
default n
prompt "Advertise using Test address(Internal Test ONLY)"
help
Used for internal test ONLY.
Use this option to advertise in a specific random address.
endmenu endmenu

View File

@ -455,17 +455,26 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
{ {
int offset = 0; int offset = 0;
int ad_struct_len = 0; int ad_struct_len = 0;
#if CONFIG_EXAMPLE_USE_CI_ADDRESS
uint32_t *addr_offset;
#endif // CONFIG_EXAMPLE_USE_CI_ADDRESS
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) { disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
return 0; return 0;
} }
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen ("ADDR_ANY")) != 0)) { if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen ("ADDR_ANY")) != 0)) {
#if !CONFIG_EXAMPLE_USE_CI_ADDRESS
ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */ /* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&peer_addr[5], &peer_addr[4], &peer_addr[3], &peer_addr[5], &peer_addr[4], &peer_addr[3],
&peer_addr[2], &peer_addr[1], &peer_addr[0]); &peer_addr[2], &peer_addr[1], &peer_addr[0]);
#else
addr_offset = (uint32_t *)&peer_addr[1];
*addr_offset = atoi(CONFIG_EXAMPLE_PEER_ADDR);
peer_addr[5] = 0xC3;
#endif // !CONFIG_EXAMPLE_USE_CI_ADDRESS
if (memcmp(peer_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { if (memcmp(peer_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0; return 0;
} }
@ -501,6 +510,9 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc)
struct ble_hs_adv_fields fields; struct ble_hs_adv_fields fields;
int rc; int rc;
int i; int i;
#if CONFIG_EXAMPLE_USE_CI_ADDRESS
uint32_t *addr_offset;
#endif // CONFIG_EXAMPLE_USE_CI_ADDRESS
/* The device has to be advertising connectability. */ /* The device has to be advertising connectability. */
if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
@ -516,10 +528,16 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc)
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) {
ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
#if !CONFIG_EXAMPLE_USE_CI_ADDRESS
/* Convert string to address */ /* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&peer_addr[5], &peer_addr[4], &peer_addr[3], &peer_addr[5], &peer_addr[4], &peer_addr[3],
&peer_addr[2], &peer_addr[1], &peer_addr[0]); &peer_addr[2], &peer_addr[1], &peer_addr[0]);
#else
addr_offset = (uint32_t *)&peer_addr[1];
*addr_offset = atoi(CONFIG_EXAMPLE_PEER_ADDR);
peer_addr[5] = 0xC3;
#endif // !CONFIG_EXAMPLE_USE_CI_ADDRESS
if (memcmp(peer_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { if (memcmp(peer_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0; return 0;
} }

View File

@ -0,0 +1,2 @@
CONFIG_EXAMPLE_USE_CI_ADDRESS=y
CONFIG_EXAMPLE_PEER_ADDR="${CI_JOB_ID}"

View File

@ -0,0 +1,4 @@
CONFIG_IDF_TARGET="esp32c2"
CONFIG_XTAL_FREQ_26=y
CONFIG_EXAMPLE_USE_CI_ADDRESS=y
CONFIG_EXAMPLE_PEER_ADDR="${CI_JOB_ID}"

View File

@ -156,4 +156,19 @@ menu "Example Configuration"
help help
Use this option to enable resolving peer's address. Use this option to enable resolving peer's address.
config EXAMPLE_USE_CI_ADDRESS
bool
default n
prompt "Advertise using Test address(Internal Test ONLY)"
help
Used for internal test ONLY.
Use this option to advertise in a specific random address.
config EXAMPLE_CI_ADDRESS_OFFSET
string
prompt "Advertise using Test address(Internal Test ONLY)"
depends on EXAMPLE_USE_CI_ADDRESS
help
Used for internal test ONLY.
Use this option to advertise in a specific random address.
endmenu endmenu

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -28,7 +28,7 @@ static uint8_t ext_adv_pattern_1[] = {
static const char *tag = "NimBLE_BLE_PRPH"; static const char *tag = "NimBLE_BLE_PRPH";
static int bleprph_gap_event(struct ble_gap_event *event, void *arg); static int bleprph_gap_event(struct ble_gap_event *event, void *arg);
#if CONFIG_EXAMPLE_RANDOM_ADDR #if CONFIG_EXAMPLE_RANDOM_ADDR || CONFIG_EXAMPLE_USE_CI_ADDRESS
static uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM; static uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM;
#else #else
static uint8_t own_addr_type; static uint8_t own_addr_type;
@ -93,7 +93,7 @@ ext_bleprph_advertise(void)
params.connectable = 1; params.connectable = 1;
/* advertise using random addr */ /* advertise using random addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC; params.own_addr_type = own_addr_type;
params.primary_phy = BLE_HCI_LE_PHY_1M; params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M; params.secondary_phy = BLE_HCI_LE_PHY_2M;
@ -462,14 +462,26 @@ bleprph_on_sync(void)
ble_app_set_addr(); ble_app_set_addr();
#endif #endif
#if CONFIG_EXAMPLE_USE_CI_ADDRESS
if (strlen(CONFIG_EXAMPLE_CI_ADDRESS_OFFSET)) {
uint8_t addr[6] = {0};
uint32_t *offset = (uint32_t *)&addr[1];
*offset = atoi(CONFIG_EXAMPLE_CI_ADDRESS_OFFSET);
addr[5] = 0xC3;
rc = ble_hs_id_set_rnd(addr);
assert(rc == 0);
}
#endif // CONFIG_EXAMPLE_USE_CI_ADDRESS
/* Make sure we have proper identity address set (public preferred) */ /* Make sure we have proper identity address set (public preferred) */
#if CONFIG_EXAMPLE_RANDOM_ADDR #if CONFIG_EXAMPLE_RANDOM_ADDR || CONFIG_EXAMPLE_USE_CI_ADDRESS
rc = ble_hs_util_ensure_addr(1); rc = ble_hs_util_ensure_addr(1);
#else #else
rc = ble_hs_util_ensure_addr(0); rc = ble_hs_util_ensure_addr(0);
#endif #endif
assert(rc == 0); assert(rc == 0);
/* Figure out address to use while advertising (no privacy for now) */ /* Figure out address to use while advertising (no privacy for now) */
rc = ble_hs_id_infer_auto(0, &own_addr_type); rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) { if (rc != 0) {

View File

@ -0,0 +1,5 @@
#
# Test Config
#
CONFIG_EXAMPLE_USE_CI_ADDRESS=y
CONFIG_EXAMPLE_CI_ADDRESS_OFFSET="${CI_JOB_ID}"

View File

@ -0,0 +1,7 @@
CONFIG_IDF_TARGET="esp32c2"
CONFIG_XTAL_FREQ_26=y
#
# Test Config
#
CONFIG_EXAMPLE_USE_CI_ADDRESS=y
CONFIG_EXAMPLE_CI_ADDRESS_OFFSET="${CI_JOB_ID}"

View File

@ -0,0 +1,63 @@
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import os.path
from typing import Tuple
import pexpect
import pytest
from pytest_embedded_idf.dut import IdfDut
# Case 1: BLE power save test
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.esp32c3
@pytest.mark.esp32s3
@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")}'),
],
indirect=True,
)
def test_power_save_conn(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None:
peripheral = dut[0]
central = dut[1]
peripheral.expect('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=30)
central.expect('NimBLE_BLE_CENT: BLE Host Task Started', timeout=30)
peripheral.expect('Returned from app_main()', timeout=30)
central.expect('Returned from app_main()', timeout=30)
central.expect('Connection established', timeout=30)
peripheral.expect('connection established; status=0', timeout=30)
output = peripheral.expect(pexpect.TIMEOUT, timeout=30)
assert 'rst:' not in str(output) and 'boot:' not in str(output)
# 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'),
],
indirect=True,
)
def test_power_save_conn_esp32c2_26mhz(dut: Tuple[IdfDut, IdfDut]) -> None:
peripheral = dut[0]
central = dut[1]
peripheral.expect('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=5)
central.expect('NimBLE_BLE_CENT: BLE Host Task Started', timeout=5)
peripheral.expect('Returned from app_main()', timeout=5)
central.expect('Returned from app_main()', timeout=5)
central.expect('Connection established', timeout=30)
peripheral.expect('connection established; status=0', timeout=30)
output = peripheral.expect(pexpect.TIMEOUT, timeout=30)
assert 'rst:' not in str(output) and 'boot:' not in str(output)