mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Set up config entries in parallel (#34755)
This commit is contained in:
parent
b876f7f11a
commit
ed925f9ef5
@ -201,8 +201,12 @@ async def _async_setup_component(
|
|||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
await hass.config_entries.flow.async_wait_init_flow_finish(domain)
|
await hass.config_entries.flow.async_wait_init_flow_finish(domain)
|
||||||
|
|
||||||
for entry in hass.config_entries.async_entries(domain):
|
await asyncio.gather(
|
||||||
await entry.async_setup(hass, integration=integration)
|
*[
|
||||||
|
entry.async_setup(hass, integration=integration)
|
||||||
|
for entry in hass.config_entries.async_entries(domain)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
hass.config.components.add(domain)
|
hass.config.components.add(domain)
|
||||||
|
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
"""Test component/platform setup."""
|
"""Test component/platform setup."""
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
|
from asynctest import Mock, patch
|
||||||
|
import pytest
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import setup
|
from homeassistant import config_entries, setup
|
||||||
import homeassistant.config as config_util
|
import homeassistant.config as config_util
|
||||||
from homeassistant.const import EVENT_COMPONENT_LOADED, EVENT_HOMEASSISTANT_START
|
from homeassistant.const import EVENT_COMPONENT_LOADED, EVENT_HOMEASSISTANT_START
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
@ -19,6 +21,7 @@ from homeassistant.helpers.config_validation import (
|
|||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
|
MockConfigEntry,
|
||||||
MockModule,
|
MockModule,
|
||||||
MockPlatform,
|
MockPlatform,
|
||||||
assert_setup_component,
|
assert_setup_component,
|
||||||
@ -34,6 +37,19 @@ VERSION_PATH = os.path.join(get_test_config_dir(), config_util.VERSION_FILE)
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def mock_handlers():
|
||||||
|
"""Mock config flows."""
|
||||||
|
|
||||||
|
class MockFlowHandler(config_entries.ConfigFlow):
|
||||||
|
"""Define a mock flow handler."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
|
||||||
|
with patch.dict(config_entries.HANDLERS, {"comp": MockFlowHandler}):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
class TestSetup:
|
class TestSetup:
|
||||||
"""Test the bootstrap utils."""
|
"""Test the bootstrap utils."""
|
||||||
|
|
||||||
@ -239,7 +255,7 @@ class TestSetup:
|
|||||||
|
|
||||||
def test_component_not_double_initialized(self):
|
def test_component_not_double_initialized(self):
|
||||||
"""Test we do not set up a component twice."""
|
"""Test we do not set up a component twice."""
|
||||||
mock_setup = mock.MagicMock(return_value=True)
|
mock_setup = Mock(return_value=True)
|
||||||
|
|
||||||
mock_integration(self.hass, MockModule("comp", setup=mock_setup))
|
mock_integration(self.hass, MockModule("comp", setup=mock_setup))
|
||||||
|
|
||||||
@ -251,7 +267,7 @@ class TestSetup:
|
|||||||
assert setup.setup_component(self.hass, "comp", {})
|
assert setup.setup_component(self.hass, "comp", {})
|
||||||
assert not mock_setup.called
|
assert not mock_setup.called
|
||||||
|
|
||||||
@mock.patch("homeassistant.util.package.install_package", return_value=False)
|
@patch("homeassistant.util.package.install_package", return_value=False)
|
||||||
def test_component_not_installed_if_requirement_fails(self, mock_install):
|
def test_component_not_installed_if_requirement_fails(self, mock_install):
|
||||||
"""Component setup should fail if requirement can't install."""
|
"""Component setup should fail if requirement can't install."""
|
||||||
self.hass.config.skip_pip = False
|
self.hass.config.skip_pip = False
|
||||||
@ -350,7 +366,7 @@ class TestSetup:
|
|||||||
{"valid": True}, extra=vol.PREVENT_EXTRA
|
{"valid": True}, extra=vol.PREVENT_EXTRA
|
||||||
)
|
)
|
||||||
|
|
||||||
mock_setup = mock.MagicMock(spec_set=True)
|
mock_setup = Mock(spec_set=True)
|
||||||
|
|
||||||
mock_entity_platform(
|
mock_entity_platform(
|
||||||
self.hass,
|
self.hass,
|
||||||
@ -469,7 +485,7 @@ async def test_component_cannot_depend_config(hass):
|
|||||||
async def test_component_warn_slow_setup(hass):
|
async def test_component_warn_slow_setup(hass):
|
||||||
"""Warn we log when a component setup takes a long time."""
|
"""Warn we log when a component setup takes a long time."""
|
||||||
mock_integration(hass, MockModule("test_component1"))
|
mock_integration(hass, MockModule("test_component1"))
|
||||||
with mock.patch.object(hass.loop, "call_later", mock.MagicMock()) as mock_call:
|
with patch.object(hass.loop, "call_later") as mock_call:
|
||||||
result = await setup.async_setup_component(hass, "test_component1", {})
|
result = await setup.async_setup_component(hass, "test_component1", {})
|
||||||
assert result
|
assert result
|
||||||
assert mock_call.called
|
assert mock_call.called
|
||||||
@ -488,7 +504,7 @@ async def test_platform_no_warn_slow(hass):
|
|||||||
mock_integration(
|
mock_integration(
|
||||||
hass, MockModule("test_component1", platform_schema=PLATFORM_SCHEMA)
|
hass, MockModule("test_component1", platform_schema=PLATFORM_SCHEMA)
|
||||||
)
|
)
|
||||||
with mock.patch.object(hass.loop, "call_later", mock.MagicMock()) as mock_call:
|
with patch.object(hass.loop, "call_later") as mock_call:
|
||||||
result = await setup.async_setup_component(hass, "test_component1", {})
|
result = await setup.async_setup_component(hass, "test_component1", {})
|
||||||
assert result
|
assert result
|
||||||
assert not mock_call.called
|
assert not mock_call.called
|
||||||
@ -524,7 +540,30 @@ async def test_when_setup_already_loaded(hass):
|
|||||||
|
|
||||||
async def test_setup_import_blows_up(hass):
|
async def test_setup_import_blows_up(hass):
|
||||||
"""Test that we handle it correctly when importing integration blows up."""
|
"""Test that we handle it correctly when importing integration blows up."""
|
||||||
with mock.patch(
|
with patch(
|
||||||
"homeassistant.loader.Integration.get_component", side_effect=ValueError
|
"homeassistant.loader.Integration.get_component", side_effect=ValueError
|
||||||
):
|
):
|
||||||
assert not await setup.async_setup_component(hass, "sun", {})
|
assert not await setup.async_setup_component(hass, "sun", {})
|
||||||
|
|
||||||
|
|
||||||
|
async def test_parallel_entry_setup(hass):
|
||||||
|
"""Test config entries are set up in parallel."""
|
||||||
|
MockConfigEntry(domain="comp", data={"value": 1}).add_to_hass(hass)
|
||||||
|
MockConfigEntry(domain="comp", data={"value": 2}).add_to_hass(hass)
|
||||||
|
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
async def mock_async_setup_entry(hass, entry):
|
||||||
|
"""Mock setting up an entry."""
|
||||||
|
calls.append(entry.data["value"])
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
calls.append(entry.data["value"])
|
||||||
|
return True
|
||||||
|
|
||||||
|
mock_integration(
|
||||||
|
hass, MockModule("comp", async_setup_entry=mock_async_setup_entry,),
|
||||||
|
)
|
||||||
|
mock_entity_platform(hass, "config_flow.comp", None)
|
||||||
|
await setup.async_setup_component(hass, "comp", {})
|
||||||
|
|
||||||
|
assert calls == [1, 2, 1, 2]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user