Skip to content

Commit 7fd9801

Browse files
serhiy-storchakaMannarAmuthanashkopclaude
authored
[3.13] gh-67765: Add tests for wsgiref.validate (GH-112398) (GH-155625)
Cover the InputWrapper and ErrorWrapper methods of wsgiref.validate: read, readline, readlines, __iter__, write, writelines and flush. Each is tested both for the AssertionError raised on an invalid call and for the data passed through on a valid one. Co-authored-by: Alex Shkop <[email protected]> (cherry picked from commit e96cf73) * Use ExtraAssertions instead of rewriting the assertions assertStartsWith() and assertEndsWith() are provided by test.support.testcase.ExtraAssertions in 3.13, so the new tests can be kept identical to the 3.14+ version. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> --------- Co-authored-by: Amuthan Mannar <[email protected]> Co-authored-by: Alex Shkop <[email protected]> Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
1 parent 35c8011 commit 7fd9801

1 file changed

Lines changed: 111 additions & 1 deletion

File tree

Lib/test/test_wsgiref.py

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from unittest import mock
22
from test import support
33
from test.support import socket_helper, control_characters_c0
4+
from test.support.testcase import ExtraAssertions
45
from test.test_httpservers import NoLogRequestHandler
56
from unittest import TestCase
67
from wsgiref.util import setup_testing_defaults
@@ -66,6 +67,26 @@ def header_app(environ, start_response):
6667
]).encode('iso-8859-1')]
6768

6869

70+
def input_app(func_name, *args):
71+
def app(e,s):
72+
req = getattr(e['wsgi.input'], func_name)(*args)
73+
s("200 OK", [("Content-Type", "text/plain; charset=utf-8")])
74+
if type(req) is list:
75+
resp = b";".join(req)
76+
else:
77+
resp = req
78+
return [resp]
79+
return app
80+
81+
82+
def errors_app(func_name, *args):
83+
def app(e,s):
84+
getattr(e['wsgi.errors'], func_name)(*args)
85+
s("200 OK", [("Content-Type", "text/plain; charset=utf-8")])
86+
return [b"data"]
87+
return app
88+
89+
6990
def run_amock(app=hello_app, data=b"GET / HTTP/1.0\n\n"):
7091
server = make_server("", 80, app, MockServer, MockHandler)
7192
inp = BufferedReader(BytesIO(data))
@@ -102,7 +123,7 @@ def compare_generic_iter(make_it, match):
102123
raise AssertionError("Too many items from .__next__()", it)
103124

104125

105-
class IntegrationTests(TestCase):
126+
class IntegrationTests(TestCase, ExtraAssertions):
106127

107128
def check_hello(self, out, has_length=True):
108129
pyver = (python_implementation() + "/" +
@@ -192,6 +213,95 @@ def bad_app(e,s):
192213
err.splitlines()[-2], "AssertionError"
193214
)
194215

216+
def test_wsgi_input_read(self):
217+
bad_app = input_app("read")
218+
good_app = input_app("read", 5)
219+
220+
out, err = run_amock(validator(bad_app))
221+
self.assertEndsWith(out,
222+
b"A server error occurred. Please contact the administrator."
223+
)
224+
225+
self.assertEqual(
226+
err.splitlines()[-2], "AssertionError"
227+
)
228+
229+
out, err = run_amock(validator(good_app), b"GET / HTTP/1.0\n\nTest 1\nTest 2\n")
230+
self.assertEndsWith(out, b"Test ")
231+
232+
def test_wsgi_input_readlines(self):
233+
bad_app = input_app("readlines", 3, 5)
234+
good_app = input_app("readlines", 1)
235+
236+
out, err = run_amock(validator(bad_app))
237+
self.assertEndsWith(out,
238+
b"A server error occurred. Please contact the administrator."
239+
)
240+
self.assertEqual(
241+
err.splitlines()[-2], "AssertionError"
242+
)
243+
out, err = run_amock(validator(good_app), b"GET / HTTP/1.0\n\nTest Line 1\nTest Line 2\n")
244+
self.assertEndsWith(out, b"Test Line 1\n")
245+
246+
def test_wsgi_input_readline(self):
247+
bad_app = input_app("readline", 3, 4)
248+
good_app = input_app("readline", 2)
249+
250+
out, err = run_amock(validator(bad_app))
251+
self.assertEndsWith(out,
252+
b"A server error occurred. Please contact the administrator."
253+
)
254+
self.assertEqual(
255+
err.splitlines()[-2], "AssertionError"
256+
)
257+
258+
out, err = run_amock(validator(good_app), b"GET / HTTP/1.0\n\nTest 1\nTest 2\n")
259+
self.assertEndsWith(out, b"Te")
260+
261+
def test_wsgi_input_close(self):
262+
app = input_app("close")
263+
out, err = run_amock(validator(app), b"GET / HTTP/1.0\n\nTest 1\nTest 2\n")
264+
self.assertEqual(err.splitlines()[-2], 'AssertionError: input.close() must not be called')
265+
self.assertEndsWith(out, b"A server error occurred. Please contact the administrator.")
266+
267+
def test_wsgi_input_iter(self):
268+
def app(e,s):
269+
req = []
270+
for line in e['wsgi.input']:
271+
req.append(line)
272+
s("200 OK", [('Content-Type', 'text/plain; charser=utf-8')])
273+
return [b';'.join(req)]
274+
275+
out, err = run_amock(validator(app), b"GET / HTTP/1.0\n\nTest 1\nTest 2\n")
276+
self.assertEndsWith(out, b"Test 1\n;Test 2\n")
277+
278+
def test_wsgi_errors_write(self):
279+
bad_app = errors_app("write", b"Test")
280+
good_app = errors_app("write", "Test")
281+
282+
out, err = run_amock(validator(bad_app), b"GET / HTTP/1.0\n\n")
283+
self.assertEqual(err.splitlines()[-2], 'AssertionError')
284+
285+
out, err = run_amock(validator(good_app), b"GET / HTTP/1.0\n\n")
286+
self.assertStartsWith(err, "Test")
287+
288+
def test_wsgi_errors_writelines(self):
289+
bad_app = errors_app("writelines", [1, "Test"])
290+
good_app = errors_app("writelines", ["Test", "Test"])
291+
292+
out, err = run_amock(validator(bad_app), b"GET / HTTP/1.0\n\n")
293+
self.assertEqual(err.splitlines()[-2], 'AssertionError')
294+
295+
out, err = run_amock(validator(good_app), b"GET / HTTP/1.0\n\n")
296+
self.assertStartsWith(err, "TestTest")
297+
298+
def test_wsgi_errors_close(self):
299+
app = errors_app("close")
300+
301+
out, err = run_amock(validator(app), b"GET / HTTP/1.0\n\n")
302+
self.assertEqual(err.splitlines()[-2],
303+
'AssertionError: errors.close() must not be called')
304+
195305
def test_bytes_validation(self):
196306
def app(e, s):
197307
s("200 OK", [

0 commit comments

Comments
 (0)