2016-03-09 09:25:50 +00:00
|
|
|
"""Test to verify that Home Assistant core works."""
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=protected-access
|
2016-09-30 19:57:24 +00:00
|
|
|
import asyncio
|
2014-11-23 17:51:16 +00:00
|
|
|
import unittest
|
2017-02-10 17:00:17 +00:00
|
|
|
from unittest.mock import patch, MagicMock, sentinel
|
2015-09-13 05:56:49 +00:00
|
|
|
from datetime import datetime, timedelta
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2015-08-04 16:16:10 +00:00
|
|
|
import pytz
|
2016-12-16 05:30:09 +00:00
|
|
|
import pytest
|
2015-08-04 16:16:10 +00:00
|
|
|
|
2015-08-17 03:53:17 +00:00
|
|
|
import homeassistant.core as ha
|
2016-09-13 02:16:14 +00:00
|
|
|
from homeassistant.exceptions import InvalidEntityFormatError
|
2016-11-24 22:49:29 +00:00
|
|
|
from homeassistant.util.async import run_coroutine_threadsafe
|
2015-08-04 16:16:10 +00:00
|
|
|
import homeassistant.util.dt as dt_util
|
2016-08-09 03:42:25 +00:00
|
|
|
from homeassistant.util.unit_system import (METRIC_SYSTEM)
|
2015-08-04 16:16:10 +00:00
|
|
|
from homeassistant.const import (
|
2017-02-10 17:00:17 +00:00
|
|
|
__version__, EVENT_STATE_CHANGED, ATTR_FRIENDLY_NAME, CONF_UNIT_SYSTEM,
|
|
|
|
ATTR_NOW, EVENT_TIME_CHANGED, EVENT_HOMEASSISTANT_STOP,
|
2017-04-07 04:00:58 +00:00
|
|
|
EVENT_HOMEASSISTANT_CLOSE, EVENT_SERVICE_REGISTERED, EVENT_SERVICE_REMOVED)
|
2015-08-04 16:16:10 +00:00
|
|
|
|
2017-02-08 17:17:52 +00:00
|
|
|
from tests.common import get_test_home_assistant
|
2016-02-14 23:08:23 +00:00
|
|
|
|
2015-08-04 16:16:10 +00:00
|
|
|
PST = pytz.timezone('America/Los_Angeles')
|
2014-11-23 17:51:16 +00:00
|
|
|
|
|
|
|
|
2016-10-05 03:44:32 +00:00
|
|
|
def test_split_entity_id():
|
|
|
|
"""Test split_entity_id."""
|
|
|
|
assert ha.split_entity_id('domain.object_id') == ['domain', 'object_id']
|
2016-08-09 03:21:40 +00:00
|
|
|
|
2016-10-05 03:44:32 +00:00
|
|
|
|
|
|
|
def test_async_add_job_schedule_callback():
|
|
|
|
"""Test that we schedule coroutines and add jobs to the job pool."""
|
|
|
|
hass = MagicMock()
|
|
|
|
job = MagicMock()
|
|
|
|
|
|
|
|
ha.HomeAssistant.async_add_job(hass, ha.callback(job))
|
|
|
|
assert len(hass.loop.call_soon.mock_calls) == 1
|
|
|
|
assert len(hass.loop.create_task.mock_calls) == 0
|
|
|
|
assert len(hass.add_job.mock_calls) == 0
|
|
|
|
|
|
|
|
|
|
|
|
@patch('asyncio.iscoroutinefunction', return_value=True)
|
|
|
|
def test_async_add_job_schedule_coroutinefunction(mock_iscoro):
|
|
|
|
"""Test that we schedule coroutines and add jobs to the job pool."""
|
|
|
|
hass = MagicMock()
|
|
|
|
job = MagicMock()
|
|
|
|
|
|
|
|
ha.HomeAssistant.async_add_job(hass, job)
|
|
|
|
assert len(hass.loop.call_soon.mock_calls) == 0
|
|
|
|
assert len(hass.loop.create_task.mock_calls) == 1
|
|
|
|
assert len(hass.add_job.mock_calls) == 0
|
|
|
|
|
|
|
|
|
|
|
|
@patch('asyncio.iscoroutinefunction', return_value=False)
|
|
|
|
def test_async_add_job_add_threaded_job_to_pool(mock_iscoro):
|
|
|
|
"""Test that we schedule coroutines and add jobs to the job pool."""
|
|
|
|
hass = MagicMock()
|
|
|
|
job = MagicMock()
|
|
|
|
|
|
|
|
ha.HomeAssistant.async_add_job(hass, job)
|
|
|
|
assert len(hass.loop.call_soon.mock_calls) == 0
|
|
|
|
assert len(hass.loop.create_task.mock_calls) == 0
|
2016-11-05 16:27:55 +00:00
|
|
|
assert len(hass.loop.run_in_executor.mock_calls) == 1
|
2016-10-05 03:44:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_async_run_job_calls_callback():
|
|
|
|
"""Test that the callback annotation is respected."""
|
|
|
|
hass = MagicMock()
|
|
|
|
calls = []
|
|
|
|
|
|
|
|
def job():
|
|
|
|
calls.append(1)
|
|
|
|
|
|
|
|
ha.HomeAssistant.async_run_job(hass, ha.callback(job))
|
|
|
|
assert len(calls) == 1
|
|
|
|
assert len(hass.async_add_job.mock_calls) == 0
|
|
|
|
|
|
|
|
|
|
|
|
def test_async_run_job_delegates_non_async():
|
|
|
|
"""Test that the callback annotation is respected."""
|
|
|
|
hass = MagicMock()
|
|
|
|
calls = []
|
|
|
|
|
|
|
|
def job():
|
|
|
|
calls.append(1)
|
|
|
|
|
|
|
|
ha.HomeAssistant.async_run_job(hass, job)
|
|
|
|
assert len(calls) == 0
|
|
|
|
assert len(hass.async_add_job.mock_calls) == 1
|
2016-08-09 03:21:40 +00:00
|
|
|
|
|
|
|
|
2017-02-13 05:24:07 +00:00
|
|
|
def test_stage_shutdown():
|
|
|
|
"""Simulate a shutdown, test calling stuff."""
|
|
|
|
hass = get_test_home_assistant()
|
|
|
|
test_stop = []
|
|
|
|
test_close = []
|
|
|
|
test_all = []
|
|
|
|
|
|
|
|
hass.bus.listen(
|
|
|
|
EVENT_HOMEASSISTANT_STOP, lambda event: test_stop.append(event))
|
|
|
|
hass.bus.listen(
|
|
|
|
EVENT_HOMEASSISTANT_CLOSE, lambda event: test_close.append(event))
|
|
|
|
hass.bus.listen('*', lambda event: test_all.append(event))
|
|
|
|
|
|
|
|
hass.stop()
|
|
|
|
|
|
|
|
assert len(test_stop) == 1
|
|
|
|
assert len(test_close) == 1
|
|
|
|
assert len(test_all) == 1
|
|
|
|
|
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
class TestHomeAssistant(unittest.TestCase):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test the Home Assistant core classes."""
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def setUp(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Setup things to be run when tests are started."""
|
2016-10-31 15:47:29 +00:00
|
|
|
self.hass = get_test_home_assistant()
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def tearDown(self):
|
2016-03-09 10:15:04 +00:00
|
|
|
"""Stop everything that was started."""
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.stop()
|
2014-11-23 20:57:29 +00:00
|
|
|
|
2016-11-09 16:41:17 +00:00
|
|
|
def test_pending_sheduler(self):
|
2016-11-08 09:24:50 +00:00
|
|
|
"""Add a coro to pending tasks."""
|
|
|
|
call_count = []
|
|
|
|
|
|
|
|
@asyncio.coroutine
|
|
|
|
def test_coro():
|
|
|
|
"""Test Coro."""
|
|
|
|
call_count.append('call')
|
|
|
|
|
2016-11-24 22:49:29 +00:00
|
|
|
for i in range(3):
|
2016-11-09 16:41:17 +00:00
|
|
|
self.hass.add_job(test_coro())
|
2016-11-08 09:24:50 +00:00
|
|
|
|
2016-11-09 16:41:17 +00:00
|
|
|
run_coroutine_threadsafe(
|
|
|
|
asyncio.wait(self.hass._pending_tasks, loop=self.hass.loop),
|
|
|
|
loop=self.hass.loop
|
|
|
|
).result()
|
|
|
|
|
2016-11-24 22:49:29 +00:00
|
|
|
assert len(self.hass._pending_tasks) == 3
|
|
|
|
assert len(call_count) == 3
|
2016-11-08 09:24:50 +00:00
|
|
|
|
2016-11-09 16:41:17 +00:00
|
|
|
def test_async_add_job_pending_tasks_coro(self):
|
|
|
|
"""Add a coro to pending tasks."""
|
2016-11-08 09:24:50 +00:00
|
|
|
call_count = []
|
|
|
|
|
|
|
|
@asyncio.coroutine
|
|
|
|
def test_coro():
|
|
|
|
"""Test Coro."""
|
|
|
|
call_count.append('call')
|
|
|
|
|
2016-11-17 04:00:08 +00:00
|
|
|
for i in range(2):
|
2016-11-08 09:24:50 +00:00
|
|
|
self.hass.add_job(test_coro())
|
|
|
|
|
2016-11-17 04:00:08 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def wait_finish_callback():
|
|
|
|
"""Wait until all stuff is scheduled."""
|
|
|
|
yield from asyncio.sleep(0, loop=self.hass.loop)
|
|
|
|
yield from asyncio.sleep(0, loop=self.hass.loop)
|
|
|
|
|
|
|
|
run_coroutine_threadsafe(
|
|
|
|
wait_finish_callback(), self.hass.loop).result()
|
|
|
|
|
|
|
|
assert len(self.hass._pending_tasks) == 2
|
2016-11-08 09:24:50 +00:00
|
|
|
self.hass.block_till_done()
|
2016-11-17 04:00:08 +00:00
|
|
|
assert len(call_count) == 2
|
2016-11-08 09:24:50 +00:00
|
|
|
|
2016-11-09 04:01:05 +00:00
|
|
|
def test_async_add_job_pending_tasks_executor(self):
|
|
|
|
"""Run a executor in pending tasks."""
|
|
|
|
call_count = []
|
|
|
|
|
|
|
|
def test_executor():
|
|
|
|
"""Test executor."""
|
|
|
|
call_count.append('call')
|
|
|
|
|
2016-11-17 04:00:08 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def wait_finish_callback():
|
|
|
|
"""Wait until all stuff is scheduled."""
|
|
|
|
yield from asyncio.sleep(0, loop=self.hass.loop)
|
|
|
|
yield from asyncio.sleep(0, loop=self.hass.loop)
|
|
|
|
|
|
|
|
for i in range(2):
|
2016-11-09 04:01:05 +00:00
|
|
|
self.hass.add_job(test_executor)
|
|
|
|
|
2016-11-17 04:00:08 +00:00
|
|
|
run_coroutine_threadsafe(
|
|
|
|
wait_finish_callback(), self.hass.loop).result()
|
|
|
|
|
|
|
|
assert len(self.hass._pending_tasks) == 2
|
2016-11-09 04:01:05 +00:00
|
|
|
self.hass.block_till_done()
|
2016-11-17 04:00:08 +00:00
|
|
|
assert len(call_count) == 2
|
2016-11-09 04:01:05 +00:00
|
|
|
|
|
|
|
def test_async_add_job_pending_tasks_callback(self):
|
|
|
|
"""Run a callback in pending tasks."""
|
|
|
|
call_count = []
|
|
|
|
|
|
|
|
@ha.callback
|
|
|
|
def test_callback():
|
|
|
|
"""Test callback."""
|
|
|
|
call_count.append('call')
|
|
|
|
|
2016-11-17 04:00:08 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def wait_finish_callback():
|
|
|
|
"""Wait until all stuff is scheduled."""
|
|
|
|
yield from asyncio.sleep(0, loop=self.hass.loop)
|
|
|
|
yield from asyncio.sleep(0, loop=self.hass.loop)
|
|
|
|
|
|
|
|
for i in range(2):
|
2016-11-09 04:01:05 +00:00
|
|
|
self.hass.add_job(test_callback)
|
|
|
|
|
2016-11-17 04:00:08 +00:00
|
|
|
run_coroutine_threadsafe(
|
|
|
|
wait_finish_callback(), self.hass.loop).result()
|
|
|
|
|
2016-11-09 04:01:05 +00:00
|
|
|
self.hass.block_till_done()
|
2016-11-17 04:00:08 +00:00
|
|
|
|
|
|
|
assert len(self.hass._pending_tasks) == 0
|
|
|
|
assert len(call_count) == 2
|
2016-11-09 04:01:05 +00:00
|
|
|
|
2016-12-16 05:30:09 +00:00
|
|
|
def test_add_job_with_none(self):
|
|
|
|
"""Try to add a job with None as function."""
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
self.hass.add_job(None, 'test_arg')
|
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
|
|
|
|
class TestEvent(unittest.TestCase):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""A Test Event class."""
|
|
|
|
|
2015-08-04 16:16:10 +00:00
|
|
|
def test_eq(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test events."""
|
2015-08-04 16:16:10 +00:00
|
|
|
now = dt_util.utcnow()
|
|
|
|
data = {'some': 'attr'}
|
|
|
|
event1, event2 = [
|
|
|
|
ha.Event('some_type', data, time_fired=now)
|
|
|
|
for _ in range(2)
|
|
|
|
]
|
|
|
|
|
|
|
|
self.assertEqual(event1, event2)
|
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
def test_repr(self):
|
2016-03-09 10:15:04 +00:00
|
|
|
"""Test that repr method works."""
|
2014-11-23 17:51:16 +00:00
|
|
|
self.assertEqual(
|
|
|
|
"<Event TestEvent[L]>",
|
|
|
|
str(ha.Event("TestEvent")))
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
"<Event TestEvent[R]: beer=nice>",
|
|
|
|
str(ha.Event("TestEvent",
|
|
|
|
{"beer": "nice"},
|
|
|
|
ha.EventOrigin.remote)))
|
|
|
|
|
2015-08-04 16:16:10 +00:00
|
|
|
def test_as_dict(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test as dictionary."""
|
2015-08-04 16:16:10 +00:00
|
|
|
event_type = 'some_type'
|
|
|
|
now = dt_util.utcnow()
|
|
|
|
data = {'some': 'attr'}
|
|
|
|
|
|
|
|
event = ha.Event(event_type, data, ha.EventOrigin.local, now)
|
|
|
|
expected = {
|
|
|
|
'event_type': event_type,
|
|
|
|
'data': data,
|
|
|
|
'origin': 'LOCAL',
|
2016-04-16 07:55:35 +00:00
|
|
|
'time_fired': now,
|
2015-08-04 16:16:10 +00:00
|
|
|
}
|
|
|
|
self.assertEqual(expected, event.as_dict())
|
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
|
|
|
|
class TestEventBus(unittest.TestCase):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test EventBus methods."""
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def setUp(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Setup things to be run when tests are started."""
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass = get_test_home_assistant()
|
|
|
|
self.bus = self.hass.bus
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def tearDown(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Stop down stuff we started."""
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.stop()
|
2014-11-23 20:57:29 +00:00
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
def test_add_remove_listener(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test remove_listener method."""
|
2016-10-31 15:47:29 +00:00
|
|
|
self.hass.allow_pool = False
|
2014-11-23 17:51:16 +00:00
|
|
|
old_count = len(self.bus.listeners)
|
|
|
|
|
2016-02-14 06:57:40 +00:00
|
|
|
def listener(_): pass
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2016-10-18 02:38:41 +00:00
|
|
|
unsub = self.bus.listen('test', listener)
|
2014-11-23 17:51:16 +00:00
|
|
|
|
|
|
|
self.assertEqual(old_count + 1, len(self.bus.listeners))
|
|
|
|
|
|
|
|
# Remove listener
|
2016-10-18 02:38:41 +00:00
|
|
|
unsub()
|
2014-11-23 17:51:16 +00:00
|
|
|
self.assertEqual(old_count, len(self.bus.listeners))
|
|
|
|
|
2016-10-18 02:38:41 +00:00
|
|
|
# Should do nothing now
|
|
|
|
unsub()
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2016-08-26 06:25:35 +00:00
|
|
|
def test_unsubscribe_listener(self):
|
|
|
|
"""Test unsubscribe listener from returned function."""
|
|
|
|
calls = []
|
|
|
|
|
2016-10-31 15:47:29 +00:00
|
|
|
@ha.callback
|
2016-08-26 06:25:35 +00:00
|
|
|
def listener(event):
|
|
|
|
"""Mock listener."""
|
|
|
|
calls.append(event)
|
|
|
|
|
|
|
|
unsub = self.bus.listen('test', listener)
|
|
|
|
|
|
|
|
self.bus.fire('test')
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-08-26 06:25:35 +00:00
|
|
|
|
|
|
|
assert len(calls) == 1
|
|
|
|
|
|
|
|
unsub()
|
|
|
|
|
|
|
|
self.bus.fire('event')
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-08-26 06:25:35 +00:00
|
|
|
|
|
|
|
assert len(calls) == 1
|
|
|
|
|
2016-10-18 02:38:41 +00:00
|
|
|
def test_listen_once_event_with_callback(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test listen_once_event method."""
|
2014-11-29 07:19:59 +00:00
|
|
|
runs = []
|
|
|
|
|
2016-10-18 02:38:41 +00:00
|
|
|
@ha.callback
|
|
|
|
def event_handler(event):
|
|
|
|
runs.append(event)
|
|
|
|
|
|
|
|
self.bus.listen_once('test_event', event_handler)
|
|
|
|
|
|
|
|
self.bus.fire('test_event')
|
|
|
|
# Second time it should not increase runs
|
|
|
|
self.bus.fire('test_event')
|
|
|
|
|
|
|
|
self.hass.block_till_done()
|
|
|
|
self.assertEqual(1, len(runs))
|
|
|
|
|
|
|
|
def test_listen_once_event_with_coroutine(self):
|
|
|
|
"""Test listen_once_event method."""
|
|
|
|
runs = []
|
|
|
|
|
|
|
|
@asyncio.coroutine
|
|
|
|
def event_handler(event):
|
|
|
|
runs.append(event)
|
|
|
|
|
|
|
|
self.bus.listen_once('test_event', event_handler)
|
|
|
|
|
|
|
|
self.bus.fire('test_event')
|
|
|
|
# Second time it should not increase runs
|
|
|
|
self.bus.fire('test_event')
|
|
|
|
|
|
|
|
self.hass.block_till_done()
|
|
|
|
self.assertEqual(1, len(runs))
|
|
|
|
|
|
|
|
def test_listen_once_event_with_thread(self):
|
|
|
|
"""Test listen_once_event method."""
|
|
|
|
runs = []
|
|
|
|
|
|
|
|
def event_handler(event):
|
|
|
|
runs.append(event)
|
|
|
|
|
|
|
|
self.bus.listen_once('test_event', event_handler)
|
2014-11-29 07:19:59 +00:00
|
|
|
|
|
|
|
self.bus.fire('test_event')
|
|
|
|
# Second time it should not increase runs
|
|
|
|
self.bus.fire('test_event')
|
2015-08-04 16:16:10 +00:00
|
|
|
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2014-11-29 07:19:59 +00:00
|
|
|
self.assertEqual(1, len(runs))
|
|
|
|
|
2016-10-05 03:44:32 +00:00
|
|
|
def test_thread_event_listener(self):
|
|
|
|
"""Test a event listener listeners."""
|
|
|
|
thread_calls = []
|
|
|
|
|
|
|
|
def thread_listener(event):
|
|
|
|
thread_calls.append(event)
|
|
|
|
|
|
|
|
self.bus.listen('test_thread', thread_listener)
|
|
|
|
self.bus.fire('test_thread')
|
|
|
|
self.hass.block_till_done()
|
|
|
|
assert len(thread_calls) == 1
|
|
|
|
|
|
|
|
def test_callback_event_listener(self):
|
|
|
|
"""Test a event listener listeners."""
|
|
|
|
callback_calls = []
|
|
|
|
|
|
|
|
@ha.callback
|
|
|
|
def callback_listener(event):
|
|
|
|
callback_calls.append(event)
|
|
|
|
|
|
|
|
self.bus.listen('test_callback', callback_listener)
|
|
|
|
self.bus.fire('test_callback')
|
|
|
|
self.hass.block_till_done()
|
|
|
|
assert len(callback_calls) == 1
|
|
|
|
|
|
|
|
def test_coroutine_event_listener(self):
|
|
|
|
"""Test a event listener listeners."""
|
|
|
|
coroutine_calls = []
|
|
|
|
|
|
|
|
@asyncio.coroutine
|
|
|
|
def coroutine_listener(event):
|
|
|
|
coroutine_calls.append(event)
|
|
|
|
|
|
|
|
self.bus.listen('test_coroutine', coroutine_listener)
|
|
|
|
self.bus.fire('test_coroutine')
|
|
|
|
self.hass.block_till_done()
|
|
|
|
assert len(coroutine_calls) == 1
|
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
|
|
|
|
class TestState(unittest.TestCase):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test State methods."""
|
2014-11-23 17:51:16 +00:00
|
|
|
|
|
|
|
def test_init(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test state.init."""
|
2014-11-23 17:51:16 +00:00
|
|
|
self.assertRaises(
|
2015-08-30 02:44:59 +00:00
|
|
|
InvalidEntityFormatError, ha.State,
|
2014-11-23 17:51:16 +00:00
|
|
|
'invalid_entity_format', 'test_state')
|
|
|
|
|
2015-08-04 16:16:10 +00:00
|
|
|
def test_domain(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test domain."""
|
2015-08-04 16:16:10 +00:00
|
|
|
state = ha.State('some_domain.hello', 'world')
|
|
|
|
self.assertEqual('some_domain', state.domain)
|
|
|
|
|
|
|
|
def test_object_id(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test object ID."""
|
2015-08-04 16:16:10 +00:00
|
|
|
state = ha.State('domain.hello', 'world')
|
|
|
|
self.assertEqual('hello', state.object_id)
|
|
|
|
|
|
|
|
def test_name_if_no_friendly_name_attr(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test if there is no friendly name."""
|
2015-08-04 16:16:10 +00:00
|
|
|
state = ha.State('domain.hello_world', 'world')
|
|
|
|
self.assertEqual('hello world', state.name)
|
|
|
|
|
|
|
|
def test_name_if_friendly_name_attr(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test if there is a friendly name."""
|
2015-08-04 16:16:10 +00:00
|
|
|
name = 'Some Unique Name'
|
|
|
|
state = ha.State('domain.hello_world', 'world',
|
|
|
|
{ATTR_FRIENDLY_NAME: name})
|
|
|
|
self.assertEqual(name, state.name)
|
|
|
|
|
|
|
|
def test_dict_conversion(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test conversion of dict."""
|
2015-08-04 16:16:10 +00:00
|
|
|
state = ha.State('domain.hello', 'world', {'some': 'attr'})
|
|
|
|
self.assertEqual(state, ha.State.from_dict(state.as_dict()))
|
|
|
|
|
|
|
|
def test_dict_conversion_with_wrong_data(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test conversion with wrong data."""
|
2015-08-04 16:16:10 +00:00
|
|
|
self.assertIsNone(ha.State.from_dict(None))
|
|
|
|
self.assertIsNone(ha.State.from_dict({'state': 'yes'}))
|
|
|
|
self.assertIsNone(ha.State.from_dict({'entity_id': 'yes'}))
|
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
def test_repr(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test state.repr."""
|
2016-04-16 07:55:35 +00:00
|
|
|
self.assertEqual("<state happy.happy=on @ 1984-12-08T12:00:00+00:00>",
|
2014-11-23 17:51:16 +00:00
|
|
|
str(ha.State(
|
|
|
|
"happy.happy", "on",
|
|
|
|
last_changed=datetime(1984, 12, 8, 12, 0, 0))))
|
|
|
|
|
2015-01-02 16:48:20 +00:00
|
|
|
self.assertEqual(
|
2016-04-16 07:55:35 +00:00
|
|
|
"<state happy.happy=on; brightness=144 @ "
|
|
|
|
"1984-12-08T12:00:00+00:00>",
|
2015-01-02 16:48:20 +00:00
|
|
|
str(ha.State("happy.happy", "on", {"brightness": 144},
|
|
|
|
datetime(1984, 12, 8, 12, 0, 0))))
|
2014-11-23 17:51:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TestStateMachine(unittest.TestCase):
|
2016-03-09 10:15:04 +00:00
|
|
|
"""Test State machine methods."""
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def setUp(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Setup things to be run when tests are started."""
|
2016-10-31 15:47:29 +00:00
|
|
|
self.hass = get_test_home_assistant()
|
2016-09-13 02:16:14 +00:00
|
|
|
self.states = self.hass.states
|
2014-11-23 17:51:16 +00:00
|
|
|
self.states.set("light.Bowl", "on")
|
|
|
|
self.states.set("switch.AC", "off")
|
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def tearDown(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Stop down stuff we started."""
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.stop()
|
2014-11-23 20:57:29 +00:00
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
def test_is_state(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test is_state method."""
|
2014-11-23 17:51:16 +00:00
|
|
|
self.assertTrue(self.states.is_state('light.Bowl', 'on'))
|
|
|
|
self.assertFalse(self.states.is_state('light.Bowl', 'off'))
|
|
|
|
self.assertFalse(self.states.is_state('light.Non_existing', 'on'))
|
|
|
|
|
2015-12-31 20:58:18 +00:00
|
|
|
def test_is_state_attr(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test is_state_attr method."""
|
2015-12-31 20:58:18 +00:00
|
|
|
self.states.set("light.Bowl", "on", {"brightness": 100})
|
|
|
|
self.assertTrue(
|
|
|
|
self.states.is_state_attr('light.Bowl', 'brightness', 100))
|
|
|
|
self.assertFalse(
|
|
|
|
self.states.is_state_attr('light.Bowl', 'friendly_name', 200))
|
|
|
|
self.assertFalse(
|
|
|
|
self.states.is_state_attr('light.Bowl', 'friendly_name', 'Bowl'))
|
|
|
|
self.assertFalse(
|
|
|
|
self.states.is_state_attr('light.Non_existing', 'brightness', 100))
|
|
|
|
|
2014-11-29 07:19:59 +00:00
|
|
|
def test_entity_ids(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test get_entity_ids method."""
|
2014-11-29 07:19:59 +00:00
|
|
|
ent_ids = self.states.entity_ids()
|
|
|
|
self.assertEqual(2, len(ent_ids))
|
2015-02-06 08:17:30 +00:00
|
|
|
self.assertTrue('light.bowl' in ent_ids)
|
|
|
|
self.assertTrue('switch.ac' in ent_ids)
|
2014-11-29 07:19:59 +00:00
|
|
|
|
|
|
|
ent_ids = self.states.entity_ids('light')
|
|
|
|
self.assertEqual(1, len(ent_ids))
|
2015-02-06 08:17:30 +00:00
|
|
|
self.assertTrue('light.bowl' in ent_ids)
|
2014-11-29 07:19:59 +00:00
|
|
|
|
2015-08-04 16:16:10 +00:00
|
|
|
def test_all(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test everything."""
|
2015-08-04 16:16:10 +00:00
|
|
|
states = sorted(state.entity_id for state in self.states.all())
|
|
|
|
self.assertEqual(['light.bowl', 'switch.ac'], states)
|
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
def test_remove(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test remove method."""
|
2016-02-14 06:57:40 +00:00
|
|
|
events = []
|
2016-10-31 15:47:29 +00:00
|
|
|
|
|
|
|
@ha.callback
|
|
|
|
def callback(event):
|
|
|
|
events.append(event)
|
|
|
|
|
|
|
|
self.hass.bus.listen(EVENT_STATE_CHANGED, callback)
|
2016-02-14 06:57:40 +00:00
|
|
|
|
|
|
|
self.assertIn('light.bowl', self.states.entity_ids())
|
2015-02-06 08:17:30 +00:00
|
|
|
self.assertTrue(self.states.remove('light.bowl'))
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-02-14 06:57:40 +00:00
|
|
|
|
|
|
|
self.assertNotIn('light.bowl', self.states.entity_ids())
|
|
|
|
self.assertEqual(1, len(events))
|
|
|
|
self.assertEqual('light.bowl', events[0].data.get('entity_id'))
|
|
|
|
self.assertIsNotNone(events[0].data.get('old_state'))
|
|
|
|
self.assertEqual('light.bowl', events[0].data['old_state'].entity_id)
|
|
|
|
self.assertIsNone(events[0].data.get('new_state'))
|
2014-11-23 17:51:16 +00:00
|
|
|
|
|
|
|
# If it does not exist, we should get False
|
|
|
|
self.assertFalse(self.states.remove('light.Bowl'))
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-02-14 06:57:40 +00:00
|
|
|
self.assertEqual(1, len(events))
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2014-12-27 07:26:39 +00:00
|
|
|
def test_case_insensitivty(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test insensitivty."""
|
2014-12-27 07:26:39 +00:00
|
|
|
runs = []
|
|
|
|
|
2016-10-31 15:47:29 +00:00
|
|
|
@ha.callback
|
|
|
|
def callback(event):
|
|
|
|
runs.append(event)
|
|
|
|
|
|
|
|
self.hass.bus.listen(EVENT_STATE_CHANGED, callback)
|
2014-12-27 07:26:39 +00:00
|
|
|
|
|
|
|
self.states.set('light.BOWL', 'off')
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2014-12-27 07:26:39 +00:00
|
|
|
|
|
|
|
self.assertTrue(self.states.is_state('light.bowl', 'off'))
|
|
|
|
self.assertEqual(1, len(runs))
|
|
|
|
|
2015-01-02 16:48:20 +00:00
|
|
|
def test_last_changed_not_updated_on_same_state(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test to not update the existing, same state."""
|
2015-01-02 16:48:20 +00:00
|
|
|
state = self.states.get('light.Bowl')
|
|
|
|
|
2015-09-13 05:56:49 +00:00
|
|
|
future = dt_util.utcnow() + timedelta(hours=10)
|
2015-01-02 16:48:20 +00:00
|
|
|
|
2015-09-13 05:56:49 +00:00
|
|
|
with patch('homeassistant.util.dt.utcnow', return_value=future):
|
|
|
|
self.states.set("light.Bowl", "on", {'attr': 'triggers_change'})
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2015-01-02 16:48:20 +00:00
|
|
|
|
2016-09-13 02:16:14 +00:00
|
|
|
state2 = self.states.get('light.Bowl')
|
|
|
|
assert state2 is not None
|
|
|
|
assert state.last_changed == state2.last_changed
|
2015-01-02 16:48:20 +00:00
|
|
|
|
2016-06-26 07:33:23 +00:00
|
|
|
def test_force_update(self):
|
|
|
|
"""Test force update option."""
|
|
|
|
events = []
|
2016-10-31 15:47:29 +00:00
|
|
|
|
|
|
|
@ha.callback
|
|
|
|
def callback(event):
|
|
|
|
events.append(event)
|
|
|
|
|
|
|
|
self.hass.bus.listen(EVENT_STATE_CHANGED, callback)
|
2016-06-26 07:33:23 +00:00
|
|
|
|
|
|
|
self.states.set('light.bowl', 'on')
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-06-26 07:33:23 +00:00
|
|
|
self.assertEqual(0, len(events))
|
|
|
|
|
|
|
|
self.states.set('light.bowl', 'on', None, True)
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-06-26 07:33:23 +00:00
|
|
|
self.assertEqual(1, len(events))
|
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
|
|
|
|
class TestServiceCall(unittest.TestCase):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test ServiceCall class."""
|
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
def test_repr(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test repr method."""
|
2014-11-23 17:51:16 +00:00
|
|
|
self.assertEqual(
|
|
|
|
"<ServiceCall homeassistant.start>",
|
|
|
|
str(ha.ServiceCall('homeassistant', 'start')))
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
"<ServiceCall homeassistant.start: fast=yes>",
|
|
|
|
str(ha.ServiceCall('homeassistant', 'start', {"fast": "yes"})))
|
|
|
|
|
|
|
|
|
|
|
|
class TestServiceRegistry(unittest.TestCase):
|
2016-03-09 10:15:04 +00:00
|
|
|
"""Test ServicerRegistry methods."""
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def setUp(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Setup things to be run when tests are started."""
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass = get_test_home_assistant()
|
|
|
|
self.services = self.hass.services
|
2016-11-05 23:36:20 +00:00
|
|
|
|
|
|
|
@ha.callback
|
|
|
|
def mock_service(call):
|
|
|
|
pass
|
|
|
|
|
|
|
|
self.services.register("Test_Domain", "TEST_SERVICE", mock_service)
|
2014-11-23 17:51:16 +00:00
|
|
|
|
2017-03-08 06:51:34 +00:00
|
|
|
self.calls_register = []
|
|
|
|
|
|
|
|
@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)
|
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def tearDown(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Stop down stuff we started."""
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.stop()
|
2014-11-23 20:57:29 +00:00
|
|
|
|
2014-11-23 17:51:16 +00:00
|
|
|
def test_has_service(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test has_service method."""
|
2014-11-23 17:51:16 +00:00
|
|
|
self.assertTrue(
|
2016-08-10 02:41:45 +00:00
|
|
|
self.services.has_service("tesT_domaiN", "tesT_servicE"))
|
2015-08-04 16:16:10 +00:00
|
|
|
self.assertFalse(
|
|
|
|
self.services.has_service("test_domain", "non_existing"))
|
|
|
|
self.assertFalse(
|
|
|
|
self.services.has_service("non_existing", "test_service"))
|
|
|
|
|
|
|
|
def test_services(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test services."""
|
2015-08-04 16:16:10 +00:00
|
|
|
expected = {
|
2015-09-27 06:17:04 +00:00
|
|
|
'test_domain': {'test_service': {'description': '', 'fields': {}}}
|
2015-08-04 16:16:10 +00:00
|
|
|
}
|
|
|
|
self.assertEqual(expected, self.services.services)
|
|
|
|
|
|
|
|
def test_call_with_blocking_done_in_time(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test call with blocking."""
|
2015-08-04 16:16:10 +00:00
|
|
|
calls = []
|
2016-09-30 19:57:24 +00:00
|
|
|
|
2016-11-05 23:36:20 +00:00
|
|
|
@ha.callback
|
2016-09-30 19:57:24 +00:00
|
|
|
def service_handler(call):
|
|
|
|
"""Service handler."""
|
|
|
|
calls.append(call)
|
|
|
|
|
2017-03-08 06:51:34 +00:00
|
|
|
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'
|
2015-08-04 16:16:10 +00:00
|
|
|
|
|
|
|
self.assertTrue(
|
2016-08-10 02:41:45 +00:00
|
|
|
self.services.call('test_domain', 'REGISTER_CALLS', blocking=True))
|
2015-08-04 16:16:10 +00:00
|
|
|
self.assertEqual(1, len(calls))
|
|
|
|
|
|
|
|
def test_call_non_existing_with_blocking(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test non-existing with blocking."""
|
2016-09-13 02:16:14 +00:00
|
|
|
prior = ha.SERVICE_CALL_LIMIT
|
|
|
|
try:
|
|
|
|
ha.SERVICE_CALL_LIMIT = 0.01
|
|
|
|
assert not self.services.call('test_domain', 'i_do_not_exist',
|
|
|
|
blocking=True)
|
|
|
|
finally:
|
|
|
|
ha.SERVICE_CALL_LIMIT = prior
|
2015-08-04 16:16:10 +00:00
|
|
|
|
2016-09-30 19:57:24 +00:00
|
|
|
def test_async_service(self):
|
|
|
|
"""Test registering and calling an async service."""
|
|
|
|
calls = []
|
|
|
|
|
|
|
|
@asyncio.coroutine
|
|
|
|
def service_handler(call):
|
|
|
|
"""Service handler coroutine."""
|
|
|
|
calls.append(call)
|
|
|
|
|
2017-03-08 06:51:34 +00:00
|
|
|
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'
|
|
|
|
|
2016-09-30 19:57:24 +00:00
|
|
|
self.assertTrue(
|
|
|
|
self.services.call('test_domain', 'REGISTER_CALLS', blocking=True))
|
|
|
|
self.hass.block_till_done()
|
|
|
|
self.assertEqual(1, len(calls))
|
|
|
|
|
2016-10-05 03:44:32 +00:00
|
|
|
def test_callback_service(self):
|
|
|
|
"""Test registering and calling an async service."""
|
|
|
|
calls = []
|
|
|
|
|
|
|
|
@ha.callback
|
|
|
|
def service_handler(call):
|
|
|
|
"""Service handler coroutine."""
|
|
|
|
calls.append(call)
|
|
|
|
|
2017-03-08 06:51:34 +00:00
|
|
|
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'
|
|
|
|
|
2016-10-05 03:44:32 +00:00
|
|
|
self.assertTrue(
|
|
|
|
self.services.call('test_domain', 'REGISTER_CALLS', blocking=True))
|
|
|
|
self.hass.block_till_done()
|
|
|
|
self.assertEqual(1, len(calls))
|
|
|
|
|
2017-03-08 06:51:34 +00:00
|
|
|
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
|
|
|
|
|
2015-08-04 16:16:10 +00:00
|
|
|
|
|
|
|
class TestConfig(unittest.TestCase):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test configuration methods."""
|
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def setUp(self):
|
2016-03-09 10:15:04 +00:00
|
|
|
"""Setup things to be run when tests are started."""
|
2015-08-04 16:16:10 +00:00
|
|
|
self.config = ha.Config()
|
2016-08-09 03:21:40 +00:00
|
|
|
self.assertIsNone(self.config.config_dir)
|
2015-08-04 16:16:10 +00:00
|
|
|
|
|
|
|
def test_path_with_file(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test get_config_path method."""
|
2016-08-09 03:21:40 +00:00
|
|
|
self.config.config_dir = '/tmp/ha-config'
|
|
|
|
self.assertEqual("/tmp/ha-config/test.conf",
|
2015-08-04 16:16:10 +00:00
|
|
|
self.config.path("test.conf"))
|
|
|
|
|
|
|
|
def test_path_with_dir_and_file(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test get_config_path method."""
|
2016-08-09 03:21:40 +00:00
|
|
|
self.config.config_dir = '/tmp/ha-config'
|
|
|
|
self.assertEqual("/tmp/ha-config/dir/test.conf",
|
|
|
|
self.config.path("dir", "test.conf"))
|
2015-08-04 16:16:10 +00:00
|
|
|
|
|
|
|
def test_as_dict(self):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test as dict."""
|
2016-10-03 07:04:43 +00:00
|
|
|
self.config.config_dir = '/tmp/ha-config'
|
2015-08-04 16:16:10 +00:00
|
|
|
expected = {
|
|
|
|
'latitude': None,
|
|
|
|
'longitude': None,
|
2017-01-20 07:55:29 +00:00
|
|
|
'elevation': None,
|
2016-07-31 20:24:49 +00:00
|
|
|
CONF_UNIT_SYSTEM: METRIC_SYSTEM.as_dict(),
|
2015-08-04 16:16:10 +00:00
|
|
|
'location_name': None,
|
|
|
|
'time_zone': 'UTC',
|
2017-02-09 18:21:57 +00:00
|
|
|
'components': set(),
|
2016-10-03 07:04:43 +00:00
|
|
|
'config_dir': '/tmp/ha-config',
|
2015-10-26 04:00:22 +00:00
|
|
|
'version': __version__,
|
2015-08-04 16:16:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.assertEqual(expected, self.config.as_dict())
|
|
|
|
|
|
|
|
|
2017-02-10 17:00:17 +00:00
|
|
|
@patch('homeassistant.core.monotonic')
|
|
|
|
def test_create_timer(mock_monotonic, loop):
|
2016-09-20 06:39:49 +00:00
|
|
|
"""Test create timer."""
|
2017-02-10 17:00:17 +00:00
|
|
|
hass = MagicMock()
|
|
|
|
funcs = []
|
|
|
|
orig_callback = ha.callback
|
|
|
|
|
|
|
|
def mock_callback(func):
|
|
|
|
funcs.append(func)
|
|
|
|
return orig_callback(func)
|
|
|
|
|
2017-04-07 04:00:58 +00:00
|
|
|
mock_monotonic.side_effect = 10.2, 10.3
|
|
|
|
|
|
|
|
with patch.object(ha, 'callback', mock_callback), \
|
|
|
|
patch('homeassistant.core.dt_util.utcnow',
|
|
|
|
return_value=sentinel.mock_date):
|
2017-02-10 17:00:17 +00:00
|
|
|
ha._async_create_timer(hass)
|
|
|
|
|
2017-04-07 04:00:58 +00:00
|
|
|
assert len(funcs) == 2
|
|
|
|
fire_time_event, stop_timer = funcs
|
2017-02-10 17:00:17 +00:00
|
|
|
|
|
|
|
assert len(hass.bus.async_listen_once.mock_calls) == 1
|
|
|
|
assert len(hass.bus.async_fire.mock_calls) == 1
|
|
|
|
assert len(hass.loop.call_later.mock_calls) == 1
|
|
|
|
|
2017-04-07 04:00:58 +00:00
|
|
|
event_type, callback = hass.bus.async_listen_once.mock_calls[0][1]
|
2017-02-10 17:00:17 +00:00
|
|
|
assert event_type == EVENT_HOMEASSISTANT_STOP
|
|
|
|
assert callback is stop_timer
|
|
|
|
|
|
|
|
slp_seconds, callback, nxt = hass.loop.call_later.mock_calls[0][1]
|
|
|
|
assert abs(slp_seconds - 0.9) < 0.001
|
|
|
|
assert callback is fire_time_event
|
|
|
|
assert abs(nxt - 11.2) < 0.001
|
|
|
|
|
|
|
|
event_type, event_data = hass.bus.async_fire.mock_calls[0][1]
|
|
|
|
assert event_type == EVENT_TIME_CHANGED
|
|
|
|
assert event_data[ATTR_NOW] is sentinel.mock_date
|
|
|
|
|
|
|
|
|
|
|
|
@patch('homeassistant.core.monotonic')
|
|
|
|
def test_timer_out_of_sync(mock_monotonic, loop):
|
|
|
|
"""Test create timer."""
|
|
|
|
hass = MagicMock()
|
|
|
|
funcs = []
|
|
|
|
orig_callback = ha.callback
|
2016-09-20 06:39:49 +00:00
|
|
|
|
2017-02-10 17:00:17 +00:00
|
|
|
def mock_callback(func):
|
|
|
|
funcs.append(func)
|
|
|
|
return orig_callback(func)
|
2016-09-20 06:39:49 +00:00
|
|
|
|
2017-02-10 17:00:17 +00:00
|
|
|
mock_monotonic.side_effect = 10.2, 11.3, 11.3
|
2016-09-20 06:39:49 +00:00
|
|
|
|
2017-04-07 04:00:58 +00:00
|
|
|
with patch.object(ha, 'callback', mock_callback), \
|
|
|
|
patch('homeassistant.core.dt_util.utcnow',
|
|
|
|
return_value=sentinel.mock_date):
|
|
|
|
ha._async_create_timer(hass)
|
|
|
|
|
|
|
|
assert len(funcs) == 2
|
|
|
|
fire_time_event, stop_timer = funcs
|
2016-09-20 06:39:49 +00:00
|
|
|
|
2017-02-10 17:00:17 +00:00
|
|
|
assert len(hass.loop.call_later.mock_calls) == 1
|
2016-09-20 06:39:49 +00:00
|
|
|
|
2017-02-10 17:00:17 +00:00
|
|
|
slp_seconds, callback, nxt = hass.loop.call_later.mock_calls[0][1]
|
|
|
|
assert slp_seconds == 1
|
|
|
|
assert callback is fire_time_event
|
|
|
|
assert abs(nxt - 12.3) < 0.001
|