diff --git a/homeassistant/core.py b/homeassistant/core.py index d7535907dfc..aa4f6c37188 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -41,6 +41,7 @@ from typing import ( final, overload, ) +import weakref from propcache.api import cached_property, under_cached_property import voluptuous as vol @@ -409,6 +410,9 @@ class CoreState(enum.Enum): return self.value +hass_instances: list[weakref.ref[HomeAssistant]] = [] + + class HomeAssistant: """Root object of the Home Assistant home automation.""" @@ -419,6 +423,7 @@ class HomeAssistant: def __new__(cls, config_dir: str) -> Self: """Set the _hass thread local data.""" hass = super().__new__(cls) + hass_instances.append(weakref.ref(hass)) _hass.hass = hass return hass diff --git a/tests/conftest.py b/tests/conftest.py index 2c23270daee..89e5361486e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -288,8 +288,25 @@ def garbage_collection() -> None: handles the most common cases and let each module override to run per test case if needed. """ + start_live_hass_instances = len( + [hass() for hass in ha.hass_instances if hass() is not None] + ) + yield gc.collect() - gc.freeze() + end_live_hass_instances = len( + [hass() for hass in ha.hass_instances if hass() is not None] + ) + if abs(start_live_hass_instances - end_live_hass_instances) > 1: + _LOGGER.error( + "Garbage collection did not clean up all Home Assistant instances. " + "Start: %s, End: %s", + start_live_hass_instances, + end_live_hass_instances, + ) + pytest.fail( + f"Garbage collection did not clean up all Home Assistant instances. " + f"Start: {start_live_hass_instances}, End: {end_live_hass_instances}" + ) @pytest.fixture(autouse=True) @@ -1325,7 +1342,8 @@ def disable_translations_once( translations_once.start() -@pytest_asyncio.fixture(autouse=True, scope="session", loop_scope="session") +# @pytest_asyncio.fixture(autouse=True, scope="session", loop_scope="session") +@pytest_asyncio.fixture(autouse=True) async def mock_zeroconf_resolver() -> AsyncGenerator[_patch]: """Mock out the zeroconf resolver.""" resolver = AsyncResolver()