Skip to content

Commit

Permalink
Increase testing coverage for ASGI
Browse files Browse the repository at this point in the history
Beautify

Specify websockets version
  • Loading branch information
ahopkins committed Jun 18, 2019
1 parent fb61834 commit b1c23fd
Show file tree
Hide file tree
Showing 9 changed files with 430 additions and 34 deletions.
8 changes: 8 additions & 0 deletions .coveragerc
Expand Up @@ -5,3 +5,11 @@ omit = site-packages, sanic/utils.py, sanic/__main__.py

[html]
directory = coverage

[report]
exclude_lines =
no cov
no qa
noqa
NOQA
pragma: no cover
29 changes: 18 additions & 11 deletions sanic/asgi.py
Expand Up @@ -88,7 +88,7 @@ def create_websocket_connection(
self._websocket_connection = WebSocketConnection(send, receive)
return self._websocket_connection

def add_task(self) -> None:
def add_task(self) -> None: # noqa
raise NotImplementedError

async def send(self, data) -> None:
Expand Down Expand Up @@ -119,15 +119,15 @@ def __init__(self, asgi_app: "ASGIApp") -> None:
"the ASGI server is stopped."
)

async def pre_startup(self) -> None:
for handler in self.asgi_app.sanic_app.listeners[
"before_server_start"
]:
response = handler(
self.asgi_app.sanic_app, self.asgi_app.sanic_app.loop
)
if isawaitable(response):
await response
# async def pre_startup(self) -> None:
# for handler in self.asgi_app.sanic_app.listeners[
# "before_server_start"
# ]:
# response = handler(
# self.asgi_app.sanic_app, self.asgi_app.sanic_app.loop
# )
# if isawaitable(response):
# await response

async def startup(self) -> None:
for handler in self.asgi_app.sanic_app.listeners[
Expand Down Expand Up @@ -233,7 +233,14 @@ async def create(
)

if sanic_app.is_request_stream:
instance.request.stream = StreamBuffer()
is_stream_handler = sanic_app.router.is_stream_handler(
instance.request
)
if is_stream_handler:
instance.request.stream = StreamBuffer(
sanic_app.config.REQUEST_BUFFER_QUEUE_SIZE
)
instance.do_stream = True

return instance

Expand Down
83 changes: 66 additions & 17 deletions sanic/testing.py
Expand Up @@ -136,7 +136,7 @@ async def _collect_response(sanic, loop):
try:
request, response = results
return request, response
except BaseException:
except BaseException: # noqa
raise ValueError(
"Request and response object expected, got ({})".format(
results
Expand All @@ -145,7 +145,7 @@ async def _collect_response(sanic, loop):
else:
try:
return results[-1]
except BaseException:
except BaseException: # noqa
raise ValueError(
"Request object expected, got ({})".format(results)
)
Expand Down Expand Up @@ -175,7 +175,7 @@ def websocket(self, *args, **kwargs):
return self._sanic_endpoint_test("websocket", *args, **kwargs)


class SanicASGIAdapter(requests.asgi.ASGIAdapter):
class SanicASGIAdapter(requests.asgi.ASGIAdapter): # noqa
async def send( # type: ignore
self,
request: requests.PreparedRequest,
Expand Down Expand Up @@ -218,19 +218,43 @@ async def send( # type: ignore
for key, value in request.headers.items()
]

scope = {
"type": "http",
"http_version": "1.1",
"method": request.method,
"path": unquote(path),
"root_path": "",
"scheme": scheme,
"query_string": query.encode(),
"headers": headers,
"client": ["testclient", 50000],
"server": [host, port],
"extensions": {"http.response.template": {}},
}
no_response = False
if scheme in {"ws", "wss"}:
subprotocol = request.headers.get("sec-websocket-protocol", None)
if subprotocol is None:
subprotocols = [] # type: typing.Sequence[str]
else:
subprotocols = [
value.strip() for value in subprotocol.split(",")
]

scope = {
"type": "websocket",
"path": unquote(path),
"root_path": "",
"scheme": scheme,
"query_string": query.encode(),
"headers": headers,
"client": ["testclient", 50000],
"server": [host, port],
"subprotocols": subprotocols,
}
no_response = True

else:
scope = {
"type": "http",
"http_version": "1.1",
"method": request.method,
"path": unquote(path),
"root_path": "",
"scheme": scheme,
"query_string": query.encode(),
"headers": headers,
"client": ["testclient", 50000],
"server": [host, port],
"extensions": {"http.response.template": {}},
}

async def receive():
nonlocal request_complete, response_complete
Expand Down Expand Up @@ -306,6 +330,10 @@ async def send(message) -> None:
if not self.suppress_exceptions:
raise exc from None

if no_response:
response_started = True
raw_kwargs = {"status_code": 204, "headers": []}

if not self.suppress_exceptions:
assert response_started, "TestClient did not receive any response."
elif not response_started:
Expand Down Expand Up @@ -349,13 +377,15 @@ def __init__(
)
self.mount("http://", adapter)
self.mount("https://", adapter)
self.mount("ws://", adapter)
self.mount("wss://", adapter)
self.headers.update({"user-agent": "testclient"})
self.app = app
self.base_url = base_url

async def request(self, method, url, gather_request=True, *args, **kwargs):

self.gather_request = gather_request
print(url)
response = await super().request(method, url, *args, **kwargs)
response.status = response.status_code
response.body = response.content
Expand All @@ -372,3 +402,22 @@ def merge_environment_settings(self, *args, **kwargs):
settings = super().merge_environment_settings(*args, **kwargs)
settings.update({"gather_return": self.gather_request})
return settings

async def websocket(self, uri, subprotocols=None, *args, **kwargs):
if uri.startswith(("ws:", "wss:")):
url = uri
else:
uri = uri if uri.startswith("/") else "/{uri}".format(uri=uri)
url = "ws://testserver{uri}".format(uri=uri)

headers = kwargs.get("headers", {})
headers.setdefault("connection", "upgrade")
headers.setdefault("sec-websocket-key", "testserver==")
headers.setdefault("sec-websocket-version", "13")
if subprotocols is not None:
headers.setdefault(
"sec-websocket-protocol", ", ".join(subprotocols)
)
kwargs["headers"] = headers

return await self.request("websocket", url, **kwargs)
5 changes: 2 additions & 3 deletions sanic/websocket.py
Expand Up @@ -143,9 +143,8 @@ async def recv(self, *args, **kwargs) -> Optional[str]:
return message["text"]
elif message["type"] == "websocket.disconnect":
pass
# await self._send({
# "type": "websocket.close"
# })

receive = recv

async def accept(self) -> None:
await self._send({"type": "websocket.accept", "subprotocol": ""})
Expand Down

0 comments on commit b1c23fd

Please sign in to comment.