Esempio n. 1
0
async def test_detect_config_fail(hass, client):
    """Test detect config."""
    with patch('homeassistant.util.location.async_detect_location_info',
               return_value=mock_coro(
                   location.LocationInfo(
                       ip=None,
                       country_code=None,
                       country_name=None,
                       region_code=None,
                       region_name=None,
                       city=None,
                       zip_code=None,
                       latitude=None,
                       longitude=None,
                       use_metric=True,
                       time_zone='Europe/Amsterdam',
                   ))):
        await client.send_json({
            'id': 1,
            'type': 'config/core/detect',
        })

        msg = await client.receive_json()

    assert msg['success'] is True
    assert msg['result'] == {
        'unit_system': 'metric',
        'time_zone': 'Europe/Amsterdam',
    }
Esempio n. 2
0
async def test_create_default_config_detect_location(hass):
    """Test that detect location sets the correct config keys."""
    with mock.patch('homeassistant.util.location.async_detect_location_info',
                    return_value=mock_coro(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.async_get_elevation',
                   return_value=mock_coro(101)), \
            mock.patch('builtins.print') as mock_print:
        await config_util.async_ensure_config_exists(hass, CONFIG_DIR)

    config = config_util.load_yaml_config_file(YAML_PATH)

    assert DOMAIN in config

    ha_conf = config[DOMAIN]

    expected_values = {
        CONF_LATITUDE: 32.8594,
        CONF_LONGITUDE: -117.2073,
        CONF_ELEVATION: 101,
        CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
        CONF_NAME: 'Home',
        CONF_TIME_ZONE: 'America/Los_Angeles',
        CONF_CUSTOMIZE: OrderedDict(),
    }

    assert expected_values == ha_conf
    assert mock_print.called
Esempio n. 3
0
async def test_detect_config_fail(hass, client):
    """Test detect config."""
    with patch(
            "homeassistant.util.location.async_detect_location_info",
            return_value=location.LocationInfo(
                ip=None,
                country_code=None,
                region_code=None,
                region_name=None,
                city=None,
                zip_code=None,
                latitude=None,
                longitude=None,
                use_metric=True,
                time_zone="Europe/Amsterdam",
            ),
    ):
        await client.send_json({"id": 1, "type": "config/core/detect"})

        msg = await client.receive_json()

    assert msg["success"] is True
    assert msg["result"] == {
        "unit_system": "metric",
        "time_zone": "Europe/Amsterdam"
    }
Esempio n. 4
0
def mock_detect_location_info():
    """ Mock implementation of util.detect_location_info. """
    return location_util.LocationInfo(
        ip='1.1.1.1',
        country_code='US',
        country_name='United States',
        region_code='CA',
        region_name='California',
        city='San Diego',
        zip_code='92122',
        time_zone='America/Los_Angeles',
        latitude='2.0',
        longitude='1.0',
        use_fahrenheit=True,
    )
Esempio n. 5
0
    with pytest.raises(MultipleInvalid):
        await config_util.async_process_ha_core_config(hass, {
            'latitude': 39,
            'longitude': -1,
            'elevation': 500,
            'name': 'Huis',
            CONF_TEMPERATURE_UNIT: 'C',
            'time_zone': 'Europe/Madrid',
            'packages': {'empty_package': None},
        })


@asynctest.mock.patch(
    'homeassistant.util.location.async_detect_location_info',
    autospec=True, return_value=mock_coro(location_util.LocationInfo(
        '0.0.0.0', 'US', 'United States', 'CA',
        'California', 'San Diego', '92122',
        'America/Los_Angeles', 32.8594, -117.2073, True)))
@asynctest.mock.patch('homeassistant.util.location.async_get_elevation',
                      autospec=True, return_value=mock_coro(101))
async def test_discovering_configuration(mock_detect, mock_elevation, hass):
    """Test auto discovery for missing core configs."""
    hass.config.latitude = None
    hass.config.longitude = None
    hass.config.elevation = None
    hass.config.location_name = None
    hass.config.time_zone = None

    await config_util.async_process_ha_core_config(hass, {})

    assert hass.config.latitude == 32.8594
    assert hass.config.longitude == -117.2073
Esempio n. 6
0
    CONF_CODE: MOCK_CODE,
}
MOCK_DATA = {CONF_TOKEN: MOCK_CREDS, "devices": [MOCK_DEVICE]}
MOCK_UDP_PORT = int(987)
MOCK_TCP_PORT = int(997)

