2017-02-21 07:40:27 +00:00
|
|
|
"""The tests for the Restore component."""
|
2018-11-28 12:16:43 +00:00
|
|
|
from datetime import datetime
|
2017-02-21 07:40:27 +00:00
|
|
|
|
|
|
|
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
2018-11-28 12:16:43 +00:00
|
|
|
from homeassistant.core import CoreState, State
|
|
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
|
|
from homeassistant.helpers.entity import Entity
|
2017-02-21 07:40:27 +00:00
|
|
|
from homeassistant.helpers.restore_state import (
|
2018-11-30 07:26:19 +00:00
|
|
|
RestoreStateData, RestoreEntity, StoredState, DATA_RESTORE_STATE_TASK)
|
2018-11-28 12:16:43 +00:00
|
|
|
from homeassistant.util import dt as dt_util
|
2017-02-21 07:40:27 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
from asynctest import patch
|
2017-02-22 08:15:48 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
from tests.common import mock_coro
|
2017-02-21 07:40:27 +00:00
|
|
|
|
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
async def test_caching_data(hass):
|
|
|
|
"""Test that we cache data."""
|
2018-11-30 07:26:19 +00:00
|
|
|
now = dt_util.utcnow()
|
|
|
|
stored_states = [
|
|
|
|
StoredState(State('input_boolean.b0', 'on'), now),
|
|
|
|
StoredState(State('input_boolean.b1', 'on'), now),
|
|
|
|
StoredState(State('input_boolean.b2', 'on'), now),
|
2017-02-21 07:40:27 +00:00
|
|
|
]
|
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
data = await RestoreStateData.async_get_instance(hass)
|
2018-11-30 07:26:19 +00:00
|
|
|
await data.store.async_save([state.as_dict() for state in stored_states])
|
2017-02-21 07:40:27 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
# Emulate a fresh load
|
|
|
|
hass.data[DATA_RESTORE_STATE_TASK] = None
|
|
|
|
|
|
|
|
entity = RestoreEntity()
|
|
|
|
entity.hass = hass
|
|
|
|
entity.entity_id = 'input_boolean.b1'
|
|
|
|
|
|
|
|
# Mock that only b1 is present this run
|
|
|
|
with patch('homeassistant.helpers.restore_state.Store.async_save'
|
|
|
|
) as mock_write_data:
|
|
|
|
state = await entity.async_get_last_state()
|
2017-02-21 07:40:27 +00:00
|
|
|
|
|
|
|
assert state is not None
|
|
|
|
assert state.entity_id == 'input_boolean.b1'
|
|
|
|
assert state.state == 'on'
|
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
assert mock_write_data.called
|
2017-02-21 07:40:27 +00:00
|
|
|
|
2017-02-22 08:15:48 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
async def test_hass_starting(hass):
|
|
|
|
"""Test that we cache data."""
|
|
|
|
hass.state = CoreState.starting
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-30 07:26:19 +00:00
|
|
|
now = dt_util.utcnow()
|
|
|
|
stored_states = [
|
|
|
|
StoredState(State('input_boolean.b0', 'on'), now),
|
|
|
|
StoredState(State('input_boolean.b1', 'on'), now),
|
|
|
|
StoredState(State('input_boolean.b2', 'on'), now),
|
2017-10-03 03:25:04 +00:00
|
|
|
]
|
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
data = await RestoreStateData.async_get_instance(hass)
|
2018-11-30 07:26:19 +00:00
|
|
|
await data.store.async_save([state.as_dict() for state in stored_states])
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
# Emulate a fresh load
|
|
|
|
hass.data[DATA_RESTORE_STATE_TASK] = None
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
entity = RestoreEntity()
|
|
|
|
entity.hass = hass
|
|
|
|
entity.entity_id = 'input_boolean.b1'
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
# Mock that only b1 is present this run
|
|
|
|
states = [
|
|
|
|
State('input_boolean.b1', 'on'),
|
|
|
|
]
|
|
|
|
with patch('homeassistant.helpers.restore_state.Store.async_save'
|
|
|
|
) as mock_write_data, patch.object(
|
|
|
|
hass.states, 'async_all', return_value=states):
|
|
|
|
state = await entity.async_get_last_state()
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
assert state is not None
|
|
|
|
assert state.entity_id == 'input_boolean.b1'
|
|
|
|
assert state.state == 'on'
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
# Assert that no data was written yet, since hass is still starting.
|
|
|
|
assert not mock_write_data.called
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
# Finish hass startup
|
|
|
|
with patch('homeassistant.helpers.restore_state.Store.async_save'
|
|
|
|
) as mock_write_data:
|
|
|
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
|
|
|
|
await hass.async_block_till_done()
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
# Assert that this session states were written
|
|
|
|
assert mock_write_data.called
|
2017-10-03 03:25:04 +00:00
|
|
|
|
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
async def test_dump_data(hass):
|
|
|
|
"""Test that we cache data."""
|
|
|
|
states = [
|
|
|
|
State('input_boolean.b0', 'on'),
|
|
|
|
State('input_boolean.b1', 'on'),
|
|
|
|
State('input_boolean.b2', 'on'),
|
|
|
|
]
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
entity = Entity()
|
|
|
|
entity.hass = hass
|
|
|
|
entity.entity_id = 'input_boolean.b0'
|
|
|
|
await entity.async_added_to_hass()
|
|
|
|
|
|
|
|
entity = RestoreEntity()
|
|
|
|
entity.hass = hass
|
|
|
|
entity.entity_id = 'input_boolean.b1'
|
|
|
|
await entity.async_added_to_hass()
|
|
|
|
|
|
|
|
data = await RestoreStateData.async_get_instance(hass)
|
2018-11-30 07:26:19 +00:00
|
|
|
now = dt_util.utcnow()
|
2018-11-28 12:16:43 +00:00
|
|
|
data.last_states = {
|
2018-11-30 07:26:19 +00:00
|
|
|
'input_boolean.b0': StoredState(State('input_boolean.b0', 'off'), now),
|
|
|
|
'input_boolean.b1': StoredState(State('input_boolean.b1', 'off'), now),
|
|
|
|
'input_boolean.b2': StoredState(State('input_boolean.b2', 'off'), now),
|
|
|
|
'input_boolean.b3': StoredState(State('input_boolean.b3', 'off'), now),
|
|
|
|
'input_boolean.b4': StoredState(
|
|
|
|
State('input_boolean.b4', 'off'),
|
|
|
|
datetime(1985, 10, 26, 1, 22, tzinfo=dt_util.UTC)),
|
2018-11-28 12:16:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
with patch('homeassistant.helpers.restore_state.Store.async_save'
|
|
|
|
) as mock_write_data, patch.object(
|
|
|
|
hass.states, 'async_all', return_value=states):
|
|
|
|
await data.async_dump_states()
|
|
|
|
|
|
|
|
assert mock_write_data.called
|
|
|
|
args = mock_write_data.mock_calls[0][1]
|
|
|
|
written_states = args[0]
|
|
|
|
|
|
|
|
# b0 should not be written, since it didn't extend RestoreEntity
|
|
|
|
# b1 should be written, since it is present in the current run
|
|
|
|
# b2 should not be written, since it is not registered with the helper
|
|
|
|
# b3 should be written, since it is still not expired
|
|
|
|
# b4 should not be written, since it is now expired
|
|
|
|
assert len(written_states) == 2
|
2018-11-30 07:26:19 +00:00
|
|
|
assert written_states[0]['state']['entity_id'] == 'input_boolean.b1'
|
|
|
|
assert written_states[0]['state']['state'] == 'on'
|
|
|
|
assert written_states[1]['state']['entity_id'] == 'input_boolean.b3'
|
|
|
|
assert written_states[1]['state']['state'] == 'off'
|
2018-11-28 12:16:43 +00:00
|
|
|
|
|
|
|
# Test that removed entities are not persisted
|
|
|
|
await entity.async_will_remove_from_hass()
|
|
|
|
|
|
|
|
with patch('homeassistant.helpers.restore_state.Store.async_save'
|
|
|
|
) as mock_write_data, patch.object(
|
|
|
|
hass.states, 'async_all', return_value=states):
|
|
|
|
await data.async_dump_states()
|
|
|
|
|
|
|
|
assert mock_write_data.called
|
|
|
|
args = mock_write_data.mock_calls[0][1]
|
|
|
|
written_states = args[0]
|
|
|
|
assert len(written_states) == 1
|
2018-11-30 07:26:19 +00:00
|
|
|
assert written_states[0]['state']['entity_id'] == 'input_boolean.b3'
|
|
|
|
assert written_states[0]['state']['state'] == 'off'
|
2018-11-28 12:16:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_dump_error(hass):
|
|
|
|
"""Test that we cache data."""
|
|
|
|
states = [
|
|
|
|
State('input_boolean.b0', 'on'),
|
|
|
|
State('input_boolean.b1', 'on'),
|
|
|
|
State('input_boolean.b2', 'on'),
|
|
|
|
]
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
entity = Entity()
|
|
|
|
entity.hass = hass
|
|
|
|
entity.entity_id = 'input_boolean.b0'
|
|
|
|
await entity.async_added_to_hass()
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
entity = RestoreEntity()
|
|
|
|
entity.hass = hass
|
|
|
|
entity.entity_id = 'input_boolean.b1'
|
|
|
|
await entity.async_added_to_hass()
|
2017-02-22 08:15:48 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
data = await RestoreStateData.async_get_instance(hass)
|
2017-02-22 08:15:48 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
with patch('homeassistant.helpers.restore_state.Store.async_save',
|
|
|
|
return_value=mock_coro(exception=HomeAssistantError)
|
|
|
|
) as mock_write_data, patch.object(
|
|
|
|
hass.states, 'async_all', return_value=states):
|
|
|
|
await data.async_dump_states()
|
2017-02-22 08:15:48 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
assert mock_write_data.called
|
2017-02-22 08:15:48 +00:00
|
|
|
|
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
async def test_load_error(hass):
|
|
|
|
"""Test that we cache data."""
|
|
|
|
entity = RestoreEntity()
|
|
|
|
entity.hass = hass
|
|
|
|
entity.entity_id = 'input_boolean.b1'
|
2017-02-22 08:15:48 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
with patch('homeassistant.helpers.storage.Store.async_load',
|
|
|
|
return_value=mock_coro(exception=HomeAssistantError)):
|
|
|
|
state = await entity.async_get_last_state()
|
2017-02-22 08:15:48 +00:00
|
|
|
|
2018-11-28 12:16:43 +00:00
|
|
|
assert state is None
|