Browse Source

some client unit tests

pull/228/head
Miguel Grinberg 6 years ago
parent
commit
e626e6c41d
No known key found for this signature in database GPG Key ID: 36848B262DF5F06C
  1. 2
      .travis.yml
  2. 3
      socketio/asyncio_namespace.py
  3. 52
      socketio/client.py
  4. 2
      socketio/namespace.py
  5. 2
      socketio/server.py
  6. 631
      tests/test_client.py
  7. 3
      tox.ini

2
.travis.yml

@ -5,8 +5,6 @@ matrix:
env: TOXENV=flake8 env: TOXENV=flake8
- python: 2.7 - python: 2.7
env: TOXENV=py27 env: TOXENV=py27
- python: 3.4
env: TOXENV=py34
- python: 3.5 - python: 3.5
env: TOXENV=py35 env: TOXENV=py35
- python: 3.6 - python: 3.6

3
socketio/asyncio_namespace.py

@ -108,6 +108,9 @@ class AsyncClientNamespace(namespace.ClientNamespace):
handlers defined in this class. If this argument is handlers defined in this class. If this argument is
omitted, the default namespace is used. omitted, the default namespace is used.
""" """
def is_asyncio_based(self):
return True
async def emit(self, event, data=None, namespace=None, callback=None): async def emit(self, event, data=None, namespace=None, callback=None):
"""Emit a custom event to the server. """Emit a custom event to the server.

52
socketio/client.py

