Browse Source

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

Forwardport of 877d7b71ae952b3bc946e5187d6c23039a71614d from stable/1.11.x
Robert Rollins 7 years ago
parent
commit
b6d4b6e544
5 changed files with 42 additions and 7 deletions
  1. 10 6
      django/test/testcases.py
  2. 8 1
      docs/releases/1.11.2.txt
  3. 5 0
      docs/releases/1.11.txt
  4. 1 0
      docs/spelling_wordlist
  5. 18 0
      tests/servers/tests.py

+ 10 - 6
django/test/testcases.py

@@ -1201,9 +1201,9 @@ class _MediaFilesHandler(FSFilesHandler):
 class LiveServerThread(threading.Thread):
     """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.port = None
+        self.port = port
         self.is_ready = threading.Event()
         self.error = None
         self.static_handler = static_handler
@@ -1223,8 +1223,10 @@ class LiveServerThread(threading.Thread):
         try:
             # Create the handler for serving static and media files
             handler = self.static_handler(_MediaFilesHandler(WSGIHandler()))
-            self.httpd = self._create_server(0)
-            self.port = self.httpd.server_address[1]
+            self.httpd = self._create_server()
+            # 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.is_ready.set()
             self.httpd.serve_forever()
@@ -1234,8 +1236,8 @@ class LiveServerThread(threading.Thread):
         finally:
             connections.close_all()
 
-    def _create_server(self, port):
-        return ThreadedWSGIServer((self.host, port), QuietWSGIRequestHandler, allow_reuse_address=False)
+    def _create_server(self):
+        return ThreadedWSGIServer((self.host, self.port), QuietWSGIRequestHandler, allow_reuse_address=False)
 
     def terminate(self):
         if hasattr(self, 'httpd'):
@@ -1257,6 +1259,7 @@ class LiveServerTestCase(TransactionTestCase):
     thread can see the changes.
     """
     host = 'localhost'
+    port = 0
     server_thread_class = LiveServerThread
     static_handler = _StaticFilesHandler
 
@@ -1298,6 +1301,7 @@ class LiveServerTestCase(TransactionTestCase):
             cls.host,
             cls.static_handler,
             connections_override=connections_override,
+            port=cls.port,
         )
 
     @classmethod

+ 8 - 1
docs/releases/1.11.2.txt

@@ -4,7 +4,14 @@ Django 1.11.2 release notes
 
 *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
 ========

+ 5 - 0
docs/releases/1.11.txt

@@ -533,6 +533,8 @@ to support it.
 Also, the minimum supported version of psycopg2 is increased from 2.4.5 to
 2.5.4.
 
+.. _liveservertestcase-port-zero-change:
+
 ``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
 ``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
 --------------------------------------------------------------------------------------
 

+ 1 - 0
docs/spelling_wordlist

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

+ 18 - 0
tests/servers/tests.py

@@ -147,6 +147,24 @@ class LiveServerPort(LiveServerBase):
             if hasattr(TestCase, 'server_thread'):
                 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):
     """If LiverServerTestCase isn't threaded, these tests will hang."""