ha-core/tests/test_config.py

312 lines
11 KiB
Python
Raw Normal View History

2016-03-09 10:25:50 +01:00
"""Test config utils."""
# pylint: disable=too-many-public-methods,protected-access
import os
import tempfile
import unittest
import unittest.mock as mock
2016-03-28 03:48:51 +02:00
import pytest
from voluptuous import MultipleInvalid
from homeassistant.core import DOMAIN, HomeAssistantError, Config
import homeassistant.config as config_util
from homeassistant.const import (
CONF_LATITUDE, CONF_LONGITUDE, CONF_TEMPERATURE_UNIT, CONF_NAME,
CONF_TIME_ZONE, CONF_ELEVATION, CONF_CUSTOMIZE, __version__,
TEMP_FAHRENHEIT)
from homeassistant.util import location as location_util, dt as dt_util
from homeassistant.helpers.entity import Entity
from tests.common import (
get_test_config_dir, get_test_home_assistant)
CONFIG_DIR = get_test_config_dir()
YAML_PATH = os.path.join(CONFIG_DIR, config_util.YAML_CONFIG_FILE)
ORIG_TIMEZONE = dt_util.DEFAULT_TIME_ZONE
def create_file(path):
2016-03-09 10:25:50 +01:00
"""Create an empty file."""
with open(path, 'w'):
pass
class TestConfig(unittest.TestCase):
2016-03-09 11:15:04 +01:00
"""Test the configutils."""
def tearDown(self): # pylint: disable=invalid-name
2016-03-09 10:25:50 +01:00
"""Clean up."""
dt_util.DEFAULT_TIME_ZONE = ORIG_TIMEZONE
if os.path.isfile(YAML_PATH):
os.remove(YAML_PATH)
if hasattr(self, 'hass'):
self.hass.stop()
def test_create_default_config(self):
2016-03-09 10:25:50 +01:00
"""Test creation of default config."""
config_util.create_default_config(CONFIG_DIR, False)
self.assertTrue(os.path.isfile(YAML_PATH))
def test_find_config_file_yaml(self):
2016-03-09 10:25:50 +01:00
"""Test if it finds a YAML config file."""
create_file(YAML_PATH)
self.assertEqual(YAML_PATH, config_util.find_config_file(CONFIG_DIR))
2015-09-01 09:18:26 +02:00
@mock.patch('builtins.print')
def test_ensure_config_exists_creates_config(self, mock_print):
2016-03-09 10:25:50 +01:00
"""Test that calling ensure_config_exists.
2016-03-09 10:25:50 +01:00
If not creates a new config file.
"""
config_util.ensure_config_exists(CONFIG_DIR, False)
self.assertTrue(os.path.isfile(YAML_PATH))
2015-09-01 09:18:26 +02:00
self.assertTrue(mock_print.called)
def test_ensure_config_exists_uses_existing_config(self):
2016-03-09 10:25:50 +01:00
"""Test that calling ensure_config_exists uses existing config."""
create_file(YAML_PATH)
config_util.ensure_config_exists(CONFIG_DIR, False)
with open(YAML_PATH) as f:
content = f.read()
# File created with create_file are empty
self.assertEqual('', content)
def test_load_yaml_config_converts_empty_files_to_dict(self):
2016-03-09 11:15:04 +01:00
"""Test that loading an empty file returns an empty dict."""
create_file(YAML_PATH)
self.assertIsInstance(
config_util.load_yaml_config_file(YAML_PATH), dict)
def test_load_yaml_config_raises_error_if_not_dict(self):
2016-03-09 10:25:50 +01:00
"""Test error raised when YAML file is not a dict."""
with open(YAML_PATH, 'w') as f:
f.write('5')
with self.assertRaises(HomeAssistantError):
config_util.load_yaml_config_file(YAML_PATH)
def test_load_yaml_config_raises_error_if_malformed_yaml(self):
2016-03-09 10:25:50 +01:00
"""Test error raised if invalid YAML."""
with open(YAML_PATH, 'w') as f:
f.write(':')
with self.assertRaises(HomeAssistantError):
config_util.load_yaml_config_file(YAML_PATH)
2016-02-02 08:41:18 +01:00
def test_load_yaml_config_raises_error_if_unsafe_yaml(self):
2016-03-09 10:25:50 +01:00
"""Test error raised if unsafe YAML."""
2016-02-02 08:41:18 +01:00
with open(YAML_PATH, 'w') as f:
f.write('hello: !!python/object/apply:os.system')
with self.assertRaises(HomeAssistantError):
config_util.load_yaml_config_file(YAML_PATH)
2016-01-24 07:37:15 +01:00
def test_load_yaml_config_preserves_key_order(self):
2016-03-09 10:25:50 +01:00
"""Test removal of library."""
with open(YAML_PATH, 'w') as f:
2016-01-24 07:37:15 +01:00
f.write('hello: 0\n')
f.write('world: 1\n')
2016-01-24 07:37:15 +01:00
self.assertEqual(
[('hello', 0), ('world', 1)],
list(config_util.load_yaml_config_file(YAML_PATH).items()))
@mock.patch('homeassistant.util.location.detect_location_info',
return_value=location_util.LocationInfo(
'0.0.0.0', 'US', 'United States', 'CA', 'California',
'San Diego', '92122', 'America/Los_Angeles', 32.8594,
-117.2073, True))
@mock.patch('homeassistant.util.location.elevation', return_value=101)
2015-09-01 09:18:26 +02:00
@mock.patch('builtins.print')
def test_create_default_config_detect_location(self, mock_detect,
mock_elev, mock_print):
2016-03-09 10:25:50 +01:00
"""Test that detect location sets the correct config keys."""
2015-09-01 09:18:26 +02:00
config_util.ensure_config_exists(CONFIG_DIR)
2016-01-24 07:37:15 +01:00
config = config_util.load_yaml_config_file(YAML_PATH)
self.assertIn(DOMAIN, config)
ha_conf = config[DOMAIN]
expected_values = {
CONF_LATITUDE: 32.8594,
CONF_LONGITUDE: -117.2073,
CONF_ELEVATION: 101,
CONF_TEMPERATURE_UNIT: 'F',
CONF_NAME: 'Home',
CONF_TIME_ZONE: 'America/Los_Angeles'
}
assert expected_values == ha_conf
assert mock_print.called
2015-09-01 09:18:26 +02:00
@mock.patch('builtins.print')
def test_create_default_config_returns_none_if_write_error(self,
mock_print):
2016-03-09 10:25:50 +01:00
"""Test the writing of a default configuration.
Non existing folder returns None.
"""
self.assertIsNone(
config_util.create_default_config(
os.path.join(CONFIG_DIR, 'non_existing_dir/'), False))
2015-09-01 09:18:26 +02:00
self.assertTrue(mock_print.called)
2016-03-28 03:48:51 +02:00
def test_core_config_schema(self):
for value in (
{'temperature_unit': 'K'},
{'time_zone': 'non-exist'},
{'latitude': '91'},
{'longitude': -181},
{'customize': 'bla'},
{'customize': {'invalid_entity_id': {}}},
{'customize': {'light.sensor': 100}},
):
with pytest.raises(MultipleInvalid):
config_util.CORE_CONFIG_SCHEMA(value)
config_util.CORE_CONFIG_SCHEMA({
'name': 'Test name',
'latitude': '-23.45',
'longitude': '123.45',
'temperature_unit': 'c',
'customize': {
'sensor.temperature': {
'hidden': True,
},
},
})
def test_entity_customization(self):
"""Test entity customization through configuration."""
self.hass = get_test_home_assistant()
config = {CONF_LATITUDE: 50,
CONF_LONGITUDE: 50,
CONF_NAME: 'Test',
CONF_CUSTOMIZE: {'test.test': {'hidden': True}}}
config_util.process_ha_core_config(self.hass, config)
entity = Entity()
entity.entity_id = 'test.test'
entity.hass = self.hass
entity.update_ha_state()
state = self.hass.states.get('test.test')
assert state.attributes['hidden']
def test_remove_lib_on_upgrade(self):
"""Test removal of library on upgrade."""
with tempfile.TemporaryDirectory() as config_dir:
version_path = os.path.join(config_dir, '.HA_VERSION')
lib_dir = os.path.join(config_dir, 'deps')
check_file = os.path.join(lib_dir, 'check')
with open(version_path, 'wt') as outp:
outp.write('0.7.0')
os.mkdir(lib_dir)
with open(check_file, 'w'):
pass
self.hass = get_test_home_assistant()
self.hass.config.config_dir = config_dir
assert os.path.isfile(check_file)
config_util.process_ha_config_upgrade(self.hass)
assert not os.path.isfile(check_file)
def test_not_remove_lib_if_not_upgrade(self):
"""Test removal of library with no upgrade."""
with tempfile.TemporaryDirectory() as config_dir:
version_path = os.path.join(config_dir, '.HA_VERSION')
lib_dir = os.path.join(config_dir, 'deps')
check_file = os.path.join(lib_dir, 'check')
with open(version_path, 'wt') as outp:
outp.write(__version__)
os.mkdir(lib_dir)
with open(check_file, 'w'):
pass
self.hass = get_test_home_assistant()
self.hass.config.config_dir = config_dir
config_util.process_ha_config_upgrade(self.hass)
assert os.path.isfile(check_file)
def test_loading_configuration(self):
"""Test loading core config onto hass object."""
config = Config()
hass = mock.Mock(config=config)
config_util.process_ha_core_config(hass, {
'latitude': 60,
'longitude': 50,
'elevation': 25,
'name': 'Huis',
'temperature_unit': 'F',
'time_zone': 'America/New_York',
})
assert config.latitude == 60
assert config.longitude == 50
assert config.elevation == 25
assert config.location_name == 'Huis'
assert config.temperature_unit == TEMP_FAHRENHEIT
assert config.time_zone.zone == 'America/New_York'
@mock.patch('homeassistant.util.location.detect_location_info',
return_value=location_util.LocationInfo(
'0.0.0.0', 'US', 'United States', 'CA', 'California',
'San Diego', '92122', 'America/Los_Angeles', 32.8594,
-117.2073, True))
@mock.patch('homeassistant.util.location.elevation', return_value=101)
def test_discovering_configuration(self, mock_detect, mock_elevation):
"""Test auto discovery for missing core configs."""
config = Config()
hass = mock.Mock(config=config)
config_util.process_ha_core_config(hass, {})
assert config.latitude == 32.8594
assert config.longitude == -117.2073
assert config.elevation == 101
assert config.location_name == 'San Diego'
assert config.temperature_unit == TEMP_FAHRENHEIT
assert config.time_zone.zone == 'America/Los_Angeles'
@mock.patch('homeassistant.util.location.detect_location_info',
return_value=None)
@mock.patch('homeassistant.util.location.elevation', return_value=0)
def test_discovering_configuration_auto_detect_fails(self, mock_detect,
mock_elevation):
"""Test config remains unchanged if discovery fails."""
config = Config()
hass = mock.Mock(config=config)
config_util.process_ha_core_config(hass, {})
blankConfig = Config()
assert config.latitude == blankConfig.latitude
assert config.longitude == blankConfig.longitude
assert config.elevation == blankConfig.elevation
assert config.location_name == blankConfig.location_name
assert config.temperature_unit == blankConfig.temperature_unit
assert config.time_zone == blankConfig.time_zone