diff --git a/homeassistant/components/zwave/__init__.py b/homeassistant/components/zwave/__init__.py index daeca63f52b..38827bc5533 100755 --- a/homeassistant/components/zwave/__init__.py +++ b/homeassistant/components/zwave/__init__.py @@ -13,6 +13,7 @@ from pprint import pprint import voluptuous as vol +from homeassistant.core import CoreState from homeassistant.loader import get_platform from homeassistant.helpers import discovery from homeassistant.helpers.entity_component import EntityComponent @@ -201,14 +202,15 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Generic Z-Wave platform setup.""" if discovery_info is None or NETWORK is None: return False + device = hass.data[DATA_ZWAVE_DICT].pop( - discovery_info[const.DISCOVERY_DEVICE]) - if device: - async_add_devices([device]) - return True - else: + discovery_info[const.DISCOVERY_DEVICE], None) + if device is None: return False + async_add_devices([device]) + return True + # pylint: disable=R0914 def setup(hass, config): @@ -258,7 +260,7 @@ def setup(hass, config): NETWORK = ZWaveNetwork(options, autostart=False) hass.data[DATA_ZWAVE_DICT] = {} - if use_debug: + if use_debug: # pragma: no cover def log_all(signal, value=None): """Log all the signals.""" print("") @@ -388,7 +390,7 @@ def setup(hass, config): """Stop Z-Wave network.""" _LOGGER.info("Stopping ZWave network.") NETWORK.stop() - if hass.state == 'RUNNING': + if hass.state == CoreState.running: hass.bus.fire(const.EVENT_NETWORK_STOP) def rename_node(service): diff --git a/tests/components/zwave/test_init.py b/tests/components/zwave/test_init.py index fe104b1e33a..2e80e5b5331 100644 --- a/tests/components/zwave/test_init.py +++ b/tests/components/zwave/test_init.py @@ -18,6 +18,13 @@ from tests.common import get_test_home_assistant from tests.mock.zwave import MockNetwork, MockNode, MockValue, MockEntityValues +@asyncio.coroutine +def test_missing_openzwave(hass): + """Test that missing openzwave lib stops setup.""" + result = yield from async_setup_component(hass, 'zwave', {'zwave': {}}) + assert not result + + @asyncio.coroutine def test_valid_device_config(hass, mock_openzwave): """Test valid device config.""" @@ -50,6 +57,87 @@ def test_invalid_device_config(hass, mock_openzwave): assert not result +def test_config_access_error(): + """Test threading error accessing config values.""" + node = MagicMock() + + def side_effect(): + raise RuntimeError + + node.values.values.side_effect = side_effect + result = zwave.get_config_value(node, 1) + assert result is None + + +@asyncio.coroutine +@patch.object(zwave, 'NETWORK') +def test_setup_platform(mock_network, hass, mock_openzwave): + """Test invalid device config.""" + mock_device = MagicMock() + hass.data[zwave.DATA_ZWAVE_DICT] = {456: mock_device} + async_add_devices = MagicMock() + + result = yield from zwave.async_setup_platform( + hass, None, async_add_devices, None) + assert not result + assert not async_add_devices.called + + result = yield from zwave.async_setup_platform( + hass, None, async_add_devices, {const.DISCOVERY_DEVICE: 123}) + assert not result + assert not async_add_devices.called + + result = yield from zwave.async_setup_platform( + hass, None, async_add_devices, {const.DISCOVERY_DEVICE: 456}) + assert result + assert async_add_devices.called + assert len(async_add_devices.mock_calls) == 1 + assert async_add_devices.mock_calls[0][1][0] == [mock_device] + + +@asyncio.coroutine +def test_zwave_ready_wait(hass, mock_openzwave): + """Test that zwave continues after waiting for network ready.""" + # Initialize zwave + yield from async_setup_component(hass, 'zwave', {'zwave': {}}) + yield from hass.async_block_till_done() + + with patch.object(zwave.time, 'sleep') as mock_sleep: + with patch.object(zwave, '_LOGGER') as mock_logger: + zwave.NETWORK.state = MockNetwork.STATE_STARTED + hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + yield from hass.async_block_till_done() + + assert mock_sleep.called + assert len(mock_sleep.mock_calls) == const.NETWORK_READY_WAIT_SECS + assert mock_logger.warning.called + assert len(mock_logger.warning.mock_calls) == 1 + assert mock_logger.warning.mock_calls[0][1][1] == \ + const.NETWORK_READY_WAIT_SECS + + +@asyncio.coroutine +def test_device_entity(hass, mock_openzwave): + """Test device entity base class.""" + node = MockNode(node_id='10', name='Mock Node') + value = MockValue(data=False, node=node, instance=2, object_id='11', + label='Sensor', + command_class=const.COMMAND_CLASS_SENSOR_BINARY) + power_value = MockValue(data=50.123456, node=node, precision=3, + command_class=const.COMMAND_CLASS_METER) + values = MockEntityValues(primary=value, power=power_value) + device = zwave.ZWaveDeviceEntity(values, 'zwave') + device.hass = hass + device.value_added() + device.update_properties() + yield from hass.async_block_till_done() + + assert not device.should_poll + assert device.unique_id == "ZWAVE-10-11" + assert device.name == 'Mock Node Sensor' + assert device.device_state_attributes[zwave.ATTR_POWER] == 50.123 + + class TestZWaveDeviceEntityValues(unittest.TestCase): """Tests for the ZWaveDeviceEntityValues helper.""" @@ -453,11 +541,15 @@ class TestZWaveServices(unittest.TestCase): def test_stop_network(self): """Test zwave stop_network service.""" - self.hass.services.call('zwave', 'stop_network', {}) - self.hass.block_till_done() + with patch.object(self.hass.bus, 'fire') as mock_fire: + self.hass.services.call('zwave', 'stop_network', {}) + self.hass.block_till_done() - assert zwave.NETWORK.stop.called - assert len(zwave.NETWORK.stop.mock_calls) == 1 + assert zwave.NETWORK.stop.called + assert len(zwave.NETWORK.stop.mock_calls) == 1 + assert mock_fire.called + assert len(mock_fire.mock_calls) == 2 + assert mock_fire.mock_calls[0][1][0] == const.EVENT_NETWORK_STOP def test_rename_node(self): """Test zwave rename_node service."""