9 changed files with 1154 additions and 2 deletions
@ -0,0 +1,83 @@ |
|||
import asyncio |
|||
|
|||
from socketio import namespace |
|||
|
|||
|
|||
class AsyncNamespace(namespace.Namespace): |
|||
"""Base class for asyncio class-based namespaces. |
|||
|
|||
A class-based namespace is a class that contains all the event handlers |
|||
for a Socket.IO namespace. The event handlers are methods of the class |
|||
with the prefix ``on_``, such as ``on_connect``, ``on_disconnect``, |
|||
``on_message``, ``on_json``, and so on. These can be regular functions or |
|||
coroutines. |
|||
|
|||
:param namespace: The Socket.IO namespace to be used with all the event |
|||
handlers defined in this class. If this argument is |
|||
omitted, the default namespace is used. |
|||
""" |
|||
def is_asyncio_based(self): |
|||
return True |
|||
|
|||
async def trigger_event(self, event, *args): |
|||
"""Dispatch an event to the proper handler method. |
|||
|
|||
In the most common usage, this method is not overloaded by subclasses, |
|||
as it performs the routing of events to methods. However, this |
|||
method can be overriden if special dispatching rules are needed, or if |
|||
having a single method that catches all events is desired. |
|||
|
|||
Note: this method is a coroutine. |
|||
""" |
|||
handler_name = 'on_' + event |
|||
if hasattr(self, handler_name): |
|||
handler = getattr(self, handler_name) |
|||
if asyncio.iscoroutinefunction(handler) is True: |
|||
try: |
|||
ret = await handler(*args) |
|||
except asyncio.CancelledError: # pragma: no cover |
|||
pass |
|||
else: |
|||
ret = handler(*args) |
|||
return ret |
|||
|
|||
async def emit(self, event, data=None, room=None, skip_sid=None, |
|||
namespace=None, callback=None): |
|||
"""Emit a custom event to one or more connected clients. |
|||
|
|||
The only difference with the :func:`socketio.Server.emit` method is |
|||
that when the ``namespace`` argument is not given the namespace |
|||
associated with the class is used. |
|||
|
|||
Note: this method is a coroutine. |
|||
""" |
|||
return await self.server.emit(event, data=data, room=room, |
|||
skip_sid=skip_sid, |
|||
namespace=namespace or self.namespace, |
|||
callback=callback) |
|||
|
|||
async def send(self, data, room=None, skip_sid=None, namespace=None, |
|||
callback=None): |
|||
"""Send a message to one or more connected clients. |
|||
|
|||
The only difference with the :func:`socketio.Server.send` method is |
|||
that when the ``namespace`` argument is not given the namespace |
|||
associated with the class is used. |
|||
|
|||
Note: this method is a coroutine. |
|||
""" |
|||
return await self.server.send(data, room=room, skip_sid=skip_sid, |
|||
namespace=namespace or self.namespace, |
|||
callback=callback) |
|||
|
|||
async def disconnect(self, sid, namespace=None): |
|||
"""Disconnect a client. |
|||
|
|||
The only difference with the :func:`socketio.Server.disconnect` method |
|||
is that when the ``namespace`` argument is not given the namespace |
|||
associated with the class is used. |
|||
|
|||
Note: this method is a coroutine. |
|||
""" |
|||
return await self.server.disconnect( |
|||
sid, namespace=namespace or self.namespace) |
@ -0,0 +1,280 @@ |
|||
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 asyncio import coroutine |
|||
from socketio import asyncio_manager |
|||
else: |
|||
# mock coroutine so that Python 2 doesn't complain |
|||
def coroutine(f): |
|||
return f |
|||
|
|||
|
|||
def AsyncMock(*args, **kwargs): |
|||
"""Return a mock asynchronous function.""" |
|||
m = mock.MagicMock(*args, **kwargs) |
|||
|
|||
@coroutine |
|||
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 TestAsyncioManager(unittest.TestCase): |
|||
def setUp(self): |
|||
mock_server = mock.MagicMock() |
|||
mock_server._emit_internal = AsyncMock() |
|||
self.bm = asyncio_manager.AsyncioManager() |
|||
self.bm.set_server(mock_server) |
|||
self.bm.initialize() |
|||
|
|||
def test_connect(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.assertIn(None, self.bm.rooms['/foo']) |
|||
self.assertIn('123', self.bm.rooms['/foo']) |
|||
self.assertIn('123', self.bm.rooms['/foo'][None]) |
|||
self.assertIn('123', self.bm.rooms['/foo']['123']) |
|||
self.assertEqual(self.bm.rooms['/foo'], {None: {'123': True}, |
|||
'123': {'123': True}}) |
|||
|
|||
def test_pre_disconnect(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.connect('456', '/foo') |
|||
self.bm.pre_disconnect('123', '/foo') |
|||
self.assertEqual(self.bm.pending_disconnect, {'/foo': ['123']}) |
|||
self.assertFalse(self.bm.is_connected('123', '/foo')) |
|||
self.bm.pre_disconnect('456', '/foo') |
|||
self.assertEqual(self.bm.pending_disconnect, {'/foo': ['123', '456']}) |
|||
self.assertFalse(self.bm.is_connected('456', '/foo')) |
|||
self.bm.disconnect('123', '/foo') |
|||
self.assertEqual(self.bm.pending_disconnect, {'/foo': ['456']}) |
|||
self.bm.disconnect('456', '/foo') |
|||
self.assertEqual(self.bm.pending_disconnect, {}) |
|||
|
|||
def test_disconnect(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.connect('456', '/foo') |
|||
self.bm.enter_room('123', '/foo', 'bar') |
|||
self.bm.enter_room('456', '/foo', 'baz') |
|||
self.bm.disconnect('123', '/foo') |
|||
self.assertEqual(self.bm.rooms['/foo'], {None: {'456': True}, |
|||
'456': {'456': True}, |
|||
'baz': {'456': True}}) |
|||
|
|||
def test_disconnect_default_namespace(self): |
|||
self.bm.connect('123', '/') |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.connect('456', '/') |
|||
self.bm.connect('456', '/foo') |
|||
self.assertTrue(self.bm.is_connected('123', '/')) |
|||
self.assertTrue(self.bm.is_connected('123', '/foo')) |
|||
self.bm.disconnect('123', '/') |
|||
self.assertFalse(self.bm.is_connected('123', '/')) |
|||
self.assertTrue(self.bm.is_connected('123', '/foo')) |
|||
self.bm.disconnect('123', '/foo') |
|||
self.assertFalse(self.bm.is_connected('123', '/foo')) |
|||
self.assertEqual(self.bm.rooms['/'], {None: {'456': True}, |
|||
'456': {'456': True}}) |
|||
self.assertEqual(self.bm.rooms['/foo'], {None: {'456': True}, |
|||
'456': {'456': True}}) |
|||
|
|||
def test_disconnect_twice(self): |
|||
self.bm.connect('123', '/') |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.connect('456', '/') |
|||
self.bm.connect('456', '/foo') |
|||
self.bm.disconnect('123', '/') |
|||
self.bm.disconnect('123', '/foo') |
|||
self.bm.disconnect('123', '/') |
|||
self.bm.disconnect('123', '/foo') |
|||
self.assertEqual(self.bm.rooms['/'], {None: {'456': True}, |
|||
'456': {'456': True}}) |
|||
self.assertEqual(self.bm.rooms['/foo'], {None: {'456': True}, |
|||
'456': {'456': True}}) |
|||
|
|||
def test_disconnect_all(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.connect('456', '/foo') |
|||
self.bm.enter_room('123', '/foo', 'bar') |
|||
self.bm.enter_room('456', '/foo', 'baz') |
|||
self.bm.disconnect('123', '/foo') |
|||
self.bm.disconnect('456', '/foo') |
|||
self.assertEqual(self.bm.rooms, {}) |
|||
|
|||
def test_disconnect_with_callbacks(self): |
|||
self.bm.connect('123', '/') |
|||
self.bm.connect('123', '/foo') |
|||
self.bm._generate_ack_id('123', '/', 'f') |
|||
self.bm._generate_ack_id('123', '/foo', 'g') |
|||
self.bm.disconnect('123', '/foo') |
|||
self.assertNotIn('/foo', self.bm.callbacks['123']) |
|||
self.bm.disconnect('123', '/') |
|||
self.assertNotIn('123', self.bm.callbacks) |
|||
|
|||
def test_trigger_sync_callback(self): |
|||
self.bm.connect('123', '/') |
|||
self.bm.connect('123', '/foo') |
|||
cb = mock.MagicMock() |
|||
id1 = self.bm._generate_ack_id('123', '/', cb) |
|||
id2 = self.bm._generate_ack_id('123', '/foo', cb) |
|||
_run(self.bm.trigger_callback('123', '/', id1, ['foo'])) |
|||
_run(self.bm.trigger_callback('123', '/foo', id2, ['bar', 'baz'])) |
|||
self.assertEqual(cb.call_count, 2) |
|||
cb.assert_any_call('foo') |
|||
cb.assert_any_call('bar', 'baz') |
|||
|
|||
def test_trigger_async_callback(self): |
|||
self.bm.connect('123', '/') |
|||
self.bm.connect('123', '/foo') |
|||
cb = AsyncMock() |
|||
id1 = self.bm._generate_ack_id('123', '/', cb) |
|||
id2 = self.bm._generate_ack_id('123', '/foo', cb) |
|||
_run(self.bm.trigger_callback('123', '/', id1, ['foo'])) |
|||
_run(self.bm.trigger_callback('123', '/foo', id2, ['bar', 'baz'])) |
|||
self.assertEqual(cb.mock.call_count, 2) |
|||
cb.mock.assert_any_call('foo') |
|||
cb.mock.assert_any_call('bar', 'baz') |
|||
|
|||
def test_invalid_callback(self): |
|||
self.bm.connect('123', '/') |
|||
cb = mock.MagicMock() |
|||
id = self.bm._generate_ack_id('123', '/', cb) |
|||
|
|||
# these should not raise an exception |
|||
_run(self.bm.trigger_callback('124', '/', id, ['foo'])) |
|||
_run(self.bm.trigger_callback('123', '/foo', id, ['foo'])) |
|||
_run(self.bm.trigger_callback('123', '/', id + 1, ['foo'])) |
|||
self.assertEqual(cb.mock.call_count, 0) |
|||
|
|||
def test_get_namespaces(self): |
|||
self.assertEqual(list(self.bm.get_namespaces()), []) |
|||
self.bm.connect('123', '/') |
|||
self.bm.connect('123', '/foo') |
|||
namespaces = list(self.bm.get_namespaces()) |
|||
self.assertEqual(len(namespaces), 2) |
|||
self.assertIn('/', namespaces) |
|||
self.assertIn('/foo', namespaces) |
|||
|
|||
def test_get_participants(self): |
|||
self.bm.connect('123', '/') |
|||
self.bm.connect('456', '/') |
|||
self.bm.connect('789', '/') |
|||
self.bm.disconnect('789', '/') |
|||
self.assertNotIn('789', self.bm.rooms['/'][None]) |
|||
participants = list(self.bm.get_participants('/', None)) |
|||
self.assertEqual(len(participants), 2) |
|||
self.assertNotIn('789', participants) |
|||
|
|||
def test_leave_invalid_room(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.leave_room('123', '/foo', 'baz') |
|||
self.bm.leave_room('123', '/bar', 'baz') |
|||
|
|||
def test_no_room(self): |
|||
rooms = self.bm.get_rooms('123', '/foo') |
|||
self.assertEqual([], rooms) |
|||
|
|||
def test_close_room(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.connect('456', '/foo') |
|||
self.bm.connect('789', '/foo') |
|||
self.bm.enter_room('123', '/foo', 'bar') |
|||
self.bm.enter_room('123', '/foo', 'bar') |
|||
self.bm.close_room('bar', '/foo') |
|||
self.assertNotIn('bar', self.bm.rooms['/foo']) |
|||
|
|||
def test_close_invalid_room(self): |
|||
self.bm.close_room('bar', '/foo') |
|||
|
|||
def test_rooms(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.enter_room('123', '/foo', 'bar') |
|||
r = self.bm.get_rooms('123', '/foo') |
|||
self.assertEqual(len(r), 2) |
|||
self.assertIn('123', r) |
|||
self.assertIn('bar', r) |
|||
|
|||
def test_emit_to_sid(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.connect('456', '/foo') |
|||
_run(self.bm.emit('my event', {'foo': 'bar'}, namespace='/foo', |
|||
room='123')) |
|||
self.bm.server._emit_internal.mock.assert_called_once_with( |
|||
'123', 'my event', {'foo': 'bar'}, '/foo', None) |
|||
|
|||
def test_emit_to_room(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.enter_room('123', '/foo', 'bar') |
|||
self.bm.connect('456', '/foo') |
|||
self.bm.enter_room('456', '/foo', 'bar') |
|||
self.bm.connect('789', '/foo') |
|||
_run(self.bm.emit('my event', {'foo': 'bar'}, namespace='/foo', |
|||
room='bar')) |
|||
self.assertEqual(self.bm.server._emit_internal.mock.call_count, 2) |
|||
self.bm.server._emit_internal.mock.assert_any_call( |
|||
'123', 'my event', {'foo': 'bar'}, '/foo', None) |
|||
self.bm.server._emit_internal.mock.assert_any_call( |
|||
'456', 'my event', {'foo': 'bar'}, '/foo', None) |
|||
|
|||
def test_emit_to_all(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.enter_room('123', '/foo', 'bar') |
|||
self.bm.connect('456', '/foo') |
|||
self.bm.enter_room('456', '/foo', 'bar') |
|||
self.bm.connect('789', '/foo') |
|||
self.bm.connect('abc', '/bar') |
|||
_run(self.bm.emit('my event', {'foo': 'bar'}, namespace='/foo')) |
|||
self.assertEqual(self.bm.server._emit_internal.mock.call_count, 3) |
|||
self.bm.server._emit_internal.mock.assert_any_call( |
|||
'123', 'my event', {'foo': 'bar'}, '/foo', None) |
|||
self.bm.server._emit_internal.mock.assert_any_call( |
|||
'456', 'my event', {'foo': 'bar'}, '/foo', None) |
|||
self.bm.server._emit_internal.mock.assert_any_call( |
|||
'789', 'my event', {'foo': 'bar'}, '/foo', None) |
|||
|
|||
def test_emit_to_all_skip_one(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm.enter_room('123', '/foo', 'bar') |
|||
self.bm.connect('456', '/foo') |
|||
self.bm.enter_room('456', '/foo', 'bar') |
|||
self.bm.connect('789', '/foo') |
|||
self.bm.connect('abc', '/bar') |
|||
_run(self.bm.emit('my event', {'foo': 'bar'}, namespace='/foo', |
|||
skip_sid='456')) |
|||
self.assertEqual(self.bm.server._emit_internal.mock.call_count, 2) |
|||
self.bm.server._emit_internal.mock.assert_any_call( |
|||
'123', 'my event', {'foo': 'bar'}, '/foo', None) |
|||
self.bm.server._emit_internal.mock.assert_any_call( |
|||
'789', 'my event', {'foo': 'bar'}, '/foo', None) |
|||
|
|||
def test_emit_with_callback(self): |
|||
self.bm.connect('123', '/foo') |
|||
self.bm._generate_ack_id = mock.MagicMock() |
|||
self.bm._generate_ack_id.return_value = 11 |
|||
_run(self.bm.emit('my event', {'foo': 'bar'}, namespace='/foo', |
|||
callback='cb')) |
|||
self.bm._generate_ack_id.assert_called_once_with('123', '/foo', 'cb') |
|||
self.bm.server._emit_internal.mock.assert_called_once_with( |
|||
'123', 'my event', {'foo': 'bar'}, '/foo', 11) |
|||
|
|||
def test_emit_to_invalid_room(self): |
|||
_run(self.bm.emit('my event', {'foo': 'bar'}, namespace='/', |
|||
room='123')) |
|||
|
|||
def test_emit_to_invalid_namespace(self): |
|||
_run(self.bm.emit('my event', {'foo': 'bar'}, namespace='/foo')) |
@ -0,0 +1,179 @@ |
|||
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 asyncio import coroutine |
|||
from socketio import asyncio_namespace |
|||
else: |
|||
# mock coroutine so that Python 2 doesn't complain |
|||
def coroutine(f): |
|||
return f |
|||
|
|||
|
|||
def AsyncMock(*args, **kwargs): |
|||
"""Return a mock asynchronous function.""" |
|||
m = mock.MagicMock(*args, **kwargs) |
|||
|
|||
@coroutine |
|||
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 TestAsyncNamespace(unittest.TestCase): |
|||
def test_connect_event(self): |
|||
result = {} |
|||
|
|||
class MyNamespace(asyncio_namespace.AsyncNamespace): |
|||
@coroutine |
|||
def on_connect(self, sid, environ): |
|||
result['result'] = (sid, environ) |
|||
|
|||
ns = MyNamespace('/foo') |
|||
ns._set_server(mock.MagicMock()) |
|||
_run(ns.trigger_event('connect', 'sid', {'foo': 'bar'})) |
|||
self.assertEqual(result['result'], ('sid', {'foo': 'bar'})) |
|||
|
|||
def test_disconnect_event(self): |
|||
result = {} |
|||
|
|||
class MyNamespace(asyncio_namespace.AsyncNamespace): |
|||
@coroutine |
|||
def on_disconnect(self, sid): |
|||
result['result'] = sid |
|||
|
|||
ns = MyNamespace('/foo') |
|||
ns._set_server(mock.MagicMock()) |
|||
_run(ns.trigger_event('disconnect', 'sid')) |
|||
self.assertEqual(result['result'], 'sid') |
|||
|
|||
def test_sync_event(self): |
|||
result = {} |
|||
|
|||
class MyNamespace(asyncio_namespace.AsyncNamespace): |
|||
def on_custom_message(self, sid, data): |
|||
result['result'] = (sid, data) |
|||
|
|||
ns = MyNamespace('/foo') |
|||
ns._set_server(mock.MagicMock()) |
|||
_run(ns.trigger_event('custom_message', 'sid', {'data': 'data'})) |
|||
self.assertEqual(result['result'], ('sid', {'data': 'data'})) |
|||
|
|||
def test_async_event(self): |
|||
result = {} |
|||
|
|||
class MyNamespace(asyncio_namespace.AsyncNamespace): |
|||
@coroutine |
|||
def on_custom_message(self, sid, data): |
|||
result['result'] = (sid, data) |
|||
|
|||
ns = MyNamespace('/foo') |
|||
ns._set_server(mock.MagicMock()) |
|||
_run(ns.trigger_event('custom_message', 'sid', {'data': 'data'})) |
|||
self.assertEqual(result['result'], ('sid', {'data': 'data'})) |
|||
|
|||
def test_event_not_found(self): |
|||
result = {} |
|||
|
|||
class MyNamespace(asyncio_namespace.AsyncNamespace): |
|||
@coroutine |
|||
def on_custom_message(self, sid, data): |
|||
result['result'] = (sid, data) |
|||
|
|||
ns = MyNamespace('/foo') |
|||
ns._set_server(mock.MagicMock()) |
|||
_run(ns.trigger_event('another_custom_message', 'sid', |
|||
{'data': 'data'})) |
|||
self.assertEqual(result, {}) |
|||
|
|||
def test_emit(self): |
|||
ns = asyncio_namespace.AsyncNamespace('/foo') |
|||
mock_server = mock.MagicMock() |
|||
mock_server.emit = AsyncMock() |
|||
ns._set_server(mock_server) |
|||
_run(ns.emit('ev', data='data', room='room', skip_sid='skip', |
|||
callback='cb')) |
|||
ns.server.emit.mock.assert_called_with( |
|||
'ev', data='data', room='room', skip_sid='skip', namespace='/foo', |
|||
callback='cb') |
|||
_run(ns.emit('ev', data='data', room='room', skip_sid='skip', |
|||
namespace='/bar', callback='cb')) |
|||
ns.server.emit.mock.assert_called_with( |
|||
'ev', data='data', room='room', skip_sid='skip', namespace='/bar', |
|||
callback='cb') |
|||
|
|||
def test_send(self): |
|||
ns = asyncio_namespace.AsyncNamespace('/foo') |
|||
mock_server = mock.MagicMock() |
|||
mock_server.send = AsyncMock() |
|||
ns._set_server(mock_server) |
|||
_run(ns.send(data='data', room='room', skip_sid='skip', callback='cb')) |
|||
ns.server.send.mock.assert_called_with( |
|||
'data', room='room', skip_sid='skip', namespace='/foo', |
|||
callback='cb') |
|||
_run(ns.send(data='data', room='room', skip_sid='skip', |
|||
namespace='/bar', callback='cb')) |
|||
ns.server.send.mock.assert_called_with( |
|||
'data', room='room', skip_sid='skip', namespace='/bar', |
|||
callback='cb') |
|||
|
|||
def test_enter_room(self): |
|||
ns = asyncio_namespace.AsyncNamespace('/foo') |
|||
ns._set_server(mock.MagicMock()) |
|||
ns.enter_room('sid', 'room') |
|||
ns.server.enter_room.assert_called_with('sid', 'room', |
|||
namespace='/foo') |
|||
ns.enter_room('sid', 'room', namespace='/bar') |
|||
ns.server.enter_room.assert_called_with('sid', 'room', |
|||
namespace='/bar') |
|||
|
|||
def test_leave_room(self): |
|||
ns = asyncio_namespace.AsyncNamespace('/foo') |
|||
ns._set_server(mock.MagicMock()) |
|||
ns.leave_room('sid', 'room') |
|||
ns.server.leave_room.assert_called_with('sid', 'room', |
|||
namespace='/foo') |
|||
ns.leave_room('sid', 'room', namespace='/bar') |
|||
ns.server.leave_room.assert_called_with('sid', 'room', |
|||
namespace='/bar') |
|||
|
|||
def test_close_room(self): |
|||
ns = asyncio_namespace.AsyncNamespace('/foo') |
|||
ns._set_server(mock.MagicMock()) |
|||
ns.close_room('room') |
|||
ns.server.close_room.assert_called_with('room', namespace='/foo') |
|||
ns.close_room('room', namespace='/bar') |
|||
ns.server.close_room.assert_called_with('room', namespace='/bar') |
|||
|
|||
def test_rooms(self): |
|||
ns = asyncio_namespace.AsyncNamespace('/foo') |
|||
ns._set_server(mock.MagicMock()) |
|||
ns.rooms('sid') |
|||
ns.server.rooms.assert_called_with('sid', namespace='/foo') |
|||
ns.rooms('sid', namespace='/bar') |
|||
ns.server.rooms.assert_called_with('sid', namespace='/bar') |
|||
|
|||
def test_disconnect(self): |
|||
ns = asyncio_namespace.AsyncNamespace('/foo') |
|||
mock_server = mock.MagicMock() |
|||
mock_server.disconnect = AsyncMock() |
|||
ns._set_server(mock_server) |
|||
_run(ns.disconnect('sid')) |
|||
ns.server.disconnect.mock.assert_called_with('sid', namespace='/foo') |
|||
_run(ns.disconnect('sid', namespace='/bar')) |
|||
ns.server.disconnect.mock.assert_called_with('sid', namespace='/bar') |
@ -0,0 +1,594 @@ |
|||
import json |
|||
import logging |
|||
import sys |
|||
import unittest |
|||
|
|||
import six |
|||
if six.PY3: |
|||
from unittest import mock |
|||
else: |
|||
import mock |
|||
|
|||
from socketio import packet |
|||
from socketio import namespace |
|||
if sys.version_info >= (3, 5): |
|||
import asyncio |
|||
from asyncio import coroutine |
|||
from socketio import asyncio_server |
|||
from socketio import asyncio_namespace |
|||
else: |
|||
# mock coroutine so that Python 2 doesn't complain |
|||
def coroutine(f): |
|||
return f |
|||
|
|||
|
|||
def AsyncMock(*args, **kwargs): |
|||
"""Return a mock asynchronous function.""" |
|||
m = mock.MagicMock(*args, **kwargs) |
|||
|
|||
@coroutine |
|||
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+') |
|||
@mock.patch('socketio.server.engineio.AsyncServer') |
|||
class TestAsyncServer(unittest.TestCase): |
|||
def tearDown(self): |
|||
# restore JSON encoder, in case a test changed it |
|||
packet.Packet.json = json |
|||
|
|||
def _get_mock_manager(self): |
|||
mgr = mock.MagicMock() |
|||
mgr.emit = AsyncMock() |
|||
mgr.trigger_callback = AsyncMock() |
|||
return mgr |
|||
|
|||
def test_create(self, eio): |
|||
eio.return_value.handle_request = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr, foo='bar') |
|||
_run(s.handle_request({})) |
|||
_run(s.handle_request({})) |
|||
eio.assert_called_once_with(**{'foo': 'bar', 'async_handlers': False}) |
|||
self.assertEqual(s.manager, mgr) |
|||
self.assertEqual(s.eio.on.call_count, 3) |
|||
self.assertEqual(s.binary, False) |
|||
self.assertEqual(s.async_handlers, False) |
|||
|
|||
def test_attach(self, eio): |
|||
s = asyncio_server.AsyncServer() |
|||
s.attach('app', 'path') |
|||
eio.return_value.attach.assert_called_once_with('app', 'path') |
|||
|
|||
def test_on_event(self, eio): |
|||
s = asyncio_server.AsyncServer() |
|||
|
|||
@s.on('connect') |
|||
def foo(): |
|||
pass |
|||
|
|||
def bar(): |
|||
pass |
|||
s.on('disconnect', bar) |
|||
s.on('disconnect', bar, namespace='/foo') |
|||
|
|||
self.assertEqual(s.handlers['/']['connect'], foo) |
|||
self.assertEqual(s.handlers['/']['disconnect'], bar) |
|||
self.assertEqual(s.handlers['/foo']['disconnect'], bar) |
|||
|
|||
def test_emit(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
_run(s.emit('my event', {'foo': 'bar'}, 'room', '123', |
|||
namespace='/foo', callback='cb')) |
|||
s.manager.emit.mock.assert_called_once_with( |
|||
'my event', {'foo': 'bar'}, '/foo', 'room', '123', 'cb') |
|||
|
|||
def test_emit_default_namespace(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
_run(s.emit('my event', {'foo': 'bar'}, 'room', '123', callback='cb')) |
|||
s.manager.emit.mock.assert_called_once_with('my event', {'foo': 'bar'}, |
|||
'/', 'room', '123', 'cb') |
|||
|
|||
def test_send(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
_run(s.send('foo', 'room', '123', namespace='/foo', callback='cb')) |
|||
s.manager.emit.mock.assert_called_once_with('message', 'foo', '/foo', |
|||
'room', '123', 'cb') |
|||
|
|||
def test_enter_room(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.enter_room('123', 'room', namespace='/foo') |
|||
s.manager.enter_room.assert_called_once_with('123', '/foo', 'room') |
|||
|
|||
def test_enter_room_default_namespace(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.enter_room('123', 'room') |
|||
s.manager.enter_room.assert_called_once_with('123', '/', 'room') |
|||
|
|||
def test_leave_room(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.leave_room('123', 'room', namespace='/foo') |
|||
s.manager.leave_room.assert_called_once_with('123', '/foo', 'room') |
|||
|
|||
def test_leave_room_default_namespace(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.leave_room('123', 'room') |
|||
s.manager.leave_room.assert_called_once_with('123', '/', 'room') |
|||
|
|||
def test_close_room(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.close_room('room', namespace='/foo') |
|||
s.manager.close_room.assert_called_once_with('room', '/foo') |
|||
|
|||
def test_close_room_default_namespace(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.close_room('room') |
|||
s.manager.close_room.assert_called_once_with('room', '/') |
|||
|
|||
def test_rooms(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.rooms('123', namespace='/foo') |
|||
s.manager.get_rooms.assert_called_once_with('123', '/foo') |
|||
|
|||
def test_rooms_default_namespace(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.rooms('123') |
|||
s.manager.get_rooms.assert_called_once_with('123', '/') |
|||
|
|||
def test_handle_request(self, eio): |
|||
eio.return_value.handle_request = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s.handle_request('environ')) |
|||
s.eio.handle_request.mock.assert_called_once_with('environ') |
|||
|
|||
def test_emit_internal(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s._emit_internal('123', 'my event', 'my data', namespace='/foo')) |
|||
s.eio.send.mock.assert_called_once_with( |
|||
'123', '2/foo,["my event","my data"]', binary=False) |
|||
|
|||
def test_emit_internal_with_tuple(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s._emit_internal('123', 'my event', ('foo', 'bar'), |
|||
namespace='/foo')) |
|||
s.eio.send.mock.assert_called_once_with( |
|||
'123', '2/foo,["my event","foo","bar"]', binary=False) |
|||
|
|||
def test_emit_internal_with_list(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s._emit_internal('123', 'my event', ['foo', 'bar'], |
|||
namespace='/foo')) |
|||
s.eio.send.mock.assert_called_once_with( |
|||
'123', '2/foo,["my event",["foo","bar"]]', binary=False) |
|||
|
|||
def test_emit_internal_with_callback(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
id = s.manager._generate_ack_id('123', '/foo', 'cb') |
|||
_run(s._emit_internal('123', 'my event', 'my data', namespace='/foo', |
|||
id=id)) |
|||
s.eio.send.mock.assert_called_once_with( |
|||
'123', '2/foo,1["my event","my data"]', binary=False) |
|||
|
|||
def test_emit_internal_default_namespace(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s._emit_internal('123', 'my event', 'my data')) |
|||
s.eio.send.mock.assert_called_once_with( |
|||
'123', '2["my event","my data"]', binary=False) |
|||
|
|||
def test_emit_internal_binary(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer(binary=True) |
|||
_run(s._emit_internal('123', u'my event', b'my binary data')) |
|||
self.assertEqual(s.eio.send.mock.call_count, 2) |
|||
|
|||
def test_transport(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
s.eio.transport = mock.MagicMock(return_value='polling') |
|||
_run(s._handle_eio_connect('foo', 'environ')) |
|||
self.assertEqual(s.transport('foo'), 'polling') |
|||
s.eio.transport.assert_called_once_with('foo') |
|||
|
|||
def test_handle_connect(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
handler = mock.MagicMock() |
|||
s.on('connect', handler) |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
handler.assert_called_once_with('123', 'environ') |
|||
s.manager.connect.assert_called_once_with('123', '/') |
|||
s.eio.send.mock.assert_called_once_with('123', '0', binary=False) |
|||
self.assertEqual(mgr.initialize.call_count, 1) |
|||
_run(s._handle_eio_connect('456', 'environ')) |
|||
self.assertEqual(mgr.initialize.call_count, 1) |
|||
|
|||
def test_handle_connect_async(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
handler = AsyncMock() |
|||
s.on('connect', handler) |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
handler.mock.assert_called_once_with('123', 'environ') |
|||
s.manager.connect.assert_called_once_with('123', '/') |
|||
s.eio.send.mock.assert_called_once_with('123', '0', binary=False) |
|||
self.assertEqual(mgr.initialize.call_count, 1) |
|||
_run(s._handle_eio_connect('456', 'environ')) |
|||
self.assertEqual(mgr.initialize.call_count, 1) |
|||
|
|||
def test_handle_connect_namespace(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
handler = mock.MagicMock() |
|||
s.on('connect', handler, namespace='/foo') |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s._handle_eio_message('123', '0/foo')) |
|||
handler.assert_called_once_with('123', 'environ') |
|||
s.manager.connect.assert_any_call('123', '/') |
|||
s.manager.connect.assert_any_call('123', '/foo') |
|||
s.eio.send.mock.assert_any_call('123', '0/foo', binary=False) |
|||
|
|||
def test_handle_connect_rejected(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
handler = mock.MagicMock(return_value=False) |
|||
s.on('connect', handler) |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
handler.assert_called_once_with('123', 'environ') |
|||
self.assertEqual(s.manager.connect.call_count, 1) |
|||
self.assertEqual(s.manager.disconnect.call_count, 1) |
|||
s.eio.send.mock.assert_called_once_with('123', '4', binary=False) |
|||
|
|||
def test_handle_connect_namespace_rejected(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
handler = mock.MagicMock(return_value=False) |
|||
s.on('connect', handler, namespace='/foo') |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s._handle_eio_message('123', '0/foo')) |
|||
self.assertEqual(s.manager.connect.call_count, 2) |
|||
self.assertEqual(s.manager.disconnect.call_count, 1) |
|||
s.eio.send.mock.assert_any_call('123', '4/foo', binary=False) |
|||
|
|||
def test_handle_disconnect(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
handler = mock.MagicMock() |
|||
s.on('disconnect', handler) |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s._handle_eio_disconnect('123')) |
|||
handler.assert_called_once_with('123') |
|||
s.manager.disconnect.assert_called_once_with('123', '/') |
|||
self.assertEqual(s.environ, {}) |
|||
|
|||
def test_handle_disconnect_namespace(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.manager.get_namespaces = mock.MagicMock(return_value=['/', '/foo']) |
|||
handler = mock.MagicMock() |
|||
s.on('disconnect', handler) |
|||
handler_namespace = mock.MagicMock() |
|||
s.on('disconnect', handler_namespace, namespace='/foo') |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s._handle_eio_message('123', '0/foo')) |
|||
_run(s._handle_eio_disconnect('123')) |
|||
handler.assert_called_once_with('123') |
|||
handler_namespace.assert_called_once_with('123') |
|||
self.assertEqual(s.environ, {}) |
|||
|
|||
def test_handle_disconnect_only_namespace(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.manager.get_namespaces = mock.MagicMock(return_value=['/', '/foo']) |
|||
handler = mock.MagicMock() |
|||
s.on('disconnect', handler) |
|||
handler_namespace = mock.MagicMock() |
|||
s.on('disconnect', handler_namespace, namespace='/foo') |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s._handle_eio_message('123', '0/foo')) |
|||
_run(s._handle_eio_message('123', '1/foo')) |
|||
self.assertEqual(handler.call_count, 0) |
|||
handler_namespace.assert_called_once_with('123') |
|||
self.assertEqual(s.environ, {'123': 'environ'}) |
|||
|
|||
def test_handle_disconnect_unknown_client(self, eio): |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
_run(s._handle_eio_disconnect('123')) |
|||
|
|||
def test_handle_event(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
handler = AsyncMock() |
|||
s.on('my message', handler) |
|||
_run(s._handle_eio_message('123', '2["my message","a","b","c"]')) |
|||
handler.mock.assert_called_once_with('123', 'a', 'b', 'c') |
|||
|
|||
def test_handle_event_with_namespace(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
handler = mock.MagicMock() |
|||
s.on('my message', handler, namespace='/foo') |
|||
_run(s._handle_eio_message('123', '2/foo,["my message","a","b","c"]')) |
|||
handler.assert_called_once_with('123', 'a', 'b', 'c') |
|||
|
|||
def test_handle_event_binary(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
handler = mock.MagicMock() |
|||
s.on('my message', handler) |
|||
_run(s._handle_eio_message('123', '52-["my message","a",' |
|||
'{"_placeholder":true,"num":1},' |
|||
'{"_placeholder":true,"num":0}]')) |
|||
_run(s._handle_eio_message('123', b'foo')) |
|||
_run(s._handle_eio_message('123', b'bar')) |
|||
handler.assert_called_once_with('123', 'a', b'bar', b'foo') |
|||
|
|||
def test_handle_event_binary_ack(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
s.manager.initialize(s) |
|||
_run(s._handle_eio_message('123', '61-321["my message","a",' |
|||
'{"_placeholder":true,"num":0}]')) |
|||
_run(s._handle_eio_message('123', b'foo')) |
|||
mgr.trigger_callback.mock.assert_called_once_with( |
|||
'123', '/', 321, ['my message', 'a', b'foo']) |
|||
|
|||
def test_handle_event_with_ack(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
handler = mock.MagicMock(return_value='foo') |
|||
s.on('my message', handler) |
|||
_run(s._handle_eio_message('123', '21000["my message","foo"]')) |
|||
handler.assert_called_once_with('123', 'foo') |
|||
s.eio.send.mock.assert_called_once_with('123', '31000["foo"]', |
|||
binary=False) |
|||
|
|||
def test_handle_event_with_ack_none(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
handler = mock.MagicMock(return_value=None) |
|||
s.on('my message', handler) |
|||
_run(s._handle_eio_message('123', '21000["my message","foo"]')) |
|||
handler.assert_called_once_with('123', 'foo') |
|||
s.eio.send.mock.assert_called_once_with('123', '31000[]', |
|||
binary=False) |
|||
|
|||
def test_handle_event_with_ack_tuple(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
handler = mock.MagicMock(return_value=(1, '2', True)) |
|||
s.on('my message', handler) |
|||
_run(s._handle_eio_message('123', '21000["my message","a","b","c"]')) |
|||
handler.assert_called_once_with('123', 'a', 'b', 'c') |
|||
s.eio.send.mock.assert_called_once_with('123', '31000[1,"2",true]', |
|||
binary=False) |
|||
|
|||
def test_handle_event_with_ack_list(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr) |
|||
handler = mock.MagicMock(return_value=[1, '2', True]) |
|||
s.on('my message', handler) |
|||
_run(s._handle_eio_message('123', '21000["my message","a","b","c"]')) |
|||
handler.assert_called_once_with('123', 'a', 'b', 'c') |
|||
s.eio.send.mock.assert_called_once_with('123', '31000[[1,"2",true]]', |
|||
binary=False) |
|||
|
|||
def test_handle_event_with_ack_binary(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
mgr = self._get_mock_manager() |
|||
s = asyncio_server.AsyncServer(client_manager=mgr, binary=True) |
|||
handler = mock.MagicMock(return_value=b'foo') |
|||
s.on('my message', handler) |
|||
_run(s._handle_eio_message('123', '21000["my message","foo"]')) |
|||
handler.assert_any_call('123', 'foo') |
|||
|
|||
def test_handle_error_packet(self, eio): |
|||
s = asyncio_server.AsyncServer() |
|||
self.assertRaises(ValueError, _run, s._handle_eio_message('123', '4')) |
|||
|
|||
def test_handle_invalid_packet(self, eio): |
|||
s = asyncio_server.AsyncServer() |
|||
self.assertRaises(ValueError, _run, s._handle_eio_message('123', '9')) |
|||
|
|||
def test_send_with_ack(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
cb = mock.MagicMock() |
|||
id1 = s.manager._generate_ack_id('123', '/', cb) |
|||
id2 = s.manager._generate_ack_id('123', '/', cb) |
|||
_run(s._emit_internal('123', 'my event', ['foo'], id=id1)) |
|||
_run(s._emit_internal('123', 'my event', ['bar'], id=id2)) |
|||
_run(s._handle_eio_message('123', '31["foo",2]')) |
|||
cb.assert_called_once_with('foo', 2) |
|||
|
|||
def test_send_with_ack_namespace(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s._handle_eio_message('123', '0/foo')) |
|||
cb = mock.MagicMock() |
|||
id = s.manager._generate_ack_id('123', '/foo', cb) |
|||
_run(s._emit_internal('123', 'my event', ['foo'], namespace='/foo', |
|||
id=id)) |
|||
_run(s._handle_eio_message('123', '3/foo,1["foo",2]')) |
|||
cb.assert_called_once_with('foo', 2) |
|||
|
|||
def test_disconnect(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s.disconnect('123')) |
|||
s.eio.send.mock.assert_any_call('123', '1', binary=False) |
|||
|
|||
def test_disconnect_namespace(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s._handle_eio_message('123', '0/foo')) |
|||
_run(s.disconnect('123', namespace='/foo')) |
|||
s.eio.send.mock.assert_any_call('123', '1/foo', binary=False) |
|||
|
|||
def test_disconnect_twice(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s.disconnect('123')) |
|||
calls = s.eio.send.mock.call_count |
|||
_run(s.disconnect('123')) |
|||
self.assertEqual(calls, s.eio.send.mock.call_count) |
|||
|
|||
def test_disconnect_twice_namespace(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s._handle_eio_message('123', '0/foo')) |
|||
_run(s.disconnect('123', namespace='/foo')) |
|||
calls = s.eio.send.mock.call_count |
|||
_run(s.disconnect('123', namespace='/foo')) |
|||
self.assertEqual(calls, s.eio.send.mock.call_count) |
|||
|
|||
def test_namespace_handler(self, eio): |
|||
eio.return_value.send = AsyncMock() |
|||
result = {} |
|||
|
|||
class MyNamespace(asyncio_namespace.AsyncNamespace): |
|||
def on_connect(self, sid, environ): |
|||
result['result'] = (sid, environ) |
|||
|
|||
@coroutine |
|||
def on_disconnect(self, sid): |
|||
result['result'] = ('disconnect', sid) |
|||
|
|||
@coroutine |
|||
def on_foo(self, sid, data): |
|||
result['result'] = (sid, data) |
|||
|
|||
def on_bar(self, sid): |
|||
result['result'] = 'bar' |
|||
|
|||
@coroutine |
|||
def on_baz(self, sid, data1, data2): |
|||
result['result'] = (data1, data2) |
|||
|
|||
s = asyncio_server.AsyncServer() |
|||
s.register_namespace(MyNamespace('/foo')) |
|||
_run(s._handle_eio_connect('123', 'environ')) |
|||
_run(s._handle_eio_message('123', '0/foo')) |
|||
self.assertEqual(result['result'], ('123', 'environ')) |
|||
_run(s._handle_eio_message('123', '2/foo,["foo","a"]')) |
|||
self.assertEqual(result['result'], ('123', 'a')) |
|||
_run(s._handle_eio_message('123', '2/foo,["bar"]')) |
|||
self.assertEqual(result['result'], 'bar') |
|||
_run(s._handle_eio_message('123', '2/foo,["baz","a","b"]')) |
|||
self.assertEqual(result['result'], ('a', 'b')) |
|||
_run(s.disconnect('123', '/foo')) |
|||
self.assertEqual(result['result'], ('disconnect', '123')) |
|||
|
|||
def test_bad_namespace_handler(self, eio): |
|||
class Dummy(object): |
|||
pass |
|||
|
|||
class SyncNS(namespace.Namespace): |
|||
pass |
|||
|
|||
s = asyncio_server.AsyncServer() |
|||
self.assertRaises(ValueError, s.register_namespace, 123) |
|||
self.assertRaises(ValueError, s.register_namespace, Dummy) |
|||
self.assertRaises(ValueError, s.register_namespace, Dummy()) |
|||
self.assertRaises(ValueError, s.register_namespace, |
|||
namespace.Namespace) |
|||
self.assertRaises(ValueError, s.register_namespace, SyncNS()) |
|||
|
|||
def test_logger(self, eio): |
|||
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) |
|||
s = asyncio_server.AsyncServer(logger='foo') |
|||
self.assertEqual(s.logger, 'foo') |
|||
|
|||
def test_engineio_logger(self, eio): |
|||
asyncio_server.AsyncServer(engineio_logger='foo') |
|||
eio.assert_called_once_with(**{'logger': 'foo', |
|||
'async_handlers': False}) |
|||
|
|||
def test_custom_json(self, eio): |
|||
# 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) |
|||
eio.assert_called_once_with(**{'json': CustomJSON, |
|||
'async_handlers': False}) |
|||
|
|||
pkt = packet.Packet(packet_type=packet.EVENT, |
|||
data={six.text_type('foo'): six.text_type('bar')}) |
|||
self.assertEqual(pkt.encode(), '2*** encoded ***') |
|||
pkt2 = packet.Packet(encoded_packet=pkt.encode()) |
|||
self.assertEqual(pkt2.data, '+++ decoded +++') |
|||
|
|||
# restore the default JSON module |
|||
packet.Packet.json = json |
|||
|
|||
def test_start_background_task(self, eio): |
|||
eio.return_value.start_background_task = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s.start_background_task('foo', 'bar', baz='baz')) |
|||
s.eio.start_background_task.mock.assert_called_once_with('foo', 'bar', |
|||
baz='baz') |
|||
|
|||
def test_sleep(self, eio): |
|||
eio.return_value.sleep = AsyncMock() |
|||
s = asyncio_server.AsyncServer() |
|||
_run(s.sleep(1.23)) |
|||
s.eio.sleep.mock.assert_called_once_with(1.23) |
Loading…
Reference in new issue