diff --git a/tests/components/recorder/common.py b/tests/components/recorder/common.py index e0f43323f25..2ded3513a7e 100644 --- a/tests/components/recorder/common.py +++ b/tests/components/recorder/common.py @@ -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): """Record some test states. diff --git a/tests/components/recorder/test_entity_registry.py b/tests/components/recorder/test_entity_registry.py index 37223f206a1..a74992525b1 100644 --- a/tests/components/recorder/test_entity_registry.py +++ b/tests/components/recorder/test_entity_registry.py @@ -1,6 +1,5 @@ """The tests for sensor recorder platform.""" -from collections.abc import Callable from unittest.mock import patch import pytest @@ -8,23 +7,22 @@ from sqlalchemy import select from sqlalchemy.orm import Session 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.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.setup import setup_component +from homeassistant.setup import async_setup_component from homeassistant.util import dt as dt_util from .common import ( ForceReturnConnectionToPool, assert_dict_of_states_equal_without_context_and_last_changed, + async_record_states, 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 @@ -40,41 +38,44 @@ def _count_entity_id_in_states_meta( ) -def test_rename_entity_without_collision( - hass_recorder: Callable[..., HomeAssistant], caplog: pytest.LogCaptureFixture +@pytest.fixture +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: """Test states meta is migrated when entity_id is changed.""" - hass = hass_recorder() - setup_component(hass, "sensor", {}) + await async_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 - 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) + zero, four, states = await async_record_states(hass) hist = history.get_significant_states( hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"}) ) assert_dict_of_states_equal_without_context_and_last_changed(states, hist) - @callback - def rename_entry(): - entity_reg.async_update_entity("sensor.test1", new_entity_id="sensor.test99") - - hass.add_job(rename_entry) - wait_recording_done(hass) + entity_registry.async_update_entity("sensor.test1", new_entity_id="sensor.test99") + await async_wait_recording_done(hass) hist = history.get_significant_states( 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") assert_dict_of_states_equal_without_context_and_last_changed(states, hist) - hass.states.set("sensor.test99", "post_migrate") - wait_recording_done(hass) + hass.states.async_set("sensor.test99", "post_migrate") + await async_wait_recording_done(hass) new_hist = history.get_significant_states( hass, zero, @@ -101,8 +102,8 @@ def test_rename_entity_without_collision( async def test_rename_entity_on_mocked_platform( - async_setup_recorder_instance: RecorderInstanceGenerator, hass: HomeAssistant, + entity_registry: er.EntityRegistry, caplog: pytest.LogCaptureFixture, ) -> None: """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 when we rename it. """ - instance = await async_setup_recorder_instance(hass) - entity_reg = er.async_get(hass) + instance = recorder.get_instance(hass) start = dt_util.utcnow() - reg_entry = entity_reg.async_get_or_create( + reg_entry = entity_registry.async_get_or_create( "sensor", "test", "unique_0000", @@ -142,7 +142,7 @@ async def test_rename_entity_on_mocked_platform( ["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() # We have to call the remove method ourselves since we are mocking the platform 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 -def test_rename_entity_collision( - hass_recorder: Callable[..., HomeAssistant], caplog: pytest.LogCaptureFixture +async def test_rename_entity_collision( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + caplog: pytest.LogCaptureFixture, ) -> None: """Test states meta is not migrated when there is a collision.""" - hass = hass_recorder() - setup_component(hass, "sensor", {}) + await async_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 - 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) + zero, four, states = await async_record_states(hass) hist = history.get_significant_states( hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"}) ) assert_dict_of_states_equal_without_context_and_last_changed(states, hist) assert len(hist["sensor.test1"]) == 3 - hass.states.set("sensor.test99", "collision") - hass.states.remove("sensor.test99") + hass.states.async_set("sensor.test99", "collision") + hass.states.async_remove("sensor.test99") - hass.block_till_done() + await hass.async_block_till_done() # Rename entity sensor.test1 to sensor.test99 - @callback - def rename_entry(): - entity_reg.async_update_entity("sensor.test1", new_entity_id="sensor.test99") - - hass.add_job(rename_entry) - wait_recording_done(hass) + entity_registry.async_update_entity("sensor.test1", new_entity_id="sensor.test99") + await async_wait_recording_done(hass) # History is not migrated on collision hist = history.get_significant_states( @@ -248,8 +239,8 @@ def test_rename_entity_collision( with session_scope(hass=hass) as session: assert _count_entity_id_in_states_meta(hass, session, "sensor.test99") == 1 - hass.states.set("sensor.test99", "post_migrate") - wait_recording_done(hass) + hass.states.async_set("sensor.test99", "post_migrate") + await async_wait_recording_done(hass) new_hist = history.get_significant_states( hass, zero, @@ -270,44 +261,39 @@ def test_rename_entity_collision( assert "Blocked attempt to insert duplicated state rows" not in caplog.text -def test_rename_entity_collision_without_states_meta_safeguard( - hass_recorder: Callable[..., HomeAssistant], caplog: pytest.LogCaptureFixture +async def test_rename_entity_collision_without_states_meta_safeguard( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + caplog: pytest.LogCaptureFixture, ) -> None: """Test states meta is not migrated when there is a collision. This test disables the safeguard in the states_meta_manager and relies on the filter_unique_constraint_integrity_error safeguard. """ - hass = hass_recorder() - setup_component(hass, "sensor", {}) + await async_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 - 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) + zero, four, states = await async_record_states(hass) hist = history.get_significant_states( hass, zero, four, list(set(states) | {"sensor.test99", "sensor.test1"}) ) assert_dict_of_states_equal_without_context_and_last_changed(states, hist) assert len(hist["sensor.test1"]) == 3 - hass.states.set("sensor.test99", "collision") - hass.states.remove("sensor.test99") + hass.states.async_set("sensor.test99", "collision") + hass.states.async_remove("sensor.test99") - hass.block_till_done() - wait_recording_done(hass) + await hass.async_block_till_done() + await async_wait_recording_done(hass) # Verify history before collision 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 with patch.object(instance.states_meta_manager, "get", return_value=None): # Rename entity sensor.test1 to sensor.test99 - @callback - def rename_entry(): - entity_reg.async_update_entity( - "sensor.test1", new_entity_id="sensor.test99" - ) - - hass.add_job(rename_entry) - wait_recording_done(hass) + entity_registry.async_update_entity( + "sensor.test1", new_entity_id="sensor.test99" + ) + await async_wait_recording_done(hass) # History is not migrated on collision 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: assert _count_entity_id_in_states_meta(hass, session, "sensor.test99") == 1 - hass.states.set("sensor.test99", "post_migrate") - wait_recording_done(hass) + hass.states.async_set("sensor.test99", "post_migrate") + await async_wait_recording_done(hass) new_hist = history.get_significant_states( hass,