Convert recorder entity registry tests to use async API (#116448)

* Convert recorder entity registry tests to use async API

* Address review comment

* Make sure recorder is patch is set up before hass fixture
This commit is contained in:
Erik Montnemery 2024-05-03 14:10:58 +02:00 committed by GitHub
parent f309064a7f
commit e9b9d2d545
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 89 additions and 102 deletions

View File

@ -257,6 +257,11 @@ def assert_dict_of_states_equal_without_context_and_last_changed(
) )
async def async_record_states(hass: HomeAssistant):
"""Record some test states."""
return await hass.async_add_executor_job(record_states, hass)
def record_states(hass): def record_states(hass):
"""Record some test states. """Record some test states.

View File

@ -1,6 +1,5 @@
"""The tests for sensor recorder platform.""" """The tests for sensor recorder platform."""
from collections.abc import Callable
from unittest.mock import patch from unittest.mock import patch
import pytest import pytest
@ -8,23 +7,22 @@ from sqlalchemy import select
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from homeassistant.components import recorder from homeassistant.components import recorder
from homeassistant.components.recorder import history from homeassistant.components.recorder import Recorder, history
from homeassistant.components.recorder.db_schema import StatesMeta from homeassistant.components.recorder.db_schema import StatesMeta
from homeassistant.components.recorder.util import session_scope from homeassistant.components.recorder.util import session_scope
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from homeassistant.setup import setup_component from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
from .common import ( from .common import (
ForceReturnConnectionToPool, ForceReturnConnectionToPool,
assert_dict_of_states_equal_without_context_and_last_changed, assert_dict_of_states_equal_without_context_and_last_changed,
async_record_states,
async_wait_recording_done, async_wait_recording_done,
record_states,
wait_recording_done,
) )
from tests.common import MockEntity, MockEntityPlatform, mock_registry from tests.common import MockEntity, MockEntityPlatform
from tests.typing import RecorderInstanceGenerator from tests.typing import RecorderInstanceGenerator
@ -40,41 +38,44 @@ def _count_entity_id_in_states_meta(
) )
def test_rename_entity_without_collision( @pytest.fixture
hass_recorder: Callable[..., HomeAssistant], caplog: pytest.LogCaptureFixture async def mock_recorder_before_hass(
async_setup_recorder_instance: RecorderInstanceGenerator,
) -> None:
"""Set up recorder."""
@pytest.fixture(autouse=True)
def setup_recorder(recorder_mock: Recorder) -> recorder.Recorder:
"""Set up recorder."""
async def test_rename_entity_without_collision(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test states meta is migrated when entity_id is changed.""" """Test states meta is migrated when entity_id is changed."""
hass = hass_recorder() await async_setup_component(hass, "sensor", {})
setup_component(hass, "sensor", {})
entity_reg = mock_registry(hass) reg_entry = entity_registry.async_get_or_create(
"sensor",
"test",
"unique_0000",
suggested_object_id="test1",
)
assert reg_entry.entity_id == "sensor.test1"
await hass.async_block_till_done()
@callback zero, four, states = await async_record_states(hass)
def add_entry():
reg_entry = entity_reg.async_get_or_create(
"sensor",
"test",
"unique_0000",
suggested_object_id="test1",
)
assert reg_entry.entity_id == "sensor.test1"
hass.add_job(add_entry)
hass.block_till_done()
zero, four, states = record_states(hass)
hist = history.get_significant_states( hist = history.get_significant_states(
hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"}) hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"})
) )
assert_dict_of_states_equal_without_context_and_last_changed(states, hist) assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
@callback entity_registry.async_update_entity("sensor.test1", new_entity_id="sensor.test99")
def rename_entry(): await async_wait_recording_done(hass)
entity_reg.async_update_entity("sensor.test1", new_entity_id="sensor.test99")
hass.add_job(rename_entry)
wait_recording_done(hass)
hist = history.get_significant_states( hist = history.get_significant_states(
hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"}) hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"})
@ -82,8 +83,8 @@ def test_rename_entity_without_collision(
states["sensor.test99"] = states.pop("sensor.test1") states["sensor.test99"] = states.pop("sensor.test1")
assert_dict_of_states_equal_without_context_and_last_changed(states, hist) assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
hass.states.set("sensor.test99", "post_migrate") hass.states.async_set("sensor.test99", "post_migrate")
wait_recording_done(hass) await async_wait_recording_done(hass)
new_hist = history.get_significant_states( new_hist = history.get_significant_states(
hass, hass,
zero, zero,
@ -101,8 +102,8 @@ def test_rename_entity_without_collision(
async def test_rename_entity_on_mocked_platform( async def test_rename_entity_on_mocked_platform(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant, hass: HomeAssistant,
entity_registry: er.EntityRegistry,
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test states meta is migrated when entity_id is changed when using a mocked platform. """Test states meta is migrated when entity_id is changed when using a mocked platform.
@ -111,11 +112,10 @@ async def test_rename_entity_on_mocked_platform(
sure that we do not record the entity as removed in the database sure that we do not record the entity as removed in the database
when we rename it. when we rename it.
""" """
instance = await async_setup_recorder_instance(hass) instance = recorder.get_instance(hass)
entity_reg = er.async_get(hass)
start = dt_util.utcnow() start = dt_util.utcnow()
reg_entry = entity_reg.async_get_or_create( reg_entry = entity_registry.async_get_or_create(
"sensor", "sensor",
"test", "test",
"unique_0000", "unique_0000",
@ -142,7 +142,7 @@ async def test_rename_entity_on_mocked_platform(
["sensor.test1", "sensor.test99"], ["sensor.test1", "sensor.test99"],
) )
entity_reg.async_update_entity("sensor.test1", new_entity_id="sensor.test99") entity_registry.async_update_entity("sensor.test1", new_entity_id="sensor.test99")
await hass.async_block_till_done() await hass.async_block_till_done()
# We have to call the remove method ourselves since we are mocking the platform # We have to call the remove method ourselves since we are mocking the platform
hass.states.async_remove("sensor.test1") hass.states.async_remove("sensor.test1")
@ -196,47 +196,38 @@ async def test_rename_entity_on_mocked_platform(
assert "the new entity_id is already in use" not in caplog.text assert "the new entity_id is already in use" not in caplog.text
def test_rename_entity_collision( async def test_rename_entity_collision(
hass_recorder: Callable[..., HomeAssistant], caplog: pytest.LogCaptureFixture hass: HomeAssistant,
entity_registry: er.EntityRegistry,
caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test states meta is not migrated when there is a collision.""" """Test states meta is not migrated when there is a collision."""
hass = hass_recorder() await async_setup_component(hass, "sensor", {})
setup_component(hass, "sensor", {})
entity_reg = mock_registry(hass) reg_entry = entity_registry.async_get_or_create(
"sensor",
"test",
"unique_0000",
suggested_object_id="test1",
)
assert reg_entry.entity_id == "sensor.test1"
await hass.async_block_till_done()
@callback zero, four, states = await async_record_states(hass)
def add_entry():
reg_entry = entity_reg.async_get_or_create(
"sensor",
"test",
"unique_0000",
suggested_object_id="test1",
)
assert reg_entry.entity_id == "sensor.test1"
hass.add_job(add_entry)
hass.block_till_done()
zero, four, states = record_states(hass)
hist = history.get_significant_states( hist = history.get_significant_states(
hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"}) hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"})
) )
assert_dict_of_states_equal_without_context_and_last_changed(states, hist) assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
assert len(hist["sensor.test1"]) == 3 assert len(hist["sensor.test1"]) == 3
hass.states.set("sensor.test99", "collision") hass.states.async_set("sensor.test99", "collision")
hass.states.remove("sensor.test99") hass.states.async_remove("sensor.test99")
hass.block_till_done() await hass.async_block_till_done()
# Rename entity sensor.test1 to sensor.test99 # Rename entity sensor.test1 to sensor.test99
@callback entity_registry.async_update_entity("sensor.test1", new_entity_id="sensor.test99")
def rename_entry(): await async_wait_recording_done(hass)
entity_reg.async_update_entity("sensor.test1", new_entity_id="sensor.test99")
hass.add_job(rename_entry)
wait_recording_done(hass)
# History is not migrated on collision # History is not migrated on collision
hist = history.get_significant_states( hist = history.get_significant_states(
@ -248,8 +239,8 @@ def test_rename_entity_collision(
with session_scope(hass=hass) as session: with session_scope(hass=hass) as session:
assert _count_entity_id_in_states_meta(hass, session, "sensor.test99") == 1 assert _count_entity_id_in_states_meta(hass, session, "sensor.test99") == 1
hass.states.set("sensor.test99", "post_migrate") hass.states.async_set("sensor.test99", "post_migrate")
wait_recording_done(hass) await async_wait_recording_done(hass)
new_hist = history.get_significant_states( new_hist = history.get_significant_states(
hass, hass,
zero, zero,
@ -270,44 +261,39 @@ def test_rename_entity_collision(
assert "Blocked attempt to insert duplicated state rows" not in caplog.text assert "Blocked attempt to insert duplicated state rows" not in caplog.text
def test_rename_entity_collision_without_states_meta_safeguard( async def test_rename_entity_collision_without_states_meta_safeguard(
hass_recorder: Callable[..., HomeAssistant], caplog: pytest.LogCaptureFixture hass: HomeAssistant,
entity_registry: er.EntityRegistry,
caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test states meta is not migrated when there is a collision. """Test states meta is not migrated when there is a collision.
This test disables the safeguard in the states_meta_manager This test disables the safeguard in the states_meta_manager
and relies on the filter_unique_constraint_integrity_error safeguard. and relies on the filter_unique_constraint_integrity_error safeguard.
""" """
hass = hass_recorder() await async_setup_component(hass, "sensor", {})
setup_component(hass, "sensor", {})
entity_reg = mock_registry(hass) reg_entry = entity_registry.async_get_or_create(
"sensor",
"test",
"unique_0000",
suggested_object_id="test1",
)
assert reg_entry.entity_id == "sensor.test1"
await hass.async_block_till_done()
@callback zero, four, states = await async_record_states(hass)
def add_entry():
reg_entry = entity_reg.async_get_or_create(
"sensor",
"test",
"unique_0000",
suggested_object_id="test1",
)
assert reg_entry.entity_id == "sensor.test1"
hass.add_job(add_entry)
hass.block_till_done()
zero, four, states = record_states(hass)
hist = history.get_significant_states( hist = history.get_significant_states(
hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"}) hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"})
) )
assert_dict_of_states_equal_without_context_and_last_changed(states, hist) assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
assert len(hist["sensor.test1"]) == 3 assert len(hist["sensor.test1"]) == 3
hass.states.set("sensor.test99", "collision") hass.states.async_set("sensor.test99", "collision")
hass.states.remove("sensor.test99") hass.states.async_remove("sensor.test99")
hass.block_till_done() await hass.async_block_till_done()
wait_recording_done(hass) await async_wait_recording_done(hass)
# Verify history before collision # Verify history before collision
hist = history.get_significant_states( hist = history.get_significant_states(
@ -321,14 +307,10 @@ def test_rename_entity_collision_without_states_meta_safeguard(
# so that we hit the filter_unique_constraint_integrity_error safeguard in the entity_registry # so that we hit the filter_unique_constraint_integrity_error safeguard in the entity_registry
with patch.object(instance.states_meta_manager, "get", return_value=None): with patch.object(instance.states_meta_manager, "get", return_value=None):
# Rename entity sensor.test1 to sensor.test99 # Rename entity sensor.test1 to sensor.test99
@callback entity_registry.async_update_entity(
def rename_entry(): "sensor.test1", new_entity_id="sensor.test99"
entity_reg.async_update_entity( )
"sensor.test1", new_entity_id="sensor.test99" await async_wait_recording_done(hass)
)
hass.add_job(rename_entry)
wait_recording_done(hass)
# History is not migrated on collision # History is not migrated on collision
hist = history.get_significant_states( hist = history.get_significant_states(
@ -340,8 +322,8 @@ def test_rename_entity_collision_without_states_meta_safeguard(
with session_scope(hass=hass) as session: with session_scope(hass=hass) as session:
assert _count_entity_id_in_states_meta(hass, session, "sensor.test99") == 1 assert _count_entity_id_in_states_meta(hass, session, "sensor.test99") == 1
hass.states.set("sensor.test99", "post_migrate") hass.states.async_set("sensor.test99", "post_migrate")
wait_recording_done(hass) await async_wait_recording_done(hass)
new_hist = history.get_significant_states( new_hist = history.get_significant_states(
hass, hass,