Skip to content

Commit

Permalink
Testing overhaul
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesroberts committed Dec 18, 2021
1 parent a9db3be commit 0daf220
Show file tree
Hide file tree
Showing 15 changed files with 221 additions and 110 deletions.
4 changes: 4 additions & 0 deletions clean_install.sh
@@ -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
8 changes: 4 additions & 4 deletions fastwsgi.py
Expand Up @@ -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")


Expand All @@ -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)
5 changes: 4 additions & 1 deletion lgtm.yml
@@ -1,4 +1,7 @@
path_classifiers:
library:
- llhttp/**/*.c
- llhttp/**/*.h
- llhttp/**/*.h
- libuv/**/*.c
- libuv/**/*.h
- performance_benchmarks/**/*.py
Empty file added tests/__init__.py
Empty file.
4 changes: 4 additions & 0 deletions tests/apps_under_test/__init__.py
@@ -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
4 changes: 4 additions & 0 deletions tests/apps_under_test/basic_app.py
@@ -0,0 +1,4 @@
def basic_app(environ, start_response):
headers = [("Content-Type", "text/plain")]
start_response("200 OK", headers)
return [b"Hello World"]
18 changes: 18 additions & 0 deletions tests/apps_under_test/flask_app.py
@@ -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
30 changes: 30 additions & 0 deletions tests/apps_under_test/wsgi_app.py
@@ -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)
11 changes: 11 additions & 0 deletions tests/apps_under_test/wsgi_validator_app.py
@@ -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)
86 changes: 77 additions & 9 deletions tests/conftest.py
@@ -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)
48 changes: 15 additions & 33 deletions tests/test_flask.py
@@ -1,40 +1,22 @@
import requests
from flask import Flask

app = Flask(__name__)

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.get("/")
def get():
return "get", 200

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.post("/")
def post():
return "post", 201


@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 == ""
21 changes: 21 additions & 0 deletions tests/test_raw_requests.py
@@ -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
38 changes: 0 additions & 38 deletions tests/test_uwsgi.py

This file was deleted.

25 changes: 0 additions & 25 deletions tests/test_valid_wsgi_server.py

This file was deleted.

29 changes: 29 additions & 0 deletions tests/test_wsgi.py
@@ -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 == ""

0 comments on commit 0daf220

Please sign in to comment.