async HTTP component (#3914)

* Migrate WSGI to asyncio

* Rename wsgi -> http

* Python 3.4 compat

* Move linting to Python 3.4

* lint

* Lint

* Fix Python 3.4 mock_open + binary data

* Surpress logging aiohttp.access

* Spelling

* Sending files is a coroutine

* More callback annotations and naming fixes

* Fix ios
This commit is contained in:
Paulus Schoutsen 2016-10-23 23:48:01 -07:00 committed by GitHub
parent 9aa88819a5
commit 519d9f2fd0
45 changed files with 1422 additions and 1009 deletions

View file

@ -1,36 +1,18 @@
"""The tests for generic camera component."""
import unittest
import asyncio
from unittest import mock
import requests_mock
from werkzeug.test import EnvironBuilder
from homeassistant.bootstrap import setup_component
from homeassistant.components.http import request_class
from tests.common import get_test_home_assistant
class TestGenericCamera(unittest.TestCase):
"""Test the generic camera platform."""
@asyncio.coroutine
def test_fetching_url(aioclient_mock, hass, test_client):
"""Test that it fetches the given url."""
aioclient_mock.get('http://example.com', text='hello world')
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.wsgi = mock.MagicMock()
self.hass.config.components.append('http')
def tearDown(self):
"""Stop everything that was started."""
self.hass.stop()
@requests_mock.Mocker()
def test_fetching_url(self, m):
"""Test that it fetches the given url."""
self.hass.wsgi = mock.MagicMock()
m.get('http://example.com', text='hello world')
assert setup_component(self.hass, 'camera', {
def setup_platform():
"""Setup the platform."""
assert setup_component(hass, 'camera', {
'camera': {
'name': 'config_test',
'platform': 'generic',
@ -39,32 +21,32 @@ class TestGenericCamera(unittest.TestCase):
'password': 'pass'
}})
image_view = self.hass.wsgi.mock_calls[0][1][0]
yield from hass.loop.run_in_executor(None, setup_platform)
builder = EnvironBuilder(method='GET')
Request = request_class()
request = Request(builder.get_environ())
request.authenticated = True
resp = image_view.get(request, 'camera.config_test')
client = yield from test_client(hass.http.app)
assert m.call_count == 1
assert resp.status_code == 200, resp.response
assert resp.response[0].decode('utf-8') == 'hello world'
resp = yield from client.get('/api/camera_proxy/camera.config_test')
image_view.get(request, 'camera.config_test')
assert m.call_count == 2
assert aioclient_mock.call_count == 1
assert resp.status == 200
body = yield from resp.text()
assert body == 'hello world'
@requests_mock.Mocker()
def test_limit_refetch(self, m):
"""Test that it fetches the given url."""
self.hass.wsgi = mock.MagicMock()
from requests.exceptions import Timeout
m.get('http://example.com/5a', text='hello world')
m.get('http://example.com/10a', text='hello world')
m.get('http://example.com/15a', text='hello planet')
m.get('http://example.com/20a', status_code=404)
resp = yield from client.get('/api/camera_proxy/camera.config_test')
assert aioclient_mock.call_count == 2
assert setup_component(self.hass, 'camera', {
@asyncio.coroutine
def test_limit_refetch(aioclient_mock, hass, test_client):
"""Test that it fetches the given url."""
aioclient_mock.get('http://example.com/5a', text='hello world')
aioclient_mock.get('http://example.com/10a', text='hello world')
aioclient_mock.get('http://example.com/15a', text='hello planet')
aioclient_mock.get('http://example.com/20a', status=404)
def setup_platform():
"""Setup the platform."""
assert setup_component(hass, 'camera', {
'camera': {
'name': 'config_test',
'platform': 'generic',
@ -73,43 +55,47 @@ class TestGenericCamera(unittest.TestCase):
'limit_refetch_to_url_change': True,
}})
image_view = self.hass.wsgi.mock_calls[0][1][0]
yield from hass.loop.run_in_executor(None, setup_platform)
builder = EnvironBuilder(method='GET')
Request = request_class()
request = Request(builder.get_environ())
request.authenticated = True
client = yield from test_client(hass.http.app)
self.hass.states.set('sensor.temp', '5')
resp = yield from client.get('/api/camera_proxy/camera.config_test')
with mock.patch('requests.get', side_effect=Timeout()):
resp = image_view.get(request, 'camera.config_test')
assert m.call_count == 0
assert resp.status_code == 500, resp.response
hass.states.async_set('sensor.temp', '5')
self.hass.states.set('sensor.temp', '10')
with mock.patch('async_timeout.timeout',
side_effect=asyncio.TimeoutError()):
resp = yield from client.get('/api/camera_proxy/camera.config_test')
assert aioclient_mock.call_count == 0
assert resp.status == 500
resp = image_view.get(request, 'camera.config_test')
assert m.call_count == 1
assert resp.status_code == 200, resp.response
assert resp.response[0].decode('utf-8') == 'hello world'
hass.states.async_set('sensor.temp', '10')
resp = image_view.get(request, 'camera.config_test')
assert m.call_count == 1
assert resp.status_code == 200, resp.response
assert resp.response[0].decode('utf-8') == 'hello world'
resp = yield from client.get('/api/camera_proxy/camera.config_test')
assert aioclient_mock.call_count == 1
assert resp.status == 200
body = yield from resp.text()
assert body == 'hello world'
self.hass.states.set('sensor.temp', '15')
resp = yield from client.get('/api/camera_proxy/camera.config_test')
assert aioclient_mock.call_count == 1
assert resp.status == 200
body = yield from resp.text()
assert body == 'hello world'
# Url change = fetch new image
resp = image_view.get(request, 'camera.config_test')
assert m.call_count == 2
assert resp.status_code == 200, resp.response
assert resp.response[0].decode('utf-8') == 'hello planet'
hass.states.async_set('sensor.temp', '15')
# Cause a template render error
self.hass.states.remove('sensor.temp')
resp = image_view.get(request, 'camera.config_test')
assert m.call_count == 2
assert resp.status_code == 200, resp.response
assert resp.response[0].decode('utf-8') == 'hello planet'
# Url change = fetch new image
resp = yield from client.get('/api/camera_proxy/camera.config_test')
assert aioclient_mock.call_count == 2
assert resp.status == 200
body = yield from resp.text()
assert body == 'hello planet'
# Cause a template render error
hass.states.async_remove('sensor.temp')
resp = yield from client.get('/api/camera_proxy/camera.config_test')
assert aioclient_mock.call_count == 2
assert resp.status == 200
body = yield from resp.text()
assert body == 'hello planet'