From 286a09d737ef3caacf7c9d9c8a317fb719968d0e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 29 Mar 2024 18:16:53 -1000 Subject: [PATCH] Mark executor jobs as background unless created from a tracked task (#114450) * Mark executor jobs as background unless created from a tracked task If the current task is not tracked the executor job should not be a background task to avoid delaying startup and shutdown. Currently any executor job created in a untracked task or background task would end up being tracked and delaying startup/shutdown * import exec has the same issue * Avoid tracking import executor jobs There is no reason to track these jobs as they are always awaited and we do not want to support fire and forget import executor jobs * fix xiaomi_miio * lots of fire time changed without background await * revert changes moved to other PR * more * more * more * m * m * p * fix fire and forget tests * scrape * sonos * system * more * capture callback before block * coverage * more * more races * more races * more * missed some * more fixes * missed some more * fix * remove unneeded * one more race * two --- homeassistant/core.py | 7 +++- .../aurora_abb_powerone/test_sensor.py | 8 ++-- tests/components/cast/test_config_flow.py | 4 +- tests/components/cast/test_media_player.py | 8 ++-- tests/components/fritz/test_image.py | 4 +- tests/components/fritz/test_sensor.py | 2 +- .../components/fritzbox/test_binary_sensor.py | 6 +-- tests/components/fritzbox/test_button.py | 2 +- tests/components/fritzbox/test_climate.py | 12 +++--- tests/components/fritzbox/test_cover.py | 2 +- tests/components/fritzbox/test_light.py | 6 +-- tests/components/fritzbox/test_sensor.py | 6 +-- tests/components/fritzbox/test_switch.py | 6 +-- .../components/geo_rss_events/test_sensor.py | 4 +- tests/components/google_mail/test_sensor.py | 4 +- .../maxcube/test_maxcube_binary_sensor.py | 6 +-- .../maxcube/test_maxcube_climate.py | 22 +++++----- tests/components/metoffice/test_weather.py | 10 ++--- .../mikrotik/test_device_tracker.py | 8 ++-- .../components/monoprice/test_media_player.py | 18 ++++----- .../panasonic_viera/test_media_player.py | 4 +- tests/components/pjlink/test_media_player.py | 4 +- tests/components/profiler/test_init.py | 10 ++--- tests/components/ps4/test_media_player.py | 2 + tests/components/python_script/test_init.py | 40 +++++++++---------- .../components/samsungtv/test_media_player.py | 10 ++--- .../components/schlage/test_binary_sensor.py | 4 +- tests/components/schlage/test_lock.py | 2 +- tests/components/scrape/test_sensor.py | 12 +++--- .../components/solaredge/test_coordinator.py | 10 ++--- tests/components/sonos/conftest.py | 3 +- tests/components/sonos/test_repairs.py | 5 ++- tests/components/sonos/test_sensor.py | 29 +++++++++----- tests/components/sonos/test_speaker.py | 16 +++++++- .../soundtouch/test_media_player.py | 2 +- tests/components/speedtestdotnet/test_init.py | 2 +- .../systemmonitor/test_binary_sensor.py | 2 +- tests/components/systemmonitor/test_sensor.py | 22 +++++----- tests/components/tcp/test_binary_sensor.py | 2 +- tests/components/temper/test_sensor.py | 2 +- .../totalconnect/test_alarm_control_panel.py | 10 ++--- tests/components/uvc/test_camera.py | 12 +++--- tests/components/ws66i/test_media_player.py | 20 +++++----- tests/components/xiaomi_miio/test_vacuum.py | 4 +- .../yale_smart_alarm/test_coordinator.py | 12 +++--- tests/test_core.py | 40 +++++++++++++++++++ 46 files changed, 246 insertions(+), 180 deletions(-) diff --git a/homeassistant/core.py b/homeassistant/core.py index 2ed4de35925..4794b284fd2 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -774,8 +774,11 @@ class HomeAssistant: ) -> asyncio.Future[_T]: """Add an executor job from within the event loop.""" task = self.loop.run_in_executor(None, target, *args) - self._tasks.add(task) - task.add_done_callback(self._tasks.remove) + + tracked = asyncio.current_task() in self._tasks + task_bucket = self._tasks if tracked else self._background_tasks + task_bucket.add(task) + task.add_done_callback(task_bucket.remove) return task diff --git a/tests/components/aurora_abb_powerone/test_sensor.py b/tests/components/aurora_abb_powerone/test_sensor.py index 178cf165f67..4bc5a5d3086 100644 --- a/tests/components/aurora_abb_powerone/test_sensor.py +++ b/tests/components/aurora_abb_powerone/test_sensor.py @@ -201,7 +201,7 @@ async def test_sensor_dark(hass: HomeAssistant, freezer: FrozenDateTimeFactory) ): freezer.tick(SCAN_INTERVAL * 2) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) power = hass.states.get("sensor.mydevicename_total_energy") assert power.state == "unknown" # sun rose again @@ -218,7 +218,7 @@ async def test_sensor_dark(hass: HomeAssistant, freezer: FrozenDateTimeFactory) ): freezer.tick(SCAN_INTERVAL * 4) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) power = hass.states.get("sensor.mydevicename_power_output") assert power is not None assert power.state == "45.7" @@ -237,7 +237,7 @@ async def test_sensor_dark(hass: HomeAssistant, freezer: FrozenDateTimeFactory) ): freezer.tick(SCAN_INTERVAL * 6) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) power = hass.states.get("sensor.mydevicename_power_output") assert power.state == "unknown" # should this be 'available'? @@ -277,7 +277,7 @@ async def test_sensor_unknown_error( ): freezer.tick(SCAN_INTERVAL * 2) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert ( "Exception: AuroraError('another error') occurred, 2 retries remaining" in caplog.text diff --git a/tests/components/cast/test_config_flow.py b/tests/components/cast/test_config_flow.py index 62c21fc95ee..a7b9311e88b 100644 --- a/tests/components/cast/test_config_flow.py +++ b/tests/components/cast/test_config_flow.py @@ -278,7 +278,7 @@ async def test_known_hosts(hass: HomeAssistant, castbrowser_mock) -> None: result["flow_id"], {"known_hosts": "192.168.0.1, 192.168.0.2"} ) assert result["type"] == "create_entry" - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) config_entry = hass.config_entries.async_entries("cast")[0] assert castbrowser_mock.return_value.start_discovery.call_count == 1 @@ -291,7 +291,7 @@ async def test_known_hosts(hass: HomeAssistant, castbrowser_mock) -> None: user_input={"known_hosts": "192.168.0.11, 192.168.0.12"}, ) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) castbrowser_mock.return_value.start_discovery.assert_not_called() castbrowser_mock.assert_not_called() diff --git a/tests/components/cast/test_media_player.py b/tests/components/cast/test_media_player.py index 9ef31457d5c..8381f27398a 100644 --- a/tests/components/cast/test_media_player.py +++ b/tests/components/cast/test_media_player.py @@ -137,8 +137,8 @@ async def async_setup_cast_internal_discovery(hass, config=None): return_value=browser, ) as cast_browser: add_entities = await async_setup_cast(hass, config) - await hass.async_block_till_done() - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) + await hass.async_block_till_done(wait_background_tasks=True) assert browser.start_discovery.call_count == 1 @@ -209,8 +209,8 @@ async def async_setup_media_player_cast(hass: HomeAssistant, info: ChromecastInf entry = MockConfigEntry(data=data, domain="cast") entry.add_to_hass(hass) assert await hass.config_entries.async_setup(entry.entry_id) - await hass.async_block_till_done() - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) + await hass.async_block_till_done(wait_background_tasks=True) discovery_callback = cast_browser.call_args[0][0].add_cast diff --git a/tests/components/fritz/test_image.py b/tests/components/fritz/test_image.py index 85d02eff153..5d6b9265760 100644 --- a/tests/components/fritz/test_image.py +++ b/tests/components/fritz/test_image.py @@ -199,7 +199,7 @@ async def test_image_update_unavailable( # fritzbox becomes unavailable fc_class_mock().call_action_side_effect(ReadTimeout) async_fire_time_changed(hass, utcnow() + timedelta(seconds=60)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("image.mock_title_guestwifi") assert state.state == STATE_UNKNOWN @@ -207,7 +207,7 @@ async def test_image_update_unavailable( # fritzbox is available again fc_class_mock().call_action_side_effect(None) async_fire_time_changed(hass, utcnow() + timedelta(seconds=60)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("image.mock_title_guestwifi") assert state.state != STATE_UNKNOWN diff --git a/tests/components/fritz/test_sensor.py b/tests/components/fritz/test_sensor.py index 4427fc6961e..37116e66719 100644 --- a/tests/components/fritz/test_sensor.py +++ b/tests/components/fritz/test_sensor.py @@ -134,7 +134,7 @@ async def test_sensor_update_fail( fc_class_mock().call_action_side_effect(FritzConnectionException) async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=300)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) sensors = hass.states.async_all(SENSOR_DOMAIN) for sensor in sensors: diff --git a/tests/components/fritzbox/test_binary_sensor.py b/tests/components/fritzbox/test_binary_sensor.py index 3828cedc67f..3e1a2691f67 100644 --- a/tests/components/fritzbox/test_binary_sensor.py +++ b/tests/components/fritzbox/test_binary_sensor.py @@ -104,7 +104,7 @@ async def test_update(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert fritz().update_devices.call_count == 2 assert fritz().login.call_count == 1 @@ -123,7 +123,7 @@ async def test_update_error(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert fritz().update_devices.call_count == 2 assert fritz().login.call_count == 1 @@ -146,7 +146,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(f"{DOMAIN}.new_device_alarm") assert state diff --git a/tests/components/fritzbox/test_button.py b/tests/components/fritzbox/test_button.py index f254b2e0710..89e8d8357dd 100644 --- a/tests/components/fritzbox/test_button.py +++ b/tests/components/fritzbox/test_button.py @@ -65,7 +65,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(f"{DOMAIN}.new_template") assert state diff --git a/tests/components/fritzbox/test_climate.py b/tests/components/fritzbox/test_climate.py index a201eab3665..073a67f22c1 100644 --- a/tests/components/fritzbox/test_climate.py +++ b/tests/components/fritzbox/test_climate.py @@ -145,7 +145,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_next_scheduled_preset") assert state @@ -203,7 +203,7 @@ async def test_update(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert fritz().update_devices.call_count == 2 @@ -243,7 +243,7 @@ async def test_update_error(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert fritz().update_devices.call_count == 4 assert fritz().login.call_count == 4 @@ -386,7 +386,7 @@ async def test_preset_mode_update(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert fritz().update_devices.call_count == 2 @@ -397,7 +397,7 @@ async def test_preset_mode_update(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert fritz().update_devices.call_count == 3 @@ -422,7 +422,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(f"{DOMAIN}.new_climate") assert state diff --git a/tests/components/fritzbox/test_cover.py b/tests/components/fritzbox/test_cover.py index b723ac97d06..6c301fc8f46 100644 --- a/tests/components/fritzbox/test_cover.py +++ b/tests/components/fritzbox/test_cover.py @@ -108,7 +108,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(f"{DOMAIN}.new_climate") assert state diff --git a/tests/components/fritzbox/test_light.py b/tests/components/fritzbox/test_light.py index b750a2e9275..45920c7c3ee 100644 --- a/tests/components/fritzbox/test_light.py +++ b/tests/components/fritzbox/test_light.py @@ -237,7 +237,7 @@ async def test_update(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert fritz().update_devices.call_count == 2 assert fritz().login.call_count == 1 @@ -259,7 +259,7 @@ async def test_update_error(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert fritz().update_devices.call_count == 4 assert fritz().login.call_count == 4 @@ -294,7 +294,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(f"{DOMAIN}.new_light") assert state diff --git a/tests/components/fritzbox/test_sensor.py b/tests/components/fritzbox/test_sensor.py index 48b769eaac2..63d0b67d7f4 100644 --- a/tests/components/fritzbox/test_sensor.py +++ b/tests/components/fritzbox/test_sensor.py @@ -87,7 +87,7 @@ async def test_update(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert fritz().update_devices.call_count == 2 assert fritz().login.call_count == 1 @@ -105,7 +105,7 @@ async def test_update_error(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert fritz().update_devices.call_count == 4 assert fritz().login.call_count == 4 @@ -128,7 +128,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(f"{DOMAIN}.new_device_temperature") assert state diff --git a/tests/components/fritzbox/test_switch.py b/tests/components/fritzbox/test_switch.py index 67393bc09a5..417b355b396 100644 --- a/tests/components/fritzbox/test_switch.py +++ b/tests/components/fritzbox/test_switch.py @@ -151,7 +151,7 @@ async def test_update(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert fritz().update_devices.call_count == 2 assert fritz().login.call_count == 1 @@ -169,7 +169,7 @@ async def test_update_error(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert fritz().update_devices.call_count == 4 assert fritz().login.call_count == 4 @@ -207,7 +207,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None: next_update = dt_util.utcnow() + timedelta(seconds=200) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(f"{DOMAIN}.new_switch") assert state diff --git a/tests/components/geo_rss_events/test_sensor.py b/tests/components/geo_rss_events/test_sensor.py index 76f1709bd75..d19262c3339 100644 --- a/tests/components/geo_rss_events/test_sensor.py +++ b/tests/components/geo_rss_events/test_sensor.py @@ -99,7 +99,7 @@ async def test_setup( # so no changes to entities. mock_feed.return_value.update.return_value = "OK_NO_DATA", None async_fire_time_changed(hass, utcnow + geo_rss_events.SCAN_INTERVAL) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) all_states = hass.states.async_all() assert len(all_states) == 1 @@ -109,7 +109,7 @@ async def test_setup( # Simulate an update - empty data, removes all entities mock_feed.return_value.update.return_value = "ERROR", None async_fire_time_changed(hass, utcnow + 2 * geo_rss_events.SCAN_INTERVAL) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) all_states = hass.states.async_all() assert len(all_states) == 1 diff --git a/tests/components/google_mail/test_sensor.py b/tests/components/google_mail/test_sensor.py index e0b072d4b7d..6f2f1a4ec32 100644 --- a/tests/components/google_mail/test_sensor.py +++ b/tests/components/google_mail/test_sensor.py @@ -46,7 +46,7 @@ async def test_sensors( ): next_update = dt_util.utcnow() + timedelta(minutes=15) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(SENSOR) assert state.state == result @@ -61,7 +61,7 @@ async def test_sensor_reauth_trigger( with patch(TOKEN, side_effect=RefreshError): next_update = dt_util.utcnow() + timedelta(minutes=15) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) flows = hass.config_entries.flow.async_progress() diff --git a/tests/components/maxcube/test_maxcube_binary_sensor.py b/tests/components/maxcube/test_maxcube_binary_sensor.py index cc86f389884..32ec4e92ee1 100644 --- a/tests/components/maxcube/test_maxcube_binary_sensor.py +++ b/tests/components/maxcube/test_maxcube_binary_sensor.py @@ -43,7 +43,7 @@ async def test_window_shuttler( windowshutter.is_open = False async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == STATE_OFF @@ -68,12 +68,12 @@ async def test_window_shuttler_battery( windowshutter.battery = 1 # maxcube-api MAX_DEVICE_BATTERY_LOW async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(BATTERY_ENTITY_ID) assert state.state == STATE_ON # on means low windowshutter.battery = 0 # maxcube-api MAX_DEVICE_BATTERY_OK async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(BATTERY_ENTITY_ID) assert state.state == STATE_OFF # off means normal diff --git a/tests/components/maxcube/test_maxcube_climate.py b/tests/components/maxcube/test_maxcube_climate.py index cb4dc510605..e1e7dc57c47 100644 --- a/tests/components/maxcube/test_maxcube_climate.py +++ b/tests/components/maxcube/test_maxcube_climate.py @@ -140,7 +140,7 @@ async def test_thermostat_set_hvac_mode_off( thermostat.valve_position = 0 async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == HVACMode.OFF @@ -168,8 +168,8 @@ async def test_thermostat_set_hvac_mode_heat( thermostat.mode = MAX_DEVICE_MODE_MANUAL async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == HVACMode.HEAT @@ -204,7 +204,7 @@ async def test_thermostat_set_temperature( thermostat.valve_position = 0 async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == HVACMode.AUTO @@ -248,7 +248,7 @@ async def test_thermostat_set_preset_on( thermostat.target_temperature = ON_TEMPERATURE async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == HVACMode.HEAT @@ -273,7 +273,7 @@ async def test_thermostat_set_preset_comfort( thermostat.target_temperature = thermostat.comfort_temperature async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == HVACMode.HEAT @@ -298,7 +298,7 @@ async def test_thermostat_set_preset_eco( thermostat.target_temperature = thermostat.eco_temperature async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == HVACMode.HEAT @@ -323,7 +323,7 @@ async def test_thermostat_set_preset_away( thermostat.target_temperature = thermostat.eco_temperature async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == HVACMode.HEAT @@ -348,7 +348,7 @@ async def test_thermostat_set_preset_boost( thermostat.target_temperature = thermostat.eco_temperature async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == HVACMode.AUTO @@ -401,7 +401,7 @@ async def test_wallthermostat_set_hvac_mode_heat( wallthermostat.target_temperature = MIN_TEMPERATURE async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(WALL_ENTITY_ID) assert state.state == HVACMode.HEAT @@ -425,7 +425,7 @@ async def test_wallthermostat_set_hvac_mode_auto( wallthermostat.target_temperature = 23.0 async_fire_time_changed(hass, utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(WALL_ENTITY_ID) assert state.state == HVACMode.AUTO diff --git a/tests/components/metoffice/test_weather.py b/tests/components/metoffice/test_weather.py index 2aa673d4010..64a85897738 100644 --- a/tests/components/metoffice/test_weather.py +++ b/tests/components/metoffice/test_weather.py @@ -125,7 +125,7 @@ async def test_site_cannot_update( future_time = utcnow() + timedelta(minutes=20) async_fire_time_changed(hass, future_time) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) weather = hass.states.get("weather.met_office_wavertree_daily") assert weather.state == STATE_UNAVAILABLE @@ -297,7 +297,7 @@ async def test_forecast_service( # Trigger data refetch freezer.tick(DEFAULT_SCAN_INTERVAL + timedelta(seconds=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert wavertree_data["wavertree_daily_mock"].call_count == 2 assert wavertree_data["wavertree_hourly_mock"].call_count == 1 @@ -324,7 +324,7 @@ async def test_forecast_service( freezer.tick(DEFAULT_SCAN_INTERVAL + timedelta(seconds=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) response = await hass.services.async_call( WEATHER_DOMAIN, @@ -412,7 +412,7 @@ async def test_forecast_subscription( freezer.tick(DEFAULT_SCAN_INTERVAL + timedelta(seconds=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) msg = await client.receive_json() assert msg["id"] == subscription_id @@ -430,6 +430,6 @@ async def test_forecast_subscription( ) freezer.tick(timedelta(seconds=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) msg = await client.receive_json() assert msg["success"] diff --git a/tests/components/mikrotik/test_device_tracker.py b/tests/components/mikrotik/test_device_tracker.py index 47ddc038f69..89dc37fd781 100644 --- a/tests/components/mikrotik/test_device_tracker.py +++ b/tests/components/mikrotik/test_device_tracker.py @@ -88,7 +88,7 @@ async def test_device_trackers( WIRELESS_DATA.append(DEVICE_2_WIRELESS) async_fire_time_changed(hass, utcnow() + timedelta(seconds=10)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) device_2 = hass.states.get("device_tracker.device_2") assert device_2 @@ -101,7 +101,7 @@ async def test_device_trackers( del WIRELESS_DATA[1] # device 2 is removed from wireless list with freeze_time(utcnow() + timedelta(minutes=4)): async_fire_time_changed(hass, utcnow() + timedelta(minutes=4)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) device_2 = hass.states.get("device_tracker.device_2") assert device_2 @@ -110,7 +110,7 @@ async def test_device_trackers( # test state changes to away if last_seen past consider_home_interval with freeze_time(utcnow() + timedelta(minutes=6)): async_fire_time_changed(hass, utcnow() + timedelta(minutes=6)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) device_2 = hass.states.get("device_tracker.device_2") assert device_2 @@ -266,7 +266,7 @@ async def test_update_failed(hass: HomeAssistant, mock_device_registry_devices) mikrotik.hub.MikrotikData, "command", side_effect=mikrotik.errors.CannotConnect ): async_fire_time_changed(hass, utcnow() + timedelta(seconds=10)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) device_1 = hass.states.get("device_tracker.device_1") assert device_1 diff --git a/tests/components/monoprice/test_media_player.py b/tests/components/monoprice/test_media_player.py index a0afd37f3b2..f7d88692cf5 100644 --- a/tests/components/monoprice/test_media_player.py +++ b/tests/components/monoprice/test_media_player.py @@ -183,7 +183,7 @@ async def test_service_calls_with_entity_id(hass: HomeAssistant) -> None: # Restoring other media player to its previous state # The zone should not be restored await _call_monoprice_service(hass, SERVICE_RESTORE, {"entity_id": ZONE_2_ID}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) # Checking that values were not (!) restored state = hass.states.get(ZONE_1_ID) @@ -193,7 +193,7 @@ async def test_service_calls_with_entity_id(hass: HomeAssistant) -> None: # Restoring media player to its previous state await _call_monoprice_service(hass, SERVICE_RESTORE, {"entity_id": ZONE_1_ID}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ZONE_1_ID) @@ -226,7 +226,7 @@ async def test_service_calls_with_all_entities(hass: HomeAssistant) -> None: # Restoring media player to its previous state await _call_monoprice_service(hass, SERVICE_RESTORE, {"entity_id": "all"}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ZONE_1_ID) @@ -259,7 +259,7 @@ async def test_service_calls_without_relevant_entities(hass: HomeAssistant) -> N # Restoring media player to its previous state await _call_monoprice_service(hass, SERVICE_RESTORE, {"entity_id": "light.demo"}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ZONE_1_ID) @@ -273,7 +273,7 @@ async def test_restore_without_snapshort(hass: HomeAssistant) -> None: with patch.object(MockMonoprice, "restore_zone") as method_call: await _call_monoprice_service(hass, SERVICE_RESTORE, {"entity_id": ZONE_1_ID}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert not method_call.called @@ -295,7 +295,7 @@ async def test_update(hass: HomeAssistant) -> None: monoprice.set_volume(11, 38) await async_update_entity(hass, ZONE_1_ID) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ZONE_1_ID) @@ -321,7 +321,7 @@ async def test_failed_update(hass: HomeAssistant) -> None: with patch.object(MockMonoprice, "zone_status", side_effect=SerialException): await async_update_entity(hass, ZONE_1_ID) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ZONE_1_ID) @@ -347,7 +347,7 @@ async def test_empty_update(hass: HomeAssistant) -> None: with patch.object(MockMonoprice, "zone_status", return_value=None): await async_update_entity(hass, ZONE_1_ID) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ZONE_1_ID) @@ -418,7 +418,7 @@ async def test_unknown_source(hass: HomeAssistant) -> None: monoprice.set_source(11, 5) await async_update_entity(hass, ZONE_1_ID) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ZONE_1_ID) diff --git a/tests/components/panasonic_viera/test_media_player.py b/tests/components/panasonic_viera/test_media_player.py index 1203bf1ed51..dab56542e6a 100644 --- a/tests/components/panasonic_viera/test_media_player.py +++ b/tests/components/panasonic_viera/test_media_player.py @@ -23,7 +23,7 @@ async def test_media_player_handle_URLerror( mock_remote.get_mute = Mock(side_effect=URLError(None, None)) async_fire_time_changed(hass, utcnow() + timedelta(minutes=2)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state_tv = hass.states.get("media_player.panasonic_viera_tv") assert state_tv.state == STATE_UNAVAILABLE @@ -41,7 +41,7 @@ async def test_media_player_handle_HTTPError( mock_remote.get_mute = Mock(side_effect=HTTPError(None, 400, None, None, None)) async_fire_time_changed(hass, utcnow() + timedelta(minutes=2)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state_tv = hass.states.get("media_player.panasonic_viera_tv") assert state_tv.state == STATE_OFF diff --git a/tests/components/pjlink/test_media_player.py b/tests/components/pjlink/test_media_player.py index a6d17233450..d44bc942290 100644 --- a/tests/components/pjlink/test_media_player.py +++ b/tests/components/pjlink/test_media_player.py @@ -208,7 +208,7 @@ async def test_update_unavailable(projector_from_address, hass: HomeAssistant) - projector_from_address.side_effect = socket.timeout async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("media_player.test") assert state.state == "unavailable" @@ -237,7 +237,7 @@ async def test_unavailable_time(mocked_projector, hass: HomeAssistant) -> None: mocked_projector.get_power.side_effect = ProjectorError("unavailable time") async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("media_player.test") assert state.state == "off" diff --git a/tests/components/profiler/test_init.py b/tests/components/profiler/test_init.py index 1140dc74849..3cade465347 100644 --- a/tests/components/profiler/test_init.py +++ b/tests/components/profiler/test_init.py @@ -332,7 +332,7 @@ async def test_log_object_sources( caplog.clear() async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=11)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert "No new object growth found" in caplog.text fake_object2 = FakeObject() @@ -344,7 +344,7 @@ async def test_log_object_sources( caplog.clear() async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=21)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert "New object FakeObject (1/2)" in caplog.text many_objects = [FakeObject() for _ in range(30)] @@ -352,7 +352,7 @@ async def test_log_object_sources( caplog.clear() async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=31)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert "New object FakeObject (2/30)" in caplog.text assert "New objects overflowed by {'FakeObject': 25}" in caplog.text @@ -362,7 +362,7 @@ async def test_log_object_sources( caplog.clear() async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=41)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert "FakeObject" not in caplog.text assert "No new object growth found" not in caplog.text @@ -370,7 +370,7 @@ async def test_log_object_sources( await hass.async_block_till_done() async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=51)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert "FakeObject" not in caplog.text assert "No new object growth found" not in caplog.text diff --git a/tests/components/ps4/test_media_player.py b/tests/components/ps4/test_media_player.py index 875b049d8c3..6adcad03016 100644 --- a/tests/components/ps4/test_media_player.py +++ b/tests/components/ps4/test_media_player.py @@ -234,6 +234,7 @@ async def test_media_attributes_are_fetched(hass: HomeAssistant) -> None: with patch(mock_func, return_value=mock_result) as mock_fetch: await mock_ddp_response(hass, MOCK_STATUS_PLAYING) + await hass.async_block_till_done(wait_background_tasks=True) mock_state = hass.states.get(mock_entity_id) mock_attrs = dict(mock_state.attributes) @@ -255,6 +256,7 @@ async def test_media_attributes_are_fetched(hass: HomeAssistant) -> None: with patch(mock_func, return_value=mock_result) as mock_fetch_app: await mock_ddp_response(hass, MOCK_STATUS_PLAYING) + await hass.async_block_till_done(wait_background_tasks=True) mock_state = hass.states.get(mock_entity_id) mock_attrs = dict(mock_state.attributes) diff --git a/tests/components/python_script/test_init.py b/tests/components/python_script/test_init.py index bec94db71f9..1c6fead6c4a 100644 --- a/tests/components/python_script/test_init.py +++ b/tests/components/python_script/test_init.py @@ -78,7 +78,7 @@ hass.states.set('test.entity', data.get('name', 'not set')) """ hass.async_add_executor_job(execute, hass, "test.py", source, {"name": "paulus"}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.is_state("test.entity", "paulus") @@ -96,7 +96,7 @@ print("This triggers warning.") """ hass.async_add_executor_job(execute, hass, "test.py", source, {}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert "Don't use print() inside scripts." in caplog.text @@ -111,7 +111,7 @@ logger.info('Logging from inside script') """ hass.async_add_executor_job(execute, hass, "test.py", source, {}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert "Logging from inside script" in caplog.text @@ -126,7 +126,7 @@ this is not valid Python """ hass.async_add_executor_job(execute, hass, "test.py", source, {}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert "Error loading script test.py" in caplog.text @@ -140,8 +140,8 @@ async def test_execute_runtime_error( raise Exception('boom') """ - hass.async_add_executor_job(execute, hass, "test.py", source, {}) - await hass.async_block_till_done() + await hass.async_add_executor_job(execute, hass, "test.py", source, {}) + await hass.async_block_till_done(wait_background_tasks=True) assert "Error executing script: boom" in caplog.text @@ -153,7 +153,7 @@ raise Exception('boom') """ task = hass.async_add_executor_job(execute, hass, "test.py", source, {}, True) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert type(task.exception()) == HomeAssistantError assert "Error executing script (Exception): boom" in str(task.exception()) @@ -168,7 +168,7 @@ async def test_accessing_async_methods( hass.async_stop() """ - hass.async_add_executor_job(execute, hass, "test.py", source, {}) + await hass.async_add_executor_job(execute, hass, "test.py", source, {}) await hass.async_block_till_done() assert "Not allowed to access async methods" in caplog.text @@ -181,7 +181,7 @@ hass.async_stop() """ task = hass.async_add_executor_job(execute, hass, "test.py", source, {}, True) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert type(task.exception()) == ServiceValidationError assert "Not allowed to access async methods" in str(task.exception()) @@ -198,7 +198,7 @@ mylist = [1, 2, 3, 4] logger.info('Logging from inside script: %s %s' % (mydict["a"], mylist[2])) """ - hass.async_add_executor_job(execute, hass, "test.py", source, {}) + await hass.async_add_executor_job(execute, hass, "test.py", source, {}) await hass.async_block_till_done() assert "Logging from inside script: 1 3" in caplog.text @@ -217,7 +217,7 @@ async def test_accessing_forbidden_methods( "time.tzset()": "TimeWrapper.tzset", }.items(): caplog.records.clear() - hass.async_add_executor_job(execute, hass, "test.py", source, {}) + await hass.async_add_executor_job(execute, hass, "test.py", source, {}) await hass.async_block_till_done() assert f"Not allowed to access {name}" in caplog.text @@ -231,7 +231,7 @@ async def test_accessing_forbidden_methods_with_response(hass: HomeAssistant) -> "time.tzset()": "TimeWrapper.tzset", }.items(): task = hass.async_add_executor_job(execute, hass, "test.py", source, {}, True) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert type(task.exception()) == ServiceValidationError assert f"Not allowed to access {name}" in str(task.exception()) @@ -244,7 +244,7 @@ for i in [1, 2]: hass.states.set('hello.{}'.format(i), 'world') """ - hass.async_add_executor_job(execute, hass, "test.py", source, {}) + await hass.async_add_executor_job(execute, hass, "test.py", source, {}) await hass.async_block_till_done() assert hass.states.is_state("hello.1", "world") @@ -279,7 +279,7 @@ hass.states.set('hello.ab_list', '{}'.format(ab_list)) """ hass.async_add_executor_job(execute, hass, "test.py", source, {}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.is_state("hello.a", "1") assert hass.states.is_state("hello.b", "2") @@ -302,7 +302,7 @@ hass.states.set('hello.b', a[1]) hass.states.set('hello.c', a[2]) """ hass.async_add_executor_job(execute, hass, "test.py", source, {}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.is_state("hello.a", "1") assert hass.states.is_state("hello.b", "2") @@ -325,7 +325,7 @@ hass.states.set('module.datetime', """ hass.async_add_executor_job(execute, hass, "test.py", source, {}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.is_state("module.time", "1986") assert hass.states.is_state("module.time_strptime", "12:34") @@ -351,7 +351,7 @@ def b(): b() """ hass.async_add_executor_job(execute, hass, "test.py", source, {}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.is_state("hello.a", "one") assert hass.states.is_state("hello.b", "two") @@ -517,7 +517,7 @@ time.sleep(5) with patch("homeassistant.components.python_script.time.sleep"): hass.async_add_executor_job(execute, hass, "test.py", source, {}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert caplog.text.count("time.sleep") == 1 @@ -664,7 +664,7 @@ hass.states.set('hello.c', c) """ hass.async_add_executor_job(execute, hass, "aug_assign.py", source, {}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.get("hello.a").state == str(((10 + 20) * 5) - 8) assert hass.states.get("hello.b").state == ("foo" + "bar") * 2 @@ -686,5 +686,5 @@ async def test_prohibited_augmented_assignment_operations( ) -> None: """Test that prohibited augmented assignment operations raise an error.""" hass.async_add_executor_job(execute, hass, "aug_assign_prohibited.py", case, {}) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert error in caplog.text diff --git a/tests/components/samsungtv/test_media_player.py b/tests/components/samsungtv/test_media_player.py index f874b92305b..db4f3f0e41f 100644 --- a/tests/components/samsungtv/test_media_player.py +++ b/tests/components/samsungtv/test_media_player.py @@ -200,7 +200,7 @@ async def test_setup_websocket_2( next_update = mock_now + timedelta(minutes=5) freezer.move_to(next_update) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(entity_id) assert state @@ -225,7 +225,7 @@ async def test_setup_encrypted_websocket( next_update = mock_now + timedelta(minutes=5) freezer.move_to(next_update) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state @@ -242,7 +242,7 @@ async def test_update_on( next_update = mock_now + timedelta(minutes=5) freezer.move_to(next_update) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == STATE_ON @@ -262,7 +262,7 @@ async def test_update_off( next_update = mock_now + timedelta(minutes=5) freezer.move_to(next_update) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == STATE_UNAVAILABLE @@ -290,7 +290,7 @@ async def test_update_off_ws_no_power_state( next_update = mock_now + timedelta(minutes=5) freezer.move_to(next_update) async_fire_time_changed(hass, next_update) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ENTITY_ID) assert state.state == STATE_OFF diff --git a/tests/components/schlage/test_binary_sensor.py b/tests/components/schlage/test_binary_sensor.py index 4673f263c8c..97f11577b86 100644 --- a/tests/components/schlage/test_binary_sensor.py +++ b/tests/components/schlage/test_binary_sensor.py @@ -22,7 +22,7 @@ async def test_keypad_disabled_binary_sensor( # Make the coordinator refresh data. async_fire_time_changed(hass, utcnow() + timedelta(seconds=31)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) keypad = hass.states.get("binary_sensor.vault_door_keypad_disabled") assert keypad is not None @@ -43,7 +43,7 @@ async def test_keypad_disabled_binary_sensor_use_previous_logs_on_failure( # Make the coordinator refresh data. async_fire_time_changed(hass, utcnow() + timedelta(seconds=31)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) keypad = hass.states.get("binary_sensor.vault_door_keypad_disabled") assert keypad is not None diff --git a/tests/components/schlage/test_lock.py b/tests/components/schlage/test_lock.py index 0972aa97033..5b26da7b27e 100644 --- a/tests/components/schlage/test_lock.py +++ b/tests/components/schlage/test_lock.py @@ -59,7 +59,7 @@ async def test_changed_by( # Make the coordinator refresh data. async_fire_time_changed(hass, utcnow() + timedelta(seconds=31)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) mock_lock.last_changed_by.assert_called_once_with() lock_device = hass.states.get("lock.vault_door") diff --git a/tests/components/scrape/test_sensor.py b/tests/components/scrape/test_sensor.py index 41da2eb9a79..4d9c2b732dc 100644 --- a/tests/components/scrape/test_sensor.py +++ b/tests/components/scrape/test_sensor.py @@ -261,7 +261,7 @@ async def test_scrape_sensor_no_data_refresh(hass: HomeAssistant) -> None: mocker.payload = "test_scrape_sensor_no_data" async_fire_time_changed(hass, dt_util.utcnow() + DEFAULT_SCAN_INTERVAL) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.ha_version") assert state is not None @@ -541,7 +541,7 @@ async def test_templates_with_yaml(hass: HomeAssistant) -> None: hass, dt_util.utcnow() + timedelta(minutes=10), ) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.get_values_with_template") assert state.state == "Current Version: 2021.12.10" @@ -555,7 +555,7 @@ async def test_templates_with_yaml(hass: HomeAssistant) -> None: hass, dt_util.utcnow() + timedelta(minutes=20), ) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.get_values_with_template") assert state.state == STATE_UNAVAILABLE @@ -568,7 +568,7 @@ async def test_templates_with_yaml(hass: HomeAssistant) -> None: hass, dt_util.utcnow() + timedelta(minutes=30), ) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.get_values_with_template") assert state.state == "Current Version: 2021.12.10" @@ -608,7 +608,7 @@ async def test_availability( hass.states.async_set("sensor.input1", "on") freezer.tick(timedelta(minutes=10)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.current_version") assert state.state == "2021.12.10" @@ -618,7 +618,7 @@ async def test_availability( freezer.tick(timedelta(minutes=10)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.current_version") assert state.state == STATE_UNAVAILABLE diff --git a/tests/components/solaredge/test_coordinator.py b/tests/components/solaredge/test_coordinator.py index 4bd9dee930c..b1496d18d93 100644 --- a/tests/components/solaredge/test_coordinator.py +++ b/tests/components/solaredge/test_coordinator.py @@ -53,7 +53,7 @@ async def test_solaredgeoverviewdataservice_energy_values_validity( mock_solaredge().get_overview.return_value = mock_overview_data freezer.tick(OVERVIEW_UPDATE_DELAY) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.solaredge_lifetime_energy") assert state assert state.state == str(mock_overview_data["overview"]["lifeTimeData"]["energy"]) @@ -63,7 +63,7 @@ async def test_solaredgeoverviewdataservice_energy_values_validity( mock_solaredge().get_overview.return_value = mock_overview_data freezer.tick(OVERVIEW_UPDATE_DELAY) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.solaredge_lifetime_energy") assert state @@ -74,7 +74,7 @@ async def test_solaredgeoverviewdataservice_energy_values_validity( mock_solaredge().get_overview.return_value = mock_overview_data freezer.tick(OVERVIEW_UPDATE_DELAY) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.solaredge_lifetime_energy") assert state @@ -85,7 +85,7 @@ async def test_solaredgeoverviewdataservice_energy_values_validity( mock_solaredge().get_overview.return_value = mock_overview_data freezer.tick(OVERVIEW_UPDATE_DELAY) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.solaredge_energy_this_year") assert state @@ -103,7 +103,7 @@ async def test_solaredgeoverviewdataservice_energy_values_validity( mock_solaredge().get_overview.return_value = mock_overview_data freezer.tick(OVERVIEW_UPDATE_DELAY) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.solaredge_lifetime_energy") assert state diff --git a/tests/components/sonos/conftest.py b/tests/components/sonos/conftest.py index 0b3834992d8..00858a180a3 100644 --- a/tests/components/sonos/conftest.py +++ b/tests/components/sonos/conftest.py @@ -94,8 +94,9 @@ def async_setup_sonos(hass, config_entry, fire_zgs_event): async def _wrapper(): config_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(config_entry.entry_id) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) await fire_zgs_event() + await hass.async_block_till_done(wait_background_tasks=True) return _wrapper diff --git a/tests/components/sonos/test_repairs.py b/tests/components/sonos/test_repairs.py index cc1f59c5cd0..cf64912e498 100644 --- a/tests/components/sonos/test_repairs.py +++ b/tests/components/sonos/test_repairs.py @@ -28,10 +28,12 @@ async def test_subscription_repair_issues( config_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() + await hass.async_block_till_done() # Ensure an issue is registered on subscription failure + sub_callback = subscription.callback async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert issue_registry.async_get_issue(DOMAIN, SUB_FAIL_ISSUE_ID) # Ensure the issue still exists after reload @@ -42,7 +44,6 @@ async def test_subscription_repair_issues( # Ensure the issue has been removed after a successful subscription callback variables = {"ZoneGroupState": zgs_discovery} event = SonosMockEvent(soco, soco.zoneGroupTopology, variables) - sub_callback = subscription.callback sub_callback(event) await hass.async_block_till_done() assert not issue_registry.async_get_issue(DOMAIN, SUB_FAIL_ISSUE_ID) diff --git a/tests/components/sonos/test_sensor.py b/tests/components/sonos/test_sensor.py index 6e4461e5397..1f4ba8d22cd 100644 --- a/tests/components/sonos/test_sensor.py +++ b/tests/components/sonos/test_sensor.py @@ -26,6 +26,7 @@ async def test_entity_registry_unsupported( soco.get_battery_info.side_effect = NotSupportedException await async_setup_sonos() + await hass.async_block_till_done(wait_background_tasks=True) assert "media_player.zone_a" in entity_registry.entities assert "sensor.zone_a_battery" not in entity_registry.entities @@ -36,6 +37,8 @@ async def test_entity_registry_supported( hass: HomeAssistant, async_autosetup_sonos, soco, entity_registry: er.EntityRegistry ) -> None: """Test sonos device with battery registered in the device registry.""" + await hass.async_block_till_done(wait_background_tasks=True) + assert "media_player.zone_a" in entity_registry.entities assert "sensor.zone_a_battery" in entity_registry.entities assert "binary_sensor.zone_a_charging" in entity_registry.entities @@ -69,6 +72,7 @@ async def test_battery_on_s1( soco.get_battery_info.return_value = {} await async_setup_sonos() + await hass.async_block_till_done(wait_background_tasks=True) subscription = soco.deviceProperties.subscribe.return_value sub_callback = subscription.callback @@ -78,7 +82,7 @@ async def test_battery_on_s1( # Update the speaker with a callback event sub_callback(device_properties_event) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) battery = entity_registry.entities["sensor.zone_a_battery"] battery_state = hass.states.get(battery.entity_id) @@ -101,6 +105,7 @@ async def test_device_payload_without_battery( soco.get_battery_info.return_value = None await async_setup_sonos() + await hass.async_block_till_done(wait_background_tasks=True) subscription = soco.deviceProperties.subscribe.return_value sub_callback = subscription.callback @@ -109,7 +114,7 @@ async def test_device_payload_without_battery( device_properties_event.variables["more_info"] = bad_payload sub_callback(device_properties_event) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert bad_payload in caplog.text @@ -125,6 +130,7 @@ async def test_device_payload_without_battery_and_ignored_keys( soco.get_battery_info.return_value = None await async_setup_sonos() + await hass.async_block_till_done(wait_background_tasks=True) subscription = soco.deviceProperties.subscribe.return_value sub_callback = subscription.callback @@ -133,7 +139,7 @@ async def test_device_payload_without_battery_and_ignored_keys( device_properties_event.variables["more_info"] = ignored_payload sub_callback(device_properties_event) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert ignored_payload not in caplog.text @@ -150,7 +156,7 @@ async def test_audio_input_sensor( subscription = soco.avTransport.subscribe.return_value sub_callback = subscription.callback sub_callback(tv_event) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) audio_input_sensor = entity_registry.entities["sensor.zone_a_audio_input_format"] audio_input_state = hass.states.get(audio_input_sensor.entity_id) @@ -161,7 +167,7 @@ async def test_audio_input_sensor( type(soco).soundbar_audio_input_format = no_input_mock async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) no_input_mock.assert_called_once() audio_input_state = hass.states.get(audio_input_sensor.entity_id) @@ -169,13 +175,13 @@ async def test_audio_input_sensor( # Ensure state is not polled when source is not TV and state is already "No input" sub_callback(no_media_event) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) unpolled_mock = PropertyMock(return_value="Will not be polled") type(soco).soundbar_audio_input_format = unpolled_mock async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) unpolled_mock.assert_not_called() audio_input_state = hass.states.get(audio_input_sensor.entity_id) @@ -199,7 +205,7 @@ async def test_microphone_binary_sensor( # Update the speaker with a callback event subscription = soco.deviceProperties.subscribe.return_value subscription.callback(device_properties_event) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) mic_binary_sensor_state = hass.states.get(mic_binary_sensor.entity_id) assert mic_binary_sensor_state.state == STATE_ON @@ -225,17 +231,18 @@ async def test_favorites_sensor( empty_event = SonosMockEvent(soco, service, {}) subscription = service.subscribe.return_value subscription.callback(event=empty_event) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) # Reload the integration to enable the sensor async_fire_time_changed( hass, dt_util.utcnow() + timedelta(seconds=RELOAD_AFTER_UPDATE_DELAY + 1), ) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) # Trigger subscription callback for speaker discovery await fire_zgs_event() + await hass.async_block_till_done(wait_background_tasks=True) favorites_updated_event = SonosMockEvent( soco, service, {"favorites_update_id": "2", "container_update_i_ds": "FV:2,2"} @@ -245,4 +252,4 @@ async def test_favorites_sensor( return_value=True, ): subscription.callback(event=favorites_updated_event) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) diff --git a/tests/components/sonos/test_speaker.py b/tests/components/sonos/test_speaker.py index e0fc4c3baf9..2c4357060be 100644 --- a/tests/components/sonos/test_speaker.py +++ b/tests/components/sonos/test_speaker.py @@ -12,9 +12,20 @@ from tests.common import async_fire_time_changed async def test_fallback_to_polling( - hass: HomeAssistant, async_autosetup_sonos, soco, caplog: pytest.LogCaptureFixture + hass: HomeAssistant, + config_entry, + soco, + fire_zgs_event, + caplog: pytest.LogCaptureFixture, ) -> None: """Test that polling fallback works.""" + config_entry.add_to_hass(hass) + assert await hass.config_entries.async_setup(config_entry.entry_id) + # Do not wait on background tasks here because the + # subscription callback will fire an unsub the polling check + await hass.async_block_till_done() + await fire_zgs_event() + speaker = list(hass.data[DATA_SONOS].discovered.values())[0] assert speaker.soco is soco assert speaker._subscriptions @@ -30,7 +41,7 @@ async def test_fallback_to_polling( ), ): async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert not speaker._subscriptions assert speaker.subscriptions_failed @@ -46,6 +57,7 @@ async def test_subscription_creation_fails( side_effect=ConnectionError("Took too long"), ): await async_setup_sonos() + await hass.async_block_till_done(wait_background_tasks=True) speaker = list(hass.data[DATA_SONOS].discovered.values())[0] assert not speaker._subscriptions diff --git a/tests/components/soundtouch/test_media_player.py b/tests/components/soundtouch/test_media_player.py index 94e6965a571..61d0c7b4ea5 100644 --- a/tests/components/soundtouch/test_media_player.py +++ b/tests/components/soundtouch/test_media_player.py @@ -665,7 +665,7 @@ async def test_zone_attributes( hass, dt_util.utcnow() + timedelta(seconds=RELOAD_AFTER_UPDATE_DELAY + 1), ) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) entity_1_state = hass.states.get(DEVICE_1_ENTITY_ID) assert entity_1_state.attributes[ATTR_SOUNDTOUCH_ZONE]["is_master"] diff --git a/tests/components/speedtestdotnet/test_init.py b/tests/components/speedtestdotnet/test_init.py index 5083f56a8e2..2b0f803eb6f 100644 --- a/tests/components/speedtestdotnet/test_init.py +++ b/tests/components/speedtestdotnet/test_init.py @@ -74,7 +74,7 @@ async def test_server_not_found(hass: HomeAssistant, mock_api: MagicMock) -> Non hass, dt_util.utcnow() + timedelta(minutes=61), ) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("sensor.speedtest_ping") assert state is not None assert state.state == STATE_UNAVAILABLE diff --git a/tests/components/systemmonitor/test_binary_sensor.py b/tests/components/systemmonitor/test_binary_sensor.py index 51c8fc87a3a..e3fbdedc081 100644 --- a/tests/components/systemmonitor/test_binary_sensor.py +++ b/tests/components/systemmonitor/test_binary_sensor.py @@ -97,7 +97,7 @@ async def test_sensor_process_fails( freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) process_sensor = hass.states.get("binary_sensor.system_monitor_process_python3") assert process_sensor is not None diff --git a/tests/components/systemmonitor/test_sensor.py b/tests/components/systemmonitor/test_sensor.py index 11dd002c2f7..a11112d8f86 100644 --- a/tests/components/systemmonitor/test_sensor.py +++ b/tests/components/systemmonitor/test_sensor.py @@ -232,7 +232,7 @@ async def test_sensor_updating( mock_psutil.virtual_memory.side_effect = Exception("Failed to update") freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) memory_sensor = hass.states.get("sensor.system_monitor_memory_free") assert memory_sensor is not None @@ -248,7 +248,7 @@ async def test_sensor_updating( ) freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) memory_sensor = hass.states.get("sensor.system_monitor_memory_free") assert memory_sensor is not None @@ -293,7 +293,7 @@ async def test_sensor_process_fails( freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) process_sensor = hass.states.get("sensor.system_monitor_process_python3") assert process_sensor is not None @@ -330,7 +330,7 @@ async def test_sensor_network_sensors( freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) network_out_sensor = hass.states.get("sensor.system_monitor_network_out_eth1") packets_out_sensor = hass.states.get("sensor.system_monitor_packets_out_eth1") @@ -362,7 +362,7 @@ async def test_sensor_network_sensors( freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) network_out_sensor = hass.states.get("sensor.system_monitor_network_out_eth1") packets_out_sensor = hass.states.get("sensor.system_monitor_packets_out_eth1") @@ -470,7 +470,7 @@ async def test_exception_handling_disk_sensor( freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert "OS error for /" in caplog.text @@ -483,7 +483,7 @@ async def test_exception_handling_disk_sensor( freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert "OS error for /" in caplog.text @@ -498,7 +498,7 @@ async def test_exception_handling_disk_sensor( freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) disk_sensor = hass.states.get("sensor.system_monitor_disk_free") assert disk_sensor is not None @@ -528,7 +528,7 @@ async def test_cpu_percentage_is_zero_returns_unknown( freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) cpu_sensor = hass.states.get("sensor.system_monitor_processor_use") assert cpu_sensor is not None @@ -538,7 +538,7 @@ async def test_cpu_percentage_is_zero_returns_unknown( freezer.tick(timedelta(minutes=1)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) cpu_sensor = hass.states.get("sensor.system_monitor_processor_use") assert cpu_sensor is not None @@ -573,7 +573,7 @@ async def test_remove_obsolete_entities( ) freezer.tick(timedelta(minutes=5)) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) # Fake an entity which should be removed as not supported and disabled entity_registry.async_get_or_create( diff --git a/tests/components/tcp/test_binary_sensor.py b/tests/components/tcp/test_binary_sensor.py index 959c1f050fd..05aa2a471db 100644 --- a/tests/components/tcp/test_binary_sensor.py +++ b/tests/components/tcp/test_binary_sensor.py @@ -79,7 +79,7 @@ async def test_state(hass: HomeAssistant, mock_socket, now) -> None: mock_socket.recv.return_value = b"on" async_fire_time_changed(hass, now + timedelta(seconds=45)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(TEST_ENTITY) diff --git a/tests/components/temper/test_sensor.py b/tests/components/temper/test_sensor.py index 94c44cc4296..d1e74f1ab0f 100644 --- a/tests/components/temper/test_sensor.py +++ b/tests/components/temper/test_sensor.py @@ -29,7 +29,7 @@ async def test_temperature_readback(hass: HomeAssistant) -> None: await hass.async_block_till_done() async_fire_time_changed(hass, utcnow + timedelta(seconds=70)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) temperature = hass.states.get("sensor.mydevicename") assert temperature diff --git a/tests/components/totalconnect/test_alarm_control_panel.py b/tests/components/totalconnect/test_alarm_control_panel.py index 7ac6540f1ff..fa2e997756d 100644 --- a/tests/components/totalconnect/test_alarm_control_panel.py +++ b/tests/components/totalconnect/test_alarm_control_panel.py @@ -548,30 +548,30 @@ async def test_other_update_failures(hass: HomeAssistant) -> None: # then an error: ServiceUnavailable --> UpdateFailed async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.get(ENTITY_ID).state == STATE_UNAVAILABLE assert mock_request.call_count == 2 # works again async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL * 2) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.get(ENTITY_ID).state == STATE_ALARM_DISARMED assert mock_request.call_count == 3 # then an error: TotalConnectError --> UpdateFailed async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL * 3) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.get(ENTITY_ID).state == STATE_UNAVAILABLE assert mock_request.call_count == 4 # works again async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL * 4) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.get(ENTITY_ID).state == STATE_ALARM_DISARMED assert mock_request.call_count == 5 # unknown TotalConnect status via ValueError async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL * 5) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.get(ENTITY_ID).state == STATE_UNAVAILABLE assert mock_request.call_count == 6 diff --git a/tests/components/uvc/test_camera.py b/tests/components/uvc/test_camera.py index 12203a3e222..522448ecfc4 100644 --- a/tests/components/uvc/test_camera.py +++ b/tests/components/uvc/test_camera.py @@ -278,7 +278,7 @@ async def test_setup_nvr_errors_during_indexing( mock_remote.return_value.index.side_effect = None async_fire_time_changed(hass, now + timedelta(seconds=31)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) camera_states = hass.states.async_all("camera") @@ -313,7 +313,7 @@ async def test_setup_nvr_errors_during_initialization( mock_remote.side_effect = None async_fire_time_changed(hass, now + timedelta(seconds=31)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) camera_states = hass.states.async_all("camera") @@ -362,7 +362,7 @@ async def test_motion_recording_mode_properties( ] = True async_fire_time_changed(hass, now + timedelta(seconds=31)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("camera.front") @@ -375,7 +375,7 @@ async def test_motion_recording_mode_properties( mock_remote.return_value.get_camera.return_value["recordingIndicator"] = "DISABLED" async_fire_time_changed(hass, now + timedelta(seconds=61)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("camera.front") @@ -387,7 +387,7 @@ async def test_motion_recording_mode_properties( ) async_fire_time_changed(hass, now + timedelta(seconds=91)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("camera.front") @@ -399,7 +399,7 @@ async def test_motion_recording_mode_properties( ) async_fire_time_changed(hass, now + timedelta(seconds=121)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("camera.front") diff --git a/tests/components/ws66i/test_media_player.py b/tests/components/ws66i/test_media_player.py index eec6bf191f7..c13f6cbd738 100644 --- a/tests/components/ws66i/test_media_player.py +++ b/tests/components/ws66i/test_media_player.py @@ -195,7 +195,7 @@ async def test_update(hass: HomeAssistant, freezer: FrozenDateTimeFactory) -> No with patch.object(MockWs66i, "open") as method_call: freezer.tick(POLL_INTERVAL) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert not method_call.called @@ -226,13 +226,13 @@ async def test_failed_update( freezer.tick(POLL_INTERVAL) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) # Failed update, close called with patch.object(MockWs66i, "zone_status", return_value=None): freezer.tick(POLL_INTERVAL) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert hass.states.is_state(ZONE_1_ID, STATE_UNAVAILABLE) @@ -240,12 +240,12 @@ async def test_failed_update( with patch.object(MockWs66i, "zone_status", return_value=None): freezer.tick(POLL_INTERVAL) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) # A connection re-attempt succeeds freezer.tick(POLL_INTERVAL) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) # confirm entity is back on state = hass.states.get(ZONE_1_ID) @@ -315,7 +315,7 @@ async def test_source_select( freezer.tick(POLL_INTERVAL) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get(ZONE_1_ID) @@ -370,14 +370,14 @@ async def test_volume_up_down( ) freezer.tick(POLL_INTERVAL) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) # should not go below zero assert ws66i.zones[11].volume == 0 await _call_media_player_service(hass, SERVICE_VOLUME_UP, {"entity_id": ZONE_1_ID}) freezer.tick(POLL_INTERVAL) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert ws66i.zones[11].volume == 1 await _call_media_player_service( @@ -385,14 +385,14 @@ async def test_volume_up_down( ) freezer.tick(POLL_INTERVAL) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert ws66i.zones[11].volume == MAX_VOL await _call_media_player_service(hass, SERVICE_VOLUME_UP, {"entity_id": ZONE_1_ID}) freezer.tick(POLL_INTERVAL) async_fire_time_changed(hass) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) # should not go above 38 (MAX_VOL) assert ws66i.zones[11].volume == MAX_VOL diff --git a/tests/components/xiaomi_miio/test_vacuum.py b/tests/components/xiaomi_miio/test_vacuum.py index c5345386777..2cfc3a4f294 100644 --- a/tests/components/xiaomi_miio/test_vacuum.py +++ b/tests/components/xiaomi_miio/test_vacuum.py @@ -238,7 +238,7 @@ async def test_xiaomi_exceptions(hass: HomeAssistant, mock_mirobo_is_on) -> None mock_mirobo_is_on.status.side_effect = DeviceException("dummy exception") future = dt_util.utcnow() + timedelta(seconds=60) async_fire_time_changed(hass, future) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert not is_available() @@ -247,7 +247,7 @@ async def test_xiaomi_exceptions(hass: HomeAssistant, mock_mirobo_is_on) -> None mock_mirobo_is_on.status.reset_mock() future += timedelta(seconds=60) async_fire_time_changed(hass, future) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) assert not is_available() assert mock_mirobo_is_on.status.call_count == 1 diff --git a/tests/components/yale_smart_alarm/test_coordinator.py b/tests/components/yale_smart_alarm/test_coordinator.py index 5125c817567..6f1125fcf65 100644 --- a/tests/components/yale_smart_alarm/test_coordinator.py +++ b/tests/components/yale_smart_alarm/test_coordinator.py @@ -76,7 +76,7 @@ async def test_coordinator_setup_and_update_errors( client.get_all.side_effect = ConnectionError("Could not connect") async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=1)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) client.get_all.assert_called_once() state = hass.states.get("alarm_control_panel.yale_smart_alarm") assert state.state == STATE_UNAVAILABLE @@ -84,7 +84,7 @@ async def test_coordinator_setup_and_update_errors( client.get_all.side_effect = ConnectionError("Could not connect") async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=2)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) client.get_all.assert_called_once() state = hass.states.get("alarm_control_panel.yale_smart_alarm") assert state.state == STATE_UNAVAILABLE @@ -92,7 +92,7 @@ async def test_coordinator_setup_and_update_errors( client.get_all.side_effect = TimeoutError("Could not connect") async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=3)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) client.get_all.assert_called_once() state = hass.states.get("alarm_control_panel.yale_smart_alarm") assert state.state == STATE_UNAVAILABLE @@ -100,7 +100,7 @@ async def test_coordinator_setup_and_update_errors( client.get_all.side_effect = UnknownError("info") async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=4)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) client.get_all.assert_called_once() state = hass.states.get("alarm_control_panel.yale_smart_alarm") assert state.state == STATE_UNAVAILABLE @@ -110,7 +110,7 @@ async def test_coordinator_setup_and_update_errors( client.get_all.return_value = load_json client.get_armed_status.return_value = YALE_STATE_ARM_FULL async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=5)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) client.get_all.assert_called_once() state = hass.states.get("alarm_control_panel.yale_smart_alarm") assert state.state == STATE_ALARM_ARMED_AWAY @@ -118,7 +118,7 @@ async def test_coordinator_setup_and_update_errors( client.get_all.side_effect = AuthenticationError("Can not authenticate") async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=6)) - await hass.async_block_till_done() + await hass.async_block_till_done(wait_background_tasks=True) client.get_all.assert_called_once() state = hass.states.get("alarm_control_panel.yale_smart_alarm") assert state.state == STATE_UNAVAILABLE diff --git a/tests/test_core.py b/tests/test_core.py index 11fda50a180..a0a197096cd 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -588,6 +588,46 @@ async def test_async_get_hass_can_be_called(hass: HomeAssistant) -> None: my_job_create_task.join() +async def test_async_add_executor_job_background(hass: HomeAssistant) -> None: + """Test running an executor job in the background.""" + calls = [] + + def job(): + time.sleep(0.01) + calls.append(1) + + async def _async_add_executor_job(): + await hass.async_add_executor_job(job) + + task = hass.async_create_background_task( + _async_add_executor_job(), "background", eager_start=True + ) + await hass.async_block_till_done() + assert len(calls) == 0 + await hass.async_block_till_done(wait_background_tasks=True) + assert len(calls) == 1 + await task + + +async def test_async_add_executor_job(hass: HomeAssistant) -> None: + """Test running an executor job.""" + calls = [] + + def job(): + time.sleep(0.01) + calls.append(1) + + async def _async_add_executor_job(): + await hass.async_add_executor_job(job) + + task = hass.async_create_task( + _async_add_executor_job(), "background", eager_start=True + ) + await hass.async_block_till_done() + assert len(calls) == 1 + await task + + async def test_stage_shutdown(hass: HomeAssistant) -> None: """Simulate a shutdown, test calling stuff.""" test_stop = async_capture_events(hass, EVENT_HOMEASSISTANT_STOP)