From 28c80c11331eaafbac7efc6e39360ddc06954d3e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 15 Mar 2021 08:19:19 -1000 Subject: [PATCH] Ensure recorder purge tests can handle multiple purge cycle (#47956) Since a purge can generate another purge task, we now wait for three recorder queue completions by default. --- tests/components/recorder/common.py | 18 +++++++++++++ tests/components/recorder/test_purge.py | 35 +++++++++++++++---------- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/tests/components/recorder/common.py b/tests/components/recorder/common.py index 79f0f1f00d0..0bc4cfbfeb9 100644 --- a/tests/components/recorder/common.py +++ b/tests/components/recorder/common.py @@ -8,6 +8,8 @@ from homeassistant.util import dt as dt_util from tests.common import async_fire_time_changed, fire_time_changed +DEFAULT_PURGE_TASKS = 3 + def wait_recording_done(hass: HomeAssistantType) -> None: """Block till recording is done.""" @@ -42,6 +44,22 @@ async def async_wait_recording_done( await hass.async_block_till_done() +async def async_wait_purge_done( + hass: HomeAssistantType, instance: recorder.Recorder, max: int = None +) -> None: + """Wait for max number of purge events. + + Because a purge may insert another PurgeTask into + the queue after the WaitTask finishes, we need up to + a maximum number of WaitTasks that we will put into the + queue. + """ + if not max: + max = DEFAULT_PURGE_TASKS + for _ in range(max + 1): + await async_wait_recording_done(hass, instance) + + @ha.callback def async_trigger_db_commit(hass: HomeAssistantType) -> None: """Fore the recorder to commit. Async friendly.""" diff --git a/tests/components/recorder/test_purge.py b/tests/components/recorder/test_purge.py index e6bc3a99a97..bbc16cef825 100644 --- a/tests/components/recorder/test_purge.py +++ b/tests/components/recorder/test_purge.py @@ -12,7 +12,11 @@ from homeassistant.const import EVENT_STATE_CHANGED from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.util import dt as dt_util -from .common import async_recorder_block_till_done, async_wait_recording_done +from .common import ( + async_recorder_block_till_done, + async_wait_purge_done, + async_wait_recording_done, +) from .conftest import SetupRecorderInstanceT @@ -120,12 +124,15 @@ async def test_purge_method( assert recorder_runs.count() == 7 runs_before_purge = recorder_runs.all() + await hass.async_block_till_done() + await async_wait_purge_done(hass, instance) + # run purge method - no service data, use defaults await hass.services.async_call("recorder", "purge") await hass.async_block_till_done() # Small wait for recorder thread - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) # only purged old events assert states.count() == 4 @@ -136,7 +143,7 @@ async def test_purge_method( await hass.async_block_till_done() # Small wait for recorder thread - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) # we should only have 2 states left after purging assert states.count() == 2 @@ -156,7 +163,7 @@ async def test_purge_method( service_data["repack"] = True await hass.services.async_call("recorder", "purge", service_data=service_data) await hass.async_block_till_done() - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) assert "Vacuuming SQL DB to free space" in caplog.text @@ -192,7 +199,7 @@ async def test_purge_edge_case( ) instance = await async_setup_recorder_instance(hass, None) - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) service_data = {"keep_days": 2} timestamp = dt_util.utcnow() - timedelta(days=2, minutes=1) @@ -211,7 +218,7 @@ async def test_purge_edge_case( await hass.async_block_till_done() await async_recorder_block_till_done(hass, instance) - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) assert states.count() == 0 assert events.count() == 0 @@ -329,7 +336,7 @@ async def test_purge_filtered_states( await hass.async_block_till_done() await async_recorder_block_till_done(hass, instance) - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) assert states.count() == 74 assert events_state_changed.count() == 70 @@ -343,10 +350,10 @@ async def test_purge_filtered_states( await hass.async_block_till_done() await async_recorder_block_till_done(hass, instance) - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) await async_recorder_block_till_done(hass, instance) - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) assert states.count() == 13 assert events_state_changed.count() == 10 @@ -419,7 +426,7 @@ async def test_purge_filtered_events( await hass.async_block_till_done() await async_recorder_block_till_done(hass, instance) - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) assert events_purge.count() == 60 assert events_keep.count() == 10 @@ -433,10 +440,10 @@ async def test_purge_filtered_events( await hass.async_block_till_done() await async_recorder_block_till_done(hass, instance) - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) await async_recorder_block_till_done(hass, instance) - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) assert events_purge.count() == 0 assert events_keep.count() == 10 @@ -534,10 +541,10 @@ async def test_purge_filtered_events_state_changed( await hass.async_block_till_done() await async_recorder_block_till_done(hass, instance) - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) await async_recorder_block_till_done(hass, instance) - await async_wait_recording_done(hass, instance) + await async_wait_purge_done(hass, instance) assert events_keep.count() == 10 assert events_purge.count() == 0