mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02:00
Bugfixes for pilight hub component and unit tests (#3948)
This commit is contained in:
committed by
Johann Kellerman
parent
5799d1aec9
commit
081e61528d
@ -95,7 +95,6 @@ omit =
|
||||
homeassistant/components/homematic.py
|
||||
homeassistant/components/*/homematic.py
|
||||
|
||||
homeassistant/components/pilight.py
|
||||
homeassistant/components/switch/pilight.py
|
||||
|
||||
homeassistant/components/knx.py
|
||||
|
@ -14,7 +14,7 @@ from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, CONF_HOST, CONF_PORT,
|
||||
CONF_WHITELIST)
|
||||
|
||||
REQUIREMENTS = ['pilight==0.0.2']
|
||||
REQUIREMENTS = ['pilight==0.1.1']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -102,7 +102,7 @@ def setup(hass, config):
|
||||
if not whitelist:
|
||||
hass.bus.fire(EVENT, data)
|
||||
# Check if data matches the defined whitelist
|
||||
elif all(data[key] in whitelist[key] for key in whitelist):
|
||||
elif all(str(data[key]) in whitelist[key] for key in whitelist):
|
||||
hass.bus.fire(EVENT, data)
|
||||
|
||||
pilight_client.set_callback(handle_received_code)
|
||||
|
@ -294,7 +294,7 @@ pexpect==4.0.1
|
||||
phue==0.8
|
||||
|
||||
# homeassistant.components.pilight
|
||||
pilight==0.0.2
|
||||
pilight==0.1.1
|
||||
|
||||
# homeassistant.components.media_player.plex
|
||||
# homeassistant.components.sensor.plex
|
||||
|
298
tests/components/test_pilight.py
Normal file
298
tests/components/test_pilight.py
Normal file
@ -0,0 +1,298 @@
|
||||
"""The tests for the pilight component."""
|
||||
import logging
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
import socket
|
||||
|
||||
from homeassistant.bootstrap import setup_component
|
||||
from homeassistant.components import pilight
|
||||
|
||||
from tests.common import get_test_home_assistant, assert_setup_component
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PilightDaemonSim:
|
||||
"""Class to fake the interface of the pilight python package.
|
||||
|
||||
Is used in an asyncio loop, thus the mock cannot be accessed to
|
||||
determine if methods where called?!
|
||||
This is solved here in a hackish way by printing errors
|
||||
that can be checked using logging.error mocks.
|
||||
"""
|
||||
|
||||
callback = None
|
||||
called = None
|
||||
|
||||
test_message = {"protocol": "kaku_switch",
|
||||
"uuid": "1-2-3-4",
|
||||
"message": {
|
||||
"id": 0,
|
||||
"unit": 0,
|
||||
"off": 1}}
|
||||
|
||||
def __init__(self, host, port):
|
||||
"""Init pilight client, ignore parameters."""
|
||||
pass
|
||||
|
||||
def send_code(self, call): # pylint: disable=no-self-use
|
||||
"""Called pilight.send service is called."""
|
||||
_LOGGER.error('PilightDaemonSim payload: ' + str(call))
|
||||
|
||||
def start(self):
|
||||
"""Called homeassistant.start is called.
|
||||
|
||||
Also sends one test message after start up
|
||||
"""
|
||||
_LOGGER.error('PilightDaemonSim start')
|
||||
# Fake one code receive after daemon started
|
||||
if not self.called:
|
||||
self.callback(self.test_message)
|
||||
self.called = True
|
||||
|
||||
def stop(self): # pylint: disable=no-self-use
|
||||
"""Called homeassistant.stop is called."""
|
||||
_LOGGER.error('PilightDaemonSim stop')
|
||||
|
||||
def set_callback(self, function):
|
||||
"""Callback called on event pilight.pilight_received."""
|
||||
self.callback = function
|
||||
_LOGGER.error('PilightDaemonSim callback: ' + str(function))
|
||||
|
||||
|
||||
class TestPilight(unittest.TestCase):
|
||||
"""Test the Pilight component."""
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
|
||||
@patch('homeassistant.components.pilight._LOGGER.error')
|
||||
def test_connection_failed_error(self, mock_error):
|
||||
"""Try to connect at 127.0.0.1:5000 with socket error."""
|
||||
with assert_setup_component(3):
|
||||
with patch('pilight.pilight.Client',
|
||||
side_effect=socket.error) as mock_client:
|
||||
self.assertFalse(setup_component(
|
||||
self.hass, pilight.DOMAIN, {pilight.DOMAIN: {}}))
|
||||
mock_client.assert_called_once_with(host=pilight.DEFAULT_HOST,
|
||||
port=pilight.DEFAULT_PORT)
|
||||
self.assertEqual(1, mock_error.call_count)
|
||||
|
||||
@patch('homeassistant.components.pilight._LOGGER.error')
|
||||
def test_connection_timeout_error(self, mock_error):
|
||||
"""Try to connect at 127.0.0.1:5000 with socket timeout."""
|
||||
with assert_setup_component(3):
|
||||
with patch('pilight.pilight.Client',
|
||||
side_effect=socket.timeout) as mock_client:
|
||||
self.assertFalse(setup_component(
|
||||
self.hass, pilight.DOMAIN, {pilight.DOMAIN: {}}))
|
||||
mock_client.assert_called_once_with(host=pilight.DEFAULT_HOST,
|
||||
port=pilight.DEFAULT_PORT)
|
||||
self.assertEqual(1, mock_error.call_count)
|
||||
|
||||
@patch('pilight.pilight.Client', PilightDaemonSim)
|
||||
@patch('homeassistant.core._LOGGER.error')
|
||||
@patch('tests.components.test_pilight._LOGGER.error')
|
||||
def test_send_code_no_protocol(self, mock_pilight_error, mock_error):
|
||||
"""Try to send data without protocol information, should give error."""
|
||||
with assert_setup_component(3):
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, pilight.DOMAIN, {pilight.DOMAIN: {}}))
|
||||
|
||||
# Call without protocol info, should be ignored with error
|
||||
self.hass.services.call(pilight.DOMAIN, pilight.SERVICE_NAME,
|
||||
service_data={'noprotocol': 'test',
|
||||
'value': 42},
|
||||
blocking=True)
|
||||
self.hass.block_till_done()
|
||||
error_log_call = mock_error.call_args_list[-1]
|
||||
self.assertTrue(
|
||||
'required key not provided @ data[\'protocol\']' in
|
||||
str(error_log_call))
|
||||
|
||||
@patch('pilight.pilight.Client', PilightDaemonSim)
|
||||
@patch('tests.components.test_pilight._LOGGER.error')
|
||||
def test_send_code(self, mock_pilight_error):
|
||||
"""Try to send proper data."""
|
||||
with assert_setup_component(3):
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, pilight.DOMAIN, {pilight.DOMAIN: {}}))
|
||||
|
||||
# Call with protocol info, should not give error
|
||||
service_data = {'protocol': 'test',
|
||||
'value': 42}
|
||||
self.hass.services.call(pilight.DOMAIN, pilight.SERVICE_NAME,
|
||||
service_data=service_data,
|
||||
blocking=True)
|
||||
self.hass.block_till_done()
|
||||
error_log_call = mock_pilight_error.call_args_list[-1]
|
||||
service_data['protocol'] = [service_data['protocol']]
|
||||
self.assertTrue(str(service_data) in str(error_log_call))
|
||||
|
||||
@patch('pilight.pilight.Client', PilightDaemonSim)
|
||||
@patch('homeassistant.components.pilight._LOGGER.error')
|
||||
def test_send_code_fail(self, mock_pilight_error):
|
||||
"""Check IOError exception error message."""
|
||||
with assert_setup_component(3):
|
||||
with patch('pilight.pilight.Client.send_code',
|
||||
side_effect=IOError):
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, pilight.DOMAIN, {pilight.DOMAIN: {}}))
|
||||
|
||||
# Call with protocol info, should not give error
|
||||
service_data = {'protocol': 'test',
|
||||
'value': 42}
|
||||
self.hass.services.call(pilight.DOMAIN, pilight.SERVICE_NAME,
|
||||
service_data=service_data,
|
||||
blocking=True)
|
||||
self.hass.block_till_done()
|
||||
error_log_call = mock_pilight_error.call_args_list[-1]
|
||||
self.assertTrue('Pilight send failed' in str(error_log_call))
|
||||
|
||||
@patch('pilight.pilight.Client', PilightDaemonSim)
|
||||
@patch('tests.components.test_pilight._LOGGER.error')
|
||||
def test_start_stop(self, mock_pilight_error):
|
||||
"""Check correct startup and stop of pilight daemon."""
|
||||
with assert_setup_component(3):
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, pilight.DOMAIN, {pilight.DOMAIN: {}}))
|
||||
|
||||
# Test startup
|
||||
self.hass.start()
|
||||
self.hass.block_till_done()
|
||||
error_log_call = mock_pilight_error.call_args_list[-2]
|
||||
self.assertTrue(
|
||||
'PilightDaemonSim callback' in str(error_log_call))
|
||||
error_log_call = mock_pilight_error.call_args_list[-1]
|
||||
self.assertTrue(
|
||||
'PilightDaemonSim start' in str(error_log_call))
|
||||
|
||||
# Test stop
|
||||
self.hass.stop()
|
||||
error_log_call = mock_pilight_error.call_args_list[-1]
|
||||
self.assertTrue(
|
||||
'PilightDaemonSim stop' in str(error_log_call))
|
||||
|
||||
@patch('pilight.pilight.Client', PilightDaemonSim)
|
||||
@patch('homeassistant.core._LOGGER.info')
|
||||
def test_receive_code(self, mock_info):
|
||||
"""Check if code receiving via pilight daemon works."""
|
||||
with assert_setup_component(3):
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, pilight.DOMAIN, {pilight.DOMAIN: {}}))
|
||||
|
||||
# Test startup
|
||||
self.hass.start()
|
||||
self.hass.block_till_done()
|
||||
|
||||
expected_message = dict(
|
||||
{'protocol': PilightDaemonSim.test_message['protocol'],
|
||||
'uuid': PilightDaemonSim.test_message['uuid']},
|
||||
**PilightDaemonSim.test_message['message'])
|
||||
error_log_call = mock_info.call_args_list[-1]
|
||||
|
||||
# Check if all message parts are put on event bus
|
||||
for key, value in expected_message.items():
|
||||
self.assertTrue(str(key) in str(error_log_call))
|
||||
self.assertTrue(str(value) in str(error_log_call))
|
||||
|
||||
@patch('pilight.pilight.Client', PilightDaemonSim)
|
||||
@patch('homeassistant.core._LOGGER.info')
|
||||
def test_whitelist_exact_match(self, mock_info):
|
||||
"""Check whitelist filter with matched data."""
|
||||
with assert_setup_component(3):
|
||||
whitelist = {
|
||||
'protocol': [PilightDaemonSim.test_message['protocol']],
|
||||
'uuid': [PilightDaemonSim.test_message['uuid']],
|
||||
'id': [PilightDaemonSim.test_message['message']['id']],
|
||||
'unit': [PilightDaemonSim.test_message['message']['unit']]}
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, pilight.DOMAIN,
|
||||
{pilight.DOMAIN: {"whitelist": whitelist}}))
|
||||
|
||||
self.hass.start()
|
||||
self.hass.block_till_done()
|
||||
|
||||
expected_message = dict(
|
||||
{'protocol': PilightDaemonSim.test_message['protocol'],
|
||||
'uuid': PilightDaemonSim.test_message['uuid']},
|
||||
**PilightDaemonSim.test_message['message'])
|
||||
info_log_call = mock_info.call_args_list[-1]
|
||||
|
||||
# Check if all message parts are put on event bus
|
||||
for key, value in expected_message.items():
|
||||
self.assertTrue(str(key) in str(info_log_call))
|
||||
self.assertTrue(str(value) in str(info_log_call))
|
||||
|
||||
@patch('pilight.pilight.Client', PilightDaemonSim)
|
||||
@patch('homeassistant.core._LOGGER.info')
|
||||
def test_whitelist_partial_match(self, mock_info):
|
||||
"""Check whitelist filter with partially matched data, should work."""
|
||||
with assert_setup_component(3):
|
||||
whitelist = {
|
||||
'protocol': [PilightDaemonSim.test_message['protocol']],
|
||||
'id': [PilightDaemonSim.test_message['message']['id']]}
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, pilight.DOMAIN,
|
||||
{pilight.DOMAIN: {"whitelist": whitelist}}))
|
||||
|
||||
self.hass.start()
|
||||
self.hass.block_till_done()
|
||||
|
||||
expected_message = dict(
|
||||
{'protocol': PilightDaemonSim.test_message['protocol'],
|
||||
'uuid': PilightDaemonSim.test_message['uuid']},
|
||||
**PilightDaemonSim.test_message['message'])
|
||||
info_log_call = mock_info.call_args_list[-1]
|
||||
|
||||
# Check if all message parts are put on event bus
|
||||
for key, value in expected_message.items():
|
||||
self.assertTrue(str(key) in str(info_log_call))
|
||||
self.assertTrue(str(value) in str(info_log_call))
|
||||
|
||||
@patch('pilight.pilight.Client', PilightDaemonSim)
|
||||
@patch('homeassistant.core._LOGGER.info')
|
||||
def test_whitelist_or_match(self, mock_info):
|
||||
"""Check whitelist filter with several subsection, should work."""
|
||||
with assert_setup_component(3):
|
||||
whitelist = {
|
||||
'protocol': [PilightDaemonSim.test_message['protocol'],
|
||||
'other_protocoll'],
|
||||
'id': [PilightDaemonSim.test_message['message']['id']]}
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, pilight.DOMAIN,
|
||||
{pilight.DOMAIN: {"whitelist": whitelist}}))
|
||||
|
||||
self.hass.start()
|
||||
self.hass.block_till_done()
|
||||
|
||||
expected_message = dict(
|
||||
{'protocol': PilightDaemonSim.test_message['protocol'],
|
||||
'uuid': PilightDaemonSim.test_message['uuid']},
|
||||
**PilightDaemonSim.test_message['message'])
|
||||
info_log_call = mock_info.call_args_list[-1]
|
||||
|
||||
# Check if all message parts are put on event bus
|
||||
for key, value in expected_message.items():
|
||||
self.assertTrue(str(key) in str(info_log_call))
|
||||
self.assertTrue(str(value) in str(info_log_call))
|
||||
|
||||
@patch('pilight.pilight.Client', PilightDaemonSim)
|
||||
@patch('homeassistant.core._LOGGER.info')
|
||||
def test_whitelist_no_match(self, mock_info):
|
||||
"""Check whitelist filter with unmatched data, should not work."""
|
||||
with assert_setup_component(3):
|
||||
whitelist = {
|
||||
'protocol': ['wrong_protocoll'],
|
||||
'id': [PilightDaemonSim.test_message['message']['id']]}
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, pilight.DOMAIN,
|
||||
{pilight.DOMAIN: {"whitelist": whitelist}}))
|
||||
|
||||
self.hass.start()
|
||||
self.hass.block_till_done()
|
||||
|
||||
info_log_call = mock_info.call_args_list[-1]
|
||||
|
||||
self.assertFalse('Event pilight_received' in info_log_call)
|
Reference in New Issue
Block a user