-
-
Notifications
You must be signed in to change notification settings - Fork 596
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5122519
commit e84e3c5
Showing
10 changed files
with
203 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import unittest | ||
import socketio | ||
from tests.web_server import SocketIOWebServer | ||
|
||
|
||
class TestServer(unittest.TestCase): | ||
def setUp(self): | ||
sio = socketio.Server(async_mode='threading') | ||
self.instrumented_server = sio.instrument(auth=False) | ||
|
||
@sio.event | ||
def enter_room(sid, data): | ||
sio.enter_room(sid, data) | ||
|
||
@sio.event(namespace='/foo') | ||
def connect(sid, environ, auth): | ||
pass | ||
|
||
self.server = SocketIOWebServer(sio) | ||
self.server.start() | ||
|
||
import logging | ||
logging.getLogger('engineio.client').setLevel(logging.DEBUG) | ||
logging.getLogger('socketio.client').setLevel(logging.DEBUG) | ||
|
||
def tearDown(self): | ||
self.server.stop() | ||
self.instrumented_server.shutdown() | ||
self.instrumented_server.uninstrument() | ||
|
||
import logging | ||
logging.getLogger('engineio.client').setLevel(logging.NOTSET) | ||
logging.getLogger('socketio.client').setLevel(logging.NOTSET) | ||
|
||
def test_admin_connect_only_admin(self): | ||
with socketio.SimpleClient() as client: | ||
client.connect('http://localhost:8900', namespace='/admin') | ||
sid = client.sid | ||
expected = ['config', 'all_sockets', 'server_stats'] | ||
events = {} | ||
while expected: | ||
data = client.receive(timeout=5) | ||
if data[0] in expected: | ||
events[data[0]] = data[1] | ||
expected.remove(data[0]) | ||
assert 'supportedFeatures' in events['config'] | ||
assert len(events['all_sockets']) == 1 | ||
assert events['all_sockets'][0]['id'] == sid | ||
assert events['all_sockets'][0]['rooms'] == [sid] | ||
assert events['server_stats']['clientsCount'] == 1 | ||
assert events['server_stats']['pollingClientsCount'] == 0 | ||
assert len(events['server_stats']['namespaces']) == 3 | ||
assert {'name': '/', 'socketsCount': 0} in \ | ||
events['server_stats']['namespaces'] | ||
assert {'name': '/foo', 'socketsCount': 0} in \ | ||
events['server_stats']['namespaces'] | ||
assert {'name': '/admin', 'socketsCount': 1} in \ | ||
events['server_stats']['namespaces'] | ||
|
||
def test_admin_connect_with_others(self): | ||
client1 = socketio.SimpleClient() | ||
client1.connect('http://localhost:8900') | ||
client1.emit('enter_room', 'room') | ||
sid1 = client1.sid | ||
|
||
client2 = socketio.SimpleClient() | ||
client2.connect('http://localhost:8900', namespace='/foo') | ||
sid2 = client2.sid | ||
|
||
client3 = socketio.SimpleClient() | ||
client3.connect('http://localhost:8900', namespace='/admin') | ||
sid3 = client3.sid | ||
|
||
with socketio.SimpleClient() as client: | ||
client.connect('http://localhost:8900', namespace='/admin') | ||
sid = client.sid | ||
expected = ['config', 'all_sockets', 'server_stats'] | ||
events = {} | ||
while expected: | ||
data = client.receive(timeout=5) | ||
if data[0] in expected: | ||
events[data[0]] = data[1] | ||
expected.remove(data[0]) | ||
client3.disconnect() | ||
client2.disconnect() | ||
client1.disconnect() | ||
|
||
assert 'supportedFeatures' in events['config'] | ||
assert len(events['all_sockets']) == 4 | ||
assert events['server_stats']['clientsCount'] == 4 | ||
assert events['server_stats']['pollingClientsCount'] == 0 | ||
assert len(events['server_stats']['namespaces']) == 3 | ||
assert {'name': '/', 'socketsCount': 1} in \ | ||
events['server_stats']['namespaces'] | ||
assert {'name': '/foo', 'socketsCount': 1} in \ | ||
events['server_stats']['namespaces'] | ||
assert {'name': '/admin', 'socketsCount': 2} in \ | ||
events['server_stats']['namespaces'] | ||
|
||
for socket in events['all_sockets']: | ||
if socket['id'] == sid: | ||
assert socket['rooms'] == [sid] | ||
elif socket['id'] == sid1: | ||
assert socket['rooms'] == [sid1, 'room'] | ||
elif socket['id'] == sid2: | ||
assert socket['rooms'] == [sid2] | ||
elif socket['id'] == sid3: | ||
assert socket['rooms'] == [sid3] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import threading | ||
from socketserver import ThreadingMixIn | ||
from wsgiref.simple_server import make_server, WSGIServer, WSGIRequestHandler | ||
import socketio | ||
|
||
|
||
class SocketIOWebServer: | ||
"""A simple web server used for running Socket.IO servers in tests. | ||
:param sio: a Socket.IO server instance. | ||
Note 1: This class is not production-ready and is intended for testing. | ||
Note 2: This class only supports the "threading" async_mode, with WebSocket | ||
support provided by the simple-websocket package. | ||
""" | ||
def __init__(self, sio): | ||
if sio.async_mode != 'threading': | ||
raise ValueError('The async_mode must be "threading"') | ||
self.app = socketio.WSGIApp(sio) | ||
self.httpd = None | ||
self.thread = None | ||
|
||
def start(self, port=8900): | ||
"""Start the web server. | ||
:param port: the port to listen on. Defaults to 8900. | ||
The server is started in a background thread. | ||
""" | ||
class ThreadingWSGIServer(ThreadingMixIn, WSGIServer): | ||
pass | ||
|
||
class WebSocketRequestHandler(WSGIRequestHandler): | ||
def get_environ(self): | ||
env = super().get_environ() | ||
|
||
# pass the raw socket to the WSGI app so that it can be used | ||
# by WebSocket connections (hack copied from gunicorn) | ||
env['gunicorn.socket'] = self.connection | ||
return env | ||
|
||
self.httpd = make_server('', port, self._app_wrapper, | ||
ThreadingWSGIServer, WebSocketRequestHandler) | ||
self.thread = threading.Thread(target=self.httpd.serve_forever) | ||
self.thread.start() | ||
|
||
def stop(self): | ||
"""Stop the web server.""" | ||
self.httpd.shutdown() | ||
self.httpd.server_close() | ||
self.thread.join() | ||
self.httpd = None | ||
self.thread = None | ||
|
||
def _app_wrapper(self, environ, start_response): | ||
try: | ||
return self.app(environ, start_response) | ||
except StopIteration: | ||
# end the WebSocket request without sending a response | ||
# (this is a hack that was copied from gunicorn's threaded worker) | ||
start_response('200 OK', []) | ||
return [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters