mirror of
https://github.com/Manuel83/craftbeerpi3
synced 2026-11-03 20:53:54 +01:00
python 3 migration
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import six
|
||||
if six.PY3:
|
||||
from unittest import mock
|
||||
else:
|
||||
import mock
|
||||
|
||||
if sys.version_info >= (3, 5):
|
||||
from engineio.async_drivers import aiohttp as async_aiohttp
|
||||
|
||||
|
||||
@unittest.skipIf(sys.version_info < (3, 5), 'only for Python 3.5+')
|
||||
class AiohttpTests(unittest.TestCase):
|
||||
def test_create_route(self):
|
||||
app = mock.MagicMock()
|
||||
mock_server = mock.MagicMock()
|
||||
async_aiohttp.create_route(app, mock_server, '/foo')
|
||||
app.router.add_get.assert_any_call('/foo', mock_server.handle_request)
|
||||
app.router.add_post.assert_any_call('/foo', mock_server.handle_request)
|
||||
|
||||
def test_translate_request(self):
|
||||
request = mock.MagicMock()
|
||||
request._message.method = 'PUT'
|
||||
request._message.path = '/foo/bar?baz=1'
|
||||
request._message.version = (1, 1)
|
||||
request._message.headers = {'a': 'b', 'c-c': 'd', 'c_c': 'e',
|
||||
'content-type': 'application/json',
|
||||
'content-length': 123}
|
||||
request._payload = b'hello world'
|
||||
environ = async_aiohttp.translate_request(request)
|
||||
expected_environ = {
|
||||
'REQUEST_METHOD': 'PUT',
|
||||
'PATH_INFO': '/foo/bar',
|
||||
'QUERY_STRING': 'baz=1',
|
||||
'CONTENT_TYPE': 'application/json',
|
||||
'CONTENT_LENGTH': 123,
|
||||
'HTTP_A': 'b',
|
||||
# 'HTTP_C_C': 'd,e',
|
||||
'RAW_URI': '/foo/bar?baz=1',
|
||||
'SERVER_PROTOCOL': 'HTTP/1.1',
|
||||
'wsgi.input': b'hello world',
|
||||
'aiohttp.request': request,
|
||||
}
|
||||
for k, v in expected_environ.items():
|
||||
self.assertEqual(v, environ[k])
|
||||
self.assertTrue(
|
||||
environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d')
|
||||
|
||||
# @mock.patch('async_aiohttp.aiohttp.web.Response')
|
||||
def test_make_response(self):
|
||||
rv = async_aiohttp.make_response('202 ACCEPTED', {'foo': 'bar'},
|
||||
b'payload', {})
|
||||
self.assertEqual(rv.status, 202)
|
||||
self.assertEqual(rv.headers['foo'], 'bar')
|
||||
self.assertEqual(rv.body, b'payload')
|
||||
@@ -0,0 +1,279 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import six
|
||||
if six.PY3:
|
||||
from unittest import mock
|
||||
else:
|
||||
import mock
|
||||
|
||||
if sys.version_info >= (3, 5):
|
||||
import asyncio
|
||||
from engineio.async_drivers import asgi as async_asgi
|
||||
|
||||
|
||||
def AsyncMock(*args, **kwargs):
|
||||
"""Return a mock asynchronous function."""
|
||||
m = mock.MagicMock(*args, **kwargs)
|
||||
|
||||
async def mock_coro(*args, **kwargs):
|
||||
return m(*args, **kwargs)
|
||||
|
||||
mock_coro.mock = m
|
||||
return mock_coro
|
||||
|
||||
|
||||
def _run(coro):
|
||||
"""Run the given coroutine."""
|
||||
return asyncio.get_event_loop().run_until_complete(coro)
|
||||
|
||||
|
||||
@unittest.skipIf(sys.version_info < (3, 5), 'only for Python 3.5+')
|
||||
class AsgiTests(unittest.TestCase):
|
||||
def test_create_app(self):
|
||||
app = async_asgi.ASGIApp(
|
||||
'eio', 'other_app', static_files='static_files',
|
||||
engineio_path='/foo')
|
||||
self.assertEqual(app.engineio_server, 'eio')
|
||||
self.assertEqual(app.other_asgi_app, 'other_app')
|
||||
self.assertEqual(app.static_files, 'static_files')
|
||||
self.assertEqual(app.engineio_path, 'foo'),
|
||||
|
||||
def test_engineio_routing(self):
|
||||
mock_server = mock.MagicMock()
|
||||
mock_server.handle_request = AsyncMock()
|
||||
app = async_asgi.ASGIApp(mock_server)
|
||||
scope = {'type': 'http', 'path': '/engine.io/'}
|
||||
_run(app(scope, 'receive', 'send'))
|
||||
mock_server.handle_request.mock.assert_called_once_with(
|
||||
scope, 'receive', 'send')
|
||||
|
||||
def test_other_app_routing(self):
|
||||
other_app = AsyncMock()
|
||||
app = async_asgi.ASGIApp('eio', other_app)
|
||||
scope = {'type': 'http', 'path': '/foo'}
|
||||
_run(app(scope, 'receive', 'send'))
|
||||
other_app.mock.assert_called_once_with(scope, 'receive', 'send')
|
||||
|
||||
def test_static_file_routing(self):
|
||||
root_dir = os.path.dirname(__file__)
|
||||
app = async_asgi.ASGIApp('eio', static_files={
|
||||
'/': root_dir + '/index.html',
|
||||
'/foo': {'content_type': 'text/plain',
|
||||
'filename': root_dir + '/index.html'},
|
||||
'/static': root_dir,
|
||||
'/static/test/': root_dir + '/',
|
||||
})
|
||||
|
||||
def check_path(path, status_code, content_type, body):
|
||||
scope = {'type': 'http', 'path': path}
|
||||
receive = AsyncMock(return_value={'type': 'http.request'})
|
||||
send = AsyncMock()
|
||||
_run(app(scope, receive, send))
|
||||
send.mock.assert_any_call({
|
||||
'type': 'http.response.start',
|
||||
'status': status_code,
|
||||
'headers': [(b'Content-Type', content_type.encode('utf-8'))]})
|
||||
send.mock.assert_any_call({
|
||||
'type': 'http.response.body',
|
||||
'body': body.encode('utf-8')})
|
||||
|
||||
check_path('/', 200, 'text/html', '<html></html>\n')
|
||||
check_path('/foo', 200, 'text/plain', '<html></html>\n')
|
||||
check_path('/static/index.html', 200, 'text/html', '<html></html>\n')
|
||||
check_path('/static/foo.bar', 404, 'text/plain', 'Not Found')
|
||||
check_path('/static/test/index.html', 200, 'text/html',
|
||||
'<html></html>\n')
|
||||
check_path('/bar/foo', 404, 'text/plain', 'Not Found')
|
||||
check_path('', 404, 'text/plain', 'Not Found')
|
||||
|
||||
app.static_files[''] = 'index.html'
|
||||
check_path('/static/test/', 200, 'text/html',
|
||||
'<html></html>\n')
|
||||
|
||||
app.static_files[''] = {'filename': 'index.html'}
|
||||
check_path('/static/test/', 200, 'text/html',
|
||||
'<html></html>\n')
|
||||
|
||||
app.static_files[''] = {'filename': 'index.html',
|
||||
'content_type': 'image/gif'}
|
||||
check_path('/static/test/', 200, 'image/gif',
|
||||
'<html></html>\n')
|
||||
|
||||
app.static_files[''] = {'filename': 'test.gif'}
|
||||
check_path('/static/test/', 404, 'text/plain', 'Not Found')
|
||||
|
||||
app.static_files = {}
|
||||
check_path('/static/test/index.html', 404, 'text/plain', 'Not Found')
|
||||
|
||||
def test_lifespan_startup(self):
|
||||
app = async_asgi.ASGIApp('eio')
|
||||
scope = {'type': 'lifespan'}
|
||||
receive = AsyncMock(return_value={'type': 'lifespan.startup'})
|
||||
send = AsyncMock()
|
||||
_run(app(scope, receive, send))
|
||||
send.mock.assert_called_once_with(
|
||||
{'type': 'lifespan.startup.complete'})
|
||||
|
||||
def test_lifespan_shutdown(self):
|
||||
app = async_asgi.ASGIApp('eio')
|
||||
scope = {'type': 'lifespan'}
|
||||
receive = AsyncMock(return_value={'type': 'lifespan.shutdown'})
|
||||
send = AsyncMock()
|
||||
_run(app(scope, receive, send))
|
||||
send.mock.assert_called_once_with(
|
||||
{'type': 'lifespan.shutdown.complete'})
|
||||
|
||||
def test_lifespan_invalid(self):
|
||||
app = async_asgi.ASGIApp('eio')
|
||||
scope = {'type': 'lifespan'}
|
||||
receive = AsyncMock(return_value={'type': 'lifespan.foo'})
|
||||
send = AsyncMock()
|
||||
_run(app(scope, receive, send))
|
||||
send.mock.assert_not_called()
|
||||
|
||||
def test_not_found(self):
|
||||
app = async_asgi.ASGIApp('eio')
|
||||
scope = {'type': 'http', 'path': '/foo'}
|
||||
receive = AsyncMock(return_value={'type': 'http.request'})
|
||||
send = AsyncMock()
|
||||
_run(app(scope, receive, send))
|
||||
send.mock.assert_any_call(
|
||||
{'type': 'http.response.start', 'status': 404,
|
||||
'headers': [(b'Content-Type', b'text/plain')]})
|
||||
send.mock.assert_any_call({'type': 'http.response.body',
|
||||
'body': b'Not Found'})
|
||||
|
||||
def test_translate_request(self):
|
||||
receive = AsyncMock(return_value={'type': 'http.request',
|
||||
'body': b'hello world'})
|
||||
send = AsyncMock()
|
||||
environ = _run(async_asgi.translate_request({
|
||||
'type': 'http',
|
||||
'method': 'PUT',
|
||||
'headers': [(b'a', b'b'), (b'c-c', b'd'), (b'c_c', b'e'),
|
||||
(b'content-type', b'application/json'),
|
||||
(b'content-length', b'123')],
|
||||
'path': '/foo/bar',
|
||||
'query_string': b'baz=1'}, receive, send))
|
||||
expected_environ = {
|
||||
'REQUEST_METHOD': 'PUT',
|
||||
'PATH_INFO': '/foo/bar',
|
||||
'QUERY_STRING': 'baz=1',
|
||||
'CONTENT_TYPE': 'application/json',
|
||||
'CONTENT_LENGTH': '123',
|
||||
'HTTP_A': 'b',
|
||||
# 'HTTP_C_C': 'd,e',
|
||||
'RAW_URI': '/foo/bar?baz=1',
|
||||
'SERVER_PROTOCOL': 'HTTP/1.1',
|
||||
'asgi.receive': receive,
|
||||
'asgi.send': send
|
||||
}
|
||||
for k, v in expected_environ.items():
|
||||
self.assertEqual(v, environ[k])
|
||||
self.assertTrue(
|
||||
environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d')
|
||||
body = _run(environ['wsgi.input'].read())
|
||||
self.assertEqual(body, b'hello world')
|
||||
|
||||
def test_translate_request_no_query_string(self):
|
||||
receive = AsyncMock(return_value={'type': 'http.request',
|
||||
'body': b'hello world'})
|
||||
send = AsyncMock()
|
||||
environ = _run(async_asgi.translate_request({
|
||||
'type': 'http',
|
||||
'method': 'PUT',
|
||||
'headers': [(b'a', b'b'), (b'c-c', b'd'), (b'c_c', b'e'),
|
||||
(b'content-type', b'application/json'),
|
||||
(b'content-length', b'123')],
|
||||
'path': '/foo/bar'}, receive, send))
|
||||
expected_environ = {
|
||||
'REQUEST_METHOD': 'PUT',
|
||||
'PATH_INFO': '/foo/bar',
|
||||
'QUERY_STRING': '',
|
||||
'CONTENT_TYPE': 'application/json',
|
||||
'CONTENT_LENGTH': '123',
|
||||
'HTTP_A': 'b',
|
||||
# 'HTTP_C_C': 'd,e',
|
||||
'RAW_URI': '/foo/bar',
|
||||
'SERVER_PROTOCOL': 'HTTP/1.1',
|
||||
'asgi.receive': receive,
|
||||
'asgi.send': send
|
||||
}
|
||||
for k, v in expected_environ.items():
|
||||
self.assertEqual(v, environ[k])
|
||||
self.assertTrue(
|
||||
environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d')
|
||||
body = _run(environ['wsgi.input'].read())
|
||||
self.assertEqual(body, b'hello world')
|
||||
|
||||
def test_translate_request_with_large_body(self):
|
||||
receive = AsyncMock(side_effect=[
|
||||
{'type': 'http.request', 'body': b'hello ', 'more_body': True},
|
||||
{'type': 'http.request', 'body': b'world', 'more_body': True},
|
||||
{'type': 'foo.bar'}, # should stop parsing here
|
||||
{'type': 'http.request', 'body': b'!!!'},
|
||||
])
|
||||
send = AsyncMock()
|
||||
environ = _run(async_asgi.translate_request({
|
||||
'type': 'http',
|
||||
'method': 'PUT',
|
||||
'headers': [(b'a', b'b'), (b'c-c', b'd'), (b'c_c', b'e'),
|
||||
(b'content-type', b'application/json'),
|
||||
(b'content-length', b'123')],
|
||||
'path': '/foo/bar',
|
||||
'query_string': b'baz=1'}, receive, send))
|
||||
expected_environ = {
|
||||
'REQUEST_METHOD': 'PUT',
|
||||
'PATH_INFO': '/foo/bar',
|
||||
'QUERY_STRING': 'baz=1',
|
||||
'CONTENT_TYPE': 'application/json',
|
||||
'CONTENT_LENGTH': '123',
|
||||
'HTTP_A': 'b',
|
||||
# 'HTTP_C_C': 'd,e',
|
||||
'RAW_URI': '/foo/bar?baz=1',
|
||||
'SERVER_PROTOCOL': 'HTTP/1.1',
|
||||
'asgi.receive': receive,
|
||||
'asgi.send': send
|
||||
}
|
||||
for k, v in expected_environ.items():
|
||||
self.assertEqual(v, environ[k])
|
||||
self.assertTrue(
|
||||
environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d')
|
||||
body = _run(environ['wsgi.input'].read())
|
||||
self.assertEqual(body, b'hello world')
|
||||
|
||||
def test_translate_websocket_request(self):
|
||||
receive = AsyncMock(return_value={'type': 'websocket.connect'})
|
||||
send = AsyncMock()
|
||||
_run(async_asgi.translate_request({
|
||||
'type': 'websocket',
|
||||
'headers': [(b'a', b'b'), (b'c-c', b'd'), (b'c_c', b'e'),
|
||||
(b'content-type', b'application/json'),
|
||||
(b'content-length', b'123')],
|
||||
'path': '/foo/bar',
|
||||
'query_string': b'baz=1'}, receive, send))
|
||||
send.mock.assert_called_once_with({'type': 'websocket.accept'})
|
||||
|
||||
def test_translate_unknown_request(self):
|
||||
receive = AsyncMock(return_value={'type': 'http.foo'})
|
||||
send = AsyncMock()
|
||||
environ = _run(async_asgi.translate_request({
|
||||
'type': 'http',
|
||||
'path': '/foo/bar',
|
||||
'query_string': b'baz=1'}, receive, send))
|
||||
self.assertEqual(environ, {})
|
||||
|
||||
# @mock.patch('async_aiohttp.aiohttp.web.Response')
|
||||
def test_make_response(self):
|
||||
environ = {
|
||||
'asgi.send': AsyncMock()
|
||||
}
|
||||
_run(async_asgi.make_response('202 ACCEPTED', [('foo', 'bar')],
|
||||
b'payload', environ))
|
||||
environ['asgi.send'].mock.assert_any_call(
|
||||
{'type': 'http.response.start', 'status': 202,
|
||||
'headers': [(b'foo', b'bar')]})
|
||||
environ['asgi.send'].mock.assert_any_call(
|
||||
{'type': 'http.response.body', 'body': b'payload'})
|
||||
@@ -0,0 +1,76 @@
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
pass
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import six
|
||||
try:
|
||||
import tornado.web
|
||||
except ImportError:
|
||||
pass
|
||||
if six.PY3:
|
||||
from unittest import mock
|
||||
else:
|
||||
import mock
|
||||
|
||||
if sys.version_info >= (3, 5):
|
||||
from engineio.async_drivers import tornado as async_tornado
|
||||
|
||||
|
||||
def _run(coro):
|
||||
"""Run the given coroutine."""
|
||||
return asyncio.get_event_loop().run_until_complete(coro)
|
||||
|
||||
|
||||
@unittest.skipIf(sys.version_info < (3, 5), 'only for Python 3.5+')
|
||||
class TornadoTests(unittest.TestCase):
|
||||
def test_get_tornado_handler(self):
|
||||
mock_server = mock.MagicMock()
|
||||
handler = async_tornado.get_tornado_handler(mock_server)
|
||||
self.assertTrue(issubclass(handler,
|
||||
tornado.websocket.WebSocketHandler))
|
||||
|
||||
def test_translate_request(self):
|
||||
mock_handler = mock.MagicMock()
|
||||
mock_handler.request.method = 'PUT'
|
||||
mock_handler.request.path = '/foo/bar'
|
||||
mock_handler.request.query = 'baz=1'
|
||||
mock_handler.request.version = '1.1'
|
||||
mock_handler.request.headers = {
|
||||
'a': 'b',
|
||||
'c': 'd',
|
||||
'content-type': 'application/json',
|
||||
'content-length': 123
|
||||
}
|
||||
mock_handler.request.body = b'hello world'
|
||||
environ = async_tornado.translate_request(mock_handler)
|
||||
expected_environ = {
|
||||
'REQUEST_METHOD': 'PUT',
|
||||
'PATH_INFO': '/foo/bar',
|
||||
'QUERY_STRING': 'baz=1',
|
||||
'CONTENT_TYPE': 'application/json',
|
||||
'CONTENT_LENGTH': 123,
|
||||
'HTTP_A': 'b',
|
||||
'HTTP_C': 'd',
|
||||
'RAW_URI': '/foo/bar?baz=1',
|
||||
'SERVER_PROTOCOL': 'HTTP/1.1',
|
||||
# 'wsgi.input': b'hello world',
|
||||
'tornado.handler': mock_handler,
|
||||
}
|
||||
for k, v in expected_environ.items():
|
||||
self.assertEqual(v, environ[k])
|
||||
payload = _run(environ['wsgi.input'].read(1))
|
||||
payload += _run(environ['wsgi.input'].read())
|
||||
self.assertEqual(payload, b'hello world')
|
||||
|
||||
def test_make_response(self):
|
||||
mock_handler = mock.MagicMock()
|
||||
mock_environ = {'tornado.handler': mock_handler}
|
||||
async_tornado.make_response('202 ACCEPTED', [('foo', 'bar')],
|
||||
b'payload', mock_environ)
|
||||
mock_handler.set_status.assert_called_once_with(202)
|
||||
mock_handler.set_header.assert_called_once_with('foo', 'bar')
|
||||
mock_handler.write.assert_called_once_with(b'payload')
|
||||
mock_handler.finish.assert_called_once_with()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,919 @@
|
||||
import asyncio
|
||||
import gzip
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
import unittest
|
||||
import zlib
|
||||
|
||||
import six
|
||||
if six.PY3:
|
||||
from unittest import mock
|
||||
else:
|
||||
import mock
|
||||
|
||||
from engineio import asyncio_server
|
||||
from engineio.async_drivers import aiohttp as async_aiohttp
|
||||
from engineio import exceptions
|
||||
from engineio import packet
|
||||
from engineio import payload
|
||||
|
||||
|
||||
def AsyncMock(*args, **kwargs):
|
||||
"""Return a mock asynchronous function."""
|
||||
m = mock.MagicMock(*args, **kwargs)
|
||||
|
||||
async def mock_coro(*args, **kwargs):
|
||||
return m(*args, **kwargs)
|
||||
|
||||
mock_coro.mock = m
|
||||
return mock_coro
|
||||
|
||||
|
||||
def _run(coro):
|
||||
"""Run the given coroutine."""
|
||||
return asyncio.get_event_loop().run_until_complete(coro)
|
||||
|
||||
|
||||
@unittest.skipIf(sys.version_info < (3, 5), 'only for Python 3.5+')
|
||||
class TestAsyncServer(unittest.TestCase):
|
||||
@staticmethod
|
||||
def get_async_mock(environ={'REQUEST_METHOD': 'GET', 'QUERY_STRING': ''}):
|
||||
a = mock.MagicMock()
|
||||
a._async = {
|
||||
'asyncio': True,
|
||||
'create_route': mock.MagicMock(),
|
||||
'translate_request': mock.MagicMock(),
|
||||
'make_response': mock.MagicMock(),
|
||||
'websocket': 'w',
|
||||
}
|
||||
a._async['translate_request'].return_value = environ
|
||||
a._async['make_response'].return_value = 'response'
|
||||
return a
|
||||
|
||||
def _get_mock_socket(self):
|
||||
mock_socket = mock.MagicMock()
|
||||
mock_socket.connected = False
|
||||
mock_socket.closed = False
|
||||
mock_socket.closing = False
|
||||
mock_socket.upgraded = False
|
||||
mock_socket.send = AsyncMock()
|
||||
mock_socket.handle_get_request = AsyncMock()
|
||||
mock_socket.handle_post_request = AsyncMock()
|
||||
mock_socket.check_ping_timeout = AsyncMock()
|
||||
mock_socket.close = AsyncMock()
|
||||
mock_socket.session = {}
|
||||
return mock_socket
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
asyncio_server.AsyncServer._default_monitor_clients = False
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
asyncio_server.AsyncServer._default_monitor_clients = True
|
||||
|
||||
def setUp(self):
|
||||
logging.getLogger('engineio').setLevel(logging.NOTSET)
|
||||
|
||||
def tearDown(self):
|
||||
# restore JSON encoder, in case a test changed it
|
||||
packet.Packet.json = json
|
||||
|
||||
def test_is_asyncio_based(self):
|
||||
s = asyncio_server.AsyncServer()
|
||||
self.assertEqual(s.is_asyncio_based(), True)
|
||||
|
||||
def test_async_modes(self):
|
||||
s = asyncio_server.AsyncServer()
|
||||
self.assertEqual(s.async_modes(), ['aiohttp', 'sanic', 'tornado',
|
||||
'asgi'])
|
||||
|
||||
def test_async_mode_aiohttp(self):
|
||||
s = asyncio_server.AsyncServer(async_mode='aiohttp')
|
||||
self.assertEqual(s.async_mode, 'aiohttp')
|
||||
self.assertEqual(s._async['asyncio'], True)
|
||||
self.assertEqual(s._async['create_route'], async_aiohttp.create_route)
|
||||
self.assertEqual(s._async['translate_request'],
|
||||
async_aiohttp.translate_request)
|
||||
self.assertEqual(s._async['make_response'],
|
||||
async_aiohttp.make_response)
|
||||
self.assertEqual(s._async['websocket'].__name__, 'WebSocket')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_async_mode_auto_aiohttp(self, import_module):
|
||||
import_module.side_effect = [self.get_async_mock()]
|
||||
s = asyncio_server.AsyncServer()
|
||||
self.assertEqual(s.async_mode, 'aiohttp')
|
||||
|
||||
def test_async_modes_wsgi(self):
|
||||
self.assertRaises(ValueError, asyncio_server.AsyncServer,
|
||||
async_mode='eventlet')
|
||||
self.assertRaises(ValueError, asyncio_server.AsyncServer,
|
||||
async_mode='gevent')
|
||||
self.assertRaises(ValueError, asyncio_server.AsyncServer,
|
||||
async_mode='gevent_uwsgi')
|
||||
self.assertRaises(ValueError, asyncio_server.AsyncServer,
|
||||
async_mode='threading')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_attach(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.attach('app', engineio_path='abc')
|
||||
a._async['create_route'].assert_called_with('app', s, '/abc/')
|
||||
s.attach('app', engineio_path='/def/')
|
||||
a._async['create_route'].assert_called_with('app', s, '/def/')
|
||||
s.attach('app', engineio_path='/ghi')
|
||||
a._async['create_route'].assert_called_with('app', s, '/ghi/')
|
||||
s.attach('app', engineio_path='jkl/')
|
||||
a._async['create_route'].assert_called_with('app', s, '/jkl/')
|
||||
|
||||
def test_session(self):
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.sockets['foo'] = self._get_mock_socket()
|
||||
|
||||
async def _func():
|
||||
async with s.session('foo') as session:
|
||||
await s.sleep(0)
|
||||
session['username'] = 'bar'
|
||||
self.assertEqual(await s.get_session('foo'), {'username': 'bar'})
|
||||
|
||||
_run(_func())
|
||||
|
||||
def test_disconnect(self):
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
_run(s.disconnect('foo'))
|
||||
self.assertEqual(mock_socket.close.mock.call_count, 1)
|
||||
mock_socket.close.mock.assert_called_once_with()
|
||||
self.assertNotIn('foo', s.sockets)
|
||||
|
||||
def test_disconnect_all(self):
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.sockets['foo'] = mock_foo = self._get_mock_socket()
|
||||
s.sockets['bar'] = mock_bar = self._get_mock_socket()
|
||||
_run(s.disconnect())
|
||||
self.assertEqual(mock_foo.close.mock.call_count, 1)
|
||||
self.assertEqual(mock_bar.close.mock.call_count, 1)
|
||||
mock_foo.close.mock.assert_called_once_with()
|
||||
mock_bar.close.mock.assert_called_once_with()
|
||||
self.assertNotIn('foo', s.sockets)
|
||||
self.assertNotIn('bar', s.sockets)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_jsonp_not_supported(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'j=abc'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
response = _run(s.handle_request('request'))
|
||||
self.assertEqual(response, 'response')
|
||||
a._async['translate_request'].assert_called_once_with('request')
|
||||
self.assertEqual(a._async['make_response'].call_count, 1)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0],
|
||||
'400 BAD REQUEST')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_jsonp_index(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'j=233'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
response = _run(s.handle_request('request'))
|
||||
self.assertEqual(response, 'response')
|
||||
a._async['translate_request'].assert_called_once_with('request')
|
||||
self.assertEqual(a._async['make_response'].call_count, 1)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0], '200 OK')
|
||||
print('***', a._async['make_response'].call_args[0][2])
|
||||
self.assertTrue(a._async['make_response'].call_args[0][2].startswith(
|
||||
b'___eio[233]("'))
|
||||
self.assertTrue(a._async['make_response'].call_args[0][2].endswith(
|
||||
b'");'))
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(len(s.sockets), 1)
|
||||
self.assertEqual(a._async['make_response'].call_count, 1)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0], '200 OK')
|
||||
self.assertIn(('Content-Type', 'application/octet-stream'),
|
||||
a._async['make_response'].call_args[0][1])
|
||||
packets = payload.Payload(
|
||||
encoded_payload=a._async['make_response'].call_args[0][2]).packets
|
||||
self.assertEqual(len(packets), 1)
|
||||
self.assertEqual(packets[0].packet_type, packet.OPEN)
|
||||
self.assertIn('upgrades', packets[0].data)
|
||||
self.assertEqual(packets[0].data['upgrades'], ['websocket'])
|
||||
self.assertIn('sid', packets[0].data)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_async_request_response_handlers(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
a._async['translate_request'] = AsyncMock(
|
||||
return_value=a._async['translate_request'].return_value)
|
||||
a._async['make_response'] = AsyncMock(
|
||||
return_value=a._async['make_response'].return_value)
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(len(s.sockets), 1)
|
||||
self.assertEqual(a._async['make_response'].mock.call_count, 1)
|
||||
self.assertEqual(a._async['make_response'].mock.call_args[0][0],
|
||||
'200 OK')
|
||||
self.assertIn(('Content-Type', 'application/octet-stream'),
|
||||
a._async['make_response'].mock.call_args[0][1])
|
||||
packets = payload.Payload(encoded_payload=a._async[
|
||||
'make_response'].mock.call_args[0][2]).packets
|
||||
self.assertEqual(len(packets), 1)
|
||||
self.assertEqual(packets[0].packet_type, packet.OPEN)
|
||||
self.assertIn('upgrades', packets[0].data)
|
||||
self.assertEqual(packets[0].data['upgrades'], ['websocket'])
|
||||
self.assertIn('sid', packets[0].data)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_no_upgrades(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(allow_upgrades=False)
|
||||
_run(s.handle_request('request'))
|
||||
packets = payload.Payload(
|
||||
encoded_payload=a._async['make_response'].call_args[0][2]).packets
|
||||
self.assertEqual(packets[0].data['upgrades'], [])
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_b64_with_1(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'b64=1'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(allow_upgrades=False)
|
||||
s._generate_id = mock.MagicMock(return_value='1')
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_count, 1)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0], '200 OK')
|
||||
self.assertIn(('Content-Type', 'text/plain; charset=UTF-8'),
|
||||
a._async['make_response'].call_args[0][1])
|
||||
_run(s.send('1', b'\x00\x01\x02', binary=True))
|
||||
a._async['translate_request'].return_value = {
|
||||
'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=1&b64=1'}
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_args[0][2],
|
||||
b'6:b4AAEC')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_b64_with_true(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'b64=true'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(allow_upgrades=False)
|
||||
s._generate_id = mock.MagicMock(return_value='1')
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_count, 1)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0], '200 OK')
|
||||
self.assertIn(('Content-Type', 'text/plain; charset=UTF-8'),
|
||||
a._async['make_response'].call_args[0][1])
|
||||
_run(s.send('1', b'\x00\x01\x02', binary=True))
|
||||
a._async['translate_request'].return_value = {
|
||||
'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=1&b64=true'}
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_args[0][2],
|
||||
b'6:b4AAEC')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_b64_with_0(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'b64=0'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(allow_upgrades=False)
|
||||
s._generate_id = mock.MagicMock(return_value='1')
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_count, 1)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0], '200 OK')
|
||||
self.assertIn(('Content-Type', 'application/octet-stream'),
|
||||
a._async['make_response'].call_args[0][1])
|
||||
_run(s.send('1', b'\x00\x01\x02', binary=True))
|
||||
a._async['translate_request'].return_value = {
|
||||
'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=1&b64=0'}
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_args[0][2],
|
||||
b'\x01\x04\xff\x04\x00\x01\x02')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_b64_with_false(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'b64=false'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(allow_upgrades=False)
|
||||
s._generate_id = mock.MagicMock(return_value='1')
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_count, 1)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0], '200 OK')
|
||||
self.assertIn(('Content-Type', 'application/octet-stream'),
|
||||
a._async['make_response'].call_args[0][1])
|
||||
_run(s.send('1', b'\x00\x01\x02', binary=True))
|
||||
a._async['translate_request'].return_value = {
|
||||
'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=1&b64=false'}
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_args[0][2],
|
||||
b'\x01\x04\xff\x04\x00\x01\x02')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_custom_ping_times(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(ping_timeout=123, ping_interval=456)
|
||||
_run(s.handle_request('request'))
|
||||
packets = payload.Payload(
|
||||
encoded_payload=a._async['make_response'].call_args[0][2]).packets
|
||||
self.assertEqual(packets[0].data['pingTimeout'], 123000)
|
||||
self.assertEqual(packets[0].data['pingInterval'], 456000)
|
||||
|
||||
@mock.patch('engineio.asyncio_socket.AsyncSocket')
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_bad_poll(self, import_module, AsyncSocket):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
AsyncSocket.return_value = self._get_mock_socket()
|
||||
AsyncSocket.return_value.poll.side_effect = [exceptions.QueueEmpty]
|
||||
s = asyncio_server.AsyncServer()
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_count, 1)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0],
|
||||
'400 BAD REQUEST')
|
||||
|
||||
@mock.patch('engineio.asyncio_socket.AsyncSocket')
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_transport_websocket(self, import_module, AsyncSocket):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'transport=websocket'})
|
||||
import_module.side_effect = [a]
|
||||
AsyncSocket.return_value = self._get_mock_socket()
|
||||
s = asyncio_server.AsyncServer()
|
||||
s._generate_id = mock.MagicMock(return_value='123')
|
||||
# force socket to stay open, so that we can check it later
|
||||
AsyncSocket().closed = False
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(
|
||||
s.sockets['123'].send.mock.call_args[0][0].packet_type,
|
||||
packet.OPEN)
|
||||
|
||||
@mock.patch('engineio.asyncio_socket.AsyncSocket')
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_transport_websocket_closed(self, import_module,
|
||||
AsyncSocket):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'transport=websocket'})
|
||||
import_module.side_effect = [a]
|
||||
AsyncSocket.return_value = self._get_mock_socket()
|
||||
s = asyncio_server.AsyncServer()
|
||||
s._generate_id = mock.MagicMock(return_value='123')
|
||||
|
||||
# this mock handler just closes the socket, as it would happen on a
|
||||
# real websocket exchange
|
||||
async def mock_handle(environ):
|
||||
s.sockets['123'].closed = True
|
||||
|
||||
AsyncSocket().handle_get_request = mock_handle
|
||||
_run(s.handle_request('request'))
|
||||
self.assertNotIn('123', s.sockets) # socket should close on its own
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_transport_invalid(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'transport=foo'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_count, 1)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0],
|
||||
'400 BAD REQUEST')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_cors_headers(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
self.assertIn(('Access-Control-Allow-Origin', '*'), headers)
|
||||
self.assertIn(('Access-Control-Allow-Credentials', 'true'), headers)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_cors_allowed_origin(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET', 'QUERY_STRING': '',
|
||||
'HTTP_ORIGIN': 'b'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(cors_allowed_origins=['a', 'b'])
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
self.assertIn(('Access-Control-Allow-Origin', 'b'), headers)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_cors_not_allowed_origin(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET', 'QUERY_STRING': '',
|
||||
'HTTP_ORIGIN': 'c'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(cors_allowed_origins=['a', 'b'])
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
self.assertNotIn(('Access-Control-Allow-Origin', 'c'), headers)
|
||||
self.assertNotIn(('Access-Control-Allow-Origin', '*'), headers)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_cors_no_credentials(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(cors_credentials=False)
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
self.assertNotIn(('Access-Control-Allow-Credentials', 'true'), headers)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_cors_options(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'OPTIONS',
|
||||
'QUERY_STRING': ''})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(cors_credentials=False)
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
self.assertIn(('Access-Control-Allow-Methods',
|
||||
'OPTIONS, GET, POST'), headers)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_event(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
s._generate_id = mock.MagicMock(return_value='123')
|
||||
|
||||
def mock_connect(sid, environ):
|
||||
return True
|
||||
|
||||
s.on('connect', handler=mock_connect)
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(len(s.sockets), 1)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_connect_event_rejects(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
s._generate_id = mock.MagicMock(return_value='123')
|
||||
|
||||
def mock_connect(sid, environ):
|
||||
return False
|
||||
|
||||
s.on('connect')(mock_connect)
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(len(s.sockets), 0)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0],
|
||||
'401 UNAUTHORIZED')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_method_not_found(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'PUT', 'QUERY_STRING': ''})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(len(s.sockets), 0)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0],
|
||||
'405 METHOD NOT FOUND')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_get_request_with_bad_sid(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(len(s.sockets), 0)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0],
|
||||
'400 BAD REQUEST')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_post_request_with_bad_sid(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'POST',
|
||||
'QUERY_STRING': 'sid=foo'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(len(s.sockets), 0)
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0],
|
||||
'400 BAD REQUEST')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_send(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
_run(s.send('foo', 'hello'))
|
||||
self.assertEqual(mock_socket.send.mock.call_count, 1)
|
||||
self.assertEqual(mock_socket.send.mock.call_args[0][0].packet_type,
|
||||
packet.MESSAGE)
|
||||
self.assertEqual(mock_socket.send.mock.call_args[0][0].data, 'hello')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_send_unknown_socket(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
# just ensure no exceptions are raised
|
||||
_run(s.send('foo', 'hello'))
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_get_request(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
mock_socket.handle_get_request.mock.return_value = \
|
||||
[packet.Packet(packet.MESSAGE, data='hello')]
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0], '200 OK')
|
||||
packets = payload.Payload(
|
||||
encoded_payload=a._async['make_response'].call_args[0][2]).packets
|
||||
self.assertEqual(len(packets), 1)
|
||||
self.assertEqual(packets[0].packet_type, packet.MESSAGE)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_get_request_custom_response(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
mock_socket.handle_get_request.mock.return_value = 'resp'
|
||||
r = _run(s.handle_request('request'))
|
||||
self.assertEqual(r, 'resp')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_get_request_closes_socket(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
|
||||
async def mock_get_request(*args, **kwargs):
|
||||
mock_socket.closed = True
|
||||
return 'resp'
|
||||
|
||||
mock_socket.handle_get_request = mock_get_request
|
||||
r = _run(s.handle_request('request'))
|
||||
self.assertEqual(r, 'resp')
|
||||
self.assertNotIn('foo', s.sockets)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_get_request_error(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
|
||||
async def mock_get_request(*args, **kwargs):
|
||||
raise exceptions.QueueEmpty()
|
||||
|
||||
mock_socket.handle_get_request = mock_get_request
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0],
|
||||
'400 BAD REQUEST')
|
||||
self.assertEqual(len(s.sockets), 0)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_post_request(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'POST',
|
||||
'QUERY_STRING': 'sid=foo'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.sockets['foo'] = self._get_mock_socket()
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0], '200 OK')
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_post_request_error(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'POST',
|
||||
'QUERY_STRING': 'sid=foo'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
|
||||
async def mock_post_request(*args, **kwargs):
|
||||
raise exceptions.ContentTooLongError()
|
||||
|
||||
mock_socket.handle_post_request = mock_post_request
|
||||
_run(s.handle_request('request'))
|
||||
self.assertEqual(a._async['make_response'].call_args[0][0],
|
||||
'400 BAD REQUEST')
|
||||
|
||||
@staticmethod
|
||||
def _gzip_decompress(b):
|
||||
bytesio = six.BytesIO(b)
|
||||
with gzip.GzipFile(fileobj=bytesio, mode='r') as gz:
|
||||
return gz.read()
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_gzip_compression(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo',
|
||||
'HTTP_ACCEPT_ENCODING': 'gzip,deflate'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(compression_threshold=0)
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
mock_socket.handle_get_request.mock.return_value = \
|
||||
[packet.Packet(packet.MESSAGE, data='hello')]
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
self.assertIn(('Content-Encoding', 'gzip'), headers)
|
||||
self._gzip_decompress(a._async['make_response'].call_args[0][2])
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_deflate_compression(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo',
|
||||
'HTTP_ACCEPT_ENCODING': 'deflate;q=1,gzip'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(compression_threshold=0)
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
mock_socket.handle_get_request.mock.return_value = \
|
||||
[packet.Packet(packet.MESSAGE, data='hello')]
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
self.assertIn(('Content-Encoding', 'deflate'), headers)
|
||||
zlib.decompress(a._async['make_response'].call_args[0][2])
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_gzip_compression_threshold(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo',
|
||||
'HTTP_ACCEPT_ENCODING': 'gzip'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(compression_threshold=1000)
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
mock_socket.handle_get_request.mock.return_value = \
|
||||
[packet.Packet(packet.MESSAGE, data='hello')]
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
for header, value in headers:
|
||||
self.assertNotEqual(header, 'Content-Encoding')
|
||||
self.assertRaises(IOError, self._gzip_decompress,
|
||||
a._async['make_response'].call_args[0][2])
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_compression_disabled(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo',
|
||||
'HTTP_ACCEPT_ENCODING': 'gzip'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(http_compression=False,
|
||||
compression_threshold=0)
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
mock_socket.handle_get_request.mock.return_value = \
|
||||
[packet.Packet(packet.MESSAGE, data='hello')]
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
for header, value in headers:
|
||||
self.assertNotEqual(header, 'Content-Encoding')
|
||||
self.assertRaises(IOError, self._gzip_decompress,
|
||||
a._async['make_response'].call_args[0][2])
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_compression_unknown(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo',
|
||||
'HTTP_ACCEPT_ENCODING': 'rar'})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(compression_threshold=0)
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
mock_socket.handle_get_request.mock.return_value = \
|
||||
[packet.Packet(packet.MESSAGE, data='hello')]
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
for header, value in headers:
|
||||
self.assertNotEqual(header, 'Content-Encoding')
|
||||
self.assertRaises(IOError, self._gzip_decompress,
|
||||
a._async['make_response'].call_args[0][2])
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_compression_no_encoding(self, import_module):
|
||||
a = self.get_async_mock({'REQUEST_METHOD': 'GET',
|
||||
'QUERY_STRING': 'sid=foo',
|
||||
'HTTP_ACCEPT_ENCODING': ''})
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(compression_threshold=0)
|
||||
s.sockets['foo'] = mock_socket = self._get_mock_socket()
|
||||
mock_socket.handle_get_request.mock.return_value = \
|
||||
[packet.Packet(packet.MESSAGE, data='hello')]
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
for header, value in headers:
|
||||
self.assertNotEqual(header, 'Content-Encoding')
|
||||
self.assertRaises(IOError, self._gzip_decompress,
|
||||
a._async['make_response'].call_args[0][2])
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_cookie(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(cookie='sid')
|
||||
s._generate_id = mock.MagicMock(return_value='123')
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
self.assertIn(('Set-Cookie', 'sid=123'), headers)
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_no_cookie(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(cookie=None)
|
||||
s._generate_id = mock.MagicMock(return_value='123')
|
||||
_run(s.handle_request('request'))
|
||||
headers = a._async['make_response'].call_args[0][1]
|
||||
for header, value in headers:
|
||||
self.assertNotEqual(header, 'Set-Cookie')
|
||||
|
||||
def test_logger(self):
|
||||
s = asyncio_server.AsyncServer(logger=False)
|
||||
self.assertEqual(s.logger.getEffectiveLevel(), logging.ERROR)
|
||||
s.logger.setLevel(logging.NOTSET)
|
||||
s = asyncio_server.AsyncServer(logger=True)
|
||||
self.assertEqual(s.logger.getEffectiveLevel(), logging.INFO)
|
||||
s.logger.setLevel(logging.WARNING)
|
||||
s = asyncio_server.AsyncServer(logger=True)
|
||||
self.assertEqual(s.logger.getEffectiveLevel(), logging.WARNING)
|
||||
s.logger.setLevel(logging.NOTSET)
|
||||
my_logger = logging.Logger('foo')
|
||||
s = asyncio_server.AsyncServer(logger=my_logger)
|
||||
self.assertEqual(s.logger, my_logger)
|
||||
|
||||
def test_custom_json(self):
|
||||
# Warning: this test cannot run in parallel with other tests, as it
|
||||
# changes the JSON encoding/decoding functions
|
||||
|
||||
class CustomJSON(object):
|
||||
@staticmethod
|
||||
def dumps(*args, **kwargs):
|
||||
return '*** encoded ***'
|
||||
|
||||
@staticmethod
|
||||
def loads(*args, **kwargs):
|
||||
return '+++ decoded +++'
|
||||
|
||||
asyncio_server.AsyncServer(json=CustomJSON)
|
||||
pkt = packet.Packet(packet.MESSAGE, data={'foo': 'bar'})
|
||||
self.assertEqual(pkt.encode(), b'4*** encoded ***')
|
||||
pkt2 = packet.Packet(encoded_packet=pkt.encode())
|
||||
self.assertEqual(pkt2.data, '+++ decoded +++')
|
||||
|
||||
# restore the default JSON module
|
||||
packet.Packet.json = json
|
||||
|
||||
def test_background_tasks(self):
|
||||
r = []
|
||||
|
||||
async def foo(arg):
|
||||
r.append(arg)
|
||||
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.start_background_task(foo, 'bar')
|
||||
pending = asyncio.Task.all_tasks()
|
||||
asyncio.get_event_loop().run_until_complete(asyncio.wait(pending))
|
||||
self.assertEqual(r, ['bar'])
|
||||
|
||||
def test_sleep(self):
|
||||
s = asyncio_server.AsyncServer()
|
||||
_run(s.sleep(0))
|
||||
|
||||
def test_trigger_event_function(self):
|
||||
result = []
|
||||
|
||||
def foo_handler(arg):
|
||||
result.append('ok')
|
||||
result.append(arg)
|
||||
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.on('message', handler=foo_handler)
|
||||
_run(s._trigger_event('message', 'bar'))
|
||||
self.assertEqual(result, ['ok', 'bar'])
|
||||
|
||||
def test_trigger_event_coroutine(self):
|
||||
result = []
|
||||
|
||||
async def foo_handler(arg):
|
||||
result.append('ok')
|
||||
result.append(arg)
|
||||
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.on('message', handler=foo_handler)
|
||||
_run(s._trigger_event('message', 'bar'))
|
||||
self.assertEqual(result, ['ok', 'bar'])
|
||||
|
||||
def test_trigger_event_function_error(self):
|
||||
def connect_handler(arg):
|
||||
return 1 / 0
|
||||
|
||||
def foo_handler(arg):
|
||||
return 1 / 0
|
||||
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.on('connect', handler=connect_handler)
|
||||
s.on('message', handler=foo_handler)
|
||||
self.assertFalse(_run(s._trigger_event('connect', '123')))
|
||||
self.assertIsNone(_run(s._trigger_event('message', 'bar')))
|
||||
|
||||
def test_trigger_event_coroutine_error(self):
|
||||
async def connect_handler(arg):
|
||||
return 1 / 0
|
||||
|
||||
async def foo_handler(arg):
|
||||
return 1 / 0
|
||||
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.on('connect', handler=connect_handler)
|
||||
s.on('message', handler=foo_handler)
|
||||
self.assertFalse(_run(s._trigger_event('connect', '123')))
|
||||
self.assertIsNone(_run(s._trigger_event('message', 'bar')))
|
||||
|
||||
def test_trigger_event_function_async(self):
|
||||
result = []
|
||||
|
||||
def foo_handler(arg):
|
||||
result.append('ok')
|
||||
result.append(arg)
|
||||
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.on('message', handler=foo_handler)
|
||||
fut = _run(s._trigger_event('message', 'bar', run_async=True))
|
||||
asyncio.get_event_loop().run_until_complete(fut)
|
||||
self.assertEqual(result, ['ok', 'bar'])
|
||||
|
||||
def test_trigger_event_coroutine_async(self):
|
||||
result = []
|
||||
|
||||
async def foo_handler(arg):
|
||||
result.append('ok')
|
||||
result.append(arg)
|
||||
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.on('message', handler=foo_handler)
|
||||
fut = _run(s._trigger_event('message', 'bar', run_async=True))
|
||||
asyncio.get_event_loop().run_until_complete(fut)
|
||||
self.assertEqual(result, ['ok', 'bar'])
|
||||
|
||||
def test_trigger_event_function_async_error(self):
|
||||
result = []
|
||||
|
||||
def foo_handler(arg):
|
||||
result.append(arg)
|
||||
return 1 / 0
|
||||
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.on('message', handler=foo_handler)
|
||||
fut = _run(s._trigger_event('message', 'bar', run_async=True))
|
||||
self.assertRaises(
|
||||
ZeroDivisionError, asyncio.get_event_loop().run_until_complete,
|
||||
fut)
|
||||
self.assertEqual(result, ['bar'])
|
||||
|
||||
def test_trigger_event_coroutine_async_error(self):
|
||||
result = []
|
||||
|
||||
async def foo_handler(arg):
|
||||
result.append(arg)
|
||||
return 1 / 0
|
||||
|
||||
s = asyncio_server.AsyncServer()
|
||||
s.on('message', handler=foo_handler)
|
||||
fut = _run(s._trigger_event('message', 'bar', run_async=True))
|
||||
self.assertRaises(
|
||||
ZeroDivisionError, asyncio.get_event_loop().run_until_complete,
|
||||
fut)
|
||||
self.assertEqual(result, ['bar'])
|
||||
|
||||
def test_create_queue(self):
|
||||
s = asyncio_server.AsyncServer()
|
||||
q = s.create_queue()
|
||||
empty = s.get_queue_empty_exception()
|
||||
self.assertRaises(empty, q.get_nowait)
|
||||
|
||||
def test_create_event(self):
|
||||
s = asyncio_server.AsyncServer()
|
||||
e = s.create_event()
|
||||
self.assertFalse(e.is_set())
|
||||
e.set()
|
||||
self.assertTrue(e.is_set())
|
||||
|
||||
@mock.patch('importlib.import_module')
|
||||
def test_service_task_started(self, import_module):
|
||||
a = self.get_async_mock()
|
||||
import_module.side_effect = [a]
|
||||
s = asyncio_server.AsyncServer(monitor_clients=True)
|
||||
s._service_task = AsyncMock()
|
||||
_run(s.handle_request('request'))
|
||||
s._service_task.mock.assert_called_once_with()
|
||||
@@ -0,0 +1,441 @@
|
||||
import asyncio
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
|
||||
import six
|
||||
if six.PY3:
|
||||
from unittest import mock
|
||||
else:
|
||||
import mock
|
||||
|
||||
from engineio import asyncio_socket
|
||||
from engineio import exceptions
|
||||
from engineio import packet
|
||||
from engineio import payload
|
||||
|
||||
|
||||
def AsyncMock(*args, **kwargs):
|
||||
"""Return a mock asynchronous function."""
|
||||
m = mock.MagicMock(*args, **kwargs)
|
||||
|
||||
async def mock_coro(*args, **kwargs):
|
||||
return m(*args, **kwargs)
|
||||
|
||||
mock_coro.mock = m
|
||||
return mock_coro
|
||||
|
||||
|
||||
def _run(coro):
|
||||
"""Run the given coroutine."""
|
||||
return asyncio.get_event_loop().run_until_complete(coro)
|
||||
|
||||
|
||||
@unittest.skipIf(sys.version_info < (3, 5), 'only for Python 3.5+')
|
||||
class TestSocket(unittest.TestCase):
|
||||
def _get_read_mock_coro(self, payload):
|
||||
mock_input = mock.MagicMock()
|
||||
mock_input.read = AsyncMock()
|
||||
mock_input.read.mock.return_value = payload
|
||||
return mock_input
|
||||
|
||||
def _get_mock_server(self):
|
||||
mock_server = mock.Mock()
|
||||
mock_server.ping_timeout = 0.2
|
||||
mock_server.ping_interval = 0.2
|
||||
mock_server.async_handlers = False
|
||||
mock_server._async = {'asyncio': True,
|
||||
'create_route': mock.MagicMock(),
|
||||
'translate_request': mock.MagicMock(),
|
||||
'make_response': mock.MagicMock(),
|
||||
'websocket': 'w'}
|
||||
mock_server._async['translate_request'].return_value = 'request'
|
||||
mock_server._async['make_response'].return_value = 'response'
|
||||
mock_server._trigger_event = AsyncMock()
|
||||
|
||||
def create_queue(*args, **kwargs):
|
||||
queue = asyncio.Queue(*args, **kwargs)
|
||||
queue.Empty = asyncio.QueueEmpty
|
||||
return queue
|
||||
|
||||
mock_server.create_queue = create_queue
|
||||
return mock_server
|
||||
|
||||
def test_create(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
self.assertEqual(s.server, mock_server)
|
||||
self.assertEqual(s.sid, 'sid')
|
||||
self.assertFalse(s.upgraded)
|
||||
self.assertFalse(s.closed)
|
||||
self.assertTrue(hasattr(s.queue, 'get'))
|
||||
self.assertTrue(hasattr(s.queue, 'put'))
|
||||
self.assertTrue(hasattr(s.queue, 'task_done'))
|
||||
self.assertTrue(hasattr(s.queue, 'join'))
|
||||
|
||||
def test_empty_poll(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
self.assertRaises(exceptions.QueueEmpty, _run, s.poll())
|
||||
|
||||
def test_poll(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
pkt1 = packet.Packet(packet.MESSAGE, data='hello')
|
||||
pkt2 = packet.Packet(packet.MESSAGE, data='bye')
|
||||
_run(s.send(pkt1))
|
||||
_run(s.send(pkt2))
|
||||
self.assertEqual(_run(s.poll()), [pkt1, pkt2])
|
||||
|
||||
def test_poll_none(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
_run(s.queue.put(None))
|
||||
self.assertEqual(_run(s.poll()), [])
|
||||
|
||||
def test_ping_pong(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
_run(s.receive(packet.Packet(packet.PING, data='abc')))
|
||||
r = _run(s.poll())
|
||||
self.assertEqual(len(r), 1)
|
||||
self.assertTrue(r[0].encode(), b'3abc')
|
||||
|
||||
def test_message_sync_handler(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
_run(s.receive(packet.Packet(packet.MESSAGE, data='foo')))
|
||||
mock_server._trigger_event.mock.assert_called_once_with(
|
||||
'message', 'sid', 'foo', run_async=False)
|
||||
|
||||
def test_message_async_handler(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
mock_server.async_handlers = True
|
||||
_run(s.receive(packet.Packet(packet.MESSAGE, data='foo')))
|
||||
mock_server._trigger_event.mock.assert_called_once_with(
|
||||
'message', 'sid', 'foo', run_async=True)
|
||||
|
||||
def test_invalid_packet(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
self.assertRaises(exceptions.UnknownPacketError, _run,
|
||||
s.receive(packet.Packet(packet.OPEN)))
|
||||
|
||||
def test_timeout(self):
|
||||
mock_server = self._get_mock_server()
|
||||
mock_server.ping_interval = -6
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.last_ping = time.time() - 1
|
||||
s.close = AsyncMock()
|
||||
_run(s.send('packet'))
|
||||
s.close.mock.assert_called_once_with(wait=False, abort=False)
|
||||
|
||||
def test_polling_read(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'foo')
|
||||
pkt1 = packet.Packet(packet.MESSAGE, data='hello')
|
||||
pkt2 = packet.Packet(packet.MESSAGE, data='bye')
|
||||
_run(s.send(pkt1))
|
||||
_run(s.send(pkt2))
|
||||
environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}
|
||||
packets = _run(s.handle_get_request(environ))
|
||||
self.assertEqual(packets, [pkt1, pkt2])
|
||||
|
||||
def test_polling_read_error(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'foo')
|
||||
environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}
|
||||
self.assertRaises(exceptions.QueueEmpty, _run,
|
||||
s.handle_get_request(environ))
|
||||
|
||||
def test_polling_write(self):
|
||||
mock_server = self._get_mock_server()
|
||||
mock_server.max_http_buffer_size = 1000
|
||||
pkt1 = packet.Packet(packet.MESSAGE, data='hello')
|
||||
pkt2 = packet.Packet(packet.MESSAGE, data='bye')
|
||||
p = payload.Payload(packets=[pkt1, pkt2]).encode()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'foo')
|
||||
s.receive = AsyncMock()
|
||||
environ = {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'sid=foo',
|
||||
'CONTENT_LENGTH': len(p),
|
||||
'wsgi.input': self._get_read_mock_coro(p)}
|
||||
_run(s.handle_post_request(environ))
|
||||
self.assertEqual(s.receive.mock.call_count, 2)
|
||||
|
||||
def test_polling_write_too_large(self):
|
||||
mock_server = self._get_mock_server()
|
||||
pkt1 = packet.Packet(packet.MESSAGE, data='hello')
|
||||
pkt2 = packet.Packet(packet.MESSAGE, data='bye')
|
||||
p = payload.Payload(packets=[pkt1, pkt2]).encode()
|
||||
mock_server.max_http_buffer_size = len(p) - 1
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'foo')
|
||||
s.receive = AsyncMock()
|
||||
environ = {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'sid=foo',
|
||||
'CONTENT_LENGTH': len(p),
|
||||
'wsgi.input': self._get_read_mock_coro(p)}
|
||||
self.assertRaises(exceptions.ContentTooLongError, _run,
|
||||
s.handle_post_request(environ))
|
||||
|
||||
def test_upgrade_handshake(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'foo')
|
||||
s._upgrade_websocket = AsyncMock()
|
||||
environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo',
|
||||
'HTTP_CONNECTION': 'Foo,Upgrade,Bar',
|
||||
'HTTP_UPGRADE': 'websocket'}
|
||||
_run(s.handle_get_request(environ))
|
||||
s._upgrade_websocket.mock.assert_called_once_with(environ)
|
||||
|
||||
def test_upgrade(self):
|
||||
mock_server = self._get_mock_server()
|
||||
mock_server._async['websocket'] = mock.MagicMock()
|
||||
mock_ws = AsyncMock()
|
||||
mock_server._async['websocket'].return_value = mock_ws
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = True
|
||||
environ = "foo"
|
||||
_run(s._upgrade_websocket(environ))
|
||||
mock_server._async['websocket'].assert_called_once_with(
|
||||
s._websocket_handler)
|
||||
mock_ws.mock.assert_called_once_with(environ)
|
||||
|
||||
def test_upgrade_twice(self):
|
||||
mock_server = self._get_mock_server()
|
||||
mock_server._async['websocket'] = mock.MagicMock()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = True
|
||||
s.upgraded = True
|
||||
environ = "foo"
|
||||
self.assertRaises(IOError, _run, s._upgrade_websocket(environ))
|
||||
|
||||
def test_upgrade_packet(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = True
|
||||
_run(s.receive(packet.Packet(packet.UPGRADE)))
|
||||
r = _run(s.poll())
|
||||
self.assertEqual(len(r), 1)
|
||||
self.assertEqual(r[0].encode(), packet.Packet(packet.NOOP).encode())
|
||||
|
||||
def test_upgrade_no_probe(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = True
|
||||
ws = mock.MagicMock()
|
||||
ws.wait = AsyncMock()
|
||||
ws.wait.mock.return_value = packet.Packet(packet.NOOP).encode(
|
||||
always_bytes=False)
|
||||
_run(s._websocket_handler(ws))
|
||||
self.assertFalse(s.upgraded)
|
||||
|
||||
def test_upgrade_no_upgrade_packet(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = True
|
||||
s.queue.join = AsyncMock(return_value=None)
|
||||
ws = mock.MagicMock()
|
||||
ws.send = AsyncMock()
|
||||
ws.wait = AsyncMock()
|
||||
probe = six.text_type('probe')
|
||||
ws.wait.mock.side_effect = [
|
||||
packet.Packet(packet.PING, data=probe).encode(
|
||||
always_bytes=False),
|
||||
packet.Packet(packet.NOOP).encode(always_bytes=False)]
|
||||
_run(s._websocket_handler(ws))
|
||||
ws.send.mock.assert_called_once_with(packet.Packet(
|
||||
packet.PONG, data=probe).encode(always_bytes=False))
|
||||
self.assertEqual(_run(s.queue.get()).packet_type, packet.NOOP)
|
||||
self.assertFalse(s.upgraded)
|
||||
|
||||
def test_upgrade_not_supported(self):
|
||||
mock_server = self._get_mock_server()
|
||||
mock_server._async['websocket'] = None
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = True
|
||||
environ = "foo"
|
||||
_run(s._upgrade_websocket(environ))
|
||||
mock_server._bad_request.assert_called_once_with()
|
||||
|
||||
def test_close_packet(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = True
|
||||
s.close = AsyncMock()
|
||||
_run(s.receive(packet.Packet(packet.CLOSE)))
|
||||
s.close.mock.assert_called_once_with(wait=False, abort=True)
|
||||
|
||||
def test_websocket_read_write(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = False
|
||||
s.queue.join = AsyncMock(return_value=None)
|
||||
foo = six.text_type('foo')
|
||||
bar = six.text_type('bar')
|
||||
s.poll = AsyncMock(side_effect=[
|
||||
[packet.Packet(packet.MESSAGE, data=bar)], None])
|
||||
ws = mock.MagicMock()
|
||||
ws.send = AsyncMock()
|
||||
ws.wait = AsyncMock()
|
||||
ws.wait.mock.side_effect = [
|
||||
packet.Packet(packet.MESSAGE, data=foo).encode(
|
||||
always_bytes=False),
|
||||
None]
|
||||
_run(s._websocket_handler(ws))
|
||||
self.assertTrue(s.connected)
|
||||
self.assertTrue(s.upgraded)
|
||||
self.assertEqual(mock_server._trigger_event.mock.call_count, 2)
|
||||
mock_server._trigger_event.mock.assert_has_calls([
|
||||
mock.call('message', 'sid', 'foo', run_async=False),
|
||||
mock.call('disconnect', 'sid')])
|
||||
ws.send.mock.assert_called_with('4bar')
|
||||
|
||||
def test_websocket_upgrade_read_write(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = True
|
||||
s.queue.join = AsyncMock(return_value=None)
|
||||
foo = six.text_type('foo')
|
||||
bar = six.text_type('bar')
|
||||
probe = six.text_type('probe')
|
||||
s.poll = AsyncMock(side_effect=[
|
||||
[packet.Packet(packet.MESSAGE, data=bar)], exceptions.QueueEmpty])
|
||||
ws = mock.MagicMock()
|
||||
ws.send = AsyncMock()
|
||||
ws.wait = AsyncMock()
|
||||
ws.wait.mock.side_effect = [
|
||||
packet.Packet(packet.PING, data=probe).encode(
|
||||
always_bytes=False),
|
||||
packet.Packet(packet.UPGRADE).encode(always_bytes=False),
|
||||
packet.Packet(packet.MESSAGE, data=foo).encode(
|
||||
always_bytes=False),
|
||||
None]
|
||||
_run(s._websocket_handler(ws))
|
||||
self.assertTrue(s.upgraded)
|
||||
self.assertEqual(mock_server._trigger_event.mock.call_count, 2)
|
||||
mock_server._trigger_event.mock.assert_has_calls([
|
||||
mock.call('message', 'sid', 'foo', run_async=False),
|
||||
mock.call('disconnect', 'sid')])
|
||||
ws.send.mock.assert_called_with('4bar')
|
||||
|
||||
def test_websocket_upgrade_with_payload(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = True
|
||||
s.queue.join = AsyncMock(return_value=None)
|
||||
probe = six.text_type('probe')
|
||||
ws = mock.MagicMock()
|
||||
ws.send = AsyncMock()
|
||||
ws.wait = AsyncMock()
|
||||
ws.wait.mock.side_effect = [
|
||||
packet.Packet(packet.PING, data=probe).encode(
|
||||
always_bytes=False),
|
||||
packet.Packet(packet.UPGRADE, data=b'2').encode(
|
||||
always_bytes=False)]
|
||||
_run(s._websocket_handler(ws))
|
||||
self.assertTrue(s.upgraded)
|
||||
|
||||
def test_websocket_upgrade_with_backlog(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = True
|
||||
s.queue.join = AsyncMock(return_value=None)
|
||||
probe = six.text_type('probe')
|
||||
foo = six.text_type('foo')
|
||||
ws = mock.MagicMock()
|
||||
ws.send = AsyncMock()
|
||||
ws.wait = AsyncMock()
|
||||
ws.wait.mock.side_effect = [
|
||||
packet.Packet(packet.PING, data=probe).encode(
|
||||
always_bytes=False),
|
||||
packet.Packet(packet.UPGRADE, data=b'2').encode(
|
||||
always_bytes=False)]
|
||||
s.upgrading = True
|
||||
_run(s.send(packet.Packet(packet.MESSAGE, data=foo)))
|
||||
_run(s._websocket_handler(ws))
|
||||
self.assertTrue(s.upgraded)
|
||||
self.assertFalse(s.upgrading)
|
||||
self.assertEqual(s.packet_backlog, [])
|
||||
ws.send.mock.assert_called_with('4foo')
|
||||
|
||||
def test_websocket_read_write_wait_fail(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = False
|
||||
s.queue.join = AsyncMock(return_value=None)
|
||||
foo = six.text_type('foo')
|
||||
bar = six.text_type('bar')
|
||||
s.poll = AsyncMock(side_effect=[
|
||||
[packet.Packet(packet.MESSAGE, data=bar)],
|
||||
[packet.Packet(packet.MESSAGE, data=bar)], exceptions.QueueEmpty])
|
||||
ws = mock.MagicMock()
|
||||
ws.send = AsyncMock()
|
||||
ws.wait = AsyncMock()
|
||||
ws.wait.mock.side_effect = [
|
||||
packet.Packet(packet.MESSAGE, data=foo).encode(
|
||||
always_bytes=False),
|
||||
RuntimeError]
|
||||
ws.send.mock.side_effect = [None, RuntimeError]
|
||||
_run(s._websocket_handler(ws))
|
||||
self.assertEqual(s.closed, True)
|
||||
|
||||
def test_websocket_ignore_invalid_packet(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.connected = False
|
||||
s.queue.join = AsyncMock(return_value=None)
|
||||
foo = six.text_type('foo')
|
||||
bar = six.text_type('bar')
|
||||
s.poll = AsyncMock(side_effect=[
|
||||
[packet.Packet(packet.MESSAGE, data=bar)], exceptions.QueueEmpty])
|
||||
ws = mock.MagicMock()
|
||||
ws.send = AsyncMock()
|
||||
ws.wait = AsyncMock()
|
||||
ws.wait.mock.side_effect = [
|
||||
packet.Packet(packet.OPEN).encode(always_bytes=False),
|
||||
packet.Packet(packet.MESSAGE, data=foo).encode(
|
||||
always_bytes=False),
|
||||
None]
|
||||
_run(s._websocket_handler(ws))
|
||||
self.assertTrue(s.connected)
|
||||
self.assertEqual(mock_server._trigger_event.mock.call_count, 2)
|
||||
mock_server._trigger_event.mock.assert_has_calls([
|
||||
mock.call('message', 'sid', foo, run_async=False),
|
||||
mock.call('disconnect', 'sid')])
|
||||
ws.send.mock.assert_called_with('4bar')
|
||||
|
||||
def test_send_after_close(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
_run(s.close(wait=False))
|
||||
self.assertRaises(exceptions.SocketIsClosedError, _run,
|
||||
s.send(packet.Packet(packet.NOOP)))
|
||||
|
||||
def test_close_after_close(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
_run(s.close(wait=False))
|
||||
self.assertTrue(s.closed)
|
||||
self.assertEqual(mock_server._trigger_event.mock.call_count, 1)
|
||||
mock_server._trigger_event.mock.assert_called_once_with('disconnect',
|
||||
'sid')
|
||||
_run(s.close())
|
||||
self.assertEqual(mock_server._trigger_event.mock.call_count, 1)
|
||||
|
||||
def test_close_and_wait(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.queue = mock.MagicMock()
|
||||
s.queue.put = AsyncMock()
|
||||
s.queue.join = AsyncMock()
|
||||
_run(s.close(wait=True))
|
||||
s.queue.join.mock.assert_called_once_with()
|
||||
|
||||
def test_close_without_wait(self):
|
||||
mock_server = self._get_mock_server()
|
||||
s = asyncio_socket.AsyncSocket(mock_server, 'sid')
|
||||
s.queue = mock.MagicMock()
|
||||
s.queue.put = AsyncMock()
|
||||
s.queue.join = AsyncMock()
|
||||
_run(s.close(wait=False))
|
||||
self.assertEqual(s.queue.join.mock.call_count, 0)
|
||||
Reference in New Issue
Block a user