Convert core tests to async (#43287)

This commit is contained in:
Paulus Schoutsen 2020-11-16 18:25:55 +01:00 committed by GitHub
parent 819dd27925
commit 479de9433c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -6,7 +6,6 @@ import functools
import logging
import os
from tempfile import TemporaryDirectory
import unittest
import pytest
import pytz
@ -33,16 +32,16 @@ from homeassistant.const import (
__version__,
)
import homeassistant.core as ha
from homeassistant.exceptions import InvalidEntityFormatError, InvalidStateError
from homeassistant.exceptions import (
InvalidEntityFormatError,
InvalidStateError,
ServiceNotFound,
)
import homeassistant.util.dt as dt_util
from homeassistant.util.unit_system import METRIC_SYSTEM
from tests.async_mock import MagicMock, Mock, PropertyMock, patch
from tests.common import (
async_capture_events,
async_mock_service,
get_test_home_assistant,
)
from tests.common import async_capture_events, async_mock_service
PST = pytz.timezone("America/Los_Angeles")
@ -337,7 +336,7 @@ def test_state_as_dict():
assert state.as_dict() is state.as_dict()
async def test_add_remove_listener(hass):
async def test_eventbus_add_remove_listener(hass):
"""Test remove_listener method."""
old_count = len(hass.bus.async_listeners())
@ -356,7 +355,7 @@ async def test_add_remove_listener(hass):
unsub()
async def test_unsubscribe_listener(hass):
async def test_eventbus_unsubscribe_listener(hass):
"""Test unsubscribe listener from returned function."""
calls = []
@ -380,7 +379,7 @@ async def test_unsubscribe_listener(hass):
assert len(calls) == 1
async def test_listen_once_event_with_callback(hass):
async def test_eventbus_listen_once_event_with_callback(hass):
"""Test listen_once_event method."""
runs = []
@ -398,7 +397,7 @@ async def test_listen_once_event_with_callback(hass):
assert len(runs) == 1
async def test_listen_once_event_with_coroutine(hass):
async def test_eventbus_listen_once_event_with_coroutine(hass):
"""Test listen_once_event method."""
runs = []
@ -415,7 +414,7 @@ async def test_listen_once_event_with_coroutine(hass):
assert len(runs) == 1
async def test_listen_once_event_with_thread(hass):
async def test_eventbus_listen_once_event_with_thread(hass):
"""Test listen_once_event method."""
runs = []
@ -432,7 +431,7 @@ async def test_listen_once_event_with_thread(hass):
assert len(runs) == 1
async def test_thread_event_listener(hass):
async def test_eventbus_thread_event_listener(hass):
"""Test thread event listener."""
thread_calls = []
@ -445,7 +444,7 @@ async def test_thread_event_listener(hass):
assert len(thread_calls) == 1
async def test_callback_event_listener(hass):
async def test_eventbus_callback_event_listener(hass):
"""Test callback event listener."""
callback_calls = []
@ -459,7 +458,7 @@ async def test_callback_event_listener(hass):
assert len(callback_calls) == 1
async def test_coroutine_event_listener(hass):
async def test_eventbus_coroutine_event_listener(hass):
"""Test coroutine event listener."""
coroutine_calls = []
@ -550,117 +549,92 @@ def test_state_repr():
)
class TestStateMachine(unittest.TestCase):
"""Test State machine methods."""
async def test_statemachine_is_state(hass):
"""Test is_state method."""
hass.states.async_set("light.bowl", "on", {})
assert hass.states.is_state("light.Bowl", "on")
assert not hass.states.is_state("light.Bowl", "off")
assert not hass.states.is_state("light.Non_existing", "on")
# pylint: disable=invalid-name
def setUp(self):
"""Set up things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.states = self.hass.states
self.states.set("light.Bowl", "on")
self.states.set("switch.AC", "off")
# pylint: disable=invalid-name
def tearDown(self):
"""Stop down stuff we started."""
self.hass.stop()
async def test_statemachine_entity_ids(hass):
"""Test get_entity_ids method."""
hass.states.async_set("light.bowl", "on", {})
hass.states.async_set("SWITCH.AC", "off", {})
ent_ids = hass.states.async_entity_ids()
assert len(ent_ids) == 2
assert "light.bowl" in ent_ids
assert "switch.ac" in ent_ids
def test_is_state(self):
"""Test is_state method."""
assert self.states.is_state("light.Bowl", "on")
assert not self.states.is_state("light.Bowl", "off")
assert not self.states.is_state("light.Non_existing", "on")
ent_ids = hass.states.async_entity_ids("light")
assert len(ent_ids) == 1
assert "light.bowl" in ent_ids
def test_entity_ids(self):
"""Test get_entity_ids method."""
ent_ids = self.states.entity_ids()
assert len(ent_ids) == 2
assert "light.bowl" in ent_ids
assert "switch.ac" in ent_ids
states = sorted(state.entity_id for state in hass.states.async_all())
assert states == ["light.bowl", "switch.ac"]
ent_ids = self.states.entity_ids("light")
assert len(ent_ids) == 1
assert "light.bowl" in ent_ids
def test_all(self):
"""Test everything."""
states = sorted(state.entity_id for state in self.states.all())
assert ["light.bowl", "switch.ac"] == states
async def test_statemachine_remove(hass):
"""Test remove method."""
hass.states.async_set("light.bowl", "on", {})
events = async_capture_events(hass, EVENT_STATE_CHANGED)
def test_remove(self):
"""Test remove method."""
events = []
assert "light.bowl" in hass.states.async_entity_ids()
assert hass.states.async_remove("light.bowl")
await hass.async_block_till_done()
@ha.callback
def callback(event):
events.append(event)
assert "light.bowl" not in hass.states.async_entity_ids()
assert len(events) == 1
assert events[0].data.get("entity_id") == "light.bowl"
assert events[0].data.get("old_state") is not None
assert events[0].data["old_state"].entity_id == "light.bowl"
assert events[0].data.get("new_state") is None
self.hass.bus.listen(EVENT_STATE_CHANGED, callback)
# If it does not exist, we should get False
assert not hass.states.async_remove("light.Bowl")
await hass.async_block_till_done()
assert len(events) == 1
assert "light.bowl" in self.states.entity_ids()
assert self.states.remove("light.bowl")
self.hass.block_till_done()
assert "light.bowl" not in self.states.entity_ids()
assert len(events) == 1
assert events[0].data.get("entity_id") == "light.bowl"
assert events[0].data.get("old_state") is not None
assert events[0].data["old_state"].entity_id == "light.bowl"
assert events[0].data.get("new_state") is None
async def test_statemachine_case_insensitivty(hass):
"""Test insensitivty."""
events = async_capture_events(hass, EVENT_STATE_CHANGED)
# If it does not exist, we should get False
assert not self.states.remove("light.Bowl")
self.hass.block_till_done()
assert len(events) == 1
hass.states.async_set("light.BOWL", "off")
await hass.async_block_till_done()
def test_case_insensitivty(self):
"""Test insensitivty."""
runs = []
assert hass.states.is_state("light.bowl", "off")
assert len(events) == 1
@ha.callback
def callback(event):
runs.append(event)
self.hass.bus.listen(EVENT_STATE_CHANGED, callback)
async def test_statemachine_last_changed_not_updated_on_same_state(hass):
"""Test to not update the existing, same state."""
hass.states.async_set("light.bowl", "on", {})
state = hass.states.get("light.Bowl")
self.states.set("light.BOWL", "off")
self.hass.block_till_done()
future = dt_util.utcnow() + timedelta(hours=10)
assert self.states.is_state("light.bowl", "off")
assert len(runs) == 1
with patch("homeassistant.util.dt.utcnow", return_value=future):
hass.states.async_set("light.Bowl", "on", {"attr": "triggers_change"})
await hass.async_block_till_done()
def test_last_changed_not_updated_on_same_state(self):
"""Test to not update the existing, same state."""
state = self.states.get("light.Bowl")
state2 = hass.states.get("light.Bowl")
assert state2 is not None
assert state.last_changed == state2.last_changed
future = dt_util.utcnow() + timedelta(hours=10)
with patch("homeassistant.util.dt.utcnow", return_value=future):
self.states.set("light.Bowl", "on", {"attr": "triggers_change"})
self.hass.block_till_done()
async def test_statemachine_force_update(hass):
"""Test force update option."""
hass.states.async_set("light.bowl", "on", {})
events = async_capture_events(hass, EVENT_STATE_CHANGED)
state2 = self.states.get("light.Bowl")
assert state2 is not None
assert state.last_changed == state2.last_changed
hass.states.async_set("light.bowl", "on")
await hass.async_block_till_done()
assert len(events) == 0
def test_force_update(self):
"""Test force update option."""
events = []
@ha.callback
def callback(event):
events.append(event)
self.hass.bus.listen(EVENT_STATE_CHANGED, callback)
self.states.set("light.bowl", "on")
self.hass.block_till_done()
assert len(events) == 0
self.states.set("light.bowl", "on", None, True)
self.hass.block_till_done()
assert len(events) == 1
hass.states.async_set("light.bowl", "on", None, True)
await hass.async_block_till_done()
assert len(events) == 1
def test_service_call_repr():
@ -675,202 +649,154 @@ def test_service_call_repr():
)
class TestServiceRegistry(unittest.TestCase):
"""Test ServicerRegistry methods."""
async def test_serviceregistry_has_service(hass):
"""Test has_service method."""
hass.services.async_register("test_domain", "test_service", lambda call: None)
assert len(hass.services.async_services()) == 1
assert hass.services.has_service("tesT_domaiN", "tesT_servicE")
assert not hass.services.has_service("test_domain", "non_existing")
assert not hass.services.has_service("non_existing", "test_service")
# pylint: disable=invalid-name
def setUp(self):
"""Set up things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.services = self.hass.services
@ha.callback
def mock_service(call):
pass
async def test_serviceregistry_call_with_blocking_done_in_time(hass):
"""Test call with blocking."""
registered_events = async_capture_events(hass, EVENT_SERVICE_REGISTERED)
calls = async_mock_service(hass, "test_domain", "register_calls")
await hass.async_block_till_done()
self.services.register("Test_Domain", "TEST_SERVICE", mock_service)
assert len(registered_events) == 1
assert registered_events[0].data["domain"] == "test_domain"
assert registered_events[0].data["service"] == "register_calls"
self.calls_register = []
assert await hass.services.async_call(
"test_domain", "REGISTER_CALLS", blocking=True
)
assert len(calls) == 1
@ha.callback
def mock_event_register(event):
"""Mock register event."""
self.calls_register.append(event)
self.hass.bus.listen(EVENT_SERVICE_REGISTERED, mock_event_register)
async def test_serviceregistry_call_non_existing_with_blocking(hass):
"""Test non-existing with blocking."""
with pytest.raises(ha.ServiceNotFound):
await hass.services.async_call("test_domain", "i_do_not_exist", blocking=True)
# pylint: disable=invalid-name
def tearDown(self):
"""Stop down stuff we started."""
self.hass.stop()
def test_has_service(self):
"""Test has_service method."""
assert self.services.has_service("tesT_domaiN", "tesT_servicE")
assert not self.services.has_service("test_domain", "non_existing")
assert not self.services.has_service("non_existing", "test_service")
async def test_serviceregistry_async_service(hass):
"""Test registering and calling an async service."""
calls = []
def test_services(self):
"""Test services."""
assert len(self.services.services) == 1
async def service_handler(call):
"""Service handler coroutine."""
calls.append(call)
def test_call_with_blocking_done_in_time(self):
"""Test call with blocking."""
calls = []
hass.services.async_register("test_domain", "register_calls", service_handler)
@ha.callback
def service_handler(call):
"""Service handler."""
calls.append(call)
assert await hass.services.async_call(
"test_domain", "REGISTER_CALLS", blocking=True
)
assert len(calls) == 1
self.services.register("test_domain", "register_calls", service_handler)
self.hass.block_till_done()
assert len(self.calls_register) == 1
assert self.calls_register[-1].data["domain"] == "test_domain"
assert self.calls_register[-1].data["service"] == "register_calls"
async def test_serviceregistry_async_service_partial(hass):
"""Test registering and calling an wrapped async service."""
calls = []
assert self.services.call("test_domain", "REGISTER_CALLS", blocking=True)
assert len(calls) == 1
async def service_handler(call):
"""Service handler coroutine."""
calls.append(call)
def test_call_non_existing_with_blocking(self):
"""Test non-existing with blocking."""
with pytest.raises(ha.ServiceNotFound):
self.services.call("test_domain", "i_do_not_exist", blocking=True)
hass.services.async_register(
"test_domain", "register_calls", functools.partial(service_handler)
)
await hass.async_block_till_done()
def test_async_service(self):
"""Test registering and calling an async service."""
calls = []
assert await hass.services.async_call(
"test_domain", "REGISTER_CALLS", blocking=True
)
assert len(calls) == 1
async def service_handler(call):
"""Service handler coroutine."""
calls.append(call)
self.services.register("test_domain", "register_calls", service_handler)
self.hass.block_till_done()
async def test_serviceregistry_callback_service(hass):
"""Test registering and calling an async service."""
calls = []
assert len(self.calls_register) == 1
assert self.calls_register[-1].data["domain"] == "test_domain"
assert self.calls_register[-1].data["service"] == "register_calls"
@ha.callback
def service_handler(call):
"""Service handler coroutine."""
calls.append(call)
assert self.services.call("test_domain", "REGISTER_CALLS", blocking=True)
self.hass.block_till_done()
assert len(calls) == 1
hass.services.async_register("test_domain", "register_calls", service_handler)
def test_async_service_partial(self):
"""Test registering and calling an wrapped async service."""
calls = []
assert await hass.services.async_call(
"test_domain", "REGISTER_CALLS", blocking=True
)
assert len(calls) == 1
async def service_handler(call):
"""Service handler coroutine."""
calls.append(call)
self.services.register(
"test_domain", "register_calls", functools.partial(service_handler)
async def test_serviceregistry_remove_service(hass):
"""Test remove service."""
calls_remove = async_capture_events(hass, EVENT_SERVICE_REMOVED)
hass.services.async_register("test_domain", "test_service", lambda call: None)
assert hass.services.has_service("test_Domain", "test_Service")
hass.services.async_remove("test_Domain", "test_Service")
await hass.async_block_till_done()
assert not hass.services.has_service("test_Domain", "test_Service")
assert len(calls_remove) == 1
assert calls_remove[-1].data["domain"] == "test_domain"
assert calls_remove[-1].data["service"] == "test_service"
async def test_serviceregistry_service_that_not_exists(hass):
"""Test remove service that not exists."""
calls_remove = async_capture_events(hass, EVENT_SERVICE_REMOVED)
assert not hass.services.has_service("test_xxx", "test_yyy")
hass.services.async_remove("test_xxx", "test_yyy")
await hass.async_block_till_done()
assert len(calls_remove) == 0
with pytest.raises(ServiceNotFound):
await hass.services.async_call("test_do_not", "exist", {})
async def test_serviceregistry_async_service_raise_exception(hass):
"""Test registering and calling an async service raise exception."""
async def service_handler(_):
"""Service handler coroutine."""
raise ValueError
hass.services.async_register("test_domain", "register_calls", service_handler)
with pytest.raises(ValueError):
assert await hass.services.async_call(
"test_domain", "REGISTER_CALLS", blocking=True
)
self.hass.block_till_done()
assert len(self.calls_register) == 1
assert self.calls_register[-1].data["domain"] == "test_domain"
assert self.calls_register[-1].data["service"] == "register_calls"
# Non-blocking service call never throw exception
await hass.services.async_call("test_domain", "REGISTER_CALLS", blocking=False)
await hass.async_block_till_done()
assert self.services.call("test_domain", "REGISTER_CALLS", blocking=True)
self.hass.block_till_done()
assert len(calls) == 1
def test_callback_service(self):
"""Test registering and calling an async service."""
calls = []
async def test_serviceregistry_callback_service_raise_exception(hass):
"""Test registering and calling an callback service raise exception."""
@ha.callback
def service_handler(call):
"""Service handler coroutine."""
calls.append(call)
@ha.callback
def service_handler(_):
"""Service handler coroutine."""
raise ValueError
self.services.register("test_domain", "register_calls", service_handler)
self.hass.block_till_done()
hass.services.async_register("test_domain", "register_calls", service_handler)
assert len(self.calls_register) == 1
assert self.calls_register[-1].data["domain"] == "test_domain"
assert self.calls_register[-1].data["service"] == "register_calls"
with pytest.raises(ValueError):
assert await hass.services.async_call(
"test_domain", "REGISTER_CALLS", blocking=True
)
assert self.services.call("test_domain", "REGISTER_CALLS", blocking=True)
self.hass.block_till_done()
assert len(calls) == 1
def test_remove_service(self):
"""Test remove service."""
calls_remove = []
@ha.callback
def mock_event_remove(event):
"""Mock register event."""
calls_remove.append(event)
self.hass.bus.listen(EVENT_SERVICE_REMOVED, mock_event_remove)
assert self.services.has_service("test_Domain", "test_Service")
self.services.remove("test_Domain", "test_Service")
self.hass.block_till_done()
assert not self.services.has_service("test_Domain", "test_Service")
assert len(calls_remove) == 1
assert calls_remove[-1].data["domain"] == "test_domain"
assert calls_remove[-1].data["service"] == "test_service"
def test_remove_service_that_not_exists(self):
"""Test remove service that not exists."""
calls_remove = []
@ha.callback
def mock_event_remove(event):
"""Mock register event."""
calls_remove.append(event)
self.hass.bus.listen(EVENT_SERVICE_REMOVED, mock_event_remove)
assert not self.services.has_service("test_xxx", "test_yyy")
self.services.remove("test_xxx", "test_yyy")
self.hass.block_till_done()
assert len(calls_remove) == 0
def test_async_service_raise_exception(self):
"""Test registering and calling an async service raise exception."""
async def service_handler(_):
"""Service handler coroutine."""
raise ValueError
self.services.register("test_domain", "register_calls", service_handler)
self.hass.block_till_done()
with pytest.raises(ValueError):
assert self.services.call("test_domain", "REGISTER_CALLS", blocking=True)
self.hass.block_till_done()
# Non-blocking service call never throw exception
self.services.call("test_domain", "REGISTER_CALLS", blocking=False)
self.hass.block_till_done()
def test_callback_service_raise_exception(self):
"""Test registering and calling an callback service raise exception."""
@ha.callback
def service_handler(_):
"""Service handler coroutine."""
raise ValueError
self.services.register("test_domain", "register_calls", service_handler)
self.hass.block_till_done()
with pytest.raises(ValueError):
assert self.services.call("test_domain", "REGISTER_CALLS", blocking=True)
self.hass.block_till_done()
# Non-blocking service call never throw exception
self.services.call("test_domain", "REGISTER_CALLS", blocking=False)
self.hass.block_till_done()
# Non-blocking service call never throw exception
await hass.services.async_call("test_domain", "REGISTER_CALLS", blocking=False)
await hass.async_block_till_done()
def test_config_defaults():