Collection of core tests improvements (#33757)

* Collection of core tests improvements

* Added some more

* Fix aiohttp client response release
This commit is contained in:
Franck Nijhof 2020-04-07 18:33:23 +02:00 committed by GitHub
parent 1f7803c541
commit 60bc517d01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 302 additions and 343 deletions

View file

@ -1,6 +1,5 @@
"""Test the aiohttp client helper."""
import asyncio
import unittest
import aiohttp
import pytest
@ -8,9 +7,6 @@ import pytest
from homeassistant.core import EVENT_HOMEASSISTANT_CLOSE
import homeassistant.helpers.aiohttp_client as client
from homeassistant.setup import async_setup_component
from homeassistant.util.async_ import run_callback_threadsafe
from tests.common import get_test_home_assistant
@pytest.fixture
@ -33,130 +29,91 @@ def camera_client(hass, hass_client):
yield hass.loop.run_until_complete(hass_client())
class TestHelpersAiohttpClient(unittest.TestCase):
"""Test homeassistant.helpers.aiohttp_client module."""
async def test_get_clientsession_with_ssl(hass):
"""Test init clientsession with ssl."""
client.async_get_clientsession(hass)
def setup_method(self, method):
"""Set up things to be run when tests are started."""
self.hass = get_test_home_assistant()
def teardown_method(self, method):
"""Stop everything that was started."""
self.hass.stop()
def test_get_clientsession_with_ssl(self):
"""Test init clientsession with ssl."""
run_callback_threadsafe(
self.hass.loop, client.async_get_clientsession, self.hass
).result()
assert isinstance(
self.hass.data[client.DATA_CLIENTSESSION], aiohttp.ClientSession
)
assert isinstance(self.hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector)
def test_get_clientsession_without_ssl(self):
"""Test init clientsession without ssl."""
run_callback_threadsafe(
self.hass.loop, client.async_get_clientsession, self.hass, False
).result()
assert isinstance(
self.hass.data[client.DATA_CLIENTSESSION_NOTVERIFY], aiohttp.ClientSession
)
assert isinstance(
self.hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector
)
def test_create_clientsession_with_ssl_and_cookies(self):
"""Test create clientsession with ssl."""
def _async_helper():
return client.async_create_clientsession(self.hass, cookies={"bla": True})
session = run_callback_threadsafe(self.hass.loop, _async_helper).result()
assert isinstance(session, aiohttp.ClientSession)
assert isinstance(self.hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector)
def test_create_clientsession_without_ssl_and_cookies(self):
"""Test create clientsession without ssl."""
def _async_helper():
return client.async_create_clientsession(
self.hass, False, cookies={"bla": True}
)
session = run_callback_threadsafe(self.hass.loop, _async_helper).result()
assert isinstance(session, aiohttp.ClientSession)
assert isinstance(
self.hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector
)
def test_get_clientsession_cleanup(self):
"""Test init clientsession with ssl."""
run_callback_threadsafe(
self.hass.loop, client.async_get_clientsession, self.hass
).result()
assert isinstance(
self.hass.data[client.DATA_CLIENTSESSION], aiohttp.ClientSession
)
assert isinstance(self.hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector)
self.hass.bus.fire(EVENT_HOMEASSISTANT_CLOSE)
self.hass.block_till_done()
assert self.hass.data[client.DATA_CLIENTSESSION].closed
assert self.hass.data[client.DATA_CONNECTOR].closed
def test_get_clientsession_cleanup_without_ssl(self):
"""Test init clientsession with ssl."""
run_callback_threadsafe(
self.hass.loop, client.async_get_clientsession, self.hass, False
).result()
assert isinstance(
self.hass.data[client.DATA_CLIENTSESSION_NOTVERIFY], aiohttp.ClientSession
)
assert isinstance(
self.hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector
)
self.hass.bus.fire(EVENT_HOMEASSISTANT_CLOSE)
self.hass.block_till_done()
assert self.hass.data[client.DATA_CLIENTSESSION_NOTVERIFY].closed
assert self.hass.data[client.DATA_CONNECTOR_NOTVERIFY].closed
assert isinstance(hass.data[client.DATA_CLIENTSESSION], aiohttp.ClientSession)
assert isinstance(hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector)
@asyncio.coroutine
def test_async_aiohttp_proxy_stream(aioclient_mock, camera_client):
async def test_get_clientsession_without_ssl(hass):
"""Test init clientsession without ssl."""
client.async_get_clientsession(hass, verify_ssl=False)
assert isinstance(
hass.data[client.DATA_CLIENTSESSION_NOTVERIFY], aiohttp.ClientSession
)
assert isinstance(hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector)
async def test_create_clientsession_with_ssl_and_cookies(hass):
"""Test create clientsession with ssl."""
session = client.async_create_clientsession(hass, cookies={"bla": True})
assert isinstance(session, aiohttp.ClientSession)
assert isinstance(hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector)
async def test_create_clientsession_without_ssl_and_cookies(hass):
"""Test create clientsession without ssl."""
session = client.async_create_clientsession(hass, False, cookies={"bla": True})
assert isinstance(session, aiohttp.ClientSession)
assert isinstance(hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector)
async def test_get_clientsession_cleanup(hass):
"""Test init clientsession with ssl."""
client.async_get_clientsession(hass)
assert isinstance(hass.data[client.DATA_CLIENTSESSION], aiohttp.ClientSession)
assert isinstance(hass.data[client.DATA_CONNECTOR], aiohttp.TCPConnector)
hass.bus.async_fire(EVENT_HOMEASSISTANT_CLOSE)
await hass.async_block_till_done()
assert hass.data[client.DATA_CLIENTSESSION].closed
assert hass.data[client.DATA_CONNECTOR].closed
async def test_get_clientsession_cleanup_without_ssl(hass):
"""Test init clientsession with ssl."""
client.async_get_clientsession(hass, verify_ssl=False)
assert isinstance(
hass.data[client.DATA_CLIENTSESSION_NOTVERIFY], aiohttp.ClientSession
)
assert isinstance(hass.data[client.DATA_CONNECTOR_NOTVERIFY], aiohttp.TCPConnector)
hass.bus.async_fire(EVENT_HOMEASSISTANT_CLOSE)
await hass.async_block_till_done()
assert hass.data[client.DATA_CLIENTSESSION_NOTVERIFY].closed
assert hass.data[client.DATA_CONNECTOR_NOTVERIFY].closed
async def test_async_aiohttp_proxy_stream(aioclient_mock, camera_client):
"""Test that it fetches the given url."""
aioclient_mock.get("http://example.com/mjpeg_stream", content=b"Frame1Frame2Frame3")
resp = yield from camera_client.get("/api/camera_proxy_stream/camera.config_test")
resp = await camera_client.get("/api/camera_proxy_stream/camera.config_test")
assert resp.status == 200
assert aioclient_mock.call_count == 1
body = yield from resp.text()
body = await resp.text()
assert body == "Frame1Frame2Frame3"
@asyncio.coroutine
def test_async_aiohttp_proxy_stream_timeout(aioclient_mock, camera_client):
async def test_async_aiohttp_proxy_stream_timeout(aioclient_mock, camera_client):
"""Test that it fetches the given url."""
aioclient_mock.get("http://example.com/mjpeg_stream", exc=asyncio.TimeoutError())
resp = yield from camera_client.get("/api/camera_proxy_stream/camera.config_test")
resp = await camera_client.get("/api/camera_proxy_stream/camera.config_test")
assert resp.status == 504
@asyncio.coroutine
def test_async_aiohttp_proxy_stream_client_err(aioclient_mock, camera_client):
async def test_async_aiohttp_proxy_stream_client_err(aioclient_mock, camera_client):
"""Test that it fetches the given url."""
aioclient_mock.get("http://example.com/mjpeg_stream", exc=aiohttp.ClientError())
resp = yield from camera_client.get("/api/camera_proxy_stream/camera.config_test")
resp = await camera_client.get("/api/camera_proxy_stream/camera.config_test")
assert resp.status == 502

View file

@ -1,143 +1,131 @@
"""Test dispatcher helpers."""
import asyncio
from functools import partial
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import (
async_dispatcher_connect,
dispatcher_connect,
dispatcher_send,
async_dispatcher_send,
)
from tests.common import get_test_home_assistant
async def test_simple_function(hass):
"""Test simple function (executor)."""
calls = []
def test_funct(data):
"""Test function."""
calls.append(data)
async_dispatcher_connect(hass, "test", test_funct)
async_dispatcher_send(hass, "test", 3)
await hass.async_block_till_done()
assert calls == [3]
async_dispatcher_send(hass, "test", "bla")
await hass.async_block_till_done()
assert calls == [3, "bla"]
class TestHelpersDispatcher:
"""Tests for discovery helper methods."""
async def test_simple_function_unsub(hass):
"""Test simple function (executor) and unsub."""
calls1 = []
calls2 = []
def setup_method(self, method):
"""Set up things to be run when tests are started."""
self.hass = get_test_home_assistant()
def test_funct1(data):
"""Test function."""
calls1.append(data)
def teardown_method(self, method):
"""Stop everything that was started."""
self.hass.stop()
def test_funct2(data):
"""Test function."""
calls2.append(data)
def test_simple_function(self):
"""Test simple function (executor)."""
calls = []
async_dispatcher_connect(hass, "test1", test_funct1)
unsub = async_dispatcher_connect(hass, "test2", test_funct2)
async_dispatcher_send(hass, "test1", 3)
async_dispatcher_send(hass, "test2", 4)
await hass.async_block_till_done()
def test_funct(data):
"""Test function."""
calls.append(data)
assert calls1 == [3]
assert calls2 == [4]
dispatcher_connect(self.hass, "test", test_funct)
dispatcher_send(self.hass, "test", 3)
self.hass.block_till_done()
unsub()
assert calls == [3]
async_dispatcher_send(hass, "test1", 5)
async_dispatcher_send(hass, "test2", 6)
await hass.async_block_till_done()
dispatcher_send(self.hass, "test", "bla")
self.hass.block_till_done()
assert calls1 == [3, 5]
assert calls2 == [4]
assert calls == [3, "bla"]
# check don't kill the flow
unsub()
def test_simple_function_unsub(self):
"""Test simple function (executor) and unsub."""
calls1 = []
calls2 = []
async_dispatcher_send(hass, "test1", 7)
async_dispatcher_send(hass, "test2", 8)
await hass.async_block_till_done()
def test_funct1(data):
"""Test function."""
calls1.append(data)
assert calls1 == [3, 5, 7]
assert calls2 == [4]
def test_funct2(data):
"""Test function."""
calls2.append(data)
dispatcher_connect(self.hass, "test1", test_funct1)
unsub = dispatcher_connect(self.hass, "test2", test_funct2)
dispatcher_send(self.hass, "test1", 3)
dispatcher_send(self.hass, "test2", 4)
self.hass.block_till_done()
async def test_simple_callback(hass):
"""Test simple callback (async)."""
calls = []
assert calls1 == [3]
assert calls2 == [4]
@callback
def test_funct(data):
"""Test function."""
calls.append(data)
unsub()
async_dispatcher_connect(hass, "test", test_funct)
async_dispatcher_send(hass, "test", 3)
await hass.async_block_till_done()
dispatcher_send(self.hass, "test1", 5)
dispatcher_send(self.hass, "test2", 6)
self.hass.block_till_done()
assert calls == [3]
assert calls1 == [3, 5]
assert calls2 == [4]
async_dispatcher_send(hass, "test", "bla")
await hass.async_block_till_done()
# check don't kill the flow
unsub()
assert calls == [3, "bla"]
dispatcher_send(self.hass, "test1", 7)
dispatcher_send(self.hass, "test2", 8)
self.hass.block_till_done()
assert calls1 == [3, 5, 7]
assert calls2 == [4]
async def test_simple_coro(hass):
"""Test simple coro (async)."""
calls = []
def test_simple_callback(self):
"""Test simple callback (async)."""
calls = []
async def async_test_funct(data):
"""Test function."""
calls.append(data)
@callback
def test_funct(data):
"""Test function."""
calls.append(data)
async_dispatcher_connect(hass, "test", async_test_funct)
async_dispatcher_send(hass, "test", 3)
await hass.async_block_till_done()
dispatcher_connect(self.hass, "test", test_funct)
dispatcher_send(self.hass, "test", 3)
self.hass.block_till_done()
assert calls == [3]
assert calls == [3]
async_dispatcher_send(hass, "test", "bla")
await hass.async_block_till_done()
dispatcher_send(self.hass, "test", "bla")
self.hass.block_till_done()
assert calls == [3, "bla"]
assert calls == [3, "bla"]
def test_simple_coro(self):
"""Test simple coro (async)."""
calls = []
async def test_simple_function_multiargs(hass):
"""Test simple function (executor)."""
calls = []
@asyncio.coroutine
def test_funct(data):
"""Test function."""
calls.append(data)
def test_funct(data1, data2, data3):
"""Test function."""
calls.append(data1)
calls.append(data2)
calls.append(data3)
dispatcher_connect(self.hass, "test", test_funct)
dispatcher_send(self.hass, "test", 3)
self.hass.block_till_done()
async_dispatcher_connect(hass, "test", test_funct)
async_dispatcher_send(hass, "test", 3, 2, "bla")
await hass.async_block_till_done()
assert calls == [3]
dispatcher_send(self.hass, "test", "bla")
self.hass.block_till_done()
assert calls == [3, "bla"]
def test_simple_function_multiargs(self):
"""Test simple function (executor)."""
calls = []
def test_funct(data1, data2, data3):
"""Test function."""
calls.append(data1)
calls.append(data2)
calls.append(data3)
dispatcher_connect(self.hass, "test", test_funct)
dispatcher_send(self.hass, "test", 3, 2, "bla")
self.hass.block_till_done()
assert calls == [3, 2, "bla"]
assert calls == [3, 2, "bla"]
async def test_callback_exception_gets_logged(hass, caplog):
@ -150,7 +138,7 @@ async def test_callback_exception_gets_logged(hass, caplog):
# wrap in partial to test message logging.
async_dispatcher_connect(hass, "test", partial(bad_handler))
dispatcher_send(hass, "test", "bad")
async_dispatcher_send(hass, "test", "bad")
await hass.async_block_till_done()
await hass.async_block_till_done()

View file

@ -18,55 +18,57 @@ from tests.common import get_test_home_assistant, mock_registry
def test_generate_entity_id_requires_hass_or_ids():
"""Ensure we require at least hass or current ids."""
fmt = "test.{}"
with pytest.raises(ValueError):
entity.generate_entity_id(fmt, "hello world")
entity.generate_entity_id("test.{}", "hello world")
def test_generate_entity_id_given_keys():
"""Test generating an entity id given current ids."""
fmt = "test.{}"
assert (
entity.generate_entity_id(
fmt, "overwrite hidden true", current_ids=["test.overwrite_hidden_true"]
"test.{}",
"overwrite hidden true",
current_ids=["test.overwrite_hidden_true"],
)
== "test.overwrite_hidden_true_2"
)
assert (
entity.generate_entity_id(
fmt, "overwrite hidden true", current_ids=["test.another_entity"]
"test.{}", "overwrite hidden true", current_ids=["test.another_entity"]
)
== "test.overwrite_hidden_true"
)
def test_async_update_support(hass):
async def test_async_update_support(hass):
"""Test async update getting called."""
sync_update = []
async_update = []
class AsyncEntity(entity.Entity):
"""A test entity."""
entity_id = "sensor.test"
def update(self):
"""Update entity."""
sync_update.append([1])
ent = AsyncEntity()
ent.hass = hass
hass.loop.run_until_complete(ent.async_update_ha_state(True))
await ent.async_update_ha_state(True)
assert len(sync_update) == 1
assert len(async_update) == 0
@asyncio.coroutine
def async_update_func():
async def async_update_func():
"""Async update."""
async_update.append(1)
ent.async_update = async_update_func
hass.loop.run_until_complete(ent.async_update_ha_state(True))
await ent.async_update_ha_state(True)
assert len(sync_update) == 1
assert len(async_update) == 1
@ -123,13 +125,11 @@ class TestHelpersEntity:
assert state.attributes.get(ATTR_DEVICE_CLASS) == "test_class"
@asyncio.coroutine
def test_warn_slow_update(hass):
async def test_warn_slow_update(hass):
"""Warn we log when entity update takes a long time."""
update_call = False
@asyncio.coroutine
def async_update():
async def async_update():
"""Mock async update."""
nonlocal update_call
update_call = True
@ -140,7 +140,7 @@ def test_warn_slow_update(hass):
mock_entity.async_update = async_update
with patch.object(hass.loop, "call_later", MagicMock()) as mock_call:
yield from mock_entity.async_update_ha_state(True)
await mock_entity.async_update_ha_state(True)
assert mock_call.called
assert len(mock_call.mock_calls) == 2
@ -154,13 +154,11 @@ def test_warn_slow_update(hass):
assert update_call
@asyncio.coroutine
def test_warn_slow_update_with_exception(hass):
async def test_warn_slow_update_with_exception(hass):
"""Warn we log when entity update takes a long time and trow exception."""
update_call = False
@asyncio.coroutine
def async_update():
async def async_update():
"""Mock async update."""
nonlocal update_call
update_call = True
@ -172,7 +170,7 @@ def test_warn_slow_update_with_exception(hass):
mock_entity.async_update = async_update
with patch.object(hass.loop, "call_later", MagicMock()) as mock_call:
yield from mock_entity.async_update_ha_state(True)
await mock_entity.async_update_ha_state(True)
assert mock_call.called
assert len(mock_call.mock_calls) == 2
@ -186,13 +184,11 @@ def test_warn_slow_update_with_exception(hass):
assert update_call
@asyncio.coroutine
def test_warn_slow_device_update_disabled(hass):
async def test_warn_slow_device_update_disabled(hass):
"""Disable slow update warning with async_device_update."""
update_call = False
@asyncio.coroutine
def async_update():
async def async_update():
"""Mock async update."""
nonlocal update_call
update_call = True
@ -203,19 +199,17 @@ def test_warn_slow_device_update_disabled(hass):
mock_entity.async_update = async_update
with patch.object(hass.loop, "call_later", MagicMock()) as mock_call:
yield from mock_entity.async_device_update(warning=False)
await mock_entity.async_device_update(warning=False)
assert not mock_call.called
assert update_call
@asyncio.coroutine
def test_async_schedule_update_ha_state(hass):
async def test_async_schedule_update_ha_state(hass):
"""Warn we log when entity update takes a long time and trow exception."""
update_call = False
@asyncio.coroutine
def async_update():
async def async_update():
"""Mock async update."""
nonlocal update_call
update_call = True
@ -226,7 +220,7 @@ def test_async_schedule_update_ha_state(hass):
mock_entity.async_update = async_update
mock_entity.async_schedule_update_ha_state(True)
yield from hass.async_block_till_done()
await hass.async_block_till_done()
assert update_call is True
@ -236,6 +230,8 @@ async def test_async_async_request_call_without_lock(hass):
updates = []
class AsyncEntity(entity.Entity):
"""Test entity."""
def __init__(self, entity_id):
"""Initialize Async test entity."""
self.entity_id = entity_id
@ -271,6 +267,8 @@ async def test_async_async_request_call_with_lock(hass):
test_semaphore = asyncio.Semaphore(1)
class AsyncEntity(entity.Entity):
"""Test entity."""
def __init__(self, entity_id, lock):
"""Initialize Async test entity."""
self.entity_id = entity_id
@ -319,6 +317,8 @@ async def test_async_parallel_updates_with_zero(hass):
test_lock = asyncio.Event()
class AsyncEntity(entity.Entity):
"""Test entity."""
def __init__(self, entity_id, count):
"""Initialize Async test entity."""
self.entity_id = entity_id
@ -354,6 +354,8 @@ async def test_async_parallel_updates_with_zero_on_sync_update(hass):
test_lock = threading.Event()
class AsyncEntity(entity.Entity):
"""Test entity."""
def __init__(self, entity_id, count):
"""Initialize Async test entity."""
self.entity_id = entity_id
@ -393,6 +395,8 @@ async def test_async_parallel_updates_with_one(hass):
test_semaphore = asyncio.Semaphore(1)
class AsyncEntity(entity.Entity):
"""Test entity."""
def __init__(self, entity_id, count):
"""Initialize Async test entity."""
self.entity_id = entity_id
@ -467,6 +471,8 @@ async def test_async_parallel_updates_with_two(hass):
test_semaphore = asyncio.Semaphore(2)
class AsyncEntity(entity.Entity):
"""Test entity."""
def __init__(self, entity_id, count):
"""Initialize Async test entity."""
self.entity_id = entity_id
@ -474,11 +480,10 @@ async def test_async_parallel_updates_with_two(hass):
self._count = count
self.parallel_updates = test_semaphore
@asyncio.coroutine
def async_update(self):
async def async_update(self):
"""Test update."""
updates.append(self._count)
yield from test_lock.acquire()
await test_lock.acquire()
ent_1 = AsyncEntity("sensor.test_1", 1)
ent_2 = AsyncEntity("sensor.test_2", 2)
@ -529,15 +534,14 @@ async def test_async_parallel_updates_with_two(hass):
test_lock.release()
@asyncio.coroutine
def test_async_remove_no_platform(hass):
async def test_async_remove_no_platform(hass):
"""Test async_remove method when no platform set."""
ent = entity.Entity()
ent.hass = hass
ent.entity_id = "test.test"
yield from ent.async_update_ha_state()
await ent.async_update_ha_state()
assert len(hass.states.async_entity_ids()) == 1
yield from ent.async_remove()
await ent.async_remove()
assert len(hass.states.async_entity_ids()) == 0
@ -686,6 +690,8 @@ async def test_warn_slow_write_state_custom_component(hass, caplog):
"""Check that we log a warning if reading properties takes too long."""
class CustomComponentEntity(entity.Entity):
"""Custom component entity."""
__module__ = "custom_components.bla.sensor"
mock_entity = CustomComponentEntity()

View file

@ -1,6 +1,5 @@
"""Test event helpers."""
# pylint: disable=protected-access
import asyncio
from datetime import datetime, timedelta
from unittest.mock import patch
@ -104,8 +103,7 @@ async def test_track_state_change(hass):
async_track_state_change(hass, "light.Bowl", wildcard_run_callback)
@asyncio.coroutine
def wildercard_run_callback(entity_id, old_state, new_state):
async def wildercard_run_callback(entity_id, old_state, new_state):
wildercard_runs.append((old_state, new_state))
async_track_state_change(hass, MATCH_ALL, wildercard_run_callback)
@ -189,8 +187,7 @@ async def test_track_template(hass):
async_track_template(hass, template_condition, wildcard_run_callback)
@asyncio.coroutine
def wildercard_run_callback(entity_id, old_state, new_state):
async def wildercard_run_callback(entity_id, old_state, new_state):
wildercard_runs.append((old_state, new_state))
async_track_template(
@ -263,8 +260,7 @@ async def test_track_same_state_simple_trigger(hass):
entity_ids="light.Bowl",
)
@asyncio.coroutine
def coroutine_run_callback():
async def coroutine_run_callback():
coroutine_runs.append(1)
async_track_same_state(
@ -738,27 +734,27 @@ async def test_periodic_task_duplicate_time(hass):
async def test_periodic_task_entering_dst(hass):
"""Test periodic task behavior when entering dst."""
tz = dt_util.get_time_zone("Europe/Vienna")
dt_util.set_default_time_zone(tz)
timezone = dt_util.get_time_zone("Europe/Vienna")
dt_util.set_default_time_zone(timezone)
specific_runs = []
unsub = async_track_time_change(
hass, lambda x: specific_runs.append(1), hour=2, minute=30, second=0
)
_send_time_changed(hass, tz.localize(datetime(2018, 3, 25, 1, 50, 0)))
_send_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, tz.localize(datetime(2018, 3, 25, 3, 50, 0)))
_send_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, tz.localize(datetime(2018, 3, 26, 1, 50, 0)))
_send_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, tz.localize(datetime(2018, 3, 26, 2, 50, 0)))
_send_time_changed(hass, timezone.localize(datetime(2018, 3, 26, 2, 50, 0)))
await hass.async_block_till_done()
assert len(specific_runs) == 1
@ -767,29 +763,35 @@ async def test_periodic_task_entering_dst(hass):
async def test_periodic_task_leaving_dst(hass):
"""Test periodic task behavior when leaving dst."""
tz = dt_util.get_time_zone("Europe/Vienna")
dt_util.set_default_time_zone(tz)
timezone = dt_util.get_time_zone("Europe/Vienna")
dt_util.set_default_time_zone(timezone)
specific_runs = []
unsub = async_track_time_change(
hass, lambda x: specific_runs.append(1), hour=2, minute=30, second=0
)
_send_time_changed(hass, tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=False))
_send_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(
hass, tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=False)
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(hass, tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=True))
_send_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(hass, tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True))
_send_time_changed(
hass, timezone.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True)
)
await hass.async_block_till_done()
assert len(specific_runs) == 2

