Fix Test Cases: test_http for Py3.9+, test_json_response_json for ujson 5.4.0+, and test_zero_downtime; Test Case Type Annotations (#2504)

This commit is contained in:
Zhiwei 2022-07-24 14:07:54 -05:00 committed by GitHub
parent 4429e76532
commit 8f6c87c3d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 18 deletions

View File

@ -2,6 +2,7 @@ import json as stdjson
from collections import namedtuple from collections import namedtuple
from pathlib import Path from pathlib import Path
from sys import version_info
import pytest import pytest
@ -35,7 +36,7 @@ def test_app(app: Sanic):
@pytest.fixture @pytest.fixture
def runner(test_app): def runner(test_app: Sanic):
client = ReusableClient(test_app, port=PORT) client = ReusableClient(test_app, port=PORT)
client.run() client.run()
yield client yield client
@ -43,7 +44,7 @@ def runner(test_app):
@pytest.fixture @pytest.fixture
def client(runner): def client(runner: ReusableClient):
client = namedtuple("Client", ("raw", "send", "recv")) client = namedtuple("Client", ("raw", "send", "recv"))
raw = RawClient(runner.host, runner.port) raw = RawClient(runner.host, runner.port)
@ -74,7 +75,10 @@ def test_full_message(client):
""" """
) )
response = client.recv() response = client.recv()
assert len(response) == 151
# AltSvcCheck touchup removes the Alt-Svc header from the
# response in the Python 3.9+ in this case
assert len(response) == (151 if version_info < (3, 9) else 140)
assert b"200 OK" in response assert b"200 OK" in response

View File

@ -3,18 +3,27 @@ import sys
from dataclasses import asdict, dataclass from dataclasses import asdict, dataclass
from functools import partial from functools import partial
from json import dumps as sdumps from json import dumps as sdumps
from string import ascii_lowercase
from typing import Dict
import pytest import pytest
try: try:
import ujson
from ujson import dumps as udumps from ujson import dumps as udumps
ujson_version = tuple(
map(int, ujson.__version__.strip(ascii_lowercase).split("."))
)
NO_UJSON = False NO_UJSON = False
DEFAULT_DUMPS = udumps DEFAULT_DUMPS = udumps
except ModuleNotFoundError: except ModuleNotFoundError:
NO_UJSON = True NO_UJSON = True
DEFAULT_DUMPS = partial(sdumps, separators=(",", ":")) DEFAULT_DUMPS = partial(sdumps, separators=(",", ":"))
ujson_version = None
from sanic import Sanic from sanic import Sanic
from sanic.response import BaseHTTPResponse, json from sanic.response import BaseHTTPResponse, json
@ -34,7 +43,7 @@ def foo():
@pytest.fixture @pytest.fixture
def payload(foo): def payload(foo: Foo):
return {"foo": foo} return {"foo": foo}
@ -58,7 +67,7 @@ def test_change_encoder_to_some_custom():
@pytest.mark.skipif(NO_UJSON is True, reason="ujson not installed") @pytest.mark.skipif(NO_UJSON is True, reason="ujson not installed")
def test_json_response_ujson(payload): def test_json_response_ujson(payload: Dict[str, Foo]):
"""ujson will look at __json__""" """ujson will look at __json__"""
response = json(payload) response = json(payload)
assert response.body == b'{"foo":{"bar":"bar"}}' assert response.body == b'{"foo":{"bar":"bar"}}'
@ -75,7 +84,13 @@ def test_json_response_ujson(payload):
json(payload) json(payload)
@pytest.mark.skipif(NO_UJSON is True, reason="ujson not installed") @pytest.mark.skipif(
NO_UJSON is True or ujson_version >= (5, 4, 0),
reason=(
"ujson not installed or version is 5.4.0 or newer, "
"which can handle arbitrary size integers"
),
)
def test_json_response_json(): def test_json_response_json():
"""One of the easiest ways to tell the difference is that ujson cannot """One of the easiest ways to tell the difference is that ujson cannot
serialize over 64 bits""" serialize over 64 bits"""

View File

@ -5,13 +5,17 @@ import platform
import subprocess import subprocess
import sys import sys
from asyncio import AbstractEventLoop
from string import ascii_lowercase from string import ascii_lowercase
import httpcore import httpcore
import httpx import httpx
import pytest import pytest
from pytest import LogCaptureFixture
from sanic import Sanic from sanic import Sanic
from sanic.request import Request
from sanic.response import text from sanic.response import text
@ -45,7 +49,7 @@ def socket_cleanup():
pass pass
def test_unix_socket_creation(caplog): def test_unix_socket_creation(caplog: LogCaptureFixture):
from socket import AF_UNIX, socket from socket import AF_UNIX, socket
with socket(AF_UNIX) as sock: with socket(AF_UNIX) as sock:
@ -56,7 +60,7 @@ def test_unix_socket_creation(caplog):
app = Sanic(name="test") app = Sanic(name="test")
@app.listener("after_server_start") @app.listener("after_server_start")
def running(app, loop): def running(app: Sanic, loop: AbstractEventLoop):
assert os.path.exists(SOCKPATH) assert os.path.exists(SOCKPATH)
assert ino != os.stat(SOCKPATH).st_ino assert ino != os.stat(SOCKPATH).st_ino
app.stop() app.stop()
@ -73,7 +77,7 @@ def test_unix_socket_creation(caplog):
@pytest.mark.parametrize("path", (".", "no-such-directory/sanictest.sock")) @pytest.mark.parametrize("path", (".", "no-such-directory/sanictest.sock"))
def test_invalid_paths(path): def test_invalid_paths(path: str):
app = Sanic(name="test") app = Sanic(name="test")
with pytest.raises((FileExistsError, FileNotFoundError)): with pytest.raises((FileExistsError, FileNotFoundError)):
@ -87,7 +91,7 @@ def test_dont_replace_file():
app = Sanic(name="test") app = Sanic(name="test")
@app.listener("after_server_start") @app.listener("after_server_start")
def stop(app, loop): def stop(app: Sanic, loop: AbstractEventLoop):
app.stop() app.stop()
with pytest.raises(FileExistsError): with pytest.raises(FileExistsError):
@ -104,7 +108,7 @@ def test_dont_follow_symlink():
app = Sanic(name="test") app = Sanic(name="test")
@app.listener("after_server_start") @app.listener("after_server_start")
def stop(app, loop): def stop(app: Sanic, loop: AbstractEventLoop):
app.stop() app.stop()
with pytest.raises(FileExistsError): with pytest.raises(FileExistsError):
@ -115,7 +119,7 @@ def test_socket_deleted_while_running():
app = Sanic(name="test") app = Sanic(name="test")
@app.listener("after_server_start") @app.listener("after_server_start")
async def hack(app, loop): async def hack(app: Sanic, loop: AbstractEventLoop):
os.unlink(SOCKPATH) os.unlink(SOCKPATH)
app.stop() app.stop()
@ -126,7 +130,7 @@ def test_socket_replaced_with_file():
app = Sanic(name="test") app = Sanic(name="test")
@app.listener("after_server_start") @app.listener("after_server_start")
async def hack(app, loop): async def hack(app: Sanic, loop: AbstractEventLoop):
os.unlink(SOCKPATH) os.unlink(SOCKPATH)
with open(SOCKPATH, "w") as f: with open(SOCKPATH, "w") as f:
f.write("Not a socket") f.write("Not a socket")
@ -139,11 +143,11 @@ def test_unix_connection():
app = Sanic(name="test") app = Sanic(name="test")
@app.get("/") @app.get("/")
def handler(request): def handler(request: Request):
return text(f"{request.conn_info.server}") return text(f"{request.conn_info.server}")
@app.listener("after_server_start") @app.listener("after_server_start")
async def client(app, loop): async def client(app: Sanic, loop: AbstractEventLoop):
if httpx_version >= (0, 20): if httpx_version >= (0, 20):
transport = httpx.AsyncHTTPTransport(uds=SOCKPATH) transport = httpx.AsyncHTTPTransport(uds=SOCKPATH)
else: else:
@ -162,11 +166,11 @@ def test_unix_connection():
app_multi = Sanic(name="test") app_multi = Sanic(name="test")
def handler(request): def handler(request: Request):
return text(f"{request.conn_info.server}") return text(f"{request.conn_info.server}")
async def client(app, loop): async def client(app: Sanic, loop: AbstractEventLoop):
try: try:
async with httpx.AsyncClient(uds=SOCKPATH) as client: async with httpx.AsyncClient(uds=SOCKPATH) as client:
r = await client.get("http://myhost.invalid/") r = await client.get("http://myhost.invalid/")
@ -229,7 +233,7 @@ async def test_zero_downtime():
ino = os.stat(SOCKPATH).st_ino ino = os.stat(SOCKPATH).st_ino
task = asyncio.get_event_loop().create_task(client()) task = asyncio.get_event_loop().create_task(client())
start_time = current_time() start_time = current_time()
while current_time() < start_time + 4: while current_time() < start_time + 6:
# Start a new one and wait until the socket is replaced # Start a new one and wait until the socket is replaced
processes.append(spawn()) processes.append(spawn())
while ino == os.stat(SOCKPATH).st_ino: while ino == os.stat(SOCKPATH).st_ino: