Testing overhaul

This commit is contained in:
James Roberts
2021-12-18 17:39:30 +02:00
parent a9db3be5aa
commit 0daf220291
15 changed files with 221 additions and 110 deletions

4
clean_install.sh Normal file
View File

@@ -0,0 +1,4 @@
sudo rm -rf /usr/local/lib/python3.8/dist-packages/_fastwsgi*;
sudo rm -rf /usr/local/lib/python3.8/dist-packages/fastwsgi*;
rm -rf build/ dist/ bin/ __pycache__/
sudo python3 setup.py install

View File

@@ -48,9 +48,9 @@ def import_from_string(import_str):
return module
def print_server_details():
def print_server_details(host, port):
print(f"\n==== FastWSGI ==== ")
print(f"Host: {HOST}\nPort: {PORT}")
print(f"Host: {host}\nPort: {port}")
print("==================\n")
@@ -65,8 +65,8 @@ def run_from_cli():
_fastwsgi.run_server(wsgi_app, "", PORT, BACKLOG, LOGGING)
def run(wsgi_app, host, port, backlog=1024):
print_server_details()
def run(wsgi_app, host=HOST, port=PORT, backlog=1024):
print_server_details(host, port)
print(f"Server listening at http://{host}:{port}")
_fastwsgi.run_server(wsgi_app, host, port, backlog, LOGGING)
# run_multi_process_server(wsgi_app)

View File

@@ -1,4 +1,7 @@
path_classifiers:
library:
- llhttp/**/*.c
- llhttp/**/*.h
- llhttp/**/*.h
- libuv/**/*.c
- libuv/**/*.h
- performance_benchmarks/**/*.py

0
tests/__init__.py Normal file
View File

View File

@@ -0,0 +1,4 @@
from .basic_app import basic_app
from .wsgi_app import wsgi_app
from .flask_app import app as flask_app
from .wsgi_validator_app import validator_app

View File

@@ -0,0 +1,4 @@
def basic_app(environ, start_response):
headers = [("Content-Type", "text/plain")]
start_response("200 OK", headers)
return [b"Hello World"]

View File

@@ -0,0 +1,18 @@
from flask import Flask
app = Flask(__name__)
@app.get("/get")
def get():
return "get", 200
@app.post("/post")
def post():
return "post", 201
@app.delete("/delete")
def delete():
return "delete", 204

View File

@@ -0,0 +1,30 @@
def _get(environ, start_repsonse):
assert environ.get("REQUEST_METHOD") == "GET"
headers = [("Content-Type", "text/plain")]
start_repsonse("200 OK", headers)
return [b"OK"]
def _post(environ, start_repsonse):
assert environ.get("REQUEST_METHOD") == "POST"
headers = [("Content-Type", "text/plain")]
start_repsonse("201 Created", headers)
return [b"OK"]
def _delete(environ, start_response):
assert environ.get("REQUEST_METHOD") == "DELETE"
start_response("204 No Content", [])
return [b""]
routes = {
"/get": _get,
"/post": _post,
"/delete": _delete,
}
def wsgi_app(environ, start_response):
app = routes.get(environ["PATH_INFO"])
return app(environ, start_response)

View File

@@ -0,0 +1,11 @@
from wsgiref.validate import validator
def simple_app(environ, start_response):
status = "200 OK"
headers = [("Content-type", "text/plain")]
start_response(status, headers)
return [b"Valid"]
validator_app = validator(simple_app)

View File

@@ -1,28 +1,96 @@
import os
import sys
import pytest
import fastwsgi
import time
from enum import Enum
from contextlib import contextmanager
from multiprocessing import Process, set_start_method
from tests.apps_under_test import (
basic_app,
wsgi_app,
flask_app,
validator_app,
)
HOST = "127.0.0.1"
PORT = 8080
PORT = 5000
class ServerProcess:
def __init__(self, application, host=HOST, port=PORT) -> None:
self.process = Process(target=fastwsgi.run, args=(application, host, port))
self.endpoint = f"http://{host}:{port}"
self.host = host
self.port = port
def __enter__(self):
def start(self):
self.process.start()
time.sleep(1) # Allow server to start
return self
def __exit__(self, exc_type, exc_value, exc_tb):
def kill(self):
self.process.kill()
@pytest.fixture(autouse=True, scope="session")
def server_process():
class Servers(Enum):
BASIC_TEST_SERVER = 1
WSGI_TEST_SERVER = 2
FLASK_TEST_SERVER = 3
VALIDATOR_TEST_SERVER = 4
servers = {
Servers.BASIC_TEST_SERVER: basic_app,
Servers.WSGI_TEST_SERVER: wsgi_app,
Servers.FLASK_TEST_SERVER: flask_app,
Servers.VALIDATOR_TEST_SERVER: validator_app,
}
@contextmanager
def mute_stdout():
old_out = sys.stdout
sys.stdout = open(os.devnull, "w")
yield
sys.stdout = old_out
def pytest_sessionstart(session):
set_start_method("fork")
return ServerProcess
for i, server in enumerate(servers.items()):
with mute_stdout():
name, app = server
server_process = ServerProcess(app, port=PORT + i)
server_process.start()
print(f"{name} is listening on port={PORT+i}")
servers[name] = server_process
def pytest_sessionfinish(session, exitstatus):
for server_process in servers.values():
server_process.kill()
@pytest.fixture
def server_process():
return servers.get(Servers.BASIC_TEST_SERVER)
@pytest.fixture
def basic_test_server():
return servers.get(Servers.BASIC_TEST_SERVER)
@pytest.fixture
def flask_test_server():
return servers.get(Servers.FLASK_TEST_SERVER)
@pytest.fixture
def wsgi_test_server():
return servers.get(Servers.WSGI_TEST_SERVER)
@pytest.fixture
def validator_test_server():
return servers.get(Servers.VALIDATOR_TEST_SERVER)