MOCK_AUTO = {"Config Mode": "Auto Discover"}
MOCK_MANUAL = {"Config Mode": "Manual Entry", CONF_IP_ADDRESS: MOCK_HOST}

MOCK_LOCATION = location.LocationInfo(
    "0.0.0.0",
    "US",
    "United States",
    "CA",
    "California",
    "San Diego",
    "92122",
    "America/Los_Angeles",
    32.8594,
    -117.2073,
    True,
)


async def test_full_flow_implementation(hass):
    """Test registering an implementation and flow works."""
    flow = ps4.PlayStation4FlowHandler()
    flow.hass = hass
    flow.location = MOCK_LOCATION
    manager = hass.config_entries
Esempio n. 7
0
class TestConfig(unittest.TestCase):
    """Test the configutils."""

    # pylint: disable=invalid-name
    def setUp(self):
        """Initialize a test Home Assistant instance."""
        self.hass = get_test_home_assistant()

    # pylint: disable=invalid-name
    def tearDown(self):
        """Clean up."""
        dt_util.DEFAULT_TIME_ZONE = ORIG_TIMEZONE

        if os.path.isfile(YAML_PATH):
            os.remove(YAML_PATH)

        if os.path.isfile(VERSION_PATH):
            os.remove(VERSION_PATH)

        self.hass.stop()

    def test_create_default_config(self):
        """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):
        """Test if it finds a YAML config file."""
        create_file(YAML_PATH)

        self.assertEqual(YAML_PATH, config_util.find_config_file(CONFIG_DIR))

    @mock.patch('builtins.print')
    def test_ensure_config_exists_creates_config(self, mock_print):
        """Test that calling ensure_config_exists.

        If not creates a new config file.
        """
        config_util.ensure_config_exists(CONFIG_DIR, False)

        self.assertTrue(os.path.isfile(YAML_PATH))
        self.assertTrue(mock_print.called)

    def test_ensure_config_exists_uses_existing_config(self):
        """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):
        """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):
        """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):
        """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)

    def test_load_yaml_config_raises_error_if_unsafe_yaml(self):
        """Test error raised if unsafe YAML."""
        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)

    def test_load_yaml_config_preserves_key_order(self):
        """Test removal of library."""
        with open(YAML_PATH, 'w') as f:
            f.write('hello: 0\n')
            f.write('world: 1\n')

        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)
    @mock.patch('builtins.print')
    def test_create_default_config_detect_location(self, mock_detect,
                                                   mock_elev, mock_print):
        """Test that detect location sets the correct config keys."""
        config_util.ensure_config_exists(CONFIG_DIR)

        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_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
            CONF_NAME: 'Home',
            CONF_TIME_ZONE: 'America/Los_Angeles'
        }

        assert expected_values == ha_conf
        assert mock_print.called

    @mock.patch('builtins.print')
    def test_create_default_config_returns_none_if_write_error(
            self, mock_print):
        """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))
        self.assertTrue(mock_print.called)

    def test_core_config_schema(self):
        """Test core config schema."""
        for value in (
            {
                CONF_UNIT_SYSTEM: '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',
            CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
            'customize': {
                'sensor.temperature': {
                    'hidden': True,
                },
            },
        })

    def test_entity_customization(self):
        """Test entity customization through configuration."""
        config = {
            CONF_LATITUDE: 50,
            CONF_LONGITUDE: 50,
            CONF_NAME: 'Test',
            CONF_CUSTOMIZE: {
                'test.test': {
                    'hidden': True
                }
            }
        }

        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(self.hass, config),
            self.hass.loop).result()

        entity = Entity()
        entity.entity_id = 'test.test'
        entity.hass = self.hass
        entity.update_ha_state()

        self.hass.block_till_done()

        state = self.hass.states.get('test.test')

        assert state.attributes['hidden']

    @mock.patch('homeassistant.config.shutil')
    @mock.patch('homeassistant.config.os')
    def test_remove_lib_on_upgrade(self, mock_os, mock_shutil):
        """Test removal of library on upgrade."""
        ha_version = '0.7.0'

        mock_os.path.isdir = mock.Mock(return_value=True)

        mock_open = mock.mock_open()
        with mock.patch('homeassistant.config.open', mock_open, create=True):
            opened_file = mock_open.return_value
            opened_file.readline.return_value = ha_version

            self.hass.config.path = mock.Mock()

            config_util.process_ha_config_upgrade(self.hass)

            hass_path = self.hass.config.path.return_value

            self.assertEqual(mock_os.path.isdir.call_count, 1)
            self.assertEqual(mock_os.path.isdir.call_args,
                             mock.call(hass_path))

            self.assertEqual(mock_shutil.rmtree.call_count, 1)
            self.assertEqual(mock_shutil.rmtree.call_args,
                             mock.call(hass_path))

    @mock.patch('homeassistant.config.shutil')
    @mock.patch('homeassistant.config.os')
    def test_not_remove_lib_if_not_upgrade(self, mock_os, mock_shutil):
        """Test removal of library with no upgrade."""
        ha_version = __version__

        mock_os.path.isdir = mock.Mock(return_value=True)

        mock_open = mock.mock_open()
        with mock.patch('homeassistant.config.open', mock_open, create=True):
            opened_file = mock_open.return_value
            opened_file.readline.return_value = ha_version

            self.hass.config.path = mock.Mock()

            config_util.process_ha_config_upgrade(self.hass)

            assert mock_os.path.isdir.call_count == 0
            assert mock_shutil.rmtree.call_count == 0

    def test_loading_configuration(self):
        """Test loading core config onto hass object."""
        self.hass.config = mock.Mock()

        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(
                self.hass, {
                    'latitude': 60,
                    'longitude': 50,
                    'elevation': 25,
                    'name': 'Huis',
                    CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
                    'time_zone': 'America/New_York',
                }), self.hass.loop).result()

        assert self.hass.config.latitude == 60
        assert self.hass.config.longitude == 50
        assert self.hass.config.elevation == 25
        assert self.hass.config.location_name == 'Huis'
        assert self.hass.config.units.name == CONF_UNIT_SYSTEM_IMPERIAL
        assert self.hass.config.time_zone.zone == 'America/New_York'

    def test_loading_configuration_temperature_unit(self):
        """Test backward compatibility when loading core config."""
        self.hass.config = mock.Mock()

        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(
                self.hass, {
                    'latitude': 60,
                    'longitude': 50,
                    'elevation': 25,
                    'name': 'Huis',
                    CONF_TEMPERATURE_UNIT: 'C',
                    'time_zone': 'America/New_York',
                }), self.hass.loop).result()

        assert self.hass.config.latitude == 60
        assert self.hass.config.longitude == 50
        assert self.hass.config.elevation == 25
        assert self.hass.config.location_name == 'Huis'
        assert self.hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
        assert self.hass.config.time_zone.zone == 'America/New_York'

    @mock.patch('homeassistant.util.location.detect_location_info',
                autospec=True,
                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',
                autospec=True,
                return_value=101)
    def test_discovering_configuration(self, mock_detect, mock_elevation):
        """Test auto discovery for missing core configs."""
        self.hass.config.latitude = None
        self.hass.config.longitude = None
        self.hass.config.elevation = None
        self.hass.config.location_name = None
        self.hass.config.time_zone = None

        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(self.hass, {}),
            self.hass.loop).result()

        assert self.hass.config.latitude == 32.8594
        assert self.hass.config.longitude == -117.2073
        assert self.hass.config.elevation == 101
        assert self.hass.config.location_name == 'San Diego'
        assert self.hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
        assert self.hass.config.units.is_metric
        assert self.hass.config.time_zone.zone == 'America/Los_Angeles'

    @mock.patch('homeassistant.util.location.detect_location_info',
                autospec=True,
                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."""
        self.hass.config = Config()

        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(self.hass, {}),
            self.hass.loop).result()

        blankConfig = Config()
        assert self.hass.config.latitude == blankConfig.latitude
        assert self.hass.config.longitude == blankConfig.longitude
        assert self.hass.config.elevation == blankConfig.elevation
        assert self.hass.config.location_name == blankConfig.location_name
        assert self.hass.config.units == blankConfig.units
        assert self.hass.config.time_zone == blankConfig.time_zone
Esempio n. 8
0
class TestConfig(unittest.TestCase):
    """Test the configutils."""

    # pylint: disable=invalid-name
    def setUp(self):
        """Initialize a test Home Assistant instance."""
        self.hass = get_test_home_assistant()

    # pylint: disable=invalid-name
    def tearDown(self):
        """Clean up."""
        dt_util.DEFAULT_TIME_ZONE = ORIG_TIMEZONE

        if os.path.isfile(YAML_PATH):
            os.remove(YAML_PATH)

        if os.path.isfile(SECRET_PATH):
            os.remove(SECRET_PATH)

        if os.path.isfile(VERSION_PATH):
            os.remove(VERSION_PATH)

        if os.path.isfile(GROUP_PATH):
            os.remove(GROUP_PATH)

        if os.path.isfile(AUTOMATIONS_PATH):
            os.remove(AUTOMATIONS_PATH)

        if os.path.isfile(SCRIPTS_PATH):
            os.remove(SCRIPTS_PATH)

        if os.path.isfile(CUSTOMIZE_PATH):
            os.remove(CUSTOMIZE_PATH)

        self.hass.stop()

    # pylint: disable=no-self-use
    def test_create_default_config(self):
        """Test creation of default config."""
        config_util.create_default_config(CONFIG_DIR, False)

        assert os.path.isfile(YAML_PATH)
        assert os.path.isfile(SECRET_PATH)
        assert os.path.isfile(VERSION_PATH)
        assert os.path.isfile(GROUP_PATH)
        assert os.path.isfile(AUTOMATIONS_PATH)
        assert os.path.isfile(CUSTOMIZE_PATH)

    def test_find_config_file_yaml(self):
        """Test if it finds a YAML config file."""
        create_file(YAML_PATH)

        assert YAML_PATH == config_util.find_config_file(CONFIG_DIR)

    @mock.patch('builtins.print')
    def test_ensure_config_exists_creates_config(self, mock_print):
        """Test that calling ensure_config_exists.

        If not creates a new config file.
        """
        config_util.ensure_config_exists(CONFIG_DIR, False)

        assert os.path.isfile(YAML_PATH)
        assert mock_print.called

    def test_ensure_config_exists_uses_existing_config(self):
        """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
        assert '' == content

    def test_load_yaml_config_converts_empty_files_to_dict(self):
        """Test that loading an empty file returns an empty dict."""
        create_file(YAML_PATH)

        assert isinstance(config_util.load_yaml_config_file(YAML_PATH), dict)

    def test_load_yaml_config_raises_error_if_not_dict(self):
        """Test error raised when YAML file is not a dict."""
        with open(YAML_PATH, 'w') as f:
            f.write('5')

        with pytest.raises(HomeAssistantError):
            config_util.load_yaml_config_file(YAML_PATH)

    def test_load_yaml_config_raises_error_if_malformed_yaml(self):
        """Test error raised if invalid YAML."""
        with open(YAML_PATH, 'w') as f:
            f.write(':')

        with pytest.raises(HomeAssistantError):
            config_util.load_yaml_config_file(YAML_PATH)

    def test_load_yaml_config_raises_error_if_unsafe_yaml(self):
        """Test error raised if unsafe YAML."""
        with open(YAML_PATH, 'w') as f:
            f.write('hello: !!python/object/apply:os.system')

        with pytest.raises(HomeAssistantError):
            config_util.load_yaml_config_file(YAML_PATH)

    def test_load_yaml_config_preserves_key_order(self):
        """Test removal of library."""
        with open(YAML_PATH, 'w') as f:
            f.write('hello: 2\n')
            f.write('world: 1\n')

        assert [('hello', 2), ('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)
    @mock.patch('builtins.print')
    def test_create_default_config_detect_location(self, mock_detect,
                                                   mock_elev, mock_print):
        """Test that detect location sets the correct config keys."""
        config_util.ensure_config_exists(CONFIG_DIR)

        config = config_util.load_yaml_config_file(YAML_PATH)

        assert DOMAIN in config

        ha_conf = config[DOMAIN]

        expected_values = {
            CONF_LATITUDE: 32.8594,
            CONF_LONGITUDE: -117.2073,
            CONF_ELEVATION: 101,
            CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
            CONF_NAME: 'Home',
            CONF_TIME_ZONE: 'America/Los_Angeles',
            CONF_CUSTOMIZE: OrderedDict(),
        }

        assert expected_values == ha_conf
        assert mock_print.called

    @mock.patch('builtins.print')
    def test_create_default_config_returns_none_if_write_error(
            self, mock_print):
        """Test the writing of a default configuration.

        Non existing folder returns None.
        """
        assert config_util.create_default_config(
            os.path.join(CONFIG_DIR, 'non_existing_dir/'), False) is None
        assert mock_print.called

    # pylint: disable=no-self-use
    def test_core_config_schema(self):
        """Test core config schema."""
        for value in (
            {
                CONF_UNIT_SYSTEM: 'K'
            },
            {
                'time_zone': 'non-exist'
            },
            {
                'latitude': '91'
            },
            {
                'longitude': -181
            },
            {
                'customize': 'bla'
            },
            {
                'customize': {
                    'light.sensor': 100
                }
            },
            {
                'customize': {
                    'entity_id': []
                }
            },
        ):
            with pytest.raises(MultipleInvalid):
                config_util.CORE_CONFIG_SCHEMA(value)

        config_util.CORE_CONFIG_SCHEMA({
            'name': 'Test name',
            'latitude': '-23.45',
            'longitude': '123.45',
            CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
            'customize': {
                'sensor.temperature': {
                    'hidden': True,
                },
            },
        })

    def test_customize_dict_schema(self):
        """Test basic customize config validation."""
        values = (
            {
                ATTR_FRIENDLY_NAME: None
            },
            {
                ATTR_HIDDEN: '2'
            },
            {
                ATTR_ASSUMED_STATE: '2'
            },
        )

        for val in values:
            print(val)
            with pytest.raises(MultipleInvalid):
                config_util.CUSTOMIZE_DICT_SCHEMA(val)

        assert config_util.CUSTOMIZE_DICT_SCHEMA({
            ATTR_FRIENDLY_NAME: 2,
            ATTR_HIDDEN: '1',
            ATTR_ASSUMED_STATE: '0',
        }) == {
            ATTR_FRIENDLY_NAME: '2',
            ATTR_HIDDEN: True,
            ATTR_ASSUMED_STATE: False
        }

    def test_customize_glob_is_ordered(self):
        """Test that customize_glob preserves order."""
        conf = config_util.CORE_CONFIG_SCHEMA(
            {'customize_glob': OrderedDict()})
        assert isinstance(conf['customize_glob'], OrderedDict)

    def _compute_state(self, config):
        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(self.hass, config),
            self.hass.loop).result()

        entity = Entity()
        entity.entity_id = 'test.test'
        entity.hass = self.hass
        entity.schedule_update_ha_state()

        self.hass.block_till_done()

        return self.hass.states.get('test.test')

    def test_entity_customization(self):
        """Test entity customization through configuration."""
        config = {
            CONF_LATITUDE: 50,
            CONF_LONGITUDE: 50,
            CONF_NAME: 'Test',
            CONF_CUSTOMIZE: {
                'test.test': {
                    'hidden': True
                }
            }
        }

        state = self._compute_state(config)

        assert state.attributes['hidden']

    @mock.patch('homeassistant.config.shutil')
    @mock.patch('homeassistant.config.os')
    def test_remove_lib_on_upgrade(self, mock_os, mock_shutil):
        """Test removal of library on upgrade from before 0.50."""
        ha_version = '0.49.0'
        mock_os.path.isdir = mock.Mock(return_value=True)
        mock_open = mock.mock_open()
        with mock.patch('homeassistant.config.open', mock_open, create=True):
            opened_file = mock_open.return_value
            # pylint: disable=no-member
            opened_file.readline.return_value = ha_version
            self.hass.config.path = mock.Mock()
            config_util.process_ha_config_upgrade(self.hass)
            hass_path = self.hass.config.path.return_value

            assert mock_os.path.isdir.call_count == 1
            assert mock_os.path.isdir.call_args == mock.call(hass_path)
            assert mock_shutil.rmtree.call_count == 1
            assert mock_shutil.rmtree.call_args == mock.call(hass_path)

    def test_process_config_upgrade(self):
        """Test update of version on upgrade."""
        ha_version = '0.8.0'

        mock_open = mock.mock_open()
        with mock.patch('homeassistant.config.open', mock_open, create=True):
            opened_file = mock_open.return_value
            # pylint: disable=no-member
            opened_file.readline.return_value = ha_version

            config_util.process_ha_config_upgrade(self.hass)

            assert opened_file.write.call_count == 1
            assert opened_file.write.call_args == mock.call(__version__)

    def test_config_upgrade_same_version(self):
        """Test no update of version on no upgrade."""
        ha_version = __version__

        mock_open = mock.mock_open()
        with mock.patch('homeassistant.config.open', mock_open, create=True):
            opened_file = mock_open.return_value
            # pylint: disable=no-member
            opened_file.readline.return_value = ha_version

            config_util.process_ha_config_upgrade(self.hass)

            assert opened_file.write.call_count == 0

    def test_config_upgrade_no_file(self):
        """Test update of version on upgrade, with no version file."""
        mock_open = mock.mock_open()
        mock_open.side_effect = [FileNotFoundError(), mock.DEFAULT]
        with mock.patch('homeassistant.config.open', mock_open, create=True):
            opened_file = mock_open.return_value
            # pylint: disable=no-member
            config_util.process_ha_config_upgrade(self.hass)
            assert opened_file.write.call_count == 1
            assert opened_file.write.call_args == mock.call(__version__)

    @mock.patch('homeassistant.config.shutil')
    @mock.patch('homeassistant.config.os')
    def test_migrate_file_on_upgrade(self, mock_os, mock_shutil):
        """Test migrate of config files on upgrade."""
        ha_version = '0.7.0'

        mock_os.path.isdir = mock.Mock(return_value=True)

        mock_open = mock.mock_open()

        def _mock_isfile(filename):
            return True

        with mock.patch('homeassistant.config.open', mock_open, create=True), \
                mock.patch(
                    'homeassistant.config.os.path.isfile', _mock_isfile):
            opened_file = mock_open.return_value
            # pylint: disable=no-member
            opened_file.readline.return_value = ha_version

            self.hass.config.path = mock.Mock()

            config_util.process_ha_config_upgrade(self.hass)

        assert mock_os.rename.call_count == 1

    @mock.patch('homeassistant.config.shutil')
    @mock.patch('homeassistant.config.os')
    def test_migrate_no_file_on_upgrade(self, mock_os, mock_shutil):
        """Test not migrating config files on upgrade."""
        ha_version = '0.7.0'

        mock_os.path.isdir = mock.Mock(return_value=True)

        mock_open = mock.mock_open()

        def _mock_isfile(filename):
            return False

        with mock.patch('homeassistant.config.open', mock_open, create=True), \
                mock.patch(
                    'homeassistant.config.os.path.isfile', _mock_isfile):
            opened_file = mock_open.return_value
            # pylint: disable=no-member
            opened_file.readline.return_value = ha_version

            self.hass.config.path = mock.Mock()

            config_util.process_ha_config_upgrade(self.hass)

        assert mock_os.rename.call_count == 0

    def test_loading_configuration(self):
        """Test loading core config onto hass object."""
        self.hass.config = mock.Mock()

        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(
                self.hass, {
                    'latitude': 60,
                    'longitude': 50,
                    'elevation': 25,
                    'name': 'Huis',
                    CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
                    'time_zone': 'America/New_York',
                    'whitelist_external_dirs': '/tmp',
                }), self.hass.loop).result()

        assert self.hass.config.latitude == 60
        assert self.hass.config.longitude == 50
        assert self.hass.config.elevation == 25
        assert self.hass.config.location_name == 'Huis'
        assert self.hass.config.units.name == CONF_UNIT_SYSTEM_IMPERIAL
        assert self.hass.config.time_zone.zone == 'America/New_York'
        assert len(self.hass.config.whitelist_external_dirs) == 2
        assert '/tmp' in self.hass.config.whitelist_external_dirs

    def test_loading_configuration_temperature_unit(self):
        """Test backward compatibility when loading core config."""
        self.hass.config = mock.Mock()

        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(
                self.hass, {
                    'latitude': 60,
                    'longitude': 50,
                    'elevation': 25,
                    'name': 'Huis',
                    CONF_TEMPERATURE_UNIT: 'C',
                    'time_zone': 'America/New_York',
                }), self.hass.loop).result()

        assert self.hass.config.latitude == 60
        assert self.hass.config.longitude == 50
        assert self.hass.config.elevation == 25
        assert self.hass.config.location_name == 'Huis'
        assert self.hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
        assert self.hass.config.time_zone.zone == 'America/New_York'

    def test_loading_configuration_from_packages(self):
        """Test loading packages config onto hass object config."""
        self.hass.config = mock.Mock()

        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(
                self.hass, {
                    'latitude': 39,
                    'longitude': -1,
                    'elevation': 500,
                    'name': 'Huis',
                    CONF_TEMPERATURE_UNIT: 'C',
                    'time_zone': 'Europe/Madrid',
                    'packages': {
                        'package_1': {
                            'wake_on_lan': None
                        },
                        'package_2': {
                            'light': {
                                'platform': 'hue'
                            },
                            'media_extractor': None,
                            'sun': None
                        }
                    },
                }), self.hass.loop).result()

        # Empty packages not allowed
        with pytest.raises(MultipleInvalid):
            run_coroutine_threadsafe(
                config_util.async_process_ha_core_config(
                    self.hass, {
                        'latitude': 39,
                        'longitude': -1,
                        'elevation': 500,
                        'name': 'Huis',
                        CONF_TEMPERATURE_UNIT: 'C',
                        'time_zone': 'Europe/Madrid',
                        'packages': {
                            'empty_package': None
                        },
                    }), self.hass.loop).result()

    @mock.patch('homeassistant.util.location.detect_location_info',
                autospec=True,
                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',
                autospec=True,
                return_value=101)
    def test_discovering_configuration(self, mock_detect, mock_elevation):
        """Test auto discovery for missing core configs."""
        self.hass.config.latitude = None
        self.hass.config.longitude = None
        self.hass.config.elevation = None
        self.hass.config.location_name = None
        self.hass.config.time_zone = None

        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(self.hass, {}),
            self.hass.loop).result()

        assert self.hass.config.latitude == 32.8594
        assert self.hass.config.longitude == -117.2073
        assert self.hass.config.elevation == 101
        assert self.hass.config.location_name == 'San Diego'
        assert self.hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
        assert self.hass.config.units.is_metric
        assert self.hass.config.time_zone.zone == 'America/Los_Angeles'

    @mock.patch('homeassistant.util.location.detect_location_info',
                autospec=True,
                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."""
        self.hass.config = Config()
        self.hass.config.config_dir = "/test/config"

        run_coroutine_threadsafe(
            config_util.async_process_ha_core_config(self.hass, {}),
            self.hass.loop).result()

        blankConfig = Config()
        assert self.hass.config.latitude == blankConfig.latitude
        assert self.hass.config.longitude == blankConfig.longitude
        assert self.hass.config.elevation == blankConfig.elevation
        assert self.hass.config.location_name == blankConfig.location_name
        assert self.hass.config.units == blankConfig.units
        assert self.hass.config.time_zone == blankConfig.time_zone
        assert len(self.hass.config.whitelist_external_dirs) == 1
        assert "/test/config/www" in self.hass.config.whitelist_external_dirs

    @mock.patch('homeassistant.scripts.check_config.check_ha_config_file')
    def test_check_ha_config_file_correct(self, mock_check):
        """Check that restart propagates to stop."""
        mock_check.return_value = check_config.HomeAssistantConfig()
        assert run_coroutine_threadsafe(
            config_util.async_check_ha_config_file(self.hass),
            self.hass.loop).result() is None

    @mock.patch('homeassistant.scripts.check_config.check_ha_config_file')
    def test_check_ha_config_file_wrong(self, mock_check):
        """Check that restart with a bad config doesn't propagate to stop."""
        mock_check.return_value = check_config.HomeAssistantConfig()
        mock_check.return_value.add_error("bad")

        assert run_coroutine_threadsafe(
            config_util.async_check_ha_config_file(self.hass),
            self.hass.loop).result() == 'bad'
Esempio n. 9
0
                'elevation': 500,
                'name': 'Huis',
                CONF_TEMPERATURE_UNIT: 'C',
                'time_zone': 'Europe/Madrid',
                'packages': {
                    'empty_package': None
                },
            })


