Files
esphome/tests/component_tests/ethernet/test_ethernet.py
T
2184ec2928 [ethernet] Add CH390 SPI ethernet support (#18226)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-10 12:24:16 -05:00

93 lines
3.1 KiB
Python

"""Tests for the ethernet final-validation coexistence gate and schema bounds."""
import pytest
from voluptuous import Invalid
from esphome import config_validation as cv
from esphome.components.esp32 import (
KEY_BOARD,
KEY_IDF_VERSION,
KEY_VARIANT,
VARIANT_ESP32S3,
)
from esphome.components.ethernet import CONF_CLOCK_SPEED, CONFIG_SCHEMA, _final_validate
from esphome.components.network import _validate_priority_list
from esphome.const import CONF_PRIORITY, PlatformFramework
from esphome.core import CORE
import esphome.final_validate as fv
from ..types import SetCoreConfigCallable
_CH390_CONFIG = {
"type": "CH390",
"clk_pin": 47,
"mosi_pin": 48,
"miso_pin": 14,
"cs_pin": 21,
}
@pytest.fixture(autouse=True)
def _reset_full_config():
"""Reset fv.full_config so each test starts with a clean slate."""
token = fv.full_config.set({})
yield
fv.full_config.reset(token)
def test_rejects_wifi_and_ethernet_without_priority() -> None:
"""Wi-Fi + ethernet without a network: priority: list must be rejected."""
fv.full_config.set({"wifi": {}, "ethernet": {}})
with pytest.raises(Invalid, match="cannot be used together with component wifi"):
_final_validate({})
def test_rejects_wifi_and_ethernet_with_incomplete_priority() -> None:
"""A priority list missing an interface is rejected and names what's missing."""
fv.full_config.set(
{
"wifi": {},
"ethernet": {},
"network": {CONF_PRIORITY: _validate_priority_list(["ethernet"])},
}
)
with pytest.raises(Invalid, match=r"must.*list both interfaces; missing: wifi"):
_final_validate({})
@pytest.mark.parametrize("clock_speed", ["26.67MHz", "72MHz"])
def test_ch390_accepts_clock_speed_up_to_the_datasheet_maximum(
set_core_config: SetCoreConfigCallable, clock_speed: str
) -> None:
"""CH390 SCK is rated to 72MHz, so the schema must accept the whole range."""
set_core_config(
PlatformFramework.ESP32_IDF,
platform_data={
KEY_BOARD: "esp32-s3-devkitc-1",
KEY_VARIANT: VARIANT_ESP32S3,
KEY_IDF_VERSION: cv.Version(5, 3, 2),
},
)
# _validate derives use_address from the node name, which has no default here.
CORE.name = "ch390-test"
config = CONFIG_SCHEMA({**_CH390_CONFIG, CONF_CLOCK_SPEED: clock_speed})
assert config[CONF_CLOCK_SPEED] == cv.frequency(clock_speed)
def test_ch390_rejects_clock_speed_above_the_datasheet_maximum(
set_core_config: SetCoreConfigCallable,
) -> None:
"""The shared 80MHz ceiling is out of spec for this part."""
set_core_config(
PlatformFramework.ESP32_IDF,
platform_data={
KEY_BOARD: "esp32-s3-devkitc-1",
KEY_VARIANT: VARIANT_ESP32S3,
KEY_IDF_VERSION: cv.Version(5, 3, 2),
},
)
# _validate derives use_address from the node name, which has no default here.
CORE.name = "ch390-test"
with pytest.raises(Invalid, match="value must be at most 72000000"):
CONFIG_SCHEMA({**_CH390_CONFIG, CONF_CLOCK_SPEED: "80MHz"})