@ -95,7 +95,7 @@ class Client(object):
self.connection_namespaces = None self.connection_namespaces = None
self.socketio_path = None self.socketio_path = None
self.namespaces = None self.namespaces = []
self.handlers = {} self.handlers = {}
self.namespace_handlers = {} self.namespace_handlers = {}
self.callbacks = {} self.callbacks = {}
@ -245,7 +245,21 @@ class Client(object):
id = self._generate_ack_id(namespace, callback) id = self._generate_ack_id(namespace, callback)
else: else:
id = None id = None
self._emit_internal(event, data, namespace, id) if six.PY2 and not self.binary:
binary = False # pragma: nocover
else:
binary = None
# tuples are expanded to multiple arguments, everything else is sent
# as a single argument
if isinstance(data, tuple):
data = list(data)
elif data is not None:
data = [data]
else:
data = []
self._send_packet(packet.Packet(packet.EVENT, namespace=namespace,
data=[event] + data, id=id,
binary=binary))
def send(self, data, namespace=None, callback=None): def send(self, data, namespace=None, callback=None):
"""Send a message to one or more connected clients. """Send a message to one or more connected clients.
@ -265,7 +279,8 @@ class Client(object):
by the client. Callback functions can only be used by the client. Callback functions can only be used
when addressing an individual client. when addressing an individual client.
""" """
self.emit('message', data, namespace, callback) self.emit('message', data=data, namespace=namespace,
callback=callback)
def disconnect(self): def disconnect(self):
"""Disconnect from the server.""" """Disconnect from the server."""
@ -311,24 +326,6 @@ class Client(object):
""" """
return self.eio.sleep(seconds) return self.eio.sleep(seconds)
def _emit_internal(self, event, data, namespace=None, id=None):
"""Send a message to a client."""
if six.PY2 and not self.binary:
binary = False # pragma: nocover
else:
binary = None
# tuples are expanded to multiple arguments, everything else is sent
# as a single argument
if isinstance(data, tuple):
data = list(data)
elif data is not None:
data = [data]
else:
data = []
self._send_packet(packet.Packet(packet.EVENT, namespace=namespace,
data=[event] + data, id=id,
binary=binary))
def _send_packet(self, pkt): def _send_packet(self, pkt):
"""Send a Socket.IO packet to the server.""" """Send a Socket.IO packet to the server."""
encoded_packet = pkt.encode() encoded_packet = pkt.encode()
@ -356,6 +353,8 @@ class Client(object):
if namespace == '/': if namespace == '/':
for n in self.namespaces: for n in self.namespaces:
self._send_packet(packet.Packet(packet.CONNECT, namespace=n)) self._send_packet(packet.Packet(packet.CONNECT, namespace=n))
elif namespace not in self.namespaces:
self.namespaces.append(namespace)
def _handle_disconnect(self, namespace): def _handle_disconnect(self, namespace):
namespace = namespace or '/' namespace = namespace or '/'
@ -366,9 +365,6 @@ class Client(object):
def _handle_event(self, namespace, id, data): def _handle_event(self, namespace, id, data):
namespace = namespace or '/' namespace = namespace or '/'
self.logger.info('Received event "%s" [%s]', data[0], namespace) self.logger.info('Received event "%s" [%s]', data[0], namespace)
self._handle_event_internal(data, namespace, id)
def _handle_event_internal(self, data, namespace, id):
r = self._trigger_event(data[0], namespace, *data[1:]) r = self._trigger_event(data[0], namespace, *data[1:])
if id is not None: if id is not None:
# send ACK packet with the response returned by the handler # send ACK packet with the response returned by the handler
@ -400,7 +396,7 @@ class Client(object):
if callback is not None: if callback is not None:
callback(*data) callback(*data)
def _handle_error(self, namespace, data): def _handle_error(self, namespace):
namespace = namespace or '/' namespace = namespace or '/'
self.logger.info('Connection to namespace {} was rejected'.format( self.logger.info('Connection to namespace {} was rejected'.format(
namespace)) namespace))
@ -413,7 +409,7 @@ class Client(object):
if namespace in self.handlers and event in self.handlers[namespace]: if namespace in self.handlers and event in self.handlers[namespace]:
return self.handlers[namespace][event](*args) return self.handlers[namespace][event](*args)
# or else, forward the event to a namepsace handler if one exists # or else, forward the event to a namespace handler if one exists
elif namespace in self.namespace_handlers: elif namespace in self.namespace_handlers:
return self.namespace_handlers[namespace].trigger_event( return self.namespace_handlers[namespace].trigger_event(
event, *args) event, *args)
@ -449,7 +445,7 @@ class Client(object):
'Maximum reconnection attempts reached, giving up') 'Maximum reconnection attempts reached, giving up')
break break
def _handle_eio_connect(self): def _handle_eio_connect(self): # pragma: no cover
"""Handle the Engine.IO connection event.""" """Handle the Engine.IO connection event."""
self.logger.info('Engine.IO connection established') self.logger.info('Engine.IO connection established')
@ -477,7 +473,7 @@ class Client(object):
pkt.packet_type == packet.BINARY_ACK: pkt.packet_type == packet.BINARY_ACK:
self._binary_packet = pkt self._binary_packet = pkt
elif pkt.packet_type == packet.ERROR: elif pkt.packet_type == packet.ERROR:
self._handle_error(pkt.namespace, pkt.data) self._handle_error(pkt.namespace)
else: else:
raise ValueError('Unknown packet type.') raise ValueError('Unknown packet type.')

2
socketio/namespace.py

@ -124,7 +124,7 @@ class ClientNamespace(BaseNamespace):
omitted, the default namespace is used. omitted, the default namespace is used.
""" """
def __init__(self, namespace=None): def __init__(self, namespace=None):
super(Namespace, self).__init__(namespace=namespace) super(ClientNamespace, self).__init__(namespace=namespace)
self.client = None self.client = None
def _set_client(self, client): def _set_client(self, client):

2
socketio/server.py

@ -489,7 +489,7 @@ class Server(object):
if namespace in self.handlers and event in self.handlers[namespace]: if namespace in self.handlers and event in self.handlers[namespace]:
return self.handlers[namespace][event](*args) return self.handlers[namespace][event](*args)
# or else, forward the event to a namepsace handler if one exists # or else, forward the event to a namespace handler if one exists
elif namespace in self.namespace_handlers: elif namespace in self.namespace_handlers:
return self.namespace_handlers[namespace].trigger_event( return self.namespace_handlers[namespace].trigger_event(
event, *args) event, *args)

