From 6fc064fa6a39b57b52e839002d33605b4ea71a72 Mon Sep 17 00:00:00 2001 From: Artur Pragacz <49985303+arturpragacz@users.noreply.github.com> Date: Tue, 27 May 2025 08:23:39 +0200 Subject: [PATCH] Test that recorder is not promoted to earlier stage in bootstrap (#142695) Test that recorder is not promoted to earlier stage --- homeassistant/bootstrap.py | 2 -- tests/test_bootstrap.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index b3e056f787d..55aeaef2554 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -171,8 +171,6 @@ FRONTEND_INTEGRATIONS = { # Stage 0 is divided into substages. Each substage has a name, a set of integrations and a timeout. # The substage containing recorder should have no timeout, as it could cancel a database migration. # Recorder freezes "recorder" timeout during a migration, but it does not freeze other timeouts. -# The substages preceding it should also have no timeout, until we ensure that the recorder -# is not accidentally promoted as a dependency of any of the integrations in them. # If we add timeouts to the frontend substages, we should make sure they don't apply in recovery mode. STAGE_0_INTEGRATIONS = ( # Load logging and http deps as soon as possible diff --git a/tests/test_bootstrap.py b/tests/test_bootstrap.py index ebfc6b81e00..2af7ef4dc07 100644 --- a/tests/test_bootstrap.py +++ b/tests/test_bootstrap.py @@ -1618,3 +1618,36 @@ async def test_no_base_platforms_loaded_before_recorder(hass: HomeAssistant) -> assert not problems, ( f"Integrations that are setup before recorder implement base platforms: {problems}" ) + + +async def test_recorder_not_promoted(hass: HomeAssistant) -> None: + """Verify that recorder is not promoted to earlier than its own stage.""" + integrations_before_recorder: set[str] = set() + for _, integrations, _ in bootstrap.STAGE_0_INTEGRATIONS: + if "recorder" in integrations: + break + integrations_before_recorder |= integrations + else: + pytest.fail("recorder not in stage 0") + + integrations_or_excs = await loader.async_get_integrations( + hass, integrations_before_recorder + ) + integrations: dict[str, Integration] = {} + for domain, integration in integrations_or_excs.items(): + assert not isinstance(integrations_or_excs, Exception) + integrations[domain] = integration + + integrations_all_dependencies = ( + await loader.resolve_integrations_after_dependencies( + hass, integrations.values(), ignore_exceptions=True + ) + ) + all_integrations = integrations.copy() + all_integrations.update( + (domain, loader.async_get_loaded_integration(hass, domain)) + for domains in integrations_all_dependencies.values() + for domain in domains + ) + + assert "recorder" not in all_integrations