Change back to codecov (#2363)
This commit is contained in:
parent
101151b419
commit
8b0eaa097c
|
@ -1,28 +0,0 @@
|
|||
exclude_patterns:
|
||||
- "sanic/__main__.py"
|
||||
- "sanic/application/logo.py"
|
||||
- "sanic/application/motd.py"
|
||||
- "sanic/reloader_helpers.py"
|
||||
- "sanic/simple.py"
|
||||
- "sanic/utils.py"
|
||||
- ".github/"
|
||||
- "changelogs/"
|
||||
- "docker/"
|
||||
- "docs/"
|
||||
- "examples/"
|
||||
- "scripts/"
|
||||
- "tests/"
|
||||
checks:
|
||||
argument-count:
|
||||
enabled: false
|
||||
file-lines:
|
||||
config:
|
||||
threshold: 1000
|
||||
method-count:
|
||||
config:
|
||||
threshold: 40
|
||||
complex-logic:
|
||||
enabled: false
|
||||
method-complexity:
|
||||
config:
|
||||
threshold: 10
|
14
.coveragerc
14
.coveragerc
|
@ -3,13 +3,12 @@ branch = True
|
|||
source = sanic
|
||||
omit =
|
||||
site-packages
|
||||
sanic/application/logo.py
|
||||
sanic/application/motd.py
|
||||
sanic/cli
|
||||
sanic/__main__.py
|
||||
sanic/compat.py
|
||||
sanic/reloader_helpers.py
|
||||
sanic/simple.py
|
||||
sanic/utils.py
|
||||
sanic/cli
|
||||
|
||||
[html]
|
||||
directory = coverage
|
||||
|
@ -21,3 +20,12 @@ exclude_lines =
|
|||
noqa
|
||||
NOQA
|
||||
pragma: no cover
|
||||
omit =
|
||||
site-packages
|
||||
sanic/__main__.py
|
||||
sanic/compat.py
|
||||
sanic/reloader_helpers.py
|
||||
sanic/simple.py
|
||||
sanic/utils.py
|
||||
sanic/cli
|
||||
skip_empty = True
|
||||
|
|
11
.github/workflows/coverage.yml
vendored
11
.github/workflows/coverage.yml
vendored
|
@ -20,7 +20,6 @@ jobs:
|
|||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
@ -29,9 +28,9 @@ jobs:
|
|||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install tox
|
||||
- uses: paambaati/codeclimate-action@v2.5.3
|
||||
if: always()
|
||||
env:
|
||||
CC_TEST_REPORTER_ID: ${{ secrets.CODECLIMATE }}
|
||||
- name: Run coverage
|
||||
run: tox -e coverage
|
||||
- uses: codecov/codecov-action@v2
|
||||
with:
|
||||
coverageCommand: tox -e coverage
|
||||
files: ./coverage.xml
|
||||
fail_ci_if_error: false
|
||||
|
|
27
codecov.yml
Normal file
27
codecov.yml
Normal file
|
@ -0,0 +1,27 @@
|
|||
coverage:
|
||||
status:
|
||||
patch:
|
||||
default:
|
||||
target: auto
|
||||
threshold: 0.75
|
||||
project:
|
||||
default:
|
||||
target: auto
|
||||
threshold: 0.5
|
||||
precision: 3
|
||||
codecov:
|
||||
require_ci_to_pass: false
|
||||
ignore:
|
||||
- "sanic/__main__.py"
|
||||
- "sanic/compat.py"
|
||||
- "sanic/reloader_helpers.py"
|
||||
- "sanic/simple.py"
|
||||
- "sanic/utils.py"
|
||||
- "sanic/cli"
|
||||
- ".github/"
|
||||
- "changelogs/"
|
||||
- "docker/"
|
||||
- "docs/"
|
||||
- "examples/"
|
||||
- "scripts/"
|
||||
- "tests/"
|
16
sanic/app.py
16
sanic/app.py
|
@ -114,7 +114,7 @@ if TYPE_CHECKING: # no cov
|
|||
Extend = TypeVar("Extend") # type: ignore
|
||||
|
||||
|
||||
if OS_IS_WINDOWS:
|
||||
if OS_IS_WINDOWS: # no cov
|
||||
enable_windows_color_support()
|
||||
|
||||
filterwarnings("once", category=DeprecationWarning)
|
||||
|
@ -1554,7 +1554,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
|
|||
) -> Task:
|
||||
if not isinstance(task, Future):
|
||||
prepped = cls._prep_task(task, app, loop)
|
||||
if sys.version_info < (3, 8):
|
||||
if sys.version_info < (3, 8): # no cov
|
||||
if name:
|
||||
error_logger.warning(
|
||||
"Cannot set a name for a task when using Python 3.7. "
|
||||
|
@ -1598,7 +1598,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
|
|||
|
||||
:param task: future, couroutine or awaitable
|
||||
"""
|
||||
if name and sys.version_info == (3, 7):
|
||||
if name and sys.version_info < (3, 8): # no cov
|
||||
name = None
|
||||
error_logger.warning(
|
||||
"Cannot set a name for a task when using Python 3.7. Your "
|
||||
|
@ -1626,7 +1626,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
|
|||
def get_task(
|
||||
self, name: str, *, raise_exception: bool = True
|
||||
) -> Optional[Task]:
|
||||
if sys.version_info < (3, 8):
|
||||
if sys.version_info < (3, 8): # no cov
|
||||
error_logger.warning(
|
||||
"This feature (get_task) is only supported on using "
|
||||
"Python 3.8+."
|
||||
|
@ -1648,7 +1648,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
|
|||
*,
|
||||
raise_exception: bool = True,
|
||||
) -> None:
|
||||
if sys.version_info < (3, 8):
|
||||
if sys.version_info < (3, 8): # no cov
|
||||
error_logger.warning(
|
||||
"This feature (cancel_task) is only supported on using "
|
||||
"Python 3.8+."
|
||||
|
@ -1660,7 +1660,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
|
|||
if msg:
|
||||
if sys.version_info >= (3, 9):
|
||||
args = (msg,)
|
||||
else:
|
||||
else: # no cov
|
||||
raise RuntimeError(
|
||||
"Cancelling a task with a message is only supported "
|
||||
"on Python 3.9+."
|
||||
|
@ -1672,7 +1672,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
|
|||
...
|
||||
|
||||
def purge_tasks(self):
|
||||
if sys.version_info < (3, 8):
|
||||
if sys.version_info < (3, 8): # no cov
|
||||
error_logger.warning(
|
||||
"This feature (purge_tasks) is only supported on using "
|
||||
"Python 3.8+."
|
||||
|
@ -1709,7 +1709,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
|
|||
|
||||
@property
|
||||
def tasks(self):
|
||||
if sys.version_info < (3, 8):
|
||||
if sys.version_info < (3, 8): # no cov
|
||||
error_logger.warning(
|
||||
"This feature (tasks) is only supported on using "
|
||||
"Python 3.8+."
|
||||
|
|
|
@ -53,14 +53,14 @@ class ErrorHandler:
|
|||
self._warn_fallback_deprecation()
|
||||
|
||||
@property
|
||||
def fallback(self):
|
||||
def fallback(self): # no cov
|
||||
# This is for backwards compat and can be removed in v22.6
|
||||
if self._fallback is _default:
|
||||
return DEFAULT_FORMAT
|
||||
return self._fallback
|
||||
|
||||
@fallback.setter
|
||||
def fallback(self, value: str):
|
||||
def fallback(self, value: str): # no cov
|
||||
self._warn_fallback_deprecation()
|
||||
if not isinstance(value, str):
|
||||
raise SanicException(
|
||||
|
@ -236,7 +236,7 @@ class ErrorHandler:
|
|||
except Exception:
|
||||
try:
|
||||
url = repr(request.url)
|
||||
except AttributeError:
|
||||
except AttributeError: # no cov
|
||||
url = "unknown"
|
||||
response_message = (
|
||||
"Exception raised in exception handler " '"%s" for uri: %s'
|
||||
|
@ -281,7 +281,7 @@ class ErrorHandler:
|
|||
if quiet is False or noisy is True:
|
||||
try:
|
||||
url = repr(request.url)
|
||||
except AttributeError:
|
||||
except AttributeError: # no cov
|
||||
url = "unknown"
|
||||
|
||||
error_logger.exception(
|
||||
|
|
12
sanic/log.py
12
sanic/log.py
|
@ -6,7 +6,7 @@ from typing import Any, Dict
|
|||
from warnings import warn
|
||||
|
||||
|
||||
LOGGING_CONFIG_DEFAULTS: Dict[str, Any] = dict(
|
||||
LOGGING_CONFIG_DEFAULTS: Dict[str, Any] = dict( # no cov
|
||||
version=1,
|
||||
disable_existing_loggers=False,
|
||||
loggers={
|
||||
|
@ -57,7 +57,7 @@ LOGGING_CONFIG_DEFAULTS: Dict[str, Any] = dict(
|
|||
)
|
||||
|
||||
|
||||
class Colors(str, Enum):
|
||||
class Colors(str, Enum): # no cov
|
||||
END = "\033[0m"
|
||||
BLUE = "\033[01;34m"
|
||||
GREEN = "\033[01;32m"
|
||||
|
@ -65,23 +65,23 @@ class Colors(str, Enum):
|
|||
RED = "\033[01;31m"
|
||||
|
||||
|
||||
logger = logging.getLogger("sanic.root")
|
||||
logger = logging.getLogger("sanic.root") # no cov
|
||||
"""
|
||||
General Sanic logger
|
||||
"""
|
||||
|
||||
error_logger = logging.getLogger("sanic.error")
|
||||
error_logger = logging.getLogger("sanic.error") # no cov
|
||||
"""
|
||||
Logger used by Sanic for error logging
|
||||
"""
|
||||
|
||||
access_logger = logging.getLogger("sanic.access")
|
||||
access_logger = logging.getLogger("sanic.access") # no cov
|
||||
"""
|
||||
Logger used by Sanic for access logging
|
||||
"""
|
||||
|
||||
|
||||
def deprecation(message: str, version: float):
|
||||
def deprecation(message: str, version: float): # no cov
|
||||
version_info = f"[DEPRECATION v{version}] "
|
||||
if sys.stdout.isatty():
|
||||
version_info = f"{Colors.RED}{version_info}"
|
||||
|
|
|
@ -13,7 +13,7 @@ ASGISend = Callable[[ASGIMessage], Awaitable[None]]
|
|||
ASGIReceive = Callable[[], Awaitable[ASGIMessage]]
|
||||
|
||||
|
||||
class MockProtocol:
|
||||
class MockProtocol: # no cov
|
||||
def __init__(self, transport: "MockTransport", loop):
|
||||
# This should be refactored when < 3.8 support is dropped
|
||||
self.transport = transport
|
||||
|
@ -56,7 +56,7 @@ class MockProtocol:
|
|||
await self._not_paused.wait()
|
||||
|
||||
|
||||
class MockTransport:
|
||||
class MockTransport: # no cov
|
||||
_protocol: Optional[MockProtocol]
|
||||
|
||||
def __init__(
|
||||
|
|
|
@ -9,7 +9,7 @@ from websockets.typing import Data
|
|||
from sanic.exceptions import ServerError
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
if TYPE_CHECKING: # no cov
|
||||
from .impl import WebsocketImplProtocol
|
||||
|
||||
UTF8Decoder = codecs.getincrementaldecoder("utf-8")
|
||||
|
@ -37,7 +37,7 @@ class WebsocketFrameAssembler:
|
|||
"get_id",
|
||||
"put_id",
|
||||
)
|
||||
if TYPE_CHECKING:
|
||||
if TYPE_CHECKING: # no cov
|
||||
protocol: "WebsocketImplProtocol"
|
||||
read_mutex: asyncio.Lock
|
||||
write_mutex: asyncio.Lock
|
||||
|
@ -131,7 +131,7 @@ class WebsocketFrameAssembler:
|
|||
if self.paused:
|
||||
self.protocol.resume_frames()
|
||||
self.paused = False
|
||||
if not self.get_in_progress:
|
||||
if not self.get_in_progress: # no cov
|
||||
# This should be guarded against with the read_mutex,
|
||||
# exception is here as a failsafe
|
||||
raise ServerError(
|
||||
|
@ -204,7 +204,7 @@ class WebsocketFrameAssembler:
|
|||
if self.paused:
|
||||
self.protocol.resume_frames()
|
||||
self.paused = False
|
||||
if not self.get_in_progress:
|
||||
if not self.get_in_progress: # no cov
|
||||
# This should be guarded against with the read_mutex,
|
||||
# exception is here as a failsafe
|
||||
raise ServerError(
|
||||
|
@ -212,7 +212,7 @@ class WebsocketFrameAssembler:
|
|||
"asynchronous get was in progress."
|
||||
)
|
||||
self.get_in_progress = False
|
||||
if not self.message_complete.is_set():
|
||||
if not self.message_complete.is_set(): # no cov
|
||||
# This should be guarded against with the read_mutex,
|
||||
# exception is here as a failsafe
|
||||
raise ServerError(
|
||||
|
@ -220,7 +220,7 @@ class WebsocketFrameAssembler:
|
|||
"message was complete."
|
||||
)
|
||||
self.message_complete.clear()
|
||||
if self.message_fetched.is_set():
|
||||
if self.message_fetched.is_set(): # no cov
|
||||
# This should be guarded against with the read_mutex,
|
||||
# and get_in_progress check, this exception is
|
||||
# here as a failsafe
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import asyncio
|
||||
import base64
|
||||
import logging
|
||||
import random
|
||||
import re
|
||||
|
@ -205,7 +204,3 @@ def sanic_ext(ext_instance): # noqa
|
|||
yield sanic_ext
|
||||
with suppress(KeyError):
|
||||
del sys.modules["sanic_ext"]
|
||||
|
||||
|
||||
def encode_basic_auth_credentials(username, password):
|
||||
return base64.b64encode(f"{username}:{password}".encode()).decode("ascii")
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import base64
|
||||
import logging
|
||||
|
||||
from json import dumps as json_dumps
|
||||
|
@ -18,7 +19,10 @@ from sanic import Blueprint, Sanic
|
|||
from sanic.exceptions import ServerError
|
||||
from sanic.request import DEFAULT_HTTP_CONTENT_TYPE, RequestParameters
|
||||
from sanic.response import html, json, text
|
||||
from tests.conftest import encode_basic_auth_credentials
|
||||
|
||||
|
||||
def encode_basic_auth_credentials(username, password):
|
||||
return base64.b64encode(f"{username}:{password}".encode()).decode("ascii")
|
||||
|
||||
|
||||
# ------------------------------------------------------------ #
|
||||
|
|
237
tests/test_websockets.py
Normal file
237
tests/test_websockets.py
Normal file
|
@ -0,0 +1,237 @@
|
|||
import re
|
||||
|
||||
from asyncio import Event, Queue, TimeoutError
|
||||
from unittest.mock import AsyncMock, Mock, call
|
||||
|
||||
import pytest
|
||||
|
||||
from websockets.frames import CTRL_OPCODES, DATA_OPCODES, Frame
|
||||
|
||||
from sanic.exceptions import ServerError
|
||||
from sanic.server.websockets.frame import WebsocketFrameAssembler
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_message_incomplete_timeout_0():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete = AsyncMock(spec=Event)
|
||||
assembler.message_complete.is_set = Mock(return_value=False)
|
||||
data = await assembler.get(0)
|
||||
|
||||
assert data is None
|
||||
assembler.message_complete.is_set.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_message_in_progress():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.get_in_progress = True
|
||||
|
||||
message = re.escape(
|
||||
"Called get() on Websocket frame assembler "
|
||||
"while asynchronous get is already in progress."
|
||||
)
|
||||
|
||||
with pytest.raises(ServerError, match=message):
|
||||
await assembler.get()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_message_incomplete():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete.wait = AsyncMock(return_value=True)
|
||||
assembler.message_complete.is_set = Mock(return_value=False)
|
||||
data = await assembler.get()
|
||||
|
||||
assert data is None
|
||||
assembler.message_complete.wait.assert_awaited_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_message():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete.wait = AsyncMock(return_value=True)
|
||||
assembler.message_complete.is_set = Mock(return_value=True)
|
||||
data = await assembler.get()
|
||||
|
||||
assert data == b""
|
||||
assembler.message_complete.wait.assert_awaited_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_message_with_timeout():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete.wait = AsyncMock(return_value=True)
|
||||
assembler.message_complete.is_set = Mock(return_value=True)
|
||||
data = await assembler.get(0.1)
|
||||
|
||||
assert data == b""
|
||||
assembler.message_complete.wait.assert_awaited_once()
|
||||
assert assembler.message_complete.is_set.call_count == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_message_with_timeouterror():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete.wait = AsyncMock(return_value=True)
|
||||
assembler.message_complete.is_set = Mock(return_value=True)
|
||||
assembler.message_complete.wait.side_effect = TimeoutError("...")
|
||||
data = await assembler.get(0.1)
|
||||
|
||||
assert data == b""
|
||||
assembler.message_complete.wait.assert_awaited_once()
|
||||
assert assembler.message_complete.is_set.call_count == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_not_completed():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete = AsyncMock(spec=Event)
|
||||
assembler.message_complete.is_set = Mock(return_value=False)
|
||||
data = await assembler.get()
|
||||
|
||||
assert data is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_not_completed_start():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete = AsyncMock(spec=Event)
|
||||
assembler.message_complete.is_set = Mock(side_effect=[False, True])
|
||||
data = await assembler.get(0.1)
|
||||
|
||||
assert data is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_paused():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete = AsyncMock(spec=Event)
|
||||
assembler.message_complete.is_set = Mock(side_effect=[False, True])
|
||||
assembler.paused = True
|
||||
data = await assembler.get()
|
||||
|
||||
assert data is None
|
||||
assembler.protocol.resume_frames.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_data():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete = AsyncMock(spec=Event)
|
||||
assembler.message_complete.is_set = Mock(return_value=True)
|
||||
assembler.chunks = [b"foo", b"bar"]
|
||||
data = await assembler.get()
|
||||
|
||||
assert data == b"foobar"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_iter_in_progress():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.get_in_progress = True
|
||||
|
||||
message = re.escape(
|
||||
"Called get_iter on Websocket frame assembler "
|
||||
"while asynchronous get is already in progress."
|
||||
)
|
||||
|
||||
with pytest.raises(ServerError, match=message):
|
||||
[x async for x in assembler.get_iter()]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_iter_none_in_queue():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete.set()
|
||||
assembler.chunks = [b"foo", b"bar"]
|
||||
|
||||
chunks = [x async for x in assembler.get_iter()]
|
||||
|
||||
assert chunks == [b"foo", b"bar"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ws_frame_get_iter_paused():
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete.set()
|
||||
assembler.paused = True
|
||||
|
||||
[x async for x in assembler.get_iter()]
|
||||
assembler.protocol.resume_frames.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("opcode", DATA_OPCODES)
|
||||
async def test_ws_frame_put_not_fetched(opcode):
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_fetched.set()
|
||||
|
||||
message = re.escape(
|
||||
"Websocket put() got a new message when the previous message was "
|
||||
"not yet fetched."
|
||||
)
|
||||
with pytest.raises(ServerError, match=message):
|
||||
await assembler.put(Frame(opcode, b""))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("opcode", DATA_OPCODES)
|
||||
async def test_ws_frame_put_fetched(opcode):
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_fetched = AsyncMock()
|
||||
assembler.message_fetched.is_set = Mock(return_value=False)
|
||||
|
||||
await assembler.put(Frame(opcode, b""))
|
||||
assembler.message_fetched.wait.assert_awaited_once()
|
||||
assembler.message_fetched.clear.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("opcode", DATA_OPCODES)
|
||||
async def test_ws_frame_put_message_complete(opcode):
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.message_complete.set()
|
||||
|
||||
message = re.escape(
|
||||
"Websocket put() got a new message when a message was "
|
||||
"already in its chamber."
|
||||
)
|
||||
with pytest.raises(ServerError, match=message):
|
||||
await assembler.put(Frame(opcode, b""))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("opcode", DATA_OPCODES)
|
||||
async def test_ws_frame_put_message_into_queue(opcode):
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
assembler.chunks_queue = AsyncMock(spec=Queue)
|
||||
assembler.message_fetched = AsyncMock()
|
||||
assembler.message_fetched.is_set = Mock(return_value=False)
|
||||
|
||||
await assembler.put(Frame(opcode, b"foo"))
|
||||
|
||||
assembler.chunks_queue.put.has_calls(
|
||||
call(b"foo"),
|
||||
call(None),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("opcode", DATA_OPCODES)
|
||||
async def test_ws_frame_put_not_fin(opcode):
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
|
||||
retval = await assembler.put(Frame(opcode, b"foo", fin=False))
|
||||
|
||||
assert retval is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("opcode", CTRL_OPCODES)
|
||||
async def test_ws_frame_put_skip_ctrl(opcode):
|
||||
assembler = WebsocketFrameAssembler(Mock())
|
||||
|
||||
retval = await assembler.put(Frame(opcode, b""))
|
||||
|
||||
assert retval is None
|
Loading…
Reference in New Issue
Block a user