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