"""The tests for the DD-WRT device tracker platform.""" import os import unittest from unittest import mock import logging import re import requests import requests_mock from homeassistant import config from homeassistant.bootstrap import setup_component from homeassistant.components import device_tracker from homeassistant.const import ( CONF_PLATFORM, CONF_HOST, CONF_PASSWORD, CONF_USERNAME) from homeassistant.components.device_tracker import DOMAIN from homeassistant.util import slugify from tests.common import ( get_test_home_assistant, assert_setup_component, load_fixture) from ...test_util.aiohttp import mock_aiohttp_client TEST_HOST = '127.0.0.1' _LOGGER = logging.getLogger(__name__) class TestDdwrt(unittest.TestCase): """Tests for the Ddwrt device tracker platform.""" hass = None def run(self, result=None): """Mock out http calls to macvendor API for whole test suite.""" with mock_aiohttp_client() as aioclient_mock: macvendor_re = re.compile('http://api.macvendors.com/.*') aioclient_mock.get(macvendor_re, text='') super().run(result) def setup_method(self, _): """Setup things to be run when tests are started.""" self.hass = get_test_home_assistant() self.hass.config.components = ['zone'] def teardown_method(self, _): """Stop everything that was started.""" self.hass.stop() try: os.remove(self.hass.config.path(device_tracker.YAML_DEVICES)) except FileNotFoundError: pass @mock.patch('homeassistant.components.device_tracker.ddwrt._LOGGER.error') def test_login_failed(self, mock_error): """Create a Ddwrt scanner with wrong credentials.""" with requests_mock.Mocker() as mock_request: mock_request.register_uri( 'GET', r'http://%s/Status_Wireless.live.asp' % TEST_HOST, status_code=401) with assert_setup_component(1): assert setup_component( self.hass, DOMAIN, {DOMAIN: { CONF_PLATFORM: 'ddwrt', CONF_HOST: TEST_HOST, CONF_USERNAME: 'fake_user', CONF_PASSWORD: '0' }}) self.assertTrue( 'Failed to authenticate' in str(mock_error.call_args_list[-1])) @mock.patch('homeassistant.components.device_tracker.ddwrt._LOGGER.error') def test_invalid_response(self, mock_error): """Test error handling when response has an error status.""" with requests_mock.Mocker() as mock_request: mock_request.register_uri( 'GET', r'http://%s/Status_Wireless.live.asp' % TEST_HOST, status_code=444) with assert_setup_component(1): assert setup_component( self.hass, DOMAIN, {DOMAIN: { CONF_PLATFORM: 'ddwrt', CONF_HOST: TEST_HOST, CONF_USERNAME: 'fake_user', CONF_PASSWORD: '0' }}) self.assertTrue( 'Invalid response from ddwrt' in str(mock_error.call_args_list[-1])) @mock.patch('homeassistant.components.device_tracker._LOGGER.error') @mock.patch('homeassistant.components.device_tracker.' 'ddwrt.DdWrtDeviceScanner.get_ddwrt_data', return_value=None) def test_no_response(self, data_mock, error_mock): """Create a Ddwrt scanner with no response in init, should fail.""" with assert_setup_component(1): assert setup_component( self.hass, DOMAIN, {DOMAIN: { CONF_PLATFORM: 'ddwrt', CONF_HOST: TEST_HOST, CONF_USERNAME: 'fake_user', CONF_PASSWORD: '0' }}) self.assertTrue( 'Error setting up platform' in str(error_mock.call_args_list[-1])) @mock.patch('homeassistant.components.device_tracker.ddwrt.requests.get', side_effect=requests.exceptions.Timeout) @mock.patch('homeassistant.components.device_tracker.ddwrt._LOGGER.error') def test_get_timeout(self, mock_error, mock_request): """Test get Ddwrt data with request time out.""" with assert_setup_component(1): assert setup_component( self.hass, DOMAIN, {DOMAIN: { CONF_PLATFORM: 'ddwrt', CONF_HOST: TEST_HOST, CONF_USERNAME: 'fake_user', CONF_PASSWORD: '0' }}) self.assertTrue( 'Connection to the router timed out' in str(mock_error.call_args_list[-1])) def test_scan_devices(self): """Test creating device info (MAC, name) from response. The created known_devices.yaml device info is compared to the DD-WRT Lan Status request response fixture. This effectively checks the data parsing functions. """ with requests_mock.Mocker() as mock_request: mock_request.register_uri( 'GET', r'http://%s/Status_Wireless.live.asp' % TEST_HOST, text=load_fixture('Ddwrt_Status_Wireless.txt')) mock_request.register_uri( 'GET', r'http://%s/Status_Lan.live.asp' % TEST_HOST, text=load_fixture('Ddwrt_Status_Lan.txt')) with assert_setup_component(1): assert setup_component( self.hass, DOMAIN, {DOMAIN: { CONF_PLATFORM: 'ddwrt', CONF_HOST: TEST_HOST, CONF_USERNAME: 'fake_user', CONF_PASSWORD: '0' }}) self.hass.block_till_done() path = self.hass.config.path(device_tracker.YAML_DEVICES) devices = config.load_yaml_config_file(path) for device in devices: self.assertIn( devices[device]['mac'], load_fixture('Ddwrt_Status_Lan.txt')) self.assertIn( slugify(devices[device]['name']), load_fixture('Ddwrt_Status_Lan.txt')) def test_device_name_no_data(self): """Test creating device info (MAC only) when no response.""" with requests_mock.Mocker() as mock_request: mock_request.register_uri( 'GET', r'http://%s/Status_Wireless.live.asp' % TEST_HOST, text=load_fixture('Ddwrt_Status_Wireless.txt')) mock_request.register_uri( 'GET', r'http://%s/Status_Lan.live.asp' % TEST_HOST, text=None) with assert_setup_component(1): assert setup_component( self.hass, DOMAIN, {DOMAIN: { CONF_PLATFORM: 'ddwrt', CONF_HOST: TEST_HOST, CONF_USERNAME: 'fake_user', CONF_PASSWORD: '0' }}) self.hass.block_till_done() path = self.hass.config.path(device_tracker.YAML_DEVICES) devices = config.load_yaml_config_file(path) for device in devices: _LOGGER.error(devices[device]) self.assertIn( devices[device]['mac'], load_fixture('Ddwrt_Status_Lan.txt')) def test_device_name_no_dhcp(self): """Test creating device info (MAC) when missing dhcp response.""" with requests_mock.Mocker() as mock_request: mock_request.register_uri( 'GET', r'http://%s/Status_Wireless.live.asp' % TEST_HOST, text=load_fixture('Ddwrt_Status_Wireless.txt')) mock_request.register_uri( 'GET', r'http://%s/Status_Lan.live.asp' % TEST_HOST, text=load_fixture('Ddwrt_Status_Lan.txt'). replace('dhcp_leases', 'missing')) with assert_setup_component(1): assert setup_component( self.hass, DOMAIN, {DOMAIN: { CONF_PLATFORM: 'ddwrt', CONF_HOST: TEST_HOST, CONF_USERNAME: 'fake_user', CONF_PASSWORD: '0' }}) self.hass.block_till_done() path = self.hass.config.path(device_tracker.YAML_DEVICES) devices = config.load_yaml_config_file(path) for device in devices: _LOGGER.error(devices[device]) self.assertIn( devices[device]['mac'], load_fixture('Ddwrt_Status_Lan.txt')) def test_update_no_data(self): """Test error handling of no response when active devices checked.""" with requests_mock.Mocker() as mock_request: mock_request.register_uri( 'GET', r'http://%s/Status_Wireless.live.asp' % TEST_HOST, # First request has to work to setup connection [{'text': load_fixture('Ddwrt_Status_Wireless.txt')}, # Second request to get active devices fails {'text': None}]) mock_request.register_uri( 'GET', r'http://%s/Status_Lan.live.asp' % TEST_HOST, text=load_fixture('Ddwrt_Status_Lan.txt')) with assert_setup_component(1): assert setup_component( self.hass, DOMAIN, {DOMAIN: { CONF_PLATFORM: 'ddwrt', CONF_HOST: TEST_HOST, CONF_USERNAME: 'fake_user', CONF_PASSWORD: '0' }}) def test_update_wrong_data(self): """Test error handling of bad response when active devices checked.""" with requests_mock.Mocker() as mock_request: mock_request.register_uri( 'GET', r'http://%s/Status_Wireless.live.asp' % TEST_HOST, text=load_fixture('Ddwrt_Status_Wireless.txt'). replace('active_wireless', 'missing')) mock_request.register_uri( 'GET', r'http://%s/Status_Lan.live.asp' % TEST_HOST, text=load_fixture('Ddwrt_Status_Lan.txt')) with assert_setup_component(1): assert setup_component( self.hass, DOMAIN, {DOMAIN: { CONF_PLATFORM: 'ddwrt', CONF_HOST: TEST_HOST, CONF_USERNAME: 'fake_user', CONF_PASSWORD: '0' }})