summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorFlorian Apolloner <florian@apolloner.eu>2014-05-25 22:52:47 +0200
committerFlorian Apolloner <florian@apolloner.eu>2014-06-11 08:57:30 +0200
commite2efc8965edf684aaf48621680ef54b84e116576 (patch)
tree8e33e8db9881b60369831f7fb853be71f5e17960 /tests
parenta1c6cd6a167f90fc4dfd76b2a2de87bc617b26e6 (diff)
Fixed #22680 -- I/O operation on closed file.
This patch is two-fold; first it ensure that Django does close everything in request.FILES at the end of the request and secondly the storage system should no longer close any files during save, it's up to the caller to handle that -- or let Django close the files at the end of the request.
Diffstat (limited to 'tests')
-rw-r--r--tests/file_storage/tests.py20
-rw-r--r--tests/file_uploads/tests.py31
-rw-r--r--tests/file_uploads/urls.py1
-rw-r--r--tests/file_uploads/views.py6
4 files changed, 57 insertions, 1 deletions
diff --git a/tests/file_storage/tests.py b/tests/file_storage/tests.py
index da9410d70f..c3800cbc89 100644
--- a/tests/file_storage/tests.py
+++ b/tests/file_storage/tests.py
@@ -19,7 +19,8 @@ from django.core.cache import cache
from django.core.exceptions import SuspiciousOperation
from django.core.files.base import File, ContentFile
from django.core.files.storage import FileSystemStorage, get_storage_class
-from django.core.files.uploadedfile import SimpleUploadedFile
+from django.core.files.uploadedfile import (InMemoryUploadedFile, SimpleUploadedFile,
+ TemporaryUploadedFile)
from django.test import LiveServerTestCase, SimpleTestCase
from django.test import override_settings
from django.utils import six
@@ -206,6 +207,23 @@ class FileStorageTests(unittest.TestCase):
self.storage.delete('path/to/test.file')
+ def test_save_doesnt_close(self):
+ with TemporaryUploadedFile('test', 'text/plain', 1, 'utf8') as file:
+ file.write(b'1')
+ file.seek(0)
+ self.assertFalse(file.closed)
+ self.storage.save('path/to/test.file', file)
+ self.assertFalse(file.closed)
+ self.assertFalse(file.file.closed)
+
+ file = InMemoryUploadedFile(six.StringIO('1'), '', 'test',
+ 'text/plain', 1, 'utf8')
+ with file:
+ self.assertFalse(file.closed)
+ self.storage.save('path/to/test.file', file)
+ self.assertFalse(file.closed)
+ self.assertFalse(file.file.closed)
+
def test_file_path(self):
"""
File storage returns the full path of a file
diff --git a/tests/file_uploads/tests.py b/tests/file_uploads/tests.py
index b6f8cfe17e..1e2ba488e6 100644
--- a/tests/file_uploads/tests.py
+++ b/tests/file_uploads/tests.py
@@ -327,6 +327,37 @@ class FileUploadTests(TestCase):
self.assertEqual(got.get('file1'), 1)
self.assertEqual(got.get('file2'), 2)
+ def test_fileuploads_closed_at_request_end(self):
+ file = tempfile.NamedTemporaryFile
+ with file() as f1, file() as f2a, file() as f2b:
+ response = self.client.post('/fd_closing/t/', {
+ 'file': f1,
+ 'file2': (f2a, f2b),
+ })
+
+ request = response.wsgi_request
+ # Check that the files got actually parsed.
+ self.assertTrue(hasattr(request, '_files'))
+
+ file = request._files['file']
+ self.assertTrue(file.closed)
+
+ files = request._files.getlist('file2')
+ self.assertTrue(files[0].closed)
+ self.assertTrue(files[1].closed)
+
+ def test_no_parsing_triggered_by_fd_closing(self):
+ file = tempfile.NamedTemporaryFile
+ with file() as f1, file() as f2a, file() as f2b:
+ response = self.client.post('/fd_closing/f/', {
+ 'file': f1,
+ 'file2': (f2a, f2b),
+ })
+
+ request = response.wsgi_request
+ # Check that the fd closing logic doesn't trigger parsing of the stream
+ self.assertFalse(hasattr(request, '_files'))
+
def test_file_error_blocking(self):
"""
The server should not block when there are upload errors (bug #8622).
diff --git a/tests/file_uploads/urls.py b/tests/file_uploads/urls.py
index ae20a2b79f..99f0cd3eb5 100644
--- a/tests/file_uploads/urls.py
+++ b/tests/file_uploads/urls.py
@@ -15,4 +15,5 @@ urlpatterns = [
url(r'^getlist_count/$', views.file_upload_getlist_count),
url(r'^upload_errors/$', views.file_upload_errors),
url(r'^filename_case/$', views.file_upload_filename_case_view),
+ url(r'^fd_closing/(?P<access>t|f)/$', views.file_upload_fd_closing),
]
diff --git a/tests/file_uploads/views.py b/tests/file_uploads/views.py
index a29391af6e..de195f4d39 100644
--- a/tests/file_uploads/views.py
+++ b/tests/file_uploads/views.py
@@ -157,3 +157,9 @@ def file_upload_content_type_extra(request):
(k, smart_str(v)) for k, v in uploadedfile.content_type_extra.items()
])
return HttpResponse(json.dumps(params))
+
+
+def file_upload_fd_closing(request, access):
+ if access == 't':
+ request.FILES # Trigger file parsing.
+ return HttpResponse('')