Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
f1f838e
Adds a realisic Werkzeug-based server for testing, and modifies one o…
theGOTOguy Aug 27, 2021
b270e73
Remove annotations that broke the build in Python 2.7
theGOTOguy Aug 27, 2021
7d4ce9e
Attempt to fix pickling error in Windows and MacOS builds.
theGOTOguy Aug 27, 2021
8916243
Fix pickling error for echo_application from Windows and MacOS builds.
theGOTOguy Aug 27, 2021
695ac32
See if a 15-second pause when starting the server fixes the "connecti…
theGOTOguy Aug 27, 2021
6cbf092
Attempt to fix flaky tests by waiting for the Werkzeug server to be a…
theGOTOguy Aug 27, 2021
287f3eb
I wonder if the reason the MacOS errors are occurring is related to c…
theGOTOguy Aug 27, 2021
efc8de9
Merge pull request #1 from theGOTOguy/main
theGOTOguy Aug 27, 2021
bfc0949
Try to fix the socket error in MacOS by not reusing the same socket w…
theGOTOguy Aug 27, 2021
70b5ef9
Reviewing the changes, I'm not sure why wheel was dropped as a test d…
theGOTOguy Aug 27, 2021
9ca4848
Clean up port auto-selection using contextlib.
theGOTOguy Aug 27, 2021
539721b
Actually use the SOCKET_CONNECT_TIMEOUT variable.
theGOTOguy Aug 27, 2021
5587641
Further simplify the Werkzeug test server.
theGOTOguy Aug 28, 2021
f02fb67
Merge branch 'main' into testchunkedserialization
theGOTOguy Jul 28, 2022
5e10520
Use the example WerkzeugServer instead of the existing fake server.
theGOTOguy Jul 28, 2022
df89070
Linter fixes.
theGOTOguy Jul 28, 2022
9a6a8b2
Fix linter issue.
theGOTOguy Jul 28, 2022
7ce0767
Linter fix.
theGOTOguy Jul 28, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pytest-httpbin==1.0.0
pytest-mock==2.0.0
httpbin==0.7.0
trustme
Werkzeug
wheel

# Flask Stack
Expand Down
12 changes: 6 additions & 6 deletions tests/test_lowlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pytest
from tests.testserver.server import Server, consume_socket_content
from tests.testserver.werkzeug_server import WerkzeugServer

import requests
from requests.compat import JSONDecodeError
Expand All @@ -23,17 +24,16 @@ def echo_response_handler(sock):

def test_chunked_upload():
"""can safely send generators"""
close_server = threading.Event()
server = Server.basic_response_server(wait_to_close_event=close_server)
data = iter([b"a", b"b", b"c"])
server = WerkzeugServer.echo_server()
data = iter([b'a', b'b', b'c'])

with server as (host, port):
url = f"http://{host}:{port}/"
url = f'http://{host}:{port}/'
r = requests.post(url, data=data, stream=True)
close_server.set() # release server block

assert r.content == b'abc'
assert r.status_code == 200
assert r.request.headers["Transfer-Encoding"] == "chunked"
assert r.request.headers['Transfer-Encoding'] == 'chunked'


def test_chunked_encoding_error():
Expand Down
55 changes: 55 additions & 0 deletions tests/testserver/werkzeug_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import multiprocessing
import socket
from contextlib import closing

from werkzeug import Request, Response, run_simple


@Request.application
def echo_application(request):
return Response(request.get_data(), 200, content_type=request.content_type)


class WerkzeugServer:
"""Realistic WSGI server for unit testing."""

SOCKET_CONNECT_TIMEOUT = 2

def __init__(self, application, host="localhost", port=0):
super().__init__()

self.host = host
self.port = port

# Werkzeug will not automatically pick a valid port for us.
if not self.port:
with closing(socket.socket()) as sock:
sock.bind((self.host, self.port))
self.port = sock.getsockname()[1]

self.process = multiprocessing.Process(
target=run_simple, args=(self.host, self.port, application)
)

@classmethod
def echo_server(cls):
return WerkzeugServer(echo_application)

def _socket_is_ready(self):
with closing(socket.socket()) as sock:
sock.settimeout(self.SOCKET_CONNECT_TIMEOUT)
return sock.connect_ex((self.host, self.port)) == 0

def __enter__(self):
self.process.start()

# Confirm that we can actually connect to the socket before we return.
# This protects from flaky tests should the process come up too late.
while not self._socket_is_ready():
pass

return self.host, self.port

def __exit__(self, exc_type, exc_value, traceback):
self.process.terminate()
return False