summaryrefslogtreecommitdiff
path: root/tests/responses
diff options
context:
space:
mode:
authorPiotr Kunicki <piotr.kunicki@o2.pl>2021-10-14 11:41:10 +0200
committerCarlton Gibson <carlton.gibson@noumenal.es>2021-10-14 15:05:04 +0200
commitdc724c5bf9d3b8d59c9571aa751c3cd001cdeced (patch)
tree8f3d1079a843438a6a2f95a40a30a1528259ec5d /tests/responses
parent3ac476439751334138edcbb9abd73f783afcec4c (diff)
Fixed #30509 -- Made FileResponse better handle buffers and non-zero file offsets.
Diffstat (limited to 'tests/responses')
-rw-r--r--tests/responses/test_fileresponse.py82
1 files changed, 76 insertions, 6 deletions
diff --git a/tests/responses/test_fileresponse.py b/tests/responses/test_fileresponse.py
index 28e6f8e48d..85350cd9f1 100644
--- a/tests/responses/test_fileresponse.py
+++ b/tests/responses/test_fileresponse.py
@@ -18,17 +18,71 @@ class UnseekableBytesIO(io.BytesIO):
class FileResponseTests(SimpleTestCase):
def test_content_length_file(self):
response = FileResponse(open(__file__, 'rb'))
- self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__)))
response.close()
+ self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__)))
def test_content_length_buffer(self):
response = FileResponse(io.BytesIO(b'binary content'))
self.assertEqual(response.headers['Content-Length'], '14')
+ def test_content_length_nonzero_starting_position_file(self):
+ file = open(__file__, 'rb')
+ file.seek(10)
+ response = FileResponse(file)
+ response.close()
+ self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__) - 10))
+
+ def test_content_length_nonzero_starting_position_buffer(self):
+ test_tuples = (
+ ('BytesIO', io.BytesIO),
+ ('UnseekableBytesIO', UnseekableBytesIO),
+ )
+ for buffer_class_name, BufferClass in test_tuples:
+ with self.subTest(buffer_class_name=buffer_class_name):
+ buffer = BufferClass(b'binary content')
+ buffer.seek(10)
+ response = FileResponse(buffer)
+ self.assertEqual(response.headers['Content-Length'], '4')
+
+ def test_content_length_nonzero_starting_position_file_seekable_no_tell(self):
+ class TestFile:
+ def __init__(self, path, *args, **kwargs):
+ self._file = open(path, *args, **kwargs)
+
+ def read(self, n_bytes=-1):
+ return self._file.read(n_bytes)
+
+ def seek(self, offset, whence=io.SEEK_SET):
+ return self._file.seek(offset, whence)
+
+ def seekable(self):
+ return True
+
+ @property
+ def name(self):
+ return self._file.name
+
+ def close(self):
+ if self._file:
+ self._file.close()
+ self._file = None
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, e_type, e_val, e_tb):
+ self.close()
+
+ file = TestFile(__file__, 'rb')
+ file.seek(10)
+ response = FileResponse(file)
+ response.close()
+ self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__) - 10))
+
def test_content_type_file(self):
response = FileResponse(open(__file__, 'rb'))
- self.assertIn(response.headers['Content-Type'], ['text/x-python', 'text/plain'])
response.close()
+ self.assertIn(response.headers['Content-Type'], ['text/x-python', 'text/plain'])
def test_content_type_buffer(self):
response = FileResponse(io.BytesIO(b'binary content'))
@@ -38,8 +92,14 @@ class FileResponseTests(SimpleTestCase):
response = FileResponse(io.BytesIO(b'binary content'), content_type='video/webm')
self.assertEqual(response.headers['Content-Type'], 'video/webm')
+ def test_content_type_buffer_explicit_default(self):
+ response = FileResponse(io.BytesIO(b'binary content'), content_type='text/html')
+ self.assertEqual(response.headers['Content-Type'], 'text/html')
+
def test_content_type_buffer_named(self):
test_tuples = (
+ (__file__, ['text/x-python', 'text/plain']),
+ (__file__ + 'nosuchfile', ['application/octet-stream']),
('test_fileresponse.py', ['text/x-python', 'text/plain']),
('test_fileresponse.pynosuchfile', ['application/octet-stream']),
)
@@ -59,15 +119,16 @@ class FileResponseTests(SimpleTestCase):
(False, 'inline'),
(True, 'attachment'),
)
- for (filename, header_filename), (as_attachment, header_disposition)\
- in itertools.product(filenames, dispositions):
+ for (filename, header_filename), (as_attachment, header_disposition) in itertools.product(
+ filenames, dispositions
+ ):
with self.subTest(filename=filename, disposition=header_disposition):
response = FileResponse(open(__file__, 'rb'), filename=filename, as_attachment=as_attachment)
+ response.close()
self.assertEqual(
response.headers['Content-Disposition'],
'%s; filename="%s"' % (header_disposition, header_filename),
)
- response.close()
def test_content_disposition_buffer(self):
response = FileResponse(io.BytesIO(b'binary content'))
@@ -89,7 +150,7 @@ class FileResponseTests(SimpleTestCase):
filename='custom_name.py',
)
self.assertEqual(
- response.headers['Content-Disposition'], '%s; filename="custom_name.py"' % header_disposition
+ response.headers['Content-Disposition'], '%s; filename="custom_name.py"' % header_disposition,
)
def test_response_buffer(self):
@@ -108,6 +169,15 @@ class FileResponseTests(SimpleTestCase):
response = FileResponse(buffer)
self.assertEqual(list(response), [b'tent'])
+ def test_buffer_explicit_absolute_filename(self):
+ """
+ Headers are set correctly with a buffer when an absolute filename is
+ provided.
+ """
+ response = FileResponse(io.BytesIO(b'binary content'), filename=__file__)
+ self.assertEqual(response.headers['Content-Length'], '14')
+ self.assertEqual(response.headers['Content-Disposition'], 'inline; filename="test_fileresponse.py"')
+
@skipIf(sys.platform == 'win32', "Named pipes are Unix-only.")
def test_file_from_named_pipe_response(self):
with tempfile.TemporaryDirectory() as temp_dir: