def test_component_platform_not_found(self, isfile_patch): """Test errors if component or platform not found.""" # Make sure they don't exist set_component('beer', None) files = { YAML_CONFIG_FILE: BASE_CONFIG + 'beer:', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir()) assert res['components'].keys() == {'homeassistant'} assert res['except'] == { check_config.ERROR_STR: ['Component not found: beer']} assert res['secret_cache'] == {} assert res['secrets'] == {} assert len(res['yaml_files']) == 1 set_component('light.beer', None) files = { YAML_CONFIG_FILE: BASE_CONFIG + 'light:\n platform: beer', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir()) assert res['components'].keys() == {'homeassistant', 'light'} assert res['components']['light'] == [] assert res['except'] == { check_config.ERROR_STR: [ 'Platform not found: light.beer', ]} assert res['secret_cache'] == {} assert res['secrets'] == {} assert len(res['yaml_files']) == 1
def test_config_component_platform_fail_validation(self): """Test errors if component & platform not found.""" files = { 'component.yaml': BASE_CONFIG + 'http:\n password: err123', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('component.yaml')) change_yaml_files(res) self.assertDictEqual({ 'components': {}, 'except': {'http': {'password': '******'}}, 'secret_cache': {}, 'secrets': {}, 'yaml_files': ['.../component.yaml'] }, res) files = { 'platform.yaml': (BASE_CONFIG + 'mqtt:\n\n' 'light:\n platform: mqtt_json'), } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('platform.yaml')) change_yaml_files(res) self.assertDictEqual({ 'components': {'mqtt': {'keepalive': 60, 'port': 1883, 'protocol': '3.1.1'}}, 'except': {'light.mqtt_json': {'platform': 'mqtt_json'}}, 'secret_cache': {}, 'secrets': {}, 'yaml_files': ['.../platform.yaml'] }, res)
def test_include_yaml(self): """Test include yaml.""" with patch_yaml_files({'test.yaml': 'value'}): conf = 'key: !include test.yaml' with io.StringIO(conf) as file: doc = yaml.yaml.safe_load(file) assert doc["key"] == "value" with patch_yaml_files({'test.yaml': None}): conf = 'key: !include test.yaml' with io.StringIO(conf) as file: doc = yaml.yaml.safe_load(file) assert doc["key"] == {}
def test_secrets(self, isfile_patch): """Test secrets config checking method.""" secrets_path = get_test_config_dir('secrets.yaml') files = { get_test_config_dir(YAML_CONFIG_FILE): BASE_CONFIG + ( 'http:\n' ' api_password: !secret http_pw'), secrets_path: ( 'logger: debug\n' 'http_pw: abc123'), } with patch_yaml_files(files): res = check_config.check(get_test_config_dir(), True) assert res['except'] == {} assert res['components'].keys() == {'homeassistant', 'http'} assert res['components']['http'] == { 'api_password': '******', 'cors_allowed_origins': [], 'ip_ban_enabled': True, 'login_attempts_threshold': -1, 'server_host': '0.0.0.0', 'server_port': 8123, 'trusted_networks': [], 'use_x_forwarded_for': False} assert res['secret_cache'] == {secrets_path: {'http_pw': 'abc123'}} assert res['secrets'] == {'http_pw': 'abc123'} assert normalize_yaml_files(res) == [ '.../configuration.yaml', '.../secrets.yaml']
def test_include_dir_merge_named_recursive(self, mock_walk): """Test include dir merge named yaml.""" mock_walk.return_value = [ ['/tmp', ['tmp2', '.ignore', 'ignore'], ['first.yaml']], ['/tmp/tmp2', [], ['second.yaml', 'third.yaml']], ['/tmp/ignore', [], ['.ignore.yaml']] ] with patch_yaml_files({ '/tmp/first.yaml': 'key1: one', '/tmp/tmp2/second.yaml': 'key2: two', '/tmp/tmp2/third.yaml': 'key3: three\nkey4: four' }): conf = "key: !include_dir_merge_named /tmp" with io.StringIO(conf) as file: assert '.ignore' in mock_walk.return_value[0][1], \ "Expecting .ignore in here" doc = yaml.yaml.safe_load(file) assert 'tmp2' in mock_walk.return_value[0][1] assert '.ignore' not in mock_walk.return_value[0][1] assert doc["key"] == { "key1": "one", "key2": "two", "key3": "three", "key4": "four" }
def test_reading_broken_yaml_config(self): """Test when known devices contains invalid data.""" files = {'empty.yaml': '', 'nodict.yaml': '100', 'badkey.yaml': '@:\n name: Device', 'noname.yaml': 'my_device:\n', 'allok.yaml': 'My Device:\n name: Device', 'oneok.yaml': ('My Device!:\n name: Device\n' 'bad_device:\n nme: Device')} args = {'hass': self.hass, 'consider_home': timedelta(seconds=60)} with patch_yaml_files(files): assert device_tracker.load_config('empty.yaml', **args) == [] assert device_tracker.load_config('nodict.yaml', **args) == [] assert device_tracker.load_config('noname.yaml', **args) == [] assert device_tracker.load_config('badkey.yaml', **args) == [] res = device_tracker.load_config('allok.yaml', **args) assert len(res) == 1 assert res[0].name == 'Device' assert res[0].dev_id == 'my_device' res = device_tracker.load_config('oneok.yaml', **args) assert len(res) == 1 assert res[0].name == 'Device' assert res[0].dev_id == 'my_device'
def test_component_platform_not_found(self, mock_get_loop): """Test errors if component or platform not found.""" files = { 'badcomponent.yaml': BASE_CONFIG + 'beer:', 'badplatform.yaml': BASE_CONFIG + 'light:\n platform: beer', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('badcomponent.yaml')) change_yaml_files(res) self.assertDictEqual({}, res['components']) self.assertDictEqual({check_config.ERROR_STR: ['Component not found: beer']}, res['except']) self.assertDictEqual({}, res['secret_cache']) self.assertDictEqual({}, res['secrets']) self.assertListEqual(['.../badcomponent.yaml'], res['yaml_files']) res = check_config.check(get_test_config_dir('badplatform.yaml')) change_yaml_files(res) self.assertDictEqual({'light': []}, res['components']) self.assertDictEqual({check_config.ERROR_STR: ['Platform not found: light.beer']}, res['except']) self.assertDictEqual({}, res['secret_cache']) self.assertDictEqual({}, res['secrets']) self.assertListEqual(['.../badplatform.yaml'], res['yaml_files'])
def test_include_yaml(self): """Test include yaml.""" with patch_yaml_files({"test.yaml": "value"}): conf = "key: !include test.yaml" with io.StringIO(conf) as file: doc = yaml.yaml.safe_load(file) assert doc["key"] == "value"
def test_async_added_to_hass(hass): """Test restoring state.""" attr = { device_tracker.ATTR_LONGITUDE: 18, device_tracker.ATTR_LATITUDE: -33, device_tracker.ATTR_LATITUDE: -33, device_tracker.ATTR_SOURCE_TYPE: 'gps', device_tracker.ATTR_GPS_ACCURACY: 2, device_tracker.ATTR_BATTERY: 100 } mock_restore_cache(hass, [State('device_tracker.jk', 'home', attr)]) path = hass.config.path(device_tracker.YAML_DEVICES) files = { path: 'jk:\n name: JK Phone\n track: True', } with patch_yaml_files(files): yield from device_tracker.async_setup(hass, {}) state = hass.states.get('device_tracker.jk') assert state assert state.state == 'home' for key, val in attr.items(): atr = state.attributes.get(key) assert atr == val, "{}={} expected: {}".format(key, atr, val)
def test_component_platform_not_found(self): """Test errors if component or platform not found.""" # Make sure they don't exist set_component('beer', None) set_component('light.beer', None) files = { 'badcomponent.yaml': BASE_CONFIG + 'beer:', 'badplatform.yaml': BASE_CONFIG + 'light:\n platform: beer', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('badcomponent.yaml')) change_yaml_files(res) self.assertDictEqual({}, res['components']) self.assertDictEqual({ check_config.ERROR_STR: [ 'Component not found: beer', 'Setup failed for beer: Component not found.'] }, res['except']) self.assertDictEqual({}, res['secret_cache']) self.assertDictEqual({}, res['secrets']) self.assertListEqual(['.../badcomponent.yaml'], res['yaml_files']) res = check_config.check(get_test_config_dir('badplatform.yaml')) change_yaml_files(res) assert res['components'] == {'light': [], 'group': None} assert res['except'] == { check_config.ERROR_STR: [ 'Platform not found: light.beer', ]} self.assertDictEqual({}, res['secret_cache']) self.assertDictEqual({}, res['secrets']) self.assertListEqual(['.../badplatform.yaml'], res['yaml_files'])
def test_secrets(self, mock_get_loop): """Test secrets config checking method.""" files = { get_test_config_dir('secret.yaml'): ( BASE_CONFIG + 'http:\n' ' api_password: !secret http_pw'), 'secrets.yaml': ('logger: debug\n' 'http_pw: abc123'), } self.maxDiff = None with patch_yaml_files(files): config_path = get_test_config_dir('secret.yaml') secrets_path = get_test_config_dir('secrets.yaml') res = check_config.check(config_path) change_yaml_files(res) # convert secrets OrderedDict to dict for assertequal for key, val in res['secret_cache'].items(): res['secret_cache'][key] = dict(val) self.assertDictEqual({ 'components': {'http': {'api_password': '******', 'server_port': 8123}}, 'except': {}, 'secret_cache': {secrets_path: {'http_pw': 'abc123'}}, 'secrets': {'http_pw': 'abc123'}, 'yaml_files': ['.../secret.yaml', '.../secrets.yaml'] }, res)
def test_reading_broken_yaml_config(self): # pylint: disable=no-self-use """Test when known devices contains invalid data.""" files = { "empty.yaml": "", "nodict.yaml": "100", "badkey.yaml": "@:\n name: Device", "noname.yaml": "my_device:\n", "allok.yaml": "My Device:\n name: Device", "oneok.yaml": ("My Device!:\n name: Device\n" "bad_device:\n nme: Device"), } args = {"hass": self.hass, "consider_home": timedelta(seconds=60)} with patch_yaml_files(files): assert device_tracker.load_config("empty.yaml", **args) == [] assert device_tracker.load_config("nodict.yaml", **args) == [] assert device_tracker.load_config("noname.yaml", **args) == [] assert device_tracker.load_config("badkey.yaml", **args) == [] res = device_tracker.load_config("allok.yaml", **args) assert len(res) == 1 assert res[0].name == "Device" assert res[0].dev_id == "my_device" res = device_tracker.load_config("oneok.yaml", **args) assert len(res) == 1 assert res[0].name == "Device" assert res[0].dev_id == "my_device"
def test_config_component_platform_fail_validation(self): """Test errors if component & platform not found.""" files = { 'component.yaml': BASE_CONFIG + 'http:\n password: err123', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('component.yaml')) change_yaml_files(res) self.assertDictEqual({}, res['components']) res['except'].pop(check_config.ERROR_STR) self.assertDictEqual( {'http': {'password': '******'}}, res['except'] ) self.assertDictEqual({}, res['secret_cache']) self.assertDictEqual({}, res['secrets']) self.assertListEqual(['.../component.yaml'], res['yaml_files']) files = { 'platform.yaml': (BASE_CONFIG + 'mqtt:\n\n' 'light:\n platform: mqtt_json'), } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('platform.yaml')) change_yaml_files(res) self.assertDictEqual( {'mqtt': { 'keepalive': 60, 'port': 1883, 'protocol': '3.1.1', 'discovery': False, 'discovery_prefix': 'homeassistant', 'tls_version': 'auto', }, 'light': [], 'group': None}, res['components'] ) self.assertDictEqual( {'light.mqtt_json': {'platform': 'mqtt_json'}}, res['except'] ) self.assertDictEqual({}, res['secret_cache']) self.assertDictEqual({}, res['secrets']) self.assertListEqual(['.../platform.yaml'], res['yaml_files'])
def test_bad_core_config(self, isfile_patch): """Test a bad core config setup.""" files = { YAML_CONFIG_FILE: BAD_CORE_CONFIG, } with patch_yaml_files(files): res = check_config.check(get_test_config_dir()) assert res['except'].keys() == {'homeassistant'} assert res['except']['homeassistant'][1] == {'unit_system': 'bad'}
def test_include_dir_merge_list(self, mock_walk): """Test include dir merge list yaml.""" mock_walk.return_value = [["/tmp", [], ["first.yaml", "second.yaml"]]] with patch_yaml_files({"/tmp/first.yaml": "- one", "/tmp/second.yaml": "- two\n- three"}): conf = "key: !include_dir_merge_list /tmp" with io.StringIO(conf) as file: doc = yaml.yaml.safe_load(file) assert sorted(doc["key"]) == sorted(["one", "two", "three"])
def test_include_dir_list(self, mock_walk): """Test include dir list yaml.""" mock_walk.return_value = [["/tmp", [], ["one.yaml", "two.yaml"]]] with patch_yaml_files({"/tmp/one.yaml": "one", "/tmp/two.yaml": "two"}): conf = "key: !include_dir_list /tmp" with io.StringIO(conf) as file: doc = yaml.yaml.safe_load(file) assert sorted(doc["key"]) == sorted(["one", "two"])
def test_include_dir_named(self, mock_walk): """Test include dir named yaml.""" mock_walk.return_value = [["/tmp", [], ["first.yaml", "second.yaml"]]] with patch_yaml_files({"/tmp/first.yaml": "one", "/tmp/second.yaml": "two"}): conf = "key: !include_dir_named /tmp" correct = {"first": "one", "second": "two"} with io.StringIO(conf) as file: doc = yaml.yaml.safe_load(file) assert doc["key"] == correct
def test_reload_core_with_wrong_conf(self, mock_process, mock_error): """Test reload core conf service.""" files = { config.YAML_CONFIG_FILE: yaml.dump(['invalid', 'config']) } with patch_yaml_files(files, True): comps.reload_core_config(self.hass) self.hass.block_till_done() assert mock_error.called assert mock_process.called is False
def test_include_dir_merge_named(self, mock_walk): """Test include dir merge named yaml.""" mock_walk.return_value = [["/tmp", [], ["first.yaml", "second.yaml"]]] files = {"/tmp/first.yaml": "key1: one", "/tmp/second.yaml": "key2: two\nkey3: three"} with patch_yaml_files(files): conf = "key: !include_dir_merge_named /tmp" with io.StringIO(conf) as file: doc = yaml.yaml.safe_load(file) assert doc["key"] == {"key1": "one", "key2": "two", "key3": "three"}
def test_from_config_file(hass): """Test with configuration file.""" components = set(['browser', 'conversation', 'script']) files = { 'config.yaml': ''.join('{}:\n'.format(comp) for comp in components) } with patch_yaml_files(files, True): yield from bootstrap.async_from_config_file('config.yaml') assert components == hass.config.components
def test_reading_broken_yaml_config(self): # pylint: disable=no-self-use """Test when known devices contains invalid data.""" files = {'empty.yaml': '', 'bad.yaml': '100', 'ok.yaml': 'my_device:\n name: Device'} with patch_yaml_files(files): # File is empty assert device_tracker.load_config('empty.yaml', None, False) == [] # File contains a non-dict format assert device_tracker.load_config('bad.yaml', None, False) == [] # A file that works fine assert len(device_tracker.load_config('ok.yaml', None, False)) == 1
def test_config_platform_valid(self, isfile_patch): """Test a valid platform setup.""" files = { YAML_CONFIG_FILE: BASE_CONFIG + 'light:\n platform: demo', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir()) assert res['components'].keys() == {'homeassistant', 'light'} assert res['components']['light'] == [{'platform': 'demo'}] assert res['except'] == {} assert res['secret_cache'] == {} assert res['secrets'] == {} assert len(res['yaml_files']) == 1
def test_include_dir_list(self, mock_walk): """Test include dir list yaml.""" mock_walk.return_value = [ ['/tmp', [], ['one.yaml', 'two.yaml']], ] with patch_yaml_files({ '/tmp/one.yaml': 'one', '/tmp/two.yaml': 'two', }): conf = "key: !include_dir_list /tmp" with io.StringIO(conf) as file: doc = yaml.yaml.safe_load(file) assert sorted(doc["key"]) == sorted(["one", "two"])
def test_bootstrap_error(self): """Test a valid platform setup.""" files = { YAML_CONFIG_FILE: BASE_CONFIG + 'automation: !include no.yaml', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir(YAML_CONFIG_FILE)) err = res['except'].pop(check_config.ERROR_STR) assert len(err) == 1 assert res['except'] == {} assert res['components'] == {} # No components, load failed assert res['secret_cache'] == {} assert res['secrets'] == {} assert res['yaml_files'] == {}
def test_config_component_platform_fail_validation(self, isfile_patch): """Test errors if component & platform not found.""" files = { YAML_CONFIG_FILE: BASE_CONFIG + 'http:\n password: err123', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir()) assert res['components'].keys() == {'homeassistant'} assert res['except'].keys() == {'http'} assert res['except']['http'][1] == {'http': {'password': '******'}} assert res['secret_cache'] == {} assert res['secrets'] == {} assert len(res['yaml_files']) == 1 files = { YAML_CONFIG_FILE: (BASE_CONFIG + 'mqtt:\n\n' 'light:\n platform: mqtt_json'), } with patch_yaml_files(files): res = check_config.check(get_test_config_dir()) assert res['components'].keys() == { 'homeassistant', 'light', 'mqtt'} assert res['components']['light'] == [] assert res['components']['mqtt'] == { 'keepalive': 60, 'port': 1883, 'protocol': '3.1.1', 'discovery': False, 'discovery_prefix': 'homeassistant', 'tls_version': 'auto', } assert res['except'].keys() == {'light.mqtt_json'} assert res['except']['light.mqtt_json'][1] == { 'platform': 'mqtt_json'} assert res['secret_cache'] == {} assert res['secrets'] == {} assert len(res['yaml_files']) == 1
def test_include_dir_named(self, mock_walk): """Test include dir named yaml.""" mock_walk.return_value = [ ['/tmp', [], ['first.yaml', 'second.yaml']] ] with patch_yaml_files({ '/tmp/first.yaml': 'one', '/tmp/second.yaml': 'two' }): conf = "key: !include_dir_named /tmp" correct = {'first': 'one', 'second': 'two'} with io.StringIO(conf) as file: doc = yaml.yaml.safe_load(file) assert doc["key"] == correct
def test_config_platform_valid(self, mock_get_loop): """Test a valid platform setup.""" files = { 'light.yaml': BASE_CONFIG + 'light:\n platform: demo', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('light.yaml')) change_yaml_files(res) self.assertDictEqual({ 'components': {'light': [{'platform': 'demo'}]}, 'except': {}, 'secret_cache': {}, 'secrets': {}, 'yaml_files': ['.../light.yaml'] }, res)
def test_include_dir_list_recursive(self, mock_walk): """Test include dir recursive list yaml.""" mock_walk.return_value = [ ["/tmp", ["tmp2", ".ignore", "ignore"], ["zero.yaml"]], ["/tmp/tmp2", [], ["one.yaml", "two.yaml"]], ["/tmp/ignore", [], [".ignore.yaml"]], ] with patch_yaml_files({"/tmp/zero.yaml": "zero", "/tmp/tmp2/one.yaml": "one", "/tmp/tmp2/two.yaml": "two"}): conf = "key: !include_dir_list /tmp" with io.StringIO(conf) as file: assert ".ignore" in mock_walk.return_value[0][1], "Expecting .ignore in here" doc = yaml.yaml.safe_load(file) assert "tmp2" in mock_walk.return_value[0][1] assert ".ignore" not in mock_walk.return_value[0][1] assert sorted(doc["key"]) == sorted(["zero", "one", "two"])
def test_bootstrap_error(self): \ # pylint: disable=no-self-use,invalid-name """Test a valid platform setup.""" files = { 'badbootstrap.yaml': BASE_CONFIG + 'automation: !include no.yaml', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('badbootstrap.yaml')) change_yaml_files(res) err = res['except'].pop(check_config.ERROR_STR) assert len(err) == 1 assert res['except'] == {} assert res['components'] == {} assert res['secret_cache'] == {} assert res['secrets'] == {}
def test_from_config_file(self, mock_detect): """Test with configuration file.""" components = ['browser', 'conversation', 'script'] files = { 'config.yaml': ''.join( '{}:\n'.format(comp) for comp in components ) } with mock.patch('os.path.isfile', mock.Mock(return_value=True)), \ mock.patch('os.access', mock.Mock(return_value=True)), \ patch_yaml_files(files, True): self.hass = bootstrap.from_config_file('config.yaml') components.append('group') assert sorted(components) == sorted(self.hass.config.components)
def test_include_dir_merge_named(mock_walk, try_both_loaders): """Test include dir merge named yaml.""" mock_walk.return_value = [["/test", [], ["first.yaml", "second.yaml"]]] files = { "/test/first.yaml": "key1: one", "/test/second.yaml": "key2: two\nkey3: three", } with patch_yaml_files(files): conf = "key: !include_dir_merge_named /test" with io.StringIO(conf) as file: doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader) assert doc["key"] == { "key1": "one", "key2": "two", "key3": "three" }
def test_from_config_file(self, mock_upgrade, mock_detect, mock_signal): """Test with configuration file.""" components = set(['browser', 'conversation', 'script']) files = { 'config.yaml': ''.join( '{}:\n'.format(comp) for comp in components ) } with mock.patch('os.path.isfile', mock.Mock(return_value=True)), \ mock.patch('os.access', mock.Mock(return_value=True)), \ mock.patch('homeassistant.bootstrap.async_enable_logging', mock.Mock(return_value=True)), \ patch_yaml_files(files, True): self.hass = bootstrap.from_config_file('config.yaml') components.add('group') assert components == self.hass.config.components
async def test_async_hass_config_yaml_merge(merge_log_err, hass): """Test merge during async config reload.""" config = { config_util.CONF_CORE: { config_util.CONF_PACKAGES: {"pack_dict": {"input_boolean": {"ib1": None}}} }, "input_boolean": {"ib2": None}, "light": {"platform": "test"}, } files = {config_util.YAML_CONFIG_FILE: yaml.dump(config)} with patch_yaml_files(files, True): conf = await config_util.async_hass_config_yaml(hass) assert merge_log_err.call_count == 0 assert conf[config_util.CONF_CORE].get(config_util.CONF_PACKAGES) is not None assert len(conf) == 3 assert len(conf["input_boolean"]) == 2 assert len(conf["light"]) == 1
async def test_package_invalid(hass, loop): """Test a valid platform setup.""" files = { YAML_CONFIG_FILE: BASE_CONFIG + ( ' packages:\n' ' p1:\n' ' group: ["a"]'), } with patch('os.path.isfile', return_value=True), patch_yaml_files(files): res = await async_check_ha_config_file(hass) log_ha_config(res) assert res.errors[0].domain == 'homeassistant.packages.p1.group' assert res.errors[0].config == {'group': ['a']} # Only 1 error expected res.errors.pop(0) assert not res.errors assert res.keys() == {'homeassistant'}
def test_secrets(self): """Test secrets config checking method.""" files = { get_test_config_dir('secret.yaml'): (BASE_CONFIG + 'http:\n' ' api_password: !secret http_pw'), 'secrets.yaml': ('logger: debug\n' 'http_pw: abc123'), } self.maxDiff = None with patch_yaml_files(files): config_path = get_test_config_dir('secret.yaml') secrets_path = get_test_config_dir('secrets.yaml') res = check_config.check(config_path) change_yaml_files(res) # convert secrets OrderedDict to dict for assertequal for key, val in res['secret_cache'].items(): res['secret_cache'][key] = dict(val) self.assertDictEqual( { 'components': { 'http': { 'api_password': '******', 'server_port': 8123, 'use_x_forwarded_for': False } }, 'except': {}, 'secret_cache': { secrets_path: { 'http_pw': 'abc123' } }, 'secrets': { 'http_pw': 'abc123' }, 'yaml_files': ['.../secret.yaml', '.../secrets.yaml'] }, res)
def test_package_invalid(isfile_patch, loop): """Test an invalid package.""" files = { YAML_CONFIG_FILE: BASE_CONFIG + (" packages:\n p1:\n" ' group: ["a"]') } with patch_yaml_files(files): res = check_config.check(get_test_config_dir()) assert res["except"].keys() == {"homeassistant.packages.p1.group"} assert res["except"]["homeassistant.packages.p1.group"][1] == { "group": ["a"] } assert len(res["except"]) == 1 assert res["components"].keys() == {"homeassistant"} assert len(res["components"]) == 1 assert res["secret_cache"] == {} assert res["secrets"] == {} assert len(res["yaml_files"]) == 1
def test_package_invalid(self): \ # pylint: disable=no-self-use,invalid-name """Test a valid platform setup.""" files = { 'bad.yaml': BASE_CONFIG + (' packages:\n' ' p1:\n' ' group: ["a"]'), } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('bad.yaml')) change_yaml_files(res) err = res['except'].pop('homeassistant.packages.p1') assert res['except'] == {} assert err == {'group': ['a']} assert res['yaml_files'] == ['.../bad.yaml'] assert res['components'] == {} assert res['secret_cache'] == {} assert res['secrets'] == {}
async def test_async_hass_config_yaml_merge(merge_log_err, hass): """Test merge during async config reload.""" config = { config_util.CONF_CORE: {config_util.CONF_PACKAGES: { 'pack_dict': { 'input_boolean': {'ib1': None}}}}, 'input_boolean': {'ib2': None}, 'light': {'platform': 'test'} } files = {config_util.YAML_CONFIG_FILE: yaml.dump(config)} with patch_yaml_files(files, True): conf = await config_util.async_hass_config_yaml(hass) assert merge_log_err.call_count == 0 assert conf[config_util.CONF_CORE].get(config_util.CONF_PACKAGES) \ is not None assert len(conf) == 3 assert len(conf['input_boolean']) == 2 assert len(conf['light']) == 1
def test_config_platform_valid(self): """Test a valid platform setup.""" files = { 'light.yaml': BASE_CONFIG + 'light:\n platform: demo', } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('light.yaml')) change_yaml_files(res) self.assertDictEqual( { 'components': { 'light': [{ 'platform': 'demo' }] }, 'except': {}, 'secret_cache': {}, 'secrets': {}, 'yaml_files': ['.../light.yaml'] }, res)
def test_include_dir_list_recursive(self, mock_walk): """Test include dir recursive list yaml.""" mock_walk.return_value = [[ '/tmp', ['tmp2', '.ignore', 'ignore'], ['zero.yaml'] ], ['/tmp/tmp2', [], ['one.yaml', 'two.yaml']], ['/tmp/ignore', [], ['.ignore.yaml']]] with patch_yaml_files({ '/tmp/zero.yaml': 'zero', '/tmp/tmp2/one.yaml': 'one', '/tmp/tmp2/two.yaml': 'two' }): conf = "key: !include_dir_list /tmp" with io.StringIO(conf) as file: assert '.ignore' in mock_walk.return_value[0][1], \ "Expecting .ignore in here" doc = yaml.yaml.safe_load(file) assert 'tmp2' in mock_walk.return_value[0][1] assert '.ignore' not in mock_walk.return_value[0][1] assert sorted(doc["key"]) == sorted(["zero", "one", "two"])
async def test_config_platform_raise(hass): """Test bad config validation platform.""" mock_platform( hass, "bla.config", Mock(async_validate_config=Mock(side_effect=Exception("Broken"))), ) files = { YAML_CONFIG_FILE: BASE_CONFIG + """ bla: value: 1 """, } with patch("os.path.isfile", return_value=True), patch_yaml_files(files): res = await async_check_ha_config_file(hass) assert len(res.errors) == 1 err = res.errors[0] assert err.domain == "bla" assert err.message == "Unexpected error calling config validator: Broken" assert err.config == {"value": 1}
def test_package_invalid(self, isfile_patch): """Test a valid platform setup.""" files = { YAML_CONFIG_FILE: BASE_CONFIG + (' packages:\n' ' p1:\n' ' group: ["a"]'), } with patch_yaml_files(files): res = check_config.check(get_test_config_dir()) assert res['except'].keys() == {'homeassistant.packages.p1.group'} assert res['except']['homeassistant.packages.p1.group'][1] == \ {'group': ['a']} assert len(res['except']) == 1 assert res['components'].keys() == {'homeassistant'} assert len(res['components']) == 1 assert res['secret_cache'] == {} assert res['secrets'] == {} assert len(res['yaml_files']) == 1
async def test_component_platform_not_found_2(hass, loop): """Test errors if component or platform not found.""" # Make sure they don't exist files = { YAML_CONFIG_FILE: BASE_CONFIG + 'light:\n platform: beer', } with patch('os.path.isfile', return_value=True), patch_yaml_files(files): res = await async_check_ha_config_file(hass) log_ha_config(res) assert res.keys() == {'homeassistant', 'light'} assert res['light'] == [] assert res.errors[0] == CheckConfigError( 'Integration beer not found when trying to verify its ' 'light platform.', None, None) # Only 1 error expected res.errors.pop(0) assert not res.errors
def test_reload_core_conf(self): """Test reload core conf service.""" ent = entity.Entity() ent.entity_id = 'test.entity' ent.hass = self.hass ent.schedule_update_ha_state() self.hass.block_till_done() state = self.hass.states.get('test.entity') assert state is not None assert state.state == 'unknown' assert state.attributes == {} files = { config.YAML_CONFIG_FILE: yaml.dump({ ha.DOMAIN: { 'latitude': 10, 'longitude': 20, 'customize': { 'test.Entity': { 'hello': 'world' } } } }) } with patch_yaml_files(files, True): comps.reload_core_config(self.hass) self.hass.block_till_done() assert self.hass.config.latitude == 10 assert self.hass.config.longitude == 20 ent.schedule_update_ha_state() self.hass.block_till_done() state = self.hass.states.get('test.entity') assert state is not None assert state.state == 'unknown' assert state.attributes.get('hello') == 'world'
def test_reload_core_conf(self): """Test reload core conf service.""" ent = entity.Entity() ent.entity_id = "test.entity" ent.hass = self.hass ent.schedule_update_ha_state() self.hass.block_till_done() state = self.hass.states.get("test.entity") assert state is not None assert state.state == "unknown" assert state.attributes == {} files = { config.YAML_CONFIG_FILE: yaml.dump({ ha.DOMAIN: { "latitude": 10, "longitude": 20, "customize": { "test.Entity": { "hello": "world" } }, } }) } with patch_yaml_files(files, True): reload_core_config(self.hass) self.hass.block_till_done() assert self.hass.config.latitude == 10 assert self.hass.config.longitude == 20 ent.schedule_update_ha_state() self.hass.block_till_done() state = self.hass.states.get("test.entity") assert state is not None assert state.state == "unknown" assert state.attributes.get("hello") == "world"
async def test_component_requirement_not_found(hass): """Test errors if component with a requirement not found not found.""" # Make sure they don't exist files = {YAML_CONFIG_FILE: BASE_CONFIG + "test_custom_component:"} with patch( "homeassistant.helpers.check_config.async_get_integration_with_requirements", side_effect=RequirementsNotFound("test_custom_component", ["any"]), ), patch("os.path.isfile", return_value=True), patch_yaml_files(files): res = await async_check_ha_config_file(hass) log_ha_config(res) assert res.keys() == {"homeassistant"} assert res.errors[0] == CheckConfigError( "Integration error: test_custom_component - Requirements for test_custom_component not found: ['any'].", None, None, ) # Only 1 error expected res.errors.pop(0) assert not res.errors
def test_include_dir_named_recursive(self, mock_walk): """Test include dir named yaml.""" mock_walk.return_value = [[ '/tmp', ['tmp2', '.ignore', 'ignore'], ['first.yaml'] ], ['/tmp/tmp2', [], ['second.yaml', 'third.yaml']], ['/tmp/ignore', [], ['.ignore.yaml']]] with patch_yaml_files({ '/tmp/first.yaml': 'one', '/tmp/tmp2/second.yaml': 'two', '/tmp/tmp2/third.yaml': 'three' }): conf = "key: !include_dir_named /tmp" correct = {'first': 'one', 'second': 'two', 'third': 'three'} with io.StringIO(conf) as file: assert '.ignore' in mock_walk.return_value[0][1], \ "Expecting .ignore in here" doc = yaml.yaml.safe_load(file) assert 'tmp2' in mock_walk.return_value[0][1] assert '.ignore' not in mock_walk.return_value[0][1] assert doc["key"] == correct
def test_include_dir_merge_list_recursive(self, mock_walk): """Test include dir merge list yaml.""" mock_walk.return_value = [[ '/tmp', ['tmp2', '.ignore', 'ignore'], ['first.yaml'] ], ['/tmp/tmp2', [], ['second.yaml', 'third.yaml']], ['/tmp/ignore', [], ['.ignore.yaml']]] with patch_yaml_files({ '/tmp/first.yaml': '- one', '/tmp/tmp2/second.yaml': '- two', '/tmp/tmp2/third.yaml': '- three\n- four' }): conf = "key: !include_dir_merge_list /tmp" with io.StringIO(conf) as file: assert '.ignore' in mock_walk.return_value[0][1], \ "Expecting .ignore in here" doc = yaml.yaml.safe_load(file) assert 'tmp2' in mock_walk.return_value[0][1] assert '.ignore' not in mock_walk.return_value[0][1] assert sorted(doc["key"]) == sorted( ["one", "two", "three", "four"])
def test_secrets(self): """Test secrets config checking method.""" files = { get_test_config_dir('secret.yaml'): ( BASE_CONFIG + 'http:\n' ' api_password: !secret http_pw'), 'secrets.yaml': ('logger: debug\n' 'http_pw: abc123'), } self.maxDiff = None with patch_yaml_files(files): config_path = get_test_config_dir('secret.yaml') secrets_path = get_test_config_dir('secrets.yaml') res = check_config.check(config_path) change_yaml_files(res) # convert secrets OrderedDict to dict for assertequal for key, val in res['secret_cache'].items(): res['secret_cache'][key] = dict(val) self.assertDictEqual({ 'components': {'http': {'api_password': '******', 'cors_allowed_origins': [], 'development': '0', 'ip_ban_enabled': True, 'login_attempts_threshold': -1, 'server_host': '0.0.0.0', 'server_port': 8123, 'ssl_certificate': None, 'ssl_key': None, 'trusted_networks': [], 'use_x_forwarded_for': False}}, 'except': {}, 'secret_cache': {secrets_path: {'http_pw': 'abc123'}}, 'secrets': {'http_pw': 'abc123'}, 'yaml_files': ['.../secret.yaml', '.../secrets.yaml'] }, res)
def test_include_dir_list_recursive(mock_walk): """Test include dir recursive list yaml.""" mock_walk.return_value = [ ["/tmp", ["tmp2", ".ignore", "ignore"], ["zero.yaml"]], ["/tmp/tmp2", [], ["one.yaml", "two.yaml"]], ["/tmp/ignore", [], [".ignore.yaml"]], ] with patch_yaml_files({ "/tmp/zero.yaml": "zero", "/tmp/tmp2/one.yaml": "one", "/tmp/tmp2/two.yaml": "two", }): conf = "key: !include_dir_list /tmp" with io.StringIO(conf) as file: assert ( ".ignore" in mock_walk.return_value[0][1]), "Expecting .ignore in here" doc = yaml_loader.yaml.safe_load(file) assert "tmp2" in mock_walk.return_value[0][1] assert ".ignore" not in mock_walk.return_value[0][1] assert sorted(doc["key"]) == sorted(["zero", "one", "two"])
def test_include_dir_named_recursive(mock_walk): """Test include dir named yaml.""" mock_walk.return_value = [ ["/tmp", ["tmp2", ".ignore", "ignore"], ["first.yaml"]], ["/tmp/tmp2", [], ["second.yaml", "third.yaml"]], ["/tmp/ignore", [], [".ignore.yaml"]], ] with patch_yaml_files({ "/tmp/first.yaml": "one", "/tmp/tmp2/second.yaml": "two", "/tmp/tmp2/third.yaml": "three", }): conf = "key: !include_dir_named /tmp" correct = {"first": "one", "second": "two", "third": "three"} with io.StringIO(conf) as file: assert ( ".ignore" in mock_walk.return_value[0][1]), "Expecting .ignore in here" doc = yaml_loader.yaml.safe_load(file) assert "tmp2" in mock_walk.return_value[0][1] assert ".ignore" not in mock_walk.return_value[0][1] assert doc["key"] == correct
def test_include_dir_merge_list_recursive(mock_walk): """Test include dir merge list yaml.""" mock_walk.return_value = [ ["/tmp", ["tmp2", ".ignore", "ignore"], ["first.yaml"]], ["/tmp/tmp2", [], ["second.yaml", "third.yaml"]], ["/tmp/ignore", [], [".ignore.yaml"]], ] with patch_yaml_files({ "/tmp/first.yaml": "- one", "/tmp/tmp2/second.yaml": "- two", "/tmp/tmp2/third.yaml": "- three\n- four", }): conf = "key: !include_dir_merge_list /tmp" with io.StringIO(conf) as file: assert ( ".ignore" in mock_walk.return_value[0][1]), "Expecting .ignore in here" doc = yaml_loader.yaml.safe_load(file) assert "tmp2" in mock_walk.return_value[0][1] assert ".ignore" not in mock_walk.return_value[0][1] assert sorted(doc["key"]) == sorted( ["one", "two", "three", "four"])
def test_secrets(isfile_patch, loop): """Test secrets config checking method.""" secrets_path = get_test_config_dir("secrets.yaml") files = { get_test_config_dir(YAML_CONFIG_FILE): BASE_CONFIG + ("http:\n" " cors_allowed_origins: !secret http_pw"), secrets_path: ("logger: debug\n" "http_pw: http://google.com"), } with patch_yaml_files(files): res = check_config.check(get_test_config_dir(), True) assert res["except"] == {} assert res["components"].keys() == {"homeassistant", "http"} assert res["components"]["http"] == { "cors_allowed_origins": ["http://google.com"], "ip_ban_enabled": True, "login_attempts_threshold": -1, "server_host": "0.0.0.0", "server_port": 8123, "ssl_profile": "modern", } assert res["secret_cache"] == { secrets_path: { "http_pw": "http://google.com" } } assert res["secrets"] == {"http_pw": "http://google.com"} assert normalize_yaml_files(res) == [ ".../configuration.yaml", ".../secrets.yaml", ]
async def test_async_added_to_hass(hass): """Test restoring state.""" attr = { ATTR_LONGITUDE: 18, ATTR_LATITUDE: -33, const.ATTR_SOURCE_TYPE: "gps", ATTR_GPS_ACCURACY: 2, const.ATTR_BATTERY: 100, } mock_restore_cache(hass, [State("device_tracker.jk", "home", attr)]) path = hass.config.path(legacy.YAML_DEVICES) files = {path: "jk:\n name: JK Phone\n track: True"} with patch_yaml_files(files): assert await async_setup_component(hass, device_tracker.DOMAIN, {}) state = hass.states.get("device_tracker.jk") assert state assert state.state == "home" for key, val in attr.items(): atr = state.attributes.get(key) assert atr == val, f"{key}={atr} expected: {val}"
async def test_reading_broken_yaml_config(hass): """Test when known devices contains invalid data.""" files = { 'empty.yaml': '', 'nodict.yaml': '100', 'badkey.yaml': '@:\n name: Device', 'noname.yaml': 'my_device:\n', 'allok.yaml': 'My Device:\n name: Device', 'oneok.yaml': ('My Device!:\n name: Device\n' 'bad_device:\n nme: Device') } args = {'hass': hass, 'consider_home': timedelta(seconds=60)} with patch_yaml_files(files): assert await device_tracker.async_load_config('empty.yaml', **args) == [] assert await device_tracker.async_load_config('nodict.yaml', **args) == [] assert await device_tracker.async_load_config('noname.yaml', **args) == [] assert await device_tracker.async_load_config('badkey.yaml', **args) == [] res = await device_tracker.async_load_config('allok.yaml', **args) assert len(res) == 1 assert res[0].name == 'Device' assert res[0].dev_id == 'my_device' res = await device_tracker.async_load_config('oneok.yaml', **args) assert len(res) == 1 assert res[0].name == 'Device' assert res[0].dev_id == 'my_device'
def test_no_key(self): """Test item without an key.""" files = {YAML_CONFIG_FILE: 'a: a\nnokeyhere'} with self.assertRaises(HomeAssistantError), \ patch_yaml_files(files): yaml.load_yaml(YAML_CONFIG_FILE)
def test_unhashable_key(self): """Test an unhasable key.""" files = {YAML_CONFIG_FILE: 'message:\n {{ states.state }}'} with self.assertRaises(HomeAssistantError), \ patch_yaml_files(files): load_yaml_config_file(YAML_CONFIG_FILE)
def load_yaml(fname, string): """Write a string to file and return the parsed yaml.""" FILES[fname] = string with patch_yaml_files(FILES): return load_yaml_config_file(fname)
def test_duplicate_key(self): """Test duplicate dict keys.""" files = {YAML_CONFIG_FILE: 'key: thing1\nkey: thing2'} with self.assertRaises(HomeAssistantError): with patch_yaml_files(files): load_yaml_config_file(YAML_CONFIG_FILE)
def test_duplicate_key(caplog): """Test duplicate dict keys.""" files = {YAML_CONFIG_FILE: 'key: thing1\nkey: thing2'} with patch_yaml_files(files): load_yaml_config_file(YAML_CONFIG_FILE) assert 'contains duplicate key' in caplog.text