1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-12 00:02:21 +01:00

tests, address review comments

This commit is contained in:
J. Nick Koston
2025-06-15 20:22:29 -05:00
parent a4efc63bf2
commit 787ec43266
10 changed files with 686 additions and 32 deletions

View File

@@ -2,8 +2,10 @@
from __future__ import annotations
import asyncio
import logging
from pathlib import Path
import re
import pytest
@@ -29,24 +31,111 @@ async def test_loop_disable_enable(
"EXTERNAL_COMPONENT_PATH", external_components_path
)
# Write, compile and run the ESPHome device, then connect to API
async with run_compiled(yaml_config), api_client_connected() as client:
# Track log messages and events
log_messages = []
self_disable_10_disabled = asyncio.Event()
normal_component_10_loops = asyncio.Event()
redundant_enable_tested = asyncio.Event()
redundant_disable_tested = asyncio.Event()
self_disable_10_counts = []
normal_component_counts = []
def on_log_line(line: str) -> None:
"""Process each log line from the process output."""
# Strip ANSI color codes
clean_line = re.sub(r"\x1b\[[0-9;]*m", "", line)
if "loop_test_component" not in clean_line:
return
log_messages.append(clean_line)
# Track specific events using the cleaned line
if "[self_disable_10]" in clean_line:
if "Loop count:" in clean_line:
# Extract loop count
try:
count = int(clean_line.split("Loop count: ")[1])
self_disable_10_counts.append(count)
except (IndexError, ValueError):
pass
elif "Disabling self after 10 loops" in clean_line:
self_disable_10_disabled.set()
elif "[normal_component]" in clean_line and "Loop count:" in clean_line:
try:
count = int(clean_line.split("Loop count: ")[1])
normal_component_counts.append(count)
if count >= 10:
normal_component_10_loops.set()
except (IndexError, ValueError):
pass
elif (
"[redundant_enable]" in clean_line
and "Testing enable when already enabled" in clean_line
):
redundant_enable_tested.set()
elif (
"[redundant_disable]" in clean_line
and "Testing disable when will be disabled" in clean_line
):
redundant_disable_tested.set()
# Write, compile and run the ESPHome device with log callback
async with (
run_compiled(yaml_config, line_callback=on_log_line),
api_client_connected() as client,
):
# Verify we can connect and get device info
device_info = await client.device_info()
assert device_info is not None
assert device_info.name == "loop-test"
# The fact that this compiles and runs proves that:
# 1. The partitioned vector implementation works
# 2. Components can call disable_loop() and enable_loop()
# 3. The system handles multiple component instances correctly
# 4. Actions for enabling/disabling components work
# Wait for self_disable_10 to disable itself
try:
await asyncio.wait_for(self_disable_10_disabled.wait(), timeout=10.0)
except asyncio.TimeoutError:
pytest.fail("self_disable_10 did not disable itself within 10 seconds")
# Note: Host platform doesn't send component logs through API,
# so we can't verify the runtime behavior through logs.
# However, the successful compilation and execution proves
# the implementation is correct.
_LOGGER.info(
"Loop disable/enable test passed - code compiles and runs successfully!"
# Verify it ran exactly 10 times
assert len(self_disable_10_counts) == 10, (
f"Expected 10 loops for self_disable_10, got {len(self_disable_10_counts)}"
)
assert self_disable_10_counts == list(range(1, 11)), (
f"Expected counts 1-10, got {self_disable_10_counts}"
)
# Wait for normal_component to run at least 10 times
try:
await asyncio.wait_for(normal_component_10_loops.wait(), timeout=10.0)
except asyncio.TimeoutError:
pytest.fail(
f"normal_component did not reach 10 loops within timeout, got {len(normal_component_counts)}"
)
# Wait for redundant operation tests
try:
await asyncio.wait_for(redundant_enable_tested.wait(), timeout=10.0)
except asyncio.TimeoutError:
pytest.fail("redundant_enable did not test enabling when already enabled")
try:
await asyncio.wait_for(redundant_disable_tested.wait(), timeout=10.0)
except asyncio.TimeoutError:
pytest.fail(
"redundant_disable did not test disabling when will be disabled"
)
# Wait a bit to see if self_disable_10 gets re-enabled
await asyncio.sleep(3)
# Check final counts
later_self_disable_counts = [c for c in self_disable_10_counts if c > 10]
if later_self_disable_counts:
_LOGGER.info(
f"self_disable_10 was successfully re-enabled and ran {len(later_self_disable_counts)} more times"
)
_LOGGER.info("Loop disable/enable test passed - all assertions verified!")