pythonasyncioeventletgeventlong-pollinglow-latencysocket-iosocketiosocketio-serverweb-serverwebsocket
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1332 lines
47 KiB
1332 lines
47 KiB
import logging
|
|
import time
|
|
from unittest import mock
|
|
|
|
from engineio import exceptions as engineio_exceptions
|
|
from engineio import json
|
|
from engineio import packet as engineio_packet
|
|
import pytest
|
|
|
|
from socketio import async_namespace
|
|
from socketio import client
|
|
from socketio import exceptions
|
|
from socketio import msgpack_packet
|
|
from socketio import namespace
|
|
from socketio import packet
|
|
|
|
|
|
class TestClient:
|
|
def test_is_asyncio_based(self):
|
|
c = client.Client()
|
|
assert not c.is_asyncio_based()
|
|
|
|
@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,
|
|
handle_sigint=False,
|
|
foo='bar',
|
|
)
|
|
assert not c.reconnection
|
|
assert c.reconnection_attempts == 123
|
|
assert c.reconnection_delay == 5
|
|
assert c.reconnection_delay_max == 10
|
|
assert c.randomization_factor == 0.2
|
|
assert not c.handle_sigint
|
|
engineio_client_class().assert_called_once_with(
|
|
foo='bar', handle_sigint=False)
|
|
assert c.connection_url is None
|
|
assert c.connection_headers is None
|
|
assert c.connection_transports is None
|
|
assert c.connection_namespaces == []
|
|
assert c.socketio_path is None
|
|
assert c.sid is None
|
|
|
|
assert c.namespaces == {}
|
|
assert c.handlers == {}
|
|
assert c.namespace_handlers == {}
|
|
assert c.callbacks == {}
|
|
assert c._binary_packet is None
|
|
assert c._reconnect_task is None
|
|
assert c.packet_class == packet.Packet
|
|
|
|
def test_msgpack(self):
|
|
c = client.Client(serializer='msgpack')
|
|
assert c.packet_class == msgpack_packet.MsgPackPacket
|
|
|
|
def test_custom_serializer(self):
|
|
class CustomPacket(packet.Packet):
|
|
pass
|
|
|
|
c = client.Client(serializer=CustomPacket)
|
|
assert c.packet_class == CustomPacket
|
|
|
|
def test_custom_json(self):
|
|
client.Client()
|
|
assert packet.Packet.json == json
|
|
assert engineio_packet.Packet.json == json
|
|
client.Client(json='foo')
|
|
assert packet.Packet.json == 'foo'
|
|
assert engineio_packet.Packet.json == 'foo'
|
|
packet.Packet.json = json
|
|
|
|
def test_logger(self):
|
|
c = client.Client(logger=False)
|
|
assert c.logger.getEffectiveLevel() == logging.ERROR
|
|
c.logger.setLevel(logging.NOTSET)
|
|
c = client.Client(logger=True)
|
|
assert c.logger.getEffectiveLevel() == logging.INFO
|
|
c.logger.setLevel(logging.WARNING)
|
|
c = client.Client(logger=True)
|
|
assert c.logger.getEffectiveLevel() == logging.WARNING
|
|
c.logger.setLevel(logging.NOTSET)
|
|
my_logger = logging.Logger('foo')
|
|
c = client.Client(logger=my_logger)
|
|
assert c.logger == my_logger
|
|
|
|
@mock.patch('socketio.client.Client._engineio_client_class')
|
|
def test_engineio_logger(self, engineio_client_class):
|
|
client.Client(engineio_logger='foo')
|
|
engineio_client_class().assert_called_once_with(
|
|
handle_sigint=True, logger='foo')
|
|
|
|
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')
|
|
|
|
assert c.handlers['/']['connect'] == foo
|
|
assert c.handlers['/']['disconnect'] == bar
|
|
assert c.handlers['/foo']['disconnect'] == bar
|
|
|
|
def test_event(self):
|
|
c = client.Client()
|
|
|
|
@c.event
|
|
def connect():
|
|
pass
|
|
|
|
@c.event
|
|
def foo():
|
|
pass
|
|
|
|
@c.event
|
|
def bar():
|
|
pass
|
|
|
|
@c.event(namespace='/foo')
|
|
def disconnect():
|
|
pass
|
|
|
|
assert c.handlers['/']['connect'] == connect
|
|
assert c.handlers['/']['foo'] == foo
|
|
assert c.handlers['/']['bar'] == bar
|
|
assert c.handlers['/foo']['disconnect'] == disconnect
|
|
|
|
def test_namespace_handler(self):
|
|
class MyNamespace(namespace.ClientNamespace):
|
|
pass
|
|
|
|
c = client.Client()
|
|
n = MyNamespace('/foo')
|
|
c.register_namespace(n)
|
|
assert c.namespace_handlers['/foo'] == n
|
|
|
|
def test_namespace_handler_wrong_class(self):
|
|
class MyNamespace:
|
|
def __init__(self, n):
|
|
pass
|
|
|
|
c = client.Client()
|
|
n = MyNamespace('/foo')
|
|
with pytest.raises(ValueError):
|
|
c.register_namespace(n)
|
|
|
|
def test_namespace_handler_wrong_async(self):
|
|
class MyNamespace(async_namespace.AsyncClientNamespace):
|
|
pass
|
|
|
|
c = client.Client()
|
|
n = MyNamespace('/foo')
|
|
with pytest.raises(ValueError):
|
|
c.register_namespace(n)
|
|
|
|
def test_connect(self):
|
|
c = client.Client()
|
|
c.eio.connect = mock.MagicMock()
|
|
c.connect(
|
|
'url',
|
|
headers='headers',
|
|
auth='auth',
|
|
transports='transports',
|
|
namespaces=['/foo', '/', '/bar'],
|
|
socketio_path='path',
|
|
wait=False,
|
|
)
|
|
assert c.connection_url == 'url'
|
|
assert c.connection_headers == 'headers'
|
|
assert c.connection_auth == 'auth'
|
|
assert c.connection_transports == 'transports'
|
|
assert c.connection_namespaces == ['/foo', '/', '/bar']
|
|
assert c.socketio_path == 'path'
|
|
c.eio.connect.assert_called_once_with(
|
|
'url',
|
|
headers='headers',
|
|
transports='transports',
|
|
engineio_path='path',
|
|
)
|
|
|
|
def test_connect_functions(self):
|
|
c = client.Client()
|
|
c.eio.connect = mock.MagicMock()
|
|
c.connect(
|
|
lambda: 'url',
|
|
headers=lambda: 'headers',
|
|
auth='auth',
|
|
transports='transports',
|
|
namespaces=['/foo', '/', '/bar'],
|
|
socketio_path='path',
|
|
wait=False,
|
|
)
|
|
c.eio.connect.assert_called_once_with(
|
|
'url',
|
|
headers='headers',
|
|
transports='transports',
|
|
engineio_path='path',
|
|
)
|
|
|
|
def test_connect_one_namespace(self):
|
|
c = client.Client()
|
|
c.eio.connect = mock.MagicMock()
|
|
c.connect(
|
|
'url',
|
|
headers='headers',
|
|
transports='transports',
|
|
namespaces='/foo',
|
|
socketio_path='path',
|
|
wait=False,
|
|
)
|
|
assert c.connection_url == 'url'
|
|
assert c.connection_headers == 'headers'
|
|
assert c.connection_transports == 'transports'
|
|
assert c.connection_namespaces == ['/foo']
|
|
assert c.socketio_path == 'path'
|
|
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.on('baz', mock.MagicMock(), namespace='*')
|
|
c.connect(
|
|
'url',
|
|
headers='headers',
|
|
transports='transports',
|
|
socketio_path='path',
|
|
wait=False,
|
|
)
|
|
assert c.connection_url == 'url'
|
|
assert c.connection_headers == 'headers'
|
|
assert c.connection_transports == 'transports'
|
|
assert c.connection_namespaces == ['/foo', '/'] or \
|
|
c.connection_namespaces == ['/', '/foo']
|
|
assert c.socketio_path == 'path'
|
|
c.eio.connect.assert_called_once_with(
|
|
'url',
|
|
headers='headers',
|
|
transports='transports',
|
|
engineio_path='path',
|
|
)
|
|
|
|
def test_connect_no_namespaces(self):
|
|
c = client.Client()
|
|
c.eio.connect = mock.MagicMock()
|
|
c.connect(
|
|
'url',
|
|
headers='headers',
|
|
transports='transports',
|
|
socketio_path='path',
|
|
wait=False,
|
|
)
|
|
assert c.connection_url == 'url'
|
|
assert c.connection_headers == 'headers'
|
|
assert c.connection_transports == 'transports'
|
|
assert c.connection_namespaces == ['/']
|
|
assert c.socketio_path == 'path'
|
|
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='/')
|
|
with pytest.raises(exceptions.ConnectionError):
|
|
c.connect(
|
|
'url',
|
|
headers='headers',
|
|
transports='transports',
|
|
socketio_path='path',
|
|
wait=False,
|
|
)
|
|
|
|
def test_connect_twice(self):
|
|
c = client.Client()
|
|
c.eio.connect = mock.MagicMock()
|
|
c.connect(
|
|
'url',
|
|
wait=False,
|
|
)
|
|
with pytest.raises(exceptions.ConnectionError):
|
|
c.connect(
|
|
'url',
|
|
wait=False,
|
|
)
|
|
|
|
def test_connect_wait_single_namespace(self):
|
|
c = client.Client()
|
|
c.eio.connect = mock.MagicMock()
|
|
c._connect_event = mock.MagicMock()
|
|
|
|
def mock_connect(timeout):
|
|
assert timeout == 0.01
|
|
c.namespaces = {'/': '123'}
|
|
return True
|
|
|
|
c._connect_event.wait = mock_connect
|
|
c.connect(
|
|
'url',
|
|
wait=True,
|
|
wait_timeout=0.01,
|
|
)
|
|
assert c.connected is True
|
|
|
|
def test_connect_wait_two_namespaces(self):
|
|
c = client.Client()
|
|
c.eio.connect = mock.MagicMock()
|
|
c._connect_event = mock.MagicMock()
|
|
|
|
def mock_connect(timeout):
|
|
assert timeout == 0.01
|
|
if c.namespaces == {}:
|
|
c.namespaces = {'/bar': '123'}
|
|
return True
|
|
elif c.namespaces == {'/bar': '123'}:
|
|
c.namespaces = {'/bar': '123', '/foo': '456'}
|
|
return True
|
|
return False
|
|
|
|
c._connect_event.wait = mock_connect
|
|
c.connect(
|
|
'url',
|
|
namespaces=['/foo', '/bar'],
|
|
wait=True,
|
|
wait_timeout=0.01,
|
|
)
|
|
assert c.connected is True
|
|
assert c.namespaces == {'/bar': '123', '/foo': '456'}
|
|
|
|
def test_connect_timeout(self):
|
|
c = client.Client()
|
|
c.eio.connect = mock.MagicMock()
|
|
c.disconnect = mock.MagicMock()
|
|
with pytest.raises(exceptions.ConnectionError):
|
|
c.connect(
|
|
'url',
|
|
wait=True,
|
|
wait_timeout=0.01,
|
|
)
|
|
c.disconnect.assert_called_once_with()
|
|
|
|
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()
|
|
assert c.eio.wait.call_count == 2
|
|
assert c.sleep.call_count == 2
|
|
|
|
def test_get_sid(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/': '1', '/foo': '2'}
|
|
assert c.get_sid() == '1'
|
|
assert c.get_sid('/') == '1'
|
|
assert c.get_sid('/foo') == '2'
|
|
assert c.get_sid('/bar') is None
|
|
|
|
def test_emit_no_arguments(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/': '1'}
|
|
c._send_packet = mock.MagicMock()
|
|
c.emit('foo')
|
|
expected_packet = packet.Packet(
|
|
packet.EVENT, namespace='/', data=['foo'], id=None)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_emit_one_argument(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/': '1'}
|
|
c._send_packet = mock.MagicMock()
|
|
c.emit('foo', 'bar')
|
|
expected_packet = packet.Packet(
|
|
packet.EVENT,
|
|
namespace='/',
|
|
data=['foo', 'bar'],
|
|
id=None,
|
|
)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_emit_one_argument_list(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/': '1'}
|
|
c._send_packet = mock.MagicMock()
|
|
c.emit('foo', ['bar', 'baz'])
|
|
expected_packet = packet.Packet(
|
|
packet.EVENT,
|
|
namespace='/',
|
|
data=['foo', ['bar', 'baz']],
|
|
id=None,
|
|
)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_emit_two_arguments(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/': '1'}
|
|
c._send_packet = mock.MagicMock()
|
|
c.emit('foo', ('bar', 'baz'))
|
|
expected_packet = packet.Packet(
|
|
packet.EVENT,
|
|
namespace='/',
|
|
data=['foo', 'bar', 'baz'],
|
|
id=None,
|
|
)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_emit_namespace(self):
|
|
c = client.Client()
|
|
c.namespaces = ['/foo']
|
|
c._send_packet = mock.MagicMock()
|
|
c.emit('foo', namespace='/foo')
|
|
expected_packet = packet.Packet(
|
|
packet.EVENT, namespace='/foo', data=['foo'], id=None)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_emit_unknown_namespace(self):
|
|
c = client.Client()
|
|
c.namespaces = ['/foo']
|
|
with pytest.raises(exceptions.BadNamespaceError):
|
|
c.emit('foo', namespace='/bar')
|
|
|
|
def test_emit_with_callback(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/': '1'}
|
|
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)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
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.namespaces = {'/foo': '1'}
|
|
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)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
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()
|
|
c.namespaces = {'/': '1'}
|
|
c._send_packet = mock.MagicMock()
|
|
c.emit('foo', b'bar')
|
|
expected_packet = packet.Packet(
|
|
packet.EVENT,
|
|
namespace='/',
|
|
data=['foo', b'bar'],
|
|
id=None,
|
|
)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_emit_not_binary(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/': '1'}
|
|
c._send_packet = mock.MagicMock()
|
|
c.emit('foo', 'bar')
|
|
expected_packet = packet.Packet(
|
|
packet.EVENT,
|
|
namespace='/',
|
|
data=['foo', 'bar'],
|
|
id=None,
|
|
)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
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_call(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/': '1'}
|
|
|
|
def fake_event_wait(timeout=None):
|
|
assert timeout == 60
|
|
c._generate_ack_id.call_args_list[0][0][1]('foo', 321)
|
|
return True
|
|
|
|
c._send_packet = mock.MagicMock()
|
|
c._generate_ack_id = mock.MagicMock(return_value=123)
|
|
c.eio = mock.MagicMock()
|
|
c.eio.create_event.return_value.wait = fake_event_wait
|
|
assert c.call('foo') == ('foo', 321)
|
|
expected_packet = packet.Packet(
|
|
packet.EVENT, namespace='/', data=['foo'], id=123)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_call_with_timeout(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/': '1'}
|
|
|
|
def fake_event_wait(timeout=None):
|
|
assert timeout == 12
|
|
return False
|
|
|
|
c._send_packet = mock.MagicMock()
|
|
c._generate_ack_id = mock.MagicMock(return_value=123)
|
|
c.eio = mock.MagicMock()
|
|
c.eio.create_event.return_value.wait = fake_event_wait
|
|
with pytest.raises(exceptions.TimeoutError):
|
|
c.call('foo', timeout=12)
|
|
expected_packet = packet.Packet(
|
|
packet.EVENT, namespace='/', data=['foo'], id=123)
|
|
assert c._send_packet.call_count == 1
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_disconnect(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/': '1'}
|
|
c._trigger_event = mock.MagicMock()
|
|
c._send_packet = mock.MagicMock()
|
|
c.eio = mock.MagicMock()
|
|
c.eio.state = 'connected'
|
|
c.disconnect()
|
|
assert c.connected
|
|
assert c._trigger_event.call_count == 0
|
|
assert c._send_packet.call_count == 1
|
|
expected_packet = packet.Packet(packet.DISCONNECT, namespace='/')
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
c.eio.disconnect.assert_called_once_with()
|
|
|
|
def test_disconnect_namespaces(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/foo': '1', '/bar': '2'}
|
|
c._trigger_event = mock.MagicMock()
|
|
c._send_packet = mock.MagicMock()
|
|
c.eio = mock.MagicMock()
|
|
c.eio.state = 'connected'
|
|
c.disconnect()
|
|
assert c._trigger_event.call_count == 0
|
|
assert c._send_packet.call_count == 2
|
|
expected_packet = packet.Packet(packet.DISCONNECT, namespace='/foo')
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
expected_packet = packet.Packet(packet.DISCONNECT, namespace='/bar')
|
|
assert (
|
|
c._send_packet.call_args_list[1][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_transport(self):
|
|
c = client.Client()
|
|
c.eio.transport = mock.MagicMock(return_value='foo')
|
|
assert 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')
|
|
assert 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'))
|
|
c.eio.send.assert_called_once_with('2"foo"')
|
|
|
|
def test_send_packet_binary(self):
|
|
c = client.Client()
|
|
c.eio.send = mock.MagicMock()
|
|
c._send_packet(packet.Packet(packet.EVENT, b'foo'))
|
|
assert c.eio.send.call_args_list == [
|
|
mock.call('51-{"_placeholder":true,"num":0}'),
|
|
mock.call(b'foo'),
|
|
] or c.eio.send.call_args_list == [
|
|
mock.call('51-{"num":0,"_placeholder":true}'),
|
|
mock.call(b'foo'),
|
|
]
|
|
|
|
def test_send_packet_default_binary(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"')
|
|
|
|
def test_generate_ack_id(self):
|
|
c = client.Client()
|
|
assert c._generate_ack_id('/', 'cb') == 1
|
|
assert c._generate_ack_id('/', 'cb') == 2
|
|
assert c._generate_ack_id('/', 'cb') == 3
|
|
assert c._generate_ack_id('/foo', 'cb') == 1
|
|
assert c._generate_ack_id('/bar', 'cb') == 1
|
|
assert c._generate_ack_id('/', 'cb') == 4
|
|
assert c._generate_ack_id('/bar', 'cb') == 2
|
|
|
|
def test_handle_connect(self):
|
|
c = client.Client()
|
|
c._connect_event = mock.MagicMock()
|
|
c._trigger_event = mock.MagicMock()
|
|
c._send_packet = mock.MagicMock()
|
|
c._handle_connect('/', {'sid': '123'})
|
|
assert c.namespaces == {'/': '123'}
|
|
c._connect_event.set.assert_called_once_with()
|
|
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': '1', '/bar': '2'}
|
|
c._connect_event = mock.MagicMock()
|
|
c._trigger_event = mock.MagicMock()
|
|
c._send_packet = mock.MagicMock()
|
|
c._handle_connect('/', {'sid': '3'})
|
|
c._connect_event.set.assert_called_once_with()
|
|
c._trigger_event.assert_called_once_with('connect', namespace='/')
|
|
assert c.namespaces == {'/': '3', '/foo': '1', '/bar': '2'}
|
|
|
|
def test_handle_connect_namespace(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/foo': '1'}
|
|
c._connect_event = mock.MagicMock()
|
|
c._trigger_event = mock.MagicMock()
|
|
c._send_packet = mock.MagicMock()
|
|
c._handle_connect('/foo', {'sid': '123'})
|
|
c._handle_connect('/bar', {'sid': '2'})
|
|
assert c._trigger_event.call_count == 1
|
|
c._connect_event.set.assert_called_once_with()
|
|
c._trigger_event.assert_called_once_with('connect', namespace='/bar')
|
|
assert c.namespaces == {'/foo': '1', '/bar': '2'}
|
|
|
|
def test_handle_disconnect(self):
|
|
c = client.Client()
|
|
c.namespace = {'/': '1'}
|
|
c.connected = True
|
|
c._trigger_event = mock.MagicMock()
|
|
c._handle_disconnect('/')
|
|
c._trigger_event.assert_any_call('disconnect', '/',
|
|
c.reason.SERVER_DISCONNECT)
|
|
c._trigger_event.assert_any_call('__disconnect_final', '/')
|
|
assert not c.connected
|
|
c._handle_disconnect('/')
|
|
assert c._trigger_event.call_count == 2
|
|
|
|
def test_handle_disconnect_namespace(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/foo': '1', '/bar': '2'}
|
|
c._trigger_event = mock.MagicMock()
|
|
c._handle_disconnect('/foo')
|
|
c._trigger_event.assert_any_call('disconnect', '/foo',
|
|
c.reason.SERVER_DISCONNECT)
|
|
c._trigger_event.assert_any_call('__disconnect_final', '/foo')
|
|
assert c.namespaces == {'/bar': '2'}
|
|
assert c.connected
|
|
c._handle_disconnect('/bar')
|
|
c._trigger_event.assert_any_call('disconnect', '/bar',
|
|
c.reason.SERVER_DISCONNECT)
|
|
c._trigger_event.assert_any_call('__disconnect_final', '/bar')
|
|
assert c.namespaces == {}
|
|
assert not c.connected
|
|
|
|
def test_handle_disconnect_unknown_namespace(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/foo': '1', '/bar': '2'}
|
|
c._trigger_event = mock.MagicMock()
|
|
c._handle_disconnect('/baz')
|
|
c._trigger_event.assert_any_call('disconnect', '/baz',
|
|
c.reason.SERVER_DISCONNECT)
|
|
c._trigger_event.assert_any_call('__disconnect_final', '/baz')
|
|
assert c.namespaces == {'/foo': '1', '/bar': '2'}
|
|
assert c.connected
|
|
|
|
def test_handle_disconnect_default_namespace(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/foo': '1', '/bar': '2'}
|
|
c._trigger_event = mock.MagicMock()
|
|
c._handle_disconnect('/')
|
|
c._trigger_event.assert_any_call('disconnect', '/',
|
|
c.reason.SERVER_DISCONNECT)
|
|
c._trigger_event.assert_any_call('__disconnect_final', '/')
|
|
assert c.namespaces == {'/foo': '1', '/bar': '2'}
|
|
assert c.connected
|
|
|
|
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()
|
|
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'))
|
|
assert c._send_packet.call_count == 1
|
|
expected_packet = packet.Packet(
|
|
packet.ACK, namespace='/', id=123, data=[])
|
|
assert (
|
|
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()
|
|
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'))
|
|
assert c._send_packet.call_count == 1
|
|
expected_packet = packet.Packet(
|
|
packet.ACK, namespace='/', id=123, data=['ret'])
|
|
assert (
|
|
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()
|
|
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'))
|
|
assert c._send_packet.call_count == 1
|
|
expected_packet = packet.Packet(
|
|
packet.ACK, namespace='/', id=123, data=[['a', 'b']])
|
|
assert (
|
|
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()
|
|
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'))
|
|
assert c._send_packet.call_count == 1
|
|
expected_packet = packet.Packet(
|
|
packet.ACK, namespace='/', id=123, data=['a', 'b'])
|
|
assert (
|
|
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')
|
|
assert 123 not in 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()
|
|
assert 123 in c.callbacks['/foo']
|
|
|
|
def test_handle_error(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/foo': '1', '/bar': '2'}
|
|
c._connect_event = mock.MagicMock()
|
|
c._trigger_event = mock.MagicMock()
|
|
c._handle_error('/', 'error')
|
|
assert c.namespaces == {}
|
|
assert not c.connected
|
|
c._connect_event.set.assert_called_once_with()
|
|
c._trigger_event.assert_called_once_with('connect_error', '/', 'error')
|
|
|
|
def test_handle_error_with_no_arguments(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/foo': '1', '/bar': '2'}
|
|
c._connect_event = mock.MagicMock()
|
|
c._trigger_event = mock.MagicMock()
|
|
c._handle_error('/', None)
|
|
assert c.namespaces == {}
|
|
assert not c.connected
|
|
c._connect_event.set.assert_called_once_with()
|
|
c._trigger_event.assert_called_once_with('connect_error', '/')
|
|
|
|
def test_handle_error_namespace(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/foo': '1', '/bar': '2'}
|
|
c._connect_event = mock.MagicMock()
|
|
c._trigger_event = mock.MagicMock()
|
|
c._handle_error('/bar', ['error', 'message'])
|
|
assert c.namespaces == {'/foo': '1'}
|
|
assert c.connected
|
|
c._connect_event.set.assert_called_once_with()
|
|
c._trigger_event.assert_called_once_with(
|
|
'connect_error', '/bar', 'error', 'message'
|
|
)
|
|
|
|
def test_handle_error_namespace_with_no_arguments(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/foo': '1', '/bar': '2'}
|
|
c._connect_event = mock.MagicMock()
|
|
c._trigger_event = mock.MagicMock()
|
|
c._handle_error('/bar', None)
|
|
assert c.namespaces == {'/foo': '1'}
|
|
assert c.connected
|
|
c._connect_event.set.assert_called_once_with()
|
|
c._trigger_event.assert_called_once_with('connect_error', '/bar')
|
|
|
|
def test_handle_error_unknown_namespace(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/foo': '1', '/bar': '2'}
|
|
c._connect_event = mock.MagicMock()
|
|
c._handle_error('/baz', 'error')
|
|
assert c.namespaces == {'/foo': '1', '/bar': '2'}
|
|
assert c.connected
|
|
c._connect_event.set.assert_called_once_with()
|
|
|
|
def test_trigger_event(self):
|
|
c = client.Client()
|
|
handler = mock.MagicMock()
|
|
catchall_handler = mock.MagicMock()
|
|
c.on('foo', handler)
|
|
c.on('*', catchall_handler)
|
|
c._trigger_event('foo', '/', 1, '2')
|
|
c._trigger_event('bar', '/', 1, '2', 3)
|
|
c._trigger_event('connect', '/') # should not trigger
|
|
handler.assert_called_once_with(1, '2')
|
|
catchall_handler.assert_called_once_with('bar', 1, '2', 3)
|
|
|
|
def test_trigger_event_namespace(self):
|
|
c = client.Client()
|
|
handler = mock.MagicMock()
|
|
catchall_handler = mock.MagicMock()
|
|
c.on('foo', handler, namespace='/bar')
|
|
c.on('*', catchall_handler, namespace='/bar')
|
|
c._trigger_event('foo', '/bar', 1, '2')
|
|
c._trigger_event('bar', '/bar', 1, '2', 3)
|
|
handler.assert_called_once_with(1, '2')
|
|
catchall_handler.assert_called_once_with('bar', 1, '2', 3)
|
|
|
|
def test_trigger_event_with_catchall_namespace(self):
|
|
c = client.Client()
|
|
connect_star_handler = mock.MagicMock()
|
|
msg_foo_handler = mock.MagicMock()
|
|
msg_star_handler = mock.MagicMock()
|
|
star_foo_handler = mock.MagicMock()
|
|
star_star_handler = mock.MagicMock()
|
|
c.on('connect', connect_star_handler, namespace='*')
|
|
c.on('msg', msg_foo_handler, namespace='/foo')
|
|
c.on('msg', msg_star_handler, namespace='*')
|
|
c.on('*', star_foo_handler, namespace='/foo')
|
|
c.on('*', star_star_handler, namespace='*')
|
|
c._trigger_event('connect', '/bar')
|
|
c._trigger_event('msg', '/foo', 'a', 'b')
|
|
c._trigger_event('msg', '/bar', 'a', 'b')
|
|
c._trigger_event('my message', '/foo', 'a', 'b', 'c')
|
|
c._trigger_event('my message', '/bar', 'a', 'b', 'c')
|
|
c._trigger_event('disconnect', '/bar')
|
|
connect_star_handler.assert_called_once_with('/bar')
|
|
msg_foo_handler.assert_called_once_with('a', 'b')
|
|
msg_star_handler.assert_called_once_with('/bar', 'a', 'b')
|
|
star_foo_handler.assert_called_once_with(
|
|
'my message', 'a', 'b', 'c')
|
|
star_star_handler.assert_called_once_with(
|
|
'my message', '/bar', 'a', 'b', 'c')
|
|
|
|
def test_trigger_event_with_catchall_namespace_handler(self):
|
|
result = {}
|
|
|
|
class MyNamespace(namespace.ClientNamespace):
|
|
def on_connect(self, ns):
|
|
result['result'] = (ns,)
|
|
|
|
def on_disconnect(self, ns, reason):
|
|
result['result'] = ('disconnect', ns, reason)
|
|
|
|
def on_foo(self, ns, data):
|
|
result['result'] = (ns, data)
|
|
|
|
def on_bar(self, ns):
|
|
result['result'] = 'bar' + ns
|
|
|
|
def on_baz(self, ns, data1, data2):
|
|
result['result'] = (ns, data1, data2)
|
|
|
|
c = client.Client()
|
|
c.register_namespace(MyNamespace('*'))
|
|
c._trigger_event('connect', '/foo')
|
|
assert result['result'] == ('/foo',)
|
|
c._trigger_event('foo', '/foo', 'a')
|
|
assert result['result'] == ('/foo', 'a')
|
|
c._trigger_event('bar', '/foo')
|
|
assert result['result'] == 'bar/foo'
|
|
c._trigger_event('baz', '/foo', 'a', 'b')
|
|
assert result['result'] == ('/foo', 'a', 'b')
|
|
c._trigger_event('disconnect', '/foo', 'bar')
|
|
assert result['result'] == ('disconnect', '/foo', 'bar')
|
|
|
|
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')
|
|
assert result == [1, '2']
|
|
|
|
def test_trigger_event_unknown_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', '/bar', 1, '2')
|
|
assert result == []
|
|
|
|
@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._reconnect_abort = c.eio.create_event()
|
|
c._reconnect_abort.wait = mock.MagicMock(return_value=False)
|
|
c.connect = mock.MagicMock(
|
|
side_effect=[ValueError, exceptions.ConnectionError, None]
|
|
)
|
|
c._handle_reconnect()
|
|
assert c._reconnect_abort.wait.call_count == 3
|
|
assert c._reconnect_abort.wait.call_args_list == [
|
|
mock.call(1.5),
|
|
mock.call(1.5),
|
|
mock.call(4.0),
|
|
]
|
|
assert c._reconnect_task is 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._reconnect_abort = c.eio.create_event()
|
|
c._reconnect_abort.wait = mock.MagicMock(return_value=False)
|
|
c.connect = mock.MagicMock(
|
|
side_effect=[ValueError, exceptions.ConnectionError, None]
|
|
)
|
|
c._handle_reconnect()
|
|
assert c._reconnect_abort.wait.call_count == 3
|
|
assert c._reconnect_abort.wait.call_args_list == [
|
|
mock.call(1.5),
|
|
mock.call(1.5),
|
|
mock.call(3.0),
|
|
]
|
|
assert c._reconnect_task is 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.connection_namespaces = ['/']
|
|
c._reconnect_task = 'foo'
|
|
c._reconnect_abort = c.eio.create_event()
|
|
c._reconnect_abort.wait = mock.MagicMock(return_value=False)
|
|
c._trigger_event = mock.MagicMock()
|
|
c.connect = mock.MagicMock(
|
|
side_effect=[ValueError, exceptions.ConnectionError, None]
|
|
)
|
|
c._handle_reconnect()
|
|
assert c._reconnect_abort.wait.call_count == 2
|
|
assert c._reconnect_abort.wait.call_args_list == [
|
|
mock.call(1.5),
|
|
mock.call(1.5),
|
|
]
|
|
assert c._reconnect_task == 'foo'
|
|
c._trigger_event.assert_called_once_with('__disconnect_final',
|
|
namespace='/')
|
|
|
|
@mock.patch('socketio.client.random.random', side_effect=[1, 0, 0.5])
|
|
def test_handle_reconnect_aborted(self, random):
|
|
c = client.Client()
|
|
c.connection_namespaces = ['/']
|
|
c._reconnect_task = 'foo'
|
|
c._reconnect_abort = c.eio.create_event()
|
|
c._reconnect_abort.wait = mock.MagicMock(side_effect=[False, True])
|
|
c._trigger_event = mock.MagicMock()
|
|
c.connect = mock.MagicMock(side_effect=exceptions.ConnectionError)
|
|
c._handle_reconnect()
|
|
assert c._reconnect_abort.wait.call_count == 2
|
|
assert c._reconnect_abort.wait.call_args_list == [
|
|
mock.call(1.5),
|
|
mock.call(1.5),
|
|
]
|
|
assert c._reconnect_task == 'foo'
|
|
c._trigger_event.assert_called_once_with('__disconnect_final',
|
|
namespace='/')
|
|
|
|
def test_shutdown_disconnect(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/': '1'}
|
|
c._trigger_event = mock.MagicMock()
|
|
c._send_packet = mock.MagicMock()
|
|
c.eio = mock.MagicMock()
|
|
c.eio.state = 'connected'
|
|
c.shutdown()
|
|
assert c._trigger_event.call_count == 0
|
|
assert c._send_packet.call_count == 1
|
|
expected_packet = packet.Packet(packet.DISCONNECT, namespace='/')
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
c.eio.disconnect.assert_called_once_with()
|
|
|
|
def test_shutdown_disconnect_namespaces(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/foo': '1', '/bar': '2'}
|
|
c._trigger_event = mock.MagicMock()
|
|
c._send_packet = mock.MagicMock()
|
|
c.eio = mock.MagicMock()
|
|
c.eio.state = 'connected'
|
|
c.shutdown()
|
|
assert c._trigger_event.call_count == 0
|
|
assert c._send_packet.call_count == 2
|
|
expected_packet = packet.Packet(packet.DISCONNECT, namespace='/foo')
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
expected_packet = packet.Packet(packet.DISCONNECT, namespace='/bar')
|
|
assert (
|
|
c._send_packet.call_args_list[1][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
@mock.patch('socketio.client.random.random', side_effect=[1, 0, 0.5])
|
|
def test_shutdown_reconnect(self, random):
|
|
c = client.Client()
|
|
c.connection_namespaces = ['/']
|
|
c._reconnect_task = mock.MagicMock()
|
|
c._trigger_event = mock.MagicMock()
|
|
c.connect = mock.MagicMock(side_effect=exceptions.ConnectionError)
|
|
task = c.start_background_task(c._handle_reconnect)
|
|
time.sleep(0.1)
|
|
c.shutdown()
|
|
task.join()
|
|
c._trigger_event.assert_called_once_with('__disconnect_final',
|
|
namespace='/')
|
|
c._reconnect_task.join.assert_called_once_with()
|
|
|
|
def test_handle_eio_connect(self):
|
|
c = client.Client()
|
|
c.connection_namespaces = ['/', '/foo']
|
|
c.connection_auth = 'auth'
|
|
c._send_packet = mock.MagicMock()
|
|
c.eio.sid = 'foo'
|
|
assert c.sid is None
|
|
c._handle_eio_connect()
|
|
assert c.sid == 'foo'
|
|
assert c._send_packet.call_count == 2
|
|
expected_packet = packet.Packet(
|
|
packet.CONNECT, data='auth', namespace='/')
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
expected_packet = packet.Packet(
|
|
packet.CONNECT, data='auth', namespace='/foo')
|
|
assert (
|
|
c._send_packet.call_args_list[1][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_handle_eio_connect_function(self):
|
|
c = client.Client()
|
|
c.connection_namespaces = ['/', '/foo']
|
|
c.connection_auth = lambda: 'auth'
|
|
c._send_packet = mock.MagicMock()
|
|
c.eio.sid = 'foo'
|
|
assert c.sid is None
|
|
c._handle_eio_connect()
|
|
assert c.sid == 'foo'
|
|
assert c._send_packet.call_count == 2
|
|
expected_packet = packet.Packet(
|
|
packet.CONNECT, data='auth', namespace='/')
|
|
assert (
|
|
c._send_packet.call_args_list[0][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
expected_packet = packet.Packet(
|
|
packet.CONNECT, data='auth', namespace='/foo')
|
|
assert (
|
|
c._send_packet.call_args_list[1][0][0].encode()
|
|
== expected_packet.encode()
|
|
)
|
|
|
|
def test_handle_eio_message(self):
|
|
c = client.Client()
|
|
c._handle_connect = mock.MagicMock()
|
|
c._handle_disconnect = mock.MagicMock()
|
|
c._handle_event = mock.MagicMock()
|
|
c._handle_ack = mock.MagicMock()
|
|
c._handle_error = mock.MagicMock()
|
|
|
|
c._handle_eio_message('0{"sid":"123"}')
|
|
c._handle_connect.assert_called_with(None, {'sid': '123'})
|
|
c._handle_eio_message('0/foo,{"sid":"123"}')
|
|
c._handle_connect.assert_called_with('/foo', {'sid': '123'})
|
|
c._handle_eio_message('1')
|
|
c._handle_disconnect.assert_called_with(None)
|
|
c._handle_eio_message('1/foo')
|
|
c._handle_disconnect.assert_called_with('/foo')
|
|
c._handle_eio_message('2["foo"]')
|
|
c._handle_event.assert_called_with(None, None, ['foo'])
|
|
c._handle_eio_message('3/foo,["bar"]')
|
|
c._handle_ack.assert_called_with('/foo', None, ['bar'])
|
|
c._handle_eio_message('4')
|
|
c._handle_error.assert_called_with(None, None)
|
|
c._handle_eio_message('4"foo"')
|
|
c._handle_error.assert_called_with(None, 'foo')
|
|
c._handle_eio_message('4["foo"]')
|
|
c._handle_error.assert_called_with(None, ['foo'])
|
|
c._handle_eio_message('4/foo')
|
|
c._handle_error.assert_called_with('/foo', None)
|
|
c._handle_eio_message('4/foo,["foo","bar"]')
|
|
c._handle_error.assert_called_with('/foo', ['foo', 'bar'])
|
|
c._handle_eio_message('51-{"_placeholder":true,"num":0}')
|
|
assert c._binary_packet.packet_type == packet.BINARY_EVENT
|
|
c._handle_eio_message(b'foo')
|
|
c._handle_event.assert_called_with(None, None, b'foo')
|
|
c._handle_eio_message(
|
|
'62-/foo,{"1":{"_placeholder":true,"num":1},'
|
|
'"2":{"_placeholder":true,"num":0}}'
|
|
)
|
|
assert c._binary_packet.packet_type == packet.BINARY_ACK
|
|
c._handle_eio_message(b'bar')
|
|
c._handle_eio_message(b'foo')
|
|
c._handle_ack.assert_called_with(
|
|
'/foo', None, {'1': b'foo', '2': b'bar'}
|
|
)
|
|
with pytest.raises(ValueError):
|
|
c._handle_eio_message('9')
|
|
|
|
def test_eio_disconnect(self):
|
|
c = client.Client()
|
|
c.namespaces = {'/': '1'}
|
|
c.connected = True
|
|
c._trigger_event = mock.MagicMock()
|
|
c.start_background_task = mock.MagicMock()
|
|
c.sid = 'foo'
|
|
c.eio.state = 'connected'
|
|
c._handle_eio_disconnect('foo')
|
|
c._trigger_event.assert_called_once_with('disconnect', '/', 'foo')
|
|
assert c.sid is None
|
|
assert not c.connected
|
|
|
|
def test_eio_disconnect_namespaces(self):
|
|
c = client.Client()
|
|
c.connected = True
|
|
c.namespaces = {'/': '1', '/foo': '2', '/bar': '3'}
|
|
c._trigger_event = mock.MagicMock()
|
|
c.start_background_task = mock.MagicMock()
|
|
c.sid = 'foo'
|
|
c.eio.state = 'connected'
|
|
c._handle_eio_disconnect(c.reason.CLIENT_DISCONNECT)
|
|
c._trigger_event.assert_any_call('disconnect', '/foo',
|
|
c.reason.CLIENT_DISCONNECT)
|
|
c._trigger_event.assert_any_call('disconnect', '/bar',
|
|
c.reason.CLIENT_DISCONNECT)
|
|
c._trigger_event.assert_any_call('disconnect', '/',
|
|
c.reason.CLIENT_DISCONNECT)
|
|
assert c.sid is None
|
|
assert not c.connected
|
|
|
|
def test_eio_disconnect_reconnect(self):
|
|
c = client.Client(reconnection=True)
|
|
c.start_background_task = mock.MagicMock()
|
|
c.eio.state = 'connected'
|
|
c._handle_eio_disconnect(c.reason.CLIENT_DISCONNECT)
|
|
c.start_background_task.assert_called_once_with(c._handle_reconnect)
|
|
|
|
def test_eio_disconnect_self_disconnect(self):
|
|
c = client.Client(reconnection=True)
|
|
c.start_background_task = mock.MagicMock()
|
|
c.eio.state = 'disconnected'
|
|
c._handle_eio_disconnect(c.reason.CLIENT_DISCONNECT)
|
|
c.start_background_task.assert_not_called()
|
|
|
|
def test_eio_disconnect_no_reconnect(self):
|
|
c = client.Client(reconnection=False)
|
|
c.namespaces = {'/': '1'}
|
|
c.connected = True
|
|
c._trigger_event = mock.MagicMock()
|
|
c.start_background_task = mock.MagicMock()
|
|
c.sid = 'foo'
|
|
c.eio.state = 'connected'
|
|
c._handle_eio_disconnect(c.reason.TRANSPORT_ERROR)
|
|
c._trigger_event.assert_any_call('disconnect', '/',
|
|
c.reason.TRANSPORT_ERROR)
|
|
c._trigger_event.assert_any_call('__disconnect_final', '/')
|
|
assert c.sid is None
|
|
assert not c.connected
|
|
c.start_background_task.assert_not_called()
|
|
|