From ba8488d8f1d2f24791958bf5940e16d8f136ec68 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 9 Apr 2017 01:05:34 -0700 Subject: [PATCH] Make discovery not block start (#6991) * Make discovery not block start * Fix tests --- homeassistant/components/discovery.py | 10 +++- tests/components/test_discovery.py | 79 +++++++++------------------ 2 files changed, 35 insertions(+), 54 deletions(-) diff --git a/homeassistant/components/discovery.py b/homeassistant/components/discovery.py index 26036342452..891e34ee8a9 100644 --- a/homeassistant/components/discovery.py +++ b/homeassistant/components/discovery.py @@ -13,6 +13,7 @@ import logging import voluptuous as vol +from homeassistant.core import callback from homeassistant.const import EVENT_HOMEASSISTANT_START import homeassistant.helpers.config_validation as cv from homeassistant.helpers.event import async_track_point_in_utc_time @@ -105,7 +106,7 @@ def async_setup(hass, config): hass, component, platform, info, config) @asyncio.coroutine - def scan_devices(_): + def scan_devices(now): """Scan for devices.""" results = yield from hass.loop.run_in_executor( None, _discover, netdisco) @@ -116,7 +117,12 @@ def async_setup(hass, config): async_track_point_in_utc_time(hass, scan_devices, dt_util.utcnow() + SCAN_INTERVAL) - hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, scan_devices) + @callback + def schedule_first(event): + """Schedule the first discovery when Home Assistant starts up.""" + async_track_point_in_utc_time(hass, scan_devices, dt_util.utcnow()) + + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, schedule_first) return True diff --git a/tests/components/test_discovery.py b/tests/components/test_discovery.py index abffc3b17cd..6b03ffa34e7 100644 --- a/tests/components/test_discovery.py +++ b/tests/components/test_discovery.py @@ -5,9 +5,9 @@ from unittest.mock import patch from homeassistant.bootstrap import async_setup_component from homeassistant.components import discovery -from homeassistant.const import EVENT_HOMEASSISTANT_START +from homeassistant.util.dt import utcnow -from tests.common import mock_coro +from tests.common import mock_coro, fire_time_changed # One might consider to "mock" services, but it's easy enough to just use # what is already available. @@ -34,24 +34,34 @@ IGNORE_CONFIG = { @asyncio.coroutine -def test_unknown_service(hass): - """Test that unknown service is ignored.""" - result = yield from async_setup_component(hass, 'discovery', { - 'discovery': {}, - }) +def mock_discovery(hass, discoveries, config=BASE_CONFIG): + """Helper to mock discoveries.""" + result = yield from async_setup_component(hass, 'discovery', config) assert result - def discover(netdisco): - """Fake discovery.""" - return [('this_service_will_never_be_supported', {'info': 'some'})] + yield from hass.async_start() - with patch.object(discovery, '_discover', discover), \ + with patch.object(discovery, '_discover', discoveries), \ patch('homeassistant.components.discovery.async_discover', return_value=mock_coro()) as mock_discover, \ patch('homeassistant.components.discovery.async_load_platform', return_value=mock_coro()) as mock_platform: - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + fire_time_changed(hass, utcnow()) + # Work around an issue where our loop.call_soon not get caught yield from hass.async_block_till_done() + yield from hass.async_block_till_done() + + return mock_discover, mock_platform + + +@asyncio.coroutine +def test_unknown_service(hass): + """Test that unknown service is ignored.""" + def discover(netdisco): + """Fake discovery.""" + return [('this_service_will_never_be_supported', {'info': 'some'})] + + mock_discover, mock_platform = yield from mock_discovery(hass, discover) assert not mock_discover.called assert not mock_platform.called @@ -60,20 +70,11 @@ def test_unknown_service(hass): @asyncio.coroutine def test_load_platform(hass): """Test load a platform.""" - result = yield from async_setup_component(hass, 'discovery', BASE_CONFIG) - assert result - def discover(netdisco): """Fake discovery.""" return [(SERVICE, SERVICE_INFO)] - with patch.object(discovery, '_discover', discover), \ - patch('homeassistant.components.discovery.async_discover', - return_value=mock_coro()) as mock_discover, \ - patch('homeassistant.components.discovery.async_load_platform', - return_value=mock_coro()) as mock_platform: - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) - yield from hass.async_block_till_done() + mock_discover, mock_platform = yield from mock_discovery(hass, discover) assert not mock_discover.called assert mock_platform.called @@ -84,20 +85,11 @@ def test_load_platform(hass): @asyncio.coroutine def test_load_component(hass): """Test load a component.""" - result = yield from async_setup_component(hass, 'discovery', BASE_CONFIG) - assert result - def discover(netdisco): """Fake discovery.""" return [(SERVICE_NO_PLATFORM, SERVICE_INFO)] - with patch.object(discovery, '_discover', discover), \ - patch('homeassistant.components.discovery.async_discover', - return_value=mock_coro()) as mock_discover, \ - patch('homeassistant.components.discovery.async_load_platform', - return_value=mock_coro()) as mock_platform: - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) - yield from hass.async_block_till_done() + mock_discover, mock_platform = yield from mock_discovery(hass, discover) assert mock_discover.called assert not mock_platform.called @@ -109,20 +101,12 @@ def test_load_component(hass): @asyncio.coroutine def test_ignore_service(hass): """Test ignore service.""" - result = yield from async_setup_component(hass, 'discovery', IGNORE_CONFIG) - assert result - def discover(netdisco): """Fake discovery.""" return [(SERVICE_NO_PLATFORM, SERVICE_INFO)] - with patch.object(discovery, '_discover', discover), \ - patch('homeassistant.components.discovery.async_discover', - return_value=mock_coro()) as mock_discover, \ - patch('homeassistant.components.discovery.async_load_platform', - return_value=mock_coro()) as mock_platform: - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) - yield from hass.async_block_till_done() + mock_discover, mock_platform = yield from mock_discovery(hass, discover, + IGNORE_CONFIG) assert not mock_discover.called assert not mock_platform.called @@ -131,21 +115,12 @@ def test_ignore_service(hass): @asyncio.coroutine def test_discover_duplicates(hass): """Test load a component.""" - result = yield from async_setup_component(hass, 'discovery', BASE_CONFIG) - assert result - def discover(netdisco): """Fake discovery.""" return [(SERVICE_NO_PLATFORM, SERVICE_INFO), (SERVICE_NO_PLATFORM, SERVICE_INFO)] - with patch.object(discovery, '_discover', discover), \ - patch('homeassistant.components.discovery.async_discover', - return_value=mock_coro()) as mock_discover, \ - patch('homeassistant.components.discovery.async_load_platform', - return_value=mock_coro()) as mock_platform: - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) - yield from hass.async_block_till_done() + mock_discover, mock_platform = yield from mock_discovery(hass, discover) assert mock_discover.called assert mock_discover.call_count == 1