View File

@@ -1,40 +1,22 @@
import requests
from flask import Flask
app = Flask(__name__)
@app.get("/")
def get():
return "get", 200
def test_flask_get(flask_test_server):
url = f"{flask_test_server.endpoint}/get"
result = requests.get(url)
assert result.status_code == 200
assert result.text == "get"
@app.post("/")
def post():
return "post", 201
def test_flask_post(flask_test_server):
url = f"{flask_test_server.endpoint}/post"
result = requests.post(url, json={"test": "data"})
assert result.status_code == 201
assert result.text == "post"
@app.delete("/")
def delete():
return "", 204
def test_flask_get(server_process):
with server_process(app) as server:
result = requests.get(server.endpoint)
assert result.status_code == 200
assert result.text == "get"
def test_flask_post(server_process):
with server_process(app) as server:
result = requests.post(server.endpoint, json={"test": "data"})
assert result.status_code == 201
assert result.text == "post"
def test_flask_delete(server_process):
with server_process(app) as server:
result = requests.delete(server.endpoint)
assert result.status_code == 204
assert result.text == ""
def test_flask_delete(flask_test_server):
url = f"{flask_test_server.endpoint}/delete"
result = requests.delete(url)
assert result.status_code == 204
assert result.text == ""

View File

@@ -0,0 +1,21 @@
import socket
import pytest
BAD_REQUEST_RESPONSE = b"HTTP/1.1 400 Bad Request\r\n\r\n"
raw_requests = [
"GET\r\n\r\n",
"/\r\n\r\n",
"GET ???\r\n\r\n",
"GET / HTTP\r\n\r\n",
"\r\n",
]
@pytest.mark.parametrize("raw_request", raw_requests)
def test_bad_requests(basic_test_server, raw_request):
host, port = basic_test_server.host, basic_test_server.port
connection = socket.create_connection((host, port))
connection.send(raw_request.encode())
data = connection.recv(4096)
assert data == BAD_REQUEST_RESPONSE

View File

@@ -1,38 +0,0 @@
import requests
def wsgi_app(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
return [b"Hello, WSGI!"]
def wsgi_app_delete(environ, start_response):
start_response('204 No Content', [])
return [b""]
def test_uwsgi_get(server_process):
with server_process(wsgi_app) as server:
result = requests.get(server.endpoint)
assert result.status_code == 200
assert result.text == "Hello, WSGI!"
def test_uwsgi_post(server_process):
with server_process(wsgi_app) as server:
# Post with no data
result = requests.get(server.endpoint)
assert result.status_code == 200
assert result.text == "Hello, WSGI!"
# Post with data
result = requests.get(server.endpoint, {"test": "data"})
assert result.status_code == 200
assert result.text == "Hello, WSGI!"
def test_uwsgi_delete(server_process):
with server_process(wsgi_app_delete) as server:
result = requests.get(server.endpoint)
assert result.status_code == 204
assert result.text == ""

View File

@@ -1,25 +0,0 @@
import requests
from wsgiref.validate import validator
def simple_app(environ, start_response):
status = '200 OK'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)
return [b"Valid"]
validator_app = validator(simple_app)
def test_get_valid_wsgi_server(server_process):
with server_process(validator_app) as server:
result = requests.get(server.endpoint)
assert result.text == "Valid"
def test_post_valid_wsgi_server(server_process):
with server_process(validator_app) as server:
result = requests.post(server.endpoint, json={"test": "data"})
assert result.text == "Valid"

29
tests/test_wsgi.py Normal file
View File

@@ -0,0 +1,29 @@
import requests
def test_wsgi_get(wsgi_test_server):
url = f"{wsgi_test_server.endpoint}/get"
result = requests.get(url)
assert result.status_code == 200
assert result.text == "OK"
def test_wsgi_post(wsgi_test_server):
# Post with no data
url = f"{wsgi_test_server.endpoint}/post"
result = requests.post(url)
assert result.status_code == 201
assert result.text == "OK"
# Post with data
result = requests.post(url, json={"test": "data"})
assert result.status_code == 201
assert result.text == "OK"
def test_wsgi_delete(wsgi_test_server):
url = f"{wsgi_test_server.endpoint}/delete"
result = requests.delete(url)
assert result.status_code == 204
assert result.text == ""