Fixed #28212 -- Allowed customizing the port that LiveServerTestCase uses.

Forwardport of 877d7b71ae from stable/1.11.x
This commit is contained in:
Robert Rollins 2017-05-22 10:16:56 -07:00 committed by Tim Graham
parent a30482a4b6
commit b6d4b6e544
5 changed files with 42 additions and 7 deletions

View File

@ -1201,9 +1201,9 @@ class _MediaFilesHandler(FSFilesHandler):
class LiveServerThread(threading.Thread): class LiveServerThread(threading.Thread):
"""Thread for running a live http server while the tests are running.""" """Thread for running a live http server while the tests are running."""
def __init__(self, host, static_handler, connections_override=None): def __init__(self, host, static_handler, connections_override=None, port=0):
self.host = host self.host = host
self.port = None self.port = port
self.is_ready = threading.Event() self.is_ready = threading.Event()
self.error = None self.error = None
self.static_handler = static_handler self.static_handler = static_handler
@ -1223,8 +1223,10 @@ class LiveServerThread(threading.Thread):
try: try:
# Create the handler for serving static and media files # Create the handler for serving static and media files
handler = self.static_handler(_MediaFilesHandler(WSGIHandler())) handler = self.static_handler(_MediaFilesHandler(WSGIHandler()))
self.httpd = self._create_server(0) self.httpd = self._create_server()
self.port = self.httpd.server_address[1] # If binding to port zero, assign the port allocated by the OS.
if self.port == 0:
self.port = self.httpd.server_address[1]
self.httpd.set_app(handler) self.httpd.set_app(handler)
self.is_ready.set() self.is_ready.set()
self.httpd.serve_forever() self.httpd.serve_forever()
@ -1234,8 +1236,8 @@ class LiveServerThread(threading.Thread):
finally: finally:
connections.close_all() connections.close_all()
def _create_server(self, port): def _create_server(self):
return ThreadedWSGIServer((self.host, port), QuietWSGIRequestHandler, allow_reuse_address=False) return ThreadedWSGIServer((self.host, self.port), QuietWSGIRequestHandler, allow_reuse_address=False)
def terminate(self): def terminate(self):
if hasattr(self, 'httpd'): if hasattr(self, 'httpd'):
@ -1257,6 +1259,7 @@ class LiveServerTestCase(TransactionTestCase):
thread can see the changes. thread can see the changes.
""" """
host = 'localhost' host = 'localhost'
port = 0
server_thread_class = LiveServerThread server_thread_class = LiveServerThread
static_handler = _StaticFilesHandler static_handler = _StaticFilesHandler
@ -1298,6 +1301,7 @@ class LiveServerTestCase(TransactionTestCase):
cls.host, cls.host,
cls.static_handler, cls.static_handler,
connections_override=connections_override, connections_override=connections_override,
port=cls.port,
) )
@classmethod @classmethod

View File

@ -4,7 +4,14 @@ Django 1.11.2 release notes
*Under development* *Under development*
Django 1.11.2 fixes several bugs in 1.11.1. Django 1.11.2 adds a minor feature and fixes several bugs in 1.11.1.
Minor feature
=============
The new ``LiveServerTestCase.port`` attribute reallows the use case of binding
to a specific port following the :ref:`bind to port zero
<liveservertestcase-port-zero-change>` change in Django 1.11.
Bugfixes Bugfixes
======== ========

View File

@ -533,6 +533,8 @@ to support it.
Also, the minimum supported version of psycopg2 is increased from 2.4.5 to Also, the minimum supported version of psycopg2 is increased from 2.4.5 to
2.5.4. 2.5.4.
.. _liveservertestcase-port-zero-change:
``LiveServerTestCase`` binds to port zero ``LiveServerTestCase`` binds to port zero
----------------------------------------- -----------------------------------------
@ -542,6 +544,9 @@ to assign a free port. The ``DJANGO_LIVE_TEST_SERVER_ADDRESS`` environment
variable is no longer used, and as it's also no longer used, the variable is no longer used, and as it's also no longer used, the
``manage.py test --liveserver`` option is removed. ``manage.py test --liveserver`` option is removed.
If you need to bind ``LiveServerTestCase`` to a specific port, use the ``port``
attribute added in Django 1.11.2.
Protection against insecure redirects in :mod:`django.contrib.auth` and ``i18n`` views Protection against insecure redirects in :mod:`django.contrib.auth` and ``i18n`` views
-------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------

View File

@ -550,6 +550,7 @@ rc
readded readded
reallow reallow
reallowed reallowed
reallows
rebase rebase
rebased rebased
rebasing rebasing

View File

@ -147,6 +147,24 @@ class LiveServerPort(LiveServerBase):
if hasattr(TestCase, 'server_thread'): if hasattr(TestCase, 'server_thread'):
TestCase.server_thread.terminate() TestCase.server_thread.terminate()
def test_specified_port_bind(self):
"""LiveServerTestCase.port customizes the server's port."""
TestCase = type(str('TestCase'), (LiveServerBase,), {})
# Find an open port and tell TestCase to use it.
s = socket.socket()
s.bind(('', 0))
TestCase.port = s.getsockname()[1]
s.close()
TestCase.setUpClass()
try:
self.assertEqual(
TestCase.port, TestCase.server_thread.port,
'Did not use specified port for LiveServerTestCase thread: %s' % TestCase.port
)
finally:
if hasattr(TestCase, 'server_thread'):
TestCase.server_thread.terminate()
class LiverServerThreadedTests(LiveServerBase): class LiverServerThreadedTests(LiveServerBase):
"""If LiverServerTestCase isn't threaded, these tests will hang.""" """If LiverServerTestCase isn't threaded, these tests will hang."""