1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-24 21:06:19 +00:00

Fix circular dependancy detection (#100458)

* Fix _async_component_dependencies

Fix bug with circular dependency detection
Fix bug with circular after_dependency detection
Simplify interface and make the code more readable

* Implement review feedback

* Pass all conflicting deps to Exception

* Change inner docstring

Co-authored-by: Erik Montnemery <erik@montnemery.com>

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
Artur Pragacz
2023-09-28 08:05:00 +02:00
committed by GitHub
parent d41144ee88
commit e1771ae01e
2 changed files with 57 additions and 51 deletions

View File

@@ -11,35 +11,46 @@ from homeassistant.core import HomeAssistant, callback
from .common import MockModule, async_get_persistent_notifications, mock_integration
async def test_component_dependencies(hass: HomeAssistant) -> None:
"""Test if we can get the proper load order of components."""
async def test_circular_component_dependencies(hass: HomeAssistant) -> None:
"""Test if we can detect circular dependencies of components."""
mock_integration(hass, MockModule("mod1"))
mock_integration(hass, MockModule("mod2", ["mod1"]))
mod_3 = mock_integration(hass, MockModule("mod3", ["mod2"]))
mock_integration(hass, MockModule("mod3", ["mod1"]))
mod_4 = mock_integration(hass, MockModule("mod4", ["mod2", "mod3"]))
assert {"mod1", "mod2", "mod3"} == await loader._async_component_dependencies(
hass, "mod_3", mod_3, set(), set()
)
deps = await loader._async_component_dependencies(hass, mod_4)
assert deps == {"mod1", "mod2", "mod3", "mod4"}
# Create circular dependency
# Create a circular dependency
mock_integration(hass, MockModule("mod1", ["mod4"]))
with pytest.raises(loader.CircularDependency):
await loader._async_component_dependencies(hass, mod_4)
# Create a different circular dependency
mock_integration(hass, MockModule("mod1", ["mod3"]))
with pytest.raises(loader.CircularDependency):
await loader._async_component_dependencies(hass, "mod_3", mod_3, set(), set())
await loader._async_component_dependencies(hass, mod_4)
# Depend on non-existing component
mod_1 = mock_integration(hass, MockModule("mod1", ["nonexisting"]))
with pytest.raises(loader.IntegrationNotFound):
await loader._async_component_dependencies(hass, "mod_1", mod_1, set(), set())
# Having an after dependency 2 deps down that is circular
mod_1 = mock_integration(
hass, MockModule("mod1", partial_manifest={"after_dependencies": ["mod_3"]})
# Create a circular after_dependency
mock_integration(
hass, MockModule("mod1", partial_manifest={"after_dependencies": ["mod4"]})
)
with pytest.raises(loader.CircularDependency):
await loader._async_component_dependencies(hass, "mod_3", mod_3, set(), set())
await loader._async_component_dependencies(hass, mod_4)
# Create a different circular after_dependency
mock_integration(
hass, MockModule("mod1", partial_manifest={"after_dependencies": ["mod3"]})
)
with pytest.raises(loader.CircularDependency):
await loader._async_component_dependencies(hass, mod_4)
async def test_nonexistent_component_dependencies(hass: HomeAssistant) -> None:
"""Test if we can detect nonexistent dependencies of components."""
mod_1 = mock_integration(hass, MockModule("mod1", ["nonexistent"]))
with pytest.raises(loader.IntegrationNotFound):
await loader._async_component_dependencies(hass, mod_1)
def test_component_loader(hass: HomeAssistant) -> None: