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:
parent
4429e76532
commit
8f6c87c3d6
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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"""
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user