mirror of
https://github.com/esphome/esphome.git
synced 2026-10-05 10:31:29 +00:00
A table-build failure that keeps the link for legacy nodes now charges the backoff, so an unwalkable database stops retrying at advertisement cadence. The write action re-resolves from the current table only. The neutral engine drops a discovery completion that raced a teardown. Slot charging and the cap-check skip read one mapping, so a platform cannot be skipped uncharged.
80 lines
3.1 KiB
Python
80 lines
3.1 KiB
Python
"""Tests for the cross-component GATT slot ledger."""
|
|
|
|
import pytest
|
|
|
|
from esphome import config_validation as cv
|
|
from esphome.components import (
|
|
ble_client,
|
|
ble_device_base,
|
|
bluetooth_connection,
|
|
bluetooth_proxy,
|
|
rp2040_ble,
|
|
)
|
|
from esphome.const import CONF_MAC_ADDRESS, PlatformFramework
|
|
from esphome.core import CORE
|
|
|
|
from ..types import SetCoreConfigCallable
|
|
|
|
|
|
def test_gatt_slot_ledger_rejects_overcommit_on_rp2(
|
|
set_core_config: SetCoreConfigCallable,
|
|
) -> None:
|
|
# rp2 owns its budget: the stack's validation reports the overcommit and
|
|
# the neutral cap check stays silent (one message per misconfiguration).
|
|
set_core_config(PlatformFramework.RP2_ARDUINO)
|
|
bluetooth_connection.consume_gatt_slot("bluetooth_proxy", 3)({})
|
|
bluetooth_connection.consume_gatt_slot("ble_client")({})
|
|
bluetooth_connection.FINAL_VALIDATE_SCHEMA({})
|
|
with pytest.raises(cv.Invalid, match="rp2 maximum is 3"):
|
|
rp2040_ble.validate_connection_slots()
|
|
|
|
|
|
def test_gatt_slot_ledger_skipped_in_testing_mode(
|
|
set_core_config: SetCoreConfigCallable,
|
|
) -> None:
|
|
# Grouped component builds merge fixtures past the cap; the check defers
|
|
# to testing mode like esp32_ble.validate_connection_slots.
|
|
set_core_config(PlatformFramework.RP2_ARDUINO)
|
|
bluetooth_connection.consume_gatt_slot("bluetooth_proxy", 3)({})
|
|
bluetooth_connection.consume_gatt_slot("ble_client")({})
|
|
CORE.testing_mode = True
|
|
try:
|
|
bluetooth_connection.FINAL_VALIDATE_SCHEMA({})
|
|
rp2040_ble.validate_connection_slots()
|
|
finally:
|
|
CORE.testing_mode = False
|
|
|
|
|
|
def test_real_validators_charge_the_ledger_on_rp2(
|
|
set_core_config: SetCoreConfigCallable,
|
|
) -> None:
|
|
# End to end through the component CONFIG_SCHEMAs (no hand charges):
|
|
# removing either consumer's consume_gatt_slot call fails this test.
|
|
set_core_config(PlatformFramework.RP2_ARDUINO)
|
|
ble_device_base.register_hub_provider("rp2_ble_tracker")
|
|
CORE.loaded_integrations.add("rp2_ble_tracker")
|
|
bluetooth_proxy.CONFIG_SCHEMA({})
|
|
ble_client.CONFIG_SCHEMA({CONF_MAC_ADDRESS: "AA:BB:CC:DD:EE:FF"})
|
|
# The proxy defaults to 3 slots on rp2; ble_client's claim overcommits
|
|
# and rp2's own budget names every claimant.
|
|
with pytest.raises(
|
|
cv.Invalid,
|
|
match="Components: bluetooth_proxy, bluetooth_proxy, bluetooth_proxy, "
|
|
"ble_client",
|
|
):
|
|
rp2040_ble.validate_connection_slots()
|
|
|
|
|
|
def test_neutral_cap_check_guards_future_hub_platforms(
|
|
set_core_config: SetCoreConfigCallable, monkeypatch: pytest.MonkeyPatch
|
|
) -> None:
|
|
# Both current platforms defer to their stack budgets; pin the message
|
|
# and boundary of the branch a future budget-less hub platform takes.
|
|
set_core_config(PlatformFramework.RP2_ARDUINO)
|
|
monkeypatch.setattr(bluetooth_connection, "_STACK_BUDGETS", {})
|
|
bluetooth_connection.consume_gatt_slot("bluetooth_proxy", 3)({})
|
|
bluetooth_connection.FINAL_VALIDATE_SCHEMA({})
|
|
bluetooth_connection.consume_gatt_slot("ble_client")({})
|
|
with pytest.raises(cv.Invalid, match="supports at most 3 GATT client connection"):
|
|
bluetooth_connection.FINAL_VALIDATE_SCHEMA({})
|