@asynctest.mock.patch(
    'homeassistant.util.location.async_detect_location_info',
    autospec=True,
    return_value=mock_coro(
        location_util.LocationInfo('0.0.0.0', 'US', 'United States', 'CA',
                                   'California', 'San Diego', '92122',
                                   'America/Los_Angeles', 32.8594, -117.2073,
                                   True)))
@asynctest.mock.patch('homeassistant.util.location.async_get_elevation',
                      autospec=True,
                      return_value=mock_coro(101))
async def test_discovering_configuration(mock_detect, mock_elevation, hass):
    """Test auto discovery for missing core configs."""
    hass.config.latitude = None
    hass.config.longitude = None
    hass.config.elevation = None
    hass.config.location_name = None
    hass.config.time_zone = None

    await config_util.async_process_ha_core_config(hass, {})

    assert hass.config.latitude == 32.8594
Esempio n. 10
0
class TestConfig(unittest.TestCase):
    """Test the configutils."""

    def tearDown(self):  # pylint: disable=invalid-name
        """Clean up."""
        dt_util.DEFAULT_TIME_ZONE = ORIG_TIMEZONE

        if os.path.isfile(YAML_PATH):
            os.remove(YAML_PATH)

        if os.path.isfile(VERSION_PATH):
            os.remove(VERSION_PATH)

        if hasattr(self, 'hass'):
            self.hass.stop()

    def test_create_default_config(self):
        """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):
        """Test if it finds a YAML config file."""
        create_file(YAML_PATH)

        self.assertEqual(YAML_PATH, config_util.find_config_file(CONFIG_DIR))

    @mock.patch('builtins.print')
    def test_ensure_config_exists_creates_config(self, mock_print):
        """Test that calling ensure_config_exists.

        If not creates a new config file.
        """
        config_util.ensure_config_exists(CONFIG_DIR, False)

        self.assertTrue(os.path.isfile(YAML_PATH))
        self.assertTrue(mock_print.called)

    def test_ensure_config_exists_uses_existing_config(self):
        """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):
        """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):
        """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):
        """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)

    def test_load_yaml_config_raises_error_if_unsafe_yaml(self):
        """Test error raised if unsafe YAML."""
        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)

    def test_load_yaml_config_preserves_key_order(self):
        """Test removal of library."""
        with open(YAML_PATH, 'w') as f:
            f.write('hello: 0\n')
            f.write('world: 1\n')

        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)
    @mock.patch('builtins.print')
    def test_create_default_config_detect_location(self, mock_detect,
                                                   mock_elev, mock_print):
        """Test that detect location sets the correct config keys."""
        config_util.ensure_config_exists(CONFIG_DIR)

        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

    @mock.patch('builtins.print')
    def test_create_default_config_returns_none_if_write_error(self,
                                                               mock_print):
        """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))
        self.assertTrue(mock_print.called)

    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
Esempio n. 11
0
~~~~~~~~~~~~~~

Tests initialization.
"""
import betamax

from homeassistant import util
from homeassistant.util import location

with betamax.Betamax.configure() as config:
    config.cassette_library_dir = 'tests/cassettes'

# Automatically called during different setups. Too often forgotten
# so mocked by default.
location.detect_location_info = lambda: location.LocationInfo(
    ip='1.1.1.1',
    country_code='US',
    country_name='United States',
    region_code='CA',
    region_name='California',
    city='San Diego',
    zip_code='92122',
    time_zone='America/Los_Angeles',
    latitude='2.0',
    longitude='1.0',
    use_fahrenheit=True,
)

location.elevation = lambda latitude, longitude: 0
util.get_local_ip = lambda: '127.0.0.1'