Skip to content

Commit

Permalink
Fix test client [call]back returning (#732)
Browse files Browse the repository at this point in the history
If you preinitialize all the test clients, you won't get the server
acknowledgements because only last initialized test client's
monkeypatched successfully _send_packet, with self in its closure. So
when other test client instances check self.ack is None when
callback=True in emit(), it doesn't contain the ack meant for them.
  • Loading branch information
pilona authored and miguelgrinberg committed Oct 9, 2018
1 parent d8688bd commit 4b0648c
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 14 deletions.
15 changes: 8 additions & 7 deletions flask_socketio/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SocketIOTestClient(object):
:param headers: A dictionary with custom HTTP headers.
"""
queue = {}
ack = None
acks = {}

def __init__(self, app, socketio, namespace=None, query_string=None,
headers=None):
Expand All @@ -37,12 +37,13 @@ def _mock_send_packet(sid, pkt):
'namespace': pkt.namespace or '/'})
elif pkt.packet_type == packet.ACK or \
pkt.packet_type == packet.BINARY_ACK:
self.ack = {'args': pkt.data,
'namespace': pkt.namespace or '/'}
self.acks[sid] = {'args': pkt.data,
'namespace': pkt.namespace or '/'}

self.app = app
self.sid = uuid.uuid4().hex
self.queue[self.sid] = []
self.acks[self.sid] = None
self.callback_counter = 0
self.socketio = socketio
socketio.server._send_packet = _mock_send_packet
Expand Down Expand Up @@ -116,17 +117,17 @@ def emit(self, event, *args, **kwargs):
id = self.callback_counter
pkt = packet.Packet(packet.EVENT, data=[event] + list(args),
namespace=namespace, id=id)
self.ack = None
with self.app.app_context():
encoded_pkt = pkt.encode()
if isinstance(encoded_pkt, list):
for epkt in encoded_pkt:
self.socketio.server._handle_eio_message(self.sid, epkt)
else:
self.socketio.server._handle_eio_message(self.sid, encoded_pkt)
if self.ack is not None:
return self.ack['args'][0] if len(self.ack['args']) == 1 \
else self.ack['args']
ack = self.acks.pop(self.sid, None)
if ack is not None:
return ack['args'][0] if len(ack['args']) == 1 \
else ack['args']

def send(self, data, json=False, callback=False, namespace=None):
"""Send a text or JSON message to the server.
Expand Down
14 changes: 7 additions & 7 deletions test_socketio.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,41 +492,41 @@ def test_error_handling_default(self):

def test_ack(self):
client1 = socketio.test_client(app)
client2 = socketio.test_client(app)
client3 = socketio.test_client(app)
ack = client1.send('echo this message back', callback=True)
self.assertEqual(ack, 'echo this message back')
ack = client1.send('test noackargs', callback=True)
# python-socketio releases before 1.5 did not correctly implement
# callbacks with no arguments. Here we check for [] (the correct, 1.5
# and up response) and None (the wrong pre-1.5 response).
self.assertTrue(ack == [] or ack is None)
client2 = socketio.test_client(app)
ack2 = client2.send({'a': 'b'}, json=True, callback=True)
self.assertEqual(ack2, {'a': 'b'})
client3 = socketio.test_client(app)
ack3 = client3.emit('my custom event', {'a': 'b'}, callback=True)
self.assertEqual(ack3, {'a': 'b'})

def test_noack(self):
client1 = socketio.test_client(app)
client2 = socketio.test_client(app)
client3 = socketio.test_client(app)
no_ack_dict = {'noackargs': True}
noack = client1.send("test noackargs", callback=False)
self.assertIsNone(noack)
client2 = socketio.test_client(app)
noack2 = client2.send(no_ack_dict, json=True, callback=False)
self.assertIsNone(noack2)
client3 = socketio.test_client(app)
noack3 = client3.emit('my custom event', no_ack_dict)
self.assertIsNone(noack3)

def test_error_handling_ack(self):
client1 = socketio.test_client(app)
client2 = socketio.test_client(app, namespace='/test')
client3 = socketio.test_client(app, namespace='/unused_namespace')
errorack = client1.emit("error testing", "", callback=True)
self.assertIsNotNone(errorack)
client2 = socketio.test_client(app, namespace='/test')
errorack_namespace = client2.emit("error testing", "",
namespace='/test', callback=True)
self.assertIsNotNone(errorack_namespace)
client3 = socketio.test_client(app, namespace='/unused_namespace')
errorack_default = client3.emit("error testing", "",
namespace='/unused_namespace',
callback=True)
Expand Down Expand Up @@ -631,7 +631,7 @@ def on_connect():
received = client.get_received()
self.assertEqual(len(received), 1)
self.assertEqual(received[0]['args'], {'connected': 'foo'})


if __name__ == '__main__':
unittest.main()

0 comments on commit 4b0648c

Please sign in to comment.