Files
esphome/tests/unit_tests/test_preferences.py
T

150 lines
5.0 KiB
Python

"""Tests for esphome.preferences storage backend selection."""
import pytest
from esphome import preferences
from esphome.components.esp32 import KEY_ESP32
from esphome.components.esp32.const import (
VARIANT_ESP32,
VARIANT_ESP32C2,
VARIANT_ESP32C3,
VARIANT_ESP32C61,
)
import esphome.config_validation as cv
from esphome.const import (
CONF_STORAGE,
KEY_CORE,
KEY_TARGET_PLATFORM,
KEY_VARIANT,
PLATFORM_ESP32,
PLATFORM_ESP8266,
PLATFORM_RP2040,
)
from esphome.core import CORE
def _set_platform(platform: str) -> None:
CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: platform}
def _set_esp32(variant: str) -> None:
_set_platform(PLATFORM_ESP32)
CORE.data[KEY_ESP32] = {KEY_VARIANT: variant}
def _validate(value: dict):
return cv.Schema(preferences.storage_schema())(value)
def _define_names() -> set[str]:
return {define.name for define in CORE.defines}
def test_is_in_flash() -> None:
_set_platform(PLATFORM_ESP8266)
assert preferences.is_in_flash(preferences.STORAGE_FLASH) is True
assert preferences.is_in_flash(preferences.STORAGE_RTC) is False
# The RTC storage define is ESP32-specific.
assert "USE_ESP32_RTC_PREFERENCES" not in _define_names()
def test_is_in_flash_esp32_rtc_emits_define() -> None:
_set_esp32(VARIANT_ESP32)
assert preferences.is_in_flash(preferences.STORAGE_FLASH) is True
assert "USE_ESP32_RTC_PREFERENCES" not in _define_names()
assert preferences.is_in_flash(preferences.STORAGE_RTC) is False
assert "USE_ESP32_RTC_PREFERENCES" in _define_names()
def test_request_rtc_storage_esp32_only() -> None:
_set_platform(PLATFORM_ESP8266)
preferences.request_rtc_storage()
# ESP8266 always has its RTC backend; no define is needed or emitted.
assert "USE_ESP32_RTC_PREFERENCES" not in _define_names()
def test_request_rtc_storage_esp32_emits_define() -> None:
_set_esp32(VARIANT_ESP32)
preferences.request_rtc_storage()
assert "USE_ESP32_RTC_PREFERENCES" in _define_names()
@pytest.mark.parametrize("variant", [VARIANT_ESP32, VARIANT_ESP32C3])
def test_validate_rtc_storage_accepted(variant: str) -> None:
_set_esp32(variant)
assert preferences.validate_rtc_storage(True) is True
assert preferences.validate_rtc_storage(False) is False
def test_validate_rtc_storage_esp8266() -> None:
_set_platform(PLATFORM_ESP8266)
# Tolerated no-op: the ESP8266 backend always has RTC storage.
assert preferences.validate_rtc_storage(True) is True
# But it cannot be disabled, so an explicit false is an error.
with pytest.raises(cv.Invalid, match="always enabled on ESP8266"):
preferences.validate_rtc_storage(False)
@pytest.mark.parametrize("variant", [VARIANT_ESP32C2, VARIANT_ESP32C61])
def test_validate_rtc_storage_rejected_without_rtc_memory(variant: str) -> None:
_set_esp32(variant)
with pytest.raises(cv.Invalid, match="not supported on this platform"):
preferences.validate_rtc_storage(True)
# Disabling it is always fine.
assert preferences.validate_rtc_storage(False) is False
def test_validate_rtc_storage_rejected_on_unsupported_platform() -> None:
_set_platform(PLATFORM_RP2040)
with pytest.raises(cv.Invalid, match="not supported on this platform"):
preferences.validate_rtc_storage(True)
@pytest.mark.parametrize(
("platform", "expected"),
[
# Defaults preserve each platform's historic behavior.
(PLATFORM_ESP8266, preferences.STORAGE_RTC),
(PLATFORM_RP2040, preferences.STORAGE_FLASH),
],
)
def test_default_storage_per_platform(platform: str, expected: str) -> None:
_set_platform(platform)
assert _validate({})[CONF_STORAGE] == expected
@pytest.mark.parametrize("variant", [VARIANT_ESP32, VARIANT_ESP32C2])
def test_default_storage_esp32_is_flash(variant: str) -> None:
# ESP32 defaults to flash on every variant, including those without RTC memory.
_set_esp32(variant)
assert _validate({})[CONF_STORAGE] == preferences.STORAGE_FLASH
def test_rtc_allowed_on_esp8266() -> None:
_set_platform(PLATFORM_ESP8266)
assert _validate({CONF_STORAGE: "rtc"})[CONF_STORAGE] == preferences.STORAGE_RTC
@pytest.mark.parametrize("variant", [VARIANT_ESP32, VARIANT_ESP32C3])
def test_rtc_allowed_on_esp32_with_rtc_memory(variant: str) -> None:
_set_esp32(variant)
assert _validate({CONF_STORAGE: "rtc"})[CONF_STORAGE] == preferences.STORAGE_RTC
@pytest.mark.parametrize("variant", [VARIANT_ESP32C2, VARIANT_ESP32C61])
def test_rtc_rejected_on_esp32_without_rtc_memory(variant: str) -> None:
_set_esp32(variant)
with pytest.raises(cv.Invalid, match="not supported on this platform"):
_validate({CONF_STORAGE: "rtc"})
def test_rtc_rejected_on_unsupported_platform() -> None:
_set_platform(PLATFORM_RP2040)
with pytest.raises(cv.Invalid, match="not supported on this platform"):
_validate({CONF_STORAGE: "rtc"})
def test_flash_allowed_on_unsupported_platform() -> None:
_set_platform(PLATFORM_RP2040)
assert _validate({CONF_STORAGE: "flash"})[CONF_STORAGE] == preferences.STORAGE_FLASH