View file

@ -1,5 +1,4 @@
"""Test service helpers."""
import asyncio
from collections import OrderedDict
from copy import deepcopy
import unittest
@ -286,13 +285,12 @@ async def test_extract_entity_ids_from_area(hass, area_mock):
)
@asyncio.coroutine
def test_async_get_all_descriptions(hass):
async def test_async_get_all_descriptions(hass):
"""Test async_get_all_descriptions."""
group = hass.components.group
group_config = {group.DOMAIN: {}}
yield from async_setup_component(hass, group.DOMAIN, group_config)
descriptions = yield from service.async_get_all_descriptions(hass)
await async_setup_component(hass, group.DOMAIN, group_config)
descriptions = await service.async_get_all_descriptions(hass)
assert len(descriptions) == 1
@ -301,8 +299,8 @@ def test_async_get_all_descriptions(hass):
logger = hass.components.logger
logger_config = {logger.DOMAIN: {}}
yield from async_setup_component(hass, logger.DOMAIN, logger_config)
descriptions = yield from service.async_get_all_descriptions(hass)
await async_setup_component(hass, logger.DOMAIN, logger_config)
descriptions = await service.async_get_all_descriptions(hass)
assert len(descriptions) == 2

View file

@ -25,8 +25,7 @@ from homeassistant.util import dt as dt_util
from tests.common import async_mock_service
@asyncio.coroutine
def test_async_track_states(hass):
async def test_async_track_states(hass):
"""Test AsyncTrackStates context manager."""
point1 = dt_util.utcnow()
point2 = point1 + timedelta(seconds=5)
@ -50,8 +49,7 @@ def test_async_track_states(hass):
assert [state2, state3] == sorted(states, key=lambda state: state.entity_id)
@asyncio.coroutine
def test_call_to_component(hass):
async def test_call_to_component(hass):
"""Test calls to components state reproduction functions."""
with patch(
"homeassistant.components.media_player.reproduce_state.async_reproduce_states"
@ -69,7 +67,7 @@ def test_call_to_component(hass):
state_climate = ha.State("climate.test", "bad")
context = "dummy_context"
yield from state.async_reproduce_state(
await state.async_reproduce_state(
hass,
[state_media_player, state_climate],
blocking=True,

View file

@ -1,6 +1,5 @@
"""Test the bootstrapping."""
# pylint: disable=protected-access
import asyncio
import logging
import os
from unittest.mock import Mock
@ -29,11 +28,10 @@ _LOGGER = logging.getLogger(__name__)
@patch("homeassistant.bootstrap.async_enable_logging", Mock())
@asyncio.coroutine
def test_home_assistant_core_config_validation(hass):
async def test_home_assistant_core_config_validation(hass):
"""Test if we pass in wrong information for HA conf."""
# Extensive HA conf validation testing is done
result = yield from bootstrap.async_from_config_dict(
result = await bootstrap.async_from_config_dict(
{"homeassistant": {"latitude": "some string"}}, hass
)
assert result is None

View file

@ -1,6 +1,5 @@
"""Test config utils."""
# pylint: disable=protected-access
import asyncio
from collections import OrderedDict
import copy
import os
@ -740,8 +739,7 @@ async def test_merge_duplicate_keys(merge_log_err, hass):
assert len(config["input_select"]) == 1
@asyncio.coroutine
def test_merge_customize(hass):
async def test_merge_customize(hass):
"""Test loading core config onto hass object."""
core_config = {
"latitude": 60,
@ -755,7 +753,7 @@ def test_merge_customize(hass):
"pkg1": {"homeassistant": {"customize": {"b.b": {"friendly_name": "BB"}}}}
},
}
yield from config_util.async_process_ha_core_config(hass, core_config)
await config_util.async_process_ha_core_config(hass, core_config)
assert hass.data[config_util.DATA_CUSTOMIZE].get("b.b") == {"friendly_name": "BB"}

View file

@ -314,12 +314,10 @@ async def test_remove_entry_handles_callback_error(hass, manager):
assert [item.entry_id for item in manager.async_entries()] == []
@asyncio.coroutine
def test_remove_entry_raises(hass, manager):
async def test_remove_entry_raises(hass, manager):
"""Test if a component raises while removing entry."""
@asyncio.coroutine
def mock_unload_entry(hass, entry):
async def mock_unload_entry(hass, entry):
"""Mock unload entry function."""
raise Exception("BROKEN")
@ -337,14 +335,13 @@ def test_remove_entry_raises(hass, manager):
"test3",
]
result = yield from manager.async_remove("test2")
result = await manager.async_remove("test2")
assert result == {"require_restart": True}
assert [item.entry_id for item in manager.async_entries()] == ["test1", "test3"]
@asyncio.coroutine
def test_remove_entry_if_not_loaded(hass, manager):
async def test_remove_entry_if_not_loaded(hass, manager):
"""Test that we can remove an entry that is not loaded."""
mock_unload_entry = MagicMock(return_value=mock_coro(True))
@ -360,7 +357,7 @@ def test_remove_entry_if_not_loaded(hass, manager):
"test3",
]
result = yield from manager.async_remove("test2")
result = await manager.async_remove("test2")
assert result == {"require_restart": False}
assert [item.entry_id for item in manager.async_entries()] == ["test1", "test3"]
@ -368,8 +365,7 @@ def test_remove_entry_if_not_loaded(hass, manager):
assert len(mock_unload_entry.mock_calls) == 0
@asyncio.coroutine
def test_add_entry_calls_setup_entry(hass, manager):
async def test_add_entry_calls_setup_entry(hass, manager):
"""Test we call setup_config_entry."""
mock_setup_entry = MagicMock(return_value=mock_coro(True))
@ -377,18 +373,19 @@ def test_add_entry_calls_setup_entry(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
@asyncio.coroutine
def async_step_user(self, user_input=None):
async def async_step_user(self, user_input=None):
"""Test user step."""
return self.async_create_entry(title="title", data={"token": "supersecret"})
with patch.dict(config_entries.HANDLERS, {"comp": TestFlow, "beer": 5}):
yield from manager.flow.async_init(
await manager.flow.async_init(
"comp", context={"source": config_entries.SOURCE_USER}
)
yield from hass.async_block_till_done()
await hass.async_block_till_done()
assert len(mock_setup_entry.mock_calls) == 1
p_hass, p_entry = mock_setup_entry.mock_calls[0][1]
@ -397,8 +394,7 @@ def test_add_entry_calls_setup_entry(hass, manager):
assert p_entry.data == {"token": "supersecret"}
@asyncio.coroutine
def test_entries_gets_entries(manager):
async def test_entries_gets_entries(manager):
"""Test entries are filtered by domain."""
MockConfigEntry(domain="test").add_to_manager(manager)
entry1 = MockConfigEntry(domain="test2")
@ -409,8 +405,7 @@ def test_entries_gets_entries(manager):
assert manager.async_entries("test2") == [entry1, entry2]
@asyncio.coroutine
def test_domains_gets_uniques(manager):
async def test_domains_gets_uniques(manager):
"""Test we only return each domain once."""
MockConfigEntry(domain="test").add_to_manager(manager)
MockConfigEntry(domain="test2").add_to_manager(manager)
@ -429,10 +424,13 @@ async def test_saving_and_loading(hass):
mock_entity_platform(hass, "config_flow.test", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 5
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
async def async_step_user(self, user_input=None):
"""Test user step."""
await self.async_set_unique_id("unique")
return self.async_create_entry(title="Test Title", data={"token": "abcd"})
@ -442,11 +440,13 @@ async def test_saving_and_loading(hass):
)
class Test2Flow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 3
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_PUSH
@asyncio.coroutine
def async_step_user(self, user_input=None):
async def async_step_user(self, user_input=None):
"""Test user step."""
return self.async_create_entry(
title="Test 2 Title", data={"username": "bla"}
)
@ -528,9 +528,12 @@ async def test_discovery_notification(hass):
with patch.dict(config_entries.HANDLERS):
class TestFlow(config_entries.ConfigFlow, domain="test"):
"""Test flow."""
VERSION = 5
async def async_step_discovery(self, user_input=None):
"""Test discovery step."""
if user_input is not None:
return self.async_create_entry(
title="Test Title", data={"token": "abcd"}
@ -560,9 +563,12 @@ async def test_discovery_notification_not_created(hass):
await async_setup_component(hass, "persistent_notification", {})
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 5
async def async_step_discovery(self, user_input=None):
"""Test discovery step."""
return self.async_abort(reason="test")
with patch.dict(config_entries.HANDLERS, {"test": TestFlow}):
@ -685,11 +691,15 @@ async def test_entry_options(hass, manager):
entry.add_to_manager(manager)
class TestFlow:
"""Test flow."""
@staticmethod
@callback
def async_get_options_flow(config_entry):
"""Test options flow."""
class OptionsFlowHandler(data_entry_flow.FlowHandler):
pass
"""Test options flow handler."""
return OptionsFlowHandler()
@ -703,7 +713,6 @@ async def test_entry_options(hass, manager):
await manager.options.async_finish_flow(flow, {"data": {"second": True}})
assert entry.data == {"first": True}
assert entry.options == {"second": True}
@ -1014,10 +1023,12 @@ async def test_unqiue_id_persisted(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
async def async_step_user(self, user_input=None):
"""Test user step."""
await self.async_set_unique_id("mock-unique-id")
return self.async_create_entry(title="mock-title", data={})
@ -1058,10 +1069,12 @@ async def test_unique_id_existing_entry(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
async def async_step_user(self, user_input=None):
"""Test user step."""
existing_entry = await self.async_set_unique_id("mock-unique-id")
assert existing_entry is not None
@ -1100,10 +1113,12 @@ async def test_unique_id_update_existing_entry(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
async def async_step_user(self, user_input=None):
"""Test user step."""
await self.async_set_unique_id("mock-unique-id")
await self._abort_if_unique_id_configured(updates={"host": "1.1.1.1"})
@ -1134,10 +1149,12 @@ async def test_unique_id_not_update_existing_entry(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
async def async_step_user(self, user_input=None):
"""Test user step."""
await self.async_set_unique_id("mock-unique-id")
await self._abort_if_unique_id_configured(updates={"host": "0.0.0.0"})
@ -1161,10 +1178,12 @@ async def test_unique_id_in_progress(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
async def async_step_user(self, user_input=None):
"""Test user step."""
await self.async_set_unique_id("mock-unique-id")
return self.async_show_form(step_id="discovery")
@ -1193,10 +1212,12 @@ async def test_finish_flow_aborts_progress(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
async def async_step_user(self, user_input=None):
"""Test user step."""
await self.async_set_unique_id("mock-unique-id", raise_on_progress=False)
if user_input is None:
@ -1228,10 +1249,12 @@ async def test_unique_id_ignore(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
async def async_step_user(self, user_input=None):
"""Test user flow."""
await self.async_set_unique_id("mock-unique-id")
return self.async_show_form(step_id="discovery")
@ -1268,10 +1291,12 @@ async def test_unignore_step_form(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
async def async_step_unignore(self, user_input):
"""Test unignore step."""
unique_id = user_input["unique_id"]
await self.async_set_unique_id(unique_id)
return self.async_show_form(step_id="discovery")
@ -1310,10 +1335,12 @@ async def test_unignore_create_entry(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
async def async_step_unignore(self, user_input):
"""Test unignore step."""
unique_id = user_input["unique_id"]
await self.async_set_unique_id(unique_id)
return self.async_create_entry(title="yo", data={})
@ -1355,6 +1382,7 @@ async def test_unignore_default_impl(hass, manager):
mock_entity_platform(hass, "config_flow.comp", None)
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
@ -1395,10 +1423,12 @@ async def test_partial_flows_hidden(hass, manager):
pause_discovery = asyncio.Event()
class TestFlow(config_entries.ConfigFlow):
"""Test flow."""
VERSION = 1
async def async_step_discovery(self, user_input):
"""Test discovery step."""
discovery_started.set()
await pause_discovery.wait()
return self.async_show_form(step_id="someform")

View file

@ -1,6 +1,5 @@
"""Test component/platform setup."""
# pylint: disable=protected-access
import asyncio
import logging
import os
import threading
@ -265,8 +264,7 @@ class TestSetup:
"""Test component setup while waiting for lock is not set up twice."""
result = []
@asyncio.coroutine
def async_setup(hass, config):
async def async_setup(hass, config):
"""Tracking Setup."""
result.append(1)
@ -462,21 +460,17 @@ class TestSetup:
assert call_order == [1, 1, 2]
@asyncio.coroutine
def test_component_cannot_depend_config(hass):
async def test_component_cannot_depend_config(hass):
"""Test config is not allowed to be a dependency."""
result = yield from setup._async_process_dependencies(
hass, None, "test", ["config"]
)
result = await setup._async_process_dependencies(hass, None, "test", ["config"])
assert not result
@asyncio.coroutine
def test_component_warn_slow_setup(hass):
async def test_component_warn_slow_setup(hass):
"""Warn we log when a component setup takes a long time."""
mock_integration(hass, MockModule("test_component1"))
with mock.patch.object(hass.loop, "call_later", mock.MagicMock()) as mock_call:
result = yield from setup.async_setup_component(hass, "test_component1", {})
result = await setup.async_setup_component(hass, "test_component1", {})
assert result
assert mock_call.called
assert len(mock_call.mock_calls) == 3
@ -489,14 +483,13 @@ def test_component_warn_slow_setup(hass):
assert mock_call().cancel.called
@asyncio.coroutine
def test_platform_no_warn_slow(hass):
async def test_platform_no_warn_slow(hass):
"""Do not warn for long entity setup time."""
mock_integration(
hass, MockModule("test_component1", platform_schema=PLATFORM_SCHEMA)
)
with mock.patch.object(hass.loop, "call_later", mock.MagicMock()) as mock_call:
result = yield from setup.async_setup_component(hass, "test_component1", {})
result = await setup.async_setup_component(hass, "test_component1", {})
assert result
assert not mock_call.called

View file

@ -1,5 +1,4 @@
"""Aiohttp test utils."""
import asyncio
from contextlib import contextmanager
import json as _json
import re
@ -13,7 +12,7 @@ from yarl import URL
from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE
retype = type(re.compile(""))
RETYPE = type(re.compile(""))
def mock_stream(data):
@ -58,7 +57,7 @@ class AiohttpClientMocker:
if content is None:
content = b""
if not isinstance(url, retype):
if not isinstance(url, RETYPE):
url = URL(url)
if params:
url = url.with_query(params)
@ -173,7 +172,7 @@ class AiohttpClientMockResponse:
return False
# regular expression matching
if isinstance(self._url, retype):
if isinstance(self._url, RETYPE):
return self._url.search(str(url)) is not None
if (
@ -220,25 +219,20 @@ class AiohttpClientMockResponse:
"""Return content."""
return mock_stream(self.response)
@asyncio.coroutine
def read(self):
async def read(self):
"""Return mock response."""
return self.response
@asyncio.coroutine
def text(self, encoding="utf-8"):
async def text(self, encoding="utf-8"):
"""Return mock response as a string."""
return self.response.decode(encoding)
@asyncio.coroutine
def json(self, encoding="utf-8"):
async def json(self, encoding="utf-8"):
"""Return mock response as a json."""
return _json.loads(self.response.decode(encoding))
@asyncio.coroutine
def release(self):
"""Mock release."""
pass
def raise_for_status(self):
"""Raise error if status is 400 or higher."""
@ -253,7 +247,6 @@ class AiohttpClientMockResponse:
def close(self):
"""Mock close."""
pass
@contextmanager

View file

@ -19,8 +19,7 @@ def test_sensitive_data_filter():
assert sensitive_record.msg == "******* log"
@asyncio.coroutine
def test_async_handler_loop_log(loop):
async def test_async_handler_loop_log(loop):
"""Test logging data inside from inside the event loop."""
loop._thread_ident = threading.get_ident()
@ -39,13 +38,12 @@ def test_async_handler_loop_log(loop):
log_record = logging.makeLogRecord({"msg": "Test Log Record"})
handler.emit(log_record)
yield from handler.async_close(True)
await handler.async_close(True)
assert queue.get_nowait().msg == "Test Log Record"
assert queue.empty()
@asyncio.coroutine
def test_async_handler_thread_log(loop):
async def test_async_handler_thread_log(loop):
"""Test logging data from a thread."""
loop._thread_ident = threading.get_ident()
@ -60,8 +58,8 @@ def test_async_handler_thread_log(loop):
handler.emit(log_record)
handler.close()
yield from loop.run_in_executor(None, add_log)
yield from handler.async_close(True)
await loop.run_in_executor(None, add_log)
await handler.async_close(True)
assert queue.get_nowait().msg == "Test Log Record"
assert queue.empty()