2018-08-17 15:36:48 +00:00
|
|
|
import pytest
|
2018-10-29 14:46:42 +00:00
|
|
|
|
|
|
|
from starlette import status
|
2018-08-17 15:36:48 +00:00
|
|
|
from starlette.testclient import TestClient
|
2018-09-05 09:29:04 +00:00
|
|
|
from starlette.websockets import WebSocket, WebSocketDisconnect
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
|
2018-09-05 10:39:38 +00:00
|
|
|
def test_websocket_url():
|
2018-08-17 15:36:48 +00:00
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
await websocket.accept()
|
2018-10-05 10:29:06 +00:00
|
|
|
await websocket.send_json({"url": str(websocket.url)})
|
2018-09-05 10:39:38 +00:00
|
|
|
await websocket.close()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("/123?a=abc") as websocket:
|
|
|
|
data = websocket.receive_json()
|
2018-08-17 15:36:48 +00:00
|
|
|
assert data == {"url": "ws://testserver/123?a=abc"}
|
|
|
|
|
|
|
|
|
2018-09-05 10:39:38 +00:00
|
|
|
def test_websocket_query_params():
|
2018-08-17 15:36:48 +00:00
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
query_params = dict(websocket.query_params)
|
|
|
|
await websocket.accept()
|
|
|
|
await websocket.send_json({"params": query_params})
|
|
|
|
await websocket.close()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("/?a=abc&b=456") as websocket:
|
|
|
|
data = websocket.receive_json()
|
2018-08-17 15:36:48 +00:00
|
|
|
assert data == {"params": {"a": "abc", "b": "456"}}
|
|
|
|
|
|
|
|
|
2018-09-05 10:39:38 +00:00
|
|
|
def test_websocket_headers():
|
2018-08-17 15:36:48 +00:00
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
headers = dict(websocket.headers)
|
|
|
|
await websocket.accept()
|
|
|
|
await websocket.send_json({"headers": headers})
|
|
|
|
await websocket.close()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("/") as websocket:
|
2018-08-17 15:36:48 +00:00
|
|
|
expected_headers = {
|
|
|
|
"accept": "*/*",
|
|
|
|
"accept-encoding": "gzip, deflate",
|
|
|
|
"connection": "upgrade",
|
|
|
|
"host": "testserver",
|
|
|
|
"user-agent": "testclient",
|
|
|
|
"sec-websocket-key": "testserver==",
|
|
|
|
"sec-websocket-version": "13",
|
|
|
|
}
|
2018-09-05 10:39:38 +00:00
|
|
|
data = websocket.receive_json()
|
2018-08-17 15:36:48 +00:00
|
|
|
assert data == {"headers": expected_headers}
|
|
|
|
|
|
|
|
|
2018-09-05 10:39:38 +00:00
|
|
|
def test_websocket_port():
|
2018-08-17 15:36:48 +00:00
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
await websocket.accept()
|
|
|
|
await websocket.send_json({"port": websocket.url.port})
|
|
|
|
await websocket.close()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("ws://example.com:123/123?a=abc") as websocket:
|
|
|
|
data = websocket.receive_json()
|
2018-08-17 15:36:48 +00:00
|
|
|
assert data == {"port": 123}
|
|
|
|
|
|
|
|
|
2018-09-05 10:39:38 +00:00
|
|
|
def test_websocket_send_and_receive_text():
|
2018-08-17 15:36:48 +00:00
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
await websocket.accept()
|
|
|
|
data = await websocket.receive_text()
|
|
|
|
await websocket.send_text("Message was: " + data)
|
|
|
|
await websocket.close()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("/") as websocket:
|
|
|
|
websocket.send_text("Hello, world!")
|
|
|
|
data = websocket.receive_text()
|
2018-08-17 15:36:48 +00:00
|
|
|
assert data == "Message was: Hello, world!"
|
|
|
|
|
|
|
|
|
2018-09-05 10:39:38 +00:00
|
|
|
def test_websocket_send_and_receive_bytes():
|
2018-08-17 15:36:48 +00:00
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
await websocket.accept()
|
|
|
|
data = await websocket.receive_bytes()
|
|
|
|
await websocket.send_bytes(b"Message was: " + data)
|
|
|
|
await websocket.close()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("/") as websocket:
|
|
|
|
websocket.send_bytes(b"Hello, world!")
|
|
|
|
data = websocket.receive_bytes()
|
2018-08-17 15:36:48 +00:00
|
|
|
assert data == b"Message was: Hello, world!"
|
|
|
|
|
|
|
|
|
2018-09-05 10:39:38 +00:00
|
|
|
def test_websocket_send_and_receive_json():
|
2018-08-17 15:36:48 +00:00
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
await websocket.accept()
|
|
|
|
data = await websocket.receive_json()
|
|
|
|
await websocket.send_json({"message": data})
|
|
|
|
await websocket.close()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("/") as websocket:
|
|
|
|
websocket.send_json({"hello": "world"})
|
|
|
|
data = websocket.receive_json()
|
2018-08-17 15:36:48 +00:00
|
|
|
assert data == {"message": {"hello": "world"}}
|
|
|
|
|
|
|
|
|
|
|
|
def test_client_close():
|
|
|
|
close_code = None
|
|
|
|
|
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
|
|
|
nonlocal close_code
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
await websocket.accept()
|
2018-08-17 15:36:48 +00:00
|
|
|
try:
|
2018-10-02 12:15:33 +00:00
|
|
|
await websocket.receive_text()
|
2018-08-17 15:36:48 +00:00
|
|
|
except WebSocketDisconnect as exc:
|
|
|
|
close_code = exc.code
|
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("/") as websocket:
|
2018-10-18 07:47:04 +00:00
|
|
|
websocket.close(code=status.WS_1001_GOING_AWAY)
|
|
|
|
assert close_code == status.WS_1001_GOING_AWAY
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_application_close():
|
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
await websocket.accept()
|
2018-10-18 07:47:04 +00:00
|
|
|
await websocket.close(status.WS_1001_GOING_AWAY)
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("/") as websocket:
|
2018-08-17 15:36:48 +00:00
|
|
|
with pytest.raises(WebSocketDisconnect) as exc:
|
2018-09-05 10:39:38 +00:00
|
|
|
websocket.receive_text()
|
2018-10-18 07:47:04 +00:00
|
|
|
assert exc.value.code == status.WS_1001_GOING_AWAY
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_rejected_connection():
|
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-10-18 07:47:04 +00:00
|
|
|
await websocket.close(status.WS_1001_GOING_AWAY)
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
|
|
|
with pytest.raises(WebSocketDisconnect) as exc:
|
2018-08-28 13:45:06 +00:00
|
|
|
client.websocket_connect("/")
|
2018-10-18 07:47:04 +00:00
|
|
|
assert exc.value.code == status.WS_1001_GOING_AWAY
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_subprotocol():
|
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
assert websocket["subprotocols"] == ["soap", "wamp"]
|
|
|
|
await websocket.accept(subprotocol="wamp")
|
|
|
|
await websocket.close()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("/", subprotocols=["soap", "wamp"]) as websocket:
|
|
|
|
assert websocket.accepted_subprotocol == "wamp"
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
|
2018-09-05 10:39:38 +00:00
|
|
|
def test_websocket_exception():
|
2018-08-17 15:36:48 +00:00
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
|
|
|
assert False
|
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
|
|
|
with pytest.raises(AssertionError):
|
2018-08-28 13:45:06 +00:00
|
|
|
client.websocket_connect("/123?a=abc")
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_duplicate_close():
|
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
await websocket.accept()
|
|
|
|
await websocket.close()
|
|
|
|
await websocket.close()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
|
|
|
with pytest.raises(RuntimeError):
|
2018-10-02 12:15:33 +00:00
|
|
|
with client.websocket_connect("/"):
|
2018-08-17 15:36:48 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def test_duplicate_disconnect():
|
|
|
|
def app(scope):
|
|
|
|
async def asgi(receive, send):
|
2018-10-02 12:24:02 +00:00
|
|
|
websocket = WebSocket(scope, receive=receive, send=send)
|
2018-09-05 10:39:38 +00:00
|
|
|
await websocket.accept()
|
|
|
|
message = await websocket.receive()
|
2018-08-17 15:36:48 +00:00
|
|
|
assert message["type"] == "websocket.disconnect"
|
2018-09-05 10:39:38 +00:00
|
|
|
message = await websocket.receive()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
return asgi
|
|
|
|
|
|
|
|
client = TestClient(app)
|
|
|
|
with pytest.raises(RuntimeError):
|
2018-09-05 10:39:38 +00:00
|
|
|
with client.websocket_connect("/") as websocket:
|
|
|
|
websocket.close()
|
2018-08-17 15:36:48 +00:00
|
|
|
|
|
|
|
|
2018-09-05 10:39:38 +00:00
|
|
|
def test_websocket_scope_interface():
|
2018-08-17 15:36:48 +00:00
|
|
|
"""
|
2018-09-05 09:29:04 +00:00
|
|
|
A WebSocket can be instantiated with a scope, and presents a `Mapping`
|
2018-08-17 15:36:48 +00:00
|
|
|
interface.
|
|
|
|
"""
|
2018-10-02 12:15:33 +00:00
|
|
|
|
2018-10-02 12:24:02 +00:00
|
|
|
async def mock_receive():
|
|
|
|
pass # pragma: no cover
|
|
|
|
|
|
|
|
async def mock_send(message):
|
|
|
|
pass # pragma: no cover
|
|
|
|
|
2018-10-02 12:15:33 +00:00
|
|
|
websocket = WebSocket(
|
|
|
|
{"type": "websocket", "path": "/abc/", "headers": []},
|
2018-10-02 12:24:02 +00:00
|
|
|
receive=mock_receive,
|
|
|
|
send=mock_send,
|
2018-10-02 12:15:33 +00:00
|
|
|
)
|
2018-09-05 10:39:38 +00:00
|
|
|
assert websocket["type"] == "websocket"
|
|
|
|
assert dict(websocket) == {"type": "websocket", "path": "/abc/", "headers": []}
|
|
|
|
assert len(websocket) == 3
|