631
tests/test_client.py

@ -0,0 +1,631 @@
import json
import logging
import sys
import unittest
import six
if six.PY3:
from unittest import mock
else:
import mock
from engineio import exceptions as engineio_exceptions
from engineio import packet as engineio_packet
if six.PY3:
from socketio import asyncio_namespace
else:
asyncio_namespace = None
from socketio import client
from socketio import exceptions
from socketio import namespace
from socketio import packet
class TesClient(unittest.TestCase):
def test_is_asyncio_based(self):
c = client.Client()
self.assertEqual(c.is_asyncio_based(), False)
@mock.patch('socketio.client.Client._engineio_client_class')
def test_create(self, engineio_client_class):
c = client.Client(reconnection=False, reconnection_attempts=123,
reconnection_delay=5, reconnection_delay_max=10,
randomization_factor=0.2, binary=True, foo='bar')
self.assertEqual(c.reconnection, False)
self.assertEqual(c.reconnection_attempts, 123)
self.assertEqual(c.reconnection_delay, 5)
self.assertEqual(c.reconnection_delay_max, 10)
self.assertEqual(c.randomization_factor, 0.2)
self.assertEqual(c.binary, True)
engineio_client_class().assert_called_once_with(foo='bar')
self.assertEqual(c.connection_url, None)
self.assertEqual(c.connection_headers, None)
self.assertEqual(c.connection_transports, None)
self.assertEqual(c.connection_namespaces, None)
self.assertEqual(c.socketio_path, None)
self.assertEqual(c.namespaces, [])
self.assertEqual(c.handlers, {})
self.assertEqual(c.namespace_handlers, {})
self.assertEqual(c.callbacks, {})
self.assertEqual(c._binary_packet, None)
self.assertEqual(c._reconnect_task, None)
def test_custon_json(self):
client.Client()
self.assertEqual(packet.Packet.json, json)
self.assertEqual(engineio_packet.Packet.json, json)
client.Client(json='foo')
self.assertEqual(packet.Packet.json, 'foo')
self.assertEqual(engineio_packet.Packet.json, 'foo')
packet.Packet.json = json
def test_logger(self):
c = client.Client(logger=False)
self.assertEqual(c.logger.getEffectiveLevel(), logging.ERROR)
c.logger.setLevel(logging.NOTSET)
c = client.Client(logger=True)
self.assertEqual(c.logger.getEffectiveLevel(), logging.INFO)
c.logger.setLevel(logging.WARNING)
c = client.Client(logger=True)
self.assertEqual(c.logger.getEffectiveLevel(), logging.WARNING)
c.logger.setLevel(logging.NOTSET)
my_logger = logging.Logger('foo')
c = client.Client(logger=my_logger)
self.assertEqual(c.logger, my_logger)
def test_on_event(self):
c = client.Client()
@c.on('connect')
def foo():
pass
def bar():
pass
c.on('disconnect', bar)
c.on('disconnect', bar, namespace='/foo')
self.assertEqual(c.handlers['/']['connect'], foo)
self.assertEqual(c.handlers['/']['disconnect'], bar)
self.assertEqual(c.handlers['/foo']['disconnect'], bar)
def test_namespace_handler(self):
class MyNamespace(namespace.ClientNamespace):
pass
c = client.Client()
n = MyNamespace('/foo')
c.register_namespace(n)
self.assertEqual(c.namespace_handlers['/foo'], n)
def test_namespace_handler_wrong_class(self):
class MyNamespace(object):
def __init__(self, n):
pass
c = client.Client()
n = MyNamespace('/foo')
self.assertRaises(ValueError, c.register_namespace, n)
@unittest.skipIf(sys.version_info < (3, 0), 'only for Python 3')
def test_namespace_handler_wrong_async(self):
class MyNamespace(asyncio_namespace.AsyncClientNamespace):
pass
c = client.Client()
n = MyNamespace('/foo')
self.assertRaises(ValueError, c.register_namespace, n)
def test_connect(self):
c = client.Client()
c.eio.connect = mock.MagicMock()
c.connect('url', headers='headers', transports='transports',
namespaces=['/foo', '/', '/bar'], socketio_path='path')
self.assertEqual(c.connection_url, 'url')
self.assertEqual(c.connection_headers, 'headers')
self.assertEqual(c.connection_transports, 'transports')
self.assertEqual(c.connection_namespaces, ['/foo', '/', '/bar'])
self.assertEqual(c.socketio_path, 'path')
self.assertEqual(c.namespaces, ['/foo', '/bar'])
c.eio.connect.assert_called_once_with(
'url', headers='headers', transports='transports',
engineio_path='path')
def test_connect_default_namespaces(self):
c = client.Client()
c.eio.connect = mock.MagicMock()
c.on('foo', mock.MagicMock(), namespace='/foo')
c.on('bar', mock.MagicMock(), namespace='/')
c.connect('url', headers='headers', transports='transports',
socketio_path='path')
self.assertEqual(c.connection_url, 'url')
self.assertEqual(c.connection_headers, 'headers')
self.assertEqual(c.connection_transports, 'transports')
self.assertEqual(c.connection_namespaces, None)
self.assertEqual(c.socketio_path, 'path')
self.assertEqual(c.namespaces, ['/foo'])
c.eio.connect.assert_called_once_with(
'url', headers='headers', transports='transports',
engineio_path='path')
def test_connect_error(self):
c = client.Client()
c.eio.connect = mock.MagicMock(
side_effect=engineio_exceptions.ConnectionError('foo'))
c.on('foo', mock.MagicMock(), namespace='/foo')
c.on('bar', mock.MagicMock(), namespace='/')
self.assertRaises(
exceptions.ConnectionError, c.connect, 'url', headers='headers',
transports='transports', socketio_path='path')
def test_wait_no_reconnect(self):
c = client.Client()
c.eio.wait = mock.MagicMock()
c.sleep = mock.MagicMock()
c._reconnect_task = None
c.wait()
c.eio.wait.assert_called_once_with()
c.sleep.assert_called_once_with(1)
def test_wait_reconnect_failed(self):
c = client.Client()
c.eio.wait = mock.MagicMock()
c.sleep = mock.MagicMock()
c._reconnect_task = mock.MagicMock()
states = ['disconnected']
def fake_join():
c.eio.state = states.pop(0)
c._reconnect_task.join = fake_join
c.wait()
c.eio.wait.assert_called_once_with()
c.sleep.assert_called_once_with(1)
def test_wait_reconnect_successful(self):
c = client.Client()
c.eio.wait = mock.MagicMock()
c.sleep = mock.MagicMock()
c._reconnect_task = mock.MagicMock()
states = ['connected', 'disconnected']
def fake_join():
c.eio.state = states.pop(0)
c._reconnect_task.join = fake_join
c.wait()
self.assertEqual(c.eio.wait.call_count, 2)
self.assertEqual(c.sleep.call_count, 2)
def test_emit_no_arguments(self):
c = client.Client()
c._send_packet = mock.MagicMock()
c.emit('foo')
expected_packet = packet.Packet(packet.EVENT, namespace='/',
data=['foo'], id=None, binary=False)
self.assertEqual(c._send_packet.call_count, 1)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_emit_one_argument(self):
c = client.Client()
c._send_packet = mock.MagicMock()
c.emit('foo', 'bar')
expected_packet = packet.Packet(packet.EVENT, namespace='/',
data=['foo', 'bar'], id=None,
binary=False)
self.assertEqual(c._send_packet.call_count, 1)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_emit_one_argument_list(self):
c = client.Client()
c._send_packet = mock.MagicMock()
c.emit('foo', ['bar', 'baz'])
expected_packet = packet.Packet(packet.EVENT, namespace='/',
data=['foo', ['bar', 'baz']], id=None,
binary=False)
self.assertEqual(c._send_packet.call_count, 1)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_emit_two_arguments(self):
c = client.Client()
c._send_packet = mock.MagicMock()
c.emit('foo', ('bar', 'baz'))
expected_packet = packet.Packet(packet.EVENT, namespace='/',
data=['foo', 'bar', 'baz'], id=None,
binary=False)
self.assertEqual(c._send_packet.call_count, 1)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_emit_namespace(self):
c = client.Client()
c._send_packet = mock.MagicMock()
c.emit('foo', namespace='/foo')
expected_packet = packet.Packet(packet.EVENT, namespace='/foo',
data=['foo'], id=None, binary=False)
self.assertEqual(c._send_packet.call_count, 1)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_emit_with_callback(self):
c = client.Client()
c._send_packet = mock.MagicMock()
c._generate_ack_id = mock.MagicMock(return_value=123)
c.emit('foo', callback='cb')
expected_packet = packet.Packet(packet.EVENT, namespace='/',
data=['foo'], id=123, binary=False)
self.assertEqual(c._send_packet.call_count, 1)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
c._generate_ack_id.assert_called_once_with('/', 'cb')
def test_emit_namespace_with_callback(self):
c = client.Client()
c._send_packet = mock.MagicMock()
c._generate_ack_id = mock.MagicMock(return_value=123)
c.emit('foo', namespace='/foo', callback='cb')
expected_packet = packet.Packet(packet.EVENT, namespace='/foo',
data=['foo'], id=123, binary=False)
self.assertEqual(c._send_packet.call_count, 1)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
c._generate_ack_id.assert_called_once_with('/foo', 'cb')
def test_emit_binary(self):
c = client.Client(binary=True)
c._send_packet = mock.MagicMock()
c.emit('foo', b'bar')
expected_packet = packet.Packet(packet.EVENT, namespace='/',
data=['foo', b'bar'], id=None,
binary=True)
self.assertEqual(c._send_packet.call_count, 1)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_emit_not_binary(self):
c = client.Client(binary=False)
c._send_packet = mock.MagicMock()
c.emit('foo', 'bar')
expected_packet = packet.Packet(packet.EVENT, namespace='/',
data=['foo', 'bar'], id=None,
binary=False)
self.assertEqual(c._send_packet.call_count, 1)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_send(self):
c = client.Client()
c.emit = mock.MagicMock()
c.send('data', 'namespace', 'callback')
c.emit.assert_called_once_with(
'message', data='data', namespace='namespace',
callback='callback')
def test_send_with_defaults(self):
c = client.Client()
c.emit = mock.MagicMock()
c.send('data')
c.emit.assert_called_once_with(
'message', data='data', namespace=None, callback=None)
def test_disconnect(self):
c = client.Client()
c._trigger_event = mock.MagicMock()
c._send_packet = mock.MagicMock()
c.disconnect()
c._trigger_event.assert_called_once_with('disconnect', namespace='/')
self.assertEqual(c._send_packet.call_count, 1)
expected_packet = packet.Packet(packet.DISCONNECT, namespace='/')
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_disconnect_namespaces(self):
c = client.Client()
c.namespaces = ['/foo', '/bar']
c._trigger_event = mock.MagicMock()
c._send_packet = mock.MagicMock()
c.disconnect()
self.assertEqual(c._trigger_event.call_args_list, [
mock.call('disconnect', namespace='/foo'),
mock.call('disconnect', namespace='/bar'),
mock.call('disconnect', namespace='/')
])
self.assertEqual(c._send_packet.call_count, 3)
expected_packet = packet.Packet(packet.DISCONNECT, namespace='/foo')
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
expected_packet = packet.Packet(packet.DISCONNECT, namespace='/bar')
self.assertEqual(c._send_packet.call_args_list[1][0][0].encode(),
expected_packet.encode())
expected_packet = packet.Packet(packet.DISCONNECT, namespace='/')
self.assertEqual(c._send_packet.call_args_list[2][0][0].encode(),
expected_packet.encode())
def test_transport(self):
c = client.Client()
c.eio.transport = mock.MagicMock(return_value='foo')
self.assertEqual(c.transport(), 'foo')
c.eio.transport.assert_called_once_with()
def test_start_background_task(self):
c = client.Client()
c.eio.start_background_task = mock.MagicMock(return_value='foo')
self.assertEqual(c.start_background_task('foo', 'bar', baz='baz'),
'foo')
c.eio.start_background_task.assert_called_once_with('foo', 'bar',
baz='baz')
def test_sleep(self):
c = client.Client()
c.eio.sleep = mock.MagicMock()
c.sleep(1.23)
c.eio.sleep.assert_called_once_with(1.23)
def test_send_packet(self):
c = client.Client()
c.eio.send = mock.MagicMock()
c._send_packet(packet.Packet(packet.EVENT, 'foo', binary=False))
c.eio.send.assert_called_once_with('2"foo"', binary=False)
def test_send_packet_binary(self):
c = client.Client()
c.eio.send = mock.MagicMock()
c._send_packet(packet.Packet(packet.EVENT, b'foo', binary=True))
self.assertTrue(c.eio.send.call_args_list == [
mock.call('51-{"_placeholder":true,"num":0}', binary=False),
mock.call(b'foo', binary=True)
] or c.eio.send.call_args_list == [
mock.call('51-{"num":0,"_placeholder":true}', binary=False),
mock.call(b'foo', binary=True)
])
@unittest.skipIf(sys.version_info < (3, 0), 'only for Python 3')
def test_send_packet_default_binary_py3(self):
c = client.Client()
c.eio.send = mock.MagicMock()
c._send_packet(packet.Packet(packet.EVENT, 'foo'))
c.eio.send.assert_called_once_with('2"foo"', binary=False)
@unittest.skipIf(sys.version_info >= (3, 0), 'only for Python 2')
def test_send_packet_default_binary_py2(self):
c = client.Client()
c.eio.send = mock.MagicMock()
c._send_packet(packet.Packet(packet.EVENT, 'foo'))
self.assertTrue(c.eio.send.call_args_list == [
mock.call('51-{"_placeholder":true,"num":0}', binary=False),
mock.call(b'foo', binary=True)
] or c.eio.send.call_args_list == [
mock.call('51-{"num":0,"_placeholder":true}', binary=False),
mock.call(b'foo', binary=True)
])
def test_generate_ack_id(self):
c = client.Client()
self.assertEqual(c._generate_ack_id('/', 'cb'), 1)
self.assertEqual(c._generate_ack_id('/', 'cb'), 2)
self.assertEqual(c._generate_ack_id('/', 'cb'), 3)
self.assertEqual(c._generate_ack_id('/foo', 'cb'), 1)
self.assertEqual(c._generate_ack_id('/bar', 'cb'), 1)
self.assertEqual(c._generate_ack_id('/', 'cb'), 4)
self.assertEqual(c._generate_ack_id('/bar', 'cb'), 2)
def test_handle_connect(self):
c = client.Client()
c._trigger_event = mock.MagicMock()
c._send_packet = mock.MagicMock()
c._handle_connect('/')
c._trigger_event.assert_called_once_with('connect', namespace='/')
c._send_packet.assert_not_called()
def test_handle_connect_with_namespaces(self):
c = client.Client()
c.namespaces = ['/foo', '/bar']
c._trigger_event = mock.MagicMock()
c._send_packet = mock.MagicMock()
c._handle_connect('/')
c._trigger_event.assert_called_once_with('connect', namespace='/')
self.assertEqual(c._send_packet.call_count, 2)
expected_packet = packet.Packet(packet.CONNECT, namespace='/foo')
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
expected_packet = packet.Packet(packet.CONNECT, namespace='/bar')
self.assertEqual(c._send_packet.call_args_list[1][0][0].encode(),
expected_packet.encode())
def test_handle_connect_namespace(self):
c = client.Client()
c.namespaces = ['/foo']
c._trigger_event = mock.MagicMock()
c._send_packet = mock.MagicMock()
c._handle_connect('/foo')
c._handle_connect('/bar')
self.assertEqual(c._trigger_event.call_args_list, [
mock.call('connect', namespace='/foo'),
mock.call('connect', namespace='/bar')
])
c._send_packet.assert_not_called()
self.assertEqual(c.namespaces, ['/foo', '/bar'])
def test_handle_disconnect(self):
c = client.Client()
c._trigger_event = mock.MagicMock()
c._handle_disconnect('/')
c._trigger_event.assert_called_once_with('disconnect', namespace='/')
def test_handle_disconnect_namespace(self):
c = client.Client()
c.namespaces = ['/foo', '/bar']
c._trigger_event = mock.MagicMock()
c._handle_disconnect('/foo')
c._trigger_event.assert_called_once_with('disconnect',
namespace='/foo')
self.assertEqual(c.namespaces, ['/bar'])
def test_handle_disconnect_unknown_namespace(self):
c = client.Client()
c.namespaces = ['/foo', '/bar']
c._trigger_event = mock.MagicMock()
c._handle_disconnect('/baz')
c._trigger_event.assert_called_once_with('disconnect',
namespace='/baz')
self.assertEqual(c.namespaces, ['/foo', '/bar'])
def test_handle_event(self):
c = client.Client()
c._trigger_event = mock.MagicMock()
c._handle_event('/', None, ['foo', ('bar', 'baz')])
c._trigger_event.assert_called_once_with('foo', '/', ('bar', 'baz'))
def test_handle_event_with_id_no_arguments(self):
c = client.Client(binary=True)
c._trigger_event = mock.MagicMock(return_value=None)
c._send_packet = mock.MagicMock()
c._handle_event('/', 123, ['foo', ('bar', 'baz')])
c._trigger_event.assert_called_once_with('foo', '/', ('bar', 'baz'))
self.assertEqual(c._send_packet.call_count, 1)
expected_packet = packet.Packet(packet.ACK, namespace='/', id=123,
data=[], binary=None)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_handle_event_with_id_one_argument(self):
c = client.Client(binary=True)
c._trigger_event = mock.MagicMock(return_value='ret')
c._send_packet = mock.MagicMock()
c._handle_event('/', 123, ['foo', ('bar', 'baz')])
c._trigger_event.assert_called_once_with('foo', '/', ('bar', 'baz'))
self.assertEqual(c._send_packet.call_count, 1)
expected_packet = packet.Packet(packet.ACK, namespace='/', id=123,
data=['ret'], binary=None)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_handle_event_with_id_one_list_argument(self):
c = client.Client(binary=True)
c._trigger_event = mock.MagicMock(return_value=['a', 'b'])
c._send_packet = mock.MagicMock()
c._handle_event('/', 123, ['foo', ('bar', 'baz')])
c._trigger_event.assert_called_once_with('foo', '/', ('bar', 'baz'))
self.assertEqual(c._send_packet.call_count, 1)
expected_packet = packet.Packet(packet.ACK, namespace='/', id=123,
data=[['a', 'b']], binary=None)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_handle_event_with_id_two_arguments(self):
c = client.Client(binary=True)
c._trigger_event = mock.MagicMock(return_value=('a', 'b'))
c._send_packet = mock.MagicMock()
c._handle_event('/', 123, ['foo', ('bar', 'baz')])
c._trigger_event.assert_called_once_with('foo', '/', ('bar', 'baz'))
self.assertEqual(c._send_packet.call_count, 1)
expected_packet = packet.Packet(packet.ACK, namespace='/', id=123,
data=['a', 'b'], binary=None)
self.assertEqual(c._send_packet.call_args_list[0][0][0].encode(),
expected_packet.encode())
def test_handle_ack(self):
c = client.Client()
mock_cb = mock.MagicMock()
c.callbacks['/foo'] = {123: mock_cb}
c._handle_ack('/foo', 123, ['bar', 'baz'])
mock_cb.assert_called_once_with('bar', 'baz')
self.assertNotIn(123, c.callbacks['/foo'])
def test_handle_ack_not_found(self):
c = client.Client()
mock_cb = mock.MagicMock()
c.callbacks['/foo'] = {123: mock_cb}
c._handle_ack('/foo', 124, ['bar', 'baz'])
mock_cb.assert_not_called()
self.assertIn(123, c.callbacks['/foo'])
def test_handle_error(self):
c = client.Client()
c.namespaces = ['/foo', '/bar']
c._handle_error('/bar')
self.assertEqual(c.namespaces, ['/foo'])
def test_handle_error_unknown_namespace(self):
c = client.Client()
c.namespaces = ['/foo', '/bar']
c._handle_error('/baz')
self.assertEqual(c.namespaces, ['/foo', '/bar'])
def test_trigger_event(self):
c = client.Client()
handler = mock.MagicMock()
c.on('foo', handler)
c._trigger_event('foo', '/', 1, '2')
handler.assert_called_once_with(1, '2')
def test_trigger_event_namespace(self):
c = client.Client()
handler = mock.MagicMock()
c.on('foo', handler, namespace='/bar')
c._trigger_event('foo', '/bar', 1, '2')
handler.assert_called_once_with(1, '2')
def test_trigger_event_class_namespace(self):
c = client.Client()
result = []
class MyNamespace(namespace.ClientNamespace):
def on_foo(self, a, b):
result.append(a)
result.append(b)
c.register_namespace(MyNamespace('/'))
c._trigger_event('foo', '/', 1, '2')
self.assertEqual(result, [1, '2'])
@mock.patch('socketio.client.random.random', side_effect=[1, 0, 0.5])
def test_handle_reconnect(self, random):
c = client.Client()
c._reconnect_task = 'foo'
c.sleep = mock.MagicMock()
c.connect = mock.MagicMock(side_effect=[ValueError,
exceptions.ConnectionError, None])
c._handle_reconnect()
self.assertEqual(c.sleep.call_count, 3)
self.assertEqual(c.sleep.call_args_list, [
mock.call(1.5),
mock.call(1.5),
mock.call(4.0)
])
self.assertEqual(c._reconnect_task, None)
@mock.patch('socketio.client.random.random', side_effect=[1, 0, 0.5])
def test_handle_reconnect_max_delay(self, random):
c = client.Client(reconnection_delay_max=3)
c._reconnect_task = 'foo'
c.sleep = mock.MagicMock()
c.connect = mock.MagicMock(side_effect=[ValueError,
exceptions.ConnectionError, None])
c._handle_reconnect()
self.assertEqual(c.sleep.call_count, 3)
self.assertEqual(c.sleep.call_args_list, [
mock.call(1.5),
mock.call(1.5),
mock.call(3.0)
])
self.assertEqual(c._reconnect_task, None)
@mock.patch('socketio.client.random.random', side_effect=[1, 0, 0.5])
def test_handle_reconnect_max_attempts(self, random):
c = client.Client(reconnection_attempts=2)
c._reconnect_task = 'foo'
c.sleep = mock.MagicMock()
c.connect = mock.MagicMock(side_effect=[ValueError,
exceptions.ConnectionError, None])
c._handle_reconnect()
self.assertEqual(c.sleep.call_count, 2)
self.assertEqual(c.sleep.call_args_list, [
mock.call(1.5),
mock.call(1.5)
])
self.assertEqual(c._reconnect_task, 'foo')

3
tox.ini

@ -1,5 +1,5 @@
[tox] [tox]
envlist=flake8,py27,py34,py35,py36,py37,pypy,pypy3,docs,coverage envlist=flake8,py27,py35,py36,py37,pypy,pypy3,docs,coverage
skip_missing_interpreters=True skip_missing_interpreters=True
[testenv] [testenv]
@ -13,7 +13,6 @@ deps=
basepython = basepython =
flake8: python3.6 flake8: python3.6
py27: python2.7 py27: python2.7
py34: python3.4
py35: python3.5 py35: python3.5
py36: python3.6 py36: python3.6
py37: python3.7 py37: python3.7

Loading…
Cancel
Save