From 89a9634d35c1a2d3b563a54d45df8ef951ab2486 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 29 Jun 2020 11:39:24 -0500 Subject: [PATCH] Use eventloop for scheduling (#37184) Co-authored-by: Paulus Schoutsen --- homeassistant/components/flux/switch.py | 5 +- homeassistant/components/statistics/sensor.py | 12 +- homeassistant/components/sun/__init__.py | 14 ++- homeassistant/components/tod/binary_sensor.py | 9 +- homeassistant/const.py | 2 +- homeassistant/helpers/event.py | 28 ++--- homeassistant/helpers/update_coordinator.py | 4 +- tests/common.py | 18 ++- tests/components/asuswrt/test_sensor.py | 37 +++--- tests/components/automation/test_sun.py | 8 +- tests/components/cert_expiry/test_sensors.py | 29 ++--- tests/components/cloud/test_google_config.py | 4 +- tests/components/device_tracker/test_init.py | 12 +- tests/components/duckdns/test_init.py | 8 +- tests/components/flux/test_switch.py | 26 ++-- .../generic_thermostat/test_climate.py | 35 +++--- .../here_travel_time/test_sensor.py | 16 ++- tests/components/homekit/test_accessories.py | 12 +- .../components/homekit_controller/conftest.py | 5 +- .../islamic_prayer_times/test_init.py | 5 +- .../islamic_prayer_times/test_sensor.py | 3 +- .../jewish_calendar/test_binary_sensor.py | 11 +- .../components/jewish_calendar/test_sensor.py | 16 ++- .../manual/test_alarm_control_panel.py | 2 +- .../manual_mqtt/test_alarm_control_panel.py | 2 +- tests/components/metoffice/test_sensor.py | 5 +- tests/components/metoffice/test_weather.py | 8 +- .../mikrotik/test_device_tracker.py | 2 +- tests/components/moon/test_sensor.py | 65 ++++++---- tests/components/mqtt/test_binary_sensor.py | 10 +- tests/components/mqtt/test_sensor.py | 7 +- tests/components/pilight/test_init.py | 13 +- tests/components/push/test_camera.py | 5 +- .../pvpc_hourly_pricing/test_config_flow.py | 4 +- .../pvpc_hourly_pricing/test_sensor.py | 2 +- tests/components/rflink/test_binary_sensor.py | 2 +- tests/components/statistics/test_sensor.py | 13 +- tests/components/sun/test_init.py | 4 +- tests/components/tod/test_binary_sensor.py | 7 ++ tests/components/yr/test_sensor.py | 9 +- tests/conftest.py | 44 ++++++- tests/helpers/test_event.py | 115 +++++++++--------- 42 files changed, 366 insertions(+), 272 deletions(-) diff --git a/homeassistant/components/flux/switch.py b/homeassistant/components/flux/switch.py index 8a27c99c78d..4d45f217a59 100644 --- a/homeassistant/components/flux/switch.py +++ b/homeassistant/components/flux/switch.py @@ -31,8 +31,7 @@ from homeassistant.const import ( SUN_EVENT_SUNRISE, SUN_EVENT_SUNSET, ) -import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.event import async_track_time_interval +from homeassistant.helpers import config_validation as cv, event from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.sun import get_astral_event_date from homeassistant.util import slugify @@ -224,7 +223,7 @@ class FluxSwitch(SwitchEntity, RestoreEntity): if self.is_on: return - self.unsub_tracker = async_track_time_interval( + self.unsub_tracker = event.async_track_time_interval( self.hass, self.async_flux_update, datetime.timedelta(seconds=self._interval), diff --git a/homeassistant/components/statistics/sensor.py b/homeassistant/components/statistics/sensor.py index 00e029e49c6..906b0a2c68b 100644 --- a/homeassistant/components/statistics/sensor.py +++ b/homeassistant/components/statistics/sensor.py @@ -17,12 +17,8 @@ from homeassistant.const import ( STATE_UNKNOWN, ) from homeassistant.core import callback -import homeassistant.helpers.config_validation as cv +from homeassistant.helpers import config_validation as cv, event from homeassistant.helpers.entity import Entity -from homeassistant.helpers.event import ( - async_track_point_in_utc_time, - async_track_state_change, -) from homeassistant.util import dt as dt_util _LOGGER = logging.getLogger(__name__) @@ -116,11 +112,11 @@ class StatisticsSensor(Entity): self.async_schedule_update_ha_state(True) @callback - def async_stats_sensor_startup(event): + def async_stats_sensor_startup(_): """Add listener and get recorded state.""" _LOGGER.debug("Startup for %s", self.entity_id) - async_track_state_change( + event.async_track_state_change( self.hass, self._entity_id, async_stats_sensor_state_listener ) @@ -296,7 +292,7 @@ class StatisticsSensor(Entity): self.async_schedule_update_ha_state(True) self._update_listener = None - self._update_listener = async_track_point_in_utc_time( + self._update_listener = event.async_track_point_in_utc_time( self.hass, _scheduled_update, next_to_purge_timestamp ) diff --git a/homeassistant/components/sun/__init__.py b/homeassistant/components/sun/__init__.py index 9529a9c0cad..c4692598447 100644 --- a/homeassistant/components/sun/__init__.py +++ b/homeassistant/components/sun/__init__.py @@ -9,8 +9,8 @@ from homeassistant.const import ( SUN_EVENT_SUNSET, ) from homeassistant.core import callback +from homeassistant.helpers import event from homeassistant.helpers.entity import Entity -from homeassistant.helpers.event import async_track_point_in_utc_time from homeassistant.helpers.sun import ( get_astral_location, get_location_astral_event_next, @@ -99,7 +99,7 @@ class Sun(Entity): self.rising = self.phase = None self._next_change = None - def update_location(event): + def update_location(_event): self.location = get_astral_location(self.hass) self.update_events(dt_util.utcnow()) @@ -135,9 +135,9 @@ class Sun(Entity): STATE_ATTR_RISING: self.rising, } - def _check_event(self, utc_point_in_time, event, before): + def _check_event(self, utc_point_in_time, sun_event, before): next_utc = get_location_astral_event_next( - self.location, event, utc_point_in_time + self.location, sun_event, utc_point_in_time ) if next_utc < self._next_change: self._next_change = next_utc @@ -207,7 +207,9 @@ class Sun(Entity): self.update_sun_position(utc_point_in_time) # Set timer for the next solar event - async_track_point_in_utc_time(self.hass, self.update_events, self._next_change) + event.async_track_point_in_utc_time( + self.hass, self.update_events, self._next_change + ) _LOGGER.debug("next time: %s", self._next_change.isoformat()) @callback @@ -232,6 +234,6 @@ class Sun(Entity): # position update just drop it if utc_point_in_time + delta * 1.25 > self._next_change: return - async_track_point_in_utc_time( + event.async_track_point_in_utc_time( self.hass, self.update_sun_position, utc_point_in_time + delta ) diff --git a/homeassistant/components/tod/binary_sensor.py b/homeassistant/components/tod/binary_sensor.py index 8a5bbf16c6c..fde26acf604 100644 --- a/homeassistant/components/tod/binary_sensor.py +++ b/homeassistant/components/tod/binary_sensor.py @@ -14,8 +14,7 @@ from homeassistant.const import ( SUN_EVENT_SUNSET, ) from homeassistant.core import callback -import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.event import async_track_point_in_utc_time +from homeassistant.helpers import config_validation as cv, event from homeassistant.helpers.sun import get_astral_event_date, get_astral_event_next from homeassistant.util import dt as dt_util @@ -55,9 +54,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= async_add_entities([sensor]) -def is_sun_event(event): +def is_sun_event(sun_event): """Return true if event is sun event not time.""" - return event in (SUN_EVENT_SUNRISE, SUN_EVENT_SUNSET) + return sun_event in (SUN_EVENT_SUNRISE, SUN_EVENT_SUNSET) class TodSensor(BinarySensorEntity): @@ -236,6 +235,6 @@ class TodSensor(BinarySensorEntity): self._calculate_next_update() self.async_write_ha_state() - async_track_point_in_utc_time( + event.async_track_point_in_utc_time( self.hass, self._point_in_time_listener, self.next_update ) diff --git a/homeassistant/const.py b/homeassistant/const.py index fe90ccf8504..3472e46dd69 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -4,7 +4,7 @@ MINOR_VERSION = 113 PATCH_VERSION = "0.dev0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" -REQUIRED_PYTHON_VER = (3, 7, 0) +REQUIRED_PYTHON_VER = (3, 7, 1) # Truthy date string triggers showing related deprecation warning messages. REQUIRED_NEXT_PYTHON_VER = (3, 8, 0) REQUIRED_NEXT_PYTHON_DATE = "" diff --git a/homeassistant/helpers/event.py b/homeassistant/helpers/event.py index a5f433b0e23..84e418e5eb0 100644 --- a/homeassistant/helpers/event.py +++ b/homeassistant/helpers/event.py @@ -2,6 +2,7 @@ from datetime import datetime, timedelta import functools as ft import logging +import time from typing import Any, Awaitable, Callable, Dict, Iterable, Optional, Union import attr @@ -316,26 +317,21 @@ def async_track_point_in_utc_time( point_in_time = dt_util.as_utc(point_in_time) @callback - def point_in_time_listener(event: Event) -> None: + def point_in_time_listener() -> None: """Listen for matching time_changed events.""" - now = event.data[ATTR_NOW] + hass.async_run_job(action, point_in_time) - if now < point_in_time or hasattr(point_in_time_listener, "run"): - return + cancel_callback = hass.loop.call_at( + hass.loop.time() + point_in_time.timestamp() - time.time(), + point_in_time_listener, + ) - # Set variable so that we will never run twice. - # Because the event bus might have to wait till a thread comes - # available to execute this listener it might occur that the - # listener gets lined up twice to be executed. This will make - # sure the second time it does nothing. - setattr(point_in_time_listener, "run", True) - async_unsub() + @callback + def unsub_point_in_time_listener() -> None: + """Cancel the call_later.""" + cancel_callback.cancel() - hass.async_run_job(action, now) - - async_unsub = hass.bus.async_listen(EVENT_TIME_CHANGED, point_in_time_listener) - - return async_unsub + return unsub_point_in_time_listener track_point_in_utc_time = threaded_listener_factory(async_track_point_in_utc_time) diff --git a/homeassistant/helpers/update_coordinator.py b/homeassistant/helpers/update_coordinator.py index 7fb96fdf7c8..3c8a5d2924e 100644 --- a/homeassistant/helpers/update_coordinator.py +++ b/homeassistant/helpers/update_coordinator.py @@ -8,7 +8,7 @@ from typing import Any, Awaitable, Callable, List, Optional import aiohttp from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback -from homeassistant.helpers.event import async_track_point_in_utc_time +from homeassistant.helpers import event from homeassistant.util.dt import utcnow from .debounce import Debouncer @@ -99,7 +99,7 @@ class DataUpdateCoordinator: # minimizing the time between the point and the real activation. # That way we obtain a constant update frequency, # as long as the update process takes less than a second - self._unsub_refresh = async_track_point_in_utc_time( + self._unsub_refresh = event.async_track_point_in_utc_time( self.hass, self._handle_refresh_interval, utcnow().replace(microsecond=0) + self.update_interval, diff --git a/tests/common.py b/tests/common.py index dfe832cc4ce..03ab5b0e0a0 100644 --- a/tests/common.py +++ b/tests/common.py @@ -11,6 +11,7 @@ import logging import os import sys import threading +import time import uuid from aiohttp.test_utils import unused_port as get_test_instance_port # noqa @@ -284,9 +285,22 @@ fire_mqtt_message = threadsafe_callback_factory(async_fire_mqtt_message) @ha.callback -def async_fire_time_changed(hass, time): +def async_fire_time_changed(hass, datetime_): """Fire a time changes event.""" - hass.bus.async_fire(EVENT_TIME_CHANGED, {"now": date_util.as_utc(time)}) + hass.bus.async_fire(EVENT_TIME_CHANGED, {"now": date_util.as_utc(datetime_)}) + + for task in list(hass.loop._scheduled): + if not isinstance(task, asyncio.TimerHandle): + continue + if task.cancelled(): + continue + + future_seconds = task.when() - hass.loop.time() + mock_seconds_into_future = datetime_.timestamp() - time.time() + + if mock_seconds_into_future >= future_seconds: + task._run() + task.cancel() fire_time_changed = threadsafe_callback_factory(async_fire_time_changed) diff --git a/tests/components/asuswrt/test_sensor.py b/tests/components/asuswrt/test_sensor.py index 6d58b909280..6de3f1b2dcb 100644 --- a/tests/components/asuswrt/test_sensor.py +++ b/tests/components/asuswrt/test_sensor.py @@ -1,5 +1,5 @@ """The tests for the AsusWrt sensor platform.""" -from datetime import datetime, timedelta +from datetime import timedelta from aioasuswrt.asuswrt import Device @@ -16,7 +16,6 @@ from homeassistant.components.asuswrt import ( from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component -import homeassistant.util.dt as dt_util from homeassistant.util.dt import utcnow from tests.async_mock import AsyncMock, patch @@ -51,7 +50,7 @@ MOCK_BYTES_TOTAL = [60000000000, 50000000000] MOCK_CURRENT_TRANSFER_RATES = [20000000, 10000000] -async def test_sensors(hass: HomeAssistant): +async def test_sensors(hass: HomeAssistant, mock_device_tracker_conf): """Test creating an AsusWRT sensor.""" with patch("homeassistant.components.asuswrt.AsusWrt") as AsusWrt: AsusWrt().connection.async_connect = AsyncMock() @@ -61,23 +60,17 @@ async def test_sensors(hass: HomeAssistant): return_value=MOCK_CURRENT_TRANSFER_RATES ) - now = datetime(2020, 1, 1, 1, tzinfo=dt_util.UTC) - with patch(("homeassistant.helpers.event.dt_util.utcnow"), return_value=now): - assert await async_setup_component(hass, DOMAIN, VALID_CONFIG_ROUTER_SSH) - await hass.async_block_till_done() - async_fire_time_changed(hass, utcnow() + timedelta(seconds=30)) - await hass.async_block_till_done() + assert await async_setup_component(hass, DOMAIN, VALID_CONFIG_ROUTER_SSH) + await hass.async_block_till_done() + async_fire_time_changed(hass, utcnow() + timedelta(seconds=30)) + await hass.async_block_till_done() - assert ( - hass.states.get(f"{sensor.DOMAIN}.asuswrt_devices_connected").state - == "3" - ) - assert ( - hass.states.get(f"{sensor.DOMAIN}.asuswrt_download_speed").state - == "160.0" - ) - assert hass.states.get(f"{sensor.DOMAIN}.asuswrt_download").state == "60.0" - assert ( - hass.states.get(f"{sensor.DOMAIN}.asuswrt_upload_speed").state == "80.0" - ) - assert hass.states.get(f"{sensor.DOMAIN}.asuswrt_upload").state == "50.0" + assert ( + hass.states.get(f"{sensor.DOMAIN}.asuswrt_devices_connected").state == "3" + ) + assert ( + hass.states.get(f"{sensor.DOMAIN}.asuswrt_download_speed").state == "160.0" + ) + assert hass.states.get(f"{sensor.DOMAIN}.asuswrt_download").state == "60.0" + assert hass.states.get(f"{sensor.DOMAIN}.asuswrt_upload_speed").state == "80.0" + assert hass.states.get(f"{sensor.DOMAIN}.asuswrt_upload").state == "50.0" diff --git a/tests/components/automation/test_sun.py b/tests/components/automation/test_sun.py index 4efb19ff201..f730dae3cf1 100644 --- a/tests/components/automation/test_sun.py +++ b/tests/components/automation/test_sun.py @@ -37,7 +37,7 @@ def teardown(): dt_util.set_default_time_zone(ORIG_TIME_ZONE) -async def test_sunset_trigger(hass, calls): +async def test_sunset_trigger(hass, calls, legacy_patchable_time): """Test the sunset trigger.""" now = datetime(2015, 9, 15, 23, tzinfo=dt_util.UTC) trigger_time = datetime(2015, 9, 16, 2, tzinfo=dt_util.UTC) @@ -70,7 +70,7 @@ async def test_sunset_trigger(hass, calls): assert len(calls) == 1 -async def test_sunrise_trigger(hass, calls): +async def test_sunrise_trigger(hass, calls, legacy_patchable_time): """Test the sunrise trigger.""" now = datetime(2015, 9, 13, 23, tzinfo=dt_util.UTC) trigger_time = datetime(2015, 9, 16, 14, tzinfo=dt_util.UTC) @@ -92,7 +92,7 @@ async def test_sunrise_trigger(hass, calls): assert len(calls) == 1 -async def test_sunset_trigger_with_offset(hass, calls): +async def test_sunset_trigger_with_offset(hass, calls, legacy_patchable_time): """Test the sunset trigger with offset.""" now = datetime(2015, 9, 15, 23, tzinfo=dt_util.UTC) trigger_time = datetime(2015, 9, 16, 2, 30, tzinfo=dt_util.UTC) @@ -125,7 +125,7 @@ async def test_sunset_trigger_with_offset(hass, calls): assert calls[0].data["some"] == "sun - sunset - 0:30:00" -async def test_sunrise_trigger_with_offset(hass, calls): +async def test_sunrise_trigger_with_offset(hass, calls, legacy_patchable_time): """Test the sunrise trigger with offset.""" now = datetime(2015, 9, 13, 23, tzinfo=dt_util.UTC) trigger_time = datetime(2015, 9, 16, 13, 30, tzinfo=dt_util.UTC) diff --git a/tests/components/cert_expiry/test_sensors.py b/tests/components/cert_expiry/test_sensors.py index 7896da9e74b..76c6716411b 100644 --- a/tests/components/cert_expiry/test_sensors.py +++ b/tests/components/cert_expiry/test_sensors.py @@ -6,7 +6,7 @@ import ssl from homeassistant.components.cert_expiry.const import DOMAIN from homeassistant.config_entries import ENTRY_STATE_SETUP_RETRY from homeassistant.const import CONF_HOST, CONF_PORT, STATE_UNAVAILABLE, STATE_UNKNOWN -import homeassistant.util.dt as dt_util +from homeassistant.util.dt import utcnow from .const import HOST, PORT from .helpers import future_timestamp, static_datetime @@ -91,7 +91,7 @@ async def test_async_setup_entry_host_unavailable(hass): assert entry.state == ENTRY_STATE_SETUP_RETRY - next_update = dt_util.utcnow() + timedelta(seconds=45) + next_update = utcnow() + timedelta(seconds=45) async_fire_time_changed(hass, next_update) with patch( "homeassistant.components.cert_expiry.helper.get_cert", @@ -115,8 +115,6 @@ async def test_update_sensor(hass): timestamp = future_timestamp(100) with patch("homeassistant.util.dt.utcnow", return_value=starting_time), patch( - "homeassistant.helpers.update_coordinator.utcnow", return_value=starting_time - ), patch( "homeassistant.components.cert_expiry.get_cert_expiry_timestamp", return_value=timestamp, ): @@ -139,14 +137,11 @@ async def test_update_sensor(hass): assert state.attributes.get("is_valid") next_update = starting_time + timedelta(hours=24) - with patch("homeassistant.util.dt.utcnow", return_value=next_update), patch( - "homeassistant.helpers.update_coordinator.utcnow", return_value=next_update - ), patch( "homeassistant.components.cert_expiry.get_cert_expiry_timestamp", return_value=timestamp, ): - async_fire_time_changed(hass, next_update) + async_fire_time_changed(hass, utcnow() + timedelta(hours=24)) await hass.async_block_till_done() state = hass.states.get("sensor.cert_expiry_example_com") @@ -176,8 +171,6 @@ async def test_update_sensor_network_errors(hass): timestamp = future_timestamp(100) with patch("homeassistant.util.dt.utcnow", return_value=starting_time), patch( - "homeassistant.helpers.update_coordinator.utcnow", return_value=starting_time - ), patch( "homeassistant.components.cert_expiry.get_cert_expiry_timestamp", return_value=timestamp, ): @@ -202,12 +195,10 @@ async def test_update_sensor_network_errors(hass): next_update = starting_time + timedelta(hours=24) with patch("homeassistant.util.dt.utcnow", return_value=next_update), patch( - "homeassistant.helpers.update_coordinator.utcnow", return_value=next_update - ), patch( "homeassistant.components.cert_expiry.helper.get_cert", side_effect=socket.gaierror, ): - async_fire_time_changed(hass, next_update) + async_fire_time_changed(hass, utcnow() + timedelta(hours=24)) await hass.async_block_till_done() next_update = starting_time + timedelta(hours=48) @@ -216,12 +207,10 @@ async def test_update_sensor_network_errors(hass): assert state.state == STATE_UNAVAILABLE with patch("homeassistant.util.dt.utcnow", return_value=next_update), patch( - "homeassistant.helpers.update_coordinator.utcnow", return_value=next_update - ), patch( "homeassistant.components.cert_expiry.get_cert_expiry_timestamp", return_value=timestamp, ): - async_fire_time_changed(hass, next_update) + async_fire_time_changed(hass, utcnow() + timedelta(hours=48)) await hass.async_block_till_done() state = hass.states.get("sensor.cert_expiry_example_com") @@ -234,12 +223,10 @@ async def test_update_sensor_network_errors(hass): next_update = starting_time + timedelta(hours=72) with patch("homeassistant.util.dt.utcnow", return_value=next_update), patch( - "homeassistant.helpers.update_coordinator.utcnow", return_value=next_update - ), patch( "homeassistant.components.cert_expiry.helper.get_cert", side_effect=ssl.SSLError("something bad"), ): - async_fire_time_changed(hass, next_update) + async_fire_time_changed(hass, utcnow() + timedelta(hours=72)) await hass.async_block_till_done() state = hass.states.get("sensor.cert_expiry_example_com") @@ -258,11 +245,9 @@ async def test_update_sensor_network_errors(hass): next_update = starting_time + timedelta(hours=96) with patch("homeassistant.util.dt.utcnow", return_value=next_update), patch( - "homeassistant.helpers.update_coordinator.utcnow", return_value=next_update - ), patch( "homeassistant.components.cert_expiry.helper.get_cert", side_effect=Exception() ): - async_fire_time_changed(hass, next_update) + async_fire_time_changed(hass, utcnow() + timedelta(hours=96)) await hass.async_block_till_done() state = hass.states.get("sensor.cert_expiry_example_com") diff --git a/tests/components/cloud/test_google_config.py b/tests/components/cloud/test_google_config.py index 3808f9b179c..5dd4afe883c 100644 --- a/tests/components/cloud/test_google_config.py +++ b/tests/components/cloud/test_google_config.py @@ -51,7 +51,9 @@ async def test_sync_entities(aioclient_mock, hass, cloud_prefs): assert len(mock_request_sync.mock_calls) == 1 -async def test_google_update_expose_trigger_sync(hass, cloud_prefs): +async def test_google_update_expose_trigger_sync( + hass, legacy_patchable_time, cloud_prefs +): """Test Google config responds to updating exposed entities.""" config = CloudGoogleConfig( hass, diff --git a/tests/components/device_tracker/test_init.py b/tests/components/device_tracker/test_init.py index 1a366b0d2df..9424ed229b5 100644 --- a/tests/components/device_tracker/test_init.py +++ b/tests/components/device_tracker/test_init.py @@ -225,12 +225,14 @@ async def test_discover_platform(mock_demo_setup_scanner, mock_see, hass): async def test_update_stale(hass, mock_device_tracker_conf): """Test stalled update.""" + scanner = getattr(hass.components, "test.device_tracker").SCANNER scanner.reset() scanner.come_home("DEV1") - register_time = datetime(2015, 9, 15, 23, tzinfo=dt_util.UTC) - scan_time = datetime(2015, 9, 15, 23, 1, tzinfo=dt_util.UTC) + now = dt_util.utcnow() + register_time = datetime(now.year + 1, 9, 15, 23, tzinfo=dt_util.UTC) + scan_time = datetime(now.year + 1, 9, 15, 23, 1, tzinfo=dt_util.UTC) with patch( "homeassistant.components.device_tracker.legacy.dt_util.utcnow", @@ -433,8 +435,10 @@ async def test_see_state(hass, yaml_devices): async def test_see_passive_zone_state(hass, mock_device_tracker_conf): """Test that the device tracker sets gps for passive trackers.""" - register_time = datetime(2015, 9, 15, 23, tzinfo=dt_util.UTC) - scan_time = datetime(2015, 9, 15, 23, 1, tzinfo=dt_util.UTC) + now = dt_util.utcnow() + + register_time = datetime(now.year + 1, 9, 15, 23, tzinfo=dt_util.UTC) + scan_time = datetime(now.year + 1, 9, 15, 23, 1, tzinfo=dt_util.UTC) with assert_setup_component(1, zone.DOMAIN): zone_info = { diff --git a/tests/components/duckdns/test_init.py b/tests/components/duckdns/test_init.py index 9bc9b3504e7..03fce0df20e 100644 --- a/tests/components/duckdns/test_init.py +++ b/tests/components/duckdns/test_init.py @@ -159,7 +159,7 @@ async def test_async_track_time_interval_backoff(hass): _LOGGER.debug("Backoff...") for idx in range(1, len(intervals)): tme += intervals[idx] - async_fire_time_changed(hass, tme) + async_fire_time_changed(hass, tme + timedelta(seconds=0.1)) await hass.async_block_till_done() assert call_count == idx + 1 @@ -167,7 +167,7 @@ async def test_async_track_time_interval_backoff(hass): _LOGGER.debug("Max backoff reached - intervals[-1]") for _idx in range(1, 10): tme += intervals[-1] - async_fire_time_changed(hass, tme) + async_fire_time_changed(hass, tme + timedelta(seconds=0.1)) await hass.async_block_till_done() assert call_count == idx + 1 + _idx @@ -176,14 +176,14 @@ async def test_async_track_time_interval_backoff(hass): call_count = 0 ret_val = True tme += intervals[-1] - async_fire_time_changed(hass, tme) + async_fire_time_changed(hass, tme + timedelta(seconds=0.1)) await hass.async_block_till_done() assert call_count == 1 _LOGGER.debug("No backoff - intervals[0]") for _idx in range(2, 10): tme += intervals[0] - async_fire_time_changed(hass, tme) + async_fire_time_changed(hass, tme + timedelta(seconds=0.1)) await hass.async_block_till_done() assert call_count == _idx diff --git a/tests/components/flux/test_switch.py b/tests/components/flux/test_switch.py index 0eada7da667..f10029a6469 100644 --- a/tests/components/flux/test_switch.py +++ b/tests/components/flux/test_switch.py @@ -282,7 +282,7 @@ async def test_flux_before_sunrise_known_location(hass): # pylint: disable=invalid-name -async def test_flux_after_sunrise_before_sunset(hass): +async def test_flux_after_sunrise_before_sunset(hass, legacy_patchable_time): """Test the flux switch after sunrise and before sunset.""" platform = getattr(hass.components, "test.light") platform.init() @@ -336,7 +336,7 @@ async def test_flux_after_sunrise_before_sunset(hass): # pylint: disable=invalid-name -async def test_flux_after_sunset_before_stop(hass): +async def test_flux_after_sunset_before_stop(hass, legacy_patchable_time): """Test the flux switch after sunset and before stop.""" platform = getattr(hass.components, "test.light") platform.init() @@ -391,7 +391,7 @@ async def test_flux_after_sunset_before_stop(hass): # pylint: disable=invalid-name -async def test_flux_after_stop_before_sunrise(hass): +async def test_flux_after_stop_before_sunrise(hass, legacy_patchable_time): """Test the flux switch after stop and before sunrise.""" platform = getattr(hass.components, "test.light") platform.init() @@ -445,7 +445,7 @@ async def test_flux_after_stop_before_sunrise(hass): # pylint: disable=invalid-name -async def test_flux_with_custom_start_stop_times(hass): +async def test_flux_with_custom_start_stop_times(hass, legacy_patchable_time): """Test the flux with custom start and stop times.""" platform = getattr(hass.components, "test.light") platform.init() @@ -558,7 +558,9 @@ async def test_flux_before_sunrise_stop_next_day(hass): # pylint: disable=invalid-name -async def test_flux_after_sunrise_before_sunset_stop_next_day(hass): +async def test_flux_after_sunrise_before_sunset_stop_next_day( + hass, legacy_patchable_time +): """ Test the flux switch after sunrise and before sunset. @@ -618,7 +620,9 @@ async def test_flux_after_sunrise_before_sunset_stop_next_day(hass): # pylint: disable=invalid-name @pytest.mark.parametrize("x", [0, 1]) -async def test_flux_after_sunset_before_midnight_stop_next_day(hass, x): +async def test_flux_after_sunset_before_midnight_stop_next_day( + hass, legacy_patchable_time, x +): """Test the flux switch after sunset and before stop. This test has the stop_time on the next day (after midnight). @@ -792,7 +796,7 @@ async def test_flux_after_stop_before_sunrise_stop_next_day(hass): # pylint: disable=invalid-name -async def test_flux_with_custom_colortemps(hass): +async def test_flux_with_custom_colortemps(hass, legacy_patchable_time): """Test the flux with custom start and stop colortemps.""" platform = getattr(hass.components, "test.light") platform.init() @@ -849,7 +853,7 @@ async def test_flux_with_custom_colortemps(hass): # pylint: disable=invalid-name -async def test_flux_with_custom_brightness(hass): +async def test_flux_with_custom_brightness(hass, legacy_patchable_time): """Test the flux with custom start and stop colortemps.""" platform = getattr(hass.components, "test.light") platform.init() @@ -904,7 +908,7 @@ async def test_flux_with_custom_brightness(hass): assert call.data[light.ATTR_XY_COLOR] == [0.506, 0.385] -async def test_flux_with_multiple_lights(hass): +async def test_flux_with_multiple_lights(hass, legacy_patchable_time): """Test the flux switch with multiple light entities.""" platform = getattr(hass.components, "test.light") platform.init() @@ -982,7 +986,7 @@ async def test_flux_with_multiple_lights(hass): assert call.data[light.ATTR_XY_COLOR] == [0.46, 0.376] -async def test_flux_with_mired(hass): +async def test_flux_with_mired(hass, legacy_patchable_time): """Test the flux switch´s mode mired.""" platform = getattr(hass.components, "test.light") platform.init() @@ -1034,7 +1038,7 @@ async def test_flux_with_mired(hass): assert call.data[light.ATTR_COLOR_TEMP] == 269 -async def test_flux_with_rgb(hass): +async def test_flux_with_rgb(hass, legacy_patchable_time): """Test the flux switch´s mode rgb.""" platform = getattr(hass.components, "test.light") platform.init() diff --git a/tests/components/generic_thermostat/test_climate.py b/tests/components/generic_thermostat/test_climate.py index 5e144c3684a..313ff43ca6a 100644 --- a/tests/components/generic_thermostat/test_climate.py +++ b/tests/components/generic_thermostat/test_climate.py @@ -32,7 +32,11 @@ from homeassistant.setup import async_setup_component from homeassistant.util.unit_system import METRIC_SYSTEM from tests.async_mock import patch -from tests.common import assert_setup_component, mock_restore_cache +from tests.common import ( + assert_setup_component, + async_fire_time_changed, + mock_restore_cache, +) from tests.components.climate import common ENTITY = "climate.test" @@ -949,13 +953,13 @@ async def test_temp_change_ac_trigger_on_long_enough_3(hass, setup_comp_7): await hass.async_block_till_done() await common.async_set_temperature(hass, 25) test_time = datetime.datetime.now(pytz.UTC) - _send_time_changed(hass, test_time) + async_fire_time_changed(hass, test_time) await hass.async_block_till_done() assert 0 == len(calls) - _send_time_changed(hass, test_time + datetime.timedelta(minutes=5)) + async_fire_time_changed(hass, test_time + datetime.timedelta(minutes=5)) await hass.async_block_till_done() assert 0 == len(calls) - _send_time_changed(hass, test_time + datetime.timedelta(minutes=10)) + async_fire_time_changed(hass, test_time + datetime.timedelta(minutes=10)) await hass.async_block_till_done() assert 1 == len(calls) call = calls[0] @@ -972,13 +976,13 @@ async def test_temp_change_ac_trigger_off_long_enough_3(hass, setup_comp_7): await hass.async_block_till_done() await common.async_set_temperature(hass, 25) test_time = datetime.datetime.now(pytz.UTC) - _send_time_changed(hass, test_time) + async_fire_time_changed(hass, test_time) await hass.async_block_till_done() assert 0 == len(calls) - _send_time_changed(hass, test_time + datetime.timedelta(minutes=5)) + async_fire_time_changed(hass, test_time + datetime.timedelta(minutes=5)) await hass.async_block_till_done() assert 0 == len(calls) - _send_time_changed(hass, test_time + datetime.timedelta(minutes=10)) + async_fire_time_changed(hass, test_time + datetime.timedelta(minutes=10)) await hass.async_block_till_done() assert 1 == len(calls) call = calls[0] @@ -987,11 +991,6 @@ async def test_temp_change_ac_trigger_off_long_enough_3(hass, setup_comp_7): assert ENT_SWITCH == call.data["entity_id"] -def _send_time_changed(hass, now): - """Send a time changed event.""" - hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: now}) - - @pytest.fixture async def setup_comp_8(hass): """Initialize components.""" @@ -1025,13 +1024,13 @@ async def test_temp_change_heater_trigger_on_long_enough_2(hass, setup_comp_8): await hass.async_block_till_done() await common.async_set_temperature(hass, 25) test_time = datetime.datetime.now(pytz.UTC) - _send_time_changed(hass, test_time) + async_fire_time_changed(hass, test_time) await hass.async_block_till_done() assert 0 == len(calls) - _send_time_changed(hass, test_time + datetime.timedelta(minutes=5)) + async_fire_time_changed(hass, test_time + datetime.timedelta(minutes=5)) await hass.async_block_till_done() assert 0 == len(calls) - _send_time_changed(hass, test_time + datetime.timedelta(minutes=10)) + async_fire_time_changed(hass, test_time + datetime.timedelta(minutes=10)) await hass.async_block_till_done() assert 1 == len(calls) call = calls[0] @@ -1048,13 +1047,13 @@ async def test_temp_change_heater_trigger_off_long_enough_2(hass, setup_comp_8): await hass.async_block_till_done() await common.async_set_temperature(hass, 25) test_time = datetime.datetime.now(pytz.UTC) - _send_time_changed(hass, test_time) + async_fire_time_changed(hass, test_time) await hass.async_block_till_done() assert 0 == len(calls) - _send_time_changed(hass, test_time + datetime.timedelta(minutes=5)) + async_fire_time_changed(hass, test_time + datetime.timedelta(minutes=5)) await hass.async_block_till_done() assert 0 == len(calls) - _send_time_changed(hass, test_time + datetime.timedelta(minutes=10)) + async_fire_time_changed(hass, test_time + datetime.timedelta(minutes=10)) await hass.async_block_till_done() assert 1 == len(calls) call = calls[0] diff --git a/tests/components/here_travel_time/test_sensor.py b/tests/components/here_travel_time/test_sensor.py index c6240749aa3..386dbbdf0ee 100644 --- a/tests/components/here_travel_time/test_sensor.py +++ b/tests/components/here_travel_time/test_sensor.py @@ -567,7 +567,7 @@ async def test_bicycle(hass, requests_mock_credentials_check): assert sensor.attributes.get(ATTR_ICON) == ICON_BICYCLE -async def test_location_zone(hass, requests_mock_truck_response): +async def test_location_zone(hass, requests_mock_truck_response, legacy_patchable_time): """Test that origin/destination supplied by a zone works.""" utcnow = dt_util.utcnow() # Patching 'utcnow' to gain more control over the timed update. @@ -618,7 +618,9 @@ async def test_location_zone(hass, requests_mock_truck_response): _assert_truck_sensor(sensor) -async def test_location_sensor(hass, requests_mock_truck_response): +async def test_location_sensor( + hass, requests_mock_truck_response, legacy_patchable_time +): """Test that origin/destination supplied by a sensor works.""" utcnow = dt_util.utcnow() # Patching 'utcnow' to gain more control over the timed update. @@ -658,7 +660,9 @@ async def test_location_sensor(hass, requests_mock_truck_response): _assert_truck_sensor(sensor) -async def test_location_person(hass, requests_mock_truck_response): +async def test_location_person( + hass, requests_mock_truck_response, legacy_patchable_time +): """Test that origin/destination supplied by a person works.""" utcnow = dt_util.utcnow() # Patching 'utcnow' to gain more control over the timed update. @@ -707,7 +711,9 @@ async def test_location_person(hass, requests_mock_truck_response): _assert_truck_sensor(sensor) -async def test_location_device_tracker(hass, requests_mock_truck_response): +async def test_location_device_tracker( + hass, requests_mock_truck_response, legacy_patchable_time +): """Test that origin/destination supplied by a device_tracker works.""" utcnow = dt_util.utcnow() # Patching 'utcnow' to gain more control over the timed update. @@ -757,7 +763,7 @@ async def test_location_device_tracker(hass, requests_mock_truck_response): async def test_location_device_tracker_added_after_update( - hass, requests_mock_truck_response, caplog + hass, requests_mock_truck_response, legacy_patchable_time, caplog ): """Test that device_tracker added after first update works.""" caplog.set_level(logging.ERROR) diff --git a/tests/components/homekit/test_accessories.py b/tests/components/homekit/test_accessories.py index fd99230f206..b19e63d3b4c 100644 --- a/tests/components/homekit/test_accessories.py +++ b/tests/components/homekit/test_accessories.py @@ -2,7 +2,7 @@ This includes tests for all mock object types. """ -from datetime import datetime, timedelta +from datetime import timedelta import pytest @@ -37,9 +37,7 @@ from homeassistant.const import ( ATTR_BATTERY_CHARGING, ATTR_BATTERY_LEVEL, ATTR_ENTITY_ID, - ATTR_NOW, ATTR_SERVICE, - EVENT_TIME_CHANGED, STATE_OFF, STATE_ON, STATE_UNAVAILABLE, @@ -49,7 +47,7 @@ from homeassistant.helpers.event import TRACK_STATE_CHANGE_CALLBACKS import homeassistant.util.dt as dt_util from tests.async_mock import Mock, patch -from tests.common import async_mock_service +from tests.common import async_fire_time_changed, async_mock_service async def test_debounce(hass): @@ -66,11 +64,11 @@ async def test_debounce(hass): debounce_demo = debounce(demo_func) assert debounce_demo.__name__ == "demo_func" - now = datetime(2018, 1, 1, 20, 0, 0, tzinfo=dt_util.UTC) + now = dt_util.utcnow() with patch("homeassistant.util.dt.utcnow", return_value=now): await hass.async_add_executor_job(debounce_demo, mock, "value") - hass.bus.async_fire(EVENT_TIME_CHANGED, {ATTR_NOW: now + timedelta(seconds=3)}) + async_fire_time_changed(hass, now + timedelta(seconds=3)) await hass.async_block_till_done() assert counter == 1 assert len(arguments) == 2 @@ -79,7 +77,7 @@ async def test_debounce(hass): await hass.async_add_executor_job(debounce_demo, mock, "value") await hass.async_add_executor_job(debounce_demo, mock, "value") - hass.bus.async_fire(EVENT_TIME_CHANGED, {ATTR_NOW: now + timedelta(seconds=3)}) + async_fire_time_changed(hass, now + timedelta(seconds=3)) await hass.async_block_till_done() assert counter == 2 diff --git a/tests/components/homekit_controller/conftest.py b/tests/components/homekit_controller/conftest.py index ac4a0b4b5d6..3b023e0da51 100644 --- a/tests/components/homekit_controller/conftest.py +++ b/tests/components/homekit_controller/conftest.py @@ -5,13 +5,16 @@ from unittest import mock from aiohomekit.testing import FakeController import pytest +import homeassistant.util.dt as dt_util + import tests.async_mock @pytest.fixture def utcnow(request): """Freeze time at a known point.""" - start_dt = datetime.datetime(2019, 1, 1, 0, 0, 0) + now = dt_util.utcnow() + start_dt = datetime.datetime(now.year + 1, 1, 1, 0, 0, 0) with mock.patch("homeassistant.util.dt.utcnow") as dt_utcnow: dt_utcnow.return_value = start_dt yield dt_utcnow diff --git a/tests/components/islamic_prayer_times/test_init.py b/tests/components/islamic_prayer_times/test_init.py index 9fb9333e045..f3d4351ae29 100644 --- a/tests/components/islamic_prayer_times/test_init.py +++ b/tests/components/islamic_prayer_times/test_init.py @@ -85,7 +85,7 @@ async def test_unload_entry(hass): assert islamic_prayer_times.DOMAIN not in hass.data -async def test_islamic_prayer_times_timestamp_format(hass): +async def test_islamic_prayer_times_timestamp_format(hass, legacy_patchable_time): """Test Islamic prayer times timestamp format.""" entry = MockConfigEntry(domain=islamic_prayer_times.DOMAIN, data={}) entry.add_to_hass(hass) @@ -94,7 +94,6 @@ async def test_islamic_prayer_times_timestamp_format(hass): "prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times", return_value=PRAYER_TIMES, ), patch("homeassistant.util.dt.now", return_value=NOW): - await hass.config_entries.async_setup(entry.entry_id) assert ( @@ -103,7 +102,7 @@ async def test_islamic_prayer_times_timestamp_format(hass): ) -async def test_update(hass): +async def test_update(hass, legacy_patchable_time): """Test sensors are updated with new prayer times.""" entry = MockConfigEntry(domain=islamic_prayer_times.DOMAIN, data={}) entry.add_to_hass(hass) diff --git a/tests/components/islamic_prayer_times/test_sensor.py b/tests/components/islamic_prayer_times/test_sensor.py index 3ee6a59136a..13b69207cde 100644 --- a/tests/components/islamic_prayer_times/test_sensor.py +++ b/tests/components/islamic_prayer_times/test_sensor.py @@ -8,7 +8,7 @@ from tests.async_mock import patch from tests.common import MockConfigEntry -async def test_islamic_prayer_times_sensors(hass): +async def test_islamic_prayer_times_sensors(hass, legacy_patchable_time): """Test minimum Islamic prayer times configuration.""" entry = MockConfigEntry(domain=islamic_prayer_times.DOMAIN, data={}) entry.add_to_hass(hass) @@ -17,7 +17,6 @@ async def test_islamic_prayer_times_sensors(hass): "prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times", return_value=PRAYER_TIMES, ), patch("homeassistant.util.dt.now", return_value=NOW): - await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() diff --git a/tests/components/jewish_calendar/test_binary_sensor.py b/tests/components/jewish_calendar/test_binary_sensor.py index a9ea2449c6f..b9b980d29c2 100644 --- a/tests/components/jewish_calendar/test_binary_sensor.py +++ b/tests/components/jewish_calendar/test_binary_sensor.py @@ -60,7 +60,16 @@ MELACHA_TEST_IDS = [ ids=MELACHA_TEST_IDS, ) async def test_issur_melacha_sensor( - hass, now, candle_lighting, havdalah, diaspora, tzname, latitude, longitude, result + hass, + legacy_patchable_time, + now, + candle_lighting, + havdalah, + diaspora, + tzname, + latitude, + longitude, + result, ): """Test Issur Melacha sensor output.""" time_zone = dt_util.get_time_zone(tzname) diff --git a/tests/components/jewish_calendar/test_sensor.py b/tests/components/jewish_calendar/test_sensor.py index 59b6dc01313..60def2e09d2 100644 --- a/tests/components/jewish_calendar/test_sensor.py +++ b/tests/components/jewish_calendar/test_sensor.py @@ -144,7 +144,16 @@ TEST_IDS = [ ids=TEST_IDS, ) async def test_jewish_calendar_sensor( - hass, now, tzname, latitude, longitude, language, sensor, diaspora, result + hass, + legacy_patchable_time, + now, + tzname, + latitude, + longitude, + language, + sensor, + diaspora, + result, ): """Test Jewish calendar sensor output.""" time_zone = dt_util.get_time_zone(tzname) @@ -478,6 +487,7 @@ SHABBAT_TEST_IDS = [ ) async def test_shabbat_times_sensor( hass, + legacy_patchable_time, language, now, candle_lighting, @@ -553,7 +563,7 @@ OMER_TEST_IDS = [ @pytest.mark.parametrize(["test_time", "result"], OMER_PARAMS, ids=OMER_TEST_IDS) -async def test_omer_sensor(hass, test_time, result): +async def test_omer_sensor(hass, legacy_patchable_time, test_time, result): """Test Omer Count sensor output.""" test_time = hass.config.time_zone.localize(test_time) @@ -587,7 +597,7 @@ DAFYOMI_TEST_IDS = [ @pytest.mark.parametrize(["test_time", "result"], DAFYOMI_PARAMS, ids=DAFYOMI_TEST_IDS) -async def test_dafyomi_sensor(hass, test_time, result): +async def test_dafyomi_sensor(hass, legacy_patchable_time, test_time, result): """Test Daf Yomi sensor output.""" test_time = hass.config.time_zone.localize(test_time) diff --git a/tests/components/manual/test_alarm_control_panel.py b/tests/components/manual/test_alarm_control_panel.py index c1f7fd5a7e0..9cf76ebbc8f 100644 --- a/tests/components/manual/test_alarm_control_panel.py +++ b/tests/components/manual/test_alarm_control_panel.py @@ -1450,7 +1450,7 @@ async def test_armed_custom_bypass_with_specific_pending(hass): assert STATE_ALARM_ARMED_CUSTOM_BYPASS == hass.states.get(entity_id).state -async def test_arm_away_after_disabled_disarmed(hass): +async def test_arm_away_after_disabled_disarmed(hass, legacy_patchable_time): """Test pending state with and without zero trigger time.""" assert await async_setup_component( hass, diff --git a/tests/components/manual_mqtt/test_alarm_control_panel.py b/tests/components/manual_mqtt/test_alarm_control_panel.py index aa318d61b84..87a887b0751 100644 --- a/tests/components/manual_mqtt/test_alarm_control_panel.py +++ b/tests/components/manual_mqtt/test_alarm_control_panel.py @@ -1348,7 +1348,7 @@ async def test_trigger_with_specific_pending(hass, mqtt_mock): assert STATE_ALARM_DISARMED == hass.states.get(entity_id).state -async def test_arm_away_after_disabled_disarmed(hass, mqtt_mock): +async def test_arm_away_after_disabled_disarmed(hass, legacy_patchable_time, mqtt_mock): """Test pending state with and without zero trigger time.""" assert await async_setup_component( hass, diff --git a/tests/components/metoffice/test_sensor.py b/tests/components/metoffice/test_sensor.py index 70a66a3093c..5d6f2787861 100644 --- a/tests/components/metoffice/test_sensor.py +++ b/tests/components/metoffice/test_sensor.py @@ -23,9 +23,8 @@ from tests.common import MockConfigEntry, load_fixture "datapoint.Forecast.datetime.datetime", Mock(now=Mock(return_value=datetime(2020, 4, 25, 12, tzinfo=timezone.utc))), ) -async def test_one_sensor_site_running(hass, requests_mock): +async def test_one_sensor_site_running(hass, requests_mock, legacy_patchable_time): """Test the Met Office sensor platform.""" - # all metoffice test data encapsulated in here mock_json = json.loads(load_fixture("metoffice.json")) all_sites = json.dumps(mock_json["all_sites"]) @@ -62,7 +61,7 @@ async def test_one_sensor_site_running(hass, requests_mock): "datapoint.Forecast.datetime.datetime", Mock(now=Mock(return_value=datetime(2020, 4, 25, 12, tzinfo=timezone.utc))), ) -async def test_two_sensor_sites_running(hass, requests_mock): +async def test_two_sensor_sites_running(hass, requests_mock, legacy_patchable_time): """Test we handle two sets of sensors running for two different sites.""" # all metoffice test data encapsulated in here diff --git a/tests/components/metoffice/test_weather.py b/tests/components/metoffice/test_weather.py index 08440798f47..05cec7ef46e 100644 --- a/tests/components/metoffice/test_weather.py +++ b/tests/components/metoffice/test_weather.py @@ -20,7 +20,7 @@ from tests.common import MockConfigEntry, async_fire_time_changed, load_fixture "datapoint.Forecast.datetime.datetime", Mock(now=Mock(return_value=datetime(2020, 4, 25, 12, tzinfo=timezone.utc))), ) -async def test_site_cannot_connect(hass, requests_mock): +async def test_site_cannot_connect(hass, requests_mock, legacy_patchable_time): """Test we handle cannot connect error.""" requests_mock.get("/public/data/val/wxfcs/all/json/sitelist/", text="") @@ -42,7 +42,7 @@ async def test_site_cannot_connect(hass, requests_mock): "datapoint.Forecast.datetime.datetime", Mock(now=Mock(return_value=datetime(2020, 4, 25, 12, tzinfo=timezone.utc))), ) -async def test_site_cannot_update(hass, requests_mock): +async def test_site_cannot_update(hass, requests_mock, legacy_patchable_time): """Test we handle cannot connect error.""" # all metoffice test data encapsulated in here @@ -77,7 +77,7 @@ async def test_site_cannot_update(hass, requests_mock): "datapoint.Forecast.datetime.datetime", Mock(now=Mock(return_value=datetime(2020, 4, 25, 12, tzinfo=timezone.utc))), ) -async def test_one_weather_site_running(hass, requests_mock): +async def test_one_weather_site_running(hass, requests_mock, legacy_patchable_time): """Test the Met Office weather platform.""" # all metoffice test data encapsulated in here @@ -111,7 +111,7 @@ async def test_one_weather_site_running(hass, requests_mock): "datapoint.Forecast.datetime.datetime", Mock(now=Mock(return_value=datetime(2020, 4, 25, 12, tzinfo=timezone.utc))), ) -async def test_two_weather_sites_running(hass, requests_mock): +async def test_two_weather_sites_running(hass, requests_mock, legacy_patchable_time): """Test we handle two different weather sites both running.""" # all metoffice test data encapsulated in here diff --git a/tests/components/mikrotik/test_device_tracker.py b/tests/components/mikrotik/test_device_tracker.py index 643f94a5ad5..4e8ea93ab30 100644 --- a/tests/components/mikrotik/test_device_tracker.py +++ b/tests/components/mikrotik/test_device_tracker.py @@ -39,7 +39,7 @@ async def test_platform_manually_configured(hass): assert mikrotik.DOMAIN not in hass.data -async def test_device_trackers(hass): +async def test_device_trackers(hass, legacy_patchable_time): """Test device_trackers created by mikrotik.""" # test devices are added from wireless list only diff --git a/tests/components/moon/test_sensor.py b/tests/components/moon/test_sensor.py index fe6e57dd9b6..59210c63b90 100644 --- a/tests/components/moon/test_sensor.py +++ b/tests/components/moon/test_sensor.py @@ -1,46 +1,59 @@ """The test for the moon sensor platform.""" from datetime import datetime -import unittest -from homeassistant.setup import setup_component +from homeassistant.components.homeassistant import ( + DOMAIN as HA_DOMAIN, + SERVICE_UPDATE_ENTITY, +) +from homeassistant.const import ATTR_ENTITY_ID +from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util from tests.async_mock import patch -from tests.common import get_test_home_assistant DAY1 = datetime(2017, 1, 1, 1, tzinfo=dt_util.UTC) DAY2 = datetime(2017, 1, 18, 1, tzinfo=dt_util.UTC) -class TestMoonSensor(unittest.TestCase): +async def test_moon_day1(hass): """Test the Moon sensor.""" + config = {"sensor": {"platform": "moon", "name": "moon_day1"}} - def setup_method(self, method): - """Set up things to be run when tests are started.""" - self.hass = get_test_home_assistant() + await async_setup_component(hass, HA_DOMAIN, {}) + assert await async_setup_component(hass, "sensor", config) + await hass.async_block_till_done() - def teardown_method(self, method): - """Stop everything that was started.""" - self.hass.stop() + assert hass.states.get("sensor.moon_day1") - @patch("homeassistant.components.moon.sensor.dt_util.utcnow", return_value=DAY1) - def test_moon_day1(self, mock_request): - """Test the Moon sensor.""" - config = {"sensor": {"platform": "moon", "name": "moon_day1"}} + with patch( + "homeassistant.components.moon.sensor.dt_util.utcnow", return_value=DAY1 + ): + await async_update_entity(hass, "sensor.moon_day1") - assert setup_component(self.hass, "sensor", config) - self.hass.block_till_done() + assert hass.states.get("sensor.moon_day1").state == "waxing_crescent" - state = self.hass.states.get("sensor.moon_day1") - assert state.state == "waxing_crescent" - @patch("homeassistant.components.moon.sensor.dt_util.utcnow", return_value=DAY2) - def test_moon_day2(self, mock_request): - """Test the Moon sensor.""" - config = {"sensor": {"platform": "moon", "name": "moon_day2"}} +async def test_moon_day2(hass): + """Test the Moon sensor.""" + config = {"sensor": {"platform": "moon", "name": "moon_day2"}} - assert setup_component(self.hass, "sensor", config) - self.hass.block_till_done() + await async_setup_component(hass, HA_DOMAIN, {}) + assert await async_setup_component(hass, "sensor", config) + await hass.async_block_till_done() - state = self.hass.states.get("sensor.moon_day2") - assert state.state == "waning_gibbous" + assert hass.states.get("sensor.moon_day2") + + with patch( + "homeassistant.components.moon.sensor.dt_util.utcnow", return_value=DAY2 + ): + await async_update_entity(hass, "sensor.moon_day2") + + assert hass.states.get("sensor.moon_day2").state == "waning_gibbous" + + +async def async_update_entity(hass, entity_id): + """Run an update action for an entity.""" + await hass.services.async_call( + HA_DOMAIN, SERVICE_UPDATE_ENTITY, {ATTR_ENTITY_ID: entity_id}, blocking=True, + ) + await hass.async_block_till_done() diff --git a/tests/components/mqtt/test_binary_sensor.py b/tests/components/mqtt/test_binary_sensor.py index 67bb6704339..ff1c5a35a11 100644 --- a/tests/components/mqtt/test_binary_sensor.py +++ b/tests/components/mqtt/test_binary_sensor.py @@ -52,7 +52,9 @@ DEFAULT_CONFIG = { } -async def test_setting_sensor_value_expires_availability_topic(hass, mqtt_mock, caplog): +async def test_setting_sensor_value_expires_availability_topic( + hass, mqtt_mock, legacy_patchable_time, caplog +): """Test the expiration of the value.""" assert await async_setup_component( hass, @@ -82,7 +84,9 @@ async def test_setting_sensor_value_expires_availability_topic(hass, mqtt_mock, await expires_helper(hass, mqtt_mock, caplog) -async def test_setting_sensor_value_expires(hass, mqtt_mock, caplog): +async def test_setting_sensor_value_expires( + hass, mqtt_mock, legacy_patchable_time, caplog +): """Test the expiration of the value.""" assert await async_setup_component( hass, @@ -520,7 +524,7 @@ async def test_discovery_update_binary_sensor(hass, mqtt_mock, caplog): async def test_expiration_on_discovery_and_discovery_update_of_binary_sensor( - hass, mqtt_mock, caplog + hass, mqtt_mock, legacy_patchable_time, caplog ): """Test that binary_sensor with expire_after set behaves correctly on discovery and discovery update.""" entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0] diff --git a/tests/components/mqtt/test_sensor.py b/tests/components/mqtt/test_sensor.py index f54a27e8805..8e52e1e6f10 100644 --- a/tests/components/mqtt/test_sensor.py +++ b/tests/components/mqtt/test_sensor.py @@ -70,7 +70,9 @@ async def test_setting_sensor_value_via_mqtt_message(hass, mqtt_mock): assert state.attributes.get("unit_of_measurement") == "fav unit" -async def test_setting_sensor_value_expires(hass, mqtt_mock, caplog): +async def test_setting_sensor_value_expires( + hass, mqtt_mock, legacy_patchable_time, caplog +): """Test the expiration of the value.""" assert await async_setup_component( hass, @@ -91,7 +93,8 @@ async def test_setting_sensor_value_expires(hass, mqtt_mock, caplog): state = hass.states.get("sensor.test") assert state.state == "unknown" - now = datetime(2017, 1, 1, 1, tzinfo=dt_util.UTC) + realnow = dt_util.utcnow() + now = datetime(realnow.year + 1, 1, 1, 1, tzinfo=dt_util.UTC) with patch(("homeassistant.helpers.event.dt_util.utcnow"), return_value=now): async_fire_time_changed(hass, now) async_fire_mqtt_message(hass, "test-topic", "100") diff --git a/tests/components/pilight/test_init.py b/tests/components/pilight/test_init.py index 5c2acc0d8f2..1e7e71f8236 100644 --- a/tests/components/pilight/test_init.py +++ b/tests/components/pilight/test_init.py @@ -6,13 +6,16 @@ import unittest import pytest -from homeassistant import core as ha from homeassistant.components import pilight from homeassistant.setup import setup_component from homeassistant.util import dt as dt_util from tests.async_mock import patch -from tests.common import assert_setup_component, get_test_home_assistant +from tests.common import ( + assert_setup_component, + async_fire_time_changed, + get_test_home_assistant, +) _LOGGER = logging.getLogger(__name__) @@ -196,13 +199,13 @@ class TestPilight(unittest.TestCase): service_data1["protocol"] = [service_data1["protocol"]] service_data2["protocol"] = [service_data2["protocol"]] - self.hass.bus.fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: dt_util.utcnow()}) + async_fire_time_changed(self.hass, dt_util.utcnow()) self.hass.block_till_done() error_log_call = mock_pilight_error.call_args_list[-1] assert str(service_data1) in str(error_log_call) new_time = dt_util.utcnow() + timedelta(seconds=5) - self.hass.bus.fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: new_time}) + async_fire_time_changed(self.hass, new_time) self.hass.block_till_done() error_log_call = mock_pilight_error.call_args_list[-1] assert str(service_data2) in str(error_log_call) @@ -407,6 +410,6 @@ class TestPilightCallrateThrottler(unittest.TestCase): for i in range(3): exp.append(i) shifted_time = now + (timedelta(seconds=delay + 0.1) * i) - self.hass.bus.fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: shifted_time}) + async_fire_time_changed(self.hass, shifted_time) self.hass.block_till_done() assert runs == exp diff --git a/tests/components/push/test_camera.py b/tests/components/push/test_camera.py index 8f4bb43045e..74d975fc57c 100644 --- a/tests/components/push/test_camera.py +++ b/tests/components/push/test_camera.py @@ -2,11 +2,12 @@ from datetime import timedelta import io -from homeassistant import core as ha from homeassistant.config import async_process_ha_core_config from homeassistant.setup import async_setup_component from homeassistant.util import dt as dt_util +from tests.common import async_fire_time_changed + async def test_bad_posting(hass, aiohttp_client): """Test that posting to wrong api endpoint fails.""" @@ -74,7 +75,7 @@ async def test_posting_url(hass, aiohttp_client): # await timeout shifted_time = dt_util.utcnow() + timedelta(seconds=15) - hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: shifted_time}) + async_fire_time_changed(hass, shifted_time) await hass.async_block_till_done() # back to initial state diff --git a/tests/components/pvpc_hourly_pricing/test_config_flow.py b/tests/components/pvpc_hourly_pricing/test_config_flow.py index d76f74f64a1..5f72875c26a 100644 --- a/tests/components/pvpc_hourly_pricing/test_config_flow.py +++ b/tests/components/pvpc_hourly_pricing/test_config_flow.py @@ -15,7 +15,9 @@ from tests.common import date_util from tests.test_util.aiohttp import AiohttpClientMocker -async def test_config_flow(hass, pvpc_aioclient_mock: AiohttpClientMocker): +async def test_config_flow( + hass, legacy_patchable_time, pvpc_aioclient_mock: AiohttpClientMocker +): """ Test config flow for pvpc_hourly_pricing. diff --git a/tests/components/pvpc_hourly_pricing/test_sensor.py b/tests/components/pvpc_hourly_pricing/test_sensor.py index 781ce35b99f..57861b8b72b 100644 --- a/tests/components/pvpc_hourly_pricing/test_sensor.py +++ b/tests/components/pvpc_hourly_pricing/test_sensor.py @@ -29,7 +29,7 @@ async def _process_time_step( async def test_sensor_availability( - hass, caplog, pvpc_aioclient_mock: AiohttpClientMocker + hass, caplog, legacy_patchable_time, pvpc_aioclient_mock: AiohttpClientMocker ): """Test sensor availability and handling of cloud access.""" hass.config.time_zone = timezone("Europe/Madrid") diff --git a/tests/components/rflink/test_binary_sensor.py b/tests/components/rflink/test_binary_sensor.py index 6a5a0b7f0e2..e20d2554f97 100644 --- a/tests/components/rflink/test_binary_sensor.py +++ b/tests/components/rflink/test_binary_sensor.py @@ -116,7 +116,7 @@ async def test_entity_availability(hass, monkeypatch): assert hass.states.get("binary_sensor.test").state == STATE_OFF -async def test_off_delay(hass, monkeypatch): +async def test_off_delay(hass, legacy_patchable_time, monkeypatch): """Test off_delay option.""" # setup mocking rflink module event_callback, create, _, _ = await mock_rflink(hass, CONFIG, DOMAIN, monkeypatch) diff --git a/tests/components/statistics/test_sensor.py b/tests/components/statistics/test_sensor.py index 2234df8e5fe..f013d374106 100644 --- a/tests/components/statistics/test_sensor.py +++ b/tests/components/statistics/test_sensor.py @@ -3,6 +3,8 @@ from datetime import datetime, timedelta import statistics import unittest +import pytest + from homeassistant.components import recorder from homeassistant.components.statistics.sensor import StatisticsSensor from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT, STATE_UNKNOWN, TEMP_CELSIUS @@ -18,6 +20,12 @@ from tests.common import ( from tests.components.recorder.common import wait_recording_done +@pytest.fixture(autouse=True) +def mock_legacy_time(legacy_patchable_time): + """Make time patchable for all the tests.""" + yield + + class TestStatisticsSensor(unittest.TestCase): """Test the Statistics sensor.""" @@ -36,10 +44,7 @@ class TestStatisticsSensor(unittest.TestCase): self.change = round(self.values[-1] - self.values[0], 2) self.average_change = round(self.change / (len(self.values) - 1), 2) self.change_rate = round(self.change / (60 * (self.count - 1)), 2) - - def teardown_method(self, method): - """Stop everything that was started.""" - self.hass.stop() + self.addCleanup(self.hass.stop) def test_binary_sensor_source(self): """Test if source is a sensor.""" diff --git a/tests/components/sun/test_init.py b/tests/components/sun/test_init.py index e023814725b..56ac683582a 100644 --- a/tests/components/sun/test_init.py +++ b/tests/components/sun/test_init.py @@ -12,7 +12,7 @@ import homeassistant.util.dt as dt_util from tests.async_mock import patch -async def test_setting_rising(hass): +async def test_setting_rising(hass, legacy_patchable_time): """Test retrieving sun setting and rising.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) with patch("homeassistant.helpers.condition.dt_util.utcnow", return_value=utc_now): @@ -103,7 +103,7 @@ async def test_setting_rising(hass): ) -async def test_state_change(hass): +async def test_state_change(hass, legacy_patchable_time): """Test if the state changes at next setting/rising.""" now = datetime(2016, 6, 1, 8, 0, 0, tzinfo=dt_util.UTC) with patch("homeassistant.helpers.condition.dt_util.utcnow", return_value=now): diff --git a/tests/components/tod/test_binary_sensor.py b/tests/components/tod/test_binary_sensor.py index afa299ef063..b776477be5c 100644 --- a/tests/components/tod/test_binary_sensor.py +++ b/tests/components/tod/test_binary_sensor.py @@ -2,6 +2,7 @@ from datetime import datetime, timedelta import unittest +import pytest import pytz from homeassistant import setup @@ -15,6 +16,12 @@ from tests.async_mock import patch from tests.common import assert_setup_component, get_test_home_assistant +@pytest.fixture(autouse=True) +def mock_legacy_time(legacy_patchable_time): + """Make time patchable for all the tests.""" + yield + + class TestBinarySensorTod(unittest.TestCase): """Test for Binary sensor tod platform.""" diff --git a/tests/components/yr/test_sensor.py b/tests/components/yr/test_sensor.py index cb0345641b7..b339dd9c132 100644 --- a/tests/components/yr/test_sensor.py +++ b/tests/components/yr/test_sensor.py @@ -11,7 +11,7 @@ from tests.common import assert_setup_component, load_fixture NOW = datetime(2016, 6, 9, 1, tzinfo=dt_util.UTC) -async def test_default_setup(hass, aioclient_mock): +async def test_default_setup(hass, legacy_patchable_time, aioclient_mock): """Test the default setup.""" aioclient_mock.get( "https://aa015h6buqvih86i1.api.met.no/weatherapi/locationforecast/1.9/", @@ -19,6 +19,7 @@ async def test_default_setup(hass, aioclient_mock): ) config = {"platform": "yr", "elevation": 0} hass.allow_pool = True + with patch( "homeassistant.components.yr.sensor.dt_util.utcnow", return_value=NOW ), assert_setup_component(1): @@ -31,7 +32,7 @@ async def test_default_setup(hass, aioclient_mock): assert state.attributes.get("unit_of_measurement") is None -async def test_custom_setup(hass, aioclient_mock): +async def test_custom_setup(hass, legacy_patchable_time, aioclient_mock): """Test a custom setup.""" aioclient_mock.get( "https://aa015h6buqvih86i1.api.met.no/weatherapi/locationforecast/1.9/", @@ -50,6 +51,7 @@ async def test_custom_setup(hass, aioclient_mock): ], } hass.allow_pool = True + with patch( "homeassistant.components.yr.sensor.dt_util.utcnow", return_value=NOW ), assert_setup_component(1): @@ -77,7 +79,7 @@ async def test_custom_setup(hass, aioclient_mock): assert state.state == "3.5" -async def test_forecast_setup(hass, aioclient_mock): +async def test_forecast_setup(hass, legacy_patchable_time, aioclient_mock): """Test a custom setup with 24h forecast.""" aioclient_mock.get( "https://aa015h6buqvih86i1.api.met.no/weatherapi/locationforecast/1.9/", @@ -97,6 +99,7 @@ async def test_forecast_setup(hass, aioclient_mock): ], } hass.allow_pool = True + with patch( "homeassistant.components.yr.sensor.dt_util.utcnow", return_value=NOW ), assert_setup_component(1): diff --git a/tests/conftest.py b/tests/conftest.py index a2fa8e8b2fd..0d100afc275 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,7 +5,7 @@ import logging import pytest import requests_mock as _requests_mock -from homeassistant import core as ha, util +from homeassistant import core as ha, loader, util from homeassistant.auth.const import GROUP_ID_ADMIN, GROUP_ID_READ_ONLY from homeassistant.auth.providers import homeassistant, legacy_api_password from homeassistant.components import mqtt @@ -15,7 +15,9 @@ from homeassistant.components.websocket_api.auth import ( TYPE_AUTH_REQUIRED, ) from homeassistant.components.websocket_api.http import URL +from homeassistant.const import ATTR_NOW, EVENT_TIME_CHANGED from homeassistant.exceptions import ServiceNotFound +from homeassistant.helpers import event from homeassistant.setup import async_setup_component from homeassistant.util import location @@ -315,3 +317,43 @@ async def mqtt_mock(hass, mqtt_client_mock, mqtt_config): component = hass.data["mqtt"] component.reset_mock() return component + + +@pytest.fixture +def legacy_patchable_time(): + """Allow time to be patchable by using event listeners instead of asyncio loop.""" + + @ha.callback + @loader.bind_hass + def async_track_point_in_utc_time(hass, action, point_in_time): + """Add a listener that fires once after a specific point in UTC time.""" + # Ensure point_in_time is UTC + point_in_time = event.dt_util.as_utc(point_in_time) + + @ha.callback + def point_in_time_listener(event): + """Listen for matching time_changed events.""" + now = event.data[ATTR_NOW] + + if now < point_in_time or hasattr(point_in_time_listener, "run"): + return + + # Set variable so that we will never run twice. + # Because the event bus might have to wait till a thread comes + # available to execute this listener it might occur that the + # listener gets lined up twice to be executed. This will make + # sure the second time it does nothing. + setattr(point_in_time_listener, "run", True) + async_unsub() + + hass.async_run_job(action, now) + + async_unsub = hass.bus.async_listen(EVENT_TIME_CHANGED, point_in_time_listener) + + return async_unsub + + with patch( + "homeassistant.helpers.event.async_track_point_in_utc_time", + async_track_point_in_utc_time, + ): + yield diff --git a/tests/helpers/test_event.py b/tests/helpers/test_event.py index 2d5ee9a9a73..eff0e6e973b 100644 --- a/tests/helpers/test_event.py +++ b/tests/helpers/test_event.py @@ -38,11 +38,6 @@ def teardown(): dt_util.set_default_time_zone(DEFAULT_TIME_ZONE) -def _send_time_changed(hass, now): - """Send a time changed event.""" - hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: now}) - - async def test_track_point_in_time(hass): """Test track point in time.""" before_birthday = datetime(1985, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC) @@ -55,16 +50,16 @@ async def test_track_point_in_time(hass): hass, callback(lambda x: runs.append(1)), birthday_paulus ) - _send_time_changed(hass, before_birthday) + async_fire_time_changed(hass, before_birthday) await hass.async_block_till_done() assert len(runs) == 0 - _send_time_changed(hass, birthday_paulus) + async_fire_time_changed(hass, birthday_paulus) await hass.async_block_till_done() assert len(runs) == 1 # A point in time tracker will only fire once, this should do nothing - _send_time_changed(hass, birthday_paulus) + async_fire_time_changed(hass, birthday_paulus) await hass.async_block_till_done() assert len(runs) == 1 @@ -72,7 +67,7 @@ async def test_track_point_in_time(hass): hass, callback(lambda x: runs.append(1)), birthday_paulus ) - _send_time_changed(hass, after_birthday) + async_fire_time_changed(hass, after_birthday) await hass.async_block_till_done() assert len(runs) == 2 @@ -81,7 +76,7 @@ async def test_track_point_in_time(hass): ) unsub() - _send_time_changed(hass, after_birthday) + async_fire_time_changed(hass, after_birthday) await hass.async_block_till_done() assert len(runs) == 2 @@ -458,26 +453,26 @@ async def test_track_time_interval(hass): hass, lambda x: specific_runs.append(1), timedelta(seconds=10) ) - _send_time_changed(hass, utc_now + timedelta(seconds=5)) + async_fire_time_changed(hass, utc_now + timedelta(seconds=5)) await hass.async_block_till_done() assert len(specific_runs) == 0 - _send_time_changed(hass, utc_now + timedelta(seconds=13)) + async_fire_time_changed(hass, utc_now + timedelta(seconds=13)) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, utc_now + timedelta(minutes=20)) + async_fire_time_changed(hass, utc_now + timedelta(minutes=20)) await hass.async_block_till_done() assert len(specific_runs) == 2 unsub() - _send_time_changed(hass, utc_now + timedelta(seconds=30)) + async_fire_time_changed(hass, utc_now + timedelta(seconds=30)) await hass.async_block_till_done() assert len(specific_runs) == 2 -async def test_track_sunrise(hass): +async def test_track_sunrise(hass, legacy_patchable_time): """Test track the sunrise.""" latitude = 32.87336 longitude = 117.22743 @@ -514,17 +509,17 @@ async def test_track_sunrise(hass): unsub2 = async_track_sunrise(hass, lambda: offset_runs.append(1), offset) # run tests - _send_time_changed(hass, next_rising - offset) + async_fire_time_changed(hass, next_rising - offset) await hass.async_block_till_done() assert len(runs) == 0 assert len(offset_runs) == 0 - _send_time_changed(hass, next_rising) + async_fire_time_changed(hass, next_rising) await hass.async_block_till_done() assert len(runs) == 1 assert len(offset_runs) == 0 - _send_time_changed(hass, next_rising + offset) + async_fire_time_changed(hass, next_rising + offset) await hass.async_block_till_done() assert len(runs) == 1 assert len(offset_runs) == 1 @@ -532,13 +527,13 @@ async def test_track_sunrise(hass): unsub() unsub2() - _send_time_changed(hass, next_rising + offset) + async_fire_time_changed(hass, next_rising + offset) await hass.async_block_till_done() assert len(runs) == 1 assert len(offset_runs) == 1 -async def test_track_sunrise_update_location(hass): +async def test_track_sunrise_update_location(hass, legacy_patchable_time): """Test track the sunrise.""" # Setup sun component hass.config.latitude = 32.87336 @@ -567,7 +562,7 @@ async def test_track_sunrise_update_location(hass): async_track_sunrise(hass, lambda: runs.append(1)) # Mimic sunrise - _send_time_changed(hass, next_rising) + async_fire_time_changed(hass, next_rising) await hass.async_block_till_done() assert len(runs) == 1 @@ -577,7 +572,7 @@ async def test_track_sunrise_update_location(hass): await hass.async_block_till_done() # Mimic sunrise - _send_time_changed(hass, next_rising) + async_fire_time_changed(hass, next_rising) await hass.async_block_till_done() # Did not increase assert len(runs) == 1 @@ -593,12 +588,12 @@ async def test_track_sunrise_update_location(hass): mod += 1 # Mimic sunrise at new location - _send_time_changed(hass, next_rising) + async_fire_time_changed(hass, next_rising) await hass.async_block_till_done() assert len(runs) == 2 -async def test_track_sunset(hass): +async def test_track_sunset(hass, legacy_patchable_time): """Test track the sunset.""" latitude = 32.87336 longitude = 117.22743 @@ -635,17 +630,17 @@ async def test_track_sunset(hass): unsub2 = async_track_sunset(hass, lambda: offset_runs.append(1), offset) # Run tests - _send_time_changed(hass, next_setting - offset) + async_fire_time_changed(hass, next_setting - offset) await hass.async_block_till_done() assert len(runs) == 0 assert len(offset_runs) == 0 - _send_time_changed(hass, next_setting) + async_fire_time_changed(hass, next_setting) await hass.async_block_till_done() assert len(runs) == 1 assert len(offset_runs) == 0 - _send_time_changed(hass, next_setting + offset) + async_fire_time_changed(hass, next_setting + offset) await hass.async_block_till_done() assert len(runs) == 1 assert len(offset_runs) == 1 @@ -653,7 +648,7 @@ async def test_track_sunset(hass): unsub() unsub2() - _send_time_changed(hass, next_setting + offset) + async_fire_time_changed(hass, next_setting + offset) await hass.async_block_till_done() assert len(runs) == 1 assert len(offset_runs) == 1 @@ -669,17 +664,17 @@ async def test_async_track_time_change(hass): hass, lambda x: specific_runs.append(1), second=[0, 30] ) - _send_time_changed(hass, datetime(2014, 5, 24, 12, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 12, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 1 assert len(wildcard_runs) == 1 - _send_time_changed(hass, datetime(2014, 5, 24, 12, 0, 15)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 12, 0, 15)) await hass.async_block_till_done() assert len(specific_runs) == 1 assert len(wildcard_runs) == 2 - _send_time_changed(hass, datetime(2014, 5, 24, 12, 0, 30)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 12, 0, 30)) await hass.async_block_till_done() assert len(specific_runs) == 2 assert len(wildcard_runs) == 3 @@ -687,7 +682,7 @@ async def test_async_track_time_change(hass): unsub() unsub_utc() - _send_time_changed(hass, datetime(2014, 5, 24, 12, 0, 30)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 12, 0, 30)) await hass.async_block_till_done() assert len(specific_runs) == 2 assert len(wildcard_runs) == 3 @@ -701,21 +696,21 @@ async def test_periodic_task_minute(hass): hass, lambda x: specific_runs.append(1), minute="/5", second=0 ) - _send_time_changed(hass, datetime(2014, 5, 24, 12, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 12, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, datetime(2014, 5, 24, 12, 3, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 12, 3, 0)) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, datetime(2014, 5, 24, 12, 5, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 12, 5, 0)) await hass.async_block_till_done() assert len(specific_runs) == 2 unsub() - _send_time_changed(hass, datetime(2014, 5, 24, 12, 5, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 12, 5, 0)) await hass.async_block_till_done() assert len(specific_runs) == 2 @@ -728,29 +723,29 @@ async def test_periodic_task_hour(hass): hass, lambda x: specific_runs.append(1), hour="/2", minute=0, second=0 ) - _send_time_changed(hass, datetime(2014, 5, 24, 22, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 22, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, datetime(2014, 5, 24, 23, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 23, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, datetime(2014, 5, 25, 0, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 25, 0, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 2 - _send_time_changed(hass, datetime(2014, 5, 25, 1, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 25, 1, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 2 - _send_time_changed(hass, datetime(2014, 5, 25, 2, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 25, 2, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 3 unsub() - _send_time_changed(hass, datetime(2014, 5, 25, 2, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 25, 2, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 3 @@ -764,7 +759,7 @@ async def test_periodic_task_wrong_input(hass): hass, lambda x: specific_runs.append(1), hour="/two" ) - _send_time_changed(hass, datetime(2014, 5, 2, 0, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 2, 0, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 0 @@ -777,29 +772,29 @@ async def test_periodic_task_clock_rollback(hass): hass, lambda x: specific_runs.append(1), hour="/2", minute=0, second=0 ) - _send_time_changed(hass, datetime(2014, 5, 24, 22, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 22, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, datetime(2014, 5, 24, 23, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 23, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, datetime(2014, 5, 24, 22, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 22, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 2 - _send_time_changed(hass, datetime(2014, 5, 24, 0, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 0, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 3 - _send_time_changed(hass, datetime(2014, 5, 25, 2, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 25, 2, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 4 unsub() - _send_time_changed(hass, datetime(2014, 5, 25, 2, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 25, 2, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 4 @@ -812,15 +807,15 @@ async def test_periodic_task_duplicate_time(hass): hass, lambda x: specific_runs.append(1), hour="/2", minute=0, second=0 ) - _send_time_changed(hass, datetime(2014, 5, 24, 22, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 22, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, datetime(2014, 5, 24, 22, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 24, 22, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed(hass, datetime(2014, 5, 25, 0, 0, 0)) + async_fire_time_changed(hass, datetime(2014, 5, 25, 0, 0, 0)) await hass.async_block_till_done() assert len(specific_runs) == 2 @@ -837,19 +832,19 @@ async def test_periodic_task_entering_dst(hass): hass, lambda x: specific_runs.append(1), hour=2, minute=30, second=0 ) - _send_time_changed(hass, timezone.localize(datetime(2018, 3, 25, 1, 50, 0))) + async_fire_time_changed(hass, timezone.localize(datetime(2018, 3, 25, 1, 50, 0))) await hass.async_block_till_done() assert len(specific_runs) == 0 - _send_time_changed(hass, timezone.localize(datetime(2018, 3, 25, 3, 50, 0))) + async_fire_time_changed(hass, timezone.localize(datetime(2018, 3, 25, 3, 50, 0))) await hass.async_block_till_done() assert len(specific_runs) == 0 - _send_time_changed(hass, timezone.localize(datetime(2018, 3, 26, 1, 50, 0))) + async_fire_time_changed(hass, timezone.localize(datetime(2018, 3, 26, 1, 50, 0))) await hass.async_block_till_done() assert len(specific_runs) == 0 - _send_time_changed(hass, timezone.localize(datetime(2018, 3, 26, 2, 50, 0))) + async_fire_time_changed(hass, timezone.localize(datetime(2018, 3, 26, 2, 50, 0))) await hass.async_block_till_done() assert len(specific_runs) == 1 @@ -866,25 +861,25 @@ async def test_periodic_task_leaving_dst(hass): hass, lambda x: specific_runs.append(1), hour=2, minute=30, second=0 ) - _send_time_changed( + async_fire_time_changed( hass, timezone.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=False) ) await hass.async_block_till_done() assert len(specific_runs) == 0 - _send_time_changed( + async_fire_time_changed( hass, timezone.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=False) ) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed( + async_fire_time_changed( hass, timezone.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=True) ) await hass.async_block_till_done() assert len(specific_runs) == 1 - _send_time_changed( + async_fire_time_changed( hass, timezone.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True) ) await hass.async_block_till_done()