summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNadège Michel <michel.nadege@gmail.com>2016-12-06 20:38:43 +0100
committerTim Graham <timograham@gmail.com>2017-02-09 19:08:32 -0500
commitbece837829eafbc22f2598dadf82c9a8364b085a (patch)
tree5dbe0327726551b6c3f5defd2a838b1add963867
parentc4e2fc5d9872c9a0c9c052a2e124f8a9b87de9b4 (diff)
Fixed #20238 -- Added threading support to LiveServerTestCase.
-rw-r--r--django/core/servers/basehttp.py5
-rw-r--r--django/test/testcases.py4
-rw-r--r--docs/releases/2.0.txt2
-rw-r--r--tests/servers/tests.py16
-rw-r--r--tests/servers/urls.py3
-rw-r--r--tests/servers/views.py17
6 files changed, 44 insertions, 3 deletions
diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py
index 68ef2a74b7..5c281b9c24 100644
--- a/django/core/servers/basehttp.py
+++ b/django/core/servers/basehttp.py
@@ -77,6 +77,11 @@ class WSGIServer(simple_server.WSGIServer):
super().handle_error(request, client_address)
+class ThreadedWSGIServer(socketserver.ThreadingMixIn, WSGIServer):
+ """A threaded version of the WSGIServer"""
+ pass
+
+
class ServerHandler(simple_server.ServerHandler):
def handle_error(self):
# Ignore broken pipe errors, otherwise pass on
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 0f879d4222..7955488f48 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -21,7 +21,7 @@ from django.core.handlers.wsgi import WSGIHandler, get_path_info
from django.core.management import call_command
from django.core.management.color import no_style
from django.core.management.sql import emit_post_migrate_signal
-from django.core.servers.basehttp import WSGIRequestHandler, WSGIServer
+from django.core.servers.basehttp import ThreadedWSGIServer, WSGIRequestHandler
from django.db import DEFAULT_DB_ALIAS, connection, connections, transaction
from django.forms.fields import CharField
from django.http import QueryDict
@@ -1248,7 +1248,7 @@ class LiveServerThread(threading.Thread):
connections.close_all()
def _create_server(self, port):
- return WSGIServer((self.host, port), QuietWSGIRequestHandler, allow_reuse_address=False)
+ return ThreadedWSGIServer((self.host, port), QuietWSGIRequestHandler, allow_reuse_address=False)
def terminate(self):
if hasattr(self, 'httpd'):
diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt
index 6b775bec80..818a8ada87 100644
--- a/docs/releases/2.0.txt
+++ b/docs/releases/2.0.txt
@@ -193,7 +193,7 @@ Templates
Tests
~~~~~
-* ...
+* Added threading support to :class:`~django.test.LiveServerTestCase`.
URLs
~~~~
diff --git a/tests/servers/tests.py b/tests/servers/tests.py
index 5052f57908..b114b968df 100644
--- a/tests/servers/tests.py
+++ b/tests/servers/tests.py
@@ -130,3 +130,19 @@ class LiveServerPort(LiveServerBase):
finally:
if hasattr(TestCase, 'server_thread'):
TestCase.server_thread.terminate()
+
+
+class LiverServerThreadedTests(LiveServerBase):
+ """If LiverServerTestCase isn't threaded, these tests will hang."""
+
+ def test_view_calls_subview(self):
+ url = '/subview_calling_view/?%s' % urlencode({'url': self.live_server_url})
+ with self.urlopen(url) as f:
+ self.assertEqual(f.read(), b'subview calling view: subview')
+
+ def test_check_model_instance_from_subview(self):
+ url = '/check_model_instance_from_subview/?%s' % urlencode({
+ 'url': self.live_server_url,
+ })
+ with self.urlopen(url) as f:
+ self.assertIn(b'emily', f.read())
diff --git a/tests/servers/urls.py b/tests/servers/urls.py
index 868ecc34f9..4963bde357 100644
--- a/tests/servers/urls.py
+++ b/tests/servers/urls.py
@@ -7,4 +7,7 @@ urlpatterns = [
url(r'^model_view/$', views.model_view),
url(r'^create_model_instance/$', views.create_model_instance),
url(r'^environ_view/$', views.environ_view),
+ url(r'^subview_calling_view/$', views.subview_calling_view),
+ url(r'^subview/$', views.subview),
+ url(r'^check_model_instance_from_subview/$', views.check_model_instance_from_subview),
]
diff --git a/tests/servers/views.py b/tests/servers/views.py
index f1fb8714c5..3fa99380b1 100644
--- a/tests/servers/views.py
+++ b/tests/servers/views.py
@@ -1,3 +1,5 @@
+from urllib.request import urlopen
+
from django.http import HttpResponse
from .models import Person
@@ -20,3 +22,18 @@ def create_model_instance(request):
def environ_view(request):
return HttpResponse("\n".join("%s: %r" % (k, v) for k, v in request.environ.items()))
+
+
+def subview(request):
+ return HttpResponse('subview')
+
+
+def subview_calling_view(request):
+ response = urlopen(request.GET['url'] + '/subview/')
+ return HttpResponse('subview calling view: {}'.format(response.read().decode()))
+
+
+def check_model_instance_from_subview(request):
+ urlopen(request.GET['url'] + '/create_model_instance/')
+ response = urlopen(request.GET['url'] + '/model_view/')
+ return HttpResponse('subview calling view: {}'.format(response.read